blob: 8d6ed79c12a69cc9ad981628873393bfc26708f1 [file] [log] [blame]
wei.wang1e45cfd32023-07-10 08:33:46 +00001/*
2 * Copyright (C) 2023 Amlogic Corporation.
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#define LOG_TAG "AML_Audio_Setting"
17
18#include <stdio.h>
19#include <stdlib.h>
20#include <stdint.h>
21#include <string.h>
22#include <unistd.h>
23#include <fcntl.h>
24#include <errno.h>
25#include <ctype.h>
26#include <poll.h>
27#include <sys/ioctl.h>
28#include <pthread.h>
29#include <linux/ioctl.h>
30#define __force
31#define __bitwise
32#define __user
33#include <sound/asound.h>
34#include "AML_Audio_Setting.h"
35#include <cutils/log.h>
36
37#ifndef SNDRV_CTL_ELEM_ID_NAME_MAXLEN
38#define SNDRV_CTL_ELEM_ID_NAME_MAXLEN 44
39#endif
40#define DEFAULT_AML_SOUND_CARD 0
41/* TLV header size*/
42#define TLV_HEADER_SIZE (2 * sizeof(unsigned int))
43
44#define TDMB_GAIN "TDMOUT_B Software Gain"
wei.wang158743372023-08-07 08:07:05 +000045#define TDMA_GAIN "TDMOUT_A Software Gain"
46#define AML_CHIP_ID "AML chip id"
47#define AML_CHIP_ID_S1A 69
wei.wang1e45cfd32023-07-10 08:33:46 +000048#define HDMI_OUT_MUTE "Audio hdmi-out mute"
49#define DAC_DIGITAL_VOLUME "DAC Digital Playback Volume"
50#define DAC_DIGITAl_DEFAULT_VOLUME (251)
51#define HEADPHONE_DAC_CHANNEL_NUM (2)
52
53extern "C" {
54
55struct mixer_ctl {
56 struct mixer *mixer;
57 struct snd_ctl_elem_info *info;
58 char **ename;
59 bool info_retrieved;
60};
61
62struct mixer {
63 int fd;
64 struct snd_ctl_card_info card_info;
65 struct snd_ctl_elem_info *elem_info;
66 struct mixer_ctl *ctl;
67 unsigned int count;
68};
69
70/* Mixer control types */
71enum mixer_ctl_type {
72 MIXER_CTL_TYPE_BOOL,
73 MIXER_CTL_TYPE_INT,
74 MIXER_CTL_TYPE_ENUM,
75 MIXER_CTL_TYPE_BYTE,
76 MIXER_CTL_TYPE_IEC958,
77 MIXER_CTL_TYPE_INT64,
78 MIXER_CTL_TYPE_UNKNOWN,
79
80 MIXER_CTL_TYPE_MAX,
81};
82
83static pthread_mutex_t g_volume_lock = PTHREAD_MUTEX_INITIALIZER;
84static pthread_mutex_t g_mute_lock = PTHREAD_MUTEX_INITIALIZER;
wei.wang158743372023-08-07 08:07:05 +000085static int chip_id = 0;
wei.wang1e45cfd32023-07-10 08:33:46 +000086
87static void _mixer_close(struct mixer *mixer)
88{
89 unsigned int n,m;
90
91 if (!mixer)
92 return;
93
94 if (mixer->fd >= 0)
95 close(mixer->fd);
96
97 if (mixer->ctl) {
98 for (n = 0; n < mixer->count; n++) {
99 if (mixer->ctl[n].ename) {
100 unsigned int max = mixer->ctl[n].info->value.enumerated.items;
101 for (m = 0; m < max; m++)
102 free(mixer->ctl[n].ename[m]);
103 free(mixer->ctl[n].ename);
104 }
105 }
106 free(mixer->ctl);
107 }
108
109 if (mixer->elem_info)
110 free(mixer->elem_info);
111
112 free(mixer);
113
114 /* TODO: verify frees */
115}
116
117static struct mixer *_mixer_open(unsigned int card)
118{
119 struct snd_ctl_elem_list elist;
120 struct snd_ctl_elem_id *eid = NULL;
121 struct mixer *mixer = NULL;
122 unsigned int n;
123 int fd;
124 char fn[256];
125
126 snprintf(fn, sizeof(fn), "/dev/snd/controlC%u", card);
127 fd = open(fn, O_RDWR);
128 if (fd < 0)
129 return 0;
130
131 memset(&elist, 0, sizeof(elist));
132 if (ioctl(fd, SNDRV_CTL_IOCTL_ELEM_LIST, &elist) < 0)
133 goto fail;
134
135 mixer = (struct mixer *)calloc(1, sizeof(*mixer));
136 if (!mixer)
137 goto fail;
138
139 mixer->ctl = (struct mixer_ctl *)calloc(elist.count, sizeof(struct mixer_ctl));
140 mixer->elem_info = (struct snd_ctl_elem_info *)calloc(elist.count, sizeof(struct snd_ctl_elem_info));
141 if (!mixer->ctl || !mixer->elem_info)
142 goto fail;
143
144 if (ioctl(fd, SNDRV_CTL_IOCTL_CARD_INFO, &mixer->card_info) < 0)
145 goto fail;
146
147 eid = (struct snd_ctl_elem_id *)calloc(elist.count, sizeof(struct snd_ctl_elem_id));
148 if (!eid)
149 goto fail;
150
151 mixer->count = elist.count;
152 mixer->fd = fd;
153 elist.space = mixer->count;
154 elist.pids = eid;
155 if (ioctl(fd, SNDRV_CTL_IOCTL_ELEM_LIST, &elist) < 0)
156 goto fail;
157
158 for (n = 0; n < mixer->count; n++) {
159 struct mixer_ctl *ctl = mixer->ctl + n;
160
161 ctl->mixer = mixer;
162 ctl->info = mixer->elem_info + n;
163 ctl->info->id.numid = eid[n].numid;
164 strncpy((char *)ctl->info->id.name, (char *)eid[n].name,
165 SNDRV_CTL_ELEM_ID_NAME_MAXLEN);
166 ctl->info->id.name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN - 1] = 0;
167 }
168
169 free(eid);
170 return mixer;
171
172fail:
173 /* TODO: verify frees in failure case */
174 if (eid)
175 free(eid);
176 if (mixer)
177 _mixer_close(mixer);
178 else if (fd >= 0)
179 close(fd);
180 return 0;
181}
182
183static bool _mixer_ctl_get_elem_info(struct mixer_ctl* ctl)
184{
185 if (!ctl->info_retrieved) {
186 if (ioctl(ctl->mixer->fd, SNDRV_CTL_IOCTL_ELEM_INFO, ctl->info) < 0)
187 return false;
188 ctl->info_retrieved = true;
189 }
190
191 if (ctl->info->type != SNDRV_CTL_ELEM_TYPE_ENUMERATED || ctl->ename)
192 return true;
193
194 struct snd_ctl_elem_info tmp;
195 char** enames = (char**)calloc(ctl->info->value.enumerated.items, sizeof(char*));
196 if (!enames)
197 return false;
198
199 for (unsigned int i = 0; i < ctl->info->value.enumerated.items; i++) {
200 memset(&tmp, 0, sizeof(tmp));
201 tmp.id.numid = ctl->info->id.numid;
202 tmp.value.enumerated.item = i;
203 if (ioctl(ctl->mixer->fd, SNDRV_CTL_IOCTL_ELEM_INFO, &tmp) < 0)
204 goto fail;
205 enames[i] = strdup(tmp.value.enumerated.name);
206 if (!enames[i])
207 goto fail;
208 }
209 ctl->ename = enames;
210 return true;
211
212fail:
213 free(enames);
214 return false;
215}
216
217static const char *_mixer_get_name(struct mixer *mixer)
218{
219 return (const char *)mixer->card_info.name;
220}
221
222static unsigned int _mixer_get_num_ctls(struct mixer *mixer)
223{
224 if (!mixer)
225 return 0;
226
227 return mixer->count;
228}
229
230static struct mixer_ctl *_mixer_get_ctl(struct mixer *mixer, unsigned int id)
231{
232 struct mixer_ctl *ctl;
233
234 if (!mixer || (id >= mixer->count))
235 return NULL;
236
237 ctl = mixer->ctl + id;
238 if (!_mixer_ctl_get_elem_info(ctl))
239 return NULL;
240
241 return ctl;
242}
243
244static struct mixer_ctl *_mixer_get_ctl_by_name(struct mixer *mixer, const char *name)
245{
246 unsigned int n;
247
248 if (!mixer)
249 return NULL;
250
251 for (n = 0; n < mixer->count; n++)
252 if (!strcmp(name, (char*) mixer->elem_info[n].id.name))
253 return _mixer_get_ctl(mixer, n);
254
255 return NULL;
256}
257
258static void _mixer_ctl_update(struct mixer_ctl *ctl)
259{
260 ioctl(ctl->mixer->fd, SNDRV_CTL_IOCTL_ELEM_INFO, ctl->info);
261}
262
263static const char *_mixer_ctl_get_name(struct mixer_ctl *ctl)
264{
265 if (!ctl)
266 return NULL;
267
268 return (const char *)ctl->info->id.name;
269}
270
271static enum mixer_ctl_type _mixer_ctl_get_type(struct mixer_ctl *ctl)
272{
273 if (!ctl)
274 return MIXER_CTL_TYPE_UNKNOWN;
275
276 switch (ctl->info->type) {
277 case SNDRV_CTL_ELEM_TYPE_BOOLEAN: return MIXER_CTL_TYPE_BOOL;
278 case SNDRV_CTL_ELEM_TYPE_INTEGER: return MIXER_CTL_TYPE_INT;
279 case SNDRV_CTL_ELEM_TYPE_ENUMERATED: return MIXER_CTL_TYPE_ENUM;
280 case SNDRV_CTL_ELEM_TYPE_BYTES: return MIXER_CTL_TYPE_BYTE;
281 case SNDRV_CTL_ELEM_TYPE_IEC958: return MIXER_CTL_TYPE_IEC958;
282 case SNDRV_CTL_ELEM_TYPE_INTEGER64: return MIXER_CTL_TYPE_INT64;
283 default: return MIXER_CTL_TYPE_UNKNOWN;
284 };
285}
286
287static const char *_mixer_ctl_get_type_string(struct mixer_ctl *ctl)
288{
289 if (!ctl)
290 return "";
291
292 switch (ctl->info->type) {
293 case SNDRV_CTL_ELEM_TYPE_BOOLEAN: return "BOOL";
294 case SNDRV_CTL_ELEM_TYPE_INTEGER: return "INT";
295 case SNDRV_CTL_ELEM_TYPE_ENUMERATED: return "ENUM";
296 case SNDRV_CTL_ELEM_TYPE_BYTES: return "BYTE";
297 case SNDRV_CTL_ELEM_TYPE_IEC958: return "IEC958";
298 case SNDRV_CTL_ELEM_TYPE_INTEGER64: return "INT64";
299 default: return "Unknown";
300 };
301}
302
303static unsigned int _mixer_ctl_get_num_values(struct mixer_ctl *ctl)
304{
305 if (!ctl)
306 return 0;
307
308 return ctl->info->count;
309}
310
311static int percent_to_int(struct snd_ctl_elem_info *ei, int percent)
312{
313 int range;
314
315 if (percent > 100)
316 percent = 100;
317 else if (percent < 0)
318 percent = 0;
319
320 range = (ei->value.integer.max - ei->value.integer.min);
321
322 return ei->value.integer.min + (range * percent) / 100;
323}
324
325static int int_to_percent(struct snd_ctl_elem_info *ei, int value)
326{
327 int range = (ei->value.integer.max - ei->value.integer.min);
328
329 if (range == 0)
330 return 0;
331
332 return ((value - ei->value.integer.min) / range) * 100;
333}
334
335static int _mixer_ctl_set_value(struct mixer_ctl *ctl, unsigned int id, int value)
336{
337 struct snd_ctl_elem_value ev;
338 int ret;
339
340 if (!ctl || (id >= ctl->info->count))
341 return -EINVAL;
342
343 memset(&ev, 0, sizeof(ev));
344 ev.id.numid = ctl->info->id.numid;
345 ret = ioctl(ctl->mixer->fd, SNDRV_CTL_IOCTL_ELEM_READ, &ev);
346 if (ret < 0)
347 return ret;
348
349 switch (ctl->info->type) {
350 case SNDRV_CTL_ELEM_TYPE_BOOLEAN:
351 ev.value.integer.value[id] = !!value;
352 break;
353
354 case SNDRV_CTL_ELEM_TYPE_INTEGER:
355 ev.value.integer.value[id] = value;
356 break;
357
358 case SNDRV_CTL_ELEM_TYPE_ENUMERATED:
359 ev.value.enumerated.item[id] = value;
360 break;
361
362 case SNDRV_CTL_ELEM_TYPE_BYTES:
363 ev.value.bytes.data[id] = value;
364 break;
365
366 default:
367 return -EINVAL;
368 }
369
370 return ioctl(ctl->mixer->fd, SNDRV_CTL_IOCTL_ELEM_WRITE, &ev);
371}
372
373static int _mixer_ctl_get_value(struct mixer_ctl *ctl, unsigned int id)
374{
375 struct snd_ctl_elem_value ev;
376 int ret;
377
378 if (!ctl || (id >= ctl->info->count))
379 return -EINVAL;
380
381 memset(&ev, 0, sizeof(ev));
382 ev.id.numid = ctl->info->id.numid;
383 ret = ioctl(ctl->mixer->fd, SNDRV_CTL_IOCTL_ELEM_READ, &ev);
384 if (ret < 0)
385 return ret;
386
387 switch (ctl->info->type) {
388 case SNDRV_CTL_ELEM_TYPE_BOOLEAN:
389 return !!ev.value.integer.value[id];
390
391 case SNDRV_CTL_ELEM_TYPE_INTEGER:
392 return ev.value.integer.value[id];
393
394 case SNDRV_CTL_ELEM_TYPE_ENUMERATED:
395 return ev.value.enumerated.item[id];
396
397 case SNDRV_CTL_ELEM_TYPE_BYTES:
398 return ev.value.bytes.data[id];
399
400 default:
401 return -EINVAL;
402 }
403
404 return 0;
405}
406
407static int _mixer_ctl_get_percent(struct mixer_ctl *ctl, unsigned int id)
408{
409 if (!ctl || (ctl->info->type != SNDRV_CTL_ELEM_TYPE_INTEGER))
410 return -EINVAL;
411
412 return int_to_percent(ctl->info, _mixer_ctl_get_value(ctl, id));
413}
414
415static int _mixer_ctl_set_percent(struct mixer_ctl *ctl, unsigned int id, int percent)
416{
417 if (!ctl || (ctl->info->type != SNDRV_CTL_ELEM_TYPE_INTEGER))
418 return -EINVAL;
419
420 return _mixer_ctl_set_value(ctl, id, percent_to_int(ctl->info, percent));
421}
422
423static int _mixer_ctl_is_access_tlv_rw(struct mixer_ctl *ctl)
424{
425 return (ctl->info->access & SNDRV_CTL_ELEM_ACCESS_TLV_READWRITE);
426}
427
428static int _mixer_ctl_get_array(struct mixer_ctl *ctl, void *array, size_t count)
429{
430 struct snd_ctl_elem_value ev;
431 int ret = 0;
432 size_t size;
433 void *source;
434 size_t total_count;
435
436 if ((!ctl) || !count || !array)
437 return -EINVAL;
438
439 total_count = ctl->info->count;
440
441 if ((ctl->info->type == SNDRV_CTL_ELEM_TYPE_BYTES) &&
442 _mixer_ctl_is_access_tlv_rw(ctl)) {
443 /* Additional two words is for the TLV header */
444 total_count += TLV_HEADER_SIZE;
445 }
446
447 if (count > total_count)
448 return -EINVAL;
449
450 memset(&ev, 0, sizeof(ev));
451 ev.id.numid = ctl->info->id.numid;
452
453 switch (ctl->info->type) {
454 case SNDRV_CTL_ELEM_TYPE_BOOLEAN:
455 case SNDRV_CTL_ELEM_TYPE_INTEGER:
456 ret = ioctl(ctl->mixer->fd, SNDRV_CTL_IOCTL_ELEM_READ, &ev);
457 if (ret < 0)
458 return ret;
459 size = sizeof(ev.value.integer.value[0]);
460 source = ev.value.integer.value;
461 break;
462
463 case SNDRV_CTL_ELEM_TYPE_BYTES:
464 /* check if this is new bytes TLV */
465 if (_mixer_ctl_is_access_tlv_rw(ctl)) {
466 struct snd_ctl_tlv *tlv;
467 int ret;
468
469 if (count > SIZE_MAX - sizeof(*tlv))
470 return -EINVAL;
471 tlv = (struct snd_ctl_tlv *)calloc(1, sizeof(*tlv) + count);
472 if (!tlv)
473 return -ENOMEM;
474 tlv->numid = ctl->info->id.numid;
475 tlv->length = count;
476 ret = ioctl(ctl->mixer->fd, SNDRV_CTL_IOCTL_TLV_READ, tlv);
477
478 source = tlv->tlv;
479 memcpy(array, source, count);
480
481 free(tlv);
482
483 return ret;
484 } else {
485 ret = ioctl(ctl->mixer->fd, SNDRV_CTL_IOCTL_ELEM_READ, &ev);
486 if (ret < 0)
487 return ret;
488 size = sizeof(ev.value.bytes.data[0]);
489 source = ev.value.bytes.data;
490 break;
491 }
492
493 case SNDRV_CTL_ELEM_TYPE_IEC958:
494 size = sizeof(ev.value.iec958);
495 source = &ev.value.iec958;
496 break;
497
498 default:
499 return -EINVAL;
500 }
501
502 memcpy(array, source, size * count);
503
504 return 0;
505}
506
507static int _mixer_ctl_set_array(struct mixer_ctl *ctl, const void *array, size_t count)
508{
509 struct snd_ctl_elem_value ev;
510 size_t size;
511 void *dest;
512 size_t total_count;
513
514 if ((!ctl) || !count || !array)
515 return -EINVAL;
516
517 total_count = ctl->info->count;
518
519 if ((ctl->info->type == SNDRV_CTL_ELEM_TYPE_BYTES) &&
520 _mixer_ctl_is_access_tlv_rw(ctl)) {
521 /* Additional two words is for the TLV header */
522 total_count += TLV_HEADER_SIZE;
523 }
524
525 if (count > total_count)
526 return -EINVAL;
527
528 memset(&ev, 0, sizeof(ev));
529 ev.id.numid = ctl->info->id.numid;
530
531 switch (ctl->info->type) {
532 case SNDRV_CTL_ELEM_TYPE_BOOLEAN:
533 case SNDRV_CTL_ELEM_TYPE_INTEGER:
534 size = sizeof(ev.value.integer.value[0]);
535 dest = ev.value.integer.value;
536 break;
537
538 case SNDRV_CTL_ELEM_TYPE_BYTES:
539 /* check if this is new bytes TLV */
540 if (_mixer_ctl_is_access_tlv_rw(ctl)) {
541 struct snd_ctl_tlv *tlv;
542 int ret = 0;
543 if (count > SIZE_MAX - sizeof(*tlv))
544 return -EINVAL;
545 tlv = (struct snd_ctl_tlv *)calloc(1, sizeof(*tlv) + count);
546 if (!tlv)
547 return -ENOMEM;
548 tlv->numid = ctl->info->id.numid;
549 tlv->length = count;
550 memcpy(tlv->tlv, array, count);
551
552 ret = ioctl(ctl->mixer->fd, SNDRV_CTL_IOCTL_TLV_WRITE, tlv);
553 free(tlv);
554
555 return ret;
556 } else {
557 size = sizeof(ev.value.bytes.data[0]);
558 dest = ev.value.bytes.data;
559 }
560 break;
561
562 case SNDRV_CTL_ELEM_TYPE_IEC958:
563 size = sizeof(ev.value.iec958);
564 dest = &ev.value.iec958;
565 break;
566
567 default:
568 return -EINVAL;
569 }
570
571 memcpy(dest, array, size * count);
572
573 return ioctl(ctl->mixer->fd, SNDRV_CTL_IOCTL_ELEM_WRITE, &ev);
574}
575
576static int _mixer_ctl_get_range_min(struct mixer_ctl *ctl)
577{
578 if (!ctl || (ctl->info->type != SNDRV_CTL_ELEM_TYPE_INTEGER))
579 return -EINVAL;
580
581 return ctl->info->value.integer.min;
582}
583
584static int _mixer_ctl_get_range_max(struct mixer_ctl *ctl)
585{
586 if (!ctl || (ctl->info->type != SNDRV_CTL_ELEM_TYPE_INTEGER))
587 return -EINVAL;
588
589 return ctl->info->value.integer.max;
590}
591
592static unsigned int _mixer_ctl_get_num_enums(struct mixer_ctl *ctl)
593{
594 if (!ctl)
595 return 0;
596
597 return ctl->info->value.enumerated.items;
598}
599
600static const char *_mixer_ctl_get_enum_string(struct mixer_ctl *ctl,
601 unsigned int enum_id)
602{
603 if (!ctl || (ctl->info->type != SNDRV_CTL_ELEM_TYPE_ENUMERATED) ||
604 (enum_id >= ctl->info->value.enumerated.items))
605 return NULL;
606
607 return (const char *)ctl->ename[enum_id];
608}
609
610static int _mixer_ctl_set_enum_by_string(struct mixer_ctl *ctl, const char *string)
611{
612 unsigned int i, num_enums;
613 struct snd_ctl_elem_value ev;
614 int ret;
615
616 if (!ctl || (ctl->info->type != SNDRV_CTL_ELEM_TYPE_ENUMERATED))
617 return -EINVAL;
618
619 num_enums = ctl->info->value.enumerated.items;
620 for (i = 0; i < num_enums; i++) {
621 if (!strcmp(string, ctl->ename[i])) {
622 memset(&ev, 0, sizeof(ev));
623 ev.value.enumerated.item[0] = i;
624 ev.id.numid = ctl->info->id.numid;
625 ret = ioctl(ctl->mixer->fd, SNDRV_CTL_IOCTL_ELEM_WRITE, &ev);
626 if (ret < 0)
627 return ret;
628 return 0;
629 }
630 }
631
632 return -EINVAL;
633}
634
635static int aml_audio_mixer_int(const char *control, int value, bool set)
636{
637 int ret = -1;
638 struct mixer_ctl *pCtrl = NULL;
639 struct mixer *mixer = NULL;
640 if (control == NULL) {
641 ALOGE("[%s:%d] control is invalid!\n", __FUNCTION__, __LINE__);
642 return ret;
643 }
644 mixer = _mixer_open(DEFAULT_AML_SOUND_CARD);
645
646 if (mixer == NULL) {
647 ALOGE("[%s:%d] mixer is invalid!\n", __FUNCTION__, __LINE__);
648 return ret;
649 }
650
651 pCtrl = _mixer_get_ctl_by_name(mixer, control);
652 if (pCtrl == NULL) {
653 ALOGE("[%s:%d] Failed to find control: %s\n", __FUNCTION__, __LINE__, control);
654 _mixer_close(mixer);
655 return ret;
656 }
657 if (set) {
658 ret = _mixer_ctl_set_value(pCtrl, 0, value);
659 ALOGV("[%s:%d] set %s: %d, ret %d", __FUNCTION__, __LINE__, control, value, ret);
660 } else {
661 ret = _mixer_ctl_get_value(pCtrl, 0);
662 }
663 _mixer_close(mixer);
664
665 return ret;
666}
667
668static int aml_audio_mixer_array(const char *control, void *array, size_t count, bool set)
669{
670 int ret = -1;
671 struct mixer_ctl *pCtrl = NULL;
672 struct mixer *mixer = NULL;
673 if (control == NULL) {
674 ALOGE("[%s:%d] control is invalid!\n", __FUNCTION__, __LINE__);
675 return ret;
676 }
677 mixer = _mixer_open(DEFAULT_AML_SOUND_CARD);
678
679 if (mixer == NULL) {
680 ALOGE("[%s:%d] mixer is invalid!\n", __FUNCTION__, __LINE__);
681 return ret;
682 }
683
684 pCtrl = _mixer_get_ctl_by_name(mixer, control);
685 if (pCtrl == NULL) {
686 ALOGE("[%s:%d] Failed to find control: %s\n", __FUNCTION__, __LINE__, control);
687 _mixer_close(mixer);
688 return ret;
689 }
690 if (set) {
691 ret = _mixer_ctl_set_array(pCtrl, array, count);
692 ALOGV("[%s:%d] set %s, ret %d", __FUNCTION__, __LINE__, control, ret);
693 } else {
694 ret = _mixer_ctl_get_array(pCtrl, array, count);
695 }
696 _mixer_close(mixer);
697
698 return ret;
699}
700
701/* Headphone mute */
702static int set_dac_digital_mute(bool mute)
703{
704 int ret = 0;
705 static bool last_mute_state = false;
706 static int dac_digital_volume = DAC_DIGITAl_DEFAULT_VOLUME; // volume range: 0 ~ 255
707 int headphone_dac_gain[HEADPHONE_DAC_CHANNEL_NUM] = {dac_digital_volume, dac_digital_volume};
708
709 if (last_mute_state == mute) {
710 return ret;
711 }
712 if (mute) {
713 dac_digital_volume = aml_audio_mixer_int(DAC_DIGITAL_VOLUME, 0, false);//get current hp vol
714 headphone_dac_gain[0] = headphone_dac_gain[1] = 0;
715 ret = aml_audio_mixer_array(DAC_DIGITAL_VOLUME, headphone_dac_gain, HEADPHONE_DAC_CHANNEL_NUM, true);
716 } else {
717 //headphone_dac_gain[0] = headphone_dac_gain[1] = dac_digital_volume;
718 ret = aml_audio_mixer_array(DAC_DIGITAL_VOLUME, headphone_dac_gain, HEADPHONE_DAC_CHANNEL_NUM, true);
719 }
720 last_mute_state = mute;
721 ALOGD("[%s:%d] DAC Digital %smute, dac_digital_volume is %d", __func__, __LINE__, mute?" ":"un", dac_digital_volume);
722 return ret;
723}
724
725int aml_audio_set_volume(int value)
726{
727 int ret = 0;
728 if (value < 0 || value > 100) {
729 ALOGE("[%s:%d]bad volume: %d", __func__, __LINE__, value);
730 return -1;
731 }
732
733 pthread_mutex_lock(&g_volume_lock);
wei.wang158743372023-08-07 08:07:05 +0000734 chip_id = aml_audio_mixer_int(AML_CHIP_ID, 0, false);
735 /*s1a use TDM-A as cvbs/hdmi_tx samesource*/
736 if (AML_CHIP_ID_S1A == chip_id)
737 ret = aml_audio_mixer_int(TDMA_GAIN, value, true);
738 else
739 ret = aml_audio_mixer_int(TDMB_GAIN, value, true);
740
741 ALOGD("[%s:%d] chip_id: %d, volume: %d, ret: %d", __func__, __LINE__, chip_id, value, ret);
wei.wang1e45cfd32023-07-10 08:33:46 +0000742 pthread_mutex_unlock(&g_volume_lock);
743
744 return ret;
745}
746
747int aml_audio_get_volume()
748{
749 pthread_mutex_lock(&g_volume_lock);
750 int ret = 0;
wei.wang158743372023-08-07 08:07:05 +0000751 if (AML_CHIP_ID_S1A == chip_id)
752 ret = aml_audio_mixer_int(TDMA_GAIN, 0, false);
753 else
754 ret = aml_audio_mixer_int(TDMB_GAIN, 0, false);
755 ALOGD("[%s:%d] chip_id: %d, volume: %d", __func__, __LINE__, chip_id, ret);
wei.wang1e45cfd32023-07-10 08:33:46 +0000756 pthread_mutex_unlock(&g_volume_lock);
757
758 return ret;
759}
760
761int aml_audio_set_mute(int port, bool mute)
762{
763 pthread_mutex_lock(&g_mute_lock);
764 int ret = -1;
765 if (port <= AUDIO_PORT_MIN || port >= AUDIO_PORT_MAX) {
766 ALOGE("[%s:%d]bad port: %d", __func__, __LINE__, port);
767 } else if (port == AUDIO_PORT_HDMI) {
768 ret = aml_audio_mixer_int(HDMI_OUT_MUTE, mute ? 1 : 0, true);
769 } else if (port == AUDIO_PORT_HEADPHONE) {
770 ret = set_dac_digital_mute(mute);
771 }
772 ALOGD("[%s:%d] port: %d, mute: %d, ret: %d", __func__, __LINE__, port, mute, ret);
773 pthread_mutex_unlock(&g_mute_lock);
774 return ret;
775}
776
777bool aml_audio_get_mute(int port)
778{
779 pthread_mutex_lock(&g_mute_lock);
780 bool ret = false;
781 if (port <= AUDIO_PORT_MIN || port >= AUDIO_PORT_MAX) {
782 ALOGE("[%s:%d]bad port: %d", __func__, __LINE__, port);
783 } else if (port == AUDIO_PORT_HDMI) {
784 ret = aml_audio_mixer_int(HDMI_OUT_MUTE, 0, false) ? true : false;
785 } else if (port == AUDIO_PORT_HEADPHONE) {
786 ret = aml_audio_mixer_int(DAC_DIGITAL_VOLUME, 0, false) ? false : true;
787 }
788 ALOGD("[%s:%d] port: %d, mute: %d", __func__, __LINE__, port, ret);
789 pthread_mutex_unlock(&g_mute_lock);
790 return ret;
791}
792
793}//extern c