1 /*
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 <unistd.h>
26 #include <cutils/str_parms.h>
27 #include <log/log.h>
28 #include <cutils/misc.h>
29 
30 #include "acdb.h"
31 #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 
set_stream_app_type_mixer_ctrl(struct audio_device * adev,int pcm_device_id,int app_type,int acdb_dev_id,int sample_rate,int stream_type,snd_device_t snd_device)38 static 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)
43 {
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;
48     int snd_device_be_idx = -1;
49 
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;
68 
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);
76     mixer_ctl_set_array(ctl, app_type_cfg, len);
77 
78 exit:
79     return rc;
80 }
81 
audio_extn_utils_send_default_app_type_cfg(void * platform,struct mixer * mixer)82 void 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 
flags_to_mode(int dir,uint32_t flags)105 static 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 
audio_extn_utils_send_app_type_cfg_hfp(struct audio_device * adev,struct audio_usecase * usecase)119 static int audio_extn_utils_send_app_type_cfg_hfp(struct audio_device *adev,
120                                        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     acdb_dev_id = platform_get_snd_device_acdb_id(snd_device);
145     if (acdb_dev_id < 0) {
146         ALOGE("%s: Couldn't get the acdb dev id", __func__);
147         rc = -EINVAL;
148         goto exit_send_app_type_cfg;
149     }
150 
151     if (usecase->type == PCM_HFP_CALL) {
152 
153         /* config HFP session:1 playback path */
154         rc = platform_get_default_app_type_v2(adev->platform, PCM_PLAYBACK, &app_type);
155         if (rc < 0)
156             goto exit_send_app_type_cfg;
157 
158         sample_rate= CODEC_BACKEND_DEFAULT_SAMPLE_RATE;
159         rc = set_stream_app_type_mixer_ctrl(adev, pcm_device_id, app_type,
160                                             acdb_dev_id, sample_rate,
161                                             PCM_PLAYBACK,
162                                             SND_DEVICE_NONE); // use legacy behavior
163         if (rc < 0)
164             goto exit_send_app_type_cfg;
165         /* config HFP session:1 capture path */
166         rc = platform_get_default_app_type_v2(adev->platform, PCM_CAPTURE, &app_type);
167 
168         if (rc == 0) {
169             rc = set_stream_app_type_mixer_ctrl(adev, pcm_device_id, app_type,
170                                                 acdb_dev_id, sample_rate,
171                                                 PCM_CAPTURE,
172                                                 SND_DEVICE_NONE);
173             if (rc < 0)
174                 goto exit_send_app_type_cfg;
175         }
176         /* config HFP session:2 capture path */
177         pcm_device_id = HFP_ASM_RX_TX;
178         snd_device = usecase->in_snd_device;
179         acdb_dev_id = platform_get_snd_device_acdb_id(snd_device);
180         if (acdb_dev_id <= 0) {
181             ALOGE("%s: Couldn't get the acdb dev id", __func__);
182             rc = -EINVAL;
183             goto exit_send_app_type_cfg;
184         }
185         rc = platform_get_default_app_type_v2(adev->platform, PCM_CAPTURE, &app_type);
186         if (rc == 0) {
187             rc = set_stream_app_type_mixer_ctrl(adev, pcm_device_id, app_type,
188                                                 acdb_dev_id, sample_rate, PCM_CAPTURE,
189                                                 SND_DEVICE_NONE);
190             if (rc < 0)
191                 goto exit_send_app_type_cfg;
192         }
193 
194         /* config HFP session:2 playback path */
195         rc = platform_get_default_app_type_v2(adev->platform, PCM_PLAYBACK, &app_type);
196         if (rc == 0) {
197             rc = set_stream_app_type_mixer_ctrl(adev, pcm_device_id, app_type,
198                                 acdb_dev_id, sample_rate,
199                                 PCM_PLAYBACK, SND_DEVICE_NONE);
200             if (rc < 0)
201                 goto exit_send_app_type_cfg;
202         }
203     }
204 
205     rc = 0;
206 exit_send_app_type_cfg:
207     return rc;
208 }
209 
210 
derive_capture_app_type_cfg(struct audio_device * adev,struct audio_usecase * usecase,int * app_type,int * sample_rate)211 static int derive_capture_app_type_cfg(struct audio_device *adev,
212                                        struct audio_usecase *usecase,
213                                        int *app_type,
214                                        int *sample_rate)
215 {
216     if (usecase->stream.in == NULL) {
217         return -1;
218     }
219     struct stream_in *in = usecase->stream.in;
220     struct stream_app_type_cfg *app_type_cfg = &in->app_type_cfg;
221 
222     *sample_rate = DEFAULT_INPUT_SAMPLING_RATE;
223     if (audio_is_usb_in_device(in->device)) {
224         platform_check_and_update_copp_sample_rate(adev->platform,
225                                                    usecase->in_snd_device,
226                                                    in->sample_rate,
227                                                    sample_rate);
228     }
229 
230     app_type_cfg->mode = flags_to_mode(1 /*capture*/, in->flags);
231     ALOGV("%s mode %s", __func__, app_type_cfg->mode);
232     if (in->format == AUDIO_FORMAT_PCM_16_BIT) {
233         platform_get_app_type_v2(adev->platform,
234                                  PCM_CAPTURE,
235                                  app_type_cfg->mode,
236                                  16,
237                                  app_type_cfg->sample_rate,
238                                  app_type);
239     } else if (in->format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
240                in->format == AUDIO_FORMAT_PCM_8_24_BIT) {
241         platform_get_app_type_v2(adev->platform,
242                                  PCM_CAPTURE,
243                                  app_type_cfg->mode,
244                                  24,
245                                  app_type_cfg->sample_rate,
246                                  app_type);
247     } else if (in->format == AUDIO_FORMAT_PCM_32_BIT) {
248         platform_get_app_type_v2(adev->platform,
249                                  PCM_CAPTURE,
250                                  app_type_cfg->mode,
251                                  32,
252                                  app_type_cfg->sample_rate,
253                                  app_type);
254     } else {
255         ALOGE("%s bad format\n", __func__);
256         return -1;
257     }
258 
259     app_type_cfg->app_type = *app_type;
260     app_type_cfg->sample_rate = *sample_rate;
261     return 0;
262 }
263 
derive_playback_app_type_cfg(struct audio_device * adev,struct audio_usecase * usecase,int * app_type,int * sample_rate)264 static int derive_playback_app_type_cfg(struct audio_device *adev,
265                                         struct audio_usecase *usecase,
266                                         int *app_type,
267                                         int *sample_rate)
268 {
269     if (usecase->stream.out == NULL) {
270         return -1;
271     }
272     struct stream_out *out = usecase->stream.out;
273     struct stream_app_type_cfg *app_type_cfg = &out->app_type_cfg;
274 
275     *sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
276 
277     // add speaker prot changes if needed
278     // and use that to check for device
279     if (audio_is_usb_out_device(out->devices)) {
280         platform_check_and_update_copp_sample_rate(adev->platform,
281                                                    usecase->out_snd_device,
282                                                    out->sample_rate,
283                                                    sample_rate);
284     } else if (out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) {
285         audio_extn_a2dp_get_sample_rate(sample_rate);
286         ALOGI("%s: Using sample rate %d for A2DP CoPP", __func__,
287                *sample_rate);
288     }
289 
290     app_type_cfg->mode = flags_to_mode(0 /*playback*/, out->flags);
291     if (!audio_is_linear_pcm(out->format)) {
292         platform_get_app_type_v2(adev->platform,
293                                  PCM_PLAYBACK,
294                                  app_type_cfg->mode,
295                                  24,
296                                  *sample_rate,
297                                  app_type);
298         ALOGV("Non pcm got app type %d", *app_type);
299     } else if (out->format == AUDIO_FORMAT_PCM_16_BIT) {
300         platform_get_app_type_v2(adev->platform,
301                                  PCM_PLAYBACK,
302                                  app_type_cfg->mode,
303                                  16,
304                                  *sample_rate,
305                                  app_type);
306     } else if (out->format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
307                out->format == AUDIO_FORMAT_PCM_8_24_BIT) {
308         platform_get_app_type_v2(adev->platform,
309                                  PCM_PLAYBACK,
310                                  app_type_cfg->mode,
311                                  24,
312                                  *sample_rate,
313                                  app_type);
314     } else if (out->format == AUDIO_FORMAT_PCM_32_BIT) {
315         platform_get_app_type_v2(adev->platform,
316                                  PCM_PLAYBACK,
317                                  app_type_cfg->mode,
318                                  32,
319                                  *sample_rate,
320                                  app_type);
321     } else {
322         ALOGE("%s bad format\n", __func__);
323         return -1;
324     }
325 
326     app_type_cfg->app_type = *app_type;
327     app_type_cfg->sample_rate = *sample_rate;
328     return 0;
329 }
330 
derive_acdb_dev_id(struct audio_device * adev __unused,struct audio_usecase * usecase)331 static int derive_acdb_dev_id(struct audio_device *adev __unused,
332                               struct audio_usecase *usecase)
333 {
334     struct stream_out *out;
335     struct stream_in *in;
336 
337     if (usecase->type == PCM_PLAYBACK) {
338         return platform_get_snd_device_acdb_id(usecase->out_snd_device);
339     } else if(usecase->type == PCM_CAPTURE) {
340         return platform_get_snd_device_acdb_id(usecase->in_snd_device);
341     }
342     return -1;
343 }
344 
audio_extn_utils_send_app_type_cfg(struct audio_device * adev,struct audio_usecase * usecase)345 int audio_extn_utils_send_app_type_cfg(struct audio_device *adev,
346                                        struct audio_usecase *usecase)
347 {
348     int len = 0;
349     int sample_rate;
350     int app_type;
351     int acdb_dev_id;
352     int new_snd_device[2] = {0};
353     int i = 0, num_devices = 1;
354     size_t app_type_cfg[MAX_LENGTH_MIXER_CONTROL_IN_INT] = {0};
355     char mixer_ctl_name[MAX_LENGTH_MIXER_CONTROL_IN_INT] = {0};
356     int pcm_device_id;
357     struct mixer_ctl *ctl;
358     int ret;
359 
360     if (usecase->type == PCM_HFP_CALL) {
361         return audio_extn_utils_send_app_type_cfg_hfp(adev, usecase);
362     }
363 
364     if (!platform_supports_app_type_cfg())
365         return -1;
366 
367     if (usecase->type == PCM_PLAYBACK) {
368         ret = derive_playback_app_type_cfg(adev,
369                                            usecase,
370                                            &app_type,
371                                            &sample_rate);
372     } else if (usecase->type == PCM_CAPTURE) {
373         ret = derive_capture_app_type_cfg(adev,
374                                           usecase,
375                                           &app_type,
376                                           &sample_rate);
377     } else {
378         ALOGE("%s: Invalid uc type : 0x%x", __func__, usecase->type);
379         return -1;
380     }
381 
382     if (ret < 0) {
383         ALOGE("%s: Failed to derive app_type for uc type : 0x%x", __func__,
384               usecase->type);
385         return -1;
386     }
387 
388     if (usecase->type == PCM_PLAYBACK) {
389         if (platform_can_split_snd_device(usecase->out_snd_device,
390                                           &num_devices, new_snd_device) < 0)
391             new_snd_device[0] = usecase->out_snd_device;
392 
393     } else if (usecase->type == PCM_CAPTURE)
394         new_snd_device[0] = usecase->in_snd_device;
395 
396     pcm_device_id = platform_get_pcm_device_id(usecase->id, usecase->type);
397 
398     for (i = 0; i < num_devices; i++) {
399         acdb_dev_id = platform_get_snd_device_acdb_id(new_snd_device[i]);
400 
401         if (acdb_dev_id < 0) {
402             ALOGE("%s: Could not find acdb id for device(%d)",
403                   __func__, new_snd_device[i]);
404             return -EINVAL;
405         }
406         ALOGV("%s: sending app type for snd_device(%d) acdb_id(%d) i %d",
407               __func__, new_snd_device[i], acdb_dev_id, i);
408 
409         set_stream_app_type_mixer_ctrl(adev, pcm_device_id, app_type, acdb_dev_id,
410                                        sample_rate,
411                                        usecase->type,
412                                        new_snd_device[i]);
413     }
414 
415     return 0;
416 }
417 
audio_extn_utils_send_app_type_gain(struct audio_device * adev,int app_type,int * gain)418 int audio_extn_utils_send_app_type_gain(struct audio_device *adev,
419                                         int app_type,
420                                         int *gain)
421 {
422     int gain_cfg[4];
423     const char *mixer_ctl_name = "App Type Gain";
424     struct mixer_ctl *ctl;
425     ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
426     if (!ctl) {
427         ALOGE("%s: Could not get volume ctl mixer %s", __func__,
428               mixer_ctl_name);
429         return -EINVAL;
430     }
431     gain_cfg[0] = 0;
432     gain_cfg[1] = app_type;
433     gain_cfg[2] = gain[0];
434     gain_cfg[3] = gain[1];
435     ALOGV("%s app_type %d l(%d) r(%d)", __func__,  app_type, gain[0], gain[1]);
436     return mixer_ctl_set_array(ctl, gain_cfg,
437                                sizeof(gain_cfg)/sizeof(gain_cfg[0]));
438 }
439 
440 // this assumes correct app_type and sample_rate fields
441 // have been set for the stream using audio_extn_utils_send_app_type_cfg
audio_extn_utils_send_audio_calibration(struct audio_device * adev,struct audio_usecase * usecase)442 void audio_extn_utils_send_audio_calibration(struct audio_device *adev,
443                                              struct audio_usecase *usecase)
444 {
445     int type = usecase->type;
446     int app_type = 0;
447 
448     if (type == PCM_PLAYBACK && usecase->stream.out != NULL) {
449         struct stream_out *out = usecase->stream.out;
450         ALOGV("%s send cal for app_type %d, rate %d", __func__,
451               out->app_type_cfg.app_type,
452               out->app_type_cfg.sample_rate);
453         platform_send_audio_calibration_v2(adev->platform, usecase,
454                                            out->app_type_cfg.app_type,
455                                            out->app_type_cfg.sample_rate);
456     } else if (type == PCM_CAPTURE && usecase->stream.in != NULL) {
457         struct stream_in *in = usecase->stream.in;
458         ALOGV("%s send cal for capture app_type %d, rate %d", __func__,
459               in->app_type_cfg.app_type,
460               in->app_type_cfg.sample_rate);
461         platform_send_audio_calibration_v2(adev->platform, usecase,
462                                            in->app_type_cfg.app_type,
463                                            in->app_type_cfg.sample_rate);
464     } else {
465         /* when app type is default. the sample rate is not used to send cal */
466         platform_get_default_app_type_v2(adev->platform, type, &app_type);
467         platform_send_audio_calibration_v2(adev->platform, usecase, app_type,
468                                            48000);
469     }
470 }
471 
472 #define MAX_SND_CARD 8
473 #define RETRY_US 500000
474 #define RETRY_NUMBER 10
475 
476 #define min(a, b) ((a) < (b) ? (a) : (b))
477 
478 static const char *kConfigLocationList[] =
479         {"/odm/etc", "/vendor/etc", "/system/etc"};
480 static const int kConfigLocationListSize =
481         (sizeof(kConfigLocationList) / sizeof(kConfigLocationList[0]));
482 
audio_extn_utils_resolve_config_file(char file_name[MIXER_PATH_MAX_LENGTH])483 bool audio_extn_utils_resolve_config_file(char file_name[MIXER_PATH_MAX_LENGTH])
484 {
485     char full_config_path[MIXER_PATH_MAX_LENGTH];
486     for (int i = 0; i < kConfigLocationListSize; i++) {
487         snprintf(full_config_path,
488                  MIXER_PATH_MAX_LENGTH,
489                  "%s/%s",
490                  kConfigLocationList[i],
491                  file_name);
492         if (F_OK == access(full_config_path, 0)) {
493             strcpy(file_name, full_config_path);
494             return true;
495         }
496     }
497     return false;
498 }
499 
500 /* platform_info_file should be size 'MIXER_PATH_MAX_LENGTH' */
audio_extn_utils_get_platform_info(const char * snd_card_name,char * platform_info_file)501 int audio_extn_utils_get_platform_info(const char* snd_card_name, char* platform_info_file)
502 {
503     if (NULL == snd_card_name) {
504         return -1;
505     }
506 
507     struct snd_card_split *snd_split_handle = NULL;
508     int ret = 0;
509     audio_extn_set_snd_card_split(snd_card_name);
510     snd_split_handle = audio_extn_get_snd_card_split();
511 
512     snprintf(platform_info_file, MIXER_PATH_MAX_LENGTH, "%s_%s_%s.xml",
513                      PLATFORM_INFO_XML_BASE_STRING, snd_split_handle->snd_card,
514                      snd_split_handle->form_factor);
515 
516     if (!audio_extn_utils_resolve_config_file(platform_info_file)) {
517         memset(platform_info_file, 0, MIXER_PATH_MAX_LENGTH);
518         snprintf(platform_info_file, MIXER_PATH_MAX_LENGTH, "%s_%s.xml",
519                      PLATFORM_INFO_XML_BASE_STRING, snd_split_handle->snd_card);
520 
521         if (!audio_extn_utils_resolve_config_file(platform_info_file)) {
522             memset(platform_info_file, 0, MIXER_PATH_MAX_LENGTH);
523             strlcpy(platform_info_file, PLATFORM_INFO_XML_PATH, MIXER_PATH_MAX_LENGTH);
524             ret = audio_extn_utils_resolve_config_file(platform_info_file) ? 0 : -1;
525         }
526     }
527 
528     return ret;
529 }
530 
audio_extn_utils_get_snd_card_num()531 int audio_extn_utils_get_snd_card_num()
532 {
533 
534     void *hw_info = NULL;
535     struct mixer *mixer = NULL;
536     int retry_num = 0;
537     int snd_card_num = 0;
538     const char* snd_card_name = NULL;
539     char platform_info_file[MIXER_PATH_MAX_LENGTH]= {0};
540 
541     struct acdb_platform_data *my_data = calloc(1, sizeof(struct acdb_platform_data));
542 
543     bool card_verifed[MAX_SND_CARD] = {0};
544     const int retry_limit = property_get_int32(
545         "vendor.audio.snd_card.open.retries",
546         property_get_int32("audio.snd_card.open.retries", RETRY_NUMBER));
547 
548     for (;;) {
549         if (snd_card_num >= MAX_SND_CARD) {
550             if (retry_num++ >= retry_limit) {
551                 ALOGE("%s: Unable to find correct sound card, aborting.", __func__);
552                 snd_card_num = -1;
553                 goto done;
554             }
555 
556             snd_card_num = 0;
557             usleep(RETRY_US);
558             continue;
559         }
560 
561         if (card_verifed[snd_card_num]) {
562             ++snd_card_num;
563             continue;
564         }
565 
566         mixer = mixer_open(snd_card_num);
567 
568         if (!mixer) {
569             ALOGE("%s: Unable to open the mixer card: %d", __func__,
570                snd_card_num);
571             ++snd_card_num;
572             continue;
573         }
574 
575         card_verifed[snd_card_num] = true;
576 
577         snd_card_name = mixer_get_name(mixer);
578         hw_info = hw_info_init(snd_card_name);
579 
580         if (audio_extn_utils_get_platform_info(snd_card_name, platform_info_file) < 0) {
581             ALOGE("Failed to find platform_info_file");
582             goto cleanup;
583         }
584 
585         /* Initialize snd card name specific ids and/or backends*/
586         if (platform_info_init(platform_info_file, my_data, false,
587                                &acdb_set_parameters) < 0) {
588             ALOGE("Failed to find platform_info_file");
589             goto cleanup;
590         }
591 
592         /* validate the sound card name
593          * my_data->snd_card_name can contain
594          *     <a> complete sound card name, i.e. <device>-<codec>-<form_factor>-snd-card
595          *         example: msm8994-tomtom-mtp-snd-card
596          *     <b> or sub string of the card name, i.e. <device>-<codec>
597          *         example: msm8994-tomtom
598          * snd_card_name is truncated to 32 charaters as per mixer_get_name() implementation
599          * so use min of my_data->snd_card_name and snd_card_name length for comparison
600          */
601 
602         if (my_data->snd_card_name != NULL &&
603                 strncmp(snd_card_name, my_data->snd_card_name,
604                         min(strlen(snd_card_name), strlen(my_data->snd_card_name))) != 0) {
605             ALOGI("%s: found valid sound card %s, but not primary sound card %s",
606                    __func__, snd_card_name, my_data->snd_card_name);
607             goto cleanup;
608         }
609 
610         ALOGI("%s: found sound card %s, primary sound card expected is %s",
611               __func__, snd_card_name, my_data->snd_card_name);
612         break;
613   cleanup:
614         ++snd_card_num;
615         mixer_close(mixer);
616         mixer = NULL;
617         hw_info_deinit(hw_info);
618         hw_info = NULL;
619     }
620 
621 done:
622     mixer_close(mixer);
623     hw_info_deinit(hw_info);
624 
625     if (my_data)
626         free(my_data);
627 
628     return snd_card_num;
629 }
630