PageRenderTime 59ms CodeModel.GetById 27ms app.highlight 27ms RepoModel.GetById 1ms app.codeStats 0ms

/arch/arm/mach-msm/board-mahimahi-audio.c

https://github.com/AICP/kernel_google_msm
C | 283 lines | 226 code | 38 blank | 19 comment | 39 complexity | 7015f101937b4aee690ce0635c286ab5 MD5 | raw file
  1/* arch/arm/mach-msm/board-mahimahi-audio.c
  2 *
  3 * Copyright (C) 2009 HTC Corporation
  4 * Copyright (C) 2009 Google Inc.
  5 *
  6 * This software is licensed under the terms of the GNU General Public
  7 * License version 2, as published by the Free Software Foundation, and
  8 * may be copied, distributed, and modified under those terms.
  9 *
 10 * This program is distributed in the hope that it will be useful,
 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 13 * GNU General Public License for more details.
 14 *
 15 */
 16
 17#include <linux/gpio.h>
 18#include <linux/delay.h>
 19#include <mach/msm_qdsp6_audio.h>
 20#include <mach/htc_acoustic_qsd.h>
 21#include <mach/proc_comm.h>
 22
 23#include "board-mahimahi.h"
 24#include "pmic.h"
 25#include "board-mahimahi-tpa2018d1.h"
 26
 27#if 0
 28#define D(fmt, args...) printk(KERN_INFO "Audio: "fmt, ##args)
 29#else
 30#define D(fmt, args...) do {} while (0)
 31#endif
 32
 33static struct mutex mic_lock;
 34static struct mutex bt_sco_lock;
 35
 36static struct q6_hw_info q6_audio_hw[Q6_HW_COUNT] = {
 37	[Q6_HW_HANDSET] = {
 38		.min_gain = -2000,
 39		.max_gain = 0,
 40	},
 41	[Q6_HW_HEADSET] = {
 42		.min_gain = -2000,
 43		.max_gain = 0,
 44	},
 45	[Q6_HW_SPEAKER] = {
 46		.min_gain = -1500,
 47		.max_gain = 0,
 48	},
 49	[Q6_HW_TTY] = {
 50		.min_gain = -2000,
 51		.max_gain = 0,
 52	},
 53	[Q6_HW_BT_SCO] = {
 54		.min_gain = -2000,
 55		.max_gain = 0,
 56	},
 57	[Q6_HW_BT_A2DP] = {
 58		.min_gain = -2000,
 59		.max_gain = 0,
 60	},
 61};
 62
 63void mahimahi_headset_enable(int en)
 64{
 65	D("%s %d\n", __func__, en);
 66	/* enable audio amp */
 67	if (en) mdelay(15);
 68	gpio_set_value(MAHIMAHI_AUD_JACKHP_EN, !!en);
 69}
 70
 71void mahimahi_speaker_enable(int en)
 72{
 73	struct spkr_config_mode scm;
 74	memset(&scm, 0, sizeof(scm));
 75
 76	D("%s %d\n", __func__, en);
 77	if (en) {
 78		scm.is_right_chan_en = 0;
 79		scm.is_left_chan_en = 1;
 80		scm.is_stereo_en = 0;
 81		scm.is_hpf_en = 1;
 82		pmic_spkr_en_mute(LEFT_SPKR, 0);
 83		pmic_spkr_en_mute(RIGHT_SPKR, 0);
 84		pmic_set_spkr_configuration(&scm);
 85		pmic_spkr_en(LEFT_SPKR, 1);
 86		pmic_spkr_en(RIGHT_SPKR, 0);
 87
 88		/* unmute */
 89		pmic_spkr_en_mute(LEFT_SPKR, 1);
 90	} else {
 91		pmic_spkr_en_mute(LEFT_SPKR, 0);
 92
 93		pmic_spkr_en(LEFT_SPKR, 0);
 94		pmic_spkr_en(RIGHT_SPKR, 0);
 95
 96		pmic_set_spkr_configuration(&scm);
 97	}
 98
 99	if (is_cdma_version(system_rev))
100		tpa2018d1_set_speaker_amp(en);
101}
102
103void mahimahi_receiver_enable(int en)
104{
105	if (is_cdma_version(system_rev) &&
106		((system_rev == 0xC1) || (system_rev == 0xC2))) {
107		struct spkr_config_mode scm;
108		memset(&scm, 0, sizeof(scm));
109
110		D("%s %d\n", __func__, en);
111		if (en) {
112			scm.is_right_chan_en = 1;
113			scm.is_left_chan_en = 0;
114			scm.is_stereo_en = 0;
115			scm.is_hpf_en = 1;
116			pmic_spkr_en_mute(RIGHT_SPKR, 0);
117			pmic_set_spkr_configuration(&scm);
118			pmic_spkr_en(RIGHT_SPKR, 1);
119
120			/* unmute */
121			pmic_spkr_en_mute(RIGHT_SPKR, 1);
122		} else {
123			pmic_spkr_en_mute(RIGHT_SPKR, 0);
124
125			pmic_spkr_en(RIGHT_SPKR, 0);
126
127			pmic_set_spkr_configuration(&scm);
128		}
129	}
130}
131
132static void config_gpio_table(uint32_t *table, int len)
133{
134	int n;
135	unsigned id;
136	for (n = 0; n < len; n++) {
137		id = table[n];
138		msm_proc_comm(PCOM_RPC_GPIO_TLMM_CONFIG_EX, &id, 0);
139	}
140}
141
142static uint32_t bt_sco_enable[] = {
143	PCOM_GPIO_CFG(MAHIMAHI_BT_PCM_OUT, 1, GPIO_OUTPUT,
144			GPIO_NO_PULL, GPIO_2MA),
145	PCOM_GPIO_CFG(MAHIMAHI_BT_PCM_IN, 1, GPIO_INPUT,
146			GPIO_NO_PULL, GPIO_2MA),
147	PCOM_GPIO_CFG(MAHIMAHI_BT_PCM_SYNC, 2, GPIO_INPUT,
148			GPIO_NO_PULL, GPIO_2MA),
149	PCOM_GPIO_CFG(MAHIMAHI_BT_PCM_CLK, 2, GPIO_INPUT,
150			GPIO_NO_PULL, GPIO_2MA),
151};
152
153static uint32_t bt_sco_disable[] = {
154	PCOM_GPIO_CFG(MAHIMAHI_BT_PCM_OUT, 0, GPIO_OUTPUT,
155			GPIO_NO_PULL, GPIO_2MA),
156	PCOM_GPIO_CFG(MAHIMAHI_BT_PCM_IN, 0, GPIO_INPUT,
157			GPIO_NO_PULL, GPIO_2MA),
158	PCOM_GPIO_CFG(MAHIMAHI_BT_PCM_SYNC, 0, GPIO_INPUT,
159			GPIO_NO_PULL, GPIO_2MA),
160	PCOM_GPIO_CFG(MAHIMAHI_BT_PCM_CLK, 0, GPIO_INPUT,
161			GPIO_NO_PULL, GPIO_2MA),
162};
163
164void mahimahi_bt_sco_enable(int en)
165{
166	static int bt_sco_refcount;
167	D("%s %d\n", __func__, en);
168
169	mutex_lock(&bt_sco_lock);
170	if (en) {
171		if (++bt_sco_refcount == 1)
172			config_gpio_table(bt_sco_enable,
173					ARRAY_SIZE(bt_sco_enable));
174	} else {
175		if (--bt_sco_refcount == 0) {
176			config_gpio_table(bt_sco_disable,
177					ARRAY_SIZE(bt_sco_disable));
178			gpio_set_value(MAHIMAHI_BT_PCM_OUT, 0);
179		}
180	}
181	mutex_unlock(&bt_sco_lock);
182}
183
184void mahimahi_mic_enable(int en)
185{
186	static int old_state = 0, new_state = 0;
187
188	D("%s %d\n", __func__, en);
189
190	mutex_lock(&mic_lock);
191	if (!!en)
192		new_state++;
193	else
194		new_state--;
195
196	if (new_state == 1 && old_state == 0) {
197		gpio_set_value(MAHIMAHI_AUD_2V5_EN, 1);
198		mdelay(60);
199	} else if (new_state == 0 && old_state == 1)
200		gpio_set_value(MAHIMAHI_AUD_2V5_EN, 0);
201	else
202		D("%s: do nothing %d %d\n", __func__, old_state, new_state);
203
204	old_state = new_state;
205	mutex_unlock(&mic_lock);
206}
207
208void mahimahi_analog_init(void)
209{
210	D("%s\n", __func__);
211	/* stereo pmic init */
212	pmic_spkr_set_gain(LEFT_SPKR, SPKR_GAIN_PLUS12DB);
213	pmic_spkr_set_gain(RIGHT_SPKR, SPKR_GAIN_PLUS12DB);
214	pmic_spkr_en_right_chan(OFF_CMD);
215	pmic_spkr_en_left_chan(OFF_CMD);
216	pmic_spkr_add_right_left_chan(OFF_CMD);
217	pmic_spkr_en_stereo(OFF_CMD);
218	pmic_spkr_select_usb_with_hpf_20hz(OFF_CMD);
219	pmic_spkr_bypass_mux(OFF_CMD);
220	pmic_spkr_en_hpf(ON_CMD);
221	pmic_spkr_en_sink_curr_from_ref_volt_cir(OFF_CMD);
222	pmic_spkr_set_mux_hpf_corner_freq(SPKR_FREQ_0_73KHZ);
223	pmic_mic_set_volt(MIC_VOLT_1_80V);
224
225	gpio_request(MAHIMAHI_AUD_JACKHP_EN, "aud_jackhp_en");
226	gpio_request(MAHIMAHI_BT_PCM_OUT, "bt_pcm_out");
227
228	gpio_direction_output(MAHIMAHI_AUD_JACKHP_EN, 0);
229
230	mutex_lock(&bt_sco_lock);
231	config_gpio_table(bt_sco_disable,
232			ARRAY_SIZE(bt_sco_disable));
233	gpio_direction_output(MAHIMAHI_BT_PCM_OUT, 0);
234	mutex_unlock(&bt_sco_lock);
235}
236
237int mahimahi_get_rx_vol(uint8_t hw, int level)
238{
239	int vol;
240
241	if (level > 100)
242		level = 100;
243	else if (level < 0)
244		level = 0;
245
246	if (is_cdma_version(system_rev) && hw == Q6_HW_HANDSET) {
247		int handset_volume[6] = { -1600, -1300, -1000, -600, -300, 0 };
248		vol = handset_volume[5 * level / 100];
249	} else {
250		struct q6_hw_info *info;
251		info = &q6_audio_hw[hw];
252		vol = info->min_gain + ((info->max_gain - info->min_gain) * level) / 100;
253	}
254
255	D("%s %d\n", __func__, vol);
256	return vol;
257}
258
259static struct qsd_acoustic_ops acoustic = {
260	.enable_mic_bias = mahimahi_mic_enable,
261};
262
263static struct q6audio_analog_ops ops = {
264	.init = mahimahi_analog_init,
265	.speaker_enable = mahimahi_speaker_enable,
266	.headset_enable = mahimahi_headset_enable,
267	.receiver_enable = mahimahi_receiver_enable,
268	.bt_sco_enable = mahimahi_bt_sco_enable,
269	.int_mic_enable = mahimahi_mic_enable,
270	.ext_mic_enable = mahimahi_mic_enable,
271	.get_rx_vol = mahimahi_get_rx_vol,
272};
273
274void __init mahimahi_audio_init(void)
275{
276	mutex_init(&mic_lock);
277	mutex_init(&bt_sco_lock);
278	q6audio_register_analog_ops(&ops);
279	acoustic_register_ops(&acoustic);
280	if (is_cdma_version(system_rev) &&
281		((system_rev == 0xC1) || (system_rev == 0xC2)))
282		q6audio_set_acdb_file("default_PMIC.acdb");
283}