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