1 /*
2  * Copyright (C) 2015 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_extn"
18 /*#define LOG_NDEBUG 0*/
19 #define LOG_NDDEBUG 0
20 
21 #include <stdlib.h>
22 #include <errno.h>
23 #include <dlfcn.h>
24 #include <cutils/properties.h>
25 #include <log/log.h>
26 
27 #include "audio_hw.h"
28 #include "audio_extn.h"
29 #include "platform.h"
30 #include "platform_api.h"
31 
32 struct snd_card_split cur_snd_card_split = {
33     .device = {0},
34     .snd_card = {0},
35     .form_factor = {0},
36 };
37 
audio_extn_get_snd_card_split()38 struct snd_card_split *audio_extn_get_snd_card_split()
39 {
40     return &cur_snd_card_split;
41 }
42 
audio_extn_set_snd_card_split(const char * in_snd_card_name)43 void audio_extn_set_snd_card_split(const char* in_snd_card_name)
44 {
45     /* sound card name follows below mentioned convention
46        <target name>-<sound card name>-<form factor>-snd-card
47        parse target name, sound card name and form factor
48     */
49     char *snd_card_name = strdup(in_snd_card_name);
50     char *tmp = NULL;
51     char *device = NULL;
52     char *snd_card = NULL;
53     char *form_factor = NULL;
54 
55     if (in_snd_card_name == NULL) {
56         ALOGE("%s: snd_card_name passed is NULL", __func__);
57         goto on_error;
58     }
59 
60     device = strtok_r(snd_card_name, "-", &tmp);
61     if (device == NULL) {
62         ALOGE("%s: called on invalid snd card name", __func__);
63         goto on_error;
64     }
65     strlcpy(cur_snd_card_split.device, device, HW_INFO_ARRAY_MAX_SIZE);
66 
67     snd_card = strtok_r(NULL, "-", &tmp);
68     if (snd_card == NULL) {
69         ALOGE("%s: called on invalid snd card name", __func__);
70         goto on_error;
71     }
72     strlcpy(cur_snd_card_split.snd_card, snd_card, HW_INFO_ARRAY_MAX_SIZE);
73 
74     form_factor = strtok_r(NULL, "-", &tmp);
75     if (form_factor == NULL) {
76         ALOGE("%s: called on invalid snd card name", __func__);
77         goto on_error;
78     }
79     strlcpy(cur_snd_card_split.form_factor, form_factor, HW_INFO_ARRAY_MAX_SIZE);
80 
81     ALOGI("%s: snd_card_name(%s) device(%s) snd_card(%s) form_factor(%s)",
82                __func__, in_snd_card_name, device, snd_card, form_factor);
83 
84 on_error:
85     if (snd_card_name)
86         free(snd_card_name);
87 }
88 
89 #ifdef KPI_OPTIMIZE_ENABLED
90 typedef int (*perf_lock_acquire_t)(int, int, int*, int);
91 typedef int (*perf_lock_release_t)(int);
92 
93 static void *qcopt_handle;
94 static perf_lock_acquire_t perf_lock_acq;
95 static perf_lock_release_t perf_lock_rel;
96 
97 static int perf_lock_handle;
98 char opt_lib_path[PROPERTY_VALUE_MAX] = {0};
99 
100 int perf_lock_opts[] = {0x101, 0x20E, 0x30E};
101 
audio_extn_perf_lock_init(void)102 int audio_extn_perf_lock_init(void)
103 {
104     int ret = 0;
105     if (qcopt_handle == NULL) {
106         if (property_get("ro.vendor.extension_library",
107                          opt_lib_path, NULL) <= 0) {
108             ALOGE("%s: Failed getting perf property", __func__);
109             ret = -EINVAL;
110             goto err;
111         }
112         if ((qcopt_handle = dlopen(opt_lib_path, RTLD_NOW)) == NULL) {
113             ALOGE("%s: Failed to open perf handle", __func__);
114             ret = -EINVAL;
115             goto err;
116         } else {
117             perf_lock_acq = (perf_lock_acquire_t)dlsym(qcopt_handle,
118                                                        "perf_lock_acq");
119             if (perf_lock_acq == NULL) {
120                 ALOGE("%s: Perf lock Acquire NULL", __func__);
121                 dlclose(qcopt_handle);
122                 qcopt_handle = NULL;
123                 ret = -EINVAL;
124                 goto err;
125             }
126             perf_lock_rel = (perf_lock_release_t)dlsym(qcopt_handle,
127                                                        "perf_lock_rel");
128             if (perf_lock_rel == NULL) {
129                 ALOGE("%s: Perf lock Release NULL", __func__);
130                 dlclose(qcopt_handle);
131                 qcopt_handle = NULL;
132                 ret = -EINVAL;
133                 goto err;
134             }
135             ALOGD("%s: Perf lock handles Success", __func__);
136         }
137     }
138 err:
139     return ret;
140 }
141 
audio_extn_perf_lock_acquire(void)142 void audio_extn_perf_lock_acquire(void)
143 {
144     if (perf_lock_acq) {
145         perf_lock_handle = perf_lock_acq(perf_lock_handle, 0, perf_lock_opts, 3);
146         ALOGV("%s: Perf lock acquired", __func__);
147     } else {
148         ALOGE("%s: Perf lock acquire error", __func__);
149     }
150 }
151 
audio_extn_perf_lock_release(void)152 void audio_extn_perf_lock_release(void)
153 {
154     if (perf_lock_rel && perf_lock_handle) {
155         perf_lock_rel(perf_lock_handle);
156         perf_lock_handle = 0;
157         ALOGV("%s: Perf lock released", __func__);
158     } else {
159         ALOGE("%s: Perf lock release error", __func__);
160     }
161 }
162 #endif /* KPI_OPTIMIZE_ENABLED */
163