blob: 7bf274ead2c8d8e37d5240dcfa7c3816c98402d3 [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>
Jiyong Park6431fe62017-06-29 15:15:58 +090025#include <unistd.h>
Yamit Mehtae3b99562016-09-16 22:44:00 +053026#include <cutils/str_parms.h>
Haynes Mathew Georgee6e2d442018-02-22 18:51:56 -080027#include <log/log.h>
Yamit Mehtae3b99562016-09-16 22:44:00 +053028#include <cutils/misc.h>
29
vivek mehta0fb11312017-05-15 19:35:32 -070030#include "acdb.h"
Yamit Mehtae3b99562016-09-16 22:44:00 +053031#include "audio_hw.h"
32#include "platform.h"
33#include "platform_api.h"
34#include "audio_extn.h"
35
36#define MAX_LENGTH_MIXER_CONTROL_IN_INT 128
37
vivek mehtaa68fea62017-06-08 19:04:02 -070038static int set_stream_app_type_mixer_ctrl(struct audio_device *adev,
39 int pcm_device_id, int app_type,
40 int acdb_dev_id, int sample_rate,
41 int stream_type,
42 snd_device_t snd_device)
Yamit Mehtae3b99562016-09-16 22:44:00 +053043{
44
45 char mixer_ctl_name[MAX_LENGTH_MIXER_CONTROL_IN_INT];
46 struct mixer_ctl *ctl;
47 int app_type_cfg[MAX_LENGTH_MIXER_CONTROL_IN_INT], len = 0, rc = 0;
vivek mehtaa68fea62017-06-08 19:04:02 -070048 int snd_device_be_idx = -1;
Yamit Mehtae3b99562016-09-16 22:44:00 +053049
50 if (stream_type == PCM_PLAYBACK) {
51 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
52 "Audio Stream %d App Type Cfg", pcm_device_id);
53 } else if (stream_type == PCM_CAPTURE) {
54 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
55 "Audio Stream Capture %d App Type Cfg", pcm_device_id);
56 }
57
58 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
59 if (!ctl) {
60 ALOGE("%s: Could not get ctl for mixer cmd - %s",
61 __func__, mixer_ctl_name);
62 rc = -EINVAL;
63 goto exit;
64 }
65 app_type_cfg[len++] = app_type;
66 app_type_cfg[len++] = acdb_dev_id;
67 app_type_cfg[len++] = sample_rate;
vivek mehtaa68fea62017-06-08 19:04:02 -070068
69 snd_device_be_idx = platform_get_snd_device_backend_index(snd_device);
70 if (snd_device_be_idx > 0)
71 app_type_cfg[len++] = snd_device_be_idx;
72 ALOGV("%s: stream type %d app_type %d, acdb_dev_id %d "
73 "sample rate %d, snd_device_be_idx %d",
74 __func__, stream_type, app_type, acdb_dev_id, sample_rate,
75 snd_device_be_idx);
Yamit Mehtae3b99562016-09-16 22:44:00 +053076 mixer_ctl_set_array(ctl, app_type_cfg, len);
77
78exit:
79 return rc;
80}
81
82void audio_extn_utils_send_default_app_type_cfg(void *platform, struct mixer *mixer)
83{
84 int app_type_cfg[MAX_LENGTH_MIXER_CONTROL_IN_INT] = {-1};
85 int length = 0, app_type = 0,rc = 0;
86 struct mixer_ctl *ctl = NULL;
87 const char *mixer_ctl_name = "App Type Config";
88
89 ctl = mixer_get_ctl_by_name(mixer, mixer_ctl_name);
90 if (!ctl) {
91 ALOGE("%s: Could not get ctl for mixer cmd - %s",__func__, mixer_ctl_name);
92 return;
93 }
94 rc = platform_get_default_app_type_v2(platform, PCM_PLAYBACK, &app_type);
95 if (rc == 0) {
96 app_type_cfg[length++] = 1;
97 app_type_cfg[length++] = app_type;
98 app_type_cfg[length++] = 48000;
99 app_type_cfg[length++] = 16;
100 mixer_ctl_set_array(ctl, app_type_cfg, length);
101 }
102 return;
103}
104
vivek mehtaa68fea62017-06-08 19:04:02 -0700105static const char *flags_to_mode(int dir, uint32_t flags)
106{
107 if (dir == 0) {
108 if (flags & AUDIO_OUTPUT_FLAG_VOIP_RX) {
109 return "voip";
110 }
111 } else if (dir == 1) {
112 if (flags & AUDIO_INPUT_FLAG_VOIP_TX) {
113 return "voip";
114 }
115 }
116 return "default";
117}
118
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -0800119static int audio_extn_utils_send_app_type_cfg_hfp(struct audio_device *adev,
Yamit Mehtae3b99562016-09-16 22:44:00 +0530120 struct audio_usecase *usecase)
121{
122 struct mixer_ctl *ctl;
123 int pcm_device_id, acdb_dev_id = 0, snd_device = usecase->out_snd_device;
124 int32_t sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
125 int app_type = 0, rc = 0;
126
127 ALOGV("%s", __func__);
128
129 if (usecase->type != PCM_HFP_CALL) {
130 ALOGV("%s: not a playback or HFP path, no need to cfg app type", __func__);
131 rc = 0;
132 goto exit_send_app_type_cfg;
133 }
134 if ((usecase->id != USECASE_AUDIO_HFP_SCO) &&
135 (usecase->id != USECASE_AUDIO_HFP_SCO_WB)) {
136 ALOGV("%s: a playback path where app type cfg is not required", __func__);
137 rc = 0;
138 goto exit_send_app_type_cfg;
139 }
140
141 snd_device = usecase->out_snd_device;
142 pcm_device_id = platform_get_pcm_device_id(usecase->id, PCM_PLAYBACK);
143
144 snd_device = (snd_device == SND_DEVICE_OUT_SPEAKER) ?
145 audio_extn_get_spkr_prot_snd_device(snd_device) : snd_device;
146 acdb_dev_id = platform_get_snd_device_acdb_id(snd_device);
147 if (acdb_dev_id < 0) {
148 ALOGE("%s: Couldn't get the acdb dev id", __func__);
149 rc = -EINVAL;
150 goto exit_send_app_type_cfg;
151 }
152
153 if (usecase->type == PCM_HFP_CALL) {
154
155 /* config HFP session:1 playback path */
156 rc = platform_get_default_app_type_v2(adev->platform, PCM_PLAYBACK, &app_type);
157 if (rc < 0)
158 goto exit_send_app_type_cfg;
159
160 sample_rate= CODEC_BACKEND_DEFAULT_SAMPLE_RATE;
vivek mehtaa68fea62017-06-08 19:04:02 -0700161 rc = set_stream_app_type_mixer_ctrl(adev, pcm_device_id, app_type,
162 acdb_dev_id, sample_rate,
163 PCM_PLAYBACK,
164 SND_DEVICE_NONE); // use legacy behavior
Yamit Mehtae3b99562016-09-16 22:44:00 +0530165 if (rc < 0)
166 goto exit_send_app_type_cfg;
167 /* config HFP session:1 capture path */
168 rc = platform_get_default_app_type_v2(adev->platform, PCM_CAPTURE, &app_type);
169
170 if (rc == 0) {
vivek mehtaa68fea62017-06-08 19:04:02 -0700171 rc = set_stream_app_type_mixer_ctrl(adev, pcm_device_id, app_type,
172 acdb_dev_id, sample_rate,
173 PCM_CAPTURE,
174 SND_DEVICE_NONE);
Yamit Mehtae3b99562016-09-16 22:44:00 +0530175 if (rc < 0)
176 goto exit_send_app_type_cfg;
177 }
178 /* config HFP session:2 capture path */
179 pcm_device_id = HFP_ASM_RX_TX;
180 snd_device = usecase->in_snd_device;
181 acdb_dev_id = platform_get_snd_device_acdb_id(snd_device);
182 if (acdb_dev_id <= 0) {
183 ALOGE("%s: Couldn't get the acdb dev id", __func__);
184 rc = -EINVAL;
185 goto exit_send_app_type_cfg;
186 }
187 rc = platform_get_default_app_type_v2(adev->platform, PCM_CAPTURE, &app_type);
188 if (rc == 0) {
vivek mehtaa68fea62017-06-08 19:04:02 -0700189 rc = set_stream_app_type_mixer_ctrl(adev, pcm_device_id, app_type,
190 acdb_dev_id, sample_rate, PCM_CAPTURE,
191 SND_DEVICE_NONE);
Yamit Mehtae3b99562016-09-16 22:44:00 +0530192 if (rc < 0)
193 goto exit_send_app_type_cfg;
194 }
195
196 /* config HFP session:2 playback path */
197 rc = platform_get_default_app_type_v2(adev->platform, PCM_PLAYBACK, &app_type);
198 if (rc == 0) {
vivek mehtaa68fea62017-06-08 19:04:02 -0700199 rc = set_stream_app_type_mixer_ctrl(adev, pcm_device_id, app_type,
200 acdb_dev_id, sample_rate,
201 PCM_PLAYBACK, SND_DEVICE_NONE);
Yamit Mehtae3b99562016-09-16 22:44:00 +0530202 if (rc < 0)
203 goto exit_send_app_type_cfg;
204 }
205 }
206
207 rc = 0;
208exit_send_app_type_cfg:
209 return rc;
210}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -0800211
vivek mehtaa68fea62017-06-08 19:04:02 -0700212
213static int derive_capture_app_type_cfg(struct audio_device *adev,
214 struct audio_usecase *usecase,
215 int *app_type,
216 int *sample_rate)
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -0800217{
Mark Urbanus2e259972017-06-15 16:50:53 -0700218 if (usecase->stream.in == NULL) {
219 return -1;
220 }
vivek mehtaa68fea62017-06-08 19:04:02 -0700221 struct stream_in *in = usecase->stream.in;
222 struct stream_app_type_cfg *app_type_cfg = &in->app_type_cfg;
223
224 *sample_rate = DEFAULT_INPUT_SAMPLING_RATE;
vivek mehta4a824772017-06-08 19:05:49 -0700225 if (audio_is_usb_in_device(in->device)) {
vivek mehtaa68fea62017-06-08 19:04:02 -0700226 platform_check_and_update_copp_sample_rate(adev->platform,
227 usecase->in_snd_device,
228 in->sample_rate,
229 sample_rate);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -0800230 }
231
vivek mehtaa68fea62017-06-08 19:04:02 -0700232 app_type_cfg->mode = flags_to_mode(1 /*capture*/, in->flags);
233 ALOGV("%s mode %s", __func__, app_type_cfg->mode);
234 if (in->format == AUDIO_FORMAT_PCM_16_BIT) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -0800235 platform_get_app_type_v2(adev->platform,
vivek mehtaa68fea62017-06-08 19:04:02 -0700236 PCM_CAPTURE,
237 app_type_cfg->mode,
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -0800238 16,
vivek mehtaa68fea62017-06-08 19:04:02 -0700239 app_type_cfg->sample_rate,
240 app_type);
241 } else if (in->format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
242 in->format == AUDIO_FORMAT_PCM_8_24_BIT) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -0800243 platform_get_app_type_v2(adev->platform,
vivek mehtaa68fea62017-06-08 19:04:02 -0700244 PCM_CAPTURE,
245 app_type_cfg->mode,
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -0800246 24,
vivek mehtaa68fea62017-06-08 19:04:02 -0700247 app_type_cfg->sample_rate,
248 app_type);
249 } else if (in->format == AUDIO_FORMAT_PCM_32_BIT) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -0800250 platform_get_app_type_v2(adev->platform,
vivek mehtaa68fea62017-06-08 19:04:02 -0700251 PCM_CAPTURE,
252 app_type_cfg->mode,
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -0800253 32,
vivek mehtaa68fea62017-06-08 19:04:02 -0700254 app_type_cfg->sample_rate,
255 app_type);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -0800256 } else {
257 ALOGE("%s bad format\n", __func__);
258 return -1;
259 }
260
vivek mehtaa68fea62017-06-08 19:04:02 -0700261 app_type_cfg->app_type = *app_type;
262 app_type_cfg->sample_rate = *sample_rate;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -0800263 return 0;
264}
265
vivek mehtaa68fea62017-06-08 19:04:02 -0700266static int derive_playback_app_type_cfg(struct audio_device *adev,
267 struct audio_usecase *usecase,
268 int *app_type,
269 int *sample_rate)
270{
Mark Urbanus2e259972017-06-15 16:50:53 -0700271 if (usecase->stream.out == NULL) {
272 return -1;
273 }
vivek mehtaa68fea62017-06-08 19:04:02 -0700274 struct stream_out *out = usecase->stream.out;
275 struct stream_app_type_cfg *app_type_cfg = &out->app_type_cfg;
276
277 *sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
278
279 // add speaker prot changes if needed
280 // and use that to check for device
vivek mehta4a824772017-06-08 19:05:49 -0700281 if (audio_is_usb_out_device(out->devices)) {
vivek mehtaa68fea62017-06-08 19:04:02 -0700282 platform_check_and_update_copp_sample_rate(adev->platform,
283 usecase->out_snd_device,
284 out->sample_rate,
285 sample_rate);
286 }
287
288 app_type_cfg->mode = flags_to_mode(0 /*playback*/, out->flags);
289 if (!audio_is_linear_pcm(out->format)) {
Haynes Mathew Georgedf0f8862017-06-28 13:36:40 -0700290 platform_get_app_type_v2(adev->platform,
291 PCM_PLAYBACK,
292 app_type_cfg->mode,
293 24,
294 *sample_rate,
295 app_type);
296 ALOGV("Non pcm got app type %d", *app_type);
vivek mehtaa68fea62017-06-08 19:04:02 -0700297 } else if (out->format == AUDIO_FORMAT_PCM_16_BIT) {
298 platform_get_app_type_v2(adev->platform,
299 PCM_PLAYBACK,
300 app_type_cfg->mode,
301 16,
302 *sample_rate,
303 app_type);
304 } else if (out->format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
305 out->format == AUDIO_FORMAT_PCM_8_24_BIT) {
306 platform_get_app_type_v2(adev->platform,
307 PCM_PLAYBACK,
308 app_type_cfg->mode,
309 24,
310 *sample_rate,
311 app_type);
312 } else if (out->format == AUDIO_FORMAT_PCM_32_BIT) {
313 platform_get_app_type_v2(adev->platform,
314 PCM_PLAYBACK,
315 app_type_cfg->mode,
316 32,
317 *sample_rate,
318 app_type);
319 } else {
320 ALOGE("%s bad format\n", __func__);
321 return -1;
322 }
323
324 app_type_cfg->app_type = *app_type;
325 app_type_cfg->sample_rate = *sample_rate;
326 return 0;
327}
328
329static int derive_acdb_dev_id(struct audio_device *adev __unused,
330 struct audio_usecase *usecase)
331{
332 struct stream_out *out;
333 struct stream_in *in;
334
335 if (usecase->type == PCM_PLAYBACK) {
carterhsue3e83ef2018-03-29 19:56:14 +0800336 return platform_get_snd_device_acdb_id(
337 audio_extn_get_spkr_prot_snd_device(usecase->out_snd_device));
vivek mehtaa68fea62017-06-08 19:04:02 -0700338 } else if(usecase->type == PCM_CAPTURE) {
339 return platform_get_snd_device_acdb_id(usecase->in_snd_device);
340 }
341 return -1;
342}
343
344int audio_extn_utils_send_app_type_cfg(struct audio_device *adev,
345 struct audio_usecase *usecase)
346{
347 int len = 0;
348 int sample_rate;
349 int app_type;
350 int acdb_dev_id;
351 size_t app_type_cfg[MAX_LENGTH_MIXER_CONTROL_IN_INT] = {0};
352 char mixer_ctl_name[MAX_LENGTH_MIXER_CONTROL_IN_INT] = {0};
353 int pcm_device_id;
354 struct mixer_ctl *ctl;
355 int ret;
356
357 if (usecase->type == PCM_HFP_CALL) {
358 return audio_extn_utils_send_app_type_cfg_hfp(adev, usecase);
359 }
360
361 if (!platform_supports_app_type_cfg())
362 return -1;
363
364 if (usecase->type == PCM_PLAYBACK) {
365 ret = derive_playback_app_type_cfg(adev,
366 usecase,
367 &app_type,
368 &sample_rate);
369 } else if (usecase->type == PCM_CAPTURE) {
370 ret = derive_capture_app_type_cfg(adev,
371 usecase,
372 &app_type,
373 &sample_rate);
374 } else {
375 ALOGE("%s: Invalid uc type : 0x%x", __func__, usecase->type);
376 return -1;
377 }
378
379 if (ret < 0) {
380 ALOGE("%s: Failed to derive app_type for uc type : 0x%x", __func__,
381 usecase->type);
382 return -1;
383 }
384
385 acdb_dev_id = derive_acdb_dev_id(adev, usecase);
386 if (acdb_dev_id <= 0) {
387 ALOGE("%s: Couldn't get the acdb dev id", __func__);
388 return -1;
389 }
390
391 pcm_device_id = platform_get_pcm_device_id(usecase->id, usecase->type);
392 set_stream_app_type_mixer_ctrl(adev, pcm_device_id, app_type, acdb_dev_id,
393 sample_rate,
394 usecase->type,
395 usecase->type == PCM_PLAYBACK ? usecase->out_snd_device :
396 usecase->in_snd_device);
397 return 0;
398}
399
vivek mehta4a824772017-06-08 19:05:49 -0700400int audio_extn_utils_send_app_type_gain(struct audio_device *adev,
401 int app_type,
402 int *gain)
403{
404 int gain_cfg[4];
405 const char *mixer_ctl_name = "App Type Gain";
406 struct mixer_ctl *ctl;
407 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
408 if (!ctl) {
409 ALOGE("%s: Could not get volume ctl mixer %s", __func__,
410 mixer_ctl_name);
411 return -EINVAL;
412 }
413 gain_cfg[0] = 0;
414 gain_cfg[1] = app_type;
415 gain_cfg[2] = gain[0];
416 gain_cfg[3] = gain[1];
417 ALOGV("%s app_type %d l(%d) r(%d)", __func__, app_type, gain[0], gain[1]);
418 return mixer_ctl_set_array(ctl, gain_cfg,
419 sizeof(gain_cfg)/sizeof(gain_cfg[0]));
420}
421
vivek mehtaa68fea62017-06-08 19:04:02 -0700422// this assumes correct app_type and sample_rate fields
423// have been set for the stream using audio_extn_utils_send_app_type_cfg
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -0800424void audio_extn_utils_send_audio_calibration(struct audio_device *adev,
425 struct audio_usecase *usecase)
426{
427 int type = usecase->type;
428 int app_type = 0;
429
430 if (type == PCM_PLAYBACK && usecase->stream.out != NULL) {
431 struct stream_out *out = usecase->stream.out;
vivek mehtaa68fea62017-06-08 19:04:02 -0700432 ALOGV("%s send cal for app_type %d, rate %d", __func__,
433 out->app_type_cfg.app_type,
434 out->app_type_cfg.sample_rate);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -0800435 platform_send_audio_calibration_v2(adev->platform, usecase,
vivek mehtaa68fea62017-06-08 19:04:02 -0700436 out->app_type_cfg.app_type,
437 out->app_type_cfg.sample_rate);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -0800438 } else if (type == PCM_CAPTURE && usecase->stream.in != NULL) {
vivek mehtaa68fea62017-06-08 19:04:02 -0700439 struct stream_in *in = usecase->stream.in;
440 ALOGV("%s send cal for capture app_type %d, rate %d", __func__,
441 in->app_type_cfg.app_type,
442 in->app_type_cfg.sample_rate);
443 platform_send_audio_calibration_v2(adev->platform, usecase,
444 in->app_type_cfg.app_type,
445 in->app_type_cfg.sample_rate);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -0800446 } else {
447 /* when app type is default. the sample rate is not used to send cal */
448 platform_get_default_app_type_v2(adev->platform, type, &app_type);
vivek mehtaa68fea62017-06-08 19:04:02 -0700449 platform_send_audio_calibration_v2(adev->platform, usecase, app_type,
450 48000);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -0800451 }
452}
vivek mehta0fb11312017-05-15 19:35:32 -0700453
454#define MAX_SND_CARD 8
455#define RETRY_US 500000
456#define RETRY_NUMBER 10
457
458#define min(a, b) ((a) < (b) ? (a) : (b))
459
460static const char *kConfigLocationList[] =
461 {"/odm/etc", "/vendor/etc", "/system/etc"};
462static const int kConfigLocationListSize =
463 (sizeof(kConfigLocationList) / sizeof(kConfigLocationList[0]));
464
465bool audio_extn_utils_resolve_config_file(char file_name[MIXER_PATH_MAX_LENGTH])
466{
467 char full_config_path[MIXER_PATH_MAX_LENGTH];
468 for (int i = 0; i < kConfigLocationListSize; i++) {
469 snprintf(full_config_path,
470 MIXER_PATH_MAX_LENGTH,
471 "%s/%s",
472 kConfigLocationList[i],
473 file_name);
474 if (F_OK == access(full_config_path, 0)) {
475 strcpy(file_name, full_config_path);
476 return true;
477 }
478 }
479 return false;
480}
481
482/* platform_info_file should be size 'MIXER_PATH_MAX_LENGTH' */
Haynes Mathew George66ff30c2017-06-01 20:24:42 -0700483int audio_extn_utils_get_platform_info(const char* snd_card_name, char* platform_info_file)
vivek mehta0fb11312017-05-15 19:35:32 -0700484{
485 if (NULL == snd_card_name) {
Haynes Mathew George66ff30c2017-06-01 20:24:42 -0700486 return -1;
vivek mehta0fb11312017-05-15 19:35:32 -0700487 }
488
489 struct snd_card_split *snd_split_handle = NULL;
Haynes Mathew George66ff30c2017-06-01 20:24:42 -0700490 int ret = 0;
vivek mehta0fb11312017-05-15 19:35:32 -0700491 audio_extn_set_snd_card_split(snd_card_name);
492 snd_split_handle = audio_extn_get_snd_card_split();
493
494 snprintf(platform_info_file, MIXER_PATH_MAX_LENGTH, "%s_%s_%s.xml",
495 PLATFORM_INFO_XML_BASE_STRING, snd_split_handle->snd_card,
496 snd_split_handle->form_factor);
497
498 if (!audio_extn_utils_resolve_config_file(platform_info_file)) {
499 memset(platform_info_file, 0, MIXER_PATH_MAX_LENGTH);
500 snprintf(platform_info_file, MIXER_PATH_MAX_LENGTH, "%s_%s.xml",
501 PLATFORM_INFO_XML_BASE_STRING, snd_split_handle->snd_card);
502
503 if (!audio_extn_utils_resolve_config_file(platform_info_file)) {
504 memset(platform_info_file, 0, MIXER_PATH_MAX_LENGTH);
505 strlcpy(platform_info_file, PLATFORM_INFO_XML_PATH, MIXER_PATH_MAX_LENGTH);
Haynes Mathew George66ff30c2017-06-01 20:24:42 -0700506 ret = audio_extn_utils_resolve_config_file(platform_info_file) ? 0 : -1;
vivek mehta0fb11312017-05-15 19:35:32 -0700507 }
508 }
Haynes Mathew George66ff30c2017-06-01 20:24:42 -0700509
510 return ret;
vivek mehta0fb11312017-05-15 19:35:32 -0700511}
512
513int audio_extn_utils_get_snd_card_num()
514{
515
516 void *hw_info = NULL;
517 struct mixer *mixer = NULL;
518 int retry_num = 0;
519 int snd_card_num = 0;
520 const char* snd_card_name = NULL;
521 char platform_info_file[MIXER_PATH_MAX_LENGTH]= {0};
522
523 struct acdb_platform_data *my_data = calloc(1, sizeof(struct acdb_platform_data));
524
525 bool card_verifed[MAX_SND_CARD] = {0};
526 const int retry_limit = property_get_int32("audio.snd_card.open.retries", RETRY_NUMBER);
527
528 for (;;) {
529 if (snd_card_num >= MAX_SND_CARD) {
530 if (retry_num++ >= retry_limit) {
531 ALOGE("%s: Unable to find correct sound card, aborting.", __func__);
532 snd_card_num = -1;
533 goto done;
534 }
535
536 snd_card_num = 0;
537 usleep(RETRY_US);
538 continue;
539 }
540
541 if (card_verifed[snd_card_num]) {
542 ++snd_card_num;
543 continue;
544 }
545
546 mixer = mixer_open(snd_card_num);
547
548 if (!mixer) {
549 ALOGE("%s: Unable to open the mixer card: %d", __func__,
550 snd_card_num);
551 ++snd_card_num;
552 continue;
553 }
554
555 card_verifed[snd_card_num] = true;
556
557 snd_card_name = mixer_get_name(mixer);
558 hw_info = hw_info_init(snd_card_name);
559
Haynes Mathew George66ff30c2017-06-01 20:24:42 -0700560 if (audio_extn_utils_get_platform_info(snd_card_name, platform_info_file) < 0) {
561 ALOGE("Failed to find platform_info_file");
562 goto cleanup;
563 }
vivek mehta0fb11312017-05-15 19:35:32 -0700564
565 /* Initialize snd card name specific ids and/or backends*/
Haynes Mathew George66ff30c2017-06-01 20:24:42 -0700566 if (snd_card_info_init(platform_info_file, my_data,
567 &acdb_set_parameters) < 0) {
568 ALOGE("Failed to find platform_info_file");
569 goto cleanup;
570 }
vivek mehta0fb11312017-05-15 19:35:32 -0700571
572 /* validate the sound card name
573 * my_data->snd_card_name can contain
574 * <a> complete sound card name, i.e. <device>-<codec>-<form_factor>-snd-card
575 * example: msm8994-tomtom-mtp-snd-card
576 * <b> or sub string of the card name, i.e. <device>-<codec>
577 * example: msm8994-tomtom
578 * snd_card_name is truncated to 32 charaters as per mixer_get_name() implementation
579 * so use min of my_data->snd_card_name and snd_card_name length for comparison
580 */
581
582 if (my_data->snd_card_name != NULL &&
583 strncmp(snd_card_name, my_data->snd_card_name,
584 min(strlen(snd_card_name), strlen(my_data->snd_card_name))) != 0) {
585 ALOGI("%s: found valid sound card %s, but not primary sound card %s",
586 __func__, snd_card_name, my_data->snd_card_name);
Haynes Mathew George66ff30c2017-06-01 20:24:42 -0700587 goto cleanup;
vivek mehta0fb11312017-05-15 19:35:32 -0700588 }
589
Haynes Mathew George66ff30c2017-06-01 20:24:42 -0700590 ALOGI("%s: found sound card %s, primary sound card expected is %s",
vivek mehta0fb11312017-05-15 19:35:32 -0700591 __func__, snd_card_name, my_data->snd_card_name);
592 break;
Haynes Mathew George66ff30c2017-06-01 20:24:42 -0700593 cleanup:
594 ++snd_card_num;
595 mixer_close(mixer);
596 mixer = NULL;
597 hw_info_deinit(hw_info);
598 hw_info = NULL;
vivek mehta0fb11312017-05-15 19:35:32 -0700599 }
600
601done:
602 mixer_close(mixer);
603 hw_info_deinit(hw_info);
604
605 if (my_data)
606 free(my_data);
607
608 return snd_card_num;
609}