blob: bd39f0bee48ecdc4bf140250c44e0ddb8e85c54c [file] [log] [blame]
Yamit Mehtae3b99562016-09-16 22:44:00 +05301/*
2 * Copyright (C) 2016 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_utils"
18//#define LOG_NDEBUG 0
19
20#include <errno.h>
21#include <cutils/properties.h>
22#include <cutils/config_utils.h>
23#include <stdlib.h>
24#include <dlfcn.h>
25#include <cutils/str_parms.h>
26#include <cutils/log.h>
27#include <cutils/misc.h>
28
vivek mehta0fb11312017-05-15 19:35:32 -070029#include "acdb.h"
Yamit Mehtae3b99562016-09-16 22:44:00 +053030#include "audio_hw.h"
31#include "platform.h"
32#include "platform_api.h"
33#include "audio_extn.h"
34
35#define MAX_LENGTH_MIXER_CONTROL_IN_INT 128
36
vivek mehtaa68fea62017-06-08 19:04:02 -070037static int set_stream_app_type_mixer_ctrl(struct audio_device *adev,
38 int pcm_device_id, int app_type,
39 int acdb_dev_id, int sample_rate,
40 int stream_type,
41 snd_device_t snd_device)
Yamit Mehtae3b99562016-09-16 22:44:00 +053042{
43
44 char mixer_ctl_name[MAX_LENGTH_MIXER_CONTROL_IN_INT];
45 struct mixer_ctl *ctl;
46 int app_type_cfg[MAX_LENGTH_MIXER_CONTROL_IN_INT], len = 0, rc = 0;
vivek mehtaa68fea62017-06-08 19:04:02 -070047 int snd_device_be_idx = -1;
Yamit Mehtae3b99562016-09-16 22:44:00 +053048
49 if (stream_type == PCM_PLAYBACK) {
50 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
51 "Audio Stream %d App Type Cfg", pcm_device_id);
52 } else if (stream_type == PCM_CAPTURE) {
53 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
54 "Audio Stream Capture %d App Type Cfg", pcm_device_id);
55 }
56
57 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
58 if (!ctl) {
59 ALOGE("%s: Could not get ctl for mixer cmd - %s",
60 __func__, mixer_ctl_name);
61 rc = -EINVAL;
62 goto exit;
63 }
64 app_type_cfg[len++] = app_type;
65 app_type_cfg[len++] = acdb_dev_id;
66 app_type_cfg[len++] = sample_rate;
vivek mehtaa68fea62017-06-08 19:04:02 -070067
68 snd_device_be_idx = platform_get_snd_device_backend_index(snd_device);
69 if (snd_device_be_idx > 0)
70 app_type_cfg[len++] = snd_device_be_idx;
71 ALOGV("%s: stream type %d app_type %d, acdb_dev_id %d "
72 "sample rate %d, snd_device_be_idx %d",
73 __func__, stream_type, app_type, acdb_dev_id, sample_rate,
74 snd_device_be_idx);
Yamit Mehtae3b99562016-09-16 22:44:00 +053075 mixer_ctl_set_array(ctl, app_type_cfg, len);
76
77exit:
78 return rc;
79}
80
81void audio_extn_utils_send_default_app_type_cfg(void *platform, struct mixer *mixer)
82{
83 int app_type_cfg[MAX_LENGTH_MIXER_CONTROL_IN_INT] = {-1};
84 int length = 0, app_type = 0,rc = 0;
85 struct mixer_ctl *ctl = NULL;
86 const char *mixer_ctl_name = "App Type Config";
87
88 ctl = mixer_get_ctl_by_name(mixer, mixer_ctl_name);
89 if (!ctl) {
90 ALOGE("%s: Could not get ctl for mixer cmd - %s",__func__, mixer_ctl_name);
91 return;
92 }
93 rc = platform_get_default_app_type_v2(platform, PCM_PLAYBACK, &app_type);
94 if (rc == 0) {
95 app_type_cfg[length++] = 1;
96 app_type_cfg[length++] = app_type;
97 app_type_cfg[length++] = 48000;
98 app_type_cfg[length++] = 16;
99 mixer_ctl_set_array(ctl, app_type_cfg, length);
100 }
101 return;
102}
103
vivek mehtaa68fea62017-06-08 19:04:02 -0700104static const char *flags_to_mode(int dir, uint32_t flags)
105{
106 if (dir == 0) {
107 if (flags & AUDIO_OUTPUT_FLAG_VOIP_RX) {
108 return "voip";
109 }
110 } else if (dir == 1) {
111 if (flags & AUDIO_INPUT_FLAG_VOIP_TX) {
112 return "voip";
113 }
114 }
115 return "default";
116}
117
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -0800118static int audio_extn_utils_send_app_type_cfg_hfp(struct audio_device *adev,
Yamit Mehtae3b99562016-09-16 22:44:00 +0530119 struct audio_usecase *usecase)
120{
121 struct mixer_ctl *ctl;
122 int pcm_device_id, acdb_dev_id = 0, snd_device = usecase->out_snd_device;
123 int32_t sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
124 int app_type = 0, rc = 0;
125
126 ALOGV("%s", __func__);
127
128 if (usecase->type != PCM_HFP_CALL) {
129 ALOGV("%s: not a playback or HFP path, no need to cfg app type", __func__);
130 rc = 0;
131 goto exit_send_app_type_cfg;
132 }
133 if ((usecase->id != USECASE_AUDIO_HFP_SCO) &&
134 (usecase->id != USECASE_AUDIO_HFP_SCO_WB)) {
135 ALOGV("%s: a playback path where app type cfg is not required", __func__);
136 rc = 0;
137 goto exit_send_app_type_cfg;
138 }
139
140 snd_device = usecase->out_snd_device;
141 pcm_device_id = platform_get_pcm_device_id(usecase->id, PCM_PLAYBACK);
142
143 snd_device = (snd_device == SND_DEVICE_OUT_SPEAKER) ?
144 audio_extn_get_spkr_prot_snd_device(snd_device) : snd_device;
145 acdb_dev_id = platform_get_snd_device_acdb_id(snd_device);
146 if (acdb_dev_id < 0) {
147 ALOGE("%s: Couldn't get the acdb dev id", __func__);
148 rc = -EINVAL;
149 goto exit_send_app_type_cfg;
150 }
151
152 if (usecase->type == PCM_HFP_CALL) {
153
154 /* config HFP session:1 playback path */
155 rc = platform_get_default_app_type_v2(adev->platform, PCM_PLAYBACK, &app_type);
156 if (rc < 0)
157 goto exit_send_app_type_cfg;
158
159 sample_rate= CODEC_BACKEND_DEFAULT_SAMPLE_RATE;
vivek mehtaa68fea62017-06-08 19:04:02 -0700160 rc = set_stream_app_type_mixer_ctrl(adev, pcm_device_id, app_type,
161 acdb_dev_id, sample_rate,
162 PCM_PLAYBACK,
163 SND_DEVICE_NONE); // use legacy behavior
Yamit Mehtae3b99562016-09-16 22:44:00 +0530164 if (rc < 0)
165 goto exit_send_app_type_cfg;
166 /* config HFP session:1 capture path */
167 rc = platform_get_default_app_type_v2(adev->platform, PCM_CAPTURE, &app_type);
168
169 if (rc == 0) {
vivek mehtaa68fea62017-06-08 19:04:02 -0700170 rc = set_stream_app_type_mixer_ctrl(adev, pcm_device_id, app_type,
171 acdb_dev_id, sample_rate,
172 PCM_CAPTURE,
173 SND_DEVICE_NONE);
Yamit Mehtae3b99562016-09-16 22:44:00 +0530174 if (rc < 0)
175 goto exit_send_app_type_cfg;
176 }
177 /* config HFP session:2 capture path */
178 pcm_device_id = HFP_ASM_RX_TX;
179 snd_device = usecase->in_snd_device;
180 acdb_dev_id = platform_get_snd_device_acdb_id(snd_device);
181 if (acdb_dev_id <= 0) {
182 ALOGE("%s: Couldn't get the acdb dev id", __func__);
183 rc = -EINVAL;
184 goto exit_send_app_type_cfg;
185 }
186 rc = platform_get_default_app_type_v2(adev->platform, PCM_CAPTURE, &app_type);
187 if (rc == 0) {
vivek mehtaa68fea62017-06-08 19:04:02 -0700188 rc = set_stream_app_type_mixer_ctrl(adev, pcm_device_id, app_type,
189 acdb_dev_id, sample_rate, PCM_CAPTURE,
190 SND_DEVICE_NONE);
Yamit Mehtae3b99562016-09-16 22:44:00 +0530191 if (rc < 0)
192 goto exit_send_app_type_cfg;
193 }
194
195 /* config HFP session:2 playback path */
196 rc = platform_get_default_app_type_v2(adev->platform, PCM_PLAYBACK, &app_type);
197 if (rc == 0) {
vivek mehtaa68fea62017-06-08 19:04:02 -0700198 rc = set_stream_app_type_mixer_ctrl(adev, pcm_device_id, app_type,
199 acdb_dev_id, sample_rate,
200 PCM_PLAYBACK, SND_DEVICE_NONE);
Yamit Mehtae3b99562016-09-16 22:44:00 +0530201 if (rc < 0)
202 goto exit_send_app_type_cfg;
203 }
204 }
205
206 rc = 0;
207exit_send_app_type_cfg:
208 return rc;
209}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -0800210
vivek mehtaa68fea62017-06-08 19:04:02 -0700211
212static int derive_capture_app_type_cfg(struct audio_device *adev,
213 struct audio_usecase *usecase,
214 int *app_type,
215 int *sample_rate)
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -0800216{
Mark Urbanus2e259972017-06-15 16:50:53 -0700217 if (usecase->stream.in == NULL) {
218 return -1;
219 }
vivek mehtaa68fea62017-06-08 19:04:02 -0700220 struct stream_in *in = usecase->stream.in;
221 struct stream_app_type_cfg *app_type_cfg = &in->app_type_cfg;
222
223 *sample_rate = DEFAULT_INPUT_SAMPLING_RATE;
vivek mehta4a824772017-06-08 19:05:49 -0700224 if (audio_is_usb_in_device(in->device)) {
vivek mehtaa68fea62017-06-08 19:04:02 -0700225 platform_check_and_update_copp_sample_rate(adev->platform,
226 usecase->in_snd_device,
227 in->sample_rate,
228 sample_rate);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -0800229 }
230
vivek mehtaa68fea62017-06-08 19:04:02 -0700231 app_type_cfg->mode = flags_to_mode(1 /*capture*/, in->flags);
232 ALOGV("%s mode %s", __func__, app_type_cfg->mode);
233 if (in->format == AUDIO_FORMAT_PCM_16_BIT) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -0800234 platform_get_app_type_v2(adev->platform,
vivek mehtaa68fea62017-06-08 19:04:02 -0700235 PCM_CAPTURE,
236 app_type_cfg->mode,
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -0800237 16,
vivek mehtaa68fea62017-06-08 19:04:02 -0700238 app_type_cfg->sample_rate,
239 app_type);
240 } else if (in->format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
241 in->format == AUDIO_FORMAT_PCM_8_24_BIT) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -0800242 platform_get_app_type_v2(adev->platform,
vivek mehtaa68fea62017-06-08 19:04:02 -0700243 PCM_CAPTURE,
244 app_type_cfg->mode,
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -0800245 24,
vivek mehtaa68fea62017-06-08 19:04:02 -0700246 app_type_cfg->sample_rate,
247 app_type);
248 } else if (in->format == AUDIO_FORMAT_PCM_32_BIT) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -0800249 platform_get_app_type_v2(adev->platform,
vivek mehtaa68fea62017-06-08 19:04:02 -0700250 PCM_CAPTURE,
251 app_type_cfg->mode,
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -0800252 32,
vivek mehtaa68fea62017-06-08 19:04:02 -0700253 app_type_cfg->sample_rate,
254 app_type);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -0800255 } else {
256 ALOGE("%s bad format\n", __func__);
257 return -1;
258 }
259
vivek mehtaa68fea62017-06-08 19:04:02 -0700260 app_type_cfg->app_type = *app_type;
261 app_type_cfg->sample_rate = *sample_rate;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -0800262 return 0;
263}
264
vivek mehtaa68fea62017-06-08 19:04:02 -0700265static int derive_playback_app_type_cfg(struct audio_device *adev,
266 struct audio_usecase *usecase,
267 int *app_type,
268 int *sample_rate)
269{
Mark Urbanus2e259972017-06-15 16:50:53 -0700270 if (usecase->stream.out == NULL) {
271 return -1;
272 }
vivek mehtaa68fea62017-06-08 19:04:02 -0700273 struct stream_out *out = usecase->stream.out;
274 struct stream_app_type_cfg *app_type_cfg = &out->app_type_cfg;
275
276 *sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
277
278 // add speaker prot changes if needed
279 // and use that to check for device
vivek mehta4a824772017-06-08 19:05:49 -0700280 if (audio_is_usb_out_device(out->devices)) {
vivek mehtaa68fea62017-06-08 19:04:02 -0700281 platform_check_and_update_copp_sample_rate(adev->platform,
282 usecase->out_snd_device,
283 out->sample_rate,
284 sample_rate);
285 }
286
287 app_type_cfg->mode = flags_to_mode(0 /*playback*/, out->flags);
288 if (!audio_is_linear_pcm(out->format)) {
289 platform_get_default_app_type_v2(adev->platform,
290 PCM_PLAYBACK,
291 app_type);
292 } else if (out->format == AUDIO_FORMAT_PCM_16_BIT) {
293 platform_get_app_type_v2(adev->platform,
294 PCM_PLAYBACK,
295 app_type_cfg->mode,
296 16,
297 *sample_rate,
298 app_type);
299 } else if (out->format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
300 out->format == AUDIO_FORMAT_PCM_8_24_BIT) {
301 platform_get_app_type_v2(adev->platform,
302 PCM_PLAYBACK,
303 app_type_cfg->mode,
304 24,
305 *sample_rate,
306 app_type);
307 } else if (out->format == AUDIO_FORMAT_PCM_32_BIT) {
308 platform_get_app_type_v2(adev->platform,
309 PCM_PLAYBACK,
310 app_type_cfg->mode,
311 32,
312 *sample_rate,
313 app_type);
314 } else {
315 ALOGE("%s bad format\n", __func__);
316 return -1;
317 }
318
319 app_type_cfg->app_type = *app_type;
320 app_type_cfg->sample_rate = *sample_rate;
321 return 0;
322}
323
324static int derive_acdb_dev_id(struct audio_device *adev __unused,
325 struct audio_usecase *usecase)
326{
327 struct stream_out *out;
328 struct stream_in *in;
329
330 if (usecase->type == PCM_PLAYBACK) {
331 return platform_get_snd_device_acdb_id(usecase->out_snd_device);
332 } else if(usecase->type == PCM_CAPTURE) {
333 return platform_get_snd_device_acdb_id(usecase->in_snd_device);
334 }
335 return -1;
336}
337
338int audio_extn_utils_send_app_type_cfg(struct audio_device *adev,
339 struct audio_usecase *usecase)
340{
341 int len = 0;
342 int sample_rate;
343 int app_type;
344 int acdb_dev_id;
345 size_t app_type_cfg[MAX_LENGTH_MIXER_CONTROL_IN_INT] = {0};
346 char mixer_ctl_name[MAX_LENGTH_MIXER_CONTROL_IN_INT] = {0};
347 int pcm_device_id;
348 struct mixer_ctl *ctl;
349 int ret;
350
351 if (usecase->type == PCM_HFP_CALL) {
352 return audio_extn_utils_send_app_type_cfg_hfp(adev, usecase);
353 }
354
355 if (!platform_supports_app_type_cfg())
356 return -1;
357
358 if (usecase->type == PCM_PLAYBACK) {
359 ret = derive_playback_app_type_cfg(adev,
360 usecase,
361 &app_type,
362 &sample_rate);
363 } else if (usecase->type == PCM_CAPTURE) {
364 ret = derive_capture_app_type_cfg(adev,
365 usecase,
366 &app_type,
367 &sample_rate);
368 } else {
369 ALOGE("%s: Invalid uc type : 0x%x", __func__, usecase->type);
370 return -1;
371 }
372
373 if (ret < 0) {
374 ALOGE("%s: Failed to derive app_type for uc type : 0x%x", __func__,
375 usecase->type);
376 return -1;
377 }
378
379 acdb_dev_id = derive_acdb_dev_id(adev, usecase);
380 if (acdb_dev_id <= 0) {
381 ALOGE("%s: Couldn't get the acdb dev id", __func__);
382 return -1;
383 }
384
385 pcm_device_id = platform_get_pcm_device_id(usecase->id, usecase->type);
386 set_stream_app_type_mixer_ctrl(adev, pcm_device_id, app_type, acdb_dev_id,
387 sample_rate,
388 usecase->type,
389 usecase->type == PCM_PLAYBACK ? usecase->out_snd_device :
390 usecase->in_snd_device);
391 return 0;
392}
393
vivek mehta4a824772017-06-08 19:05:49 -0700394int audio_extn_utils_send_app_type_gain(struct audio_device *adev,
395 int app_type,
396 int *gain)
397{
398 int gain_cfg[4];
399 const char *mixer_ctl_name = "App Type Gain";
400 struct mixer_ctl *ctl;
401 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
402 if (!ctl) {
403 ALOGE("%s: Could not get volume ctl mixer %s", __func__,
404 mixer_ctl_name);
405 return -EINVAL;
406 }
407 gain_cfg[0] = 0;
408 gain_cfg[1] = app_type;
409 gain_cfg[2] = gain[0];
410 gain_cfg[3] = gain[1];
411 ALOGV("%s app_type %d l(%d) r(%d)", __func__, app_type, gain[0], gain[1]);
412 return mixer_ctl_set_array(ctl, gain_cfg,
413 sizeof(gain_cfg)/sizeof(gain_cfg[0]));
414}
415
vivek mehtaa68fea62017-06-08 19:04:02 -0700416// this assumes correct app_type and sample_rate fields
417// have been set for the stream using audio_extn_utils_send_app_type_cfg
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -0800418void audio_extn_utils_send_audio_calibration(struct audio_device *adev,
419 struct audio_usecase *usecase)
420{
421 int type = usecase->type;
422 int app_type = 0;
423
424 if (type == PCM_PLAYBACK && usecase->stream.out != NULL) {
425 struct stream_out *out = usecase->stream.out;
vivek mehtaa68fea62017-06-08 19:04:02 -0700426 ALOGV("%s send cal for app_type %d, rate %d", __func__,
427 out->app_type_cfg.app_type,
428 out->app_type_cfg.sample_rate);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -0800429 platform_send_audio_calibration_v2(adev->platform, usecase,
vivek mehtaa68fea62017-06-08 19:04:02 -0700430 out->app_type_cfg.app_type,
431 out->app_type_cfg.sample_rate);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -0800432 } else if (type == PCM_CAPTURE && usecase->stream.in != NULL) {
vivek mehtaa68fea62017-06-08 19:04:02 -0700433 struct stream_in *in = usecase->stream.in;
434 ALOGV("%s send cal for capture app_type %d, rate %d", __func__,
435 in->app_type_cfg.app_type,
436 in->app_type_cfg.sample_rate);
437 platform_send_audio_calibration_v2(adev->platform, usecase,
438 in->app_type_cfg.app_type,
439 in->app_type_cfg.sample_rate);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -0800440 } else {
441 /* when app type is default. the sample rate is not used to send cal */
442 platform_get_default_app_type_v2(adev->platform, type, &app_type);
vivek mehtaa68fea62017-06-08 19:04:02 -0700443 platform_send_audio_calibration_v2(adev->platform, usecase, app_type,
444 48000);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -0800445 }
446}
vivek mehta0fb11312017-05-15 19:35:32 -0700447
448#define MAX_SND_CARD 8
449#define RETRY_US 500000
450#define RETRY_NUMBER 10
451
452#define min(a, b) ((a) < (b) ? (a) : (b))
453
454static const char *kConfigLocationList[] =
455 {"/odm/etc", "/vendor/etc", "/system/etc"};
456static const int kConfigLocationListSize =
457 (sizeof(kConfigLocationList) / sizeof(kConfigLocationList[0]));
458
459bool audio_extn_utils_resolve_config_file(char file_name[MIXER_PATH_MAX_LENGTH])
460{
461 char full_config_path[MIXER_PATH_MAX_LENGTH];
462 for (int i = 0; i < kConfigLocationListSize; i++) {
463 snprintf(full_config_path,
464 MIXER_PATH_MAX_LENGTH,
465 "%s/%s",
466 kConfigLocationList[i],
467 file_name);
468 if (F_OK == access(full_config_path, 0)) {
469 strcpy(file_name, full_config_path);
470 return true;
471 }
472 }
473 return false;
474}
475
476/* platform_info_file should be size 'MIXER_PATH_MAX_LENGTH' */
Haynes Mathew George66ff30c2017-06-01 20:24:42 -0700477int audio_extn_utils_get_platform_info(const char* snd_card_name, char* platform_info_file)
vivek mehta0fb11312017-05-15 19:35:32 -0700478{
479 if (NULL == snd_card_name) {
Haynes Mathew George66ff30c2017-06-01 20:24:42 -0700480 return -1;
vivek mehta0fb11312017-05-15 19:35:32 -0700481 }
482
483 struct snd_card_split *snd_split_handle = NULL;
Haynes Mathew George66ff30c2017-06-01 20:24:42 -0700484 int ret = 0;
vivek mehta0fb11312017-05-15 19:35:32 -0700485 audio_extn_set_snd_card_split(snd_card_name);
486 snd_split_handle = audio_extn_get_snd_card_split();
487
488 snprintf(platform_info_file, MIXER_PATH_MAX_LENGTH, "%s_%s_%s.xml",
489 PLATFORM_INFO_XML_BASE_STRING, snd_split_handle->snd_card,
490 snd_split_handle->form_factor);
491
492 if (!audio_extn_utils_resolve_config_file(platform_info_file)) {
493 memset(platform_info_file, 0, MIXER_PATH_MAX_LENGTH);
494 snprintf(platform_info_file, MIXER_PATH_MAX_LENGTH, "%s_%s.xml",
495 PLATFORM_INFO_XML_BASE_STRING, snd_split_handle->snd_card);
496
497 if (!audio_extn_utils_resolve_config_file(platform_info_file)) {
498 memset(platform_info_file, 0, MIXER_PATH_MAX_LENGTH);
499 strlcpy(platform_info_file, PLATFORM_INFO_XML_PATH, MIXER_PATH_MAX_LENGTH);
Haynes Mathew George66ff30c2017-06-01 20:24:42 -0700500 ret = audio_extn_utils_resolve_config_file(platform_info_file) ? 0 : -1;
vivek mehta0fb11312017-05-15 19:35:32 -0700501 }
502 }
Haynes Mathew George66ff30c2017-06-01 20:24:42 -0700503
504 return ret;
vivek mehta0fb11312017-05-15 19:35:32 -0700505}
506
507int audio_extn_utils_get_snd_card_num()
508{
509
510 void *hw_info = NULL;
511 struct mixer *mixer = NULL;
512 int retry_num = 0;
513 int snd_card_num = 0;
514 const char* snd_card_name = NULL;
515 char platform_info_file[MIXER_PATH_MAX_LENGTH]= {0};
516
517 struct acdb_platform_data *my_data = calloc(1, sizeof(struct acdb_platform_data));
518
519 bool card_verifed[MAX_SND_CARD] = {0};
520 const int retry_limit = property_get_int32("audio.snd_card.open.retries", RETRY_NUMBER);
521
522 for (;;) {
523 if (snd_card_num >= MAX_SND_CARD) {
524 if (retry_num++ >= retry_limit) {
525 ALOGE("%s: Unable to find correct sound card, aborting.", __func__);
526 snd_card_num = -1;
527 goto done;
528 }
529
530 snd_card_num = 0;
531 usleep(RETRY_US);
532 continue;
533 }
534
535 if (card_verifed[snd_card_num]) {
536 ++snd_card_num;
537 continue;
538 }
539
540 mixer = mixer_open(snd_card_num);
541
542 if (!mixer) {
543 ALOGE("%s: Unable to open the mixer card: %d", __func__,
544 snd_card_num);
545 ++snd_card_num;
546 continue;
547 }
548
549 card_verifed[snd_card_num] = true;
550
551 snd_card_name = mixer_get_name(mixer);
552 hw_info = hw_info_init(snd_card_name);
553
Haynes Mathew George66ff30c2017-06-01 20:24:42 -0700554 if (audio_extn_utils_get_platform_info(snd_card_name, platform_info_file) < 0) {
555 ALOGE("Failed to find platform_info_file");
556 goto cleanup;
557 }
vivek mehta0fb11312017-05-15 19:35:32 -0700558
559 /* Initialize snd card name specific ids and/or backends*/
Haynes Mathew George66ff30c2017-06-01 20:24:42 -0700560 if (snd_card_info_init(platform_info_file, my_data,
561 &acdb_set_parameters) < 0) {
562 ALOGE("Failed to find platform_info_file");
563 goto cleanup;
564 }
vivek mehta0fb11312017-05-15 19:35:32 -0700565
566 /* validate the sound card name
567 * my_data->snd_card_name can contain
568 * <a> complete sound card name, i.e. <device>-<codec>-<form_factor>-snd-card
569 * example: msm8994-tomtom-mtp-snd-card
570 * <b> or sub string of the card name, i.e. <device>-<codec>
571 * example: msm8994-tomtom
572 * snd_card_name is truncated to 32 charaters as per mixer_get_name() implementation
573 * so use min of my_data->snd_card_name and snd_card_name length for comparison
574 */
575
576 if (my_data->snd_card_name != NULL &&
577 strncmp(snd_card_name, my_data->snd_card_name,
578 min(strlen(snd_card_name), strlen(my_data->snd_card_name))) != 0) {
579 ALOGI("%s: found valid sound card %s, but not primary sound card %s",
580 __func__, snd_card_name, my_data->snd_card_name);
Haynes Mathew George66ff30c2017-06-01 20:24:42 -0700581 goto cleanup;
vivek mehta0fb11312017-05-15 19:35:32 -0700582 }
583
Haynes Mathew George66ff30c2017-06-01 20:24:42 -0700584 ALOGI("%s: found sound card %s, primary sound card expected is %s",
vivek mehta0fb11312017-05-15 19:35:32 -0700585 __func__, snd_card_name, my_data->snd_card_name);
586 break;
Haynes Mathew George66ff30c2017-06-01 20:24:42 -0700587 cleanup:
588 ++snd_card_num;
589 mixer_close(mixer);
590 mixer = NULL;
591 hw_info_deinit(hw_info);
592 hw_info = NULL;
vivek mehta0fb11312017-05-15 19:35:32 -0700593 }
594
595done:
596 mixer_close(mixer);
597 hw_info_deinit(hw_info);
598
599 if (my_data)
600 free(my_data);
601
602 return snd_card_num;
603}