1 /*
2  * Copyright (c) 2011-2014, The Linux Foundation. All rights reserved.
3  * Not a Contribution.
4  *
5  * Copyright (C) 2010 The Android Open Source Project
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  */
19 
20 #define LOG_TAG "audio_hw_dolby"
21 #define LOG_NDEBUG 0
22 #define LOG_NDDEBUG 0
23 
24 #include <errno.h>
25 #include <cutils/properties.h>
26 #include <stdlib.h>
27 #include <dlfcn.h>
28 #include <cutils/str_parms.h>
29 #include <cutils/log.h>
30 
31 #include "audio_hw.h"
32 #include "platform.h"
33 #include "platform_api.h"
34 #include "audio_extn.h"
35 #include "sound/compress_params.h"
36 #include "sound/devdep_params.h"
37 
38 #ifdef DS1_DOLBY_DDP_ENABLED
39 
40 #define AUDIO_PARAMETER_DDP_DEV          "ddp_device"
41 #define AUDIO_PARAMETER_DDP_CH_CAP       "ddp_chancap"
42 #define AUDIO_PARAMETER_DDP_MAX_OUT_CHAN "ddp_maxoutchan"
43 #define AUDIO_PARAMETER_DDP_OUT_MODE     "ddp_outmode"
44 #define AUDIO_PARAMETER_DDP_OUT_LFE_ON   "ddp_outlfeon"
45 #define AUDIO_PARAMETER_DDP_COMP_MODE    "ddp_compmode"
46 #define AUDIO_PARAMETER_DDP_STEREO_MODE  "ddp_stereomode"
47 
48 #define PARAM_ID_MAX_OUTPUT_CHANNELS    0x00010DE2
49 #define PARAM_ID_CTL_RUNNING_MODE       0x0
50 #define PARAM_ID_CTL_ERROR_CONCEAL      0x00010DE3
51 #define PARAM_ID_CTL_ERROR_MAX_RPTS     0x00010DE4
52 #define PARAM_ID_CNV_ERROR_CONCEAL      0x00010DE5
53 #define PARAM_ID_CTL_SUBSTREAM_SELECT   0x00010DE6
54 #define PARAM_ID_CTL_INPUT_MODE         0x0
55 #define PARAM_ID_OUT_CTL_OUTMODE        0x00010DE0
56 #define PARAM_ID_OUT_CTL_OUTLFE_ON      0x00010DE1
57 #define PARAM_ID_OUT_CTL_COMPMODE       0x00010D74
58 #define PARAM_ID_OUT_CTL_STEREO_MODE    0x00010D76
59 #define PARAM_ID_OUT_CTL_DUAL_MODE      0x00010D75
60 #define PARAM_ID_OUT_CTL_DRCSCALE_HIGH  0x00010D7A
61 #define PARAM_ID_OUT_CTL_DRCSCALE_LOW   0x00010D79
62 #define PARAM_ID_OUT_CTL_OUT_PCMSCALE   0x00010D78
63 #define PARAM_ID_OUT_CTL_MDCT_BANDLIMIT 0x00010DE7
64 #define PARAM_ID_OUT_CTL_DRC_SUPPRESS   0x00010DE8
65 
66 /* DS1-DDP Endp Params */
67 #define DDP_ENDP_NUM_PARAMS 17
68 #define DDP_ENDP_NUM_DEVICES 21
69 static int ddp_endp_params_id[DDP_ENDP_NUM_PARAMS] = {
70     PARAM_ID_MAX_OUTPUT_CHANNELS, PARAM_ID_CTL_RUNNING_MODE,
71     PARAM_ID_CTL_ERROR_CONCEAL, PARAM_ID_CTL_ERROR_MAX_RPTS,
72     PARAM_ID_CNV_ERROR_CONCEAL, PARAM_ID_CTL_SUBSTREAM_SELECT,
73     PARAM_ID_CTL_INPUT_MODE, PARAM_ID_OUT_CTL_OUTMODE,
74     PARAM_ID_OUT_CTL_OUTLFE_ON, PARAM_ID_OUT_CTL_COMPMODE,
75     PARAM_ID_OUT_CTL_STEREO_MODE, PARAM_ID_OUT_CTL_DUAL_MODE,
76     PARAM_ID_OUT_CTL_DRCSCALE_HIGH, PARAM_ID_OUT_CTL_DRCSCALE_LOW,
77     PARAM_ID_OUT_CTL_OUT_PCMSCALE, PARAM_ID_OUT_CTL_MDCT_BANDLIMIT,
78     PARAM_ID_OUT_CTL_DRC_SUPPRESS
79 };
80 
81 static struct ddp_endp_params {
82     int  device;
83     int  dev_ch_cap;
84     int  param_val[DDP_ENDP_NUM_PARAMS];
85     bool is_param_valid[DDP_ENDP_NUM_PARAMS];
86 } ddp_endp_params[DDP_ENDP_NUM_DEVICES] = {
87           {AUDIO_DEVICE_OUT_EARPIECE, 2,
88               {8, 0, 0, 0, 0, 0, 0, 21, 1, 6, 0, 0, 0, 0, 0, 0, 0},
89               {1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0 } },
90           {AUDIO_DEVICE_OUT_SPEAKER, 2,
91               {8, 0, 0, 0, 0, 0, 0, 21, 1, 6, 0, 0, 0, 0, 0, 0, 0},
92               {1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0} },
93           {AUDIO_DEVICE_OUT_WIRED_HEADSET, 2,
94               {8, 0, 0, 0, 0, 0, 0, 21, 1, 6, 0, 0, 0, 0, 0, 0, 0},
95               {1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0} },
96           {AUDIO_DEVICE_OUT_WIRED_HEADPHONE, 2,
97               {8, 0, 0, 0, 0, 0, 0, 21, 1, 6, 0, 0, 0, 0, 0, 0, 0},
98               {1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0} },
99           {AUDIO_DEVICE_OUT_BLUETOOTH_SCO, 2,
100               {8, 0, 0, 0, 0, 0, 0, 21, 1, 6, 0, 0, 0, 0, 0, 0, 0},
101               {1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0} },
102           {AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET, 2,
103               {8, 0, 0, 0, 0, 0, 0, 21, 1, 6, 0, 0, 0, 0, 0, 0, 0},
104               {1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0} },
105           {AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT, 2,
106               {8, 0, 0, 0, 0, 0, 0, 21, 1, 6, 0, 0, 0, 0, 0, 0, 0},
107               {1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0} },
108           {AUDIO_DEVICE_OUT_BLUETOOTH_A2DP, 2,
109               {8, 0, 0, 0, 0, 0, 0, 21, 1, 6, 0, 0, 0, 0, 0, 0, 0},
110               {1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0} },
111           {AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES, 2,
112               {8, 0, 0, 0, 0, 0, 0, 21, 1, 6, 0, 0, 0, 0, 0, 0, 0},
113               {1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0} },
114           {AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER, 2,
115               {8, 0, 0, 0, 0, 0, 0, 21, 1, 6, 0, 0, 0, 0, 0, 0, 0},
116               {1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0} },
117           {AUDIO_DEVICE_OUT_AUX_DIGITAL, 2,
118               {8, 0, 0, 0, 0, 0, 0, 21, 1, 2, 0, 0, 0, 0, 0, 0, 0},
119               {1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0} },
120           {AUDIO_DEVICE_OUT_AUX_DIGITAL, 6,
121               {8, 0, 0, 0, 0, 0, 0, 21, 1, 2, 0, 0, 0, 0, 0, 0, 0},
122               {1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0} },
123           {AUDIO_DEVICE_OUT_AUX_DIGITAL, 8,
124               {8, 0, 0, 0, 0, 0, 0, 21, 1, 2, 0, 0, 0, 0, 0, 0, 0},
125               {1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0} },
126           {AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET, 2,
127               {8, 0, 0, 0, 0, 0, 0, 21, 1, 6, 0, 0, 0, 0, 0, 0, 0},
128               {1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0} },
129           {AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET, 2,
130               {8, 0, 0, 0, 0, 0, 0, 21, 1, 6, 0, 0, 0, 0, 0, 0, 0},
131               {1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0} },
132           {AUDIO_DEVICE_OUT_USB_ACCESSORY, 2,
133               {8, 0, 0, 0, 0, 0, 0, 21, 1, 6, 0, 0, 0, 0, 0, 0, 0},
134               {1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0} },
135           {AUDIO_DEVICE_OUT_USB_DEVICE, 2,
136               {8, 0, 0, 0, 0, 0, 0, 21, 1, 6, 0, 0, 0, 0, 0, 0, 0},
137               {1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0} },
138           {AUDIO_DEVICE_OUT_FM, 2,
139               {8, 0, 0, 0, 0, 0, 0, 21, 1, 6, 0, 0, 0, 0, 0, 0, 0},
140               {1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0} },
141           {AUDIO_DEVICE_OUT_FM_TX, 2,
142               {8, 0, 0, 0, 0, 0, 0, 21, 1, 6, 0, 0, 0, 0, 0, 0, 0},
143               {1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0} },
144           {AUDIO_DEVICE_OUT_PROXY, 2,
145               {8, 0, 0, 0, 0, 0, 0, 21, 1, 2, 0, 0, 0, 0, 0, 0, 0},
146               {1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0} },
147           {AUDIO_DEVICE_OUT_PROXY, 6,
148               {8, 0, 0, 0, 0, 0, 0, 21, 1, 2, 0, 0, 0, 0, 0, 0, 0},
149               {1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0} },
150 };
151 
update_ddp_endp_table(int device,int dev_ch_cap,int param_id,int param_val)152 int update_ddp_endp_table(int device, int dev_ch_cap, int param_id,
153                           int param_val)
154 {
155     int idx = 0;
156     int param_idx = 0;
157     ALOGV("%s: dev 0x%x dev_ch_cap %d param_id 0x%x param_val %d",
158            __func__, device, dev_ch_cap , param_id, param_val);
159 
160     for(idx=0; idx<DDP_ENDP_NUM_DEVICES; idx++) {
161         if(ddp_endp_params[idx].device == device) {
162             if(ddp_endp_params[idx].dev_ch_cap == dev_ch_cap) {
163                 break;
164             }
165         }
166     }
167 
168     if(idx>=DDP_ENDP_NUM_DEVICES) {
169         ALOGE("%s: device not available in DDP endp config table", __func__);
170         return -EINVAL;
171     }
172 
173     for(param_idx=0; param_idx<DDP_ENDP_NUM_PARAMS; param_idx++) {
174         if (ddp_endp_params_id[param_idx] == param_id) {
175             break;
176         }
177     }
178 
179     if(param_idx>=DDP_ENDP_NUM_PARAMS) {
180         ALOGE("param not available in DDP endp config table");
181         return -EINVAL;
182     }
183 
184     ALOGV("ddp_endp_params[%d].param_val[%d] = %d", idx, param_idx, param_val);
185     ddp_endp_params[idx].param_val[param_idx] = param_val;
186     return 0;
187 }
188 
send_ddp_endp_params_stream(struct stream_out * out,int device,int dev_ch_cap,bool set_cache __unused)189 void send_ddp_endp_params_stream(struct stream_out *out,
190                                  int device, int dev_ch_cap,
191                                  bool set_cache __unused)
192 {
193     int idx, i;
194     int ddp_endp_params_data[2*DDP_ENDP_NUM_PARAMS + 1];
195     int length = 0;
196     for(idx=0; idx<DDP_ENDP_NUM_DEVICES; idx++) {
197         if(ddp_endp_params[idx].device & device) {
198             if(ddp_endp_params[idx].dev_ch_cap == dev_ch_cap) {
199                 break;
200             }
201         }
202     }
203     if(idx>=DDP_ENDP_NUM_DEVICES) {
204         ALOGE("device not available in DDP endp config table");
205         return;
206     }
207 
208     length += 1; /* offset 0 is for num of parameter. increase offset by 1 */
209     for (i=0; i<DDP_ENDP_NUM_PARAMS; i++) {
210         if(ddp_endp_params[idx].is_param_valid[i]) {
211             ddp_endp_params_data[length++] = ddp_endp_params_id[i];
212             ddp_endp_params_data[length++] = ddp_endp_params[idx].param_val[i];
213         }
214     }
215     ddp_endp_params_data[0] = (length-1)/2;
216     if(length) {
217         char mixer_ctl_name[128];
218         struct audio_device *adev = out->dev;
219         struct mixer_ctl *ctl;
220         int pcm_device_id = platform_get_pcm_device_id(out->usecase,
221                                                        PCM_PLAYBACK);
222         snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
223                  "Audio Stream %d Dec Params", pcm_device_id);
224         ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
225         if (!ctl) {
226             ALOGE("%s: Could not get ctl for mixer cmd - %s",
227                   __func__, mixer_ctl_name);
228             return;
229         }
230         mixer_ctl_set_array(ctl, ddp_endp_params_data, length);
231     }
232     return;
233 }
234 
send_ddp_endp_params(struct audio_device * adev,int ddp_dev,int dev_ch_cap)235 void send_ddp_endp_params(struct audio_device *adev,
236                           int ddp_dev, int dev_ch_cap)
237 {
238     struct listnode *node;
239     struct audio_usecase *usecase;
240 
241     list_for_each(node, &adev->usecase_list) {
242         usecase = node_to_item(node, struct audio_usecase, list);
243         if ((usecase->type == PCM_PLAYBACK) &&
244             (usecase->devices & ddp_dev) &&
245             (usecase->stream.out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
246             ((usecase->stream.out->format == AUDIO_FORMAT_AC3) ||
247              (usecase->stream.out->format == AUDIO_FORMAT_E_AC3) ||
248              (usecase->stream.out->format == AUDIO_FORMAT_E_AC3_JOC))) {
249             send_ddp_endp_params_stream(usecase->stream.out, ddp_dev,
250                                         dev_ch_cap, false /* set cache */);
251         }
252     }
253 }
254 
audio_extn_dolby_send_ddp_endp_params(struct audio_device * adev)255 void audio_extn_dolby_send_ddp_endp_params(struct audio_device *adev)
256 {
257     struct listnode *node;
258     struct audio_usecase *usecase;
259     list_for_each(node, &adev->usecase_list) {
260         usecase = node_to_item(node, struct audio_usecase, list);
261         if ((usecase->type == PCM_PLAYBACK) &&
262             (usecase->devices & AUDIO_DEVICE_OUT_ALL) &&
263             (usecase->stream.out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
264             ((usecase->stream.out->format == AUDIO_FORMAT_AC3) ||
265              (usecase->stream.out->format == AUDIO_FORMAT_E_AC3) ||
266              (usecase->stream.out->format == AUDIO_FORMAT_E_AC3_JOC))) {
267             /*
268              * Use wfd /hdmi sink channel cap for dolby params if device is wfd
269              * or hdmi. Otherwise use stereo configuration
270              */
271             int channel_cap = usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL ?
272                               adev->cur_hdmi_channels :
273                               usecase->devices & AUDIO_DEVICE_OUT_PROXY ?
274                               adev->cur_wfd_channels : 2;
275             send_ddp_endp_params_stream(usecase->stream.out, usecase->devices,
276                                         channel_cap, false /* set cache */);
277         }
278     }
279 }
280 
audio_extn_ddp_set_parameters(struct audio_device * adev,struct str_parms * parms)281 void audio_extn_ddp_set_parameters(struct audio_device *adev,
282                                    struct str_parms *parms)
283 {
284     int ddp_dev, dev_ch_cap;
285     int val, ret;
286     char value[32]={0};
287 
288     ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_SND_CARD_STATUS, value,
289                             sizeof(value));
290     if (ret >= 0) {
291         char *snd_card_status = value + 2;
292         if (strncmp(snd_card_status, "ONLINE", sizeof("ONLINE")) == 0)
293             audio_extn_dolby_set_license(adev);
294     }
295 
296     ret = str_parms_get_str(parms, AUDIO_PARAMETER_DDP_DEV, value,
297                             sizeof(value));
298     if (ret >= 0) {
299         ddp_dev = atoi(value);
300         if (!(AUDIO_DEVICE_OUT_ALL & ddp_dev))
301             return;
302     } else
303         return;
304 
305     ret = str_parms_get_str(parms, AUDIO_PARAMETER_DDP_CH_CAP, value,
306                             sizeof(value));
307     if (ret >= 0) {
308         dev_ch_cap = atoi(value);
309         if ((dev_ch_cap != 2) && (dev_ch_cap != 6) && (dev_ch_cap != 8))
310             return;
311     } else
312         return;
313 
314     ret = str_parms_get_str(parms, AUDIO_PARAMETER_DDP_MAX_OUT_CHAN, value,
315                             sizeof(value));
316     if (ret >= 0) {
317         val = atoi(value);
318         update_ddp_endp_table(ddp_dev, dev_ch_cap,
319                               PARAM_ID_MAX_OUTPUT_CHANNELS, val);
320     }
321 
322     ret = str_parms_get_str(parms, AUDIO_PARAMETER_DDP_OUT_MODE, value,
323                             sizeof(value));
324     if (ret >= 0) {
325         val = atoi(value);
326         update_ddp_endp_table(ddp_dev, dev_ch_cap,
327                               PARAM_ID_OUT_CTL_OUTMODE, val);
328     }
329 
330     ret = str_parms_get_str(parms, AUDIO_PARAMETER_DDP_OUT_LFE_ON, value,
331                             sizeof(value));
332     if (ret >= 0) {
333         val = atoi(value);
334         update_ddp_endp_table(ddp_dev, dev_ch_cap,
335                               PARAM_ID_OUT_CTL_OUTLFE_ON, val);
336     }
337 
338     ret = str_parms_get_str(parms, AUDIO_PARAMETER_DDP_COMP_MODE, value,
339                             sizeof(value));
340     if (ret >= 0) {
341         val = atoi(value);
342         update_ddp_endp_table(ddp_dev, dev_ch_cap,
343                               PARAM_ID_OUT_CTL_COMPMODE, val);
344     }
345 
346     ret = str_parms_get_str(parms, AUDIO_PARAMETER_DDP_STEREO_MODE, value,
347                             sizeof(value));
348     if (ret >= 0) {
349         val = atoi(value);
350         update_ddp_endp_table(ddp_dev, dev_ch_cap,
351                               PARAM_ID_OUT_CTL_STEREO_MODE, val);
352     }
353     /* TODO: Do we need device channel caps here?
354      * We dont have that information as this is from dolby modules
355      */
356     send_ddp_endp_params(adev, ddp_dev, dev_ch_cap);
357 }
358 #endif /* DS1_DOLBY_DDP_ENABLED */
359 
360 #if defined(DS1_DOLBY_DDP_ENABLED) || defined(DS2_DOLBY_DAP_ENABLED)
audio_extn_dolby_get_snd_codec_id(struct audio_device * adev,struct stream_out * out,audio_format_t format)361 int audio_extn_dolby_get_snd_codec_id(struct audio_device *adev,
362                                       struct stream_out *out,
363                                       audio_format_t format)
364 {
365     int id = 0;
366     /*
367      * Use wfd /hdmi sink channel cap for dolby params if device is wfd
368      * or hdmi. Otherwise use stereo configuration
369      */
370     int channel_cap = out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL ?
371                       adev->cur_hdmi_channels :
372                       out->devices & AUDIO_DEVICE_OUT_PROXY ?
373                       adev->cur_wfd_channels : 2;
374 
375     switch (format) {
376     case AUDIO_FORMAT_AC3:
377         id = SND_AUDIOCODEC_AC3;
378 #ifdef DS1_DOLBY_DDP_ENABLED
379         send_ddp_endp_params_stream(out, out->devices,
380                             channel_cap, true /* set_cache */);
381 #endif
382         audio_extn_dolby_set_dmid(adev);
383         break;
384     case AUDIO_FORMAT_E_AC3:
385     case AUDIO_FORMAT_E_AC3_JOC:
386         id = SND_AUDIOCODEC_EAC3;
387 #ifdef DS1_DOLBY_DDP_ENABLED
388         send_ddp_endp_params_stream(out, out->devices,
389                             channel_cap, true /* set_cache */);
390 #endif
391         audio_extn_dolby_set_dmid(adev);
392         break;
393     default:
394         ALOGE("%s: Unsupported audio format :%x", __func__, format);
395     }
396 
397     return id;
398 }
399 
audio_extn_is_dolby_format(audio_format_t format)400 bool audio_extn_is_dolby_format(audio_format_t format)
401 {
402     if (format == AUDIO_FORMAT_AC3 ||
403             format == AUDIO_FORMAT_E_AC3 ||
404             format == AUDIO_FORMAT_E_AC3_JOC)
405         return true;
406     else
407         return false;
408 }
409 #endif /* DS1_DOLBY_DDP_ENABLED || DS2_DOLBY_DAP_ENABLED */
410 
411 #ifdef DS1_DOLBY_DAP_ENABLED
audio_extn_dolby_set_endpoint(struct audio_device * adev)412 void audio_extn_dolby_set_endpoint(struct audio_device *adev)
413 {
414     struct listnode *node;
415     struct audio_usecase *usecase;
416     struct mixer_ctl *ctl;
417     const char *mixer_ctl_name = "DS1 DAP Endpoint";
418     int endpoint = 0, ret;
419     bool send = false;
420 
421     list_for_each(node, &adev->usecase_list) {
422         usecase = node_to_item(node, struct audio_usecase, list);
423         if ((usecase->type == PCM_PLAYBACK) &&
424             (usecase->id != USECASE_AUDIO_PLAYBACK_LOW_LATENCY)) {
425             endpoint |= usecase->devices & AUDIO_DEVICE_OUT_ALL;
426             send = true;
427         }
428     }
429     if (!send)
430         return;
431 
432     ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
433     if (!ctl) {
434         ALOGE("%s: Could not get ctl for mixer cmd - %s",
435               __func__, mixer_ctl_name);
436         return;
437     }
438     ret = mixer_ctl_set_value(ctl, 0, endpoint);
439     if (ret)
440         ALOGE("%s: Dolby set endpint cannot be set error:%d",__func__, ret);
441 
442     return;
443 }
444 #endif /* DS1_DOLBY_DAP_ENABLED */
445 
446 
447 #if defined(DS1_DOLBY_DDP_ENABLED) || defined(DS1_DOLBY_DAP_ENABLED)
audio_extn_dolby_set_dmid(struct audio_device * adev)448 void audio_extn_dolby_set_dmid(struct audio_device *adev)
449 {
450     struct listnode *node;
451     struct audio_usecase *usecase;
452     struct mixer_ctl *ctl;
453     const char *mixer_ctl_name = "DS1 Security";
454     char c_dmid[128] = {0};
455     int i_dmid, ret;
456     bool send = false;
457 
458     list_for_each(node, &adev->usecase_list) {
459         usecase = node_to_item(node, struct audio_usecase, list);
460         if (usecase->type == PCM_PLAYBACK)
461             send = true;
462     }
463     if (!send)
464         return;
465 
466     property_get("dmid",c_dmid,"0");
467     i_dmid = atoll(c_dmid);
468 
469     ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
470     if (!ctl) {
471         ALOGE("%s: Could not get ctl for mixer cmd - %s",
472               __func__, mixer_ctl_name);
473         return;
474     }
475     ALOGV("%s Dolby device manufacturer id is:%d",__func__,i_dmid);
476     ret = mixer_ctl_set_value(ctl, 0, i_dmid);
477     if (ret)
478         ALOGE("%s: Dolby DMID cannot be set error:%d",__func__, ret);
479 
480     return;
481 }
482 
483 #ifndef DS2_DOLBY_DAP_ENABLED
audio_extn_dolby_set_license(struct audio_device * adev)484 void audio_extn_dolby_set_license(struct audio_device *adev)
485 {
486     int ret, key=0;
487     char value[128] = {0};
488     struct mixer_ctl *ctl;
489     const char *mixer_ctl_name = "DS1 License";
490 
491     ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
492     if (!ctl) {
493         ALOGE("%s: Could not get ctl for mixer cmd - %s",
494               __func__, mixer_ctl_name);
495         return;
496     }
497 
498     property_get("audio.ds1.metainfo.key",value,"0");
499 #ifdef DOLBY_ACDB_LICENSE
500     key = atoi(value);
501 #else
502     key = 0;
503 #endif
504     ALOGV("%s Setting DS1 License, key:0x%x",__func__, key);
505     ret = mixer_ctl_set_value(ctl, 0, key);
506     if (ret)
507         ALOGE("%s: cannot set license, error:%d",__func__, ret);
508 
509     return;
510 }
511 #endif
512 #endif /* DS1_DOLBY_DDP_ENABLED || DS1_DOLBY_DAP_ENABLED */
513 
514 #ifdef DS2_DOLBY_DAP_ENABLED
515 struct ds2_extn_module  {
516    void *ds2_handle;
517    dap_hal_set_hw_info_t dap_hal_set_hw_info;
518 };
519 
520 static struct ds2_extn_module ds2extnmod = {
521     .ds2_handle = NULL,
522     .dap_hal_set_hw_info = NULL,
523 };
524 
audio_extn_dap_hal_init(int snd_card)525 int audio_extn_dap_hal_init(int snd_card) {
526     char c_dmid[128] = {0};
527     void *handle = NULL;
528     int i_dmid, ret = -EINVAL;
529     dap_hal_device_be_id_map_t device_be_id_map;
530 
531     ALOGV("%s: opening DAP HAL lib\n", __func__);
532     ds2extnmod.ds2_handle = dlopen(LIB_DS2_DAP_HAL, RTLD_NOW);
533     if (ds2extnmod.ds2_handle == NULL) {
534         ALOGE("%s: DLOPEN failed for %s error %s", __func__, LIB_DS2_DAP_HAL,
535               dlerror());
536         goto ret;
537     }
538     ds2extnmod.dap_hal_set_hw_info = (dap_hal_set_hw_info_t)dlsym(ds2extnmod.ds2_handle, SET_HW_INFO_FUNC);
539     if (ds2extnmod.dap_hal_set_hw_info == NULL) {
540            ALOGE("%s: dlsym error %s for %s", __func__, SET_HW_INFO_FUNC,
541                  dlerror());
542            goto close;
543     }
544     ds2extnmod.dap_hal_set_hw_info(SND_CARD, (void*)(&snd_card));
545     ALOGV("%s Sound card number is:%d",__func__,snd_card);
546 
547     platform_get_device_to_be_id_map(&device_be_id_map.device_id_to_be_id, &device_be_id_map.len);
548     ds2extnmod.dap_hal_set_hw_info(DEVICE_BE_ID_MAP, (void*)(&device_be_id_map));
549     ALOGV("%s Set be id map len:%d",__func__,device_be_id_map.len);
550     ret = 0;
551     goto ret;
552 
553 close:
554     dlclose(ds2extnmod.ds2_handle);
555     ds2extnmod.ds2_handle = NULL;
556     ds2extnmod.dap_hal_set_hw_info = NULL;
557 ret:
558     return ret;
559 }
560 
audio_extn_dap_hal_deinit()561 int audio_extn_dap_hal_deinit() {
562     if (ds2extnmod.ds2_handle != NULL) {
563        dlclose(ds2extnmod.ds2_handle);
564        ds2extnmod.ds2_handle = NULL;
565     }
566     ds2extnmod.dap_hal_set_hw_info = NULL;
567     return 0;
568 }
569 
audio_extn_dolby_ds2_set_endpoint(struct audio_device * adev)570 void audio_extn_dolby_ds2_set_endpoint(struct audio_device *adev) {
571     struct listnode *node;
572     struct audio_usecase *usecase;
573     struct mixer_ctl *ctl;
574     const char *mixer_ctl_name = "DS1 DAP Endpoint";
575     int endpoint = 0, ret;
576     bool send = false;
577 
578     list_for_each(node, &adev->usecase_list) {
579         usecase = node_to_item(node, struct audio_usecase, list);
580         if ((usecase->type == PCM_PLAYBACK) &&
581             (usecase->id != USECASE_AUDIO_PLAYBACK_LOW_LATENCY)) {
582             endpoint |= usecase->devices & AUDIO_DEVICE_OUT_ALL;
583             send = true;
584         }
585     }
586     if (!send)
587         return;
588 
589     if (ds2extnmod.dap_hal_set_hw_info) {
590         ds2extnmod.dap_hal_set_hw_info(HW_ENDPOINT, (void*)(&endpoint));
591         ALOGE("%s: Dolby set endpint :0x%x",__func__, endpoint);
592     } else {
593         ALOGE("%s: dap_hal_set_hw_info is NULL",__func__);
594     }
595 
596     return;
597 }
598 
audio_extn_ds2_enable(struct audio_device * adev)599 int audio_extn_ds2_enable(struct audio_device *adev) {
600 
601     char value[PROPERTY_VALUE_MAX] = {0};
602     bool ds2_enabled = false;
603     const char *mixer_ctl_name = "DS2 OnOff";
604     struct mixer_ctl *ctl;
605 
606     property_get("audio.dolby.ds2.enabled", value, NULL);
607     ds2_enabled = atoi(value) || !strncmp("true", value, 4);
608 
609     ALOGV("%s:", __func__);
610     if(ds2_enabled) {
611         ALOGD("%s:ds2_enabled %d", __func__, ds2_enabled);
612         ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
613         if (!ctl) {
614             ALOGE("%s: Could not get ctl for mixer cmd - %s",
615                                    __func__, mixer_ctl_name);
616             return -EINVAL;
617         }
618 
619         if (mixer_ctl_set_value(ctl, 0, ds2_enabled) < 0) {
620             ALOGE("%s: Could not set ds2 enable %d",
621                             __func__, ds2_enabled);
622             return -EINVAL;
623         }
624     }
625     return 0;
626 }
627 
audio_extn_dolby_set_dap_bypass(struct audio_device * adev,int state)628 int audio_extn_dolby_set_dap_bypass(struct audio_device *adev, int state) {
629 
630     ALOGV("%s: state %d", __func__, state);
631     if (ds2extnmod.dap_hal_set_hw_info) {
632         ds2extnmod.dap_hal_set_hw_info(DAP_BYPASS, (void*)(&state));
633         ALOGV("%s: Dolby set bypas :0x%x", __func__, state);
634     } else {
635         ALOGV("%s: dap_hal_set_hw_info is NULL", __func__);
636     }
637     return 0;
638 }
639 
audio_extn_dolby_set_license(struct audio_device * adev)640 void audio_extn_dolby_set_license(struct audio_device *adev)
641 {
642     int i_key=0;
643     char c_key[128] = {0};
644     char c_dmid[128] = {0};
645     int i_dmid, ret = -EINVAL;
646     struct dolby_param_license dolby_license;
647 
648 #ifdef DOLBY_ACDB_LICENSE
649     property_get("audio.ds1.metainfo.key",c_key,"0");
650     i_key = atoi(c_key);
651 #else
652     /* As ACDB based license mechanism is disabled, force set the license key to 0*/
653     i_key = 0;
654 #endif
655     property_get("dmid",c_dmid,"0");
656     i_dmid = atoll(c_dmid);
657     ALOGV("%s Setting DS1 License, key:0x%x dmid %d",__func__, i_key,i_dmid);
658     dolby_license.dmid = i_dmid;
659     dolby_license.license_key = i_key;
660     if (ds2extnmod.dap_hal_set_hw_info) {
661         ds2extnmod.dap_hal_set_hw_info(DMID, (void*)(&dolby_license.dmid));
662     } else {
663         ALOGV("%s: dap_hal_set_hw_info is NULL", __func__);
664         return ret;
665     }
666     return 0;
667 }
668 
669 
audio_extn_ds2_set_parameters(struct audio_device * adev,struct str_parms * parms)670 void audio_extn_ds2_set_parameters(struct audio_device *adev,
671                                    struct str_parms *parms)
672 {
673     int val, ret;
674     char value[32]={0};
675 
676     ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_SND_CARD_STATUS, value,
677                             sizeof(value));
678     if (ret >= 0) {
679         char *snd_card_status = value + 2;
680         if (strncmp(snd_card_status, "ONLINE", sizeof("ONLINE")) == 0){
681             audio_extn_dolby_set_license(adev);
682         }
683     }
684 }
685 #endif
686