blob: c19a095156266c2079d1d1a6fcc266ed6962ac4a
1 | /* |
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_hdmi" |
18 | #define LOG_NDEBUG 0 |
19 | //#define LOG_NDEBUG_FUNCTION |
20 | #ifdef LOG_NDEBUG_FUNCTION |
21 | #define LOGFUNC(...) ((void)0) |
22 | #else |
23 | #define LOGFUNC(...) (ALOGD(__VA_ARGS__)) |
24 | #endif |
25 | //#define DEBUG_HWSYNC_PASSTHROUGH |
26 | #ifndef DEBUG_HWSYNC_PASSTHROUGH |
27 | #define DEBUG(...) ((void)0) |
28 | #else |
29 | #define DEBUG(...) (ALOGD(__VA_ARGS__)) |
30 | #endif |
31 | #include <errno.h> |
32 | #include <pthread.h> |
33 | #include <stdint.h> |
34 | #include <sys/time.h> |
35 | #include <stdlib.h> |
36 | #include <sys/stat.h> |
37 | #include <fcntl.h> |
38 | #include <time.h> |
39 | #include <utils/Timers.h> |
40 | #include <cutils/log.h> |
41 | #include <cutils/str_parms.h> |
42 | #include <cutils/properties.h> |
43 | #include <linux/ioctl.h> |
44 | #include <hardware/hardware.h> |
45 | #include <system/audio.h> |
46 | #include <hardware/audio.h> |
47 | #include <sound/asound.h> |
48 | #include <tinyalsa/asoundlib.h> |
49 | |
50 | #include <audio_utils/resampler.h> |
51 | #include <audio_utils/echo_reference.h> |
52 | #include <hardware/audio_effect.h> |
53 | #include <audio_effects/effect_aec.h> |
54 | |
55 | #include "audio_hw.h" |
56 | #include "audio_hwsync.h" |
57 | #include "hdmi_audio_hw.h" |
58 | #include "audio_hw_profile.h" |
59 | #include "audio_hw_utils.h" |
60 | extern int aml_audio_hwsync_find_frame(struct aml_stream_out *out, const void *in_buffer, size_t in_bytes, uint64_t *cur_pts, int *outsize); |
61 | extern int spdifenc_write(const void *buffer, size_t numBytes); |
62 | extern uint64_t spdifenc_get_total(); |
63 | |
64 | extern int spdifenc_init(struct pcm *mypcm); |
65 | |
66 | struct pcm_config pcm_config_out = { |
67 | .channels = 2, |
68 | .rate = MM_FULL_POWER_SAMPLING_RATE, |
69 | .period_size = DEFAULT_PERIOD_SIZE, |
70 | .period_count = PLAYBACK_PERIOD_COUNT, |
71 | .format = PCM_FORMAT_S16_LE, |
72 | }; |
73 | |
74 | struct pcm_config pcm_config_in = { |
75 | .channels = 2, |
76 | .rate = MM_FULL_POWER_SAMPLING_RATE, |
77 | .period_size = DEFAULT_PERIOD_SIZE, |
78 | .period_count = PLAYBACK_PERIOD_COUNT, |
79 | .format = PCM_FORMAT_S16_LE, |
80 | }; |
81 | |
82 | static void select_output_device(struct aml_audio_device *adev); |
83 | static void select_input_device(struct aml_audio_device *adev); |
84 | static int adev_set_voice_volume(struct audio_hw_device *dev, float volume); |
85 | static int do_input_standby(struct aml_stream_in *in); |
86 | static int do_output_standby(struct aml_stream_out *out); |
87 | |
88 | extern void aml_audio_hwsync_clear_status(struct aml_stream_out *out); |
89 | |
90 | static void select_output_device(struct aml_audio_device *adev) |
91 | { |
92 | LOGFUNC("%s(mode=%d, out_device=%#x)", __FUNCTION__, adev->mode, |
93 | adev->out_device); |
94 | } |
95 | |
96 | static void select_input_device(struct aml_audio_device *adev) |
97 | { |
98 | int mic_in = adev->in_device & AUDIO_DEVICE_IN_BUILTIN_MIC; |
99 | int headset_mic = adev->in_device & AUDIO_DEVICE_IN_WIRED_HEADSET; |
100 | LOGFUNC("~~~~ %s : in_device(%#x), mic_in(%#x), headset_mic(%#x)", |
101 | __func__, adev->in_device, mic_in, headset_mic); |
102 | return; |
103 | } |
104 | |
105 | static void |
106 | force_all_standby(struct aml_audio_device *adev) |
107 | { |
108 | struct aml_stream_in *in; |
109 | struct aml_stream_out *out; |
110 | |
111 | LOGFUNC("%s(%p)", __FUNCTION__, adev); |
112 | |
113 | if (adev->active_output) { |
114 | out = adev->active_output; |
115 | pthread_mutex_lock(&out->lock); |
116 | do_output_standby(out); |
117 | pthread_mutex_unlock(&out->lock); |
118 | } |
119 | |
120 | if (adev->active_input) { |
121 | in = adev->active_input; |
122 | pthread_mutex_lock(&in->lock); |
123 | do_input_standby(in); |
124 | pthread_mutex_unlock(&in->lock); |
125 | } |
126 | } |
127 | |
128 | static void |
129 | select_mode(struct aml_audio_device *adev) |
130 | { |
131 | LOGFUNC("%s(out_device=%#x)", __FUNCTION__, adev->out_device); |
132 | LOGFUNC("%s(in_device=%#x)", __FUNCTION__, adev->in_device); |
133 | return; |
134 | force_all_standby(adev); |
135 | /* force earpiece route for in call state if speaker is the |
136 | only currently selected route. This prevents having to tear |
137 | down the modem PCMs to change route from speaker to earpiece |
138 | after the ringtone is played, but doesn't cause a route |
139 | change if a headset or bt device is already connected. If |
140 | speaker is not the only thing active, just remove it from |
141 | the route. We'll assume it'll never be used initally during |
142 | a call. This works because we're sure that the audio policy |
143 | manager will update the output device after the audio mode |
144 | change, even if the device selection did not change. */ |
145 | if ((adev->out_device & AUDIO_DEVICE_OUT_ALL) == AUDIO_DEVICE_OUT_SPEAKER) { |
146 | adev->in_device = AUDIO_DEVICE_IN_BUILTIN_MIC & ~AUDIO_DEVICE_BIT_IN; |
147 | } else { |
148 | adev->out_device &= ~AUDIO_DEVICE_OUT_SPEAKER; |
149 | } |
150 | select_output_device(adev); |
151 | select_input_device(adev); |
152 | return; |
153 | } |
154 | |
155 | |
156 | static int |
157 | check_output_stream(struct aml_stream_out *out) |
158 | { |
159 | int ret = 0; |
160 | unsigned int card = CARD_AMLOGIC_DEFAULT; |
161 | unsigned int port = PORT_MM; |
162 | int ext_card; |
163 | ext_card = get_external_card(0); |
164 | if (ext_card < 0) { |
165 | card = CARD_AMLOGIC_DEFAULT; |
166 | } else { |
167 | card = ext_card; |
168 | } |
169 | out->config.start_threshold = PERIOD_SIZE * 2; |
170 | out->config.avail_min = 0; //SHORT_PERIOD_SIZE; |
171 | return 0; |
172 | } |
173 | |
174 | /* must be called with hw device and output stream mutexes locked */ |
175 | static int start_output_stream(struct aml_stream_out *out) |
176 | { |
177 | struct aml_audio_device *adev = out->dev; |
178 | int card = CARD_AMLOGIC_DEFAULT; |
179 | int port = PORT_MM; |
180 | int ret = 0; |
181 | int codec_type = get_codec_type(out->format); |
182 | if (out->format == AUDIO_FORMAT_PCM && out->config.rate > 48000 && (out->flags & AUDIO_OUTPUT_FLAG_DIRECT)) { |
183 | ALOGI("start output stream for high sample rate pcm for direct mode\n"); |
184 | codec_type = TYPE_PCM_HIGH_SR; |
185 | } |
186 | if (codec_type == AUDIO_FORMAT_PCM && out->config.channels >= 6 && (out->flags & AUDIO_OUTPUT_FLAG_DIRECT)) { |
187 | ALOGI("start output stream for multi-channel pcm for direct mode\n"); |
188 | codec_type = TYPE_MULTI_PCM; |
189 | } |
190 | adev->active_output = out; |
191 | if (adev->mode != AUDIO_MODE_IN_CALL) { |
192 | /* FIXME: only works if only one output can be active at a time */ |
193 | select_output_device(adev); |
194 | } |
195 | LOGFUNC("%s(adev->out_device=%#x, adev->mode=%d)", __FUNCTION__, |
196 | adev->out_device, adev->mode); |
197 | card = get_aml_card(); |
198 | if (card < 0) { |
199 | ALOGE("hdmi get aml card id failed \n"); |
200 | card = CARD_AMLOGIC_DEFAULT; |
201 | } |
202 | port = get_spdif_port(); |
203 | if (port < 0) { |
204 | ALOGE("hdmi get aml card port failed \n"); |
205 | card = PORT_MM; |
206 | } |
207 | ALOGI("hdmi sound card id %d,device id %d \n", card, port); |
208 | if (out->config.channels == 6) { |
209 | ALOGI("round 6ch to 8 ch output \n"); |
210 | /* our hw only support 8 channel configure,so when 5.1,hw mask the last two channels*/ |
211 | sysfs_set_sysfs_str("/sys/class/amhdmitx/amhdmitx0/aud_output_chs", "6:7"); |
212 | out->config.channels = 8; |
213 | } |
214 | /* |
215 | 8 channel audio only support 32 byte mode,so need convert them to |
216 | PCM_FORMAT_S32_LE |
217 | */ |
218 | if (out->config.channels == 8) { |
219 | port = 0; |
220 | out->config.format = PCM_FORMAT_S32_LE; |
221 | adev->out_device = AUDIO_DEVICE_OUT_SPEAKER; |
222 | ALOGI("[%s %d]8CH format output: set port/0 adev->out_device/%d\n", |
223 | __FUNCTION__, __LINE__, AUDIO_DEVICE_OUT_SPEAKER); |
224 | } |
225 | LOGFUNC("------------open on board audio-------"); |
226 | if (getprop_bool("media.libplayer.wfd")) { |
227 | out->config.period_size = PERIOD_SIZE; |
228 | } |
229 | switch (out->format) { |
230 | case AUDIO_FORMAT_E_AC3: |
231 | out->config.period_size = PERIOD_SIZE * 2; |
232 | out->write_threshold = PLAYBACK_PERIOD_COUNT * PERIOD_SIZE * 2; |
233 | out->config.start_threshold = PLAYBACK_PERIOD_COUNT * PERIOD_SIZE * 2; |
234 | break; |
235 | case AUDIO_FORMAT_DTS_HD: |
236 | case AUDIO_FORMAT_TRUEHD: |
237 | out->config.period_size = PERIOD_SIZE * 4 * 2; |
238 | out->write_threshold = PLAYBACK_PERIOD_COUNT * PERIOD_SIZE * 4 * 2; |
239 | out->config.start_threshold = PLAYBACK_PERIOD_COUNT * PERIOD_SIZE * 4 * 2; |
240 | break; |
241 | case AUDIO_FORMAT_PCM: |
242 | default: |
243 | out->config.period_size = PERIOD_SIZE; |
244 | out->write_threshold = PLAYBACK_PERIOD_COUNT * PERIOD_SIZE; |
245 | out->config.start_threshold = PERIOD_SIZE * PLAYBACK_PERIOD_COUNT; |
246 | } |
247 | out->config.avail_min = 0; |
248 | if (codec_type != TYPE_DTS_HD) |
249 | set_codec_type(codec_type); |
250 | ALOGI("channels=%d---format=%d---period_count%d---period_size%d---rate=%d---", |
251 | out->config.channels, out->config.format, out->config.period_count, |
252 | out->config.period_size, out->config.rate); |
253 | out->pcm = pcm_open(card, port, PCM_OUT /*| PCM_MMAP | PCM_NOIRQ */ , |
254 | &(out->config)); |
255 | if (!pcm_is_ready(out->pcm)) { |
256 | ALOGE("cannot open pcm_out driver: %s", pcm_get_error(out->pcm)); |
257 | pcm_close(out->pcm); |
258 | adev->active_output = NULL; |
259 | return -ENOMEM; |
260 | } |
261 | #if 1 |
262 | if (codec_type_is_raw_data(codec_type) && !(out->flags & AUDIO_OUTPUT_FLAG_IEC958_NONAUDIO)) { |
263 | spdifenc_init(out->pcm); |
264 | out->spdif_enc_init_frame_write_sum = out->frame_write_sum; |
265 | } |
266 | #endif |
267 | //out->frame_write_sum=0; |
268 | out->codec_type = codec_type; |
269 | out->bytes_write_total = 0; |
270 | if (adev->hw_sync_mode == 1) { |
271 | LOGFUNC("start_output_stream with hw sync enable\n"); |
272 | } |
273 | return 0; |
274 | } |
275 | |
276 | static int |
277 | check_input_parameters(uint32_t sample_rate, int format, int channel_count) |
278 | { |
279 | LOGFUNC("%s(sample_rate=%d, format=%d, channel_count=%d)", __FUNCTION__, |
280 | sample_rate, format, channel_count); |
281 | |
282 | if (format != AUDIO_FORMAT_PCM_16_BIT) { |
283 | return -EINVAL; |
284 | } |
285 | |
286 | if ((channel_count < 1) || (channel_count > 2)) { |
287 | return -EINVAL; |
288 | } |
289 | |
290 | switch (sample_rate) { |
291 | case 8000: |
292 | case 11025: |
293 | case 16000: |
294 | case 22050: |
295 | case 24000: |
296 | case 32000: |
297 | case 44100: |
298 | case 48000: |
299 | break; |
300 | default: |
301 | return -EINVAL; |
302 | } |
303 | |
304 | return 0; |
305 | } |
306 | |
307 | static size_t |
308 | get_input_buffer_size(uint32_t sample_rate, int format, int channel_count) |
309 | { |
310 | size_t size; |
311 | size_t device_rate; |
312 | |
313 | LOGFUNC("%s(sample_rate=%d, format=%d, channel_count=%d)", __FUNCTION__, |
314 | sample_rate, format, channel_count); |
315 | |
316 | if (check_input_parameters(sample_rate, format, channel_count) != 0) { |
317 | return 0; |
318 | } |
319 | |
320 | /* take resampling into account and return the closest majoring |
321 | multiple of 16 frames, as audioflinger expects audio buffers to |
322 | be a multiple of 16 frames */ |
323 | size = (pcm_config_in.period_size * sample_rate) / pcm_config_in.rate; |
324 | size = ((size + 15) / 16) * 16; |
325 | |
326 | return size * channel_count * sizeof(short); |
327 | } |
328 | |
329 | |
330 | |
331 | static uint32_t |
332 | out_get_sample_rate(const struct audio_stream *stream) |
333 | { |
334 | struct aml_stream_out *out = (struct aml_stream_out *) stream; |
335 | if (out->config.rate > 0) { |
336 | return out->config.rate; |
337 | } else { |
338 | return DEFAULT_OUT_SAMPLING_RATE; |
339 | } |
340 | } |
341 | |
342 | static int |
343 | out_set_sample_rate(struct audio_stream *stream, uint32_t rate) |
344 | { |
345 | LOGFUNC("%s(%p, %d)", __FUNCTION__, stream, rate); |
346 | |
347 | return 0; |
348 | } |
349 | |
350 | static size_t |
351 | out_get_buffer_size(const struct audio_stream *stream) |
352 | { |
353 | struct aml_stream_out *out = (struct aml_stream_out *) stream; |
354 | |
355 | LOGFUNC("%s(out->config.rate=%d)", __FUNCTION__, out->config.rate); |
356 | |
357 | /* take resampling into account and return the closest majoring |
358 | * multiple of 16 frames, as audioflinger expects audio buffers to |
359 | * be a multiple of 16 frames |
360 | */ |
361 | size_t size; |
362 | switch (out->format) { |
363 | case AUDIO_FORMAT_AC3: |
364 | case AUDIO_FORMAT_DTS: |
365 | if (out->flags & AUDIO_OUTPUT_FLAG_IEC958_NONAUDIO) { |
366 | size = 4 * PERIOD_SIZE * PLAYBACK_PERIOD_COUNT; |
367 | } else { |
368 | size = PLAYBACK_PERIOD_COUNT * PERIOD_SIZE / 2; |
369 | } |
370 | break; |
371 | case AUDIO_FORMAT_E_AC3: |
372 | if (out->flags & AUDIO_OUTPUT_FLAG_IEC958_NONAUDIO) { |
373 | size = 16 * PERIOD_SIZE * PLAYBACK_PERIOD_COUNT; |
374 | } else { |
375 | size = PERIOD_SIZE; //2*PLAYBACK_PERIOD_COUNT*PERIOD_SIZE; |
376 | } |
377 | break; |
378 | case AUDIO_FORMAT_DTS_HD: |
379 | case AUDIO_FORMAT_TRUEHD: |
380 | if (out->flags & AUDIO_OUTPUT_FLAG_IEC958_NONAUDIO) { |
381 | size = 16 * PERIOD_SIZE * PLAYBACK_PERIOD_COUNT; |
382 | } else { |
383 | size = 4 * PLAYBACK_PERIOD_COUNT * PERIOD_SIZE; |
384 | } |
385 | break; |
386 | case AUDIO_FORMAT_PCM: |
387 | default: |
388 | size = PERIOD_SIZE; |
389 | } |
390 | size = ((size + 15) / 16) * 16; |
391 | size = size * audio_stream_out_frame_size(&out->stream); |
392 | DEBUG("format %x,buffer size %d\n", out->format, size); |
393 | return size; |
394 | } |
395 | |
396 | static audio_channel_mask_t |
397 | out_get_channels(const struct audio_stream *stream) |
398 | { |
399 | struct aml_stream_out *out = (struct aml_stream_out *) stream; |
400 | if (out->multich > 2) { |
401 | if (out->multich == 6) { |
402 | return AUDIO_CHANNEL_OUT_5POINT1; |
403 | } else if (out->multich == 8) { |
404 | return AUDIO_CHANNEL_OUT_7POINT1; |
405 | } |
406 | } |
407 | if (out->config.channels == 1) { |
408 | return AUDIO_CHANNEL_OUT_MONO; |
409 | } else { |
410 | return AUDIO_CHANNEL_OUT_STEREO; |
411 | } |
412 | } |
413 | |
414 | static audio_format_t |
415 | out_get_format(const struct audio_stream *stream) |
416 | { |
417 | struct aml_stream_out *out = (struct aml_stream_out *)stream; |
418 | |
419 | return out->format; |
420 | } |
421 | |
422 | static int |
423 | out_set_format(struct audio_stream *stream, int format) |
424 | { |
425 | LOGFUNC("%s(%p)", __FUNCTION__, stream); |
426 | |
427 | return 0; |
428 | } |
429 | |
430 | /* must be called with hw device and output stream mutexes locked */ |
431 | static int |
432 | do_output_standby(struct aml_stream_out *out) |
433 | { |
434 | struct aml_audio_device *adev = out->dev; |
435 | if (!out->standby) { |
436 | pcm_close(out->pcm); |
437 | out->pcm = NULL; |
438 | |
439 | adev->active_output = 0; |
440 | |
441 | /* if in call, don't turn off the output stage. This will |
442 | be done when the call is ended */ |
443 | if (adev->mode != AUDIO_MODE_IN_CALL) { |
444 | /* FIXME: only works if only one output can be active at a time */ |
445 | |
446 | //reset_mixer_state(adev->ar); |
447 | } |
448 | out->standby = 1; |
449 | } |
450 | ALOGI("clear out pause status\n"); |
451 | out->pause_status = false; |
452 | return 0; |
453 | } |
454 | |
455 | static int |
456 | out_standby(struct audio_stream *stream) |
457 | { |
458 | struct aml_stream_out *out = (struct aml_stream_out *) stream; |
459 | int status; |
460 | |
461 | LOGFUNC("%s(%p),out %p", __FUNCTION__, stream, out); |
462 | |
463 | pthread_mutex_lock(&out->dev->lock); |
464 | pthread_mutex_lock(&out->lock); |
465 | status = do_output_standby(out); |
466 | set_codec_type(TYPE_PCM); |
467 | /* clear the hdmitx channel config to default */ |
468 | if (out->multich == 6) { |
469 | sysfs_set_sysfs_str("/sys/class/amhdmitx/amhdmitx0/aud_output_chs", "0:0"); |
470 | } |
471 | if (out->format != AUDIO_FORMAT_DTS_HD) |
472 | set_codec_type(TYPE_PCM); |
473 | pthread_mutex_unlock(&out->lock); |
474 | pthread_mutex_unlock(&out->dev->lock); |
475 | return status; |
476 | } |
477 | |
478 | static int |
479 | out_dump(const struct audio_stream *stream, int fd) |
480 | { |
481 | LOGFUNC("%s(%p, %d)", __FUNCTION__, stream, fd); |
482 | return 0; |
483 | } |
484 | static int |
485 | out_flush(const struct audio_stream *stream) |
486 | { |
487 | LOGFUNC("%s(%p)", __FUNCTION__, stream); |
488 | struct aml_stream_out *out = (struct aml_stream_out *) stream; |
489 | struct aml_audio_device *adev = out->dev; |
490 | pthread_mutex_lock(&adev->lock); |
491 | pthread_mutex_lock(&out->lock); |
492 | do_output_standby(out); |
493 | out->spdif_enc_init_frame_write_sum = 0; |
494 | out->frame_write_sum = 0; |
495 | out->frame_skip_sum = 0; |
496 | out->skip_frame = 3; |
497 | pthread_mutex_unlock(&adev->lock); |
498 | pthread_mutex_unlock(&out->lock); |
499 | return 0; |
500 | } |
501 | |
502 | static int |
503 | out_set_parameters(struct audio_stream *stream, const char *kvpairs) |
504 | { |
505 | struct aml_stream_out *out = (struct aml_stream_out *) stream; |
506 | struct aml_audio_device *adev = out->dev; |
507 | struct aml_stream_in *in; |
508 | struct str_parms *parms; |
509 | char *str; |
510 | char value[64] = {0}; |
511 | int ret, val = 0; |
512 | bool force_input_standby = false; |
513 | |
514 | LOGFUNC("%s(kvpairs(%s), out_device=%#x)", __FUNCTION__, kvpairs, |
515 | adev->out_device); |
516 | parms = str_parms_create_str(kvpairs); |
517 | |
518 | ret = |
519 | str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, |
520 | sizeof(value)); |
521 | if (ret >= 0) { |
522 | val = atoi(value); |
523 | pthread_mutex_lock(&adev->lock); |
524 | pthread_mutex_lock(&out->lock); |
525 | if (((adev->out_device & AUDIO_DEVICE_OUT_ALL) != val) && (val != 0)) { |
526 | if (out == adev->active_output) { |
527 | do_output_standby(out); |
528 | /* a change in output device may change the microphone selection */ |
529 | if (adev->active_input && |
530 | adev->active_input->source == |
531 | AUDIO_SOURCE_VOICE_COMMUNICATION) { |
532 | force_input_standby = true; |
533 | } |
534 | /* force standby if moving to/from HDMI */ |
535 | if (((val & AUDIO_DEVICE_OUT_AUX_DIGITAL) ^ |
536 | (adev->out_device & AUDIO_DEVICE_OUT_AUX_DIGITAL)) || |
537 | ((val & AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET) ^ |
538 | (adev->out_device & AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET))) { |
539 | do_output_standby(out); |
540 | } |
541 | } |
542 | adev->out_device &= ~AUDIO_DEVICE_OUT_ALL; |
543 | adev->out_device |= val; |
544 | select_output_device(adev); |
545 | } |
546 | pthread_mutex_unlock(&out->lock); |
547 | if (force_input_standby) { |
548 | in = adev->active_input; |
549 | pthread_mutex_lock(&in->lock); |
550 | do_input_standby(in); |
551 | pthread_mutex_unlock(&in->lock); |
552 | } |
553 | pthread_mutex_unlock(&adev->lock); |
554 | goto exit; |
555 | } |
556 | int sr = 0; |
557 | ret = str_parms_get_int(parms, AUDIO_PARAMETER_STREAM_SAMPLING_RATE, &sr); |
558 | if (ret >= 0) { |
559 | if (sr > 0) { |
560 | ALOGI("audio hw sampling_rate change from %d to %d \n", |
561 | DEFAULT_OUT_SAMPLING_RATE, sr); |
562 | DEFAULT_OUT_SAMPLING_RATE = sr; |
563 | pcm_config_out.rate = DEFAULT_OUT_SAMPLING_RATE; |
564 | out->config.rate = DEFAULT_OUT_SAMPLING_RATE; |
565 | pthread_mutex_lock(&adev->lock); |
566 | pthread_mutex_lock(&out->lock); |
567 | if (!out->standby && (out == adev->active_output)) { |
568 | //do_output_standby (out); |
569 | //start_output_stream (out); |
570 | //out->standby = 0; |
571 | } |
572 | pthread_mutex_unlock(&adev->lock); |
573 | pthread_mutex_unlock(&out->lock); |
574 | |
575 | } |
576 | goto exit; |
577 | } |
578 | int frame_size = 0; |
579 | ret = |
580 | str_parms_get_int(parms, AUDIO_PARAMETER_STREAM_FRAME_COUNT, |
581 | &frame_size); |
582 | if (ret >= 0) { |
583 | if (frame_size > 0) { |
584 | ALOGI("audio hw frame size change from %d to %d \n", PERIOD_SIZE, |
585 | frame_size); |
586 | PERIOD_SIZE = frame_size; |
587 | pcm_config_out.period_size = PERIOD_SIZE; |
588 | out->config.period_size = PERIOD_SIZE; |
589 | pthread_mutex_lock(&adev->lock); |
590 | pthread_mutex_lock(&out->lock); |
591 | if (!out->standby && (out == adev->active_output)) { |
592 | //do_output_standby (out); |
593 | //start_output_stream (out); |
594 | //out->standby = 0; |
595 | } |
596 | pthread_mutex_unlock(&adev->lock); |
597 | pthread_mutex_unlock(&out->lock); |
598 | |
599 | } |
600 | goto exit; |
601 | } |
602 | |
603 | ret = str_parms_get_str(parms, "hw_av_sync", value, sizeof(value)); |
604 | if (ret >= 0) { |
605 | int hw_sync_id = atoi(value); |
606 | unsigned char sync_enable = (hw_sync_id == 12345678) ? 1 : 0; |
607 | ALOGI("(%p %p)set hw_sync_id %d,%s hw sync mode\n", |
608 | out, adev->active_output, hw_sync_id, sync_enable ? "enable" : "disable"); |
609 | pthread_mutex_lock(&adev->lock); |
610 | pthread_mutex_lock(&out->lock); |
611 | adev->hw_sync_mode = sync_enable; |
612 | out->frame_write_sum = 0; |
613 | out->frame_skip_sum = 0; |
614 | /* clear up previous playback output status */ |
615 | if (!out->standby && (out == adev->active_output)) { |
616 | do_output_standby(out); |
617 | } |
618 | pthread_mutex_unlock(&adev->lock); |
619 | pthread_mutex_unlock(&out->lock); |
620 | goto exit; |
621 | } |
622 | ret = str_parms_get_str(parms, "hdmi_arc_ad", value, sizeof(value)); |
623 | if (ret >= 0) { |
624 | int r; |
625 | ALOGI("(%p %p)set hdmi_arc_ad %s\n", |
626 | out, adev->active_output, value); |
627 | pthread_mutex_lock(&adev->lock); |
628 | pthread_mutex_lock(&out->lock); |
629 | int i; |
630 | char temp[7] = {0}; |
631 | unsigned ad = 0; |
632 | ALOGI("size of ad %d\n", strlen(value)); |
633 | for (i = 0; i < strlen(value); i = i + 6) { |
634 | temp[6] = '\0'; |
635 | memcpy(temp, value + i, 6); |
636 | ad = 0; |
637 | r = sscanf(temp, "%x", &ad); |
638 | if (r != 1) { |
639 | ALOGE("sscanf failed\n"); |
640 | } |
641 | adev->hdmi_arc_ad[i] = ad; |
642 | ALOGI("hdmi arc support audio ad code %x,index %d\n", ad, i / 6); |
643 | } |
644 | pthread_mutex_unlock(&adev->lock); |
645 | pthread_mutex_unlock(&out->lock); |
646 | goto exit; |
647 | } |
648 | exit: |
649 | str_parms_destroy(parms); |
650 | return ret; |
651 | } |
652 | static char * |
653 | out_get_parameters(const struct audio_stream *stream, const char *keys) |
654 | { |
655 | char *cap = NULL; |
656 | char *para = NULL; |
657 | struct aml_stream_out *out = (struct aml_stream_out *) stream; |
658 | struct aml_audio_device *adev = out->dev; |
659 | ALOGI("out_get_parameters %s,out %p\n", keys, out); |
660 | if (strstr(keys, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES)) { |
661 | if (out->out_device & AUDIO_DEVICE_OUT_HDMI_ARC) { |
662 | cap = (char *)get_hdmi_arc_cap(adev->hdmi_arc_ad, HDMI_ARC_MAX_FORMAT, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES); |
663 | } else { |
664 | cap = (char *)get_hdmi_sink_cap(AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES); |
665 | } |
666 | if (cap) { |
667 | para = strdup(cap); |
668 | free(cap); |
669 | } else { |
670 | para = strdup(""); |
671 | } |
672 | ALOGI("%s\n", para); |
673 | return para; |
674 | } else if (strstr(keys, AUDIO_PARAMETER_STREAM_SUP_CHANNELS)) { |
675 | if (out->out_device & AUDIO_DEVICE_OUT_HDMI_ARC) { |
676 | cap = (char *)get_hdmi_arc_cap(adev->hdmi_arc_ad, HDMI_ARC_MAX_FORMAT, AUDIO_PARAMETER_STREAM_SUP_CHANNELS); |
677 | } else { |
678 | cap = (char *)get_hdmi_sink_cap(AUDIO_PARAMETER_STREAM_SUP_CHANNELS); |
679 | } |
680 | if (cap) { |
681 | para = strdup(cap); |
682 | free(cap); |
683 | } else { |
684 | para = strdup(""); |
685 | } |
686 | ALOGI("%s\n", para); |
687 | return para; |
688 | } else if (strstr(keys, AUDIO_PARAMETER_STREAM_SUP_FORMATS)) { |
689 | if (out->out_device & AUDIO_DEVICE_OUT_HDMI_ARC) { |
690 | cap = (char *)get_hdmi_arc_cap(adev->hdmi_arc_ad, HDMI_ARC_MAX_FORMAT, AUDIO_PARAMETER_STREAM_SUP_FORMATS); |
691 | } else { |
692 | cap = (char *)get_hdmi_sink_cap(AUDIO_PARAMETER_STREAM_SUP_FORMATS); |
693 | } |
694 | if (cap) { |
695 | para = strdup(cap); |
696 | free(cap); |
697 | } else { |
698 | para = strdup(""); |
699 | } |
700 | ALOGI("%s\n", para); |
701 | return para; |
702 | } |
703 | return strdup(""); |
704 | } |
705 | static uint32_t out_get_latency(const struct audio_stream_out *stream) |
706 | { |
707 | struct aml_stream_out *out = (struct aml_stream_out *)stream; |
708 | uint32_t whole_latency; |
709 | uint32_t ret; |
710 | snd_pcm_sframes_t frames = 0; |
711 | whole_latency = (out->config.period_size * out->config.period_count * 1000) / out->config.rate; |
712 | if (!out->pcm || !pcm_is_ready(out->pcm)) { |
713 | return whole_latency; |
714 | } |
715 | ret = pcm_ioctl(out->pcm, SNDRV_PCM_IOCTL_DELAY, &frames); |
716 | if (ret < 0) { |
717 | return whole_latency; |
718 | } |
719 | if (out->format == AUDIO_FORMAT_E_AC3) { |
720 | frames /= 4; |
721 | } |
722 | return (frames * 1000) / out->config.rate; |
723 | |
724 | } |
725 | static int |
726 | out_set_volume(struct audio_stream_out *stream, float left, float right) |
727 | { |
728 | return -ENOSYS; |
729 | } |
730 | |
731 | static int out_pause(struct audio_stream_out *stream) |
732 | { |
733 | struct aml_stream_out *out = (struct aml_stream_out *) stream; |
734 | struct aml_audio_device *adev = out->dev; |
735 | int r = 0; |
736 | LOGFUNC("(%p)out_pause", out); |
737 | pthread_mutex_lock(&adev->lock); |
738 | pthread_mutex_lock(&out->lock); |
739 | if (out->standby || out->pause_status == true) { |
740 | goto exit; |
741 | } |
742 | if (pcm_is_ready(out->pcm)) { |
743 | r = pcm_ioctl(out->pcm, SNDRV_PCM_IOCTL_PAUSE, 1); |
744 | if (r < 0) { |
745 | ALOGE("cannot pause channel\n"); |
746 | } else { |
747 | r = 0; |
748 | } |
749 | } |
750 | if (out->dev->hw_sync_mode) { |
751 | sysfs_set_sysfs_str(TSYNC_EVENT, "AUDIO_PAUSE"); |
752 | } |
753 | ALOGI("set out pause status\n"); |
754 | out->pause_status = true; |
755 | exit: |
756 | pthread_mutex_unlock(&adev->lock); |
757 | pthread_mutex_unlock(&out->lock); |
758 | return r; |
759 | } |
760 | |
761 | static int out_resume(struct audio_stream_out *stream) |
762 | { |
763 | LOGFUNC("out_resume"); |
764 | struct aml_stream_out *out = (struct aml_stream_out *) stream; |
765 | struct aml_audio_device *adev = out->dev; |
766 | pthread_mutex_lock(&adev->lock); |
767 | pthread_mutex_lock(&out->lock); |
768 | int r = 0; |
769 | if (out->standby || out->pause_status == false) { |
770 | goto exit; |
771 | } |
772 | if (pcm_is_ready(out->pcm)) { |
773 | r = pcm_ioctl(out->pcm, SNDRV_PCM_IOCTL_PAUSE, 0); |
774 | if (r < 0) { |
775 | ALOGE("cannot resume channel\n"); |
776 | } else { |
777 | r = 0; |
778 | } |
779 | } |
780 | if (out->dev->hw_sync_mode) { |
781 | sysfs_set_sysfs_str(TSYNC_EVENT, "AUDIO_RESUME"); |
782 | } |
783 | ALOGI("clear out pause status\n"); |
784 | out->pause_status = false; |
785 | exit: |
786 | pthread_mutex_unlock(&adev->lock); |
787 | pthread_mutex_unlock(&out->lock); |
788 | return r; |
789 | } |
790 | |
791 | static ssize_t |
792 | out_write(struct audio_stream_out *stream, const void *buffer, size_t bytes) |
793 | { |
794 | int ret = 0; |
795 | struct aml_stream_out *out = (struct aml_stream_out *) stream; |
796 | struct aml_audio_device *adev = out->dev; |
797 | size_t frame_size = audio_stream_out_frame_size(stream); |
798 | size_t in_frames = bytes / frame_size; |
799 | bool force_input_standby = false; |
800 | size_t out_frames = 0; |
801 | void *buf; |
802 | uint i, total_len; |
803 | char prop[PROPERTY_VALUE_MAX]; |
804 | int codec_type = out->codec_type; |
805 | int samesource_flag = 0; |
806 | uint32_t latency_frames; |
807 | uint64_t total_frame = 0; |
808 | audio_hwsync_t *p_hwsync = &adev->hwsync; |
809 | /* acquiring hw device mutex systematically is useful if a low priority thread is waiting |
810 | * on the output stream mutex - e.g. executing select_mode() while holding the hw device |
811 | * mutex |
812 | */ |
813 | out->bytes_write_total += bytes; |
814 | DEBUG("out %p,dev %p out_write total size %lld\n", out, adev, out->bytes_write_total); |
815 | pthread_mutex_lock(&adev->lock); |
816 | pthread_mutex_lock(&out->lock); |
817 | if (out->pause_status == true) { |
818 | pthread_mutex_unlock(&adev->lock); |
819 | pthread_mutex_unlock(&out->lock); |
820 | ALOGI("call out_write when pause status,size %d,(%p)\n", bytes, out); |
821 | return 0; |
822 | } |
823 | if ((out->standby) && adev->hw_sync_mode) { |
824 | /* |
825 | there are two types of raw data come to hdmi audio hal |
826 | 1) compressed audio data without IEC61937 wrapped |
827 | 2) compressed audio data with IEC61937 wrapped (typically from amlogic amadec source) |
828 | we use the AUDIO_OUTPUT_FLAG_IEC958_NONAUDIO to distiguwish the two cases. |
829 | */ |
830 | if ((codec_type == TYPE_AC3 || codec_type == TYPE_EAC3) && (out->flags & AUDIO_OUTPUT_FLAG_IEC958_NONAUDIO)) { |
831 | spdifenc_init(out->pcm); |
832 | out->spdif_enc_init_frame_write_sum = out->frame_write_sum; |
833 | } |
834 | // todo: check timestamp header PTS discontinue for new sync point after seek |
835 | aml_audio_hwsync_clear_status(out); |
836 | out->spdif_enc_init_frame_write_sum = out->frame_write_sum; |
837 | } |
838 | if (out->standby) { |
839 | ret = start_output_stream(out); |
840 | if (ret != 0) { |
841 | pthread_mutex_unlock(&adev->lock); |
842 | goto exit; |
843 | } |
844 | out->standby = 0; |
845 | /* a change in output device may change the microphone selection */ |
846 | if (adev->active_input && |
847 | adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION) { |
848 | force_input_standby = true; |
849 | } |
850 | } |
851 | void *write_buf = NULL; |
852 | int hwsync_cost_bytes = 0; |
853 | if (adev->hw_sync_mode == 1) { |
854 | uint64_t cur_pts = 0xffffffff; |
855 | int outsize = 0; |
856 | char tempbuf[128]; |
857 | DEBUG("before aml_audio_hwsync_find_frame bytes %d\n", bytes); |
858 | hwsync_cost_bytes = aml_audio_hwsync_find_frame(out, buffer, bytes, &cur_pts, &outsize); |
859 | DEBUG("after aml_audio_hwsync_find_frame bytes remain %d,cost %d,outsize %d,pts %llx\n", |
860 | bytes - hwsync_cost_bytes, hwsync_cost_bytes, outsize, cur_pts); |
861 | //TODO,skip 3 frames after flush, to tmp fix seek pts discontinue issue.need dig more |
862 | // to find out why seek ppint pts frame is remained after flush.WTF. |
863 | if (out->skip_frame > 0) { |
864 | out->skip_frame--; |
865 | ALOGI("skip pts@%llx,cur frame size %d,cost size %d\n", cur_pts, outsize, hwsync_cost_bytes); |
866 | pthread_mutex_unlock(&adev->lock); |
867 | pthread_mutex_unlock(&out->lock); |
868 | return hwsync_cost_bytes; |
869 | } |
870 | if (cur_pts != 0xffffffff && outsize > 0) { |
871 | // if we got the frame body,which means we get a complete frame. |
872 | //we take this frame pts as the first apts. |
873 | //this can fix the seek discontinue,we got a fake frame,which maybe cached before the seek |
874 | if (p_hwsync->first_apts_flag == false) { |
875 | p_hwsync->first_apts_flag = true; |
876 | p_hwsync->first_apts = cur_pts; |
877 | sprintf(tempbuf, "AUDIO_START:0x%lx", cur_pts & 0xffffffff); |
878 | ALOGI("tsync -> %s,frame size %d", tempbuf, outsize); |
879 | if (sysfs_set_sysfs_str(TSYNC_EVENT, tempbuf) == -1) { |
880 | ALOGE("set AUDIO_START failed \n"); |
881 | } |
882 | } else { |
883 | unsigned long apts; |
884 | unsigned long latency = out_get_latency(out) * 90; |
885 | // check PTS discontinue, which may happen when audio track switching |
886 | // discontinue means PTS calculated based on first_apts and frame_write_sum |
887 | // does not match the timestamp of next audio samples |
888 | if (cur_pts > latency) { |
889 | apts = (unsigned long)cur_pts - latency; |
890 | } else { |
891 | apts = 0; |
892 | } |
893 | if (0) { //abs(cur_pts -apts) > APTS_DISCONTINUE_THRESHOLD) { |
894 | ALOGI("HW sync PTS discontinue, 0x%llx->0x%llx(from header) diff %llx,last apts %llx(from header)", |
895 | apts, cur_pts, abs(cur_pts - apts), p_hwsync->last_apts_from_header); |
896 | p_hwsync->first_apts = cur_pts; |
897 | sprintf(tempbuf, "AUDIO_TSTAMP_DISCONTINUITY:0x%lx", cur_pts); |
898 | if (sysfs_set_sysfs_str(TSYNC_EVENT, tempbuf) == -1) { |
899 | ALOGE("unable to open file %s,err: %s", TSYNC_EVENT, strerror(errno)); |
900 | } |
901 | } else { |
902 | unsigned long pcr = 0; |
903 | if (get_sysfs_int16(TSYNC_PCRSCR, &pcr) == 0) { |
904 | uint32_t apts_cal = apts & 0xffffffff; |
905 | if (abs(pcr - apts) < SYSTIME_CORRECTION_THRESHOLD) { |
906 | // do nothing |
907 | } |
908 | // limit the gap handle to 0.5~5 s. |
909 | else if ((apts - pcr) > APTS_DISCONTINUE_THRESHOLD_MIN && (apts - pcr) < APTS_DISCONTINUE_THRESHOLD_MAX) { |
910 | int insert_size = 0; |
911 | int once_write_size = 0; |
912 | if (out->codec_type == TYPE_EAC3) { |
913 | insert_size = abs(apts - pcr) / 90 * 48 * 4 * 4; |
914 | } else { |
915 | insert_size = abs(apts - pcr) / 90 * 48 * 4; |
916 | } |
917 | insert_size = insert_size & (~63); |
918 | ALOGI("audio gap %d ms ,need insert data %d\n", abs(apts - pcr) / 90, insert_size); |
919 | char *insert_buf = (char*)malloc(8192); |
920 | if (insert_buf == NULL) { |
921 | ALOGE("malloc size failed \n"); |
922 | pthread_mutex_unlock(&adev->lock); |
923 | goto exit; |
924 | } |
925 | memset(insert_buf, 0, 8192); |
926 | while (insert_size > 0) { |
927 | once_write_size = insert_size > 8192 ? 8192 : insert_size; |
928 | ret = pcm_write(out->pcm, (void *) insert_buf, once_write_size); |
929 | if (ret != 0) { |
930 | ALOGE("pcm write failed\n"); |
931 | free(insert_buf); |
932 | pthread_mutex_unlock(&adev->lock); |
933 | goto exit; |
934 | } |
935 | insert_size -= once_write_size; |
936 | } |
937 | free(insert_buf); |
938 | } |
939 | //audio pts smaller than pcr,need skip frame. |
940 | else if ((pcr - apts) > APTS_DISCONTINUE_THRESHOLD_MIN && (pcr - apts) < APTS_DISCONTINUE_THRESHOLD_MAX) { |
941 | //we assume one frame duration is 32 ms for DD+(6 blocks X 1536 frames,48K sample rate) |
942 | if (out->codec_type == TYPE_EAC3 && outsize > 0) { |
943 | ALOGI("audio slow 0x%x,skip frame @pts 0x%llx,pcr 0x%x,cur apts 0x%x\n", (pcr - apts), cur_pts, pcr, apts); |
944 | out->frame_skip_sum += 1536; |
945 | bytes = outsize; |
946 | pthread_mutex_unlock(&adev->lock); |
947 | goto exit; |
948 | } |
949 | } else { |
950 | sprintf(tempbuf, "0x%lx", apts); |
951 | ALOGI("tsync -> reset pcrscr 0x%x -> 0x%x, %s big,diff %d ms", pcr, apts, apts > pcr ? "apts" : "pcr", abs(apts - pcr) / 90); |
952 | #if 0 |
953 | int ret_val = sysfs_set_sysfs_str(TSYNC_APTS, tempbuf); |
954 | if (ret_val == -1) { |
955 | ALOGE("unable to open file %s,err: %s", TSYNC_APTS, strerror(errno)); |
956 | } |
957 | #endif |
958 | } |
959 | } |
960 | } |
961 | } |
962 | } |
963 | if (outsize > 0) { |
964 | in_frames = outsize / frame_size; |
965 | write_buf = p_hwsync->hw_sync_body_buf; |
966 | } else { |
967 | bytes = hwsync_cost_bytes; |
968 | pthread_mutex_unlock(&adev->lock); |
969 | goto exit; |
970 | } |
971 | } else { |
972 | write_buf = (void *) buffer; |
973 | } |
974 | pthread_mutex_unlock(&adev->lock); |
975 | out_frames = in_frames; |
976 | buf = (void *) write_buf; |
977 | if (getprop_bool("media.hdmihal.outdump")) { |
978 | FILE *fp1 = fopen("/data/tmp/hdmi_audio_out.pcm", "a+"); |
979 | if (fp1) { |
980 | int flen = fwrite((char *)buffer, 1, out_frames * frame_size, fp1); |
981 | LOGFUNC("flen = %d---outlen=%d ", flen, out_frames * frame_size); |
982 | fclose(fp1); |
983 | } else { |
984 | LOGFUNC("could not open file:/data/hdmi_audio_out.pcm"); |
985 | } |
986 | } |
987 | if (codec_type_is_raw_data(out->codec_type) && !(out->flags & AUDIO_OUTPUT_FLAG_IEC958_NONAUDIO)) { |
988 | //here to do IEC61937 pack |
989 | DEBUG("IEC61937 write size %d,hw_sync_mode %d,flag %x\n", out_frames * frame_size, adev->hw_sync_mode, out->flags); |
990 | if (out->codec_type > 0) { |
991 | // compressed audio DD/DD+ |
992 | bytes = spdifenc_write((void *) buf, out_frames * frame_size); |
993 | //need return actual size of this burst write |
994 | if (adev->hw_sync_mode == 1) { |
995 | bytes = hwsync_cost_bytes; |
996 | } |
997 | DEBUG("spdifenc_write return %d\n", bytes); |
998 | if (out->codec_type == TYPE_EAC3) { |
999 | out->frame_write_sum = spdifenc_get_total() / 16 + out->spdif_enc_init_frame_write_sum; |
1000 | } else { |
1001 | out->frame_write_sum = spdifenc_get_total() / 4 + out->spdif_enc_init_frame_write_sum; |
1002 | } |
1003 | DEBUG("out %p,spdifenc_get_total() / 4 %lld\n", out, spdifenc_get_total() / 16); |
1004 | } |
1005 | goto exit; |
1006 | } |
1007 | if (!out->standby) { |
1008 | if (out->multich == 8) { |
1009 | int *p32 = NULL; |
1010 | short *p16 = (short *) buf; |
1011 | short *p16_temp; |
1012 | int i, NumSamps; |
1013 | NumSamps = out_frames * frame_size / sizeof(short); |
1014 | p32 = malloc(NumSamps * sizeof(int)); |
1015 | if (p32 != NULL) { |
1016 | //here to swap the channnl data here |
1017 | //actual now:L,missing,R,RS,RRS,,LS,LRS,missing |
1018 | //expect L,C,R,RS,RRS,LRS,LS,LFE (LFE comes from to center) |
1019 | //actual audio data layout L,R,C,none/LFE,LRS,RRS,LS,RS |
1020 | p16_temp = (short *) p32; |
1021 | for (i = 0; i < NumSamps; i = i + 8) { |
1022 | p16_temp[0 + i]/*L*/ = p16[0 + i]; |
1023 | p16_temp[1 + i]/*R*/ = p16[1 + i]; |
1024 | p16_temp[2 + i] /*LFE*/ = p16[3 + i]; |
1025 | p16_temp[3 + i] /*C*/ = p16[2 + i]; |
1026 | p16_temp[4 + i] /*LS*/ = p16[6 + i]; |
1027 | p16_temp[5 + i] /*RS*/ = p16[7 + i]; |
1028 | p16_temp[6 + i] /*LRS*/ = p16[4 + i]; |
1029 | p16_temp[7 + i]/*RRS*/ = p16[5 + i]; |
1030 | } |
1031 | memcpy(p16, p16_temp, NumSamps * sizeof(short)); |
1032 | for (i = 0; i < NumSamps; i++) { //suppose 16bit/8ch PCM |
1033 | p32[i] = p16[i] << 16; |
1034 | } |
1035 | ret = pcm_write(out->pcm, (void *) p32, NumSamps * 4); |
1036 | free(p32); |
1037 | } |
1038 | } else if (out->multich == 6) { |
1039 | int *p32 = NULL; |
1040 | short *p16 = (short *) buf; |
1041 | short *p16_temp; |
1042 | int i, j, NumSamps, real_samples; |
1043 | real_samples = out_frames * frame_size / sizeof(short); |
1044 | NumSamps = real_samples * 8 / 6; |
1045 | //ALOGI("6ch to 8 ch real %d, to %d,bytes %d,frame size %d\n",real_samples,NumSamps,bytes,frame_size); |
1046 | p32 = malloc(NumSamps * sizeof(int)); |
1047 | if (p32 != NULL) { |
1048 | p16_temp = (short *) p32; |
1049 | for (i = 0; i < real_samples; i = i + 6) { |
1050 | p16_temp[0 + i]/*L*/ = p16[0 + i]; |
1051 | p16_temp[1 + i]/*R*/ = p16[1 + i]; |
1052 | p16_temp[2 + i] /*LFE*/ = p16[3 + i]; |
1053 | p16_temp[3 + i] /*C*/ = p16[2 + i]; |
1054 | p16_temp[4 + i] /*LS*/ = p16[4 + i]; |
1055 | p16_temp[5 + i] /*RS*/ = p16[5 + i]; |
1056 | } |
1057 | memcpy(p16, p16_temp, real_samples * sizeof(short)); |
1058 | memset(p32, 0, NumSamps * sizeof(int)); |
1059 | for (i = 0, j = 0; j < NumSamps; i = i + 6, j = j + 8) { //suppose 16bit/8ch PCM |
1060 | p32[j] = p16[i] << 16; |
1061 | p32[j + 1] = p16[i + 1] << 16; |
1062 | p32[j + 2] = p16[i + 2] << 16; |
1063 | p32[j + 3] = p16[i + 3] << 16; |
1064 | p32[j + 4] = p16[i + 4] << 16; |
1065 | p32[j + 5] = p16[i + 5] << 16; |
1066 | } |
1067 | ret = pcm_write(out->pcm, (void *) p32, NumSamps * 4); |
1068 | free(p32); |
1069 | } |
1070 | } else { |
1071 | #if 0 |
1072 | codec_type = |
1073 | get_sysfs_int("/sys/class/audiodsp/digital_codec"); |
1074 | samesource_flag = |
1075 | get_sysfs_int("/sys/class/audiodsp/audio_samesource"); |
1076 | if (out->last_codec_type > 0 && codec_type != out->last_codec_type) { |
1077 | samesource_flag = 1; |
1078 | } |
1079 | if (samesource_flag == 1 && codec_type) { |
1080 | ALOGI |
1081 | ("to disable same source,need reset alsa,last %d,type %d,same source flag %d ,\n", |
1082 | out->last_codec_type, codec_type, samesource_flag); |
1083 | out->last_codec_type = codec_type; |
1084 | pcm_stop(out->pcm); |
1085 | } |
1086 | #endif |
1087 | DEBUG("write size %d\n", out_frames * frame_size); |
1088 | ret = pcm_write(out->pcm, (void *) buf, out_frames * frame_size); |
1089 | if (ret == 0) { |
1090 | out->frame_write_sum += out_frames; |
1091 | } |
1092 | } |
1093 | } |
1094 | exit: |
1095 | total_frame = out->frame_write_sum + out->frame_skip_sum; |
1096 | latency_frames = out_get_latency(out) * out->config.rate / 1000; |
1097 | if (total_frame >= latency_frames) { |
1098 | out->last_frames_postion = total_frame - latency_frames; |
1099 | } else { |
1100 | out->last_frames_postion = total_frame; |
1101 | } |
1102 | pthread_mutex_unlock(&out->lock); |
1103 | if (ret != 0) { |
1104 | usleep(bytes * 1000000 / audio_stream_out_frame_size(stream) / |
1105 | out_get_sample_rate(&stream->common)); |
1106 | } |
1107 | return bytes; |
1108 | } |
1109 | |
1110 | static int |
1111 | out_get_render_position(const struct audio_stream_out *stream, |
1112 | uint32_t * dsp_frames) |
1113 | { |
1114 | LOGFUNC("%s(%p, %p)", __FUNCTION__, stream, dsp_frames); |
1115 | return -EINVAL; |
1116 | } |
1117 | |
1118 | static int |
1119 | out_add_audio_effect(const struct audio_stream *stream, |
1120 | effect_handle_t effect) |
1121 | { |
1122 | LOGFUNC("%s(%p, %p)", __FUNCTION__, stream, effect); |
1123 | return 0; |
1124 | } |
1125 | |
1126 | static int |
1127 | out_remove_audio_effect(const struct audio_stream *stream, |
1128 | effect_handle_t effect) |
1129 | { |
1130 | return 0; |
1131 | } |
1132 | |
1133 | static int |
1134 | out_get_next_write_timestamp(const struct audio_stream_out *stream, |
1135 | int64_t * timestamp) |
1136 | { |
1137 | return -EINVAL; |
1138 | } |
1139 | static int out_get_presentation_position(const struct audio_stream_out *stream, uint64_t *frames, struct timespec *timestamp) |
1140 | { |
1141 | struct aml_stream_out *out = (struct aml_stream_out *)stream; |
1142 | #if 1 |
1143 | if (frames != NULL) { |
1144 | *frames = out->last_frames_postion; |
1145 | } |
1146 | DEBUG("%p,*frames %lld\n", out, *frames); |
1147 | if (timestamp != NULL) { |
1148 | clock_gettime(CLOCK_MONOTONIC, timestamp); |
1149 | } |
1150 | #else |
1151 | #define TIME_TO_MS(time) ((uint64_t)time->tv_sec * 1000 + time->tv_nsec/1000000ULL) |
1152 | |
1153 | if (timestamp != NULL) { |
1154 | clock_gettime(CLOCK_MONOTONIC, timestamp); |
1155 | if (out->last_frames_pos == 0) { |
1156 | |
1157 | ALOGI("first frame pos \n"); |
1158 | if (frames != NULL) { |
1159 | *frames = out->last_frames_pos; |
1160 | } |
1161 | out->last_frames_pos = TIME_TO_MS(timestamp) * 48; |
1162 | } else { |
1163 | if (frames != NULL) { |
1164 | *frames = TIME_TO_MS(timestamp) * 48 - out->last_frames_pos; |
1165 | } |
1166 | ALOGI("pos %lld,first %lld\n", *frames, out->last_frames_pos); |
1167 | } |
1168 | |
1169 | } |
1170 | #undef TIME_TO_MS |
1171 | #endif |
1172 | return 0; |
1173 | } |
1174 | /** audio_stream_in implementation **/ |
1175 | |
1176 | /* must be called with hw device and input stream mutexes locked */ |
1177 | static int |
1178 | start_input_stream(struct aml_stream_in *in) |
1179 | { |
1180 | int ret = 0; |
1181 | unsigned int card = CARD_AMLOGIC_DEFAULT; |
1182 | unsigned int port = PORT_MM; |
1183 | struct aml_audio_device *adev = in->dev; |
1184 | LOGFUNC |
1185 | ("%s(need_echo_reference=%d, channels=%d, rate=%d, requested_rate=%d, mode= %d)", |
1186 | __FUNCTION__, in->need_echo_reference, in->config.channels, |
1187 | in->config.rate, in->requested_rate, adev->mode); |
1188 | adev->active_input = in; |
1189 | if (adev->mode != AUDIO_MODE_IN_CALL) { |
1190 | adev->in_device &= ~AUDIO_DEVICE_IN_ALL; |
1191 | adev->in_device |= in->device; |
1192 | select_input_device(adev); |
1193 | } |
1194 | PERIOD_SIZE = DEFAULT_PERIOD_SIZE; |
1195 | in->config.period_size = PERIOD_SIZE; |
1196 | /* this assumes routing is done previously */ |
1197 | in->pcm = pcm_open(card, port, PCM_IN, &in->config); |
1198 | if (!pcm_is_ready(in->pcm)) { |
1199 | ALOGE("cannot open pcm_in driver: %s", pcm_get_error(in->pcm)); |
1200 | pcm_close(in->pcm); |
1201 | adev->active_input = NULL; |
1202 | return -ENOMEM; |
1203 | } |
1204 | ALOGI("pcm_open in: card(%d), port(%d)", card, port); |
1205 | return 0; |
1206 | } |
1207 | |
1208 | static int |
1209 | check_input_stream(struct aml_stream_in *in) |
1210 | { |
1211 | int ret = 0; |
1212 | unsigned int card = CARD_AMLOGIC_BOARD; |
1213 | unsigned int port = 0; |
1214 | int ext_card; |
1215 | ext_card = get_external_card(1); |
1216 | if (ext_card < 0) { |
1217 | card = CARD_AMLOGIC_BOARD; |
1218 | } else { |
1219 | card = ext_card; |
1220 | } |
1221 | /* this assumes routing is done previously */ |
1222 | in->pcm = pcm_open(card, port, PCM_IN, &in->config); |
1223 | if (!pcm_is_ready(in->pcm)) { |
1224 | ALOGE("check_input_stream:cannot open pcm_in driver: %s", |
1225 | pcm_get_error(in->pcm)); |
1226 | pcm_close(in->pcm); |
1227 | return -ENOMEM; |
1228 | } |
1229 | pcm_close(in->pcm); |
1230 | return 0; |
1231 | } |
1232 | |
1233 | static uint32_t |
1234 | in_get_sample_rate(const struct audio_stream *stream) |
1235 | { |
1236 | struct aml_stream_in *in = (struct aml_stream_in *) stream; |
1237 | |
1238 | LOGFUNC("%s(%p)", __FUNCTION__, stream); |
1239 | return in->requested_rate; |
1240 | } |
1241 | |
1242 | static int |
1243 | in_set_sample_rate(struct audio_stream *stream, uint32_t rate) |
1244 | { |
1245 | LOGFUNC("%s(%p, %d)", __FUNCTION__, stream, rate); |
1246 | return 0; |
1247 | } |
1248 | |
1249 | static size_t |
1250 | in_get_buffer_size(const struct audio_stream *stream) |
1251 | { |
1252 | struct aml_stream_in *in = (struct aml_stream_in *) stream; |
1253 | |
1254 | LOGFUNC("%s(%p)", __FUNCTION__, stream); |
1255 | return get_input_buffer_size(in->config.rate, |
1256 | AUDIO_FORMAT_PCM_16_BIT, in->config.channels); |
1257 | } |
1258 | |
1259 | static audio_channel_mask_t |
1260 | in_get_channels(const struct audio_stream *stream) |
1261 | { |
1262 | struct aml_stream_in *in = (struct aml_stream_in *) stream; |
1263 | if (in->config.channels == 1) { |
1264 | return AUDIO_CHANNEL_IN_MONO; |
1265 | } else { |
1266 | return AUDIO_CHANNEL_IN_STEREO; |
1267 | } |
1268 | } |
1269 | |
1270 | static audio_format_t |
1271 | in_get_format(const struct audio_stream *stream) |
1272 | { |
1273 | return AUDIO_FORMAT_PCM_16_BIT; |
1274 | } |
1275 | |
1276 | static int |
1277 | in_set_format(struct audio_stream *stream, audio_format_t format) |
1278 | { |
1279 | LOGFUNC("%s(%p, %d)", __FUNCTION__, stream, format); |
1280 | return 0; |
1281 | } |
1282 | |
1283 | /* must be called with hw device and input stream mutexes locked */ |
1284 | static int |
1285 | do_input_standby(struct aml_stream_in *in) |
1286 | { |
1287 | struct aml_audio_device *adev = in->dev; |
1288 | LOGFUNC("%s(%p)", __FUNCTION__, in); |
1289 | if (!in->standby) { |
1290 | pcm_close(in->pcm); |
1291 | in->pcm = NULL; |
1292 | adev->active_input = 0; |
1293 | if (adev->mode != AUDIO_MODE_IN_CALL) { |
1294 | adev->in_device &= ~AUDIO_DEVICE_IN_ALL; |
1295 | select_input_device(adev); |
1296 | } |
1297 | in->standby = 1; |
1298 | } |
1299 | return 0; |
1300 | } |
1301 | |
1302 | static int |
1303 | in_standby(struct audio_stream *stream) |
1304 | { |
1305 | struct aml_stream_in *in = (struct aml_stream_in *) stream; |
1306 | int status; |
1307 | LOGFUNC("%s(%p)", __FUNCTION__, stream); |
1308 | pthread_mutex_lock(&in->dev->lock); |
1309 | pthread_mutex_lock(&in->lock); |
1310 | status = do_input_standby(in); |
1311 | pthread_mutex_unlock(&in->lock); |
1312 | pthread_mutex_unlock(&in->dev->lock); |
1313 | return status; |
1314 | } |
1315 | |
1316 | static int |
1317 | in_dump(const struct audio_stream *stream, int fd) |
1318 | { |
1319 | LOGFUNC("%s(%p, %d)", __FUNCTION__, stream, fd); |
1320 | return 0; |
1321 | } |
1322 | |
1323 | static int |
1324 | in_set_parameters(struct audio_stream *stream, const char *kvpairs) |
1325 | { |
1326 | struct aml_stream_in *in = (struct aml_stream_in *) stream; |
1327 | struct aml_audio_device *adev = in->dev; |
1328 | struct str_parms *parms; |
1329 | char *str; |
1330 | char value[32]; |
1331 | int ret, val = 0; |
1332 | bool do_standby = false; |
1333 | LOGFUNC("%s(%p, %s)", __FUNCTION__, stream, kvpairs); |
1334 | parms = str_parms_create_str(kvpairs); |
1335 | ret = |
1336 | str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, |
1337 | sizeof(value)); |
1338 | pthread_mutex_lock(&adev->lock); |
1339 | pthread_mutex_lock(&in->lock); |
1340 | if (ret >= 0) { |
1341 | val = atoi(value); |
1342 | /* no audio source uses val == 0 */ |
1343 | if ((in->source != val) && (val != 0)) { |
1344 | in->source = val; |
1345 | do_standby = true; |
1346 | } |
1347 | } |
1348 | ret = |
1349 | str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, |
1350 | sizeof(value)); |
1351 | if (ret >= 0) { |
1352 | val = atoi(value) & ~AUDIO_DEVICE_BIT_IN; |
1353 | if ((in->device != val) && (val != 0)) { |
1354 | in->device = val; |
1355 | do_standby = true; |
1356 | } |
1357 | } |
1358 | if (do_standby) { |
1359 | do_input_standby(in); |
1360 | } |
1361 | pthread_mutex_unlock(&in->lock); |
1362 | pthread_mutex_unlock(&adev->lock); |
1363 | str_parms_destroy(parms); |
1364 | return ret; |
1365 | } |
1366 | |
1367 | static char * |
1368 | in_get_parameters(const struct audio_stream *stream, const char *keys) |
1369 | { |
1370 | return strdup(""); |
1371 | } |
1372 | |
1373 | static int |
1374 | in_set_gain(struct audio_stream_in *stream, float gain) |
1375 | { |
1376 | LOGFUNC("%s(%p, %f)", __FUNCTION__, stream, gain); |
1377 | return 0; |
1378 | } |
1379 | static ssize_t |
1380 | in_read(struct audio_stream_in *stream, void *buffer, size_t bytes) |
1381 | { |
1382 | int ret = 0; |
1383 | int i = 0; |
1384 | struct aml_stream_in *in = (struct aml_stream_in *) stream; |
1385 | struct aml_audio_device *adev = in->dev; |
1386 | size_t frames_rq = bytes / audio_stream_in_frame_size(stream); |
1387 | /* acquiring hw device mutex systematically is useful if a low priority thread is waiting |
1388 | * on the input stream mutex - e.g. executing select_mode() while holding the hw device |
1389 | * mutex |
1390 | */ |
1391 | pthread_mutex_lock(&adev->lock); |
1392 | pthread_mutex_lock(&in->lock); |
1393 | if (in->standby) { |
1394 | ret = start_input_stream(in); |
1395 | if (ret == 0) { |
1396 | in->standby = 0; |
1397 | } |
1398 | } |
1399 | pthread_mutex_unlock(&adev->lock); |
1400 | ret = pcm_read(in->pcm, buffer, bytes); |
1401 | if (ret > 0) { |
1402 | ret = 0; |
1403 | } |
1404 | if (ret == 0 && adev->mic_mute) { |
1405 | LOGFUNC("%s(adev->mic_mute = %d)", __FUNCTION__, adev->mic_mute); |
1406 | memset(buffer, 0, bytes); |
1407 | } |
1408 | exit: |
1409 | if (ret < 0) |
1410 | usleep(bytes * 1000000 / audio_stream_in_frame_size(stream) / |
1411 | in_get_sample_rate(&stream->common)); |
1412 | pthread_mutex_unlock(&in->lock); |
1413 | return bytes; |
1414 | } |
1415 | |
1416 | static uint32_t |
1417 | in_get_input_frames_lost(struct audio_stream_in *stream) |
1418 | { |
1419 | return 0; |
1420 | } |
1421 | |
1422 | static int |
1423 | adev_open_output_stream(struct audio_hw_device *dev, |
1424 | audio_io_handle_t handle, |
1425 | audio_devices_t devices, |
1426 | audio_output_flags_t flags, |
1427 | struct audio_config *config, |
1428 | struct audio_stream_out **stream_out) |
1429 | { |
1430 | int ret; |
1431 | int digital_codec; //digital_codec |
1432 | struct aml_audio_device *ladev = (struct aml_audio_device *) dev; |
1433 | struct aml_stream_out *out; |
1434 | int channel_count = popcount(config->channel_mask); |
1435 | LOGFUNC("%s(devices=0x%04x,format=%d, chnum=0x%04x, SR=%d,io handle %d, flags = 0x%x )", |
1436 | __FUNCTION__, devices, config->format, channel_count, |
1437 | config->sample_rate, handle, flags); |
1438 | out = (struct aml_stream_out *) calloc(1, sizeof(struct aml_stream_out)); |
1439 | if (!out) { |
1440 | return -ENOMEM; |
1441 | } |
1442 | out->stream.common.get_sample_rate = out_get_sample_rate; |
1443 | out->stream.common.set_sample_rate = out_set_sample_rate; |
1444 | out->stream.common.get_buffer_size = out_get_buffer_size; |
1445 | out->stream.common.get_channels = out_get_channels; |
1446 | out->stream.common.get_format = out_get_format; |
1447 | out->stream.common.set_format = out_set_format; |
1448 | out->stream.common.standby = out_standby; |
1449 | out->stream.common.dump = out_dump; |
1450 | out->stream.common.set_parameters = out_set_parameters; |
1451 | out->stream.common.get_parameters = out_get_parameters; |
1452 | out->stream.common.add_audio_effect = NULL;//out_add_audio_effect; |
1453 | out->stream.common.remove_audio_effect = NULL;//out_remove_audio_effect; |
1454 | out->stream.get_latency = out_get_latency; |
1455 | out->stream.set_volume = out_set_volume; |
1456 | out->stream.write = out_write; |
1457 | out->stream.get_render_position = out_get_render_position; |
1458 | out->stream.get_next_write_timestamp = out_get_next_write_timestamp; |
1459 | out->stream.pause = out_pause; |
1460 | out->stream.resume = out_resume; |
1461 | out->stream.get_presentation_position = out_get_presentation_position; |
1462 | out->stream.flush = out_flush; |
1463 | out->config = pcm_config_out; |
1464 | digital_codec = get_codec_type(config->format); |
1465 | if (digital_codec == TYPE_EAC3) { |
1466 | out->config.period_size = pcm_config_out.period_size * 2; |
1467 | } else if (digital_codec == TYPE_TRUE_HD || digital_codec == TYPE_DTS_HD) { |
1468 | out->config.period_size = pcm_config_out.period_size * 4 * 2; |
1469 | } |
1470 | if (channel_count > 2) { |
1471 | ALOGI("[adev_open_output_stream]: out/%p channel/%d\n", out, |
1472 | channel_count); |
1473 | out->multich = channel_count; |
1474 | out->config.channels = channel_count; |
1475 | } |
1476 | if (codec_type_is_raw_data(digital_codec)) { |
1477 | ALOGI("for raw audio output,force alsa stereo output\n"); |
1478 | out->config.channels = 2; |
1479 | out->multich = 2; |
1480 | } |
1481 | /* if 2ch high sample rate PCM audio goes to direct output, set the required sample rate which needed by AF */ |
1482 | if ((flags & AUDIO_OUTPUT_FLAG_DIRECT) && config->sample_rate > 0) { |
1483 | out->config.rate = config->sample_rate; |
1484 | } |
1485 | out->format = config->format; |
1486 | out->dev = ladev; |
1487 | out->standby = 1; |
1488 | ladev->hw_sync_mode = false; |
1489 | ladev->hwsync.first_apts_flag = false; |
1490 | out->frame_write_sum = 0; |
1491 | if (flags & AUDIO_OUTPUT_FLAG_HW_AV_SYNC) { |
1492 | ALOGI("Output stream open with AUDIO_OUTPUT_FLAG_HW_AV_SYNC"); |
1493 | } |
1494 | if (audio_is_raw_data(config->format) || (flags & AUDIO_OUTPUT_FLAG_DIRECT)) { |
1495 | if (config->format == 0) { |
1496 | config->format = AUDIO_FORMAT_AC3; |
1497 | out->format = AUDIO_FORMAT_AC3; |
1498 | } |
1499 | } |
1500 | if (config->sample_rate == 0) { |
1501 | out->config.rate = config->sample_rate = 48000; |
1502 | } |
1503 | if (audio_is_raw_data(config->format)) { |
1504 | out->config.rate = config->sample_rate; |
1505 | } |
1506 | LOGFUNC("%s(devices=0x%04x,format=0x%x, chmask=0x%04x, SR=%d)", |
1507 | __FUNCTION__, devices, config->format, config->channel_mask, |
1508 | config->sample_rate); |
1509 | out->flags = flags; |
1510 | out->out_device = devices; |
1511 | *stream_out = &out->stream; |
1512 | if (devices & AUDIO_DEVICE_OUT_HDMI_ARC) { |
1513 | ALOGI("ARC stream %p\n", out); |
1514 | memset(ladev->hdmi_arc_ad, 0, sizeof(ladev->hdmi_arc_ad)); |
1515 | } |
1516 | return 0; |
1517 | err_open: |
1518 | free(out); |
1519 | *stream_out = NULL; |
1520 | return ret; |
1521 | } |
1522 | |
1523 | static void |
1524 | adev_close_output_stream(struct audio_hw_device *dev, |
1525 | struct audio_stream_out *stream) |
1526 | { |
1527 | struct aml_stream_out *out = (struct aml_stream_out *) stream; |
1528 | LOGFUNC("%s(%p, %p)", __FUNCTION__, dev, stream); |
1529 | out_standby(&stream->common); |
1530 | if (out->buffer) { |
1531 | free(out->buffer); |
1532 | } |
1533 | free(stream); |
1534 | } |
1535 | |
1536 | static int |
1537 | adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs) |
1538 | { |
1539 | LOGFUNC("%s(%p, %s)", __FUNCTION__, dev, kvpairs); |
1540 | struct aml_audio_device *adev = (struct aml_audio_device *) dev; |
1541 | return 0; |
1542 | } |
1543 | |
1544 | static char * |
1545 | adev_get_parameters(const struct audio_hw_device *dev, const char *keys) |
1546 | { |
1547 | LOGFUNC("%s(%p, %s)", __FUNCTION__, dev, keys); |
1548 | struct aml_audio_device *adev = (struct aml_audio_device *)dev; |
1549 | if (!strcmp(keys, AUDIO_PARAMETER_HW_AV_EAC3_SYNC)) { |
1550 | return strdup("true"); |
1551 | } |
1552 | return strdup(""); |
1553 | } |
1554 | |
1555 | static int |
1556 | adev_init_check(const struct audio_hw_device *dev) |
1557 | { |
1558 | LOGFUNC("%s(%p)", __FUNCTION__, dev); |
1559 | return 0; |
1560 | } |
1561 | |
1562 | static int |
1563 | adev_set_voice_volume(struct audio_hw_device *dev, float volume) |
1564 | { |
1565 | struct aml_audio_device *adev = (struct aml_audio_device *) dev; |
1566 | LOGFUNC("%s(%p, %f)", __FUNCTION__, dev, volume); |
1567 | return 0; |
1568 | } |
1569 | |
1570 | static int |
1571 | adev_set_master_volume(struct audio_hw_device *dev, float volume) |
1572 | { |
1573 | LOGFUNC("%s(%p, %f)", __FUNCTION__, dev, volume); |
1574 | return -ENOSYS; |
1575 | } |
1576 | |
1577 | static int |
1578 | adev_get_master_volume(struct audio_hw_device *dev, float *volume) |
1579 | { |
1580 | return -ENOSYS; |
1581 | } |
1582 | |
1583 | static int |
1584 | adev_set_master_mute(struct audio_hw_device *dev, bool muted) |
1585 | { |
1586 | return -ENOSYS; |
1587 | } |
1588 | |
1589 | static int |
1590 | adev_get_master_mute(struct audio_hw_device *dev, bool * muted) |
1591 | { |
1592 | return -ENOSYS; |
1593 | } |
1594 | |
1595 | static int |
1596 | adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode) |
1597 | { |
1598 | struct aml_audio_device *adev = (struct aml_audio_device *) dev; |
1599 | LOGFUNC("%s(%p, %d)", __FUNCTION__, dev, mode); |
1600 | pthread_mutex_lock(&adev->lock); |
1601 | if (adev->mode != mode) { |
1602 | adev->mode = mode; |
1603 | select_mode(adev); |
1604 | } |
1605 | pthread_mutex_unlock(&adev->lock); |
1606 | return 0; |
1607 | } |
1608 | |
1609 | static int |
1610 | adev_set_mic_mute(struct audio_hw_device *dev, bool state) |
1611 | { |
1612 | struct aml_audio_device *adev = (struct aml_audio_device *) dev; |
1613 | LOGFUNC("%s(%p, %d)", __FUNCTION__, dev, state); |
1614 | adev->mic_mute = state; |
1615 | return 0; |
1616 | } |
1617 | |
1618 | static int |
1619 | adev_get_mic_mute(const struct audio_hw_device *dev, bool * state) |
1620 | { |
1621 | struct aml_audio_device *adev = (struct aml_audio_device *) dev; |
1622 | |
1623 | LOGFUNC("%s(%p, %p)", __FUNCTION__, dev, state); |
1624 | *state = adev->mic_mute; |
1625 | return 0; |
1626 | |
1627 | } |
1628 | |
1629 | static size_t |
1630 | adev_get_input_buffer_size(const struct audio_hw_device *dev, |
1631 | const struct audio_config *config) |
1632 | { |
1633 | size_t size; |
1634 | int channel_count = popcount(config->channel_mask); |
1635 | LOGFUNC("%s(%p, %d, %d, %d)", __FUNCTION__, dev, config->sample_rate, |
1636 | config->format, channel_count); |
1637 | if (check_input_parameters |
1638 | (config->sample_rate, config->format, channel_count) != 0) { |
1639 | return 0; |
1640 | } |
1641 | return get_input_buffer_size(config->sample_rate, |
1642 | config->format, channel_count); |
1643 | |
1644 | } |
1645 | |
1646 | static int |
1647 | adev_open_input_stream(struct audio_hw_device *dev, |
1648 | audio_io_handle_t handle, |
1649 | audio_devices_t devices, |
1650 | struct audio_config *config, |
1651 | struct audio_stream_in **stream_in) |
1652 | { |
1653 | struct aml_audio_device *ladev = (struct aml_audio_device *) dev; |
1654 | struct aml_stream_in *in; |
1655 | int ret; |
1656 | int channel_count = popcount(config->channel_mask); |
1657 | LOGFUNC("**********%s(%#x, %d, 0x%04x, %d)", __FUNCTION__, |
1658 | devices, config->format, config->channel_mask, |
1659 | config->sample_rate); |
1660 | if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0) { |
1661 | return -EINVAL; |
1662 | } |
1663 | in = (struct aml_stream_in *) calloc(1, sizeof(struct aml_stream_in)); |
1664 | if (!in) { |
1665 | return -ENOMEM; |
1666 | } |
1667 | in->stream.common.get_sample_rate = in_get_sample_rate; |
1668 | in->stream.common.set_sample_rate = in_set_sample_rate; |
1669 | in->stream.common.get_buffer_size = in_get_buffer_size; |
1670 | in->stream.common.get_channels = in_get_channels; |
1671 | in->stream.common.get_format = in_get_format; |
1672 | in->stream.common.set_format = in_set_format; |
1673 | in->stream.common.standby = in_standby; |
1674 | in->stream.common.dump = in_dump; |
1675 | in->stream.common.set_parameters = in_set_parameters; |
1676 | in->stream.common.get_parameters = in_get_parameters; |
1677 | in->stream.common.add_audio_effect = NULL;//in_add_audio_effect; |
1678 | in->stream.common.remove_audio_effect = NULL;//in_remove_audio_effect; |
1679 | in->stream.set_gain = in_set_gain; |
1680 | in->stream.read = in_read; |
1681 | in->stream.get_input_frames_lost = in_get_input_frames_lost; |
1682 | in->requested_rate = config->sample_rate; |
1683 | memcpy(&in->config, &pcm_config_in, sizeof(pcm_config_in)); |
1684 | ret = check_input_stream(in); |
1685 | if (ret < 0) { |
1686 | ALOGE("fail to open input stream, change channel count from %d to %d", |
1687 | in->config.channels, channel_count); |
1688 | in->config.channels = channel_count; |
1689 | } |
1690 | if (in->config.channels == 1) { |
1691 | config->channel_mask = AUDIO_CHANNEL_IN_MONO; |
1692 | } else if (in->config.channels == 2) { |
1693 | config->channel_mask = AUDIO_CHANNEL_IN_STEREO; |
1694 | } else { |
1695 | ALOGE("Bad value of channel count : %d", in->config.channels); |
1696 | } |
1697 | in->buffer = malloc(in->config.period_size * |
1698 | audio_stream_in_frame_size(&in->stream)); |
1699 | if (!in->buffer) { |
1700 | ret = -ENOMEM; |
1701 | goto err_open; |
1702 | } |
1703 | in->dev = ladev; |
1704 | in->standby = 1; |
1705 | in->device = devices & ~AUDIO_DEVICE_BIT_IN; |
1706 | *stream_in = &in->stream; |
1707 | return 0; |
1708 | err_open: |
1709 | free(in); |
1710 | *stream_in = NULL; |
1711 | return ret; |
1712 | } |
1713 | |
1714 | static void |
1715 | adev_close_input_stream(struct audio_hw_device *dev, |
1716 | struct audio_stream_in *stream) |
1717 | { |
1718 | struct aml_stream_in *in = (struct aml_stream_in *) stream; |
1719 | |
1720 | LOGFUNC("%s(%p, %p)", __FUNCTION__, dev, stream); |
1721 | in_standby(&stream->common); |
1722 | free(stream); |
1723 | return; |
1724 | } |
1725 | |
1726 | static int |
1727 | adev_dump(const audio_hw_device_t * device, int fd) |
1728 | { |
1729 | LOGFUNC("%s(%p, %d)", __FUNCTION__, device, fd); |
1730 | #if 0 |
1731 | struct aml_audio_device *adev = (struct aml_audio_device *) device; |
1732 | struct aml_stream_out *out = (struct aml_stream_out *) stream; |
1733 | struct aml_audio_device *adev = out->dev; |
1734 | audio_hwsync_t *p_hwsync = &adev->hwsync; |
1735 | dprintf(fd, "Out %p dump:\n", out); |
1736 | dprintf(fd, "frame write sum %lld,spdif_enc_init_frame_write_sum %lld\n", |
1737 | out->frame_write_sum, out->spdif_enc_init_frame_write_sum); |
1738 | dprintf(fd, "HWSYNC status:\n"); |
1739 | dprintf(fd, "hwsync enable:%d\n", adev->hw_sync_mode); |
1740 | dprintf(fd, "hw_sync_state:%d\n", p_hwsync->hw_sync_state); |
1741 | dprintf(fd, "first_apts_flag:%d\n", p_hwsync->first_apts_flag); |
1742 | dprintf(fd, "first_apts:%llx\n", p_hwsync->first_apts); |
1743 | dprintf(fd, "last_apts_from_header:%llx\n", p_hwsync->last_apts_from_header); |
1744 | dprintf(fd, "first_apts_flag:%d\n", p_hwsync->first_apts_flag); |
1745 | dprintf(fd, "hw_sync_frame_size:%d\n", p_hwsync->hw_sync_frame_size); |
1746 | #endif |
1747 | return 0; |
1748 | } |
1749 | |
1750 | static int |
1751 | adev_close(hw_device_t * device) |
1752 | { |
1753 | struct aml_audio_device *adev = (struct aml_audio_device *) device; |
1754 | |
1755 | LOGFUNC("%s(%p)", __FUNCTION__, device); |
1756 | free(device); |
1757 | return 0; |
1758 | } |
1759 | |
1760 | |
1761 | static int |
1762 | adev_open(const hw_module_t * module, const char *name, |
1763 | hw_device_t ** device) |
1764 | { |
1765 | struct aml_audio_device *adev; |
1766 | int ret; |
1767 | LOGFUNC("%s(%p, %s, %p)", __FUNCTION__, module, name, device); |
1768 | if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) { |
1769 | return -EINVAL; |
1770 | } |
1771 | |
1772 | adev = calloc(1, sizeof(struct aml_audio_device)); |
1773 | if (!adev) { |
1774 | return -ENOMEM; |
1775 | } |
1776 | adev->hw_device.common.tag = HARDWARE_DEVICE_TAG; |
1777 | adev->hw_device.common.version = AUDIO_DEVICE_API_VERSION_2_0; |
1778 | adev->hw_device.common.module = (struct hw_module_t *) module; |
1779 | adev->hw_device.common.close = adev_close; |
1780 | //adev->hw_device.get_supported_devices = adev_get_supported_devices; |
1781 | adev->hw_device.init_check = adev_init_check; |
1782 | adev->hw_device.set_voice_volume = adev_set_voice_volume; |
1783 | adev->hw_device.set_master_volume = adev_set_master_volume; |
1784 | adev->hw_device.get_master_volume = adev_get_master_volume; |
1785 | adev->hw_device.set_master_mute = adev_set_master_mute; |
1786 | adev->hw_device.get_master_mute = adev_get_master_mute; |
1787 | adev->hw_device.set_mode = adev_set_mode; |
1788 | adev->hw_device.set_mic_mute = adev_set_mic_mute; |
1789 | adev->hw_device.get_mic_mute = adev_get_mic_mute; |
1790 | adev->hw_device.set_parameters = adev_set_parameters; |
1791 | adev->hw_device.get_parameters = adev_get_parameters; |
1792 | adev->hw_device.get_input_buffer_size = adev_get_input_buffer_size; |
1793 | adev->hw_device.open_output_stream = adev_open_output_stream; |
1794 | adev->hw_device.close_output_stream = adev_close_output_stream; |
1795 | adev->hw_device.open_input_stream = adev_open_input_stream; |
1796 | adev->hw_device.close_input_stream = adev_close_input_stream; |
1797 | adev->hw_device.dump = adev_dump; |
1798 | /* Set the default route before the PCM stream is opened */ |
1799 | adev->mode = AUDIO_MODE_NORMAL; |
1800 | adev->out_device = AUDIO_DEVICE_OUT_AUX_DIGITAL; |
1801 | adev->in_device = AUDIO_DEVICE_IN_BUILTIN_MIC & ~AUDIO_DEVICE_BIT_IN; |
1802 | select_output_device(adev); |
1803 | *device = &adev->hw_device.common; |
1804 | return 0; |
1805 | } |
1806 | |
1807 | static struct hw_module_methods_t hal_module_methods = { |
1808 | .open = adev_open, |
1809 | }; |
1810 | |
1811 | struct audio_module HAL_MODULE_INFO_SYM = { |
1812 | .common = { |
1813 | .tag = HARDWARE_MODULE_TAG, |
1814 | .module_api_version = AUDIO_MODULE_API_VERSION_0_1, |
1815 | .hal_api_version = HARDWARE_HAL_API_VERSION, |
1816 | .id = AUDIO_HARDWARE_MODULE_ID, |
1817 | .name = "aml HDMI audio HW HAL", |
1818 | .author = "amlogic, Corp.", |
1819 | .methods = &hal_module_methods, |
1820 | }, |
1821 | }; |
1822 |