1 /* drivers/mfd/cpcap-audio.c
3 * Copyright (C) 2010 Google, Inc.
6 * Iliyan Malchev <malchev@google.com>
8 * This software is licensed under the terms of the GNU General Public
9 * License version 2, as published by the Free Software Foundation, and
10 * may be copied, distributed, and modified under those terms.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
19 #include <linux/module.h>
20 #include <linux/kernel.h>
21 #include <linux/spi/cpcap-regbits.h>
22 #include <linux/spi/cpcap.h>
23 #include <linux/regulator/consumer.h>
24 #include <linux/cpcap_audio.h>
25 #include <linux/spi/cpcap.h>
26 #include <linux/mutex.h>
28 #include <linux/err.h>
29 #include <linux/gpio.h>
30 #include <linux/miscdevice.h>
31 #include <linux/cpcap_audio.h>
32 #include <linux/uaccess.h>
34 #include <mach/cpcap_audio.h>
36 static struct cpcap_device *cpcap;
37 static struct cpcap_audio_platform_data *pdata;
38 static struct cpcap_audio_stream current_output = {
39 .id = CPCAP_AUDIO_OUT_SPEAKER,
41 static struct cpcap_audio_stream current_input = {
42 .id = CPCAP_AUDIO_IN_MIC1,
44 static int codec_rate;
45 static int stdac_rate;
46 static bool dock_connected;
47 static bool bluetooth_byp;
49 static int cpcap_audio_ctl_open(struct inode *inode, struct file *file)
54 static int cpcap_audio_ctl_release(struct inode *inode, struct file *file)
59 static DEFINE_MUTEX(cpcap_lock);
61 static void tegra_setup_audio_output_off(void)
63 /* turn off the amplifier */
64 gpio_direction_output(pdata->speaker_gpio, 0);
65 gpio_direction_output(pdata->headset_gpio, 0);
67 pdata->state->stdac_mute = CPCAP_AUDIO_STDAC_MUTE;
68 pdata->state->stdac_mode = CPCAP_AUDIO_STDAC_OFF;
70 pdata->state->stdac_primary_speaker = CPCAP_AUDIO_OUT_NONE;
71 pdata->state->stdac_secondary_speaker = CPCAP_AUDIO_OUT_NONE;
72 cpcap_audio_set_audio_state(pdata->state);
75 static void tegra_setup_audio_out_speaker_on(void)
77 /* turn off the amplifier */
78 gpio_direction_output(pdata->speaker_gpio, 0);
79 gpio_direction_output(pdata->headset_gpio, 0);
81 pdata->state->stdac_mode = CPCAP_AUDIO_STDAC_ON;
82 /* Using an external amp, lineout is the loudspeaker. */
83 pdata->state->stdac_primary_speaker = CPCAP_AUDIO_OUT_LINEOUT;
84 pdata->state->stdac_secondary_speaker = CPCAP_AUDIO_OUT_NONE;
85 cpcap_audio_set_audio_state(pdata->state);
87 /* turn on the amplifier */
88 gpio_direction_output(pdata->speaker_gpio, 1);
89 gpio_direction_output(pdata->headset_gpio, 0);
92 static void tegra_setup_audio_out_headset_on(void)
94 /* turn off the amplifier */
95 gpio_direction_output(pdata->speaker_gpio, 0);
96 gpio_direction_output(pdata->headset_gpio, 0);
98 pdata->state->stdac_mode = CPCAP_AUDIO_STDAC_ON;
99 pdata->state->stdac_primary_speaker = CPCAP_AUDIO_OUT_STEREO_HEADSET;
100 pdata->state->stdac_secondary_speaker = CPCAP_AUDIO_OUT_NONE;
101 cpcap_audio_set_audio_state(pdata->state);
103 /* turn on the amplifier */
104 gpio_direction_output(pdata->speaker_gpio, 0);
105 gpio_direction_output(pdata->headset_gpio, 1);
108 static void tegra_setup_audio_out_headset_and_speaker_on(void)
110 /* turn off the amplifier */
111 gpio_direction_output(pdata->speaker_gpio, 0);
112 gpio_direction_output(pdata->headset_gpio, 0);
114 pdata->state->stdac_mode = CPCAP_AUDIO_STDAC_ON;
115 pdata->state->stdac_primary_speaker = CPCAP_AUDIO_OUT_STEREO_HEADSET;
116 pdata->state->stdac_secondary_speaker = CPCAP_AUDIO_OUT_LINEOUT;
117 cpcap_audio_set_audio_state(pdata->state);
119 /* turn on the amplifier */
120 gpio_direction_output(pdata->speaker_gpio, 1);
121 gpio_direction_output(pdata->headset_gpio, 1);
124 static void tegra_setup_audio_out_dock_headset_on(void)
126 pdata->state->stdac_mode = CPCAP_AUDIO_STDAC_ON;
127 pdata->state->stdac_primary_speaker = CPCAP_AUDIO_OUT_EMU_STEREO;
128 pdata->state->stdac_secondary_speaker = CPCAP_AUDIO_OUT_EMU_STEREO;
129 cpcap_audio_set_audio_state(pdata->state);
131 /* turn off the headset and speaker amplifiers */
132 gpio_direction_output(pdata->speaker_gpio, 0);
133 gpio_direction_output(pdata->headset_gpio, 0);
136 static void tegra_setup_audio_in_mute(void)
138 pdata->state->codec_mute = CPCAP_AUDIO_CODEC_MUTE;
139 pdata->state->codec_mode = CPCAP_AUDIO_CODEC_OFF;
141 pdata->state->microphone = CPCAP_AUDIO_IN_NONE;
143 cpcap_audio_set_audio_state(pdata->state);
146 static void tegra_setup_audio_in_handset_on(void)
148 pdata->state->codec_mute = CPCAP_AUDIO_CODEC_UNMUTE;
149 pdata->state->codec_mode = CPCAP_AUDIO_CODEC_ON;
151 pdata->state->microphone = CPCAP_AUDIO_IN_HANDSET;
152 cpcap_audio_set_audio_state(pdata->state);
155 static void tegra_setup_audio_in_headset_on(void)
157 pdata->state->codec_mute = CPCAP_AUDIO_CODEC_UNMUTE;
158 pdata->state->codec_mode = CPCAP_AUDIO_CODEC_ON;
160 pdata->state->microphone = CPCAP_AUDIO_IN_HEADSET;
161 cpcap_audio_set_audio_state(pdata->state);
164 static int rate_to_cpcap_codec_rate(int rate)
167 rate == 8000 ? CPCAP_AUDIO_CODEC_RATE_8000_HZ :
168 rate == 11025 ? CPCAP_AUDIO_CODEC_RATE_11025_HZ :
169 rate == 12000 ? CPCAP_AUDIO_CODEC_RATE_12000_HZ :
170 rate == 16000 ? CPCAP_AUDIO_CODEC_RATE_16000_HZ :
171 rate == 22050 ? CPCAP_AUDIO_CODEC_RATE_22050_HZ :
172 rate == 24000 ? CPCAP_AUDIO_CODEC_RATE_24000_HZ :
173 rate == 32000 ? CPCAP_AUDIO_CODEC_RATE_32000_HZ :
174 rate == 44100 ? CPCAP_AUDIO_CODEC_RATE_44100_HZ :
175 rate == 48000 ? CPCAP_AUDIO_CODEC_RATE_48000_HZ :
176 /*default*/ CPCAP_AUDIO_CODEC_RATE_8000_HZ;
179 static int rate_to_cpcap_stdac_rate(int rate)
182 rate == 8000 ? CPCAP_AUDIO_STDAC_RATE_8000_HZ :
183 rate == 11025 ? CPCAP_AUDIO_STDAC_RATE_11025_HZ :
184 rate == 12000 ? CPCAP_AUDIO_STDAC_RATE_12000_HZ :
185 rate == 16000 ? CPCAP_AUDIO_STDAC_RATE_16000_HZ :
186 rate == 22050 ? CPCAP_AUDIO_STDAC_RATE_22050_HZ :
187 rate == 24000 ? CPCAP_AUDIO_STDAC_RATE_24000_HZ :
188 rate == 32000 ? CPCAP_AUDIO_STDAC_RATE_32000_HZ :
189 rate == 44100 ? CPCAP_AUDIO_STDAC_RATE_44100_HZ :
190 rate == 48000 ? CPCAP_AUDIO_STDAC_RATE_48000_HZ :
191 /*default*/ CPCAP_AUDIO_STDAC_RATE_44100_HZ;
194 static void tegra_setup_audio_out_rate(int rate)
196 pdata->state->stdac_rate = rate_to_cpcap_stdac_rate(rate);
198 cpcap_audio_set_audio_state(pdata->state);
201 static void tegra_setup_audio_in_rate(int rate)
203 pdata->state->codec_rate = rate_to_cpcap_codec_rate(rate);
205 cpcap_audio_set_audio_state(pdata->state);
208 static long cpcap_audio_ctl_ioctl(struct file *file, unsigned int cmd,
212 struct cpcap_audio_stream in, out;
214 mutex_lock(&cpcap_lock);
217 case CPCAP_AUDIO_OUT_SET_OUTPUT:
218 if (copy_from_user(&out, (const void __user *)arg,
223 if (out.id > CPCAP_AUDIO_OUT_MAX) {
224 pr_err("%s: invalid audio-output selector %d\n",
231 case CPCAP_AUDIO_OUT_SPEAKER:
232 pr_debug("%s: setting output path to speaker\n",
235 tegra_setup_audio_out_speaker_on();
237 tegra_setup_audio_output_off();
238 current_output = out;
240 case CPCAP_AUDIO_OUT_HEADSET:
241 pr_debug("%s: setting output path to headset\n",
244 tegra_setup_audio_out_headset_on();
246 tegra_setup_audio_output_off();
247 current_output = out;
249 case CPCAP_AUDIO_OUT_HEADSET_AND_SPEAKER:
250 pr_debug("%s: setting output path to "
251 "headset + speaker\n", __func__);
253 tegra_setup_audio_out_headset_and_speaker_on();
255 tegra_setup_audio_output_off();
257 current_output = out;
259 case CPCAP_AUDIO_OUT_ANLG_DOCK_HEADSET:
260 pr_err("%s: setting output path to basic dock\n",
263 tegra_setup_audio_out_dock_headset_on();
265 tegra_setup_audio_output_off();
266 current_output = out;
268 case CPCAP_AUDIO_OUT_STANDBY:
269 current_output.on = !out.on;
271 pr_debug("%s: standby mode\n", __func__);
272 tegra_setup_audio_output_off();
276 switch (current_output.id) {
277 case CPCAP_AUDIO_OUT_SPEAKER:
278 pr_debug("%s: standby off (speaker)", __func__);
279 tegra_setup_audio_out_speaker_on();
281 case CPCAP_AUDIO_OUT_HEADSET:
282 pr_debug("%s: standby off (headset)", __func__);
283 tegra_setup_audio_out_headset_on();
285 case CPCAP_AUDIO_OUT_HEADSET_AND_SPEAKER:
286 pr_debug("%s: standby off (speaker + headset)",
288 tegra_setup_audio_out_headset_and_speaker_on();
290 case CPCAP_AUDIO_OUT_ANLG_DOCK_HEADSET:
291 pr_err("%s: standby off (dock headset)",
293 tegra_setup_audio_out_dock_headset_on();
299 case CPCAP_AUDIO_OUT_GET_OUTPUT:
300 if (copy_to_user((void __user *)arg, ¤t_output,
301 sizeof(current_output)))
304 case CPCAP_AUDIO_IN_SET_INPUT:
305 if (copy_from_user(&in, (const void __user *)arg,
310 if (in.id > CPCAP_AUDIO_IN_MAX) {
311 pr_err("%s: invalid audio input selector %d\n",
317 case CPCAP_AUDIO_IN_MIC1:
319 pr_debug("%s: setting input path to on-board mic\n",
321 tegra_setup_audio_in_handset_on();
323 pr_debug("%s: mute on-board mic\n", __func__);
324 tegra_setup_audio_in_mute();
329 case CPCAP_AUDIO_IN_MIC2:
331 pr_debug("%s: setting input path to headset mic\n",
333 tegra_setup_audio_in_headset_on();
335 pr_debug("%s: mute headset mic\n", __func__);
336 tegra_setup_audio_in_mute();
341 case CPCAP_AUDIO_IN_STANDBY:
342 current_input.on = !in.on;
344 pr_debug("%s: microphone in standby mode\n",
346 tegra_setup_audio_in_mute();
349 switch (current_input.id) {
350 case CPCAP_AUDIO_IN_MIC1:
351 tegra_setup_audio_in_handset_on();
353 case CPCAP_AUDIO_IN_MIC2:
354 tegra_setup_audio_in_headset_on();
360 case CPCAP_AUDIO_IN_GET_INPUT:
361 if (copy_to_user((void __user *)arg, ¤t_input,
362 sizeof(current_input)))
365 case CPCAP_AUDIO_OUT_SET_VOLUME:
366 if (arg > CPCAP_AUDIO_OUT_VOL_MAX) {
367 pr_err("%s: invalid audio volume %ld\n",
372 pdata->state->output_gain = arg;
373 cpcap_audio_set_audio_state(pdata->state);
375 case CPCAP_AUDIO_IN_SET_VOLUME:
376 if (arg > CPCAP_AUDIO_IN_VOL_MAX) {
377 pr_err("%s: invalid audio-input volume %ld\n",
382 pdata->state->input_gain = (unsigned)arg;
383 cpcap_audio_set_audio_state(pdata->state);
385 case CPCAP_AUDIO_OUT_GET_VOLUME:
386 if (copy_to_user((void __user *)arg, &pdata->state->output_gain,
387 sizeof(unsigned int))) {
392 case CPCAP_AUDIO_IN_GET_VOLUME:
393 if (copy_to_user((void __user *)arg, &pdata->state->input_gain,
394 sizeof(unsigned int))) {
399 case CPCAP_AUDIO_OUT_GET_RATE:
400 if (copy_to_user((void __user *)arg, &stdac_rate,
406 case CPCAP_AUDIO_OUT_SET_RATE:
408 if (rate < 8000 || rate > 48000) {
409 pr_err("%s: invalid rate %d\n", __func__, rate);
413 pr_debug("%s: setting output rate to %dHz\n", __func__, rate);
414 tegra_setup_audio_out_rate(rate);
416 case CPCAP_AUDIO_IN_GET_RATE:
417 if (copy_to_user((void __user *)arg, &codec_rate,
423 case CPCAP_AUDIO_IN_SET_RATE:
425 if (rate < 8000 || rate > 48000) {
426 pr_err("%s: invalid in rate %d\n", __func__, rate);
430 pr_debug("%s: setting input rate to %dHz\n", __func__, rate);
431 tegra_setup_audio_in_rate(rate);
433 case CPCAP_AUDIO_SET_BLUETOOTH_BYPASS:
434 bluetooth_byp = (bool)arg;
435 if (pdata->bluetooth_bypass)
436 pdata->bluetooth_bypass(bluetooth_byp);
438 pr_err("%s: no bluetooth bypass handler\n", __func__);
443 mutex_unlock(&cpcap_lock);
447 static const struct file_operations cpcap_audio_ctl_fops = {
448 .open = cpcap_audio_ctl_open,
449 .release = cpcap_audio_ctl_release,
450 .unlocked_ioctl = cpcap_audio_ctl_ioctl,
453 static struct miscdevice cpcap_audio_ctl = {
455 .minor = MISC_DYNAMIC_MINOR,
456 .fops = &cpcap_audio_ctl_fops,
459 /* Couple the CPCAP and Dock audio state, to avoid pops */
460 void tegra_cpcap_audio_dock_state(bool connected)
462 pr_debug("%s: %s", __func__, connected ? "connected" : "disconnected");
464 mutex_lock(&cpcap_lock);
465 dock_connected = connected;
466 /* Borrow (unused) "ext output" to keep dock speaker amplifier on. */
467 pdata->state->ext_primary_speaker = dock_connected ?
468 CPCAP_AUDIO_OUT_EMU_STEREO : CPCAP_AUDIO_OUT_NONE;
469 cpcap_audio_set_audio_state(pdata->state);
470 mutex_unlock(&cpcap_lock);
472 EXPORT_SYMBOL(tegra_cpcap_audio_dock_state);
474 static void cpcap_audio_callback(int status)
476 mutex_lock(&cpcap_lock);
477 if (status == 1 || status == 2) {
478 if (pdata->state->stdac_primary_speaker ==
479 CPCAP_AUDIO_OUT_STEREO_HEADSET)
480 tegra_setup_audio_out_headset_on();
481 if (pdata->state->microphone ==
482 CPCAP_AUDIO_IN_HEADSET)
483 tegra_setup_audio_in_headset_on();
486 if (pdata->state->stdac_primary_speaker ==
487 CPCAP_AUDIO_OUT_STEREO_HEADSET)
488 tegra_setup_audio_output_off();
489 if (pdata->state->microphone ==
490 CPCAP_AUDIO_IN_HEADSET)
491 tegra_setup_audio_in_mute();
494 mutex_unlock(&cpcap_lock);
497 static int cpcap_audio_probe(struct platform_device *pdev)
501 pr_debug("%s\n", __func__);
503 cpcap = platform_get_drvdata(pdev);
506 pdata = pdev->dev.platform_data;
509 if (pdata->speaker_gpio >= 0) {
510 tegra_gpio_enable(pdata->speaker_gpio);
511 rc = gpio_request(pdata->speaker_gpio, "speaker");
513 pr_err("%s: could not get speaker GPIO %d: %d\n",
514 __func__, pdata->speaker_gpio, rc);
519 if (pdata->headset_gpio >= 0) {
520 tegra_gpio_enable(pdata->headset_gpio);
521 rc = gpio_request(pdata->headset_gpio, "headset");
523 pr_err("%s: could not get headset GPIO %d: %d\n",
524 __func__, pdata->headset_gpio, rc);
529 pdata->state->cpcap = cpcap;
530 if (cpcap_audio_init(pdata->state, pdata->regulator))
533 cpcap->h2w_new_state = &cpcap_audio_callback;
535 rc = misc_register(&cpcap_audio_ctl);
537 pr_err("%s: failed to register misc device: %d\n", __func__,
545 if (pdata->headset_gpio >= 0)
546 gpio_free(pdata->headset_gpio);
548 if (pdata->headset_gpio >= 0)
549 tegra_gpio_disable(pdata->headset_gpio);
550 if (pdata->speaker_gpio >= 0)
551 gpio_free(pdata->speaker_gpio);
553 if (pdata->speaker_gpio >= 0)
554 tegra_gpio_disable(pdata->speaker_gpio);
559 static int tegra_audio_suspend(struct platform_device *pdev, pm_message_t mesg)
561 dev_dbg(&pdev->dev, "%s\n", __func__);
565 static int tegra_audio_resume(struct platform_device *pdev)
567 dev_dbg(&pdev->dev, "%s\n", __func__);
568 /* initialize DAC/DAP connections */
569 if (pdata->bluetooth_bypass)
570 pdata->bluetooth_bypass(bluetooth_byp);
572 pr_warn("No function for setting up DAC/DAP.");
577 static struct platform_driver cpcap_audio_driver = {
578 .probe = cpcap_audio_probe,
580 .name = "cpcap_audio",
581 .owner = THIS_MODULE,
584 .suspend = tegra_audio_suspend,
585 .resume = tegra_audio_resume,
589 static int __init tegra_cpcap_audio_init(void)
591 return cpcap_driver_register(&cpcap_audio_driver);
594 module_init(tegra_cpcap_audio_init);
595 MODULE_LICENSE("GPL");