platform.c revision b23d5286490ad2dc0edf919d52428fa02dc2b2dc
1b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent/*
2b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent * Copyright (C) 2013 The Android Open Source Project
3b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent *
4b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent * Licensed under the Apache License, Version 2.0 (the "License");
5b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent * you may not use this file except in compliance with the License.
6b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent * You may obtain a copy of the License at
7b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent *
8b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent *      http://www.apache.org/licenses/LICENSE-2.0
9b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent *
10b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent * Unless required by applicable law or agreed to in writing, software
11b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent * distributed under the License is distributed on an "AS IS" BASIS,
12b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent * See the License for the specific language governing permissions and
14b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent * limitations under the License.
15b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent */
16b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent
17b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent#define LOG_TAG "msm8960_platform"
18b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent/*#define LOG_NDEBUG 0*/
19b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent#define LOG_NDDEBUG 0
20b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent
21b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent#include <stdlib.h>
22b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent#include <dlfcn.h>
23b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent#include <cutils/log.h>
24b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent#include <cutils/properties.h>
25b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent#include <audio_hw.h>
26b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent#include <platform_api.h>
27b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent#include "platform.h"
28b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent
29b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent#define LIB_ACDB_LOADER "libacdbloader.so"
30b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent#define LIB_CSD_CLIENT "libcsd-client.so"
31b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent
32b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent#define DUALMIC_CONFIG_NONE 0      /* Target does not contain 2 mics */
33b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent#define DUALMIC_CONFIG_ENDFIRE 1
34b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent#define DUALMIC_CONFIG_BROADSIDE 2
35b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent
36b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent/*
37b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent * This is the sysfs path for the HDMI audio data block
38b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent */
39b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent#define AUDIO_DATA_BLOCK_PATH "/sys/class/graphics/fb1/audio_data_block"
40b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent
41b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent/*
42b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent * This file will have a maximum of 38 bytes:
43b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent *
44b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent * 4 bytes: number of audio blocks
45b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent * 4 bytes: total length of Short Audio Descriptor (SAD) blocks
46b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent * Maximum 10 * 3 bytes: SAD blocks
47b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent */
48b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent#define MAX_SAD_BLOCKS      10
49b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent#define SAD_BLOCK_SIZE      3
50b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent
51b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent/* EDID format ID for LPCM audio */
52b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent#define EDID_FORMAT_LPCM    1
53b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent
54b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurentstruct audio_block_header
55b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent{
56b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    int reserved;
57b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    int length;
58b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent};
59b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent
60b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent
61b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurenttypedef void (*acdb_deallocate_t)();
62b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurenttypedef int  (*acdb_init_t)();
63b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurenttypedef void (*acdb_send_audio_cal_t)(int, int);
64b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurenttypedef void (*acdb_send_voice_cal_t)(int, int);
65b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent
66b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurenttypedef int (*csd_client_init_t)();
67b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurenttypedef int (*csd_client_deinit_t)();
68b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurenttypedef int (*csd_disable_device_t)();
69b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurenttypedef int (*csd_enable_device_t)(int, int, uint32_t);
70b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurenttypedef int (*csd_volume_t)(int);
71b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurenttypedef int (*csd_mic_mute_t)(int);
72b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurenttypedef int (*csd_start_voice_t)();
73b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurenttypedef int (*csd_stop_voice_t)();
74b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent
75b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent
76b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent/* Audio calibration related functions */
77b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurentstruct platform_data {
78b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    struct audio_device *adev;
79b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    bool fluence_in_spkr_mode;
80b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    bool fluence_in_voice_call;
81b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    bool fluence_in_voice_rec;
82b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    int  dualmic_config;
83b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent
84b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    void *acdb_handle;
85b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    acdb_init_t acdb_init;
86b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    acdb_deallocate_t acdb_deallocate;
87b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    acdb_send_audio_cal_t acdb_send_audio_cal;
88b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    acdb_send_voice_cal_t acdb_send_voice_cal;
89b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent
90b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    /* CSD Client related functions for voice call */
91b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    void *csd_client;
92b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    csd_client_init_t csd_client_init;
93b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    csd_client_deinit_t csd_client_deinit;
94b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    csd_disable_device_t csd_disable_device;
95b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    csd_enable_device_t csd_enable_device;
96b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    csd_volume_t csd_volume;
97b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    csd_mic_mute_t csd_mic_mute;
98b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    csd_start_voice_t csd_start_voice;
99b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    csd_stop_voice_t csd_stop_voice;
100b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent};
101b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent
102b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurentstatic const int pcm_device_table[AUDIO_USECASE_MAX][2] = {
103b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {0, 0},
104b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {14, 14},
105b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    [USECASE_AUDIO_PLAYBACK_MULTI_CH] = {1, 1},
106b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    [USECASE_AUDIO_RECORD] = {0, 0},
107b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    [USECASE_AUDIO_RECORD_LOW_LATENCY] = {14, 14},
108b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    [USECASE_VOICE_CALL] = {12, 12},
109b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent};
110b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent
111b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent/* Array to store sound devices */
112b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurentstatic const char * const device_table[SND_DEVICE_MAX] = {
113b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    [SND_DEVICE_NONE] = "none",
114b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    /* Playback sound devices */
115b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    [SND_DEVICE_OUT_HANDSET] = "handset",
116b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    [SND_DEVICE_OUT_SPEAKER] = "speaker",
117b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    [SND_DEVICE_OUT_SPEAKER_REVERSE] = "speaker-reverse",
118b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    [SND_DEVICE_OUT_HEADPHONES] = "headphones",
119b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    [SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES] = "speaker-and-headphones",
120b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    [SND_DEVICE_OUT_VOICE_SPEAKER] = "voice-speaker",
121b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    [SND_DEVICE_OUT_VOICE_HEADPHONES] = "voice-headphones",
122b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    [SND_DEVICE_OUT_HDMI] = "hdmi",
123b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    [SND_DEVICE_OUT_SPEAKER_AND_HDMI] = "speaker-and-hdmi",
124b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    [SND_DEVICE_OUT_BT_SCO] = "bt-sco-headset",
125b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    [SND_DEVICE_OUT_VOICE_HANDSET_TMUS] = "voice-handset-tmus",
126b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    [SND_DEVICE_OUT_VOICE_TTY_FULL_HEADPHONES] = "voice-tty-full-headphones",
127b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    [SND_DEVICE_OUT_VOICE_TTY_VCO_HEADPHONES] = "voice-tty-vco-headphones",
128b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    [SND_DEVICE_OUT_VOICE_TTY_HCO_HANDSET] = "voice-tty-hco-handset",
129b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent
130b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    /* Capture sound devices */
131b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    [SND_DEVICE_IN_HANDSET_MIC] = "handset-mic",
132b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    [SND_DEVICE_IN_SPEAKER_MIC] = "speaker-mic",
133b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    [SND_DEVICE_IN_HEADSET_MIC] = "headset-mic",
134b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    [SND_DEVICE_IN_HANDSET_MIC_AEC] = "handset-mic",
135b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    [SND_DEVICE_IN_SPEAKER_MIC_AEC] = "voice-speaker-mic",
136b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    [SND_DEVICE_IN_HEADSET_MIC_AEC] = "headset-mic",
137b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    [SND_DEVICE_IN_VOICE_SPEAKER_MIC] = "voice-speaker-mic",
138b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    [SND_DEVICE_IN_VOICE_HEADSET_MIC] = "voice-headset-mic",
139b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    [SND_DEVICE_IN_HDMI_MIC] = "hdmi-mic",
140b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    [SND_DEVICE_IN_BT_SCO_MIC] = "bt-sco-mic",
141b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    [SND_DEVICE_IN_CAMCORDER_MIC] = "camcorder-mic",
142b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    [SND_DEVICE_IN_VOICE_DMIC_EF] = "voice-dmic-ef",
143b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    [SND_DEVICE_IN_VOICE_DMIC_BS] = "voice-dmic-bs",
144b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    [SND_DEVICE_IN_VOICE_DMIC_EF_TMUS] = "voice-dmic-ef-tmus",
145b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    [SND_DEVICE_IN_VOICE_SPEAKER_DMIC_EF] = "voice-speaker-dmic-ef",
146b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    [SND_DEVICE_IN_VOICE_SPEAKER_DMIC_BS] = "voice-speaker-dmic-bs",
147b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    [SND_DEVICE_IN_VOICE_TTY_FULL_HEADSET_MIC] = "voice-tty-full-headset-mic",
148b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    [SND_DEVICE_IN_VOICE_TTY_VCO_HANDSET_MIC] = "voice-tty-vco-handset-mic",
149b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    [SND_DEVICE_IN_VOICE_TTY_HCO_HEADSET_MIC] = "voice-tty-hco-headset-mic",
150b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    [SND_DEVICE_IN_VOICE_REC_MIC] = "voice-rec-mic",
151b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    [SND_DEVICE_IN_VOICE_REC_DMIC_EF] = "voice-rec-dmic-ef",
152b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    [SND_DEVICE_IN_VOICE_REC_DMIC_BS] = "voice-rec-dmic-bs",
153b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    [SND_DEVICE_IN_VOICE_REC_DMIC_EF_FLUENCE] = "voice-rec-dmic-ef-fluence",
154b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    [SND_DEVICE_IN_VOICE_REC_DMIC_BS_FLUENCE] = "voice-rec-dmic-bs-fluence",
155b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent};
156b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent
157b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent/* ACDB IDs (audio DSP path configuration IDs) for each sound device */
158b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurentstatic const int acdb_device_table[SND_DEVICE_MAX] = {
159b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    [SND_DEVICE_NONE] = -1,
160b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    [SND_DEVICE_OUT_HANDSET] = 7,
161b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    [SND_DEVICE_OUT_SPEAKER] = 14,
162b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    [SND_DEVICE_OUT_SPEAKER_REVERSE] = 14,
163b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    [SND_DEVICE_OUT_HEADPHONES] = 10,
164b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    [SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES] = 10,
165b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    [SND_DEVICE_OUT_VOICE_SPEAKER] = 14,
166b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    [SND_DEVICE_OUT_VOICE_HEADPHONES] = 10,
167b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    [SND_DEVICE_OUT_HDMI] = 18,
168b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    [SND_DEVICE_OUT_SPEAKER_AND_HDMI] = 14,
169b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    [SND_DEVICE_OUT_BT_SCO] = 22,
170b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    [SND_DEVICE_OUT_VOICE_HANDSET_TMUS] = 81,
171b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    [SND_DEVICE_OUT_VOICE_TTY_FULL_HEADPHONES] = 17,
172b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    [SND_DEVICE_OUT_VOICE_TTY_VCO_HEADPHONES] = 17,
173b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    [SND_DEVICE_OUT_VOICE_TTY_HCO_HANDSET] = 37,
174b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent
175b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    [SND_DEVICE_IN_HANDSET_MIC] = 4,
176b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    [SND_DEVICE_IN_SPEAKER_MIC] = 4,
177b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    [SND_DEVICE_IN_HEADSET_MIC] = 8,
178b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    [SND_DEVICE_IN_HANDSET_MIC_AEC] = 40,
179b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    [SND_DEVICE_IN_SPEAKER_MIC_AEC] = 42,
180b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    [SND_DEVICE_IN_HEADSET_MIC_AEC] = 47,
181b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    [SND_DEVICE_IN_VOICE_SPEAKER_MIC] = 11,
182b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    [SND_DEVICE_IN_VOICE_HEADSET_MIC] = 8,
183b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    [SND_DEVICE_IN_HDMI_MIC] = 4,
184b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    [SND_DEVICE_IN_BT_SCO_MIC] = 21,
185b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    [SND_DEVICE_IN_CAMCORDER_MIC] = 61,
186b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    [SND_DEVICE_IN_VOICE_DMIC_EF] = 6,
187b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    [SND_DEVICE_IN_VOICE_DMIC_BS] = 5,
188b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    [SND_DEVICE_IN_VOICE_DMIC_EF_TMUS] = 91,
189b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    [SND_DEVICE_IN_VOICE_SPEAKER_DMIC_EF] = 13,
190b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    [SND_DEVICE_IN_VOICE_SPEAKER_DMIC_BS] = 12,
191b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    [SND_DEVICE_IN_VOICE_TTY_FULL_HEADSET_MIC] = 16,
192b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    [SND_DEVICE_IN_VOICE_TTY_VCO_HANDSET_MIC] = 36,
193b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    [SND_DEVICE_IN_VOICE_TTY_HCO_HEADSET_MIC] = 16,
194b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    [SND_DEVICE_IN_VOICE_REC_MIC] = 62,
195b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    /* TODO: Update with proper acdb ids */
196b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    [SND_DEVICE_IN_VOICE_REC_DMIC_EF] = 62,
197b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    [SND_DEVICE_IN_VOICE_REC_DMIC_BS] = 62,
198b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    [SND_DEVICE_IN_VOICE_REC_DMIC_EF_FLUENCE] = 6,
199b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    [SND_DEVICE_IN_VOICE_REC_DMIC_BS_FLUENCE] = 5,
200b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent};
201b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent
202b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurentstatic pthread_once_t check_op_once_ctl = PTHREAD_ONCE_INIT;
203b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurentstatic bool is_tmus = false;
204b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent
205b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurentstatic void check_operator()
206b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent{
207b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    char value[PROPERTY_VALUE_MAX];
208b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    int mccmnc;
209b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    property_get("gsm.sim.operator.numeric",value,"0");
210b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    mccmnc = atoi(value);
211b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    ALOGD("%s: tmus mccmnc %d", __func__, mccmnc);
212b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    switch(mccmnc) {
213b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    /* TMUS MCC(310), MNC(490, 260, 026) */
214b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    case 310490:
215b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    case 310260:
216b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    case 310026:
217b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent        is_tmus = true;
218b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent        break;
219b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    }
220b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent}
221b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent
222b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurentbool is_operator_tmus()
223b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent{
224b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    pthread_once(&check_op_once_ctl, check_operator);
225b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    return is_tmus;
226b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent}
227b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent
228b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurentstatic int set_echo_reference(struct mixer *mixer, const char* ec_ref)
229b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent{
230b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    struct mixer_ctl *ctl;
231b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    const char *mixer_ctl_name = "EC_REF_RX";
232b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent
233b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    ctl = mixer_get_ctl_by_name(mixer, mixer_ctl_name);
234b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    if (!ctl) {
235b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent        ALOGE("%s: Could not get ctl for mixer cmd - %s",
236b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent              __func__, mixer_ctl_name);
237b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent        return -EINVAL;
238b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    }
239b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    ALOGV("Setting EC Reference: %s", ec_ref);
240b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    mixer_ctl_set_enum_by_string(ctl, ec_ref);
241b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    return 0;
242b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent}
243b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent
244b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurentvoid *platform_init(struct audio_device *adev)
245b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent{
246b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    char platform[PROPERTY_VALUE_MAX];
247b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    char baseband[PROPERTY_VALUE_MAX];
248b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    char value[PROPERTY_VALUE_MAX];
249b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    struct platform_data *my_data;
250b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent
251b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    my_data = calloc(1, sizeof(struct platform_data));
252b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent
253b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    my_data->adev = adev;
254b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    my_data->dualmic_config = DUALMIC_CONFIG_NONE;
255b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    my_data->fluence_in_spkr_mode = false;
256b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    my_data->fluence_in_voice_call = false;
257b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    my_data->fluence_in_voice_rec = false;
258b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent
259b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    property_get("persist.audio.dualmic.config",value,"");
260b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    if (!strcmp("broadside", value)) {
261b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent        my_data->dualmic_config = DUALMIC_CONFIG_BROADSIDE;
262b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent        adev->acdb_settings |= DMIC_FLAG;
263b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    } else if (!strcmp("endfire", value)) {
264b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent        my_data->dualmic_config = DUALMIC_CONFIG_ENDFIRE;
265b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent        adev->acdb_settings |= DMIC_FLAG;
266b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    }
267b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent
268b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    if (my_data->dualmic_config != DUALMIC_CONFIG_NONE) {
269b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent        property_get("persist.audio.fluence.voicecall",value,"");
270b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent        if (!strcmp("true", value)) {
271b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent            my_data->fluence_in_voice_call = true;
272b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent        }
273b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent
274b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent        property_get("persist.audio.fluence.voicerec",value,"");
275b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent        if (!strcmp("true", value)) {
276b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent            my_data->fluence_in_voice_rec = true;
277b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent        }
278b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent
279b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent        property_get("persist.audio.fluence.speaker",value,"");
280b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent        if (!strcmp("true", value)) {
281b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent            my_data->fluence_in_spkr_mode = true;
282b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent        }
283b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    }
284b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent
285b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    my_data->acdb_handle = dlopen(LIB_ACDB_LOADER, RTLD_NOW);
286b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    if (my_data->acdb_handle == NULL) {
287b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent        ALOGE("%s: DLOPEN failed for %s", __func__, LIB_ACDB_LOADER);
288b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    } else {
289b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent        ALOGV("%s: DLOPEN successful for %s", __func__, LIB_ACDB_LOADER);
290b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent        my_data->acdb_deallocate = (acdb_deallocate_t)dlsym(my_data->acdb_handle,
291b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent                                                    "acdb_loader_deallocate_ACDB");
292b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent        my_data->acdb_send_audio_cal = (acdb_send_audio_cal_t)dlsym(my_data->acdb_handle,
293b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent                                                    "acdb_loader_send_audio_cal");
294b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent        if (!my_data->acdb_send_audio_cal)
295b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent            ALOGW("%s: Could not find the symbol acdb_send_audio_cal from %s",
296b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent                  __func__, LIB_ACDB_LOADER);
297b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent        my_data->acdb_send_voice_cal = (acdb_send_voice_cal_t)dlsym(my_data->acdb_handle,
298b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent                                                    "acdb_loader_send_voice_cal");
299b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent        my_data->acdb_init = (acdb_init_t)dlsym(my_data->acdb_handle,
300b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent                                                    "acdb_loader_init_ACDB");
301b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent        if (my_data->acdb_init == NULL)
302b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent            ALOGE("%s: dlsym error %s for acdb_loader_init_ACDB", __func__, dlerror());
303b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent        else
304b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent            my_data->acdb_init();
305b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    }
306b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent
307b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    /* If platform is Fusion3, load CSD Client specific symbols
308b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent     * Voice call is handled by MDM and apps processor talks to
309b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent     * MDM through CSD Client
310b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent     */
311b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    property_get("ro.board.platform", platform, "");
312b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    property_get("ro.baseband", baseband, "");
313b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    if (!strcmp("msm8960", platform) && !strcmp("mdm", baseband)) {
314b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent        my_data->csd_client = dlopen(LIB_CSD_CLIENT, RTLD_NOW);
315b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent        if (my_data->csd_client == NULL)
316b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent            ALOGE("%s: DLOPEN failed for %s", __func__, LIB_CSD_CLIENT);
317b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    }
318b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent
319b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    if (my_data->csd_client) {
320b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent        ALOGV("%s: DLOPEN successful for %s", __func__, LIB_CSD_CLIENT);
321b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent        my_data->csd_client_deinit = (csd_client_deinit_t)dlsym(my_data->csd_client,
322b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent                                                    "csd_client_deinit");
323b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent        my_data->csd_disable_device = (csd_disable_device_t)dlsym(my_data->csd_client,
324b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent                                                    "csd_client_disable_device");
325b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent        my_data->csd_enable_device = (csd_enable_device_t)dlsym(my_data->csd_client,
326b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent                                                    "csd_client_enable_device");
327b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent        my_data->csd_start_voice = (csd_start_voice_t)dlsym(my_data->csd_client,
328b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent                                                    "csd_client_start_voice");
329b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent        my_data->csd_stop_voice = (csd_stop_voice_t)dlsym(my_data->csd_client,
330b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent                                                    "csd_client_stop_voice");
331b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent        my_data->csd_volume = (csd_volume_t)dlsym(my_data->csd_client,
332b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent                                                    "csd_client_volume");
333b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent        my_data->csd_mic_mute = (csd_mic_mute_t)dlsym(my_data->csd_client,
334b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent                                                    "csd_client_mic_mute");
335b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent        my_data->csd_client_init = (csd_client_init_t)dlsym(my_data->csd_client,
336b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent                                                    "csd_client_init");
337b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent
338b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent        if (my_data->csd_client_init == NULL) {
339b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent            ALOGE("%s: dlsym error %s for csd_client_init", __func__, dlerror());
340b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent        } else {
341b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent            my_data->csd_client_init();
342b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent        }
343b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    }
344b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent
345b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    return my_data;
346b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent}
347b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent
348b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurentvoid platform_deinit(void *platform)
349b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent{
350b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    free(platform);
351b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent}
352b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent
353b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurentconst char *platform_get_snd_device_name(snd_device_t snd_device)
354b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent{
355b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    if (snd_device >= SND_DEVICE_MIN && snd_device < SND_DEVICE_MAX)
356b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent        return device_table[snd_device];
357b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    else
358b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent        return "";
359b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent}
360b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent
361b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurentvoid platform_add_backend_name(char *mixer_path, snd_device_t snd_device)
362b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent{
363b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    if (snd_device == SND_DEVICE_IN_BT_SCO_MIC)
364b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent        strcat(mixer_path, " bt-sco");
365b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    else if(snd_device == SND_DEVICE_OUT_BT_SCO)
366b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent        strcat(mixer_path, " bt-sco");
367b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    else if (snd_device == SND_DEVICE_OUT_HDMI)
368b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent        strcat(mixer_path, " hdmi");
369b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    else if (snd_device == SND_DEVICE_OUT_SPEAKER_AND_HDMI)
370b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent        strcat(mixer_path, " speaker-and-hdmi");
371b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent}
372b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent
373b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurentint platform_get_pcm_device_id(audio_usecase_t usecase, int device_type)
374b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent{
375b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    int device_id;
376b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    if (device_type == PCM_PLAYBACK)
377b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent        device_id = pcm_device_table[usecase][0];
378b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    else
379b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent        device_id = pcm_device_table[usecase][1];
380b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    return device_id;
381b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent}
382b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent
383b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurentint platform_send_audio_calibration(void *platform, snd_device_t snd_device)
384b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent{
385b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    struct platform_data *my_data = (struct platform_data *)platform;
386b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    int acdb_dev_id, acdb_dev_type;
387b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent
388b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    acdb_dev_id = acdb_device_table[snd_device];
389b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    if (acdb_dev_id < 0) {
390b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent        ALOGE("%s: Could not find acdb id for device(%d)",
391b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent              __func__, snd_device);
392b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent        return -EINVAL;
393b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    }
394b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    if (my_data->acdb_send_audio_cal) {
395b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent        ALOGD("%s: sending audio calibration for snd_device(%d) acdb_id(%d)",
396b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent              __func__, snd_device, acdb_dev_id);
397b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent        if (snd_device >= SND_DEVICE_OUT_BEGIN &&
398b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent                snd_device < SND_DEVICE_OUT_END)
399b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent            acdb_dev_type = ACDB_DEV_TYPE_OUT;
400b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent        else
401b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent            acdb_dev_type = ACDB_DEV_TYPE_IN;
402b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent        my_data->acdb_send_audio_cal(acdb_dev_id, acdb_dev_type);
403b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    }
404b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    return 0;
405b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent}
406b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent
407b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurentint platform_switch_voice_call_device_pre(void *platform)
408b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent{
409b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    struct platform_data *my_data = (struct platform_data *)platform;
410b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    int ret = 0;
411b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent
412b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    if (my_data->csd_client != NULL) {
413b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent        /* This must be called before disabling the mixer controls on APQ side */
414b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent        if (my_data->csd_disable_device == NULL) {
415b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent            ALOGE("%s: dlsym error for csd_disable_device", __func__);
416b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent        } else {
417b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent            ret = my_data->csd_disable_device();
418b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent            if (ret < 0) {
419b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent                ALOGE("%s: csd_client_disable_device, failed, error %d",
420b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent                      __func__, ret);
421b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent            }
422b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent        }
423b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    }
424b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    return ret;
425b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent}
426b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent
427b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurentint platform_switch_voice_call_device_post(void *platform,
428b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent                                           snd_device_t out_snd_device,
429b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent                                           snd_device_t in_snd_device)
430b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent{
431b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    struct platform_data *my_data = (struct platform_data *)platform;
432b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    int acdb_rx_id, acdb_tx_id;
433b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    int ret = 0;
434b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent
435b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    if (my_data->csd_client) {
436b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent        if (my_data->csd_enable_device == NULL) {
437b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent            ALOGE("%s: dlsym error for csd_enable_device",
438b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent                  __func__);
439b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent        } else {
440b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent            acdb_rx_id = acdb_device_table[out_snd_device];
441b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent            acdb_tx_id = acdb_device_table[in_snd_device];
442b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent
443b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent            if (acdb_rx_id > 0 || acdb_tx_id > 0) {
444b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent                ret = my_data->csd_enable_device(acdb_rx_id, acdb_tx_id,
445b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent                                                    my_data->adev->acdb_settings);
446b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent                if (ret < 0) {
447b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent                    ALOGE("%s: csd_enable_device, failed, error %d",
448b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent                          __func__, ret);
449b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent                }
450b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent            } else {
451b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent                ALOGE("%s: Incorrect ACDB IDs (rx: %d tx: %d)", __func__,
452b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent                      acdb_rx_id, acdb_tx_id);
453b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent            }
454b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent        }
455b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    }
456b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent
457b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    return ret;
458b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent}
459b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent
460b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurentint platform_start_voice_call(void *platform)
461b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent{
462b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    struct platform_data *my_data = (struct platform_data *)platform;
463b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    int ret = 0;
464b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent
465b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    if (my_data->csd_client) {
466b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent        if (my_data->csd_start_voice == NULL) {
467b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent            ALOGE("dlsym error for csd_client_start_voice");
468b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent            ret = -ENOSYS;
469b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent        } else {
470b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent            ret = my_data->csd_start_voice();
471b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent            if (ret < 0) {
472b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent                ALOGE("%s: csd_start_voice error %d\n", __func__, ret);
473b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent            }
474b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent        }
475b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    }
476b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent
477b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    return ret;
478b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent}
479b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent
480b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurentint platform_stop_voice_call(void *platform)
481b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent{
482b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    struct platform_data *my_data = (struct platform_data *)platform;
483b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    int ret = 0;
484b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent
485b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    if (my_data->csd_client) {
486b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent        if (my_data->csd_stop_voice == NULL) {
487b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent            ALOGE("dlsym error for csd_stop_voice");
488b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent        } else {
489b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent            ret = my_data->csd_stop_voice();
490b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent            if (ret < 0) {
491b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent                ALOGE("%s: csd_stop_voice error %d\n", __func__, ret);
492b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent            }
493b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent        }
494b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    }
495b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent
496b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    return ret;
497b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent}
498b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent
499b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurentint platform_set_voice_volume(void *platform, int volume)
500b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent{
501b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    struct platform_data *my_data = (struct platform_data *)platform;
502b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    int ret = 0;
503b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent
504b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    if (my_data->csd_client) {
505b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent        if (my_data->csd_volume == NULL) {
506b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent            ALOGE("%s: dlsym error for csd_volume", __func__);
507b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent        } else {
508b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent            ret = my_data->csd_volume(volume);
509b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent            if (ret < 0) {
510b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent                ALOGE("%s: csd_volume error %d", __func__, ret);
511b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent            }
512b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent        }
513b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    } else {
514b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent        ALOGE("%s: No CSD Client present", __func__);
515b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    }
516b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent
517b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    return ret;
518b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent}
519b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent
520b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurentint platform_set_mic_mute(void *platform, bool state)
521b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent{
522b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    struct platform_data *my_data = (struct platform_data *)platform;
523b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    int ret = 0;
524b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent
525b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    if (my_data->adev->mode == AUDIO_MODE_IN_CALL) {
526b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent        if (my_data->csd_client) {
527b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent            if (my_data->csd_mic_mute == NULL) {
528b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent                ALOGE("%s: dlsym error for csd_mic_mute", __func__);
529b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent            } else {
530b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent                ret = my_data->csd_mic_mute(state);
531b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent                if (ret < 0) {
532b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent                    ALOGE("%s: csd_mic_mute error %d", __func__, ret);
533b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent                }
534b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent            }
535b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent        } else {
536b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent            ALOGE("%s: No CSD Client present", __func__);
537b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent        }
538b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    }
539b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent
540b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    return ret;
541b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent}
542b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent
543b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurentsnd_device_t platform_get_output_snd_device(void *platform, audio_devices_t devices)
544b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent{
545b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    struct platform_data *my_data = (struct platform_data *)platform;
546b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    struct audio_device *adev = my_data->adev;
547b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    audio_mode_t mode = adev->mode;
548b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    snd_device_t snd_device = SND_DEVICE_NONE;
549b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent
550b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    ALOGV("%s: enter: output devices(%#x)", __func__, devices);
551b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    if (devices == AUDIO_DEVICE_NONE ||
552b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent        devices & AUDIO_DEVICE_BIT_IN) {
553b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent        ALOGV("%s: Invalid output devices (%#x)", __func__, devices);
554b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent        goto exit;
555b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    }
556b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent
557b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    if (mode == AUDIO_MODE_IN_CALL) {
558b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent        if (devices & AUDIO_DEVICE_OUT_WIRED_HEADPHONE ||
559b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent            devices & AUDIO_DEVICE_OUT_WIRED_HEADSET) {
560b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent            if (adev->tty_mode == TTY_MODE_FULL)
561b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent                snd_device = SND_DEVICE_OUT_VOICE_TTY_FULL_HEADPHONES;
562b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent            else if (adev->tty_mode == TTY_MODE_VCO)
563b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent                snd_device = SND_DEVICE_OUT_VOICE_TTY_VCO_HEADPHONES;
564b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent            else if (adev->tty_mode == TTY_MODE_HCO)
565b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent                snd_device = SND_DEVICE_OUT_VOICE_TTY_HCO_HANDSET;
566b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent            else
567b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent                snd_device = SND_DEVICE_OUT_VOICE_HEADPHONES;
568b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent        } else if (devices & AUDIO_DEVICE_OUT_ALL_SCO) {
569b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent            snd_device = SND_DEVICE_OUT_BT_SCO;
570b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent        } else if (devices & AUDIO_DEVICE_OUT_SPEAKER) {
571b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent            snd_device = SND_DEVICE_OUT_VOICE_SPEAKER;
572b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent        } else if (devices & AUDIO_DEVICE_OUT_EARPIECE) {
573b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent            if (is_operator_tmus())
574b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent                snd_device = SND_DEVICE_OUT_VOICE_HANDSET_TMUS;
575b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent            else
576b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent                snd_device = SND_DEVICE_OUT_HANDSET;
577b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent        }
578b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent        if (snd_device != SND_DEVICE_NONE) {
579b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent            goto exit;
580b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent        }
581b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    }
582b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent
583b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    if (popcount(devices) == 2) {
584b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent        if (devices == (AUDIO_DEVICE_OUT_WIRED_HEADPHONE |
585b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent                        AUDIO_DEVICE_OUT_SPEAKER)) {
586b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent            snd_device = SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES;
587b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent        } else if (devices == (AUDIO_DEVICE_OUT_WIRED_HEADSET |
588b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent                               AUDIO_DEVICE_OUT_SPEAKER)) {
589b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent            snd_device = SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES;
590b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent        } else if (devices == (AUDIO_DEVICE_OUT_AUX_DIGITAL |
591b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent                               AUDIO_DEVICE_OUT_SPEAKER)) {
592b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent            snd_device = SND_DEVICE_OUT_SPEAKER_AND_HDMI;
593b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent        } else {
594b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent            ALOGE("%s: Invalid combo device(%#x)", __func__, devices);
595b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent            goto exit;
596b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent        }
597b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent        if (snd_device != SND_DEVICE_NONE) {
598b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent            goto exit;
599b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent        }
600b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    }
601b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent
602b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    if (popcount(devices) != 1) {
603b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent        ALOGE("%s: Invalid output devices(%#x)", __func__, devices);
604b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent        goto exit;
605b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    }
606b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent
607b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    if (devices & AUDIO_DEVICE_OUT_WIRED_HEADPHONE ||
608b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent        devices & AUDIO_DEVICE_OUT_WIRED_HEADSET) {
609b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent        snd_device = SND_DEVICE_OUT_HEADPHONES;
610b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    } else if (devices & AUDIO_DEVICE_OUT_SPEAKER) {
611b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent        if (adev->speaker_lr_swap)
612b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent            snd_device = SND_DEVICE_OUT_SPEAKER_REVERSE;
613b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent        else
614b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent            snd_device = SND_DEVICE_OUT_SPEAKER;
615b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    } else if (devices & AUDIO_DEVICE_OUT_ALL_SCO) {
616b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent        snd_device = SND_DEVICE_OUT_BT_SCO;
617b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    } else if (devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
618b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent        snd_device = SND_DEVICE_OUT_HDMI ;
619b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    } else if (devices & AUDIO_DEVICE_OUT_EARPIECE) {
620b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent        snd_device = SND_DEVICE_OUT_HANDSET;
621b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    } else {
622b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent        ALOGE("%s: Unknown device(s) %#x", __func__, devices);
623b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    }
624b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurentexit:
625b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    ALOGV("%s: exit: snd_device(%s)", __func__, device_table[snd_device]);
626b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    return snd_device;
627b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent}
628b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent
629b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurentsnd_device_t platform_get_input_snd_device(void *platform, audio_devices_t out_device)
630b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent{
631b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    struct platform_data *my_data = (struct platform_data *)platform;
632b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    struct audio_device *adev = my_data->adev;
633b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    audio_source_t  source = (adev->active_input == NULL) ?
634b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent                                AUDIO_SOURCE_DEFAULT : adev->active_input->source;
635b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent
636b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    audio_mode_t    mode   = adev->mode;
637b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    audio_devices_t in_device = ((adev->active_input == NULL) ?
638b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent                                    AUDIO_DEVICE_NONE : adev->active_input->device)
639b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent                                & ~AUDIO_DEVICE_BIT_IN;
640b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    audio_channel_mask_t channel_mask = (adev->active_input == NULL) ?
641b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent                                AUDIO_CHANNEL_IN_MONO : adev->active_input->channel_mask;
642b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    snd_device_t snd_device = SND_DEVICE_NONE;
643b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent
644b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    ALOGV("%s: enter: out_device(%#x) in_device(%#x)",
645b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent          __func__, out_device, in_device);
646b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    if (mode == AUDIO_MODE_IN_CALL) {
647b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent        if (out_device == AUDIO_DEVICE_NONE) {
648b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent            ALOGE("%s: No output device set for voice call", __func__);
649b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent            goto exit;
650b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent        }
651b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent        if (adev->tty_mode != TTY_MODE_OFF) {
652b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent            if (out_device & AUDIO_DEVICE_OUT_WIRED_HEADPHONE ||
653b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent                out_device & AUDIO_DEVICE_OUT_WIRED_HEADSET) {
654b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent                switch (adev->tty_mode) {
655b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent                case TTY_MODE_FULL:
656b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent                    snd_device = SND_DEVICE_IN_VOICE_TTY_FULL_HEADSET_MIC;
657b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent                    break;
658b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent                case TTY_MODE_VCO:
659b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent                    snd_device = SND_DEVICE_IN_VOICE_TTY_VCO_HANDSET_MIC;
660b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent                    break;
661b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent                case TTY_MODE_HCO:
662b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent                    snd_device = SND_DEVICE_IN_VOICE_TTY_HCO_HEADSET_MIC;
663b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent                    break;
664b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent                default:
665b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent                    ALOGE("%s: Invalid TTY mode (%#x)", __func__, adev->tty_mode);
666b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent                }
667b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent                goto exit;
668b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent            }
669b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent        }
670b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent        if (out_device & AUDIO_DEVICE_OUT_EARPIECE ||
671b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent            out_device & AUDIO_DEVICE_OUT_WIRED_HEADPHONE) {
672b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent            if (my_data->fluence_in_voice_call == false) {
673b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent                snd_device = SND_DEVICE_IN_HANDSET_MIC;
674b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent            } else {
675b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent                if (my_data->dualmic_config == DUALMIC_CONFIG_ENDFIRE) {
676b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent                    if (is_operator_tmus())
677b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent                        snd_device = SND_DEVICE_IN_VOICE_DMIC_EF_TMUS;
678b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent                    else
679b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent                        snd_device = SND_DEVICE_IN_VOICE_DMIC_EF;
680b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent                } else if(my_data->dualmic_config == DUALMIC_CONFIG_BROADSIDE)
681b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent                    snd_device = SND_DEVICE_IN_VOICE_DMIC_BS;
682b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent                else
683b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent                    snd_device = SND_DEVICE_IN_HANDSET_MIC;
684b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent            }
685b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent        } else if (out_device & AUDIO_DEVICE_OUT_WIRED_HEADSET) {
686b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent            snd_device = SND_DEVICE_IN_VOICE_HEADSET_MIC;
687b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent        } else if (out_device & AUDIO_DEVICE_OUT_ALL_SCO) {
688b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent            snd_device = SND_DEVICE_IN_BT_SCO_MIC ;
689b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent        } else if (out_device & AUDIO_DEVICE_OUT_SPEAKER) {
690b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent            if (my_data->fluence_in_voice_call && my_data->fluence_in_spkr_mode &&
691b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent                    my_data->dualmic_config == DUALMIC_CONFIG_ENDFIRE) {
692b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent                snd_device = SND_DEVICE_IN_VOICE_SPEAKER_DMIC_EF;
693b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent            } else if (my_data->fluence_in_voice_call && my_data->fluence_in_spkr_mode &&
694b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent                    my_data->dualmic_config == DUALMIC_CONFIG_BROADSIDE) {
695b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent                snd_device = SND_DEVICE_IN_VOICE_SPEAKER_DMIC_BS;
696b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent            } else {
697b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent                snd_device = SND_DEVICE_IN_VOICE_SPEAKER_MIC;
698b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent            }
699b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent        }
700b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    } else if (source == AUDIO_SOURCE_CAMCORDER) {
701b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent        if (in_device & AUDIO_DEVICE_IN_BUILTIN_MIC ||
702b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent            in_device & AUDIO_DEVICE_IN_BACK_MIC) {
703b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent            snd_device = SND_DEVICE_IN_CAMCORDER_MIC;
704b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent        }
705b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    } else if (source == AUDIO_SOURCE_VOICE_RECOGNITION) {
706b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent        if (in_device & AUDIO_DEVICE_IN_BUILTIN_MIC) {
707b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent            if (my_data->dualmic_config == DUALMIC_CONFIG_ENDFIRE) {
708b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent                if (channel_mask == AUDIO_CHANNEL_IN_FRONT_BACK)
709b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent                    snd_device = SND_DEVICE_IN_VOICE_REC_DMIC_EF;
710b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent                else if (my_data->fluence_in_voice_rec)
711b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent                    snd_device = SND_DEVICE_IN_VOICE_REC_DMIC_EF_FLUENCE;
712b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent            } else if (my_data->dualmic_config == DUALMIC_CONFIG_BROADSIDE) {
713b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent                if (channel_mask == AUDIO_CHANNEL_IN_FRONT_BACK)
714b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent                    snd_device = SND_DEVICE_IN_VOICE_REC_DMIC_BS;
715b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent                else if (my_data->fluence_in_voice_rec)
716b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent                    snd_device = SND_DEVICE_IN_VOICE_REC_DMIC_BS_FLUENCE;
717b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent            }
718b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent
719b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent            if (snd_device == SND_DEVICE_NONE) {
720b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent                snd_device = SND_DEVICE_IN_VOICE_REC_MIC;
721b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent            }
722b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent        }
723b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    } else if (source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
724b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent        if (out_device & AUDIO_DEVICE_OUT_SPEAKER)
725b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent            in_device = AUDIO_DEVICE_IN_BACK_MIC;
726b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent        if (adev->active_input) {
727b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent            if (adev->active_input->enable_aec) {
728b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent                if (in_device & AUDIO_DEVICE_IN_BACK_MIC) {
729b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent                    snd_device = SND_DEVICE_IN_SPEAKER_MIC_AEC;
730b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent                } else if (in_device & AUDIO_DEVICE_IN_BUILTIN_MIC) {
731b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent                    snd_device = SND_DEVICE_IN_HANDSET_MIC_AEC;
732b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent                } else if (in_device & AUDIO_DEVICE_IN_WIRED_HEADSET) {
733b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent                    snd_device = SND_DEVICE_IN_HEADSET_MIC_AEC;
734b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent                }
735b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent                set_echo_reference(adev->mixer, "SLIM_RX");
736b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent            } else
737b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent                set_echo_reference(adev->mixer, "NONE");
738b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent        }
739b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    } else if (source == AUDIO_SOURCE_DEFAULT) {
740b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent        goto exit;
741b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    }
742b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent
743b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent
744b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    if (snd_device != SND_DEVICE_NONE) {
745b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent        goto exit;
746b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    }
747b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent
748b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    if (in_device != AUDIO_DEVICE_NONE &&
749b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent            !(in_device & AUDIO_DEVICE_IN_VOICE_CALL) &&
750b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent            !(in_device & AUDIO_DEVICE_IN_COMMUNICATION)) {
751b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent        if (in_device & AUDIO_DEVICE_IN_BUILTIN_MIC) {
752b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent            snd_device = SND_DEVICE_IN_HANDSET_MIC;
753b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent        } else if (in_device & AUDIO_DEVICE_IN_BACK_MIC) {
754b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent            snd_device = SND_DEVICE_IN_SPEAKER_MIC;
755b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent        } else if (in_device & AUDIO_DEVICE_IN_WIRED_HEADSET) {
756b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent            snd_device = SND_DEVICE_IN_HEADSET_MIC;
757b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent        } else if (in_device & AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET) {
758b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent            snd_device = SND_DEVICE_IN_BT_SCO_MIC ;
759b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent        } else if (in_device & AUDIO_DEVICE_IN_AUX_DIGITAL) {
760b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent            snd_device = SND_DEVICE_IN_HDMI_MIC;
761b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent        } else {
762b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent            ALOGE("%s: Unknown input device(s) %#x", __func__, in_device);
763b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent            ALOGW("%s: Using default handset-mic", __func__);
764b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent            snd_device = SND_DEVICE_IN_HANDSET_MIC;
765b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent        }
766b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    } else {
767b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent        if (out_device & AUDIO_DEVICE_OUT_EARPIECE) {
768b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent            snd_device = SND_DEVICE_IN_HANDSET_MIC;
769b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent        } else if (out_device & AUDIO_DEVICE_OUT_WIRED_HEADSET) {
770b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent            snd_device = SND_DEVICE_IN_HEADSET_MIC;
771b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent        } else if (out_device & AUDIO_DEVICE_OUT_SPEAKER) {
772b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent            snd_device = SND_DEVICE_IN_SPEAKER_MIC;
773b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent        } else if (out_device & AUDIO_DEVICE_OUT_WIRED_HEADPHONE) {
774b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent            snd_device = SND_DEVICE_IN_HANDSET_MIC;
775b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent        } else if (out_device & AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET) {
776b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent            snd_device = SND_DEVICE_IN_BT_SCO_MIC;
777b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent        } else if (out_device & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
778b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent            snd_device = SND_DEVICE_IN_HDMI_MIC;
779b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent        } else {
780b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent            ALOGE("%s: Unknown output device(s) %#x", __func__, out_device);
781b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent            ALOGW("%s: Using default handset-mic", __func__);
782b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent            snd_device = SND_DEVICE_IN_HANDSET_MIC;
783b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent        }
784b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    }
785b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurentexit:
786b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    ALOGV("%s: exit: in_snd_device(%s)", __func__, device_table[snd_device]);
787b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    return snd_device;
788b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent}
789b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent
790b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurentint platform_set_hdmi_channels(void *platform,  int channel_count)
791b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent{
792b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    struct platform_data *my_data = (struct platform_data *)platform;
793b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    struct audio_device *adev = my_data->adev;
794b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    struct mixer_ctl *ctl;
795b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    const char *channel_cnt_str = NULL;
796b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    const char *mixer_ctl_name = "HDMI_RX Channels";
797b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    switch (channel_count) {
798b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    case 8:
799b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent        channel_cnt_str = "Eight"; break;
800b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    case 7:
801b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent        channel_cnt_str = "Seven"; break;
802b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    case 6:
803b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent        channel_cnt_str = "Six"; break;
804b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    case 5:
805b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent        channel_cnt_str = "Five"; break;
806b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    case 4:
807b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent        channel_cnt_str = "Four"; break;
808b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    case 3:
809b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent        channel_cnt_str = "Three"; break;
810b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    default:
811b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent        channel_cnt_str = "Two"; break;
812b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    }
813b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
814b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    if (!ctl) {
815b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent        ALOGE("%s: Could not get ctl for mixer cmd - %s",
816b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent              __func__, mixer_ctl_name);
817b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent        return -EINVAL;
818b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    }
819b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    ALOGV("HDMI channel count: %s", channel_cnt_str);
820b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    mixer_ctl_set_enum_by_string(ctl, channel_cnt_str);
821b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    return 0;
822b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent}
823b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent
824b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurentint platform_edid_get_max_channels(void)
825b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent{
826b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    FILE *file;
827b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    struct audio_block_header header;
828b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    char block[MAX_SAD_BLOCKS * SAD_BLOCK_SIZE];
829b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    char *sad = block;
830b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    int num_audio_blocks;
831b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    int channel_count;
832b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    int max_channels = 0;
833b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    int i;
834b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent
835b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    file = fopen(AUDIO_DATA_BLOCK_PATH, "rb");
836b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    if (file == NULL) {
837b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent        ALOGE("Unable to open '%s'", AUDIO_DATA_BLOCK_PATH);
838b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent        return 0;
839b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    }
840b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent
841b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    /* Read audio block header */
842b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    fread(&header, 1, sizeof(header), file);
843b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent
844b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    /* Read SAD blocks, clamping the maximum size for safety */
845b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    if (header.length > (int)sizeof(block))
846b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent        header.length = (int)sizeof(block);
847b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    fread(&block, header.length, 1, file);
848b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent
849b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    fclose(file);
850b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent
851b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    /* Calculate the number of SAD blocks */
852b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    num_audio_blocks = header.length / SAD_BLOCK_SIZE;
853b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent
854b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    for (i = 0; i < num_audio_blocks; i++) {
855b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent        /* Only consider LPCM blocks */
856b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent        if ((sad[0] >> 3) != EDID_FORMAT_LPCM)
857b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent            continue;
858b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent
859b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent        channel_count = (sad[0] & 0x7) + 1;
860b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent        if (channel_count > max_channels)
861b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent            max_channels = channel_count;
862b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent
863b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent        /* Advance to next block */
864b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent        sad += 3;
865b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    }
866b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent
867b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent    return max_channels;
868b23d5286490ad2dc0edf919d52428fa02dc2b2dcEric Laurent}
869