1/* 2 * Copyright (c) 2013, 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 tomtom_msm8994_CDP_variant_devices[] = { 87 SND_DEVICE_IN_HANDSET_MIC, 88}; 89 90static const snd_device_t tomtom_liquid_variant_devices[] = { 91 SND_DEVICE_OUT_SPEAKER, 92 SND_DEVICE_OUT_SPEAKER_EXTERNAL_1, 93 SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES_EXTERNAL_1, 94 SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES, 95 SND_DEVICE_OUT_SPEAKER_AND_ANC_HEADSET, 96 SND_DEVICE_IN_SPEAKER_MIC, 97 SND_DEVICE_IN_HEADSET_MIC, 98 SND_DEVICE_IN_VOICE_DMIC, 99 SND_DEVICE_IN_VOICE_SPEAKER_DMIC, 100 SND_DEVICE_IN_VOICE_REC_DMIC_STEREO, 101 SND_DEVICE_IN_VOICE_REC_DMIC_FLUENCE, 102 SND_DEVICE_IN_QUAD_MIC, 103 SND_DEVICE_IN_HANDSET_STEREO_DMIC, 104 SND_DEVICE_IN_SPEAKER_STEREO_DMIC, 105}; 106 107static const snd_device_t tomtom_stp_variant_devices[] = { 108 SND_DEVICE_OUT_SPEAKER, 109 SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES, 110 SND_DEVICE_OUT_SPEAKER_AND_ANC_HEADSET, 111}; 112 113static const snd_device_t taiko_DB_variant_devices[] = { 114 SND_DEVICE_OUT_SPEAKER, 115 SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES, 116 SND_DEVICE_OUT_SPEAKER_AND_ANC_HEADSET, 117 SND_DEVICE_IN_SPEAKER_MIC, 118 SND_DEVICE_IN_HEADSET_MIC, 119 SND_DEVICE_IN_QUAD_MIC, 120}; 121 122static const snd_device_t taiko_apq8084_sbc_variant_devices[] = { 123 SND_DEVICE_IN_HANDSET_MIC, 124 SND_DEVICE_IN_SPEAKER_MIC, 125}; 126 127static const snd_device_t tapan_lite_variant_devices[] = { 128 SND_DEVICE_OUT_SPEAKER, 129 SND_DEVICE_OUT_HEADPHONES, 130 SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES, 131 SND_DEVICE_OUT_VOICE_HEADPHONES, 132 SND_DEVICE_OUT_VOICE_TTY_FULL_HEADPHONES, 133 SND_DEVICE_OUT_VOICE_TTY_VCO_HEADPHONES, 134}; 135 136static const snd_device_t tapan_skuf_variant_devices[] = { 137 SND_DEVICE_OUT_SPEAKER, 138 SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES, 139 SND_DEVICE_OUT_SPEAKER_AND_ANC_HEADSET, 140 /*SND_DEVICE_OUT_SPEAKER_AND_ANC_FB_HEADSET,*/ 141}; 142 143static const snd_device_t tapan_lite_skuf_variant_devices[] = { 144 SND_DEVICE_OUT_SPEAKER, 145 SND_DEVICE_OUT_HEADPHONES, 146 SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES, 147 SND_DEVICE_OUT_VOICE_HEADPHONES, 148 SND_DEVICE_OUT_VOICE_TTY_FULL_HEADPHONES, 149 SND_DEVICE_OUT_VOICE_TTY_VCO_HEADPHONES, 150}; 151 152static const snd_device_t helicon_skuab_variant_devices[] = { 153 SND_DEVICE_OUT_SPEAKER, 154 SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES, 155 SND_DEVICE_OUT_SPEAKER_AND_ANC_HEADSET, 156 SND_DEVICE_OUT_VOICE_SPEAKER, 157}; 158 159static void update_hardware_info_8084(struct hardware_info *hw_info, const char *snd_card_name) 160{ 161 if (!strcmp(snd_card_name, "apq8084-taiko-mtp-snd-card") || 162 !strncmp(snd_card_name, "apq8084-taiko-i2s-mtp-snd-card", 163 sizeof("apq8084-taiko-i2s-mtp-snd-card")) || 164 !strncmp(snd_card_name, "apq8084-tomtom-mtp-snd-card", 165 sizeof("apq8084-tomtom-mtp-snd-card"))) { 166 strlcpy(hw_info->type, "mtp", sizeof(hw_info->type)); 167 strlcpy(hw_info->name, "apq8084", sizeof(hw_info->name)); 168 hw_info->snd_devices = NULL; 169 hw_info->num_snd_devices = 0; 170 strlcpy(hw_info->dev_extn, "", sizeof(hw_info->dev_extn)); 171 } else if ((!strcmp(snd_card_name, "apq8084-taiko-cdp-snd-card")) || 172 !strncmp(snd_card_name, "apq8084-tomtom-cdp-snd-card", 173 sizeof("apq8084-tomtom-cdp-snd-card"))) { 174 strlcpy(hw_info->type, " cdp", sizeof(hw_info->type)); 175 strlcpy(hw_info->name, "apq8084", sizeof(hw_info->name)); 176 hw_info->snd_devices = (snd_device_t *)taiko_apq8084_CDP_variant_devices; 177 hw_info->num_snd_devices = ARRAY_SIZE(taiko_apq8084_CDP_variant_devices); 178 strlcpy(hw_info->dev_extn, "-cdp", sizeof(hw_info->dev_extn)); 179 } else if (!strncmp(snd_card_name, "apq8084-taiko-i2s-cdp-snd-card", 180 sizeof("apq8084-taiko-i2s-cdp-snd-card"))) { 181 strlcpy(hw_info->type, " cdp", sizeof(hw_info->type)); 182 strlcpy(hw_info->name, "apq8084", sizeof(hw_info->name)); 183 hw_info->snd_devices = NULL; 184 hw_info->num_snd_devices = 0; 185 strlcpy(hw_info->dev_extn, "", sizeof(hw_info->dev_extn)); 186 } else if (!strcmp(snd_card_name, "apq8084-taiko-liquid-snd-card")) { 187 strlcpy(hw_info->type , " liquid", sizeof(hw_info->type)); 188 strlcpy(hw_info->name, "apq8084", sizeof(hw_info->type)); 189 hw_info->snd_devices = (snd_device_t *)taiko_liquid_variant_devices; 190 hw_info->num_snd_devices = ARRAY_SIZE(taiko_liquid_variant_devices); 191 strlcpy(hw_info->dev_extn, "-liquid", sizeof(hw_info->dev_extn)); 192 } else if (!strcmp(snd_card_name, "apq8084-taiko-sbc-snd-card")) { 193 strlcpy(hw_info->type, " sbc", sizeof(hw_info->type)); 194 strlcpy(hw_info->name, "apq8084", sizeof(hw_info->name)); 195 hw_info->snd_devices = (snd_device_t *)taiko_apq8084_sbc_variant_devices; 196 hw_info->num_snd_devices = ARRAY_SIZE(taiko_apq8084_sbc_variant_devices); 197 strlcpy(hw_info->dev_extn, "-sbc", sizeof(hw_info->dev_extn)); 198 } else { 199 ALOGW("%s: Not an 8084 device", __func__); 200 } 201} 202 203static void update_hardware_info_8994(struct hardware_info *hw_info, const char *snd_card_name) 204{ 205 if (!strcmp(snd_card_name, "msm8994-tomtom-mtp-snd-card")) { 206 strlcpy(hw_info->type, " mtp", sizeof(hw_info->type)); 207 strlcpy(hw_info->name, "msm8994", sizeof(hw_info->name)); 208 hw_info->snd_devices = NULL; 209 hw_info->num_snd_devices = 0; 210 strlcpy(hw_info->dev_extn, "", sizeof(hw_info->dev_extn)); 211 } else if (!strcmp(snd_card_name, "msm8994-tomtom-cdp-snd-card")) { 212 strlcpy(hw_info->type, " cdp", sizeof(hw_info->type)); 213 strlcpy(hw_info->name, "msm8994", sizeof(hw_info->name)); 214 hw_info->snd_devices = (snd_device_t *)tomtom_msm8994_CDP_variant_devices; 215 hw_info->num_snd_devices = ARRAY_SIZE(tomtom_msm8994_CDP_variant_devices); 216 strlcpy(hw_info->dev_extn, "-cdp", sizeof(hw_info->dev_extn)); 217 } else if (!strcmp(snd_card_name, "msm8994-tomtom-stp-snd-card")) { 218 strlcpy(hw_info->type, " stp", sizeof(hw_info->type)); 219 strlcpy(hw_info->name, "msm8994", sizeof(hw_info->name)); 220 hw_info->snd_devices = (snd_device_t *)tomtom_stp_variant_devices; 221 hw_info->num_snd_devices = ARRAY_SIZE(tomtom_stp_variant_devices); 222 strlcpy(hw_info->dev_extn, "-stp", sizeof(hw_info->dev_extn)); 223 } else if (!strcmp(snd_card_name, "msm8994-tomtom-liquid-snd-card")) { 224 strlcpy(hw_info->type, " liquid", sizeof(hw_info->type)); 225 strlcpy(hw_info->name, "msm8994", sizeof(hw_info->name)); 226 hw_info->snd_devices = (snd_device_t *)tomtom_liquid_variant_devices; 227 hw_info->num_snd_devices = ARRAY_SIZE(tomtom_liquid_variant_devices); 228 strlcpy(hw_info->dev_extn, "-liquid", sizeof(hw_info->dev_extn)); 229 } else { 230 ALOGW("%s: Not an 8994 device", __func__); 231 } 232} 233 234static void update_hardware_info_8974(struct hardware_info *hw_info, const char *snd_card_name) 235{ 236 if (!strcmp(snd_card_name, "msm8974-taiko-mtp-snd-card")) { 237 strlcpy(hw_info->type, " mtp", sizeof(hw_info->type)); 238 strlcpy(hw_info->name, "msm8974", sizeof(hw_info->name)); 239 hw_info->snd_devices = NULL; 240 hw_info->num_snd_devices = 0; 241 strlcpy(hw_info->dev_extn, "", sizeof(hw_info->dev_extn)); 242 } else if (!strcmp(snd_card_name, "msm8974-taiko-cdp-snd-card")) { 243 strlcpy(hw_info->type, " cdp", sizeof(hw_info->type)); 244 strlcpy(hw_info->name, "msm8974", sizeof(hw_info->name)); 245 hw_info->snd_devices = (snd_device_t *)taiko_CDP_variant_devices; 246 hw_info->num_snd_devices = ARRAY_SIZE(taiko_CDP_variant_devices); 247 strlcpy(hw_info->dev_extn, "-cdp", sizeof(hw_info->dev_extn)); 248 } else if (!strcmp(snd_card_name, "msm8974-taiko-fluid-snd-card")) { 249 strlcpy(hw_info->type, " fluid", sizeof(hw_info->type)); 250 strlcpy(hw_info->name, "msm8974", sizeof(hw_info->name)); 251 hw_info->snd_devices = (snd_device_t *) taiko_fluid_variant_devices; 252 hw_info->num_snd_devices = ARRAY_SIZE(taiko_fluid_variant_devices); 253 strlcpy(hw_info->dev_extn, "-fluid", sizeof(hw_info->dev_extn)); 254 } else if (!strcmp(snd_card_name, "msm8974-taiko-liquid-snd-card")) { 255 strlcpy(hw_info->type, " liquid", sizeof(hw_info->type)); 256 strlcpy(hw_info->name, "msm8974", sizeof(hw_info->name)); 257 hw_info->snd_devices = (snd_device_t *)taiko_liquid_variant_devices; 258 hw_info->num_snd_devices = ARRAY_SIZE(taiko_liquid_variant_devices); 259 strlcpy(hw_info->dev_extn, "-liquid", sizeof(hw_info->dev_extn)); 260 } else if (!strcmp(snd_card_name, "apq8074-taiko-db-snd-card")) { 261 strlcpy(hw_info->type, " dragon-board", sizeof(hw_info->type)); 262 strlcpy(hw_info->name, "msm8974", sizeof(hw_info->name)); 263 hw_info->snd_devices = (snd_device_t *)taiko_DB_variant_devices; 264 hw_info->num_snd_devices = ARRAY_SIZE(taiko_DB_variant_devices); 265 strlcpy(hw_info->dev_extn, "-DB", sizeof(hw_info->dev_extn)); 266 } else { 267 ALOGW("%s: Not an 8974 device", __func__); 268 } 269} 270 271static void update_hardware_info_8610(struct hardware_info *hw_info, const char *snd_card_name) 272{ 273 if (!strcmp(snd_card_name, "msm8x10-snd-card")) { 274 strlcpy(hw_info->type, "", sizeof(hw_info->type)); 275 strlcpy(hw_info->name, "msm8x10", sizeof(hw_info->name)); 276 hw_info->snd_devices = NULL; 277 hw_info->num_snd_devices = 0; 278 strlcpy(hw_info->dev_extn, "", sizeof(hw_info->dev_extn)); 279 } else if (!strcmp(snd_card_name, "msm8x10-skuab-snd-card")) { 280 strlcpy(hw_info->type, "skuab", sizeof(hw_info->type)); 281 strlcpy(hw_info->name, "msm8x10", sizeof(hw_info->name)); 282 hw_info->snd_devices = (snd_device_t *)helicon_skuab_variant_devices; 283 hw_info->num_snd_devices = ARRAY_SIZE(helicon_skuab_variant_devices); 284 strlcpy(hw_info->dev_extn, "-skuab", sizeof(hw_info->dev_extn)); 285 } else if (!strcmp(snd_card_name, "msm8x10-skuaa-snd-card")) { 286 strlcpy(hw_info->type, " skuaa", sizeof(hw_info->type)); 287 strlcpy(hw_info->name, "msm8x10", sizeof(hw_info->name)); 288 hw_info->snd_devices = NULL; 289 hw_info->num_snd_devices = 0; 290 strlcpy(hw_info->dev_extn, "", sizeof(hw_info->dev_extn)); 291 } else { 292 ALOGW("%s: Not an 8x10 device", __func__); 293 } 294} 295 296static void update_hardware_info_8226(struct hardware_info *hw_info, const char *snd_card_name) 297{ 298 if (!strcmp(snd_card_name, "msm8226-tapan-snd-card")) { 299 strlcpy(hw_info->type, "", sizeof(hw_info->type)); 300 strlcpy(hw_info->name, "msm8226", sizeof(hw_info->name)); 301 hw_info->snd_devices = NULL; 302 hw_info->num_snd_devices = 0; 303 strlcpy(hw_info->dev_extn, "", sizeof(hw_info->dev_extn)); 304 } else if (!strcmp(snd_card_name, "msm8226-tapan9302-snd-card")) { 305 strlcpy(hw_info->type, "tapan_lite", sizeof(hw_info->type)); 306 strlcpy(hw_info->name, "msm8226", sizeof(hw_info->name)); 307 hw_info->snd_devices = (snd_device_t *)tapan_lite_variant_devices; 308 hw_info->num_snd_devices = ARRAY_SIZE(tapan_lite_variant_devices); 309 strlcpy(hw_info->dev_extn, "-lite", sizeof(hw_info->dev_extn)); 310 } else if (!strcmp(snd_card_name, "msm8226-tapan-skuf-snd-card")) { 311 strlcpy(hw_info->type, " skuf", sizeof(hw_info->type)); 312 strlcpy(hw_info->name, "msm8226", sizeof(hw_info->name)); 313 hw_info->snd_devices = (snd_device_t *) tapan_skuf_variant_devices; 314 hw_info->num_snd_devices = ARRAY_SIZE(tapan_skuf_variant_devices); 315 strlcpy(hw_info->dev_extn, "-skuf", sizeof(hw_info->dev_extn)); 316 } else if (!strcmp(snd_card_name, "msm8226-tapan9302-skuf-snd-card")) { 317 strlcpy(hw_info->type, " tapan9302-skuf", sizeof(hw_info->type)); 318 strlcpy(hw_info->name, "msm8226", sizeof(hw_info->name)); 319 hw_info->snd_devices = (snd_device_t *)tapan_lite_skuf_variant_devices; 320 hw_info->num_snd_devices = ARRAY_SIZE(tapan_lite_skuf_variant_devices); 321 strlcpy(hw_info->dev_extn, "-skuf-lite", sizeof(hw_info->dev_extn)); 322 } else { 323 ALOGW("%s: Not an 8x26 device", __func__); 324 } 325} 326 327void *hw_info_init(const char *snd_card_name) 328{ 329 struct hardware_info *hw_info; 330 331 hw_info = malloc(sizeof(struct hardware_info)); 332 if (!hw_info) { 333 ALOGE("failed to allocate mem for hardware info"); 334 return NULL; 335 } 336 337 hw_info->snd_devices = NULL; 338 hw_info->num_snd_devices = 0; 339 strlcpy(hw_info->dev_extn, "", sizeof(hw_info->dev_extn)); 340 strlcpy(hw_info->type, "", sizeof(hw_info->type)); 341 strlcpy(hw_info->name, "", sizeof(hw_info->name)); 342 343 if(strstr(snd_card_name, "msm8974") || 344 strstr(snd_card_name, "apq8074")) { 345 ALOGV("8974 - variant soundcard"); 346 update_hardware_info_8974(hw_info, snd_card_name); 347 } else if(strstr(snd_card_name, "msm8226")) { 348 ALOGV("8x26 - variant soundcard"); 349 update_hardware_info_8226(hw_info, snd_card_name); 350 } else if(strstr(snd_card_name, "msm8x10")) { 351 ALOGV("8x10 - variant soundcard"); 352 update_hardware_info_8610(hw_info, snd_card_name); 353 } else if(strstr(snd_card_name, "apq8084")) { 354 ALOGV("8084 - variant soundcard"); 355 update_hardware_info_8084(hw_info, snd_card_name); 356 } else if(strstr(snd_card_name, "msm8994")) { 357 ALOGV("8994 - variant soundcard"); 358 update_hardware_info_8994(hw_info, snd_card_name); 359 } else { 360 ALOGE("%s: Unsupported target %s:",__func__, snd_card_name); 361 free(hw_info); 362 hw_info = NULL; 363 } 364 365 return hw_info; 366} 367 368void hw_info_deinit(void *hw_info) 369{ 370 struct hardware_info *my_data = (struct hardware_info*) hw_info; 371 372 if(!my_data) 373 free(my_data); 374} 375 376void hw_info_append_hw_type(void *hw_info, snd_device_t snd_device, 377 char *device_name) 378{ 379 struct hardware_info *my_data = (struct hardware_info*) hw_info; 380 uint32_t i = 0; 381 382 snd_device_t *snd_devices = 383 (snd_device_t *) my_data->snd_devices; 384 385 if(snd_devices != NULL) { 386 for (i = 0; i < my_data->num_snd_devices; i++) { 387 if (snd_device == (snd_device_t)snd_devices[i]) { 388 ALOGV("extract dev_extn device %d, extn = %s", 389 (snd_device_t)snd_devices[i], my_data->dev_extn); 390 CHECK(strlcat(device_name, my_data->dev_extn, 391 DEVICE_NAME_MAX_SIZE) < DEVICE_NAME_MAX_SIZE); 392 break; 393 } 394 } 395 } 396 ALOGD("%s : device_name = %s", __func__,device_name); 397} 398