blob: 1f52590807c36b41e2ee83e343910009f78ff221 [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)) {
Haynes Mathew Georgedf0f8862017-06-28 13:36:40 -0700289 platform_get_app_type_v2(adev->platform,
290 PCM_PLAYBACK,
291 app_type_cfg->mode,
292 24,
293 *sample_rate,
294 app_type);
295 ALOGV("Non pcm got app type %d", *app_type);
vivek mehtaa68fea62017-06-08 19:04:02 -0700296 } else if (out->format == AUDIO_FORMAT_PCM_16_BIT) {
297 platform_get_app_type_v2(adev->platform,
298 PCM_PLAYBACK,
299 app_type_cfg->mode,
300 16,
301 *sample_rate,
302 app_type);
303 } else if (out->format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
304 out->format == AUDIO_FORMAT_PCM_8_24_BIT) {
305 platform_get_app_type_v2(adev->platform,
306 PCM_PLAYBACK,
307 app_type_cfg->mode,
308 24,
309 *sample_rate,
310 app_type);
311 } else if (out->format == AUDIO_FORMAT_PCM_32_BIT) {
312 platform_get_app_type_v2(adev->platform,
313 PCM_PLAYBACK,
314 app_type_cfg->mode,
315 32,
316 *sample_rate,
317 app_type);
318 } else {
319 ALOGE("%s bad format\n", __func__);
320 return -1;
321 }
322
323 app_type_cfg->app_type = *app_type;
324 app_type_cfg->sample_rate = *sample_rate;
325 return 0;
326}
327
328static int derive_acdb_dev_id(struct audio_device *adev __unused,
329 struct audio_usecase *usecase)
330{
331 struct stream_out *out;
332 struct stream_in *in;
333
334 if (usecase->type == PCM_PLAYBACK) {
335 return platform_get_snd_device_acdb_id(usecase->out_snd_device);
336 } else if(usecase->type == PCM_CAPTURE) {
337 return platform_get_snd_device_acdb_id(usecase->in_snd_device);
338 }
339 return -1;
340}
341
342int audio_extn_utils_send_app_type_cfg(struct audio_device *adev,
343 struct audio_usecase *usecase)
344{
345 int len = 0;
346 int sample_rate;
347 int app_type;
348 int acdb_dev_id;
349 size_t app_type_cfg[MAX_LENGTH_MIXER_CONTROL_IN_INT] = {0};
350 char mixer_ctl_name[MAX_LENGTH_MIXER_CONTROL_IN_INT] = {0};
351 int pcm_device_id;
352 struct mixer_ctl *ctl;
353 int ret;
354
355 if (usecase->type == PCM_HFP_CALL) {
356 return audio_extn_utils_send_app_type_cfg_hfp(adev, usecase);
357 }
358
359 if (!platform_supports_app_type_cfg())
360 return -1;
361
362 if (usecase->type == PCM_PLAYBACK) {
363 ret = derive_playback_app_type_cfg(adev,
364 usecase,
365 &app_type,
366 &sample_rate);
367 } else if (usecase->type == PCM_CAPTURE) {
368 ret = derive_capture_app_type_cfg(adev,
369 usecase,
370 &app_type,
371 &sample_rate);
372 } else {
373 ALOGE("%s: Invalid uc type : 0x%x", __func__, usecase->type);
374 return -1;
375 }
376
377 if (ret < 0) {
378 ALOGE("%s: Failed to derive app_type for uc type : 0x%x", __func__,
379 usecase->type);
380 return -1;
381 }
382
383 acdb_dev_id = derive_acdb_dev_id(adev, usecase);
384 if (acdb_dev_id <= 0) {
385 ALOGE("%s: Couldn't get the acdb dev id", __func__);
386 return -1;
387 }
388
389 pcm_device_id = platform_get_pcm_device_id(usecase->id, usecase->type);
390 set_stream_app_type_mixer_ctrl(adev, pcm_device_id, app_type, acdb_dev_id,
391 sample_rate,
392 usecase->type,
393 usecase->type == PCM_PLAYBACK ? usecase->out_snd_device :
394 usecase->in_snd_device);
395 return 0;
396}
397
vivek mehta4a824772017-06-08 19:05:49 -0700398int audio_extn_utils_send_app_type_gain(struct audio_device *adev,
399 int app_type,
400 int *gain)
401{
402 int gain_cfg[4];
403 const char *mixer_ctl_name = "App Type Gain";
404 struct mixer_ctl *ctl;
405 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
406 if (!ctl) {
407 ALOGE("%s: Could not get volume ctl mixer %s", __func__,
408 mixer_ctl_name);
409 return -EINVAL;
410 }
411 gain_cfg[0] = 0;
412 gain_cfg[1] = app_type;
413 gain_cfg[2] = gain[0];
414 gain_cfg[3] = gain[1];
415 ALOGV("%s app_type %d l(%d) r(%d)", __func__, app_type, gain[0], gain[1]);
416 return mixer_ctl_set_array(ctl, gain_cfg,
417 sizeof(gain_cfg)/sizeof(gain_cfg[0]));
418}
419
vivek mehtaa68fea62017-06-08 19:04:02 -0700420// this assumes correct app_type and sample_rate fields
421// have been set for the stream using audio_extn_utils_send_app_type_cfg
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -0800422void audio_extn_utils_send_audio_calibration(struct audio_device *adev,
423 struct audio_usecase *usecase)
424{
425 int type = usecase->type;
426 int app_type = 0;
427
428 if (type == PCM_PLAYBACK && usecase->stream.out != NULL) {
429 struct stream_out *out = usecase->stream.out;
vivek mehtaa68fea62017-06-08 19:04:02 -0700430 ALOGV("%s send cal for app_type %d, rate %d", __func__,
431 out->app_type_cfg.app_type,
432 out->app_type_cfg.sample_rate);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -0800433 platform_send_audio_calibration_v2(adev->platform, usecase,
vivek mehtaa68fea62017-06-08 19:04:02 -0700434 out->app_type_cfg.app_type,
435 out->app_type_cfg.sample_rate);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -0800436 } else if (type == PCM_CAPTURE && usecase->stream.in != NULL) {
vivek mehtaa68fea62017-06-08 19:04:02 -0700437 struct stream_in *in = usecase->stream.in;
438 ALOGV("%s send cal for capture app_type %d, rate %d", __func__,
439 in->app_type_cfg.app_type,
440 in->app_type_cfg.sample_rate);
441 platform_send_audio_calibration_v2(adev->platform, usecase,
442 in->app_type_cfg.app_type,
443 in->app_type_cfg.sample_rate);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -0800444 } else {
445 /* when app type is default. the sample rate is not used to send cal */
446 platform_get_default_app_type_v2(adev->platform, type, &app_type);
vivek mehtaa68fea62017-06-08 19:04:02 -0700447 platform_send_audio_calibration_v2(adev->platform, usecase, app_type,
448 48000);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -0800449 }
450}
vivek mehta0fb11312017-05-15 19:35:32 -0700451
452#define MAX_SND_CARD 8
453#define RETRY_US 500000
454#define RETRY_NUMBER 10
455
456#define min(a, b) ((a) < (b) ? (a) : (b))
457
458static const char *kConfigLocationList[] =
459 {"/odm/etc", "/vendor/etc", "/system/etc"};
460static const int kConfigLocationListSize =
461 (sizeof(kConfigLocationList) / sizeof(kConfigLocationList[0]));
462
463bool audio_extn_utils_resolve_config_file(char file_name[MIXER_PATH_MAX_LENGTH])
464{
465 char full_config_path[MIXER_PATH_MAX_LENGTH];
466 for (int i = 0; i < kConfigLocationListSize; i++) {
467 snprintf(full_config_path,
468 MIXER_PATH_MAX_LENGTH,
469 "%s/%s",
470 kConfigLocationList[i],
471 file_name);
472 if (F_OK == access(full_config_path, 0)) {
473 strcpy(file_name, full_config_path);
474 return true;
475 }
476 }
477 return false;
478}
479
480/* platform_info_file should be size 'MIXER_PATH_MAX_LENGTH' */
Haynes Mathew George66ff30c2017-06-01 20:24:42 -0700481int audio_extn_utils_get_platform_info(const char* snd_card_name, char* platform_info_file)
vivek mehta0fb11312017-05-15 19:35:32 -0700482{
483 if (NULL == snd_card_name) {
Haynes Mathew George66ff30c2017-06-01 20:24:42 -0700484 return -1;
vivek mehta0fb11312017-05-15 19:35:32 -0700485 }
486
487 struct snd_card_split *snd_split_handle = NULL;
Haynes Mathew George66ff30c2017-06-01 20:24:42 -0700488 int ret = 0;
vivek mehta0fb11312017-05-15 19:35:32 -0700489 audio_extn_set_snd_card_split(snd_card_name);
490 snd_split_handle = audio_extn_get_snd_card_split();
491
492 snprintf(platform_info_file, MIXER_PATH_MAX_LENGTH, "%s_%s_%s.xml",
493 PLATFORM_INFO_XML_BASE_STRING, snd_split_handle->snd_card,
494 snd_split_handle->form_factor);
495
496 if (!audio_extn_utils_resolve_config_file(platform_info_file)) {
497 memset(platform_info_file, 0, MIXER_PATH_MAX_LENGTH);
498 snprintf(platform_info_file, MIXER_PATH_MAX_LENGTH, "%s_%s.xml",
499 PLATFORM_INFO_XML_BASE_STRING, snd_split_handle->snd_card);
500
501 if (!audio_extn_utils_resolve_config_file(platform_info_file)) {
502 memset(platform_info_file, 0, MIXER_PATH_MAX_LENGTH);
503 strlcpy(platform_info_file, PLATFORM_INFO_XML_PATH, MIXER_PATH_MAX_LENGTH);
Haynes Mathew George66ff30c2017-06-01 20:24:42 -0700504 ret = audio_extn_utils_resolve_config_file(platform_info_file) ? 0 : -1;
vivek mehta0fb11312017-05-15 19:35:32 -0700505 }
506 }
Haynes Mathew George66ff30c2017-06-01 20:24:42 -0700507
508 return ret;
vivek mehta0fb11312017-05-15 19:35:32 -0700509}
510
511int audio_extn_utils_get_snd_card_num()
512{
513
514 void *hw_info = NULL;
515 struct mixer *mixer = NULL;
516 int retry_num = 0;
517 int snd_card_num = 0;
518 const char* snd_card_name = NULL;
519 char platform_info_file[MIXER_PATH_MAX_LENGTH]= {0};
520
521 struct acdb_platform_data *my_data = calloc(1, sizeof(struct acdb_platform_data));
522
523 bool card_verifed[MAX_SND_CARD] = {0};
524 const int retry_limit = property_get_int32("audio.snd_card.open.retries", RETRY_NUMBER);
525
526 for (;;) {
527 if (snd_card_num >= MAX_SND_CARD) {
528 if (retry_num++ >= retry_limit) {
529 ALOGE("%s: Unable to find correct sound card, aborting.", __func__);
530 snd_card_num = -1;
531 goto done;
532 }
533
534 snd_card_num = 0;
535 usleep(RETRY_US);
536 continue;
537 }
538
539 if (card_verifed[snd_card_num]) {
540 ++snd_card_num;
541 continue;
542 }
543
544 mixer = mixer_open(snd_card_num);
545
546 if (!mixer) {
547 ALOGE("%s: Unable to open the mixer card: %d", __func__,
548 snd_card_num);
549 ++snd_card_num;
550 continue;
551 }
552
553 card_verifed[snd_card_num] = true;
554
555 snd_card_name = mixer_get_name(mixer);
556 hw_info = hw_info_init(snd_card_name);
557
Haynes Mathew George66ff30c2017-06-01 20:24:42 -0700558 if (audio_extn_utils_get_platform_info(snd_card_name, platform_info_file) < 0) {
559 ALOGE("Failed to find platform_info_file");
560 goto cleanup;
561 }
vivek mehta0fb11312017-05-15 19:35:32 -0700562
563 /* Initialize snd card name specific ids and/or backends*/
Haynes Mathew George66ff30c2017-06-01 20:24:42 -0700564 if (snd_card_info_init(platform_info_file, my_data,
565 &acdb_set_parameters) < 0) {
566 ALOGE("Failed to find platform_info_file");
567 goto cleanup;
568 }
vivek mehta0fb11312017-05-15 19:35:32 -0700569
570 /* validate the sound card name
571 * my_data->snd_card_name can contain
572 * <a> complete sound card name, i.e. <device>-<codec>-<form_factor>-snd-card
573 * example: msm8994-tomtom-mtp-snd-card
574 * <b> or sub string of the card name, i.e. <device>-<codec>
575 * example: msm8994-tomtom
576 * snd_card_name is truncated to 32 charaters as per mixer_get_name() implementation
577 * so use min of my_data->snd_card_name and snd_card_name length for comparison
578 */
579
580 if (my_data->snd_card_name != NULL &&
581 strncmp(snd_card_name, my_data->snd_card_name,
582 min(strlen(snd_card_name), strlen(my_data->snd_card_name))) != 0) {
583 ALOGI("%s: found valid sound card %s, but not primary sound card %s",
584 __func__, snd_card_name, my_data->snd_card_name);
Haynes Mathew George66ff30c2017-06-01 20:24:42 -0700585 goto cleanup;
vivek mehta0fb11312017-05-15 19:35:32 -0700586 }
587
Haynes Mathew George66ff30c2017-06-01 20:24:42 -0700588 ALOGI("%s: found sound card %s, primary sound card expected is %s",
vivek mehta0fb11312017-05-15 19:35:32 -0700589 __func__, snd_card_name, my_data->snd_card_name);
590 break;
Haynes Mathew George66ff30c2017-06-01 20:24:42 -0700591 cleanup:
592 ++snd_card_num;
593 mixer_close(mixer);
594 mixer = NULL;
595 hw_info_deinit(hw_info);
596 hw_info = NULL;
vivek mehta0fb11312017-05-15 19:35:32 -0700597 }
598
599done:
600 mixer_close(mixer);
601 hw_info_deinit(hw_info);
602
603 if (my_data)
604 free(my_data);
605
606 return snd_card_num;
607}