blob: c9d23974bddb95a214087acefaa1f33fb754b600 [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{
vivek mehtaa68fea62017-06-08 19:04:02 -0700217 struct stream_in *in = usecase->stream.in;
218 struct stream_app_type_cfg *app_type_cfg = &in->app_type_cfg;
219
220 *sample_rate = DEFAULT_INPUT_SAMPLING_RATE;
vivek mehta4a824772017-06-08 19:05:49 -0700221 if (audio_is_usb_in_device(in->device)) {
vivek mehtaa68fea62017-06-08 19:04:02 -0700222 platform_check_and_update_copp_sample_rate(adev->platform,
223 usecase->in_snd_device,
224 in->sample_rate,
225 sample_rate);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -0800226 }
227
vivek mehtaa68fea62017-06-08 19:04:02 -0700228 app_type_cfg->mode = flags_to_mode(1 /*capture*/, in->flags);
229 ALOGV("%s mode %s", __func__, app_type_cfg->mode);
230 if (in->format == AUDIO_FORMAT_PCM_16_BIT) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -0800231 platform_get_app_type_v2(adev->platform,
vivek mehtaa68fea62017-06-08 19:04:02 -0700232 PCM_CAPTURE,
233 app_type_cfg->mode,
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -0800234 16,
vivek mehtaa68fea62017-06-08 19:04:02 -0700235 app_type_cfg->sample_rate,
236 app_type);
237 } else if (in->format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
238 in->format == AUDIO_FORMAT_PCM_8_24_BIT) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -0800239 platform_get_app_type_v2(adev->platform,
vivek mehtaa68fea62017-06-08 19:04:02 -0700240 PCM_CAPTURE,
241 app_type_cfg->mode,
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -0800242 24,
vivek mehtaa68fea62017-06-08 19:04:02 -0700243 app_type_cfg->sample_rate,
244 app_type);
245 } else if (in->format == AUDIO_FORMAT_PCM_32_BIT) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -0800246 platform_get_app_type_v2(adev->platform,
vivek mehtaa68fea62017-06-08 19:04:02 -0700247 PCM_CAPTURE,
248 app_type_cfg->mode,
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -0800249 32,
vivek mehtaa68fea62017-06-08 19:04:02 -0700250 app_type_cfg->sample_rate,
251 app_type);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -0800252 } else {
253 ALOGE("%s bad format\n", __func__);
254 return -1;
255 }
256
vivek mehtaa68fea62017-06-08 19:04:02 -0700257 app_type_cfg->app_type = *app_type;
258 app_type_cfg->sample_rate = *sample_rate;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -0800259 return 0;
260}
261
vivek mehtaa68fea62017-06-08 19:04:02 -0700262static int derive_playback_app_type_cfg(struct audio_device *adev,
263 struct audio_usecase *usecase,
264 int *app_type,
265 int *sample_rate)
266{
267 struct stream_out *out = usecase->stream.out;
268 struct stream_app_type_cfg *app_type_cfg = &out->app_type_cfg;
269
270 *sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
271
272 // add speaker prot changes if needed
273 // and use that to check for device
vivek mehta4a824772017-06-08 19:05:49 -0700274 if (audio_is_usb_out_device(out->devices)) {
vivek mehtaa68fea62017-06-08 19:04:02 -0700275 platform_check_and_update_copp_sample_rate(adev->platform,
276 usecase->out_snd_device,
277 out->sample_rate,
278 sample_rate);
279 }
280
281 app_type_cfg->mode = flags_to_mode(0 /*playback*/, out->flags);
282 if (!audio_is_linear_pcm(out->format)) {
283 platform_get_default_app_type_v2(adev->platform,
284 PCM_PLAYBACK,
285 app_type);
286 } else if (out->format == AUDIO_FORMAT_PCM_16_BIT) {
287 platform_get_app_type_v2(adev->platform,
288 PCM_PLAYBACK,
289 app_type_cfg->mode,
290 16,
291 *sample_rate,
292 app_type);
293 } else if (out->format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
294 out->format == AUDIO_FORMAT_PCM_8_24_BIT) {
295 platform_get_app_type_v2(adev->platform,
296 PCM_PLAYBACK,
297 app_type_cfg->mode,
298 24,
299 *sample_rate,
300 app_type);
301 } else if (out->format == AUDIO_FORMAT_PCM_32_BIT) {
302 platform_get_app_type_v2(adev->platform,
303 PCM_PLAYBACK,
304 app_type_cfg->mode,
305 32,
306 *sample_rate,
307 app_type);
308 } else {
309 ALOGE("%s bad format\n", __func__);
310 return -1;
311 }
312
313 app_type_cfg->app_type = *app_type;
314 app_type_cfg->sample_rate = *sample_rate;
315 return 0;
316}
317
318static int derive_acdb_dev_id(struct audio_device *adev __unused,
319 struct audio_usecase *usecase)
320{
321 struct stream_out *out;
322 struct stream_in *in;
323
324 if (usecase->type == PCM_PLAYBACK) {
325 return platform_get_snd_device_acdb_id(usecase->out_snd_device);
326 } else if(usecase->type == PCM_CAPTURE) {
327 return platform_get_snd_device_acdb_id(usecase->in_snd_device);
328 }
329 return -1;
330}
331
332int audio_extn_utils_send_app_type_cfg(struct audio_device *adev,
333 struct audio_usecase *usecase)
334{
335 int len = 0;
336 int sample_rate;
337 int app_type;
338 int acdb_dev_id;
339 size_t app_type_cfg[MAX_LENGTH_MIXER_CONTROL_IN_INT] = {0};
340 char mixer_ctl_name[MAX_LENGTH_MIXER_CONTROL_IN_INT] = {0};
341 int pcm_device_id;
342 struct mixer_ctl *ctl;
343 int ret;
344
345 if (usecase->type == PCM_HFP_CALL) {
346 return audio_extn_utils_send_app_type_cfg_hfp(adev, usecase);
347 }
348
349 if (!platform_supports_app_type_cfg())
350 return -1;
351
352 if (usecase->type == PCM_PLAYBACK) {
353 ret = derive_playback_app_type_cfg(adev,
354 usecase,
355 &app_type,
356 &sample_rate);
357 } else if (usecase->type == PCM_CAPTURE) {
358 ret = derive_capture_app_type_cfg(adev,
359 usecase,
360 &app_type,
361 &sample_rate);
362 } else {
363 ALOGE("%s: Invalid uc type : 0x%x", __func__, usecase->type);
364 return -1;
365 }
366
367 if (ret < 0) {
368 ALOGE("%s: Failed to derive app_type for uc type : 0x%x", __func__,
369 usecase->type);
370 return -1;
371 }
372
373 acdb_dev_id = derive_acdb_dev_id(adev, usecase);
374 if (acdb_dev_id <= 0) {
375 ALOGE("%s: Couldn't get the acdb dev id", __func__);
376 return -1;
377 }
378
379 pcm_device_id = platform_get_pcm_device_id(usecase->id, usecase->type);
380 set_stream_app_type_mixer_ctrl(adev, pcm_device_id, app_type, acdb_dev_id,
381 sample_rate,
382 usecase->type,
383 usecase->type == PCM_PLAYBACK ? usecase->out_snd_device :
384 usecase->in_snd_device);
385 return 0;
386}
387
vivek mehta4a824772017-06-08 19:05:49 -0700388int audio_extn_utils_send_app_type_gain(struct audio_device *adev,
389 int app_type,
390 int *gain)
391{
392 int gain_cfg[4];
393 const char *mixer_ctl_name = "App Type Gain";
394 struct mixer_ctl *ctl;
395 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
396 if (!ctl) {
397 ALOGE("%s: Could not get volume ctl mixer %s", __func__,
398 mixer_ctl_name);
399 return -EINVAL;
400 }
401 gain_cfg[0] = 0;
402 gain_cfg[1] = app_type;
403 gain_cfg[2] = gain[0];
404 gain_cfg[3] = gain[1];
405 ALOGV("%s app_type %d l(%d) r(%d)", __func__, app_type, gain[0], gain[1]);
406 return mixer_ctl_set_array(ctl, gain_cfg,
407 sizeof(gain_cfg)/sizeof(gain_cfg[0]));
408}
409
vivek mehtaa68fea62017-06-08 19:04:02 -0700410// this assumes correct app_type and sample_rate fields
411// have been set for the stream using audio_extn_utils_send_app_type_cfg
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -0800412void audio_extn_utils_send_audio_calibration(struct audio_device *adev,
413 struct audio_usecase *usecase)
414{
415 int type = usecase->type;
416 int app_type = 0;
417
418 if (type == PCM_PLAYBACK && usecase->stream.out != NULL) {
419 struct stream_out *out = usecase->stream.out;
vivek mehtaa68fea62017-06-08 19:04:02 -0700420 ALOGV("%s send cal for app_type %d, rate %d", __func__,
421 out->app_type_cfg.app_type,
422 out->app_type_cfg.sample_rate);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -0800423 platform_send_audio_calibration_v2(adev->platform, usecase,
vivek mehtaa68fea62017-06-08 19:04:02 -0700424 out->app_type_cfg.app_type,
425 out->app_type_cfg.sample_rate);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -0800426 } else if (type == PCM_CAPTURE && usecase->stream.in != NULL) {
vivek mehtaa68fea62017-06-08 19:04:02 -0700427 struct stream_in *in = usecase->stream.in;
428 ALOGV("%s send cal for capture app_type %d, rate %d", __func__,
429 in->app_type_cfg.app_type,
430 in->app_type_cfg.sample_rate);
431 platform_send_audio_calibration_v2(adev->platform, usecase,
432 in->app_type_cfg.app_type,
433 in->app_type_cfg.sample_rate);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -0800434 } else {
435 /* when app type is default. the sample rate is not used to send cal */
436 platform_get_default_app_type_v2(adev->platform, type, &app_type);
vivek mehtaa68fea62017-06-08 19:04:02 -0700437 platform_send_audio_calibration_v2(adev->platform, usecase, app_type,
438 48000);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -0800439 }
440}
vivek mehta0fb11312017-05-15 19:35:32 -0700441
442#define MAX_SND_CARD 8
443#define RETRY_US 500000
444#define RETRY_NUMBER 10
445
446#define min(a, b) ((a) < (b) ? (a) : (b))
447
448static const char *kConfigLocationList[] =
449 {"/odm/etc", "/vendor/etc", "/system/etc"};
450static const int kConfigLocationListSize =
451 (sizeof(kConfigLocationList) / sizeof(kConfigLocationList[0]));
452
453bool audio_extn_utils_resolve_config_file(char file_name[MIXER_PATH_MAX_LENGTH])
454{
455 char full_config_path[MIXER_PATH_MAX_LENGTH];
456 for (int i = 0; i < kConfigLocationListSize; i++) {
457 snprintf(full_config_path,
458 MIXER_PATH_MAX_LENGTH,
459 "%s/%s",
460 kConfigLocationList[i],
461 file_name);
462 if (F_OK == access(full_config_path, 0)) {
463 strcpy(file_name, full_config_path);
464 return true;
465 }
466 }
467 return false;
468}
469
470/* platform_info_file should be size 'MIXER_PATH_MAX_LENGTH' */
Haynes Mathew George66ff30c2017-06-01 20:24:42 -0700471int audio_extn_utils_get_platform_info(const char* snd_card_name, char* platform_info_file)
vivek mehta0fb11312017-05-15 19:35:32 -0700472{
473 if (NULL == snd_card_name) {
Haynes Mathew George66ff30c2017-06-01 20:24:42 -0700474 return -1;
vivek mehta0fb11312017-05-15 19:35:32 -0700475 }
476
477 struct snd_card_split *snd_split_handle = NULL;
Haynes Mathew George66ff30c2017-06-01 20:24:42 -0700478 int ret = 0;
vivek mehta0fb11312017-05-15 19:35:32 -0700479 audio_extn_set_snd_card_split(snd_card_name);
480 snd_split_handle = audio_extn_get_snd_card_split();
481
482 snprintf(platform_info_file, MIXER_PATH_MAX_LENGTH, "%s_%s_%s.xml",
483 PLATFORM_INFO_XML_BASE_STRING, snd_split_handle->snd_card,
484 snd_split_handle->form_factor);
485
486 if (!audio_extn_utils_resolve_config_file(platform_info_file)) {
487 memset(platform_info_file, 0, MIXER_PATH_MAX_LENGTH);
488 snprintf(platform_info_file, MIXER_PATH_MAX_LENGTH, "%s_%s.xml",
489 PLATFORM_INFO_XML_BASE_STRING, snd_split_handle->snd_card);
490
491 if (!audio_extn_utils_resolve_config_file(platform_info_file)) {
492 memset(platform_info_file, 0, MIXER_PATH_MAX_LENGTH);
493 strlcpy(platform_info_file, PLATFORM_INFO_XML_PATH, MIXER_PATH_MAX_LENGTH);
Haynes Mathew George66ff30c2017-06-01 20:24:42 -0700494 ret = audio_extn_utils_resolve_config_file(platform_info_file) ? 0 : -1;
vivek mehta0fb11312017-05-15 19:35:32 -0700495 }
496 }
Haynes Mathew George66ff30c2017-06-01 20:24:42 -0700497
498 return ret;
vivek mehta0fb11312017-05-15 19:35:32 -0700499}
500
501int audio_extn_utils_get_snd_card_num()
502{
503
504 void *hw_info = NULL;
505 struct mixer *mixer = NULL;
506 int retry_num = 0;
507 int snd_card_num = 0;
508 const char* snd_card_name = NULL;
509 char platform_info_file[MIXER_PATH_MAX_LENGTH]= {0};
510
511 struct acdb_platform_data *my_data = calloc(1, sizeof(struct acdb_platform_data));
512
513 bool card_verifed[MAX_SND_CARD] = {0};
514 const int retry_limit = property_get_int32("audio.snd_card.open.retries", RETRY_NUMBER);
515
516 for (;;) {
517 if (snd_card_num >= MAX_SND_CARD) {
518 if (retry_num++ >= retry_limit) {
519 ALOGE("%s: Unable to find correct sound card, aborting.", __func__);
520 snd_card_num = -1;
521 goto done;
522 }
523
524 snd_card_num = 0;
525 usleep(RETRY_US);
526 continue;
527 }
528
529 if (card_verifed[snd_card_num]) {
530 ++snd_card_num;
531 continue;
532 }
533
534 mixer = mixer_open(snd_card_num);
535
536 if (!mixer) {
537 ALOGE("%s: Unable to open the mixer card: %d", __func__,
538 snd_card_num);
539 ++snd_card_num;
540 continue;
541 }
542
543 card_verifed[snd_card_num] = true;
544
545 snd_card_name = mixer_get_name(mixer);
546 hw_info = hw_info_init(snd_card_name);
547
Haynes Mathew George66ff30c2017-06-01 20:24:42 -0700548 if (audio_extn_utils_get_platform_info(snd_card_name, platform_info_file) < 0) {
549 ALOGE("Failed to find platform_info_file");
550 goto cleanup;
551 }
vivek mehta0fb11312017-05-15 19:35:32 -0700552
553 /* Initialize snd card name specific ids and/or backends*/
Haynes Mathew George66ff30c2017-06-01 20:24:42 -0700554 if (snd_card_info_init(platform_info_file, my_data,
555 &acdb_set_parameters) < 0) {
556 ALOGE("Failed to find platform_info_file");
557 goto cleanup;
558 }
vivek mehta0fb11312017-05-15 19:35:32 -0700559
560 /* validate the sound card name
561 * my_data->snd_card_name can contain
562 * <a> complete sound card name, i.e. <device>-<codec>-<form_factor>-snd-card
563 * example: msm8994-tomtom-mtp-snd-card
564 * <b> or sub string of the card name, i.e. <device>-<codec>
565 * example: msm8994-tomtom
566 * snd_card_name is truncated to 32 charaters as per mixer_get_name() implementation
567 * so use min of my_data->snd_card_name and snd_card_name length for comparison
568 */
569
570 if (my_data->snd_card_name != NULL &&
571 strncmp(snd_card_name, my_data->snd_card_name,
572 min(strlen(snd_card_name), strlen(my_data->snd_card_name))) != 0) {
573 ALOGI("%s: found valid sound card %s, but not primary sound card %s",
574 __func__, snd_card_name, my_data->snd_card_name);
Haynes Mathew George66ff30c2017-06-01 20:24:42 -0700575 goto cleanup;
vivek mehta0fb11312017-05-15 19:35:32 -0700576 }
577
Haynes Mathew George66ff30c2017-06-01 20:24:42 -0700578 ALOGI("%s: found sound card %s, primary sound card expected is %s",
vivek mehta0fb11312017-05-15 19:35:32 -0700579 __func__, snd_card_name, my_data->snd_card_name);
580 break;
Haynes Mathew George66ff30c2017-06-01 20:24:42 -0700581 cleanup:
582 ++snd_card_num;
583 mixer_close(mixer);
584 mixer = NULL;
585 hw_info_deinit(hw_info);
586 hw_info = NULL;
vivek mehta0fb11312017-05-15 19:35:32 -0700587 }
588
589done:
590 mixer_close(mixer);
591 hw_info_deinit(hw_info);
592
593 if (my_data)
594 free(my_data);
595
596 return snd_card_num;
597}