• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <cutils/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     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;
161         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
165         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) {
171             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);
175             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) {
189             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);
192             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) {
199             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);
202             if (rc < 0)
203                 goto exit_send_app_type_cfg;
204         }
205     }
206 
207     rc = 0;
208 exit_send_app_type_cfg:
209     return rc;
210 }
211 
212 
derive_capture_app_type_cfg(struct audio_device * adev,struct audio_usecase * usecase,int * app_type,int * sample_rate)213 static int derive_capture_app_type_cfg(struct audio_device *adev,
214                                        struct audio_usecase *usecase,
215                                        int *app_type,
216                                        int *sample_rate)
217 {
218     if (usecase->stream.in == NULL) {
219         return -1;
220     }
221     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;
225     if (audio_is_usb_in_device(in->device)) {
226         platform_check_and_update_copp_sample_rate(adev->platform,
227                                                    usecase->in_snd_device,
228                                                    in->sample_rate,
229                                                    sample_rate);
230     }
231 
232     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) {
235         platform_get_app_type_v2(adev->platform,
236                                  PCM_CAPTURE,
237                                  app_type_cfg->mode,
238                                  16,
239                                  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) {
243         platform_get_app_type_v2(adev->platform,
244                                  PCM_CAPTURE,
245                                  app_type_cfg->mode,
246                                  24,
247                                  app_type_cfg->sample_rate,
248                                  app_type);
249     } else if (in->format == AUDIO_FORMAT_PCM_32_BIT) {
250         platform_get_app_type_v2(adev->platform,
251                                  PCM_CAPTURE,
252                                  app_type_cfg->mode,
253                                  32,
254                                  app_type_cfg->sample_rate,
255                                  app_type);
256     } else {
257         ALOGE("%s bad format\n", __func__);
258         return -1;
259     }
260 
261     app_type_cfg->app_type = *app_type;
262     app_type_cfg->sample_rate = *sample_rate;
263     return 0;
264 }
265 
derive_playback_app_type_cfg(struct audio_device * adev,struct audio_usecase * usecase,int * app_type,int * sample_rate)266 static int derive_playback_app_type_cfg(struct audio_device *adev,
267                                         struct audio_usecase *usecase,
268                                         int *app_type,
269                                         int *sample_rate)
270 {
271     if (usecase->stream.out == NULL) {
272         return -1;
273     }
274     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
281     if (audio_is_usb_out_device(out->devices)) {
282         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)) {
290         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);
297     } 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 
derive_acdb_dev_id(struct audio_device * adev __unused,struct audio_usecase * usecase)329 static 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) {
336         return platform_get_snd_device_acdb_id(usecase->out_snd_device);
337     } else if(usecase->type == PCM_CAPTURE) {
338         return platform_get_snd_device_acdb_id(usecase->in_snd_device);
339     }
340     return -1;
341 }
342 
audio_extn_utils_send_app_type_cfg(struct audio_device * adev,struct audio_usecase * usecase)343 int audio_extn_utils_send_app_type_cfg(struct audio_device *adev,
344                                        struct audio_usecase *usecase)
345 {
346     int len = 0;
347     int sample_rate;
348     int app_type;
349     int acdb_dev_id;
350     size_t app_type_cfg[MAX_LENGTH_MIXER_CONTROL_IN_INT] = {0};
351     char mixer_ctl_name[MAX_LENGTH_MIXER_CONTROL_IN_INT] = {0};
352     int pcm_device_id;
353     struct mixer_ctl *ctl;
354     int ret;
355 
356     if (usecase->type == PCM_HFP_CALL) {
357         return audio_extn_utils_send_app_type_cfg_hfp(adev, usecase);
358     }
359 
360     if (!platform_supports_app_type_cfg())
361         return -1;
362 
363     if (usecase->type == PCM_PLAYBACK) {
364         ret = derive_playback_app_type_cfg(adev,
365                                            usecase,
366                                            &app_type,
367                                            &sample_rate);
368     } else if (usecase->type == PCM_CAPTURE) {
369         ret = derive_capture_app_type_cfg(adev,
370                                           usecase,
371                                           &app_type,
372                                           &sample_rate);
373     } else {
374         ALOGE("%s: Invalid uc type : 0x%x", __func__, usecase->type);
375         return -1;
376     }
377 
378     if (ret < 0) {
379         ALOGE("%s: Failed to derive app_type for uc type : 0x%x", __func__,
380               usecase->type);
381         return -1;
382     }
383 
384     acdb_dev_id = derive_acdb_dev_id(adev, usecase);
385     if (acdb_dev_id <= 0) {
386         ALOGE("%s: Couldn't get the acdb dev id", __func__);
387         return -1;
388     }
389 
390     pcm_device_id = platform_get_pcm_device_id(usecase->id, usecase->type);
391     set_stream_app_type_mixer_ctrl(adev, pcm_device_id, app_type, acdb_dev_id,
392                                    sample_rate,
393                                    usecase->type,
394                                    usecase->type == PCM_PLAYBACK ? usecase->out_snd_device :
395                                                                    usecase->in_snd_device);
396     return 0;
397 }
398 
audio_extn_utils_send_app_type_gain(struct audio_device * adev,int app_type,int * gain)399 int audio_extn_utils_send_app_type_gain(struct audio_device *adev,
400                                         int app_type,
401                                         int *gain)
402 {
403     int gain_cfg[4];
404     const char *mixer_ctl_name = "App Type Gain";
405     struct mixer_ctl *ctl;
406     ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
407     if (!ctl) {
408         ALOGE("%s: Could not get volume ctl mixer %s", __func__,
409               mixer_ctl_name);
410         return -EINVAL;
411     }
412     gain_cfg[0] = 0;
413     gain_cfg[1] = app_type;
414     gain_cfg[2] = gain[0];
415     gain_cfg[3] = gain[1];
416     ALOGV("%s app_type %d l(%d) r(%d)", __func__,  app_type, gain[0], gain[1]);
417     return mixer_ctl_set_array(ctl, gain_cfg,
418                                sizeof(gain_cfg)/sizeof(gain_cfg[0]));
419 }
420 
421 // this assumes correct app_type and sample_rate fields
422 // 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)423 void audio_extn_utils_send_audio_calibration(struct audio_device *adev,
424                                              struct audio_usecase *usecase)
425 {
426     int type = usecase->type;
427     int app_type = 0;
428 
429     if (type == PCM_PLAYBACK && usecase->stream.out != NULL) {
430         struct stream_out *out = usecase->stream.out;
431         ALOGV("%s send cal for app_type %d, rate %d", __func__,
432               out->app_type_cfg.app_type,
433               out->app_type_cfg.sample_rate);
434         platform_send_audio_calibration_v2(adev->platform, usecase,
435                                            out->app_type_cfg.app_type,
436                                            out->app_type_cfg.sample_rate);
437     } else if (type == PCM_CAPTURE && usecase->stream.in != NULL) {
438         struct stream_in *in = usecase->stream.in;
439         ALOGV("%s send cal for capture app_type %d, rate %d", __func__,
440               in->app_type_cfg.app_type,
441               in->app_type_cfg.sample_rate);
442         platform_send_audio_calibration_v2(adev->platform, usecase,
443                                            in->app_type_cfg.app_type,
444                                            in->app_type_cfg.sample_rate);
445     } else {
446         /* when app type is default. the sample rate is not used to send cal */
447         platform_get_default_app_type_v2(adev->platform, type, &app_type);
448         platform_send_audio_calibration_v2(adev->platform, usecase, app_type,
449                                            48000);
450     }
451 }
452 
453 #define MAX_SND_CARD 8
454 #define RETRY_US 500000
455 #define RETRY_NUMBER 10
456 
457 #define min(a, b) ((a) < (b) ? (a) : (b))
458 
459 static const char *kConfigLocationList[] =
460         {"/odm/etc", "/vendor/etc", "/system/etc"};
461 static const int kConfigLocationListSize =
462         (sizeof(kConfigLocationList) / sizeof(kConfigLocationList[0]));
463 
audio_extn_utils_resolve_config_file(char file_name[MIXER_PATH_MAX_LENGTH])464 bool audio_extn_utils_resolve_config_file(char file_name[MIXER_PATH_MAX_LENGTH])
465 {
466     char full_config_path[MIXER_PATH_MAX_LENGTH];
467     for (int i = 0; i < kConfigLocationListSize; i++) {
468         snprintf(full_config_path,
469                  MIXER_PATH_MAX_LENGTH,
470                  "%s/%s",
471                  kConfigLocationList[i],
472                  file_name);
473         if (F_OK == access(full_config_path, 0)) {
474             strcpy(file_name, full_config_path);
475             return true;
476         }
477     }
478     return false;
479 }
480 
481 /* 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)482 int audio_extn_utils_get_platform_info(const char* snd_card_name, char* platform_info_file)
483 {
484     if (NULL == snd_card_name) {
485         return -1;
486     }
487 
488     struct snd_card_split *snd_split_handle = NULL;
489     int ret = 0;
490     audio_extn_set_snd_card_split(snd_card_name);
491     snd_split_handle = audio_extn_get_snd_card_split();
492 
493     snprintf(platform_info_file, MIXER_PATH_MAX_LENGTH, "%s_%s_%s.xml",
494                      PLATFORM_INFO_XML_BASE_STRING, snd_split_handle->snd_card,
495                      snd_split_handle->form_factor);
496 
497     if (!audio_extn_utils_resolve_config_file(platform_info_file)) {
498         memset(platform_info_file, 0, MIXER_PATH_MAX_LENGTH);
499         snprintf(platform_info_file, MIXER_PATH_MAX_LENGTH, "%s_%s.xml",
500                      PLATFORM_INFO_XML_BASE_STRING, snd_split_handle->snd_card);
501 
502         if (!audio_extn_utils_resolve_config_file(platform_info_file)) {
503             memset(platform_info_file, 0, MIXER_PATH_MAX_LENGTH);
504             strlcpy(platform_info_file, PLATFORM_INFO_XML_PATH, MIXER_PATH_MAX_LENGTH);
505             ret = audio_extn_utils_resolve_config_file(platform_info_file) ? 0 : -1;
506         }
507     }
508 
509     return ret;
510 }
511 
audio_extn_utils_get_snd_card_num()512 int audio_extn_utils_get_snd_card_num()
513 {
514 
515     void *hw_info = NULL;
516     struct mixer *mixer = NULL;
517     int retry_num = 0;
518     int snd_card_num = 0;
519     const char* snd_card_name = NULL;
520     char platform_info_file[MIXER_PATH_MAX_LENGTH]= {0};
521 
522     struct acdb_platform_data *my_data = calloc(1, sizeof(struct acdb_platform_data));
523 
524     bool card_verifed[MAX_SND_CARD] = {0};
525     const int retry_limit = property_get_int32("audio.snd_card.open.retries", RETRY_NUMBER);
526 
527     for (;;) {
528         if (snd_card_num >= MAX_SND_CARD) {
529             if (retry_num++ >= retry_limit) {
530                 ALOGE("%s: Unable to find correct sound card, aborting.", __func__);
531                 snd_card_num = -1;
532                 goto done;
533             }
534 
535             snd_card_num = 0;
536             usleep(RETRY_US);
537             continue;
538         }
539 
540         if (card_verifed[snd_card_num]) {
541             ++snd_card_num;
542             continue;
543         }
544 
545         mixer = mixer_open(snd_card_num);
546 
547         if (!mixer) {
548             ALOGE("%s: Unable to open the mixer card: %d", __func__,
549                snd_card_num);
550             ++snd_card_num;
551             continue;
552         }
553 
554         card_verifed[snd_card_num] = true;
555 
556         snd_card_name = mixer_get_name(mixer);
557         hw_info = hw_info_init(snd_card_name);
558 
559         if (audio_extn_utils_get_platform_info(snd_card_name, platform_info_file) < 0) {
560             ALOGE("Failed to find platform_info_file");
561             goto cleanup;
562         }
563 
564         /* Initialize snd card name specific ids and/or backends*/
565         if (snd_card_info_init(platform_info_file, my_data,
566                                &acdb_set_parameters) < 0) {
567             ALOGE("Failed to find platform_info_file");
568             goto cleanup;
569         }
570 
571         /* validate the sound card name
572          * my_data->snd_card_name can contain
573          *     <a> complete sound card name, i.e. <device>-<codec>-<form_factor>-snd-card
574          *         example: msm8994-tomtom-mtp-snd-card
575          *     <b> or sub string of the card name, i.e. <device>-<codec>
576          *         example: msm8994-tomtom
577          * snd_card_name is truncated to 32 charaters as per mixer_get_name() implementation
578          * so use min of my_data->snd_card_name and snd_card_name length for comparison
579          */
580 
581         if (my_data->snd_card_name != NULL &&
582                 strncmp(snd_card_name, my_data->snd_card_name,
583                         min(strlen(snd_card_name), strlen(my_data->snd_card_name))) != 0) {
584             ALOGI("%s: found valid sound card %s, but not primary sound card %s",
585                    __func__, snd_card_name, my_data->snd_card_name);
586             goto cleanup;
587         }
588 
589         ALOGI("%s: found sound card %s, primary sound card expected is %s",
590               __func__, snd_card_name, my_data->snd_card_name);
591         break;
592   cleanup:
593         ++snd_card_num;
594         mixer_close(mixer);
595         mixer = NULL;
596         hw_info_deinit(hw_info);
597         hw_info = NULL;
598     }
599 
600 done:
601     mixer_close(mixer);
602     hw_info_deinit(hw_info);
603 
604     if (my_data)
605         free(my_data);
606 
607     return snd_card_num;
608 }
609