]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blob - sound/arm/omap/omap-alsa-tsc2101-mixer.c
Merge current mainline tree into linux-omap tree
[linux-2.6-omap-h63xx.git] / sound / arm / omap / omap-alsa-tsc2101-mixer.c
1 /*
2  * sound/arm/omap/omap-alsa-tsc2101-mixer.c
3  *
4  * Alsa Driver for TSC2101 codec for OMAP platform boards.
5  *
6  * Copyright (C) 2005 Mika Laitio <lamikr@cc.jyu.fi> and
7  *                   Everett Coleman II <gcc80x86@fuzzyneural.net>
8  *
9  * Board initialization code is based on the code in TSC2101 OSS driver.
10  * Copyright (C) 2004 Texas Instruments, Inc.
11  *      Written by Nishanth Menon and Sriram Kannan
12  *
13  * This program is free software; you can redistribute it and/or modify it
14  * under the terms of the GNU General Public License as published by the
15  * Free Software Foundation; either version 2 of the License, or (at your
16  * option) any later version.
17  *
18  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
19  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
20  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
21  * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
24  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
25  * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28  *
29  * You should have received a copy of the  GNU General Public License along
30  * with this program; if not, write  to the Free Software Foundation, Inc.,
31  * 675 Mass Ave, Cambridge, MA 02139, USA.
32  *
33  * History:
34  *
35  * 2006-03-01   Mika Laitio - Mixer for the tsc2101 driver used in omap boards.
36  *              Can switch between headset and loudspeaker playback,
37  *              mute and unmute dgc, set dgc volume. Record source switch,
38  *              keyclick, buzzer and headset volume and handset volume control
39  *              are still missing.
40  *
41  */
42
43 #include "omap-alsa-tsc2101.h"
44 #include "omap-alsa-tsc2101-mixer.h"
45
46 #include <linux/spi/tsc2101.h>
47 #include <linux/types.h>
48 #include <sound/initval.h>
49 #include <sound/control.h>
50
51 #ifdef DEBUG
52 #define M_DPRINTK(ARGS...)                              \
53         do {                                            \
54                 printk(KERN_INFO "<%s>: ", __func__);   \
55                 printk(ARGS);                           \
56         } while (0)
57 #else
58 #define M_DPRINTK(ARGS...)              /* nop */
59 #endif
60
61 #define CHECK_BIT(INDX, ARG) (((ARG) & TSC2101_BIT(INDX)) >> INDX)
62 #define IS_UNMUTED(INDX, ARG) (((CHECK_BIT(INDX, ARG)) == 0))
63
64 #define DGC_DALVL_EXTRACT(ARG) ((ARG & 0x7f00) >> 8)
65 #define DGC_DARVL_EXTRACT(ARG) ((ARG & 0x007f))
66
67 #define HGC_ADPGA_HED_EXTRACT(ARG) ((ARG & 0x7f00) >> 8)
68 #define HNGC_ADPGA_HND_EXTRACT(ARG) ((ARG & 0x7f00) >> 8)
69 #define BGC_ADPGA_BGC_EXTRACT(ARG) ((ARG & 0x7f00) >> 8)
70
71 static int current_playback_target      = PLAYBACK_TARGET_LOUDSPEAKER;
72 static int current_rec_src              = REC_SRC_SINGLE_ENDED_MICIN_HED;
73
74 /*
75  * Simplified write for the tsc2101 audio registers.
76  */
77 inline void omap_tsc2101_audio_write(u8 address, u16 data)
78 {
79         tsc2101_write_sync(mcbsp_dev.tsc2101_dev, PAGE2_AUDIO_CODEC_REGISTERS,
80                                 address, data);
81 }
82
83 /*
84  * Simplified read for the tsc2101 audio registers.
85  */
86 inline u16 omap_tsc2101_audio_read(u8 address)
87 {
88         return (tsc2101_read_sync(mcbsp_dev.tsc2101_dev,
89                                         PAGE2_AUDIO_CODEC_REGISTERS, address));
90 }
91
92 /*
93  * For selecting tsc2101 recourd source.
94  */
95 static void set_record_source(int val)
96 {
97         u16     data;
98
99         /*
100          * Mute Analog Sidetone
101          * Analog sidetone gain db?
102          * Input selected by MICSEL connected to ADC
103          */
104         data    = MPC_ASTMU | MPC_ASTG(0x45);
105         data    &= ~MPC_MICSEL(7); /* clear all MICSEL bits */
106         data    |= MPC_MICSEL(val);
107         data    |= MPC_MICADC;
108         omap_tsc2101_audio_write(TSC2101_MIXER_PGA_CTRL, data);
109
110         current_rec_src = val;
111 }
112
113 /*
114  * Converts the Alsa mixer volume (0 - 100) to real
115  * Digital Gain Control (DGC) value that can be written
116  * or read from the TSC2101 registry.
117  *
118  * Note that the number "OUTPUT_VOLUME_MAX" is smaller than OUTPUT_VOLUME_MIN
119  * because DGC works as a volume decreaser. (The more bigger value is put
120  * to DGC, the more the volume of controlled channel is decreased)
121  *
122  * In addition the TCS2101 chip would allow the maximum
123  * volume reduction be 63.5 DB
124  * but according to some tests user can not hear anything with this chip
125  * when the volume is set to be less than 25 db.
126  * Therefore this function will return a value
127  * that means 38.5 db (63.5 db - 25 db)
128  * reduction in the channel volume, when mixer is set to 0.
129  * For mixer value 100, this will return a value that means
130  * 0 db volume reduction.
131  * ([mute_left_bit]0000000[mute_right_bit]0000000)
132  */
133 int get_mixer_volume_as_dac_gain_control_volume(int vol)
134 {
135         u16 retVal;
136
137         /* Convert 0 -> 100 volume to 0x7F(min) -> y(max) volume range */
138         retVal = ((vol * OUTPUT_VOLUME_RANGE) / 100) + OUTPUT_VOLUME_MAX;
139         /* invert the value for getting the proper range 0 min and 100 max */
140         retVal = OUTPUT_VOLUME_MIN - retVal;
141
142         return retVal;
143 }
144
145 /*
146  * Converts the Alsa mixer volume (0 - 100) to TSC2101
147  * Digital Gain Control (DGC) volume. Alsa mixer volume 0
148  * is converted to value meaning the volume reduction of -38.5 db
149  * and Alsa mixer volume 100 is converted to value meaning the
150  * reduction of 0 db.
151  */
152 int set_mixer_volume_as_dac_gain_control_volume(int mixerVolL, int mixerVolR)
153 {
154         u16 val;
155         int retVal;
156         int volL;
157         int volR;
158
159         if ((mixerVolL < 0) ||
160             (mixerVolL > 100) ||
161             (mixerVolR < 0) ||
162             (mixerVolR > 100)) {
163                 printk(KERN_ERR "Trying a bad mixer volume as dac gain control"
164                         " volume value, left (%d), right (%d)!\n", mixerVolL,
165                         mixerVolR);
166                 return -EPERM;
167         }
168         M_DPRINTK("mixer volume left = %d, right = %d\n", mixerVolL, mixerVolR);
169         volL    = get_mixer_volume_as_dac_gain_control_volume(mixerVolL);
170         volR    = get_mixer_volume_as_dac_gain_control_volume(mixerVolR);
171
172         val     = omap_tsc2101_audio_read(TSC2101_DAC_GAIN_CTRL);
173         /* keep the old mute bit settings */
174         val     &= ~(DGC_DALVL(OUTPUT_VOLUME_MIN) |
175                         DGC_DARVL(OUTPUT_VOLUME_MIN));
176         val     |= DGC_DALVL(volL) | DGC_DARVL(volR);
177         retVal  = 2;
178         if (retVal)
179                 omap_tsc2101_audio_write(TSC2101_DAC_GAIN_CTRL, val);
180
181         M_DPRINTK("to registry: left = %d, right = %d, total = %d\n",
182                         DGC_DALVL_EXTRACT(val), DGC_DARVL_EXTRACT(val), val);
183         return retVal;
184 }
185
186 /*
187  * If unmuteLeft/unmuteRight == 0  --> mute
188  * If unmuteLeft/unmuteRight == 1 --> unmute
189  */
190 int dac_gain_control_unmute(int unmuteLeft, int unmuteRight)
191 {
192         u16 val;
193         int count;
194
195         count   = 0;
196         val     = omap_tsc2101_audio_read(TSC2101_DAC_GAIN_CTRL);
197         /*
198          * in alsa mixer 1 --> on, 0 == off. In tsc2101 registry 1 --> off,
199          * 0 --> on so if values are same, it's time to change the registry
200          * value.
201          */
202         if (unmuteLeft != IS_UNMUTED(15, val)) {
203                 if (unmuteLeft == 0) {
204                         /* mute --> turn bit on */
205                         val     = val | DGC_DALMU;
206                 } else {
207                         /* unmute --> turn bit off */
208                         val     = val & ~DGC_DALMU;
209                 }
210                 count++;
211         } /* L */
212         if (unmuteRight != IS_UNMUTED(7, val)) {
213                 if (unmuteRight == 0) {
214                         /* mute --> turn bit on */
215                         val     = val | DGC_DARMU;
216                 } else {
217                         /* unmute --> turn bit off */
218                         val     = val & ~DGC_DARMU;
219                 }
220                 count++;
221         } /* R */
222         if (count) {
223                 omap_tsc2101_audio_write(TSC2101_DAC_GAIN_CTRL, val);
224                 M_DPRINTK("changed value, is_unmuted left = %d, right = %d\n",
225                         IS_UNMUTED(15, val),
226                         IS_UNMUTED(7, val));
227         }
228         return count;
229 }
230
231 /*
232  * unmute: 0 --> mute, 1 --> unmute
233  * page2RegIndx: Registry index in tsc2101 page2.
234  * muteBitIndx: Index number for the bit in registry that indicates whether
235  * muted or unmuted.
236  */
237 int adc_pga_unmute_control(int unmute, int page2regIndx, int muteBitIndx)
238 {
239         int count;
240         u16 val;
241
242         count   = 0;
243         val     = omap_tsc2101_audio_read(page2regIndx);
244         /*
245          * in alsa mixer 1 --> on, 0 == off. In tsc2101 registry 1 --> off,
246          * 0 --> on so if the values are same, it's time to change the
247          * registry value...
248          */
249         if (unmute != IS_UNMUTED(muteBitIndx, val)) {
250                 if (unmute == 0) {
251                         /* mute --> turn bit on */
252                         val     = val | TSC2101_BIT(muteBitIndx);
253                 } else {
254                         /* unmute --> turn bit off */
255                         val     = val & ~TSC2101_BIT(muteBitIndx);
256                 }
257                 M_DPRINTK("changed value, is_unmuted = %d\n",
258                                 IS_UNMUTED(muteBitIndx, val));
259                 count++;
260         }
261         if (count)
262                 omap_tsc2101_audio_write(page2regIndx, val);
263
264         return count;
265 }
266
267 /*
268  * Converts the DGC registry value read from the TSC2101 registry to
269  * Alsa mixer volume format (0 - 100).
270  */
271 int get_dac_gain_control_volume_as_mixer_volume(u16 vol)
272 {
273         u16 retVal;
274
275         retVal  = OUTPUT_VOLUME_MIN - vol;
276         retVal  = ((retVal - OUTPUT_VOLUME_MAX) * 100) / OUTPUT_VOLUME_RANGE;
277         /* fix scaling error */
278         if ((retVal > 0) && (retVal < 100))
279                 retVal++;
280
281         return retVal;
282 }
283
284 /*
285  * Converts the headset gain control volume (0 - 63.5 db)
286  * to Alsa mixer volume (0 - 100)
287  */
288 int get_headset_gain_control_volume_as_mixer_volume(u16 registerVal)
289 {
290         u16 retVal;
291
292         retVal  = ((registerVal * 100) / INPUT_VOLUME_RANGE);
293         return retVal;
294 }
295
296 /*
297  * Converts the handset gain control volume (0 - 63.5 db)
298  * to Alsa mixer volume (0 - 100)
299  */
300 int get_handset_gain_control_volume_as_mixer_volume(u16 registerVal)
301 {
302         return get_headset_gain_control_volume_as_mixer_volume(registerVal);
303 }
304
305 /*
306  * Converts the Alsa mixer volume (0 - 100) to
307  * headset gain control volume (0 - 63.5 db)
308  */
309 int get_mixer_volume_as_headset_gain_control_volume(u16 mixerVal)
310 {
311         u16 retVal;
312
313         retVal  = ((mixerVal * INPUT_VOLUME_RANGE) / 100) + INPUT_VOLUME_MIN;
314         return retVal;
315 }
316
317 /*
318  * Writes Alsa mixer volume (0 - 100) to TSC2101 headset volume registry in
319  * a TSC2101 format. (0 - 63.5 db)
320  * In TSC2101 OSS driver this functionality was controlled with "SET_LINE"
321  * parameter.
322  */
323 int set_mixer_volume_as_headset_gain_control_volume(int mixerVol)
324 {
325         int volume;
326         int retVal;
327         u16 val;
328
329         if (mixerVol < 0 || mixerVol > 100) {
330                 M_DPRINTK("Trying a bad headset mixer volume value(%d)!\n",
331                                 mixerVol);
332                 return -EPERM;
333         }
334         M_DPRINTK("mixer volume = %d\n", mixerVol);
335         /*
336          * Convert 0 -> 100 volume to 0x0(min) -> 0x7D(max) volume range
337          * NOTE: 0 is minimum volume and not mute
338          */
339         volume  = get_mixer_volume_as_headset_gain_control_volume(mixerVol);
340         val     = omap_tsc2101_audio_read(TSC2101_HEADSET_GAIN_CTRL);
341         /* preserve the old mute settings */
342         val     &= ~(HGC_ADPGA_HED(INPUT_VOLUME_MAX));
343         val     |= HGC_ADPGA_HED(volume);
344         omap_tsc2101_audio_write(TSC2101_HEADSET_GAIN_CTRL, val);
345         retVal  = 1;
346
347         M_DPRINTK("to registry = %d\n", val);
348         return retVal;
349 }
350
351 /*
352  * Writes Alsa mixer volume (0 - 100) to TSC2101 handset volume registry in
353  * a TSC2101 format. (0 - 63.5 db)
354  * In TSC2101 OSS driver this functionality was controlled with
355  * "SET_MIC" parameter.
356  */
357 int set_mixer_volume_as_handset_gain_control_volume(int mixerVol)
358 {
359         int volume;
360         int retVal;
361         u16 val;
362
363         if (mixerVol < 0 || mixerVol > 100) {
364                 M_DPRINTK("Trying a bad mic mixer volume value(%d)!\n",
365                                 mixerVol);
366                 return -EPERM;
367         }
368         M_DPRINTK("mixer volume = %d\n", mixerVol);
369         /*
370          * Convert 0 -> 100 volume to 0x0(min) -> 0x7D(max) volume range
371          * NOTE: 0 is minimum volume and not mute
372          */
373         volume  = get_mixer_volume_as_headset_gain_control_volume(mixerVol);
374         val     = omap_tsc2101_audio_read(TSC2101_HANDSET_GAIN_CTRL);
375         /* preserve the old mute settigns */
376         val     &= ~(HNGC_ADPGA_HND(INPUT_VOLUME_MAX));
377         val     |= HNGC_ADPGA_HND(volume);
378         omap_tsc2101_audio_write(TSC2101_HANDSET_GAIN_CTRL, val);
379         retVal  = 1;
380
381         M_DPRINTK("to registry = %d\n", val);
382         return retVal;
383 }
384
385 void set_loudspeaker_to_playback_target(void)
386 {
387         /* power down SPK1, SPK2 and loudspeaker */
388         omap_tsc2101_audio_write(TSC2101_CODEC_POWER_CTRL,
389                         CPC_SP1PWDN | CPC_SP2PWDN | CPC_LDAPWDF);
390         /*
391          * ADC, DAC, Analog Sidetone, cellphone, buzzer softstepping enabled
392          * 1dB AGC hysteresis
393          * MICes bias 2V
394          */
395         omap_tsc2101_audio_write(TSC2101_AUDIO_CTRL_4, AC4_MB_HED(0));
396
397         /*
398          * DAC left and right routed to SPK1/SPK2
399          * SPK1/SPK2 unmuted
400          * Keyclicks routed to SPK1/SPK2 */
401         omap_tsc2101_audio_write(TSC2101_AUDIO_CTRL_5,
402                         AC5_DIFFIN |
403                         AC5_DAC2SPK1(3) | AC5_AST2SPK1 | AC5_KCL2SPK1 |
404                         AC5_DAC2SPK2(3) | AC5_AST2SPK2 | AC5_KCL2SPK2);
405
406         /*
407          * routing selected to SPK1 goes also to OUT8P/OUT8N. (loudspeaker)
408          * analog sidetone routed to loudspeaker
409          * buzzer pga routed to loudspeaker
410          * keyclick routing to loudspeaker
411          * cellphone input routed to loudspeaker
412          * mic selection (control register 04h/page2) routed to cell phone
413          * output (CP_OUT)
414          * routing selected for SPK1 goes also to cellphone output (CP_OUT)
415          * OUT8P/OUT8N (loudspeakers) unmuted (0 = unmuted)
416          * Cellphone output is not muted (0 = unmuted)
417          * Enable loudspeaker short protection control (0 = enable protection)
418          * VGND short protection control (0 = enable protection)
419          */
420         omap_tsc2101_audio_write(TSC2101_AUDIO_CTRL_6,
421                         AC6_SPL2LSK | AC6_AST2LSK | AC6_BUZ2LSK | AC6_KCL2LSK |
422                         AC6_CPI2LSK | AC6_MIC2CPO | AC6_SPL2CPO);
423         current_playback_target = PLAYBACK_TARGET_LOUDSPEAKER;
424 }
425
426 void set_headphone_to_playback_target(void)
427 {
428         /* power down SPK1, SPK2 and loudspeaker */
429         omap_tsc2101_audio_write(TSC2101_CODEC_POWER_CTRL,
430                         CPC_SP1PWDN | CPC_SP2PWDN | CPC_LDAPWDF);
431         /*
432          * ADC, DAC, Analog Sidetone, cellphone, buzzer softstepping enabled
433         Â * 1dB AGC hysteresis
434          * MICes bias 2V
435          */
436         omap_tsc2101_audio_write(TSC2101_AUDIO_CTRL_4, AC4_MB_HED(0));
437
438         /*
439          * DAC left and right routed to SPK1/SPK2
440          * SPK1/SPK2 unmuted
441          * Keyclicks routed to SPK1/SPK2
442          */
443         omap_tsc2101_audio_write(TSC2101_AUDIO_CTRL_5,
444                         AC5_DAC2SPK1(3) | AC5_AST2SPK1 | AC5_KCL2SPK1 |
445                         AC5_DAC2SPK2(3) | AC5_AST2SPK2 | AC5_KCL2SPK2 |
446                         AC5_HDSCPTC);
447
448         /* OUT8P/OUT8N muted, CPOUT muted */
449         omap_tsc2101_audio_write(TSC2101_AUDIO_CTRL_6,
450                         AC6_MUTLSPK | AC6_MUTSPK2 | AC6_LDSCPTC |
451                         AC6_VGNDSCPTC);
452         current_playback_target = PLAYBACK_TARGET_HEADPHONE;
453 }
454
455 void set_telephone_to_playback_target(void)
456 {
457         /*
458          * 0110 1101 0101 1100
459          * power down MICBIAS_HED, Analog sidetone, SPK2, DAC,
460          * Driver virtual ground, loudspeaker. Values D2-d5 are flags.
461          */
462         omap_tsc2101_audio_write(TSC2101_CODEC_POWER_CTRL,
463                         CPC_MBIAS_HED | CPC_ASTPWD | CPC_SP2PWDN | CPC_DAPWDN |
464                         CPC_VGPWDN | CPC_LSPWDN);
465
466         /*
467          * 0010 1010 0100 0000
468          * ADC, DAC, Analog Sidetone, cellphone, buzzer softstepping enabled
469          * 1dB AGC hysteresis
470          * MICes bias 2V
471          */
472         omap_tsc2101_audio_write(TSC2101_AUDIO_CTRL_4,
473                         AC4_MB_HND | AC4_MB_HED(0) | AC4_AGCHYS(1) |
474                         AC4_BISTPD | AC4_ASSTPD | AC4_DASTPD);
475         printk(KERN_INFO "set_telephone_to_playback_target(), "
476                         "TSC2101_AUDIO_CTRL_4 = %d\n",
477                         omap_tsc2101_audio_read(TSC2101_AUDIO_CTRL_4));
478
479         /*
480          * 1110 0010 0000 0010
481          * DAC left and right routed to SPK1/SPK2
482          * SPK1/SPK2 unmuted
483          * keyclicks routed to SPK1/SPK2
484          */
485         omap_tsc2101_audio_write(TSC2101_AUDIO_CTRL_5,
486                         AC5_DIFFIN | AC5_DAC2SPK1(3) |
487                         AC5_CPI2SPK1 | AC5_MUTSPK2);
488
489         omap_tsc2101_audio_write(TSC2101_AUDIO_CTRL_6,
490                         AC6_MIC2CPO | AC6_MUTLSPK |
491                         AC6_LDSCPTC | AC6_VGNDSCPTC | AC6_CAPINTF);
492         current_playback_target = PLAYBACK_TARGET_CELLPHONE;
493 }
494
495 /*
496  * 1100 0101 1101 0000
497  *
498  * #define MPC_ASTMU           TSC2101_BIT(15)
499  * #define MPC_ASTG(ARG)       (((ARG) & 0x7F) << 8)
500  * #define MPC_MICSEL(ARG)     (((ARG) & 0x07) << 5)
501  * #define MPC_MICADC          TSC2101_BIT(4)
502  * #define MPC_CPADC           TSC2101_BIT(3)
503  * #define MPC_ASTGF           (0x01)
504  */
505 static void set_telephone_to_record_source(void)
506 {
507         u16     val;
508
509         /*
510          * D0       = 0:
511          *              --> AGC is off for handset input.
512          *              --> ADC PGA is controlled by the ADMUT_HDN + ADPGA_HND
513          *          (D15, D14-D8)
514          * D4 - D1  = 0000
515          *              --> AGC time constant for handset input,
516          *              attack time = 8 mc, decay time = 100 ms
517          * D7 - D5  = 000
518          *              --> AGC Target gain for handset input = -5.5 db
519          * D14 - D8 = 011 1100
520          *              --> ADC handset PGA settings = 60 = 30 db
521          * D15          = 0
522          *              --> Handset input ON (unmuted)
523          */
524         val     = 0x3c00;       /* 0011 1100 0000 0000 = 60 = 30 */
525         omap_tsc2101_audio_write(TSC2101_HANDSET_GAIN_CTRL, val);
526
527         /*
528          * D0           = 0
529          *              --> AGC is off for headset/Aux input
530          *              --> ADC headset/Aux PGA is contoller by
531          *              ADMUT_HED + ADPGA_HED
532          *          (D15, D14-D8)
533          * D4 - D1      = 0000
534          *              --> Agc constant for headset/Aux input,
535          *              attack time = 8 mc, decay time = 100 ms
536          * D7 - D5      = 000
537          *              --> AGC target gain for headset input = -5.5 db
538          * D14 - D8 = 000 0000
539          *              --> Adc headset/AUX pga settings = 0 db
540          * D15          = 1
541          *              --> Headset/AUX input muted
542          *
543          * Mute headset aux input
544          */
545         val     = 0x8000;       /* 1000 0000 0000 0000 */
546         omap_tsc2101_audio_write(TSC2101_HEADSET_GAIN_CTRL, val);
547         set_record_source(REC_SRC_MICIN_HND_AND_AUX1);
548
549         /*
550          * hacks start
551          * D0           = flag, Headset/Aux or handset PGA flag
552          *              --> & with 1 (= 1 -->gain applied == pga
553          *              register settings)
554          * D1           = 0, DAC channel PGA soft stepping control
555          *              --> 0.5 db change every WCLK
556          * D2           = flag, DAC right channel PGA flag
557          *              --> & with 1
558          * D3           = flag, DAC left channel PGA flag
559          *              -- > & with 1
560          * D7 - D4      = 0001, keyclick length
561          *              --> 4 periods key clicks
562          * D10 - D8 = 100, keyclick frequency
563          *              --> 1 kHz,
564          * D11          = 0, Headset/Aux or handset soft stepping control
565          *              --> 0,5 db change every WCLK or ADWS
566          * D14 -D12 = 100, Keyclick applitude control
567          *              --> Medium amplitude
568          * D15          = 0, keyclick disabled
569          */
570         val     = omap_tsc2101_audio_read(TSC2101_AUDIO_CTRL_2);
571         val     = val & 0x441d;
572         val     = val | 0x4410; /* D14, D10, D4 bits == 1 */
573         omap_tsc2101_audio_write(TSC2101_AUDIO_CTRL_2, val);
574
575         /*
576          * D0           = 0     (reserved, write always 0)
577          * D1           = flag,
578          *                      --> & with 1
579          * D2 - D5      = 0000 (reserved, write always 0000)
580          * D6           = 1
581          *                      --> MICBIAS_HND = 2.0 v
582          * D8 - D7      = 00
583          *                      --> MICBIAS_HED = 3.3 v
584          * D10 - D9     = 01,
585          *                      --> Mic AGC hysteric selection = 2 db
586          * D11          = 1,
587          *                      --> Disable buzzer PGA soft stepping
588          * D12          = 0,
589          *                      --> Enable CELL phone PGA soft stepping control
590          * D13          = 1
591          *                      --> Disable analog sidetone soft
592          *                      stepping control
593          * D14          = 0
594          *                      --> Enable DAC PGA soft stepping control
595          * D15          = 0,
596          *                      --> Enable headset/Aux or Handset soft
597          *                      stepping control
598          */
599         val     = omap_tsc2101_audio_read(TSC2101_AUDIO_CTRL_4);
600         val     = val & 0x2a42; /* 0010 1010 0100 0010 */
601         val     = val | 0x2a40; /* bits D13, D11, D9, D6 == 1 */
602         omap_tsc2101_audio_write(TSC2101_AUDIO_CTRL_4, val);
603         printk(KERN_INFO "set_telephone_to_record_source(), "
604                         "TSC2101_AUDIO_CTRL_4 = %d\n",
605                         omap_tsc2101_audio_read(TSC2101_AUDIO_CTRL_4));
606         /*
607          * D0           = 0
608          *              --> reserved, write always = 0
609          * D1           = flag, read only
610          *              --> & with 1
611          * D5 - D2      = 1111, Buzzer input PGA settings
612          *              --> 0 db
613          * D6           = 1,
614          *              --> power down buzzer input pga
615          * D7           = flag, read only
616          *              --> & with 1
617          * D14 - D8     = 101 1101
618          *              --> 12 DB
619          * D15          = 0
620          *              --> power up cell phone input PGA
621          */
622         val     = omap_tsc2101_audio_read(TSC2101_BUZZER_GAIN_CTRL);
623         val     = val & 0x5dfe;
624         /* bits, D14, D12, D11, D10, D8, D6, D5,D4,D3,D2 */
625         val     = val | 0x5dfe;
626         omap_tsc2101_audio_write(TSC2101_BUZZER_GAIN_CTRL, val);
627
628         /*
629          * D6 - D0      = 000 1001
630          *              --> -4.5 db for DAC right channel volume control
631          * D7           = 1
632          *              -->  DAC right channel muted
633          * D14 - D8 = 000 1001
634          *              --> -4.5 db for DAC left channel volume control
635          * D15          = 1
636          *              --> DAC left channel muted
637          */
638         /* val  = omap_tsc2101_audio_read(TSC2101_DAC_GAIN_CTRL); */
639         val     = 0x8989;
640         omap_tsc2101_audio_write(TSC2101_DAC_GAIN_CTRL, val);
641
642         /*
643          *   0000 0000 0100 0000
644          *
645          * D1 - D0      = 0
646          *              --> GPIO 1 pin output is three stated
647          * D2           = 0
648          *              --> Disaple GPIO2 for CLKOUT mode
649          * D3           = 0
650          *              --> Disable GPUI1 for interrupt detection
651          * D4           = 0
652          *              --> Disable GPIO2 for headset detection interrupt
653          * D5           = reserved, always 0
654          * D7 - D6      = 01
655          *              --> 8 ms clitch detection
656          * D8           = reserved, write only 0
657          * D10 -D9      = 00
658          *              --> 16 ms de-bouncing
659          *          for glitch detection during headset detection
660          * D11          = flag for button press
661          * D12          = flag for headset detection
662          * D14-D13      = 00
663          *              --> type of headset detected = 00 == no stereo
664          *              headset deected
665          * D15          = 0
666          *              --> Disable headset detection
667          */
668         val     = 0x40;
669         omap_tsc2101_audio_write(TSC2101_AUDIO_CTRL_7, val);
670 }
671
672 /*
673  * Checks whether the headset is detected.
674  * If headset is detected, the type is returned. Type can be
675  *      0x01    = stereo headset detected
676  *      0x02    = cellurar headset detected
677  *      0x03    = stereo + cellurar headset detected
678  * If headset is not detected 0 is returned.
679  */
680 u16 get_headset_detected(void)
681 {
682         u16     curDetected;
683         u16     curType;
684         u16     curVal;
685
686         curType = 0;    /* not detected */
687         curVal  = omap_tsc2101_audio_read(TSC2101_AUDIO_CTRL_7);
688         curDetected     = curVal & AC7_HDDETFL;
689         if (curDetected) {
690                 printk(KERN_INFO "headset detected, checking type from %d \n",
691                         curVal);
692                 curType = ((curVal & 0x6000) >> 13);
693                 printk(KERN_INFO "headset type detected = %d \n", curType);
694         } else {
695                 printk(KERN_INFO "headset not detected\n");
696         }
697         return curType;
698 }
699
700 void init_playback_targets(void)
701 {
702         u16     val;
703
704         set_loudspeaker_to_playback_target();
705         /*
706          * Left line input volume control
707          * = SET_LINE in the OSS driver
708          */
709         set_mixer_volume_as_headset_gain_control_volume(DEFAULT_INPUT_VOLUME);
710
711         /*
712          * Set headset to be controllable by handset mixer
713          * AGC enable for handset input
714          * Handset input not muted
715          */
716         val     = omap_tsc2101_audio_read(TSC2101_HANDSET_GAIN_CTRL);
717         val     = val | HNGC_AGCEN_HND;
718         val     = val & ~HNGC_ADMUT_HND;
719         omap_tsc2101_audio_write(TSC2101_HANDSET_GAIN_CTRL, val);
720
721         /*
722          * mic input volume control
723          * SET_MIC in the OSS driver
724          */
725         set_mixer_volume_as_handset_gain_control_volume(DEFAULT_INPUT_VOLUME);
726
727         /*
728          * Left/Right headphone channel volume control
729          * Zero-cross detect on
730          */
731         set_mixer_volume_as_dac_gain_control_volume(DEFAULT_OUTPUT_VOLUME,
732                                                         DEFAULT_OUTPUT_VOLUME);
733         /* unmute */
734         dac_gain_control_unmute(1, 1);
735 }
736
737 /*
738  * Initializes tsc2101 recourd source (to line) and playback target
739  * (to loudspeaker)
740  */
741 void snd_omap_init_mixer(void)
742 {
743         FN_IN;
744
745         /* Headset/Hook switch detect enabled */
746         omap_tsc2101_audio_write(TSC2101_AUDIO_CTRL_7, AC7_DETECT);
747
748         /* Select headset to record source (MIC_INHED)*/
749         set_record_source(REC_SRC_SINGLE_ENDED_MICIN_HED);
750         /* Init loudspeaker as a default playback target*/
751         init_playback_targets();
752
753         FN_OUT(0);
754 }
755
756 static int __pcm_playback_target_info(struct snd_kcontrol *kcontrol,
757                 struct snd_ctl_elem_info *uinfo)
758 {
759         static char *texts[PLAYBACK_TARGET_COUNT] = {
760                 "Loudspeaker", "Headphone", "Cellphone"
761         };
762
763         uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
764         uinfo->count = 1;
765         uinfo->value.enumerated.items = PLAYBACK_TARGET_COUNT;
766         if (uinfo->value.enumerated.item > PLAYBACK_TARGET_COUNT - 1)
767                 uinfo->value.enumerated.item = PLAYBACK_TARGET_COUNT - 1;
768
769         strcpy(uinfo->value.enumerated.name,
770                 texts[uinfo->value.enumerated.item]);
771         return 0;
772 }
773
774 static int __pcm_playback_target_get(struct snd_kcontrol *kcontrol,
775                 struct snd_ctl_elem_value *ucontrol)
776 {
777         ucontrol->value.integer.value[0] = current_playback_target;
778         return 0;
779 }
780
781 static int __pcm_playback_target_put(struct snd_kcontrol *kcontrol,
782                 struct snd_ctl_elem_value *ucontrol)
783 {
784         int     retVal;
785         int     curVal;
786
787         retVal  = 0;
788         curVal  = ucontrol->value.integer.value[0];
789         if ((curVal >= 0) &&
790             (curVal < PLAYBACK_TARGET_COUNT) &&
791             (curVal != current_playback_target)) {
792                 if (curVal == PLAYBACK_TARGET_LOUDSPEAKER) {
793                         set_record_source(REC_SRC_SINGLE_ENDED_MICIN_HED);
794                         set_loudspeaker_to_playback_target();
795                 } else if (curVal == PLAYBACK_TARGET_HEADPHONE) {
796                         set_record_source(REC_SRC_SINGLE_ENDED_MICIN_HND);
797                         set_headphone_to_playback_target();
798                 } else if (curVal == PLAYBACK_TARGET_CELLPHONE) {
799                         set_telephone_to_record_source();
800                         set_telephone_to_playback_target();
801                 }
802                 retVal  = 1;
803         }
804         return retVal;
805 }
806
807 static int __pcm_playback_volume_info(struct snd_kcontrol *kcontrol,
808                 struct snd_ctl_elem_info *uinfo)
809 {
810         uinfo->type                     = SNDRV_CTL_ELEM_TYPE_INTEGER;
811         uinfo->count                    = 2;
812         uinfo->value.integer.min        = 0;
813         uinfo->value.integer.max        = 100;
814         return 0;
815 }
816
817 /*
818  * Alsa mixer interface function for getting the volume read from the DGC in a
819  * 0 -100 alsa mixer format.
820  */
821 static int __pcm_playback_volume_get(struct snd_kcontrol *kcontrol,
822                 struct snd_ctl_elem_value *ucontrol)
823 {
824         u16 volL;
825         u16 volR;
826         u16 val;
827
828         val     = omap_tsc2101_audio_read(TSC2101_DAC_GAIN_CTRL);
829         M_DPRINTK("registry value = %d!\n", val);
830         volL    = DGC_DALVL_EXTRACT(val);
831         volR    = DGC_DARVL_EXTRACT(val);
832         /* make sure that other bits are not on */
833         volL    = volL & ~DGC_DALMU;
834         volR    = volR & ~DGC_DARMU;
835
836         volL    = get_dac_gain_control_volume_as_mixer_volume(volL);
837         volR    = get_dac_gain_control_volume_as_mixer_volume(volR);
838
839         ucontrol->value.integer.value[0]        = volL; /* L */
840         ucontrol->value.integer.value[1]        = volR; /* R */
841
842         M_DPRINTK("mixer volume left = %ld, right = %ld\n",
843                         ucontrol->value.integer.value[0],
844                         ucontrol->value.integer.value[1]);
845         return 0;
846 }
847
848 static int __pcm_playback_volume_put(struct snd_kcontrol *kcontrol,
849                 struct snd_ctl_elem_value *ucontrol)
850 {
851         return set_mixer_volume_as_dac_gain_control_volume(
852                                         ucontrol->value.integer.value[0],
853                                         ucontrol->value.integer.value[1]);
854 }
855
856 static int __pcm_playback_switch_info(struct snd_kcontrol *kcontrol,
857                 struct snd_ctl_elem_info *uinfo)
858 {
859         uinfo->type                     = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
860         uinfo->count                    = 2;
861         uinfo->value.integer.min        = 0;
862         uinfo->value.integer.max        = 1;
863         return 0;
864 }
865
866 /*
867  * When DGC_DALMU (bit 15) is 1, the left channel is muted.
868  * When DGC_DALMU is 0, left channel is not muted.
869  * Same logic apply also for the right channel.
870  */
871 static int __pcm_playback_switch_get(struct snd_kcontrol *kcontrol,
872                 struct snd_ctl_elem_value *ucontrol)
873 {
874         u16 val = omap_tsc2101_audio_read(TSC2101_DAC_GAIN_CTRL);
875
876         ucontrol->value.integer.value[0] = IS_UNMUTED(15, val); /* left */
877         ucontrol->value.integer.value[1] = IS_UNMUTED(7, val); /* right */
878         return 0;
879 }
880
881 static int __pcm_playback_switch_put(struct snd_kcontrol *kcontrol,
882                 struct snd_ctl_elem_value *ucontrol)
883 {
884         return dac_gain_control_unmute(ucontrol->value.integer.value[0],
885                                         ucontrol->value.integer.value[1]);
886 }
887
888 static int __headset_playback_volume_info(struct snd_kcontrol *kcontrol,
889                 struct snd_ctl_elem_info *uinfo)
890 {
891         uinfo->type                     = SNDRV_CTL_ELEM_TYPE_INTEGER;
892         uinfo->count                    = 1;
893         uinfo->value.integer.min        = 0;
894         uinfo->value.integer.max        = 100;
895         return 0;
896 }
897
898 static int __headset_playback_volume_get(struct snd_kcontrol *kcontrol,
899                 struct snd_ctl_elem_value *ucontrol)
900 {
901         u16 val;
902         u16 vol;
903
904         val     = omap_tsc2101_audio_read(TSC2101_HEADSET_GAIN_CTRL);
905         M_DPRINTK("registry value = %d\n", val);
906         vol     = HGC_ADPGA_HED_EXTRACT(val);
907         vol     = vol & ~HGC_ADMUT_HED;
908
909         vol     = get_headset_gain_control_volume_as_mixer_volume(vol);
910         ucontrol->value.integer.value[0]        = vol;
911
912         M_DPRINTK("mixer volume returned = %ld\n",
913                         ucontrol->value.integer.value[0]);
914         return 0;
915 }
916
917 static int __headset_playback_volume_put(struct snd_kcontrol *kcontrol,
918                 struct snd_ctl_elem_value *ucontrol)
919 {
920         return set_mixer_volume_as_headset_gain_control_volume(
921                                         ucontrol->value.integer.value[0]);
922 }
923
924 static int __headset_playback_switch_info(struct snd_kcontrol *kcontrol,
925                 struct snd_ctl_elem_info *uinfo)
926 {
927         uinfo->type                     = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
928         uinfo->count                    = 1;
929         uinfo->value.integer.min        = 0;
930         uinfo->value.integer.max        = 1;
931         return 0;
932 }
933
934 /*
935  * When HGC_ADMUT_HED (bit 15) is 1, the headset is muted.
936  * When HGC_ADMUT_HED is 0, headset is not muted.
937  */
938 static int __headset_playback_switch_get(struct snd_kcontrol *kcontrol,
939                 struct snd_ctl_elem_value *ucontrol)
940 {
941         u16 val = omap_tsc2101_audio_read(TSC2101_HEADSET_GAIN_CTRL);
942         ucontrol->value.integer.value[0]        = IS_UNMUTED(15, val);
943         return 0;
944 }
945
946 static int __headset_playback_switch_put(struct snd_kcontrol *kcontrol,
947                 struct snd_ctl_elem_value *ucontrol)
948 {
949         /* mute/unmute headset */
950         return adc_pga_unmute_control(ucontrol->value.integer.value[0],
951                                 TSC2101_HEADSET_GAIN_CTRL,
952                                 15);
953 }
954
955 static int __handset_playback_volume_info(struct snd_kcontrol *kcontrol,
956                 struct snd_ctl_elem_info *uinfo)
957 {
958         uinfo->type                     = SNDRV_CTL_ELEM_TYPE_INTEGER;
959         uinfo->count                    = 1;
960         uinfo->value.integer.min        = 0;
961         uinfo->value.integer.max        = 100;
962         return 0;
963 }
964
965 static int __handset_playback_volume_get(struct snd_kcontrol *kcontrol,
966                 struct snd_ctl_elem_value *ucontrol)
967 {
968         u16 val;
969         u16 vol;
970
971         val     = omap_tsc2101_audio_read(TSC2101_HANDSET_GAIN_CTRL);
972         M_DPRINTK("registry value = %d\n", val);
973         vol     = HNGC_ADPGA_HND_EXTRACT(val);
974         vol     = vol & ~HNGC_ADMUT_HND;
975         vol     = get_handset_gain_control_volume_as_mixer_volume(vol);
976         ucontrol->value.integer.value[0]        = vol;
977
978         M_DPRINTK("mixer volume returned = %ld\n",
979                         ucontrol->value.integer.value[0]);
980         return 0;
981 }
982
983 static int __handset_playback_volume_put(struct snd_kcontrol *kcontrol,
984                 struct snd_ctl_elem_value *ucontrol)
985 {
986         return set_mixer_volume_as_handset_gain_control_volume(
987                                         ucontrol->value.integer.value[0]);
988 }
989
990 static int __handset_playback_switch_info(struct snd_kcontrol *kcontrol,
991                 struct snd_ctl_elem_info *uinfo)
992 {
993         uinfo->type                     = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
994         uinfo->count                    = 1;
995         uinfo->value.integer.min        = 0;
996         uinfo->value.integer.max        = 1;
997         return 0;
998 }
999
1000 /*
1001  * When HNGC_ADMUT_HND (bit 15) is 1, the handset is muted.
1002  * When HNGC_ADMUT_HND is 0, handset is not muted.
1003  */
1004 static int __handset_playback_switch_get(struct snd_kcontrol *kcontrol,
1005                 struct snd_ctl_elem_value *ucontrol)
1006 {
1007         u16 val = omap_tsc2101_audio_read(TSC2101_HANDSET_GAIN_CTRL);
1008         ucontrol->value.integer.value[0]        = IS_UNMUTED(15, val);
1009         return 0;
1010 }
1011
1012 static int __handset_playback_switch_put(struct snd_kcontrol *kcontrol,
1013                 struct snd_ctl_elem_value *ucontrol)
1014 {
1015         /* handset mute/unmute */
1016         return adc_pga_unmute_control(ucontrol->value.integer.value[0],
1017                                 TSC2101_HANDSET_GAIN_CTRL,
1018                                 15);
1019 }
1020
1021 static int __cellphone_input_switch_info(struct snd_kcontrol *kcontrol,
1022                 struct snd_ctl_elem_info *uinfo)
1023 {
1024         uinfo->type                     = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
1025         uinfo->count                    = 1;
1026         uinfo->value.integer.min        = 0;
1027         uinfo->value.integer.max        = 1;
1028         return 0;
1029 }
1030
1031 /*
1032  * When BGC_MUT_CP (bit 15) = 1, power down cellphone input pga.
1033  * When BGC_MUT_CP = 0, power up cellphone input pga.
1034  */
1035 static int __cellphone_input_switch_get(struct snd_kcontrol *kcontrol,
1036                 struct snd_ctl_elem_value *ucontrol)
1037 {
1038         u16 val = omap_tsc2101_audio_read(TSC2101_BUZZER_GAIN_CTRL);
1039         ucontrol->value.integer.value[0]        = IS_UNMUTED(15, val);
1040         return 0;
1041 }
1042
1043 static int __cellphone_input_switch_put(struct snd_kcontrol *kcontrol,
1044                 struct snd_ctl_elem_value *ucontrol)
1045 {
1046         return adc_pga_unmute_control(ucontrol->value.integer.value[0],
1047                                 TSC2101_BUZZER_GAIN_CTRL,
1048                                 15);
1049 }
1050
1051 static int __buzzer_input_switch_info(struct snd_kcontrol *kcontrol,
1052                 struct snd_ctl_elem_info *uinfo)
1053 {
1054         uinfo->type                     = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
1055         uinfo->count                    = 1;
1056         uinfo->value.integer.min        = 0;
1057         uinfo->value.integer.max        = 1;
1058         return 0;
1059 }
1060
1061 /*
1062  * When BGC_MUT_BU (bit 6) = 1, power down cellphone input pga.
1063  * When BGC_MUT_BU = 0, power up cellphone input pga.
1064  */
1065 static int __buzzer_input_switch_get(struct snd_kcontrol *kcontrol,
1066                 struct snd_ctl_elem_value *ucontrol)
1067 {
1068         u16 val = omap_tsc2101_audio_read(TSC2101_BUZZER_GAIN_CTRL);
1069         ucontrol->value.integer.value[0]        = IS_UNMUTED(6, val);
1070         return 0;
1071 }
1072
1073 static int __buzzer_input_switch_put(struct snd_kcontrol *kcontrol,
1074                 struct snd_ctl_elem_value *ucontrol)
1075 {
1076         return adc_pga_unmute_control(ucontrol->value.integer.value[0],
1077                                 TSC2101_BUZZER_GAIN_CTRL,
1078                                 6);
1079 }
1080
1081 static struct snd_kcontrol_new tsc2101_control[] __devinitdata = {
1082         {
1083                 .name   = "Target Playback Route",
1084                 .iface  = SNDRV_CTL_ELEM_IFACE_MIXER,
1085                 .index  = 0,
1086                 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
1087                 .info   = __pcm_playback_target_info,
1088                 .get    = __pcm_playback_target_get,
1089                 .put    = __pcm_playback_target_put,
1090         }, {
1091                 .name   = "Master Playback Volume",
1092                 .iface  = SNDRV_CTL_ELEM_IFACE_MIXER,
1093                 .index  = 0,
1094                 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
1095                 .info   = __pcm_playback_volume_info,
1096                 .get    = __pcm_playback_volume_get,
1097                 .put    = __pcm_playback_volume_put,
1098         }, {
1099                 .name   = "Master Playback Switch",
1100                 .iface  = SNDRV_CTL_ELEM_IFACE_MIXER,
1101                 .index  = 0,
1102                 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
1103                 .info   = __pcm_playback_switch_info,
1104                 .get    = __pcm_playback_switch_get,
1105                 .put    = __pcm_playback_switch_put,
1106         }, {
1107                 .name   = "Headset Playback Volume",
1108                 .iface  = SNDRV_CTL_ELEM_IFACE_MIXER,
1109                 .index  = 0,
1110                 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
1111                 .info   = __headset_playback_volume_info,
1112                 .get    = __headset_playback_volume_get,
1113                 .put    = __headset_playback_volume_put,
1114         }, {
1115                 .name   = "Headset Playback Switch",
1116                 .iface  = SNDRV_CTL_ELEM_IFACE_MIXER,
1117                 .index  = 0,
1118                 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
1119                 .info   = __headset_playback_switch_info,
1120                 .get    = __headset_playback_switch_get,
1121                 .put    = __headset_playback_switch_put,
1122         }, {
1123                 .name   = "Handset Playback Volume",
1124                 .iface  = SNDRV_CTL_ELEM_IFACE_MIXER,
1125                 .index  = 0,
1126                 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
1127                 .info   = __handset_playback_volume_info,
1128                 .get    = __handset_playback_volume_get,
1129                 .put    = __handset_playback_volume_put,
1130         }, {
1131                 .name   = "Handset Playback Switch",
1132                 .iface  = SNDRV_CTL_ELEM_IFACE_MIXER,
1133                 .index  = 0,
1134                 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
1135                 .info   = __handset_playback_switch_info,
1136                 .get    = __handset_playback_switch_get,
1137                 .put    = __handset_playback_switch_put,
1138         }, {
1139                 .name   = "Cellphone Input Switch",
1140                 .iface  = SNDRV_CTL_ELEM_IFACE_MIXER,
1141                 .index  = 0,
1142                 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
1143                 .info   = __cellphone_input_switch_info,
1144                 .get    = __cellphone_input_switch_get,
1145                 .put    = __cellphone_input_switch_put,
1146         }, {
1147                 .name   = "Buzzer Input Switch",
1148                 .iface  = SNDRV_CTL_ELEM_IFACE_MIXER,
1149                 .index  = 0,
1150                 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
1151                 .info   = __buzzer_input_switch_info,
1152                 .get    = __buzzer_input_switch_get,
1153                 .put    = __buzzer_input_switch_put,
1154         }
1155 };
1156
1157 #ifdef CONFIG_PM
1158
1159 void snd_omap_suspend_mixer(void)
1160 {
1161 }
1162
1163 void snd_omap_resume_mixer(void)
1164 {
1165         snd_omap_init_mixer();
1166 }
1167 #endif
1168
1169 int snd_omap_mixer(struct snd_card_omap_codec *tsc2101)
1170 {
1171         int i = 0;
1172         int err = 0;
1173
1174         if (!tsc2101)
1175                 return -EINVAL;
1176
1177         for (i = 0; i < ARRAY_SIZE(tsc2101_control); i++) {
1178                 err = snd_ctl_add(tsc2101->card,
1179                                         snd_ctl_new1(&tsc2101_control[i],
1180                                         tsc2101->card));
1181                 if (err < 0)
1182                         return err;
1183         }
1184         return 0;
1185 }