1/*
2 * Copyright (c) 2014, The Linux Foundation. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
6 * met:
7 *   * Redistributions of source code must retain the above copyright
8 *     notice, this list of conditions and the following disclaimer.
9 *   * Redistributions in binary form must reproduce the above
10 *     copyright notice, this list of conditions and the following
11 *     disclaimer in the documentation and/or other materials provided
12 *     with the distribution.
13 *   * Neither the name of The Linux Foundation nor the names of its
14 *     contributors may be used to endorse or promote products derived
15 *     from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
18 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
20 * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
21 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
24 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
25 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
26 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
27 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29
30#define LOG_TAG "hardware_info"
31/*#define LOG_NDEBUG 0*/
32#define LOG_NDDEBUG 0
33
34#include <stdlib.h>
35#include <dlfcn.h>
36#include <cutils/log.h>
37#include <cutils/str_parms.h>
38#include "audio_hw.h"
39#include "platform.h"
40#include "platform_api.h"
41
42
43struct hardware_info {
44    char name[HW_INFO_ARRAY_MAX_SIZE];
45    char type[HW_INFO_ARRAY_MAX_SIZE];
46    /* variables for handling target variants */
47    uint32_t num_snd_devices;
48    char dev_extn[HW_INFO_ARRAY_MAX_SIZE];
49    snd_device_t  *snd_devices;
50};
51
52#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
53
54static const snd_device_t taiko_fluid_variant_devices[] = {
55    SND_DEVICE_OUT_SPEAKER,
56    SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES,
57    SND_DEVICE_OUT_SPEAKER_AND_ANC_HEADSET,
58};
59
60static const snd_device_t taiko_CDP_variant_devices[] = {
61    SND_DEVICE_OUT_SPEAKER,
62    SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES,
63    SND_DEVICE_OUT_SPEAKER_AND_ANC_HEADSET,
64    SND_DEVICE_IN_QUAD_MIC,
65};
66
67static const snd_device_t taiko_apq8084_CDP_variant_devices[] = {
68    SND_DEVICE_IN_HANDSET_MIC,
69};
70
71static const snd_device_t taiko_liquid_variant_devices[] = {
72    SND_DEVICE_OUT_SPEAKER,
73    SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES,
74    SND_DEVICE_OUT_SPEAKER_AND_ANC_HEADSET,
75    SND_DEVICE_IN_SPEAKER_MIC,
76    SND_DEVICE_IN_HEADSET_MIC,
77    SND_DEVICE_IN_VOICE_DMIC,
78    SND_DEVICE_IN_VOICE_SPEAKER_DMIC,
79    SND_DEVICE_IN_VOICE_REC_DMIC_STEREO,
80    SND_DEVICE_IN_VOICE_REC_DMIC_FLUENCE,
81    SND_DEVICE_IN_QUAD_MIC,
82    SND_DEVICE_IN_HANDSET_STEREO_DMIC,
83    SND_DEVICE_IN_SPEAKER_STEREO_DMIC,
84};
85
86static const snd_device_t taiko_DB_variant_devices[] = {
87    SND_DEVICE_OUT_SPEAKER,
88    SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES,
89    SND_DEVICE_OUT_SPEAKER_AND_ANC_HEADSET,
90    SND_DEVICE_IN_SPEAKER_MIC,
91    SND_DEVICE_IN_HEADSET_MIC,
92    SND_DEVICE_IN_QUAD_MIC,
93};
94
95static const snd_device_t tapan_lite_variant_devices[] = {
96    SND_DEVICE_OUT_SPEAKER,
97    SND_DEVICE_OUT_HEADPHONES,
98    SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES,
99    SND_DEVICE_OUT_VOICE_HEADPHONES,
100    SND_DEVICE_OUT_VOICE_TTY_FULL_HEADPHONES,
101    SND_DEVICE_OUT_VOICE_TTY_VCO_HEADPHONES,
102};
103
104static const snd_device_t tapan_skuf_variant_devices[] = {
105    SND_DEVICE_OUT_SPEAKER,
106    SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES,
107    SND_DEVICE_OUT_SPEAKER_AND_ANC_HEADSET,
108    /*SND_DEVICE_OUT_SPEAKER_AND_ANC_FB_HEADSET,*/
109};
110
111static const snd_device_t tapan_lite_skuf_variant_devices[] = {
112    SND_DEVICE_OUT_SPEAKER,
113    SND_DEVICE_OUT_HEADPHONES,
114    SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES,
115    SND_DEVICE_OUT_VOICE_HEADPHONES,
116    SND_DEVICE_OUT_VOICE_TTY_FULL_HEADPHONES,
117    SND_DEVICE_OUT_VOICE_TTY_VCO_HEADPHONES,
118};
119
120static const snd_device_t helicon_skuab_variant_devices[] = {
121    SND_DEVICE_OUT_SPEAKER,
122    SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES,
123    SND_DEVICE_OUT_SPEAKER_AND_ANC_HEADSET,
124};
125
126static void update_hardware_info_8x16(struct hardware_info *hw_info, const char *snd_card_name)
127{
128    if (!strcmp(snd_card_name, "msm8x16-snd-card")) {
129        strlcpy(hw_info->type, "", sizeof(hw_info->type));
130        strlcpy(hw_info->name, "msm8x16", sizeof(hw_info->name));
131        hw_info->snd_devices = NULL;
132        hw_info->num_snd_devices = 0;
133        strlcpy(hw_info->dev_extn, "", sizeof(hw_info->dev_extn));
134    } else if (!strcmp(snd_card_name, "msm8x16-snd-card-mtp")) {
135        strlcpy(hw_info->type, "", sizeof(hw_info->type));
136        strlcpy(hw_info->name, "msm8x16", sizeof(hw_info->name));
137        hw_info->snd_devices = NULL;
138        hw_info->num_snd_devices = 0;
139        strlcpy(hw_info->dev_extn, "", sizeof(hw_info->dev_extn));
140    } else if (!strcmp(snd_card_name, "msm8x16-snd-card-sbc")) {
141        strlcpy(hw_info->type, "sbc", sizeof(hw_info->type));
142        strlcpy(hw_info->name, "msm8x16", sizeof(hw_info->name));
143        hw_info->snd_devices = NULL;
144        hw_info->num_snd_devices = 0;
145    } else if (!strcmp(snd_card_name, "msm8x16-skuh-snd-card")) {
146        strlcpy(hw_info->type, "skuh", sizeof(hw_info->type));
147        strlcpy(hw_info->name, "msm8x16", sizeof(hw_info->name));
148        hw_info->snd_devices = NULL;
149        hw_info->num_snd_devices = 0;
150        strlcpy(hw_info->dev_extn, "", sizeof(hw_info->dev_extn));
151    } else if (!strcmp(snd_card_name, "msm8x16-skui-snd-card")) {
152        strlcpy(hw_info->type, "skui", sizeof(hw_info->type));
153        strlcpy(hw_info->name, "msm8x16", sizeof(hw_info->name));
154        hw_info->snd_devices = NULL;
155        hw_info->num_snd_devices = 0;
156        strlcpy(hw_info->dev_extn, "", sizeof(hw_info->dev_extn));
157    } else if (!strcmp(snd_card_name, "msm8x16-skuhf-snd-card")) {
158        strlcpy(hw_info->type, "skuhf", sizeof(hw_info->type));
159        strlcpy(hw_info->name, "msm8x16", sizeof(hw_info->name));
160        hw_info->snd_devices = NULL;
161        hw_info->num_snd_devices = 0;
162        strlcpy(hw_info->dev_extn, "", sizeof(hw_info->dev_extn));
163    } else if (!strcmp(snd_card_name, "msm8939-snd-card")) {
164        strlcpy(hw_info->type, "", sizeof(hw_info->type));
165        strlcpy(hw_info->name, "msm8939", sizeof(hw_info->name));
166        hw_info->snd_devices = NULL;
167        hw_info->num_snd_devices = 0;
168        strlcpy(hw_info->dev_extn, "", sizeof(hw_info->dev_extn));
169    } else if (!strcmp(snd_card_name, "msm8939-snd-card-mtp")) {
170        strlcpy(hw_info->type, "", sizeof(hw_info->type));
171        strlcpy(hw_info->name, "msm8939", sizeof(hw_info->name));
172        hw_info->snd_devices = NULL;
173        hw_info->num_snd_devices = 0;
174        strlcpy(hw_info->dev_extn, "", sizeof(hw_info->dev_extn));
175    } else if (!strcmp(snd_card_name, "msm8939-snd-card-skuk")) {
176        strlcpy(hw_info->type, "skuk", sizeof(hw_info->type));
177        strlcpy(hw_info->name, "msm8939", sizeof(hw_info->name));
178        hw_info->snd_devices = NULL;
179        hw_info->num_snd_devices = 0;
180        strlcpy(hw_info->dev_extn, "", sizeof(hw_info->dev_extn));
181    } else if (!strcmp(snd_card_name, "msm8939-tapan-snd-card") ||
182               !strcmp(snd_card_name, "msm8939-tapan9302-snd-card")) {
183        strlcpy(hw_info->type, "", sizeof(hw_info->type));
184        strlcpy(hw_info->name, "msm8939", sizeof(hw_info->name));
185        hw_info->snd_devices = NULL;
186        hw_info->num_snd_devices = 0;
187        strlcpy(hw_info->dev_extn, "", sizeof(hw_info->dev_extn));
188    } else if (!strcmp(snd_card_name, "msm8909-snd-card")) {
189        strlcpy(hw_info->type, "", sizeof(hw_info->type));
190        strlcpy(hw_info->name, "msm8909", sizeof(hw_info->name));
191        hw_info->snd_devices = NULL;
192        hw_info->num_snd_devices = 0;
193        strlcpy(hw_info->dev_extn, "", sizeof(hw_info->dev_extn));
194    } else if (!strcmp(snd_card_name, "msm8909-skua-snd-card")) {
195        strlcpy(hw_info->type, "skua", sizeof(hw_info->type));
196        strlcpy(hw_info->name, "msm8909", sizeof(hw_info->name));
197        hw_info->snd_devices = NULL;
198        hw_info->num_snd_devices = 0;
199        strlcpy(hw_info->dev_extn, "", sizeof(hw_info->dev_extn));
200    } else if (!strcmp(snd_card_name, "msm8909-skuc-snd-card")) {
201        strlcpy(hw_info->type, "skuc", sizeof(hw_info->type));
202        strlcpy(hw_info->name, "msm8909", sizeof(hw_info->name));
203        hw_info->snd_devices = NULL;
204        hw_info->num_snd_devices = 0;
205        strlcpy(hw_info->dev_extn, "", sizeof(hw_info->dev_extn));
206    } else if (!strcmp(snd_card_name, "msm8909-pm8916-snd-card")) {
207        strlcpy(hw_info->type, "", sizeof(hw_info->type));
208        strlcpy(hw_info->name, "msm8909", sizeof(hw_info->name));
209        hw_info->snd_devices = NULL;
210        hw_info->num_snd_devices = 0;
211        strlcpy(hw_info->dev_extn, "", sizeof(hw_info->dev_extn));
212    } else if (!strcmp(snd_card_name, "msm8909-skue-snd-card")) {
213        strlcpy(hw_info->type, "skue", sizeof(hw_info->type));
214        strlcpy(hw_info->name, "msm8909", sizeof(hw_info->name));
215        hw_info->snd_devices = NULL;
216        hw_info->num_snd_devices = 0;
217        strlcpy(hw_info->dev_extn, "", sizeof(hw_info->dev_extn));
218    } else if (!strcmp(snd_card_name, "msm8939-snd-card-skul")) {
219        strlcpy(hw_info->type, "skul", sizeof(hw_info->type));
220        strlcpy(hw_info->name, "msm8939", sizeof(hw_info->name));
221        hw_info->snd_devices = NULL;
222        hw_info->num_snd_devices = 0;
223        strlcpy(hw_info->dev_extn, "", sizeof(hw_info->dev_extn));
224    } else if (!strcmp(snd_card_name, "msm8909-skut-snd-card")) {
225        strlcpy(hw_info->type, "skut", sizeof(hw_info->type));
226        strlcpy(hw_info->name, "msm8909", sizeof(hw_info->name));
227        hw_info->snd_devices = NULL;
228        hw_info->num_snd_devices = 0;
229        strlcpy(hw_info->dev_extn, "", sizeof(hw_info->dev_extn));
230   } else if (!strcmp(snd_card_name, "msm8x09-tasha9326-snd-card")) {
231        strlcpy(hw_info->type, "", sizeof(hw_info->type));
232        strlcpy(hw_info->name, "msm8909", sizeof(hw_info->name));
233        hw_info->snd_devices = NULL;
234        hw_info->num_snd_devices = 0;
235        strlcpy(hw_info->dev_extn, "", sizeof(hw_info->dev_extn));
236    } else {
237        ALOGW("%s: Not an  8x16/8939/8909 device", __func__);
238    }
239}
240
241void *hw_info_init(const char *snd_card_name)
242{
243    struct hardware_info *hw_info;
244
245    hw_info = malloc(sizeof(struct hardware_info));
246    if (!hw_info) {
247        ALOGE("failed to allocate mem for hardware info");
248        return NULL;
249    }
250
251    if (strstr(snd_card_name, "msm8x16") || strstr(snd_card_name, "msm8939") ||
252        strstr(snd_card_name, "msm8909") || strstr(snd_card_name, "msm8x09")) {
253        ALOGV("8x16 - variant soundcard");
254        update_hardware_info_8x16(hw_info, snd_card_name);
255    } else {
256        ALOGE("%s: Unsupported target %s:",__func__, snd_card_name);
257        free(hw_info);
258        hw_info = NULL;
259    }
260
261    return hw_info;
262}
263
264void hw_info_deinit(void *hw_info)
265{
266    struct hardware_info *my_data = (struct hardware_info*) hw_info;
267
268    if(!my_data)
269        free(my_data);
270}
271
272void hw_info_append_hw_type(void *hw_info, snd_device_t snd_device,
273                            char *device_name)
274{
275    struct hardware_info *my_data = (struct hardware_info*) hw_info;
276    uint32_t i = 0;
277
278    snd_device_t *snd_devices =
279            (snd_device_t *) my_data->snd_devices;
280
281    if(snd_devices != NULL) {
282        for (i = 0; i <  my_data->num_snd_devices; i++) {
283            if (snd_device == (snd_device_t)snd_devices[i]) {
284                ALOGV("extract dev_extn device %d, extn = %s",
285                        (snd_device_t)snd_devices[i],  my_data->dev_extn);
286                CHECK(strlcat(device_name,  my_data->dev_extn,
287                        DEVICE_NAME_MAX_SIZE) < DEVICE_NAME_MAX_SIZE);
288                break;
289            }
290        }
291    }
292    ALOGD("%s : device_name = %s", __func__,device_name);
293}
294