temp revert rk change
[firefly-linux-kernel-4.4.55.git] / drivers / mfd / tegra-cpcap-audio.c
1 /* drivers/mfd/cpcap-audio.c
2  *
3  * Copyright (C) 2010 Google, Inc.
4  *
5  * Author:
6  *      Iliyan Malchev <malchev@google.com>
7  *
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.
11  *
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.
16  *
17  */
18
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>
27 #include <linux/fs.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>
33
34 #include <mach/cpcap_audio.h>
35
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,
40 };
41 static struct cpcap_audio_stream current_input = {
42         .id     = CPCAP_AUDIO_IN_MIC1,
43 };
44 static int codec_rate;
45 static int stdac_rate;
46 static bool dock_connected;
47 static bool bluetooth_byp;
48
49 static int cpcap_audio_ctl_open(struct inode *inode, struct file *file)
50 {
51         return 0;
52 }
53
54 static int cpcap_audio_ctl_release(struct inode *inode, struct file *file)
55 {
56         return 0;
57 }
58
59 static DEFINE_MUTEX(cpcap_lock);
60
61 static void tegra_setup_audio_output_off(void)
62 {
63         /* turn off the amplifier */
64         gpio_direction_output(pdata->speaker_gpio, 0);
65         gpio_direction_output(pdata->headset_gpio, 0);
66
67         pdata->state->stdac_mute = CPCAP_AUDIO_STDAC_MUTE;
68         pdata->state->stdac_mode = CPCAP_AUDIO_STDAC_OFF;
69
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);
73 }
74
75 static void tegra_setup_audio_out_speaker_on(void)
76 {
77         /* turn off the amplifier */
78         gpio_direction_output(pdata->speaker_gpio, 0);
79         gpio_direction_output(pdata->headset_gpio, 0);
80
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);
86
87         /* turn on the amplifier */
88         gpio_direction_output(pdata->speaker_gpio, 1);
89         gpio_direction_output(pdata->headset_gpio, 0);
90 }
91
92 static void tegra_setup_audio_out_headset_on(void)
93 {
94         /* turn off the amplifier */
95         gpio_direction_output(pdata->speaker_gpio, 0);
96         gpio_direction_output(pdata->headset_gpio, 0);
97
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);
102
103         /* turn on the amplifier */
104         gpio_direction_output(pdata->speaker_gpio, 0);
105         gpio_direction_output(pdata->headset_gpio, 1);
106 }
107
108 static void tegra_setup_audio_out_headset_and_speaker_on(void)
109 {
110         /* turn off the amplifier */
111         gpio_direction_output(pdata->speaker_gpio, 0);
112         gpio_direction_output(pdata->headset_gpio, 0);
113
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);
118
119         /* turn on the amplifier */
120         gpio_direction_output(pdata->speaker_gpio, 1);
121         gpio_direction_output(pdata->headset_gpio, 1);
122 }
123
124 static void tegra_setup_audio_out_dock_headset_on(void)
125 {
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);
130
131         /* turn off the headset and speaker amplifiers */
132         gpio_direction_output(pdata->speaker_gpio, 0);
133         gpio_direction_output(pdata->headset_gpio, 0);
134 }
135
136 static void tegra_setup_audio_in_mute(void)
137 {
138         pdata->state->codec_mute = CPCAP_AUDIO_CODEC_MUTE;
139         pdata->state->codec_mode = CPCAP_AUDIO_CODEC_OFF;
140
141         pdata->state->microphone = CPCAP_AUDIO_IN_NONE;
142
143         cpcap_audio_set_audio_state(pdata->state);
144 }
145
146 static void tegra_setup_audio_in_handset_on(void)
147 {
148         pdata->state->codec_mute = CPCAP_AUDIO_CODEC_UNMUTE;
149         pdata->state->codec_mode = CPCAP_AUDIO_CODEC_ON;
150
151         pdata->state->microphone = CPCAP_AUDIO_IN_HANDSET;
152         cpcap_audio_set_audio_state(pdata->state);
153 }
154
155 static void tegra_setup_audio_in_headset_on(void)
156 {
157         pdata->state->codec_mute = CPCAP_AUDIO_CODEC_UNMUTE;
158         pdata->state->codec_mode = CPCAP_AUDIO_CODEC_ON;
159
160         pdata->state->microphone = CPCAP_AUDIO_IN_HEADSET;
161         cpcap_audio_set_audio_state(pdata->state);
162 }
163
164 static int rate_to_cpcap_codec_rate(int rate)
165 {
166         return
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;
177 }
178
179 static int rate_to_cpcap_stdac_rate(int rate)
180 {
181         return
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;
192 }
193
194 static void tegra_setup_audio_out_rate(int rate)
195 {
196         pdata->state->stdac_rate = rate_to_cpcap_stdac_rate(rate);
197         stdac_rate = rate;
198         cpcap_audio_set_audio_state(pdata->state);
199 }
200
201 static void tegra_setup_audio_in_rate(int rate)
202 {
203         pdata->state->codec_rate = rate_to_cpcap_codec_rate(rate);
204         codec_rate = rate;
205         cpcap_audio_set_audio_state(pdata->state);
206 }
207
208 static long cpcap_audio_ctl_ioctl(struct file *file, unsigned int cmd,
209                         unsigned long arg)
210 {
211         int rc = 0;
212         struct cpcap_audio_stream in, out;
213         int rate;
214         mutex_lock(&cpcap_lock);
215
216         switch (cmd) {
217         case CPCAP_AUDIO_OUT_SET_OUTPUT:
218                 if (copy_from_user(&out, (const void __user *)arg,
219                                 sizeof(out))) {
220                         rc = -EFAULT;
221                         goto done;
222                 }
223                 if (out.id > CPCAP_AUDIO_OUT_MAX) {
224                         pr_err("%s: invalid audio-output selector %d\n",
225                                 __func__, out.id);
226                         rc = -EINVAL;
227                         goto done;
228                 }
229
230                 switch (out.id) {
231                 case CPCAP_AUDIO_OUT_SPEAKER:
232                         pr_debug("%s: setting output path to speaker\n",
233                                         __func__);
234                         if (out.on)
235                                 tegra_setup_audio_out_speaker_on();
236                         else
237                                 tegra_setup_audio_output_off();
238                         current_output = out;
239                         break;
240                 case CPCAP_AUDIO_OUT_HEADSET:
241                         pr_debug("%s: setting output path to headset\n",
242                                         __func__);
243                         if (out.on)
244                                 tegra_setup_audio_out_headset_on();
245                         else
246                                 tegra_setup_audio_output_off();
247                         current_output = out;
248                         break;
249                 case CPCAP_AUDIO_OUT_HEADSET_AND_SPEAKER:
250                         pr_debug("%s: setting output path to "
251                                         "headset + speaker\n", __func__);
252                         if (out.on)
253                                 tegra_setup_audio_out_headset_and_speaker_on();
254                         else
255                                 tegra_setup_audio_output_off();
256
257                         current_output = out;
258                         break;
259                 case CPCAP_AUDIO_OUT_ANLG_DOCK_HEADSET:
260                         pr_err("%s: setting output path to basic dock\n",
261                                         __func__);
262                         if (out.on)
263                                 tegra_setup_audio_out_dock_headset_on();
264                         else
265                                 tegra_setup_audio_output_off();
266                         current_output = out;
267                         break;
268                 case CPCAP_AUDIO_OUT_STANDBY:
269                         current_output.on = !out.on;
270                         if (out.on) {
271                                 pr_debug("%s: standby mode\n", __func__);
272                                 tegra_setup_audio_output_off();
273                                 break;
274                         }
275
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();
280                                 break;
281                         case CPCAP_AUDIO_OUT_HEADSET:
282                                 pr_debug("%s: standby off (headset)", __func__);
283                                 tegra_setup_audio_out_headset_on();
284                                 break;
285                         case CPCAP_AUDIO_OUT_HEADSET_AND_SPEAKER:
286                                 pr_debug("%s: standby off (speaker + headset)",
287                                         __func__);
288                                 tegra_setup_audio_out_headset_and_speaker_on();
289                                 break;
290                         case CPCAP_AUDIO_OUT_ANLG_DOCK_HEADSET:
291                                 pr_err("%s: standby off (dock headset)",
292                                         __func__);
293                                 tegra_setup_audio_out_dock_headset_on();
294                                 break;
295                         }
296                         break;
297                 }
298                 break;
299         case CPCAP_AUDIO_OUT_GET_OUTPUT:
300                 if (copy_to_user((void __user *)arg, &current_output,
301                                         sizeof(current_output)))
302                         rc = -EFAULT;
303                 break;
304         case CPCAP_AUDIO_IN_SET_INPUT:
305                 if (copy_from_user(&in, (const void __user *)arg,
306                                 sizeof(in))) {
307                         rc = -EFAULT;
308                         goto done;
309                 }
310                 if (in.id > CPCAP_AUDIO_IN_MAX) {
311                         pr_err("%s: invalid audio input selector %d\n",
312                                 __func__, in.id);
313                         rc = -EINVAL;
314                         goto done;
315                 }
316                 switch (in.id) {
317                 case CPCAP_AUDIO_IN_MIC1:
318                         if (in.on) {
319                                 pr_debug("%s: setting input path to on-board mic\n",
320                                         __func__);
321                                 tegra_setup_audio_in_handset_on();
322                         } else {
323                                 pr_debug("%s: mute on-board mic\n", __func__);
324                                 tegra_setup_audio_in_mute();
325                         }
326
327                         current_input = in;
328                         break;
329                 case CPCAP_AUDIO_IN_MIC2:
330                         if (in.on) {
331                                 pr_debug("%s: setting input path to headset mic\n",
332                                         __func__);
333                                 tegra_setup_audio_in_headset_on();
334                         } else {
335                                 pr_debug("%s: mute headset mic\n", __func__);
336                                 tegra_setup_audio_in_mute();
337                         }
338
339                         current_input = in;
340                         break;
341                 case CPCAP_AUDIO_IN_STANDBY:
342                         current_input.on = !in.on;
343                         if (in.on) {
344                                 pr_debug("%s: microphone in standby mode\n",
345                                         __func__);
346                                 tegra_setup_audio_in_mute();
347                                 break;
348                         }
349                         switch (current_input.id) {
350                         case CPCAP_AUDIO_IN_MIC1:
351                                 tegra_setup_audio_in_handset_on();
352                                 break;
353                         case CPCAP_AUDIO_IN_MIC2:
354                                 tegra_setup_audio_in_headset_on();
355                                 break;
356                         }
357                         break;
358                 }
359                 break;
360         case CPCAP_AUDIO_IN_GET_INPUT:
361                 if (copy_to_user((void __user *)arg, &current_input,
362                                         sizeof(current_input)))
363                         rc = -EFAULT;
364                 break;
365         case CPCAP_AUDIO_OUT_SET_VOLUME:
366                 if (arg > CPCAP_AUDIO_OUT_VOL_MAX) {
367                         pr_err("%s: invalid audio volume %ld\n",
368                                 __func__, arg);
369                         rc = -EINVAL;
370                         goto done;
371                 }
372                 pdata->state->output_gain = arg;
373                 cpcap_audio_set_audio_state(pdata->state);
374                 break;
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",
378                                 __func__, arg);
379                         rc = -EINVAL;
380                         goto done;
381                 }
382                 pdata->state->input_gain = (unsigned)arg;
383                 cpcap_audio_set_audio_state(pdata->state);
384                 break;
385         case CPCAP_AUDIO_OUT_GET_VOLUME:
386                 if (copy_to_user((void __user *)arg, &pdata->state->output_gain,
387                                         sizeof(unsigned int))) {
388                         rc = -EFAULT;
389                         goto done;
390                 }
391                 break;
392         case CPCAP_AUDIO_IN_GET_VOLUME:
393                 if (copy_to_user((void __user *)arg, &pdata->state->input_gain,
394                                         sizeof(unsigned int))) {
395                         rc = -EFAULT;
396                         goto done;
397                 }
398                 break;
399         case CPCAP_AUDIO_OUT_GET_RATE:
400                 if (copy_to_user((void __user *)arg, &stdac_rate,
401                                         sizeof(int))) {
402                         rc = -EFAULT;
403                         goto done;
404                 }
405                 break;
406         case CPCAP_AUDIO_OUT_SET_RATE:
407                 rate = (int)arg;
408                 if (rate < 8000 || rate > 48000) {
409                         pr_err("%s: invalid rate %d\n", __func__, rate);
410                         rc = -EFAULT;
411                         goto done;
412                 }
413                 pr_debug("%s: setting output rate to %dHz\n", __func__, rate);
414                 tegra_setup_audio_out_rate(rate);
415                 break;
416         case CPCAP_AUDIO_IN_GET_RATE:
417                 if (copy_to_user((void __user *)arg, &codec_rate,
418                                         sizeof(int))) {
419                         rc = -EFAULT;
420                         goto done;
421                 }
422                 break;
423         case CPCAP_AUDIO_IN_SET_RATE:
424                 rate = (int)arg;
425                 if (rate < 8000 || rate > 48000) {
426                         pr_err("%s: invalid in rate %d\n", __func__, rate);
427                         rc = -EFAULT;
428                         goto done;
429                 }
430                 pr_debug("%s: setting input rate to %dHz\n", __func__, rate);
431                 tegra_setup_audio_in_rate(rate);
432                 break;
433         case CPCAP_AUDIO_SET_BLUETOOTH_BYPASS:
434                 bluetooth_byp = (bool)arg;
435                 if (pdata->bluetooth_bypass)
436                         pdata->bluetooth_bypass(bluetooth_byp);
437                 else
438                         pr_err("%s: no bluetooth bypass handler\n", __func__);
439                 break;
440         }
441
442 done:
443         mutex_unlock(&cpcap_lock);
444         return rc;
445 }
446
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,
451 };
452
453 static struct miscdevice cpcap_audio_ctl = {
454         .name = "audio_ctl",
455         .minor = MISC_DYNAMIC_MINOR,
456         .fops = &cpcap_audio_ctl_fops,
457 };
458
459 /* Couple the CPCAP and Dock audio state, to avoid pops */
460 void tegra_cpcap_audio_dock_state(bool connected)
461 {
462         pr_debug("%s: %s", __func__, connected ? "connected" : "disconnected");
463
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);
471 }
472 EXPORT_SYMBOL(tegra_cpcap_audio_dock_state);
473
474 static void cpcap_audio_callback(int status)
475 {
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();
484         }
485         if (status == 0) {
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();
492         }
493
494         mutex_unlock(&cpcap_lock);
495 }
496
497 static int cpcap_audio_probe(struct platform_device *pdev)
498 {
499         int rc;
500
501         pr_debug("%s\n", __func__);
502
503         cpcap = platform_get_drvdata(pdev);
504         BUG_ON(!cpcap);
505
506         pdata = pdev->dev.platform_data;
507         BUG_ON(!pdata);
508
509         if (pdata->speaker_gpio >= 0) {
510                 tegra_gpio_enable(pdata->speaker_gpio);
511                 rc = gpio_request(pdata->speaker_gpio, "speaker");
512                 if (rc) {
513                         pr_err("%s: could not get speaker GPIO %d: %d\n",
514                                 __func__, pdata->speaker_gpio, rc);
515                         goto fail1;
516                 }
517         }
518
519         if (pdata->headset_gpio >= 0) {
520                 tegra_gpio_enable(pdata->headset_gpio);
521                 rc = gpio_request(pdata->headset_gpio, "headset");
522                 if (rc) {
523                         pr_err("%s: could not get headset GPIO %d: %d\n",
524                                 __func__, pdata->headset_gpio, rc);
525                         goto fail2;
526                 }
527         }
528
529         pdata->state->cpcap = cpcap;
530         if (cpcap_audio_init(pdata->state, pdata->regulator))
531                 goto fail3;
532
533         cpcap->h2w_new_state = &cpcap_audio_callback;
534
535         rc = misc_register(&cpcap_audio_ctl);
536         if (rc < 0) {
537                 pr_err("%s: failed to register misc device: %d\n", __func__,
538                                 rc);
539                 goto fail3;
540         }
541
542         return rc;
543
544 fail3:
545         if (pdata->headset_gpio >= 0)
546                 gpio_free(pdata->headset_gpio);
547 fail2:
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);
552 fail1:
553         if (pdata->speaker_gpio >= 0)
554                 tegra_gpio_disable(pdata->speaker_gpio);
555         return rc;
556 }
557
558 #ifdef CONFIG_PM
559 static int tegra_audio_suspend(struct platform_device *pdev, pm_message_t mesg)
560 {
561         dev_dbg(&pdev->dev, "%s\n", __func__);
562         return 0;
563 }
564
565 static int tegra_audio_resume(struct platform_device *pdev)
566 {
567         dev_dbg(&pdev->dev, "%s\n", __func__);
568         /* initialize DAC/DAP connections */
569         if (pdata->bluetooth_bypass)
570                 pdata->bluetooth_bypass(bluetooth_byp);
571         else
572                 pr_warn("No function for setting up DAC/DAP.");
573         return 0;
574 }
575 #endif
576
577 static struct platform_driver cpcap_audio_driver = {
578         .probe = cpcap_audio_probe,
579         .driver = {
580                 .name = "cpcap_audio",
581                 .owner = THIS_MODULE,
582         },
583 #ifdef CONFIG_PM
584         .suspend = tegra_audio_suspend,
585         .resume = tegra_audio_resume,
586 #endif
587 };
588
589 static int __init tegra_cpcap_audio_init(void)
590 {
591         return cpcap_driver_register(&cpcap_audio_driver);
592 }
593
594 module_init(tegra_cpcap_audio_init);
595 MODULE_LICENSE("GPL");