1e3b9956373beb54b67957675b6e6d99fd3280edaYamit Mehta/*
2e3b9956373beb54b67957675b6e6d99fd3280edaYamit Mehta * Copyright (C) 2016 The Android Open Source Project
3e3b9956373beb54b67957675b6e6d99fd3280edaYamit Mehta *
4e3b9956373beb54b67957675b6e6d99fd3280edaYamit Mehta * Licensed under the Apache License, Version 2.0 (the "License");
5e3b9956373beb54b67957675b6e6d99fd3280edaYamit Mehta * you may not use this file except in compliance with the License.
6e3b9956373beb54b67957675b6e6d99fd3280edaYamit Mehta * You may obtain a copy of the License at
7e3b9956373beb54b67957675b6e6d99fd3280edaYamit Mehta *
8e3b9956373beb54b67957675b6e6d99fd3280edaYamit Mehta *      http://www.apache.org/licenses/LICENSE-2.0
9e3b9956373beb54b67957675b6e6d99fd3280edaYamit Mehta *
10e3b9956373beb54b67957675b6e6d99fd3280edaYamit Mehta * Unless required by applicable law or agreed to in writing, software
11e3b9956373beb54b67957675b6e6d99fd3280edaYamit Mehta * distributed under the License is distributed on an "AS IS" BASIS,
12e3b9956373beb54b67957675b6e6d99fd3280edaYamit Mehta * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13e3b9956373beb54b67957675b6e6d99fd3280edaYamit Mehta * See the License for the specific language governing permissions and
14e3b9956373beb54b67957675b6e6d99fd3280edaYamit Mehta * limitations under the License.
15e3b9956373beb54b67957675b6e6d99fd3280edaYamit Mehta */
16e3b9956373beb54b67957675b6e6d99fd3280edaYamit Mehta
17e3b9956373beb54b67957675b6e6d99fd3280edaYamit Mehta#define LOG_TAG "audio_hw_utils"
18e3b9956373beb54b67957675b6e6d99fd3280edaYamit Mehta//#define LOG_NDEBUG 0
19e3b9956373beb54b67957675b6e6d99fd3280edaYamit Mehta
20e3b9956373beb54b67957675b6e6d99fd3280edaYamit Mehta#include <errno.h>
21e3b9956373beb54b67957675b6e6d99fd3280edaYamit Mehta#include <cutils/properties.h>
22e3b9956373beb54b67957675b6e6d99fd3280edaYamit Mehta#include <cutils/config_utils.h>
23e3b9956373beb54b67957675b6e6d99fd3280edaYamit Mehta#include <stdlib.h>
24e3b9956373beb54b67957675b6e6d99fd3280edaYamit Mehta#include <dlfcn.h>
256431fe63703982df8e83644a168c7432e3fd855cJiyong Park#include <unistd.h>
26e3b9956373beb54b67957675b6e6d99fd3280edaYamit Mehta#include <cutils/str_parms.h>
27e6e2d441c567d5da185b787d6c10ca2c8b36a694Haynes Mathew George#include <log/log.h>
28e3b9956373beb54b67957675b6e6d99fd3280edaYamit Mehta#include <cutils/misc.h>
29e3b9956373beb54b67957675b6e6d99fd3280edaYamit Mehta
300fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta#include "acdb.h"
31e3b9956373beb54b67957675b6e6d99fd3280edaYamit Mehta#include "audio_hw.h"
32e3b9956373beb54b67957675b6e6d99fd3280edaYamit Mehta#include "platform.h"
33e3b9956373beb54b67957675b6e6d99fd3280edaYamit Mehta#include "platform_api.h"
34e3b9956373beb54b67957675b6e6d99fd3280edaYamit Mehta#include "audio_extn.h"
35e3b9956373beb54b67957675b6e6d99fd3280edaYamit Mehta
36e3b9956373beb54b67957675b6e6d99fd3280edaYamit Mehta#define MAX_LENGTH_MIXER_CONTROL_IN_INT 128
37e3b9956373beb54b67957675b6e6d99fd3280edaYamit Mehta
38a68fea653241619e8b4b5ad5f21a2415a03a06dbvivek mehtastatic int set_stream_app_type_mixer_ctrl(struct audio_device *adev,
39a68fea653241619e8b4b5ad5f21a2415a03a06dbvivek mehta                                          int pcm_device_id, int app_type,
40a68fea653241619e8b4b5ad5f21a2415a03a06dbvivek mehta                                          int acdb_dev_id, int sample_rate,
41a68fea653241619e8b4b5ad5f21a2415a03a06dbvivek mehta                                          int stream_type,
42a68fea653241619e8b4b5ad5f21a2415a03a06dbvivek mehta                                          snd_device_t snd_device)
43e3b9956373beb54b67957675b6e6d99fd3280edaYamit Mehta{
44e3b9956373beb54b67957675b6e6d99fd3280edaYamit Mehta
45e3b9956373beb54b67957675b6e6d99fd3280edaYamit Mehta    char mixer_ctl_name[MAX_LENGTH_MIXER_CONTROL_IN_INT];
46e3b9956373beb54b67957675b6e6d99fd3280edaYamit Mehta    struct mixer_ctl *ctl;
47e3b9956373beb54b67957675b6e6d99fd3280edaYamit Mehta    int app_type_cfg[MAX_LENGTH_MIXER_CONTROL_IN_INT], len = 0, rc = 0;
48a68fea653241619e8b4b5ad5f21a2415a03a06dbvivek mehta    int snd_device_be_idx = -1;
49e3b9956373beb54b67957675b6e6d99fd3280edaYamit Mehta
50e3b9956373beb54b67957675b6e6d99fd3280edaYamit Mehta    if (stream_type == PCM_PLAYBACK) {
51e3b9956373beb54b67957675b6e6d99fd3280edaYamit Mehta        snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
52e3b9956373beb54b67957675b6e6d99fd3280edaYamit Mehta             "Audio Stream %d App Type Cfg", pcm_device_id);
53e3b9956373beb54b67957675b6e6d99fd3280edaYamit Mehta    } else if (stream_type == PCM_CAPTURE) {
54e3b9956373beb54b67957675b6e6d99fd3280edaYamit Mehta        snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
55e3b9956373beb54b67957675b6e6d99fd3280edaYamit Mehta             "Audio Stream Capture %d App Type Cfg", pcm_device_id);
56e3b9956373beb54b67957675b6e6d99fd3280edaYamit Mehta    }
57e3b9956373beb54b67957675b6e6d99fd3280edaYamit Mehta
58e3b9956373beb54b67957675b6e6d99fd3280edaYamit Mehta    ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
59e3b9956373beb54b67957675b6e6d99fd3280edaYamit Mehta    if (!ctl) {
60e3b9956373beb54b67957675b6e6d99fd3280edaYamit Mehta        ALOGE("%s: Could not get ctl for mixer cmd - %s",
61e3b9956373beb54b67957675b6e6d99fd3280edaYamit Mehta             __func__, mixer_ctl_name);
62e3b9956373beb54b67957675b6e6d99fd3280edaYamit Mehta        rc = -EINVAL;
63e3b9956373beb54b67957675b6e6d99fd3280edaYamit Mehta        goto exit;
64e3b9956373beb54b67957675b6e6d99fd3280edaYamit Mehta    }
65e3b9956373beb54b67957675b6e6d99fd3280edaYamit Mehta    app_type_cfg[len++] = app_type;
66e3b9956373beb54b67957675b6e6d99fd3280edaYamit Mehta    app_type_cfg[len++] = acdb_dev_id;
67e3b9956373beb54b67957675b6e6d99fd3280edaYamit Mehta    app_type_cfg[len++] = sample_rate;
68a68fea653241619e8b4b5ad5f21a2415a03a06dbvivek mehta
69a68fea653241619e8b4b5ad5f21a2415a03a06dbvivek mehta    snd_device_be_idx = platform_get_snd_device_backend_index(snd_device);
70a68fea653241619e8b4b5ad5f21a2415a03a06dbvivek mehta    if (snd_device_be_idx > 0)
71a68fea653241619e8b4b5ad5f21a2415a03a06dbvivek mehta        app_type_cfg[len++] = snd_device_be_idx;
72a68fea653241619e8b4b5ad5f21a2415a03a06dbvivek mehta    ALOGV("%s: stream type %d app_type %d, acdb_dev_id %d "
73a68fea653241619e8b4b5ad5f21a2415a03a06dbvivek mehta          "sample rate %d, snd_device_be_idx %d",
74a68fea653241619e8b4b5ad5f21a2415a03a06dbvivek mehta          __func__, stream_type, app_type, acdb_dev_id, sample_rate,
75a68fea653241619e8b4b5ad5f21a2415a03a06dbvivek mehta          snd_device_be_idx);
76e3b9956373beb54b67957675b6e6d99fd3280edaYamit Mehta    mixer_ctl_set_array(ctl, app_type_cfg, len);
77e3b9956373beb54b67957675b6e6d99fd3280edaYamit Mehta
78e3b9956373beb54b67957675b6e6d99fd3280edaYamit Mehtaexit:
79e3b9956373beb54b67957675b6e6d99fd3280edaYamit Mehta    return rc;
80e3b9956373beb54b67957675b6e6d99fd3280edaYamit Mehta}
81e3b9956373beb54b67957675b6e6d99fd3280edaYamit Mehta
82e3b9956373beb54b67957675b6e6d99fd3280edaYamit Mehtavoid audio_extn_utils_send_default_app_type_cfg(void *platform, struct mixer *mixer)
83e3b9956373beb54b67957675b6e6d99fd3280edaYamit Mehta{
84e3b9956373beb54b67957675b6e6d99fd3280edaYamit Mehta    int app_type_cfg[MAX_LENGTH_MIXER_CONTROL_IN_INT] = {-1};
85e3b9956373beb54b67957675b6e6d99fd3280edaYamit Mehta    int length = 0, app_type = 0,rc = 0;
86e3b9956373beb54b67957675b6e6d99fd3280edaYamit Mehta    struct mixer_ctl *ctl = NULL;
87e3b9956373beb54b67957675b6e6d99fd3280edaYamit Mehta    const char *mixer_ctl_name = "App Type Config";
88e3b9956373beb54b67957675b6e6d99fd3280edaYamit Mehta
89e3b9956373beb54b67957675b6e6d99fd3280edaYamit Mehta    ctl = mixer_get_ctl_by_name(mixer, mixer_ctl_name);
90e3b9956373beb54b67957675b6e6d99fd3280edaYamit Mehta    if (!ctl) {
91e3b9956373beb54b67957675b6e6d99fd3280edaYamit Mehta        ALOGE("%s: Could not get ctl for mixer cmd - %s",__func__, mixer_ctl_name);
92e3b9956373beb54b67957675b6e6d99fd3280edaYamit Mehta        return;
93e3b9956373beb54b67957675b6e6d99fd3280edaYamit Mehta    }
94e3b9956373beb54b67957675b6e6d99fd3280edaYamit Mehta    rc = platform_get_default_app_type_v2(platform, PCM_PLAYBACK, &app_type);
95e3b9956373beb54b67957675b6e6d99fd3280edaYamit Mehta    if (rc == 0) {
96e3b9956373beb54b67957675b6e6d99fd3280edaYamit Mehta        app_type_cfg[length++] = 1;
97e3b9956373beb54b67957675b6e6d99fd3280edaYamit Mehta        app_type_cfg[length++] = app_type;
98e3b9956373beb54b67957675b6e6d99fd3280edaYamit Mehta        app_type_cfg[length++] = 48000;
99e3b9956373beb54b67957675b6e6d99fd3280edaYamit Mehta        app_type_cfg[length++] = 16;
100e3b9956373beb54b67957675b6e6d99fd3280edaYamit Mehta        mixer_ctl_set_array(ctl, app_type_cfg, length);
101e3b9956373beb54b67957675b6e6d99fd3280edaYamit Mehta    }
102e3b9956373beb54b67957675b6e6d99fd3280edaYamit Mehta    return;
103e3b9956373beb54b67957675b6e6d99fd3280edaYamit Mehta}
104e3b9956373beb54b67957675b6e6d99fd3280edaYamit Mehta
105a68fea653241619e8b4b5ad5f21a2415a03a06dbvivek mehtastatic const char *flags_to_mode(int dir, uint32_t flags)
106a68fea653241619e8b4b5ad5f21a2415a03a06dbvivek mehta{
107a68fea653241619e8b4b5ad5f21a2415a03a06dbvivek mehta    if (dir == 0) {
108a68fea653241619e8b4b5ad5f21a2415a03a06dbvivek mehta        if (flags & AUDIO_OUTPUT_FLAG_VOIP_RX) {
109a68fea653241619e8b4b5ad5f21a2415a03a06dbvivek mehta            return "voip";
110a68fea653241619e8b4b5ad5f21a2415a03a06dbvivek mehta        }
111a68fea653241619e8b4b5ad5f21a2415a03a06dbvivek mehta    } else if (dir == 1) {
112a68fea653241619e8b4b5ad5f21a2415a03a06dbvivek mehta        if (flags & AUDIO_INPUT_FLAG_VOIP_TX) {
113a68fea653241619e8b4b5ad5f21a2415a03a06dbvivek mehta            return "voip";
114a68fea653241619e8b4b5ad5f21a2415a03a06dbvivek mehta        }
115a68fea653241619e8b4b5ad5f21a2415a03a06dbvivek mehta    }
116a68fea653241619e8b4b5ad5f21a2415a03a06dbvivek mehta    return "default";
117a68fea653241619e8b4b5ad5f21a2415a03a06dbvivek mehta}
118a68fea653241619e8b4b5ad5f21a2415a03a06dbvivek mehta
119e5ff0fc8e7126cdd2535641e9463ee8065b6149eHaynes Mathew Georgestatic int audio_extn_utils_send_app_type_cfg_hfp(struct audio_device *adev,
120e3b9956373beb54b67957675b6e6d99fd3280edaYamit Mehta                                       struct audio_usecase *usecase)
121e3b9956373beb54b67957675b6e6d99fd3280edaYamit Mehta{
122e3b9956373beb54b67957675b6e6d99fd3280edaYamit Mehta    struct mixer_ctl *ctl;
123e3b9956373beb54b67957675b6e6d99fd3280edaYamit Mehta    int pcm_device_id, acdb_dev_id = 0, snd_device = usecase->out_snd_device;
124e3b9956373beb54b67957675b6e6d99fd3280edaYamit Mehta    int32_t sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
125e3b9956373beb54b67957675b6e6d99fd3280edaYamit Mehta    int app_type = 0, rc = 0;
126e3b9956373beb54b67957675b6e6d99fd3280edaYamit Mehta
127e3b9956373beb54b67957675b6e6d99fd3280edaYamit Mehta    ALOGV("%s", __func__);
128e3b9956373beb54b67957675b6e6d99fd3280edaYamit Mehta
129e3b9956373beb54b67957675b6e6d99fd3280edaYamit Mehta    if (usecase->type != PCM_HFP_CALL) {
130e3b9956373beb54b67957675b6e6d99fd3280edaYamit Mehta        ALOGV("%s: not a playback or HFP path, no need to cfg app type", __func__);
131e3b9956373beb54b67957675b6e6d99fd3280edaYamit Mehta        rc = 0;
132e3b9956373beb54b67957675b6e6d99fd3280edaYamit Mehta        goto exit_send_app_type_cfg;
133e3b9956373beb54b67957675b6e6d99fd3280edaYamit Mehta    }
134e3b9956373beb54b67957675b6e6d99fd3280edaYamit Mehta    if ((usecase->id != USECASE_AUDIO_HFP_SCO) &&
135e3b9956373beb54b67957675b6e6d99fd3280edaYamit Mehta        (usecase->id != USECASE_AUDIO_HFP_SCO_WB)) {
136e3b9956373beb54b67957675b6e6d99fd3280edaYamit Mehta        ALOGV("%s: a playback path where app type cfg is not required", __func__);
137e3b9956373beb54b67957675b6e6d99fd3280edaYamit Mehta        rc = 0;
138e3b9956373beb54b67957675b6e6d99fd3280edaYamit Mehta        goto exit_send_app_type_cfg;
139e3b9956373beb54b67957675b6e6d99fd3280edaYamit Mehta    }
140e3b9956373beb54b67957675b6e6d99fd3280edaYamit Mehta
141e3b9956373beb54b67957675b6e6d99fd3280edaYamit Mehta    snd_device = usecase->out_snd_device;
142e3b9956373beb54b67957675b6e6d99fd3280edaYamit Mehta    pcm_device_id = platform_get_pcm_device_id(usecase->id, PCM_PLAYBACK);
143e3b9956373beb54b67957675b6e6d99fd3280edaYamit Mehta
144e3b9956373beb54b67957675b6e6d99fd3280edaYamit Mehta    acdb_dev_id = platform_get_snd_device_acdb_id(snd_device);
145e3b9956373beb54b67957675b6e6d99fd3280edaYamit Mehta    if (acdb_dev_id < 0) {
146e3b9956373beb54b67957675b6e6d99fd3280edaYamit Mehta        ALOGE("%s: Couldn't get the acdb dev id", __func__);
147e3b9956373beb54b67957675b6e6d99fd3280edaYamit Mehta        rc = -EINVAL;
148e3b9956373beb54b67957675b6e6d99fd3280edaYamit Mehta        goto exit_send_app_type_cfg;
149e3b9956373beb54b67957675b6e6d99fd3280edaYamit Mehta    }
150e3b9956373beb54b67957675b6e6d99fd3280edaYamit Mehta
151e3b9956373beb54b67957675b6e6d99fd3280edaYamit Mehta    if (usecase->type == PCM_HFP_CALL) {
152e3b9956373beb54b67957675b6e6d99fd3280edaYamit Mehta
153e3b9956373beb54b67957675b6e6d99fd3280edaYamit Mehta        /* config HFP session:1 playback path */
154e3b9956373beb54b67957675b6e6d99fd3280edaYamit Mehta        rc = platform_get_default_app_type_v2(adev->platform, PCM_PLAYBACK, &app_type);
155e3b9956373beb54b67957675b6e6d99fd3280edaYamit Mehta        if (rc < 0)
156e3b9956373beb54b67957675b6e6d99fd3280edaYamit Mehta            goto exit_send_app_type_cfg;
157e3b9956373beb54b67957675b6e6d99fd3280edaYamit Mehta
158e3b9956373beb54b67957675b6e6d99fd3280edaYamit Mehta        sample_rate= CODEC_BACKEND_DEFAULT_SAMPLE_RATE;
159a68fea653241619e8b4b5ad5f21a2415a03a06dbvivek mehta        rc = set_stream_app_type_mixer_ctrl(adev, pcm_device_id, app_type,
160a68fea653241619e8b4b5ad5f21a2415a03a06dbvivek mehta                                            acdb_dev_id, sample_rate,
161a68fea653241619e8b4b5ad5f21a2415a03a06dbvivek mehta                                            PCM_PLAYBACK,
162a68fea653241619e8b4b5ad5f21a2415a03a06dbvivek mehta                                            SND_DEVICE_NONE); // use legacy behavior
163e3b9956373beb54b67957675b6e6d99fd3280edaYamit Mehta        if (rc < 0)
164e3b9956373beb54b67957675b6e6d99fd3280edaYamit Mehta            goto exit_send_app_type_cfg;
165e3b9956373beb54b67957675b6e6d99fd3280edaYamit Mehta        /* config HFP session:1 capture path */
166e3b9956373beb54b67957675b6e6d99fd3280edaYamit Mehta        rc = platform_get_default_app_type_v2(adev->platform, PCM_CAPTURE, &app_type);
167e3b9956373beb54b67957675b6e6d99fd3280edaYamit Mehta
168e3b9956373beb54b67957675b6e6d99fd3280edaYamit Mehta        if (rc == 0) {
169a68fea653241619e8b4b5ad5f21a2415a03a06dbvivek mehta            rc = set_stream_app_type_mixer_ctrl(adev, pcm_device_id, app_type,
170a68fea653241619e8b4b5ad5f21a2415a03a06dbvivek mehta                                                acdb_dev_id, sample_rate,
171a68fea653241619e8b4b5ad5f21a2415a03a06dbvivek mehta                                                PCM_CAPTURE,
172a68fea653241619e8b4b5ad5f21a2415a03a06dbvivek mehta                                                SND_DEVICE_NONE);
173e3b9956373beb54b67957675b6e6d99fd3280edaYamit Mehta            if (rc < 0)
174e3b9956373beb54b67957675b6e6d99fd3280edaYamit Mehta                goto exit_send_app_type_cfg;
175e3b9956373beb54b67957675b6e6d99fd3280edaYamit Mehta        }
176e3b9956373beb54b67957675b6e6d99fd3280edaYamit Mehta        /* config HFP session:2 capture path */
177e3b9956373beb54b67957675b6e6d99fd3280edaYamit Mehta        pcm_device_id = HFP_ASM_RX_TX;
178e3b9956373beb54b67957675b6e6d99fd3280edaYamit Mehta        snd_device = usecase->in_snd_device;
179e3b9956373beb54b67957675b6e6d99fd3280edaYamit Mehta        acdb_dev_id = platform_get_snd_device_acdb_id(snd_device);
180e3b9956373beb54b67957675b6e6d99fd3280edaYamit Mehta        if (acdb_dev_id <= 0) {
181e3b9956373beb54b67957675b6e6d99fd3280edaYamit Mehta            ALOGE("%s: Couldn't get the acdb dev id", __func__);
182e3b9956373beb54b67957675b6e6d99fd3280edaYamit Mehta            rc = -EINVAL;
183e3b9956373beb54b67957675b6e6d99fd3280edaYamit Mehta            goto exit_send_app_type_cfg;
184e3b9956373beb54b67957675b6e6d99fd3280edaYamit Mehta        }
185e3b9956373beb54b67957675b6e6d99fd3280edaYamit Mehta        rc = platform_get_default_app_type_v2(adev->platform, PCM_CAPTURE, &app_type);
186e3b9956373beb54b67957675b6e6d99fd3280edaYamit Mehta        if (rc == 0) {
187a68fea653241619e8b4b5ad5f21a2415a03a06dbvivek mehta            rc = set_stream_app_type_mixer_ctrl(adev, pcm_device_id, app_type,
188a68fea653241619e8b4b5ad5f21a2415a03a06dbvivek mehta                                                acdb_dev_id, sample_rate, PCM_CAPTURE,
189a68fea653241619e8b4b5ad5f21a2415a03a06dbvivek mehta                                                SND_DEVICE_NONE);
190e3b9956373beb54b67957675b6e6d99fd3280edaYamit Mehta            if (rc < 0)
191e3b9956373beb54b67957675b6e6d99fd3280edaYamit Mehta                goto exit_send_app_type_cfg;
192e3b9956373beb54b67957675b6e6d99fd3280edaYamit Mehta        }
193e3b9956373beb54b67957675b6e6d99fd3280edaYamit Mehta
194e3b9956373beb54b67957675b6e6d99fd3280edaYamit Mehta        /* config HFP session:2 playback path */
195e3b9956373beb54b67957675b6e6d99fd3280edaYamit Mehta        rc = platform_get_default_app_type_v2(adev->platform, PCM_PLAYBACK, &app_type);
196e3b9956373beb54b67957675b6e6d99fd3280edaYamit Mehta        if (rc == 0) {
197a68fea653241619e8b4b5ad5f21a2415a03a06dbvivek mehta            rc = set_stream_app_type_mixer_ctrl(adev, pcm_device_id, app_type,
198a68fea653241619e8b4b5ad5f21a2415a03a06dbvivek mehta                                acdb_dev_id, sample_rate,
199a68fea653241619e8b4b5ad5f21a2415a03a06dbvivek mehta                                PCM_PLAYBACK, SND_DEVICE_NONE);
200e3b9956373beb54b67957675b6e6d99fd3280edaYamit Mehta            if (rc < 0)
201e3b9956373beb54b67957675b6e6d99fd3280edaYamit Mehta                goto exit_send_app_type_cfg;
202e3b9956373beb54b67957675b6e6d99fd3280edaYamit Mehta        }
203e3b9956373beb54b67957675b6e6d99fd3280edaYamit Mehta    }
204e3b9956373beb54b67957675b6e6d99fd3280edaYamit Mehta
205e3b9956373beb54b67957675b6e6d99fd3280edaYamit Mehta    rc = 0;
206e3b9956373beb54b67957675b6e6d99fd3280edaYamit Mehtaexit_send_app_type_cfg:
207e3b9956373beb54b67957675b6e6d99fd3280edaYamit Mehta    return rc;
208e3b9956373beb54b67957675b6e6d99fd3280edaYamit Mehta}
209e5ff0fc8e7126cdd2535641e9463ee8065b6149eHaynes Mathew George
210a68fea653241619e8b4b5ad5f21a2415a03a06dbvivek mehta
211a68fea653241619e8b4b5ad5f21a2415a03a06dbvivek mehtastatic int derive_capture_app_type_cfg(struct audio_device *adev,
212a68fea653241619e8b4b5ad5f21a2415a03a06dbvivek mehta                                       struct audio_usecase *usecase,
213a68fea653241619e8b4b5ad5f21a2415a03a06dbvivek mehta                                       int *app_type,
214a68fea653241619e8b4b5ad5f21a2415a03a06dbvivek mehta                                       int *sample_rate)
215e5ff0fc8e7126cdd2535641e9463ee8065b6149eHaynes Mathew George{
2162e259979b6459235e527ef8283f28f1f08498b51Mark Urbanus    if (usecase->stream.in == NULL) {
2172e259979b6459235e527ef8283f28f1f08498b51Mark Urbanus        return -1;
2182e259979b6459235e527ef8283f28f1f08498b51Mark Urbanus    }
219a68fea653241619e8b4b5ad5f21a2415a03a06dbvivek mehta    struct stream_in *in = usecase->stream.in;
220a68fea653241619e8b4b5ad5f21a2415a03a06dbvivek mehta    struct stream_app_type_cfg *app_type_cfg = &in->app_type_cfg;
221a68fea653241619e8b4b5ad5f21a2415a03a06dbvivek mehta
222a68fea653241619e8b4b5ad5f21a2415a03a06dbvivek mehta    *sample_rate = DEFAULT_INPUT_SAMPLING_RATE;
2234a824779a3f91eea626ab015975ede392f84ec38vivek mehta    if (audio_is_usb_in_device(in->device)) {
224a68fea653241619e8b4b5ad5f21a2415a03a06dbvivek mehta        platform_check_and_update_copp_sample_rate(adev->platform,
225a68fea653241619e8b4b5ad5f21a2415a03a06dbvivek mehta                                                   usecase->in_snd_device,
226a68fea653241619e8b4b5ad5f21a2415a03a06dbvivek mehta                                                   in->sample_rate,
227a68fea653241619e8b4b5ad5f21a2415a03a06dbvivek mehta                                                   sample_rate);
228e5ff0fc8e7126cdd2535641e9463ee8065b6149eHaynes Mathew George    }
229e5ff0fc8e7126cdd2535641e9463ee8065b6149eHaynes Mathew George
230a68fea653241619e8b4b5ad5f21a2415a03a06dbvivek mehta    app_type_cfg->mode = flags_to_mode(1 /*capture*/, in->flags);
231a68fea653241619e8b4b5ad5f21a2415a03a06dbvivek mehta    ALOGV("%s mode %s", __func__, app_type_cfg->mode);
232a68fea653241619e8b4b5ad5f21a2415a03a06dbvivek mehta    if (in->format == AUDIO_FORMAT_PCM_16_BIT) {
233a68fea653241619e8b4b5ad5f21a2415a03a06dbvivek mehta        platform_get_app_type_v2(adev->platform,
234a68fea653241619e8b4b5ad5f21a2415a03a06dbvivek mehta                                 PCM_CAPTURE,
235a68fea653241619e8b4b5ad5f21a2415a03a06dbvivek mehta                                 app_type_cfg->mode,
236a68fea653241619e8b4b5ad5f21a2415a03a06dbvivek mehta                                 16,
237a68fea653241619e8b4b5ad5f21a2415a03a06dbvivek mehta                                 app_type_cfg->sample_rate,
238a68fea653241619e8b4b5ad5f21a2415a03a06dbvivek mehta                                 app_type);
239a68fea653241619e8b4b5ad5f21a2415a03a06dbvivek mehta    } else if (in->format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
240a68fea653241619e8b4b5ad5f21a2415a03a06dbvivek mehta               in->format == AUDIO_FORMAT_PCM_8_24_BIT) {
241a68fea653241619e8b4b5ad5f21a2415a03a06dbvivek mehta        platform_get_app_type_v2(adev->platform,
242a68fea653241619e8b4b5ad5f21a2415a03a06dbvivek mehta                                 PCM_CAPTURE,
243a68fea653241619e8b4b5ad5f21a2415a03a06dbvivek mehta                                 app_type_cfg->mode,
244a68fea653241619e8b4b5ad5f21a2415a03a06dbvivek mehta                                 24,
245a68fea653241619e8b4b5ad5f21a2415a03a06dbvivek mehta                                 app_type_cfg->sample_rate,
246a68fea653241619e8b4b5ad5f21a2415a03a06dbvivek mehta                                 app_type);
247a68fea653241619e8b4b5ad5f21a2415a03a06dbvivek mehta    } else if (in->format == AUDIO_FORMAT_PCM_32_BIT) {
248a68fea653241619e8b4b5ad5f21a2415a03a06dbvivek mehta        platform_get_app_type_v2(adev->platform,
249a68fea653241619e8b4b5ad5f21a2415a03a06dbvivek mehta                                 PCM_CAPTURE,
250a68fea653241619e8b4b5ad5f21a2415a03a06dbvivek mehta                                 app_type_cfg->mode,
251a68fea653241619e8b4b5ad5f21a2415a03a06dbvivek mehta                                 32,
252a68fea653241619e8b4b5ad5f21a2415a03a06dbvivek mehta                                 app_type_cfg->sample_rate,
253a68fea653241619e8b4b5ad5f21a2415a03a06dbvivek mehta                                 app_type);
254a68fea653241619e8b4b5ad5f21a2415a03a06dbvivek mehta    } else {
255a68fea653241619e8b4b5ad5f21a2415a03a06dbvivek mehta        ALOGE("%s bad format\n", __func__);
256e5ff0fc8e7126cdd2535641e9463ee8065b6149eHaynes Mathew George        return -1;
257e5ff0fc8e7126cdd2535641e9463ee8065b6149eHaynes Mathew George    }
258e5ff0fc8e7126cdd2535641e9463ee8065b6149eHaynes Mathew George
259a68fea653241619e8b4b5ad5f21a2415a03a06dbvivek mehta    app_type_cfg->app_type = *app_type;
260a68fea653241619e8b4b5ad5f21a2415a03a06dbvivek mehta    app_type_cfg->sample_rate = *sample_rate;
261a68fea653241619e8b4b5ad5f21a2415a03a06dbvivek mehta    return 0;
262a68fea653241619e8b4b5ad5f21a2415a03a06dbvivek mehta}
263e5ff0fc8e7126cdd2535641e9463ee8065b6149eHaynes Mathew George
264a68fea653241619e8b4b5ad5f21a2415a03a06dbvivek mehtastatic int derive_playback_app_type_cfg(struct audio_device *adev,
265a68fea653241619e8b4b5ad5f21a2415a03a06dbvivek mehta                                        struct audio_usecase *usecase,
266a68fea653241619e8b4b5ad5f21a2415a03a06dbvivek mehta                                        int *app_type,
267a68fea653241619e8b4b5ad5f21a2415a03a06dbvivek mehta                                        int *sample_rate)
268a68fea653241619e8b4b5ad5f21a2415a03a06dbvivek mehta{
2692e259979b6459235e527ef8283f28f1f08498b51Mark Urbanus    if (usecase->stream.out == NULL) {
2702e259979b6459235e527ef8283f28f1f08498b51Mark Urbanus        return -1;
2712e259979b6459235e527ef8283f28f1f08498b51Mark Urbanus    }
272a68fea653241619e8b4b5ad5f21a2415a03a06dbvivek mehta    struct stream_out *out = usecase->stream.out;
273a68fea653241619e8b4b5ad5f21a2415a03a06dbvivek mehta    struct stream_app_type_cfg *app_type_cfg = &out->app_type_cfg;
274a68fea653241619e8b4b5ad5f21a2415a03a06dbvivek mehta
275a68fea653241619e8b4b5ad5f21a2415a03a06dbvivek mehta    *sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
276a68fea653241619e8b4b5ad5f21a2415a03a06dbvivek mehta
277a68fea653241619e8b4b5ad5f21a2415a03a06dbvivek mehta    // add speaker prot changes if needed
278a68fea653241619e8b4b5ad5f21a2415a03a06dbvivek mehta    // and use that to check for device
2794a824779a3f91eea626ab015975ede392f84ec38vivek mehta    if (audio_is_usb_out_device(out->devices)) {
280a68fea653241619e8b4b5ad5f21a2415a03a06dbvivek mehta        platform_check_and_update_copp_sample_rate(adev->platform,
281a68fea653241619e8b4b5ad5f21a2415a03a06dbvivek mehta                                                   usecase->out_snd_device,
282a68fea653241619e8b4b5ad5f21a2415a03a06dbvivek mehta                                                   out->sample_rate,
283a68fea653241619e8b4b5ad5f21a2415a03a06dbvivek mehta                                                   sample_rate);
284e5ff0fc8e7126cdd2535641e9463ee8065b6149eHaynes Mathew George    }
285e5ff0fc8e7126cdd2535641e9463ee8065b6149eHaynes Mathew George
286a68fea653241619e8b4b5ad5f21a2415a03a06dbvivek mehta    app_type_cfg->mode = flags_to_mode(0 /*playback*/, out->flags);
287a68fea653241619e8b4b5ad5f21a2415a03a06dbvivek mehta    if (!audio_is_linear_pcm(out->format)) {
288df0f886b586a878615280ca34b40a3671bbac316Haynes Mathew George        platform_get_app_type_v2(adev->platform,
289df0f886b586a878615280ca34b40a3671bbac316Haynes Mathew George                                 PCM_PLAYBACK,
290df0f886b586a878615280ca34b40a3671bbac316Haynes Mathew George                                 app_type_cfg->mode,
291df0f886b586a878615280ca34b40a3671bbac316Haynes Mathew George                                 24,
292df0f886b586a878615280ca34b40a3671bbac316Haynes Mathew George                                 *sample_rate,
293df0f886b586a878615280ca34b40a3671bbac316Haynes Mathew George                                 app_type);
294df0f886b586a878615280ca34b40a3671bbac316Haynes Mathew George        ALOGV("Non pcm got app type %d", *app_type);
295a68fea653241619e8b4b5ad5f21a2415a03a06dbvivek mehta    } else if (out->format == AUDIO_FORMAT_PCM_16_BIT) {
296e5ff0fc8e7126cdd2535641e9463ee8065b6149eHaynes Mathew George        platform_get_app_type_v2(adev->platform,
297e5ff0fc8e7126cdd2535641e9463ee8065b6149eHaynes Mathew George                                 PCM_PLAYBACK,
298a68fea653241619e8b4b5ad5f21a2415a03a06dbvivek mehta                                 app_type_cfg->mode,
299a68fea653241619e8b4b5ad5f21a2415a03a06dbvivek mehta                                 16,
300a68fea653241619e8b4b5ad5f21a2415a03a06dbvivek mehta                                 *sample_rate,
301a68fea653241619e8b4b5ad5f21a2415a03a06dbvivek mehta                                 app_type);
302a68fea653241619e8b4b5ad5f21a2415a03a06dbvivek mehta    } else if (out->format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
303a68fea653241619e8b4b5ad5f21a2415a03a06dbvivek mehta               out->format == AUDIO_FORMAT_PCM_8_24_BIT) {
304e5ff0fc8e7126cdd2535641e9463ee8065b6149eHaynes Mathew George        platform_get_app_type_v2(adev->platform,
305e5ff0fc8e7126cdd2535641e9463ee8065b6149eHaynes Mathew George                                 PCM_PLAYBACK,
306a68fea653241619e8b4b5ad5f21a2415a03a06dbvivek mehta                                 app_type_cfg->mode,
307a68fea653241619e8b4b5ad5f21a2415a03a06dbvivek mehta                                 24,
308a68fea653241619e8b4b5ad5f21a2415a03a06dbvivek mehta                                 *sample_rate,
309a68fea653241619e8b4b5ad5f21a2415a03a06dbvivek mehta                                 app_type);
310a68fea653241619e8b4b5ad5f21a2415a03a06dbvivek mehta    } else if (out->format == AUDIO_FORMAT_PCM_32_BIT) {
311e5ff0fc8e7126cdd2535641e9463ee8065b6149eHaynes Mathew George        platform_get_app_type_v2(adev->platform,
312e5ff0fc8e7126cdd2535641e9463ee8065b6149eHaynes Mathew George                                 PCM_PLAYBACK,
313a68fea653241619e8b4b5ad5f21a2415a03a06dbvivek mehta                                 app_type_cfg->mode,
314a68fea653241619e8b4b5ad5f21a2415a03a06dbvivek mehta                                 32,
315a68fea653241619e8b4b5ad5f21a2415a03a06dbvivek mehta                                 *sample_rate,
316a68fea653241619e8b4b5ad5f21a2415a03a06dbvivek mehta                                 app_type);
317e5ff0fc8e7126cdd2535641e9463ee8065b6149eHaynes Mathew George    } else {
318e5ff0fc8e7126cdd2535641e9463ee8065b6149eHaynes Mathew George        ALOGE("%s bad format\n", __func__);
319e5ff0fc8e7126cdd2535641e9463ee8065b6149eHaynes Mathew George        return -1;
320e5ff0fc8e7126cdd2535641e9463ee8065b6149eHaynes Mathew George    }
321e5ff0fc8e7126cdd2535641e9463ee8065b6149eHaynes Mathew George
322a68fea653241619e8b4b5ad5f21a2415a03a06dbvivek mehta    app_type_cfg->app_type = *app_type;
323a68fea653241619e8b4b5ad5f21a2415a03a06dbvivek mehta    app_type_cfg->sample_rate = *sample_rate;
324a68fea653241619e8b4b5ad5f21a2415a03a06dbvivek mehta    return 0;
325a68fea653241619e8b4b5ad5f21a2415a03a06dbvivek mehta}
326e5ff0fc8e7126cdd2535641e9463ee8065b6149eHaynes Mathew George
327a68fea653241619e8b4b5ad5f21a2415a03a06dbvivek mehtastatic int derive_acdb_dev_id(struct audio_device *adev __unused,
328a68fea653241619e8b4b5ad5f21a2415a03a06dbvivek mehta                              struct audio_usecase *usecase)
329a68fea653241619e8b4b5ad5f21a2415a03a06dbvivek mehta{
330a68fea653241619e8b4b5ad5f21a2415a03a06dbvivek mehta    struct stream_out *out;
331a68fea653241619e8b4b5ad5f21a2415a03a06dbvivek mehta    struct stream_in *in;
332e5ff0fc8e7126cdd2535641e9463ee8065b6149eHaynes Mathew George
333a68fea653241619e8b4b5ad5f21a2415a03a06dbvivek mehta    if (usecase->type == PCM_PLAYBACK) {
3349d6679a89ddf23452bb7d370e6fc62ec1183c456Aniket Kumar Lata        return platform_get_snd_device_acdb_id(usecase->out_snd_device);
335a68fea653241619e8b4b5ad5f21a2415a03a06dbvivek mehta    } else if(usecase->type == PCM_CAPTURE) {
336a68fea653241619e8b4b5ad5f21a2415a03a06dbvivek mehta        return platform_get_snd_device_acdb_id(usecase->in_snd_device);
337a68fea653241619e8b4b5ad5f21a2415a03a06dbvivek mehta    }
338a68fea653241619e8b4b5ad5f21a2415a03a06dbvivek mehta    return -1;
339a68fea653241619e8b4b5ad5f21a2415a03a06dbvivek mehta}
340e5ff0fc8e7126cdd2535641e9463ee8065b6149eHaynes Mathew George
341a68fea653241619e8b4b5ad5f21a2415a03a06dbvivek mehtaint audio_extn_utils_send_app_type_cfg(struct audio_device *adev,
342a68fea653241619e8b4b5ad5f21a2415a03a06dbvivek mehta                                       struct audio_usecase *usecase)
343a68fea653241619e8b4b5ad5f21a2415a03a06dbvivek mehta{
344a68fea653241619e8b4b5ad5f21a2415a03a06dbvivek mehta    int len = 0;
345a68fea653241619e8b4b5ad5f21a2415a03a06dbvivek mehta    int sample_rate;
346a68fea653241619e8b4b5ad5f21a2415a03a06dbvivek mehta    int app_type;
347a68fea653241619e8b4b5ad5f21a2415a03a06dbvivek mehta    int acdb_dev_id;
348a68fea653241619e8b4b5ad5f21a2415a03a06dbvivek mehta    size_t app_type_cfg[MAX_LENGTH_MIXER_CONTROL_IN_INT] = {0};
349a68fea653241619e8b4b5ad5f21a2415a03a06dbvivek mehta    char mixer_ctl_name[MAX_LENGTH_MIXER_CONTROL_IN_INT] = {0};
350a68fea653241619e8b4b5ad5f21a2415a03a06dbvivek mehta    int pcm_device_id;
351a68fea653241619e8b4b5ad5f21a2415a03a06dbvivek mehta    struct mixer_ctl *ctl;
352a68fea653241619e8b4b5ad5f21a2415a03a06dbvivek mehta    int ret;
353a68fea653241619e8b4b5ad5f21a2415a03a06dbvivek mehta
354a68fea653241619e8b4b5ad5f21a2415a03a06dbvivek mehta    if (usecase->type == PCM_HFP_CALL) {
355a68fea653241619e8b4b5ad5f21a2415a03a06dbvivek mehta        return audio_extn_utils_send_app_type_cfg_hfp(adev, usecase);
356a68fea653241619e8b4b5ad5f21a2415a03a06dbvivek mehta    }
357a68fea653241619e8b4b5ad5f21a2415a03a06dbvivek mehta
358a68fea653241619e8b4b5ad5f21a2415a03a06dbvivek mehta    if (!platform_supports_app_type_cfg())
359a68fea653241619e8b4b5ad5f21a2415a03a06dbvivek mehta        return -1;
360a68fea653241619e8b4b5ad5f21a2415a03a06dbvivek mehta
361a68fea653241619e8b4b5ad5f21a2415a03a06dbvivek mehta    if (usecase->type == PCM_PLAYBACK) {
362a68fea653241619e8b4b5ad5f21a2415a03a06dbvivek mehta        ret = derive_playback_app_type_cfg(adev,
363a68fea653241619e8b4b5ad5f21a2415a03a06dbvivek mehta                                           usecase,
364a68fea653241619e8b4b5ad5f21a2415a03a06dbvivek mehta                                           &app_type,
365a68fea653241619e8b4b5ad5f21a2415a03a06dbvivek mehta                                           &sample_rate);
366a68fea653241619e8b4b5ad5f21a2415a03a06dbvivek mehta    } else if (usecase->type == PCM_CAPTURE) {
367a68fea653241619e8b4b5ad5f21a2415a03a06dbvivek mehta        ret = derive_capture_app_type_cfg(adev,
368a68fea653241619e8b4b5ad5f21a2415a03a06dbvivek mehta                                          usecase,
369a68fea653241619e8b4b5ad5f21a2415a03a06dbvivek mehta                                          &app_type,
370a68fea653241619e8b4b5ad5f21a2415a03a06dbvivek mehta                                          &sample_rate);
371a68fea653241619e8b4b5ad5f21a2415a03a06dbvivek mehta    } else {
372a68fea653241619e8b4b5ad5f21a2415a03a06dbvivek mehta        ALOGE("%s: Invalid uc type : 0x%x", __func__, usecase->type);
373a68fea653241619e8b4b5ad5f21a2415a03a06dbvivek mehta        return -1;
374a68fea653241619e8b4b5ad5f21a2415a03a06dbvivek mehta    }
375a68fea653241619e8b4b5ad5f21a2415a03a06dbvivek mehta
376a68fea653241619e8b4b5ad5f21a2415a03a06dbvivek mehta    if (ret < 0) {
377a68fea653241619e8b4b5ad5f21a2415a03a06dbvivek mehta        ALOGE("%s: Failed to derive app_type for uc type : 0x%x", __func__,
378a68fea653241619e8b4b5ad5f21a2415a03a06dbvivek mehta              usecase->type);
379a68fea653241619e8b4b5ad5f21a2415a03a06dbvivek mehta        return -1;
380a68fea653241619e8b4b5ad5f21a2415a03a06dbvivek mehta    }
381a68fea653241619e8b4b5ad5f21a2415a03a06dbvivek mehta
382a68fea653241619e8b4b5ad5f21a2415a03a06dbvivek mehta    acdb_dev_id = derive_acdb_dev_id(adev, usecase);
383a68fea653241619e8b4b5ad5f21a2415a03a06dbvivek mehta    if (acdb_dev_id <= 0) {
384a68fea653241619e8b4b5ad5f21a2415a03a06dbvivek mehta        ALOGE("%s: Couldn't get the acdb dev id", __func__);
385a68fea653241619e8b4b5ad5f21a2415a03a06dbvivek mehta        return -1;
386a68fea653241619e8b4b5ad5f21a2415a03a06dbvivek mehta    }
387a68fea653241619e8b4b5ad5f21a2415a03a06dbvivek mehta
388a68fea653241619e8b4b5ad5f21a2415a03a06dbvivek mehta    pcm_device_id = platform_get_pcm_device_id(usecase->id, usecase->type);
389a68fea653241619e8b4b5ad5f21a2415a03a06dbvivek mehta    set_stream_app_type_mixer_ctrl(adev, pcm_device_id, app_type, acdb_dev_id,
390a68fea653241619e8b4b5ad5f21a2415a03a06dbvivek mehta                                   sample_rate,
391a68fea653241619e8b4b5ad5f21a2415a03a06dbvivek mehta                                   usecase->type,
392a68fea653241619e8b4b5ad5f21a2415a03a06dbvivek mehta                                   usecase->type == PCM_PLAYBACK ? usecase->out_snd_device :
393a68fea653241619e8b4b5ad5f21a2415a03a06dbvivek mehta                                                                   usecase->in_snd_device);
394e5ff0fc8e7126cdd2535641e9463ee8065b6149eHaynes Mathew George    return 0;
395e5ff0fc8e7126cdd2535641e9463ee8065b6149eHaynes Mathew George}
396e5ff0fc8e7126cdd2535641e9463ee8065b6149eHaynes Mathew George
3974a824779a3f91eea626ab015975ede392f84ec38vivek mehtaint audio_extn_utils_send_app_type_gain(struct audio_device *adev,
3984a824779a3f91eea626ab015975ede392f84ec38vivek mehta                                        int app_type,
3994a824779a3f91eea626ab015975ede392f84ec38vivek mehta                                        int *gain)
4004a824779a3f91eea626ab015975ede392f84ec38vivek mehta{
4014a824779a3f91eea626ab015975ede392f84ec38vivek mehta    int gain_cfg[4];
4024a824779a3f91eea626ab015975ede392f84ec38vivek mehta    const char *mixer_ctl_name = "App Type Gain";
4034a824779a3f91eea626ab015975ede392f84ec38vivek mehta    struct mixer_ctl *ctl;
4044a824779a3f91eea626ab015975ede392f84ec38vivek mehta    ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
4054a824779a3f91eea626ab015975ede392f84ec38vivek mehta    if (!ctl) {
4064a824779a3f91eea626ab015975ede392f84ec38vivek mehta        ALOGE("%s: Could not get volume ctl mixer %s", __func__,
4074a824779a3f91eea626ab015975ede392f84ec38vivek mehta              mixer_ctl_name);
4084a824779a3f91eea626ab015975ede392f84ec38vivek mehta        return -EINVAL;
4094a824779a3f91eea626ab015975ede392f84ec38vivek mehta    }
4104a824779a3f91eea626ab015975ede392f84ec38vivek mehta    gain_cfg[0] = 0;
4114a824779a3f91eea626ab015975ede392f84ec38vivek mehta    gain_cfg[1] = app_type;
4124a824779a3f91eea626ab015975ede392f84ec38vivek mehta    gain_cfg[2] = gain[0];
4134a824779a3f91eea626ab015975ede392f84ec38vivek mehta    gain_cfg[3] = gain[1];
4144a824779a3f91eea626ab015975ede392f84ec38vivek mehta    ALOGV("%s app_type %d l(%d) r(%d)", __func__,  app_type, gain[0], gain[1]);
4154a824779a3f91eea626ab015975ede392f84ec38vivek mehta    return mixer_ctl_set_array(ctl, gain_cfg,
4164a824779a3f91eea626ab015975ede392f84ec38vivek mehta                               sizeof(gain_cfg)/sizeof(gain_cfg[0]));
4174a824779a3f91eea626ab015975ede392f84ec38vivek mehta}
4184a824779a3f91eea626ab015975ede392f84ec38vivek mehta
419a68fea653241619e8b4b5ad5f21a2415a03a06dbvivek mehta// this assumes correct app_type and sample_rate fields
420a68fea653241619e8b4b5ad5f21a2415a03a06dbvivek mehta// have been set for the stream using audio_extn_utils_send_app_type_cfg
421e5ff0fc8e7126cdd2535641e9463ee8065b6149eHaynes Mathew Georgevoid audio_extn_utils_send_audio_calibration(struct audio_device *adev,
422e5ff0fc8e7126cdd2535641e9463ee8065b6149eHaynes Mathew George                                             struct audio_usecase *usecase)
423e5ff0fc8e7126cdd2535641e9463ee8065b6149eHaynes Mathew George{
424e5ff0fc8e7126cdd2535641e9463ee8065b6149eHaynes Mathew George    int type = usecase->type;
425e5ff0fc8e7126cdd2535641e9463ee8065b6149eHaynes Mathew George    int app_type = 0;
426e5ff0fc8e7126cdd2535641e9463ee8065b6149eHaynes Mathew George
427e5ff0fc8e7126cdd2535641e9463ee8065b6149eHaynes Mathew George    if (type == PCM_PLAYBACK && usecase->stream.out != NULL) {
428e5ff0fc8e7126cdd2535641e9463ee8065b6149eHaynes Mathew George        struct stream_out *out = usecase->stream.out;
429a68fea653241619e8b4b5ad5f21a2415a03a06dbvivek mehta        ALOGV("%s send cal for app_type %d, rate %d", __func__,
430a68fea653241619e8b4b5ad5f21a2415a03a06dbvivek mehta              out->app_type_cfg.app_type,
431a68fea653241619e8b4b5ad5f21a2415a03a06dbvivek mehta              out->app_type_cfg.sample_rate);
432e5ff0fc8e7126cdd2535641e9463ee8065b6149eHaynes Mathew George        platform_send_audio_calibration_v2(adev->platform, usecase,
433a68fea653241619e8b4b5ad5f21a2415a03a06dbvivek mehta                                           out->app_type_cfg.app_type,
434a68fea653241619e8b4b5ad5f21a2415a03a06dbvivek mehta                                           out->app_type_cfg.sample_rate);
435e5ff0fc8e7126cdd2535641e9463ee8065b6149eHaynes Mathew George    } else if (type == PCM_CAPTURE && usecase->stream.in != NULL) {
436a68fea653241619e8b4b5ad5f21a2415a03a06dbvivek mehta        struct stream_in *in = usecase->stream.in;
437a68fea653241619e8b4b5ad5f21a2415a03a06dbvivek mehta        ALOGV("%s send cal for capture app_type %d, rate %d", __func__,
438a68fea653241619e8b4b5ad5f21a2415a03a06dbvivek mehta              in->app_type_cfg.app_type,
439a68fea653241619e8b4b5ad5f21a2415a03a06dbvivek mehta              in->app_type_cfg.sample_rate);
440a68fea653241619e8b4b5ad5f21a2415a03a06dbvivek mehta        platform_send_audio_calibration_v2(adev->platform, usecase,
441a68fea653241619e8b4b5ad5f21a2415a03a06dbvivek mehta                                           in->app_type_cfg.app_type,
442a68fea653241619e8b4b5ad5f21a2415a03a06dbvivek mehta                                           in->app_type_cfg.sample_rate);
443e5ff0fc8e7126cdd2535641e9463ee8065b6149eHaynes Mathew George    } else {
444e5ff0fc8e7126cdd2535641e9463ee8065b6149eHaynes Mathew George        /* when app type is default. the sample rate is not used to send cal */
445e5ff0fc8e7126cdd2535641e9463ee8065b6149eHaynes Mathew George        platform_get_default_app_type_v2(adev->platform, type, &app_type);
446a68fea653241619e8b4b5ad5f21a2415a03a06dbvivek mehta        platform_send_audio_calibration_v2(adev->platform, usecase, app_type,
447a68fea653241619e8b4b5ad5f21a2415a03a06dbvivek mehta                                           48000);
448e5ff0fc8e7126cdd2535641e9463ee8065b6149eHaynes Mathew George    }
449e5ff0fc8e7126cdd2535641e9463ee8065b6149eHaynes Mathew George}
4500fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta
4510fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta#define MAX_SND_CARD 8
4520fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta#define RETRY_US 500000
4530fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta#define RETRY_NUMBER 10
4540fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta
4550fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta#define min(a, b) ((a) < (b) ? (a) : (b))
4560fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta
4570fb113194399805a0fdbf5bb3f812e98047272bdvivek mehtastatic const char *kConfigLocationList[] =
4580fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta        {"/odm/etc", "/vendor/etc", "/system/etc"};
4590fb113194399805a0fdbf5bb3f812e98047272bdvivek mehtastatic const int kConfigLocationListSize =
4600fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta        (sizeof(kConfigLocationList) / sizeof(kConfigLocationList[0]));
4610fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta
4620fb113194399805a0fdbf5bb3f812e98047272bdvivek mehtabool audio_extn_utils_resolve_config_file(char file_name[MIXER_PATH_MAX_LENGTH])
4630fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta{
4640fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta    char full_config_path[MIXER_PATH_MAX_LENGTH];
4650fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta    for (int i = 0; i < kConfigLocationListSize; i++) {
4660fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta        snprintf(full_config_path,
4670fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta                 MIXER_PATH_MAX_LENGTH,
4680fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta                 "%s/%s",
4690fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta                 kConfigLocationList[i],
4700fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta                 file_name);
4710fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta        if (F_OK == access(full_config_path, 0)) {
4720fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta            strcpy(file_name, full_config_path);
4730fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta            return true;
4740fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta        }
4750fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta    }
4760fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta    return false;
4770fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta}
4780fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta
4790fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta/* platform_info_file should be size 'MIXER_PATH_MAX_LENGTH' */
48066ff30c81a8c561db01217297f849614a9599533Haynes Mathew Georgeint audio_extn_utils_get_platform_info(const char* snd_card_name, char* platform_info_file)
4810fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta{
4820fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta    if (NULL == snd_card_name) {
48366ff30c81a8c561db01217297f849614a9599533Haynes Mathew George        return -1;
4840fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta    }
4850fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta
4860fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta    struct snd_card_split *snd_split_handle = NULL;
48766ff30c81a8c561db01217297f849614a9599533Haynes Mathew George    int ret = 0;
4880fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta    audio_extn_set_snd_card_split(snd_card_name);
4890fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta    snd_split_handle = audio_extn_get_snd_card_split();
4900fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta
4910fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta    snprintf(platform_info_file, MIXER_PATH_MAX_LENGTH, "%s_%s_%s.xml",
4920fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta                     PLATFORM_INFO_XML_BASE_STRING, snd_split_handle->snd_card,
4930fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta                     snd_split_handle->form_factor);
4940fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta
4950fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta    if (!audio_extn_utils_resolve_config_file(platform_info_file)) {
4960fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta        memset(platform_info_file, 0, MIXER_PATH_MAX_LENGTH);
4970fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta        snprintf(platform_info_file, MIXER_PATH_MAX_LENGTH, "%s_%s.xml",
4980fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta                     PLATFORM_INFO_XML_BASE_STRING, snd_split_handle->snd_card);
4990fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta
5000fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta        if (!audio_extn_utils_resolve_config_file(platform_info_file)) {
5010fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta            memset(platform_info_file, 0, MIXER_PATH_MAX_LENGTH);
5020fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta            strlcpy(platform_info_file, PLATFORM_INFO_XML_PATH, MIXER_PATH_MAX_LENGTH);
50366ff30c81a8c561db01217297f849614a9599533Haynes Mathew George            ret = audio_extn_utils_resolve_config_file(platform_info_file) ? 0 : -1;
5040fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta        }
5050fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta    }
50666ff30c81a8c561db01217297f849614a9599533Haynes Mathew George
50766ff30c81a8c561db01217297f849614a9599533Haynes Mathew George    return ret;
5080fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta}
5090fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta
5100fb113194399805a0fdbf5bb3f812e98047272bdvivek mehtaint audio_extn_utils_get_snd_card_num()
5110fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta{
5120fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta
5130fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta    void *hw_info = NULL;
5140fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta    struct mixer *mixer = NULL;
5150fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta    int retry_num = 0;
5160fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta    int snd_card_num = 0;
5170fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta    const char* snd_card_name = NULL;
5180fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta    char platform_info_file[MIXER_PATH_MAX_LENGTH]= {0};
5190fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta
5200fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta    struct acdb_platform_data *my_data = calloc(1, sizeof(struct acdb_platform_data));
5210fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta
5220fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta    bool card_verifed[MAX_SND_CARD] = {0};
5230fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta    const int retry_limit = property_get_int32("audio.snd_card.open.retries", RETRY_NUMBER);
5240fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta
5250fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta    for (;;) {
5260fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta        if (snd_card_num >= MAX_SND_CARD) {
5270fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta            if (retry_num++ >= retry_limit) {
5280fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta                ALOGE("%s: Unable to find correct sound card, aborting.", __func__);
5290fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta                snd_card_num = -1;
5300fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta                goto done;
5310fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta            }
5320fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta
5330fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta            snd_card_num = 0;
5340fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta            usleep(RETRY_US);
5350fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta            continue;
5360fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta        }
5370fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta
5380fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta        if (card_verifed[snd_card_num]) {
5390fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta            ++snd_card_num;
5400fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta            continue;
5410fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta        }
5420fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta
5430fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta        mixer = mixer_open(snd_card_num);
5440fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta
5450fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta        if (!mixer) {
5460fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta            ALOGE("%s: Unable to open the mixer card: %d", __func__,
5470fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta               snd_card_num);
5480fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta            ++snd_card_num;
5490fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta            continue;
5500fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta        }
5510fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta
5520fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta        card_verifed[snd_card_num] = true;
5530fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta
5540fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta        snd_card_name = mixer_get_name(mixer);
5550fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta        hw_info = hw_info_init(snd_card_name);
5560fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta
55766ff30c81a8c561db01217297f849614a9599533Haynes Mathew George        if (audio_extn_utils_get_platform_info(snd_card_name, platform_info_file) < 0) {
55866ff30c81a8c561db01217297f849614a9599533Haynes Mathew George            ALOGE("Failed to find platform_info_file");
55966ff30c81a8c561db01217297f849614a9599533Haynes Mathew George            goto cleanup;
56066ff30c81a8c561db01217297f849614a9599533Haynes Mathew George        }
5610fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta
5620fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta        /* Initialize snd card name specific ids and/or backends*/
56366ff30c81a8c561db01217297f849614a9599533Haynes Mathew George        if (snd_card_info_init(platform_info_file, my_data,
56466ff30c81a8c561db01217297f849614a9599533Haynes Mathew George                               &acdb_set_parameters) < 0) {
56566ff30c81a8c561db01217297f849614a9599533Haynes Mathew George            ALOGE("Failed to find platform_info_file");
56666ff30c81a8c561db01217297f849614a9599533Haynes Mathew George            goto cleanup;
56766ff30c81a8c561db01217297f849614a9599533Haynes Mathew George        }
5680fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta
5690fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta        /* validate the sound card name
5700fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta         * my_data->snd_card_name can contain
5710fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta         *     <a> complete sound card name, i.e. <device>-<codec>-<form_factor>-snd-card
5720fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta         *         example: msm8994-tomtom-mtp-snd-card
5730fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta         *     <b> or sub string of the card name, i.e. <device>-<codec>
5740fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta         *         example: msm8994-tomtom
5750fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta         * snd_card_name is truncated to 32 charaters as per mixer_get_name() implementation
5760fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta         * so use min of my_data->snd_card_name and snd_card_name length for comparison
5770fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta         */
5780fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta
5790fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta        if (my_data->snd_card_name != NULL &&
5800fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta                strncmp(snd_card_name, my_data->snd_card_name,
5810fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta                        min(strlen(snd_card_name), strlen(my_data->snd_card_name))) != 0) {
5820fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta            ALOGI("%s: found valid sound card %s, but not primary sound card %s",
5830fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta                   __func__, snd_card_name, my_data->snd_card_name);
58466ff30c81a8c561db01217297f849614a9599533Haynes Mathew George            goto cleanup;
5850fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta        }
5860fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta
58766ff30c81a8c561db01217297f849614a9599533Haynes Mathew George        ALOGI("%s: found sound card %s, primary sound card expected is %s",
5880fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta              __func__, snd_card_name, my_data->snd_card_name);
5890fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta        break;
59066ff30c81a8c561db01217297f849614a9599533Haynes Mathew George  cleanup:
59166ff30c81a8c561db01217297f849614a9599533Haynes Mathew George        ++snd_card_num;
59266ff30c81a8c561db01217297f849614a9599533Haynes Mathew George        mixer_close(mixer);
59366ff30c81a8c561db01217297f849614a9599533Haynes Mathew George        mixer = NULL;
59466ff30c81a8c561db01217297f849614a9599533Haynes Mathew George        hw_info_deinit(hw_info);
59566ff30c81a8c561db01217297f849614a9599533Haynes Mathew George        hw_info = NULL;
5960fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta    }
5970fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta
5980fb113194399805a0fdbf5bb3f812e98047272bdvivek mehtadone:
5990fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta    mixer_close(mixer);
6000fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta    hw_info_deinit(hw_info);
6010fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta
6020fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta    if (my_data)
6030fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta        free(my_data);
6040fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta
6050fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta    return snd_card_num;
6060fb113194399805a0fdbf5bb3f812e98047272bdvivek mehta}
607