2 * sound/arm/omap/omap-alsa-tsc2101-mixer.c
4 * Alsa Driver for TSC2101 codec for OMAP platform boards.
6 * Copyright (C) 2005 Mika Laitio <lamikr@cc.jyu.fi> and
7 * Everett Coleman II <gcc80x86@fuzzyneural.net>
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
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.
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.
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.
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
43 #include "omap-alsa-tsc2101.h"
44 #include "omap-alsa-tsc2101-mixer.h"
46 #include <linux/types.h>
47 #include <sound/initval.h>
48 #include <sound/control.h>
50 //#define M_DPRINTK(ARGS...) printk(KERN_INFO "<%s>: ",__FUNCTION__);printk(ARGS)
51 #define M_DPRINTK(ARGS...) /* nop */
53 #define CHECK_BIT(INDX, ARG) (((ARG) & TSC2101_BIT(INDX)) >> INDX)
54 #define IS_UNMUTED(INDX, ARG) (((CHECK_BIT(INDX, ARG)) == 0))
56 #define DGC_DALVL_EXTRACT(ARG) ((ARG & 0x7f00) >> 8)
57 #define DGC_DARVL_EXTRACT(ARG) ((ARG & 0x007f))
59 #define HGC_ADPGA_HED_EXTRACT(ARG) ((ARG & 0x7f00) >> 8)
60 #define HNGC_ADPGA_HND_EXTRACT(ARG) ((ARG & 0x7f00) >> 8)
61 #define BGC_ADPGA_BGC_EXTRACT(ARG) ((ARG & 0x7f00) >> 8)
63 static int current_playback_target = PLAYBACK_TARGET_LOUDSPEAKER;
64 static int current_rec_src = REC_SRC_SINGLE_ENDED_MICIN_HED;
67 * Simplified write for the tsc2101 audio registers.
69 inline void omap_tsc2101_audio_write(u8 address, u16 data)
71 omap_tsc2101_write(PAGE2_AUDIO_CODEC_REGISTERS, address, data);
75 * Simplified read for the tsc2101 audio registers.
77 inline u16 omap_tsc2101_audio_read(u8 address)
79 return (omap_tsc2101_read(PAGE2_AUDIO_CODEC_REGISTERS, address));
83 * For selecting tsc2101 recourd source.
85 static void set_record_source(int val)
89 /* Mute Analog Sidetone
90 * Analog sidetone gain db?
91 * Input selected by MICSEL connected to ADC
93 data = MPC_ASTMU | MPC_ASTG(0x45);
94 data &= ~MPC_MICSEL(7); /* clear all MICSEL bits */
95 data |= MPC_MICSEL(val);
97 omap_tsc2101_audio_write(TSC2101_MIXER_PGA_CTRL, data);
99 current_rec_src = val;
103 * Converts the Alsa mixer volume (0 - 100) to real
104 * Digital Gain Control (DGC) value that can be written
105 * or read from the TSC2101 registry.
107 * Note that the number "OUTPUT_VOLUME_MAX" is smaller than OUTPUT_VOLUME_MIN
108 * because DGC works as a volume decreaser. (The more bigger value is put
109 * to DGC, the more the volume of controlled channel is decreased)
111 * In addition the TCS2101 chip would allow the maximum volume reduction be 63.5 DB
112 * but according to some tests user can not hear anything with this chip
113 * when the volume is set to be less than 25 db.
114 * Therefore this function will return a value that means 38.5 db (63.5 db - 25 db)
115 * reduction in the channel volume, when mixer is set to 0.
116 * For mixer value 100, this will return a value that means 0 db volume reduction.
117 * ([mute_left_bit]0000000[mute_right_bit]0000000)
119 int get_mixer_volume_as_dac_gain_control_volume(int vol)
123 /* Convert 0 -> 100 volume to 0x7F(min) -> y(max) volume range */
124 retVal = ((vol * OUTPUT_VOLUME_RANGE) / 100) + OUTPUT_VOLUME_MAX;
125 /* invert the value for getting the proper range 0 min and 100 max */
126 retVal = OUTPUT_VOLUME_MIN - retVal;
132 * Converts the Alsa mixer volume (0 - 100) to TSC2101
133 * Digital Gain Control (DGC) volume. Alsa mixer volume 0
134 * is converted to value meaning the volume reduction of -38.5 db
135 * and Alsa mixer volume 100 is converted to value meaning the
138 int set_mixer_volume_as_dac_gain_control_volume(int mixerVolL, int mixerVolR)
145 if ((mixerVolL < 0) ||
149 printk(KERN_ERR "Trying a bad mixer volume as dac gain control volume value, left (%d), right (%d)!\n", mixerVolL, mixerVolR);
152 M_DPRINTK("mixer volume left = %d, right = %d\n", mixerVolL, mixerVolR);
153 volL = get_mixer_volume_as_dac_gain_control_volume(mixerVolL);
154 volR = get_mixer_volume_as_dac_gain_control_volume(mixerVolR);
156 val = omap_tsc2101_audio_read(TSC2101_DAC_GAIN_CTRL);
157 /* keep the old mute bit settings */
158 val &= ~(DGC_DALVL(OUTPUT_VOLUME_MIN) | DGC_DARVL(OUTPUT_VOLUME_MIN));
159 val |= DGC_DALVL(volL) | DGC_DARVL(volR);
162 omap_tsc2101_audio_write(TSC2101_DAC_GAIN_CTRL, val);
164 M_DPRINTK("to registry: left = %d, right = %d, total = %d\n", DGC_DALVL_EXTRACT(val), DGC_DARVL_EXTRACT(val), val);
169 * If unmuteLeft/unmuteRight == 0 --> mute
170 * If unmuteLeft/unmuteRight == 1 --> unmute
172 int dac_gain_control_unmute(int unmuteLeft, int unmuteRight)
178 val = omap_tsc2101_audio_read(TSC2101_DAC_GAIN_CTRL);
179 /* in alsa mixer 1 --> on, 0 == off. In tsc2101 registry 1 --> off, 0 --> on
180 * so if values are same, it's time to change the registry value.
182 if (unmuteLeft != IS_UNMUTED(15, val)) {
183 if (unmuteLeft == 0) {
184 /* mute --> turn bit on */
185 val = val | DGC_DALMU;
188 /* unmute --> turn bit off */
189 val = val & ~DGC_DALMU;
193 if (unmuteRight != IS_UNMUTED(7, val)) {
194 if (unmuteRight == 0) {
195 /* mute --> turn bit on */
196 val = val | DGC_DARMU;
199 /* unmute --> turn bit off */
200 val = val & ~DGC_DARMU;
205 omap_tsc2101_audio_write(TSC2101_DAC_GAIN_CTRL, val);
206 M_DPRINTK("changed value, is_unmuted left = %d, right = %d\n",
214 * unmute: 0 --> mute, 1 --> unmute
215 * page2RegIndx: Registry index in tsc2101 page2.
216 * muteBitIndx: Index number for the bit in registry that indicates whether muted or unmuted.
218 int adc_pga_unmute_control(int unmute, int page2regIndx, int muteBitIndx)
224 val = omap_tsc2101_audio_read(page2regIndx);
225 /* in alsa mixer 1 --> on, 0 == off. In tsc2101 registry 1 --> off, 0 --> on
226 * so if the values are same, it's time to change the registry value...
228 if (unmute != IS_UNMUTED(muteBitIndx, val)) {
230 /* mute --> turn bit on */
231 val = val | TSC2101_BIT(muteBitIndx);
234 /* unmute --> turn bit off */
235 val = val & ~TSC2101_BIT(muteBitIndx);
237 M_DPRINTK("changed value, is_unmuted = %d\n", IS_UNMUTED(muteBitIndx, val));
241 omap_tsc2101_audio_write(page2regIndx, val);
247 * Converts the DGC registry value read from the TSC2101 registry to
248 * Alsa mixer volume format (0 - 100).
250 int get_dac_gain_control_volume_as_mixer_volume(u16 vol)
254 retVal = OUTPUT_VOLUME_MIN - vol;
255 retVal = ((retVal - OUTPUT_VOLUME_MAX) * 100) / OUTPUT_VOLUME_RANGE;
256 /* fix scaling error */
257 if ((retVal > 0) && (retVal < 100)) {
264 * Converts the headset gain control volume (0 - 63.5 db)
265 * to Alsa mixer volume (0 - 100)
267 int get_headset_gain_control_volume_as_mixer_volume(u16 registerVal)
271 retVal = ((registerVal * 100) / INPUT_VOLUME_RANGE);
276 * Converts the handset gain control volume (0 - 63.5 db)
277 * to Alsa mixer volume (0 - 100)
279 int get_handset_gain_control_volume_as_mixer_volume(u16 registerVal)
281 return get_headset_gain_control_volume_as_mixer_volume(registerVal);
285 * Converts the Alsa mixer volume (0 - 100) to
286 * headset gain control volume (0 - 63.5 db)
288 int get_mixer_volume_as_headset_gain_control_volume(u16 mixerVal)
292 retVal = ((mixerVal * INPUT_VOLUME_RANGE) / 100) + INPUT_VOLUME_MIN;
297 * Writes Alsa mixer volume (0 - 100) to TSC2101 headset volume registry in
298 * a TSC2101 format. (0 - 63.5 db)
299 * In TSC2101 OSS driver this functionality was controlled with "SET_LINE" parameter.
301 int set_mixer_volume_as_headset_gain_control_volume(int mixerVol)
307 if (mixerVol < 0 || mixerVol > 100) {
308 M_DPRINTK("Trying a bad headset mixer volume value(%d)!\n", mixerVol);
311 M_DPRINTK("mixer volume = %d\n", mixerVol);
312 /* Convert 0 -> 100 volume to 0x0(min) -> 0x7D(max) volume range */
313 /* NOTE: 0 is minimum volume and not mute */
314 volume = get_mixer_volume_as_headset_gain_control_volume(mixerVol);
315 val = omap_tsc2101_audio_read(TSC2101_HEADSET_GAIN_CTRL);
316 /* preserve the old mute settings */
317 val &= ~(HGC_ADPGA_HED(INPUT_VOLUME_MAX));
318 val |= HGC_ADPGA_HED(volume);
319 omap_tsc2101_audio_write(TSC2101_HEADSET_GAIN_CTRL, val);
322 M_DPRINTK("to registry = %d\n", val);
327 * Writes Alsa mixer volume (0 - 100) to TSC2101 handset volume registry in
328 * a TSC2101 format. (0 - 63.5 db)
329 * In TSC2101 OSS driver this functionality was controlled with "SET_MIC" parameter.
331 int set_mixer_volume_as_handset_gain_control_volume(int mixerVol)
337 if (mixerVol < 0 || mixerVol > 100) {
338 M_DPRINTK("Trying a bad mic mixer volume value(%d)!\n", mixerVol);
341 M_DPRINTK("mixer volume = %d\n", mixerVol);
342 /* Convert 0 -> 100 volume to 0x0(min) -> 0x7D(max) volume range
343 * NOTE: 0 is minimum volume and not mute
345 volume = get_mixer_volume_as_headset_gain_control_volume(mixerVol);
346 val = omap_tsc2101_audio_read(TSC2101_HANDSET_GAIN_CTRL);
347 /* preserve the old mute settigns */
348 val &= ~(HNGC_ADPGA_HND(INPUT_VOLUME_MAX));
349 val |= HNGC_ADPGA_HND(volume);
350 omap_tsc2101_audio_write(TSC2101_HANDSET_GAIN_CTRL, val);
353 M_DPRINTK("to registry = %d\n", val);
357 void set_loudspeaker_to_playback_target(void)
359 /* power down SPK1, SPK2 and loudspeaker */
360 omap_tsc2101_audio_write(TSC2101_CODEC_POWER_CTRL,
361 CPC_SP1PWDN | CPC_SP2PWDN | CPC_LDAPWDF);
362 /* ADC, DAC, Analog Sidetone, cellphone, buzzer softstepping enabled
366 omap_tsc2101_audio_write(TSC2101_AUDIO_CTRL_4, AC4_MB_HED(0));
368 /* DAC left and right routed to SPK1/SPK2
370 * Keyclicks routed to SPK1/SPK2 */
371 omap_tsc2101_audio_write(TSC2101_AUDIO_CTRL_5,
373 AC5_DAC2SPK1(3) | AC5_AST2SPK1 | AC5_KCL2SPK1 |
374 AC5_DAC2SPK2(3) | AC5_AST2SPK2 | AC5_KCL2SPK2);
376 /* routing selected to SPK1 goes also to OUT8P/OUT8N. (loudspeaker)
377 * analog sidetone routed to loudspeaker
378 * buzzer pga routed to loudspeaker
379 * keyclick routing to loudspeaker
380 * cellphone input routed to loudspeaker
381 * mic selection (control register 04h/page2) routed to cell phone output (CP_OUT)
382 * routing selected for SPK1 goes also to cellphone output (CP_OUT)
383 * OUT8P/OUT8N (loudspeakers) unmuted (0 = unmuted)
384 * Cellphone output is not muted (0 = unmuted)
385 * Enable loudspeaker short protection control (0 = enable protection)
386 * VGND short protection control (0 = enable protection)
388 omap_tsc2101_audio_write(TSC2101_AUDIO_CTRL_6,
389 AC6_SPL2LSK | AC6_AST2LSK | AC6_BUZ2LSK | AC6_KCL2LSK |
390 AC6_CPI2LSK | AC6_MIC2CPO | AC6_SPL2CPO);
391 current_playback_target = PLAYBACK_TARGET_LOUDSPEAKER;
394 void set_headphone_to_playback_target(void)
396 /* power down SPK1, SPK2 and loudspeaker */
397 omap_tsc2101_audio_write(TSC2101_CODEC_POWER_CTRL,
398 CPC_SP1PWDN | CPC_SP2PWDN | CPC_LDAPWDF);
399 /* ADC, DAC, Analog Sidetone, cellphone, buzzer softstepping enabled */
400 /* 1dB AGC hysteresis */
402 omap_tsc2101_audio_write(TSC2101_AUDIO_CTRL_4, AC4_MB_HED(0));
404 /* DAC left and right routed to SPK1/SPK2
406 * Keyclicks routed to SPK1/SPK2 */
407 omap_tsc2101_audio_write(TSC2101_AUDIO_CTRL_5,
408 AC5_DAC2SPK1(3) | AC5_AST2SPK1 | AC5_KCL2SPK1 |
409 AC5_DAC2SPK2(3) | AC5_AST2SPK2 | AC5_KCL2SPK2 |
412 /* OUT8P/OUT8N muted, CPOUT muted */
413 omap_tsc2101_audio_write(TSC2101_AUDIO_CTRL_6,
414 AC6_MUTLSPK | AC6_MUTSPK2 | AC6_LDSCPTC |
416 current_playback_target = PLAYBACK_TARGET_HEADPHONE;
419 void set_telephone_to_playback_target(void)
422 * 0110 1101 0101 1100
423 * power down MICBIAS_HED, Analog sidetone, SPK2, DAC,
424 * Driver virtual ground, loudspeaker. Values D2-d5 are flags.
426 omap_tsc2101_audio_write(TSC2101_CODEC_POWER_CTRL,
427 CPC_MBIAS_HED | CPC_ASTPWD | CPC_SP2PWDN | CPC_DAPWDN |
428 CPC_VGPWDN | CPC_LSPWDN);
431 * 0010 1010 0100 0000
432 * ADC, DAC, Analog Sidetone, cellphone, buzzer softstepping enabled
436 omap_tsc2101_audio_write(TSC2101_AUDIO_CTRL_4,
437 AC4_MB_HND | AC4_MB_HED(0) | AC4_AGCHYS(1) |
438 AC4_BISTPD | AC4_ASSTPD | AC4_DASTPD);
439 printk("set_telephone_to_playback_target(), TSC2101_AUDIO_CTRL_4 = %d\n", omap_tsc2101_audio_read(TSC2101_AUDIO_CTRL_4));
442 * 1110 0010 0000 0010
443 * DAC left and right routed to SPK1/SPK2
445 * keyclicks routed to SPK1/SPK2
447 omap_tsc2101_audio_write(TSC2101_AUDIO_CTRL_5,
448 AC5_DIFFIN | AC5_DAC2SPK1(3) |
449 AC5_CPI2SPK1 | AC5_MUTSPK2);
451 omap_tsc2101_audio_write(TSC2101_AUDIO_CTRL_6,
452 AC6_MIC2CPO | AC6_MUTLSPK |
453 AC6_LDSCPTC | AC6_VGNDSCPTC | AC6_CAPINTF);
454 current_playback_target = PLAYBACK_TARGET_CELLPHONE;
458 * 1100 0101 1101 0000
460 * #define MPC_ASTMU TSC2101_BIT(15)
461 * #define MPC_ASTG(ARG) (((ARG) & 0x7F) << 8)
462 * #define MPC_MICSEL(ARG) (((ARG) & 0x07) << 5)
463 * #define MPC_MICADC TSC2101_BIT(4)
464 * #define MPC_CPADC TSC2101_BIT(3)
465 * #define MPC_ASTGF (0x01)
467 static void set_telephone_to_record_source(void)
473 * --> AGC is off for handset input.
474 * --> ADC PGA is controlled by the ADMUT_HDN + ADPGA_HND
477 * --> AGC time constant for handset input,
478 * attack time = 8 mc, decay time = 100 ms
480 * --> AGC Target gain for handset input = -5.5 db
481 * D14 - D8 = 011 1100
482 * --> ADC handset PGA settings = 60 = 30 db
484 * --> Handset input ON (unmuted)
486 val = 0x3c00; // 0011 1100 0000 0000 = 60 = 30
487 omap_tsc2101_audio_write(TSC2101_HANDSET_GAIN_CTRL, val);
491 * --> AGC is off for headset/Aux input
492 * --> ADC headset/Aux PGA is contoller by ADMUT_HED + ADPGA_HED
495 * --> Agc constant for headset/Aux input,
496 * attack time = 8 mc, decay time = 100 ms
498 * --> AGC target gain for headset input = -5.5 db
499 * D14 - D8 = 000 0000
500 * --> Adc headset/AUX pga settings = 0 db
502 * --> Headset/AUX input muted
504 * Mute headset aux input
506 val = 0x8000; // 1000 0000 0000 0000
507 omap_tsc2101_audio_write(TSC2101_HEADSET_GAIN_CTRL, val);
508 set_record_source(REC_SRC_MICIN_HND_AND_AUX1);
511 /* D0 = flag, Headset/Aux or handset PGA flag
512 * --> & with 1 (= 1 -->gain applied == pga register settings)
513 * D1 = 0, DAC channel PGA soft stepping control
514 * --> 0.5 db change every WCLK
515 * D2 = flag, DAC right channel PGA flag
517 * D3 = flag, DAC left channel PGA flag
519 * D7 - D4 = 0001, keyclick length
520 * --> 4 periods key clicks
521 * D10 - D8 = 100, keyclick frequenzy
523 * D11 = 0, Headset/Aux or handset soft stepping control
524 * --> 0,5 db change every WCLK or ADWS
525 * D14 -D12 = 100, Keyclick applitude control
526 * --> Medium amplitude
527 * D15 = 0, keyclick disabled
529 val = omap_tsc2101_audio_read(TSC2101_AUDIO_CTRL_2);
531 val = val | 0x4410; // D14, D10, D4 bits == 1
532 omap_tsc2101_audio_write(TSC2101_AUDIO_CTRL_2, val);
535 * D0 = 0 (reserved, write always 0)
538 * D2 - D5 = 0000 (reserved, write always 0000)
540 * --> MICBIAS_HND = 2.0 v
542 * --> MICBIAS_HED = 3.3 v
544 * --> Mic AGC hysteric selection = 2 db
546 * --> Disable buzzer PGA soft stepping
548 * --> Enable CELL phone PGA soft stepping control
550 * --> Disable analog sidetone soft stepping control
552 * --> Enable DAC PGA soft stepping control
554 * --> Enable headset/Aux or Handset soft stepping control
556 val = omap_tsc2101_audio_read(TSC2101_AUDIO_CTRL_4);
557 val = val & 0x2a42; // 0010 1010 0100 0010
558 val = val | 0x2a40; // bits D13, D11, D9, D6 == 1
559 omap_tsc2101_audio_write(TSC2101_AUDIO_CTRL_4, val);
560 printk("set_telephone_to_record_source(), TSC2101_AUDIO_CTRL_4 = %d\n", omap_tsc2101_audio_read(TSC2101_AUDIO_CTRL_4));
563 * --> reserved, write always = 0
564 * D1 = flag, read only
566 * D5 - D2 = 1111, Buzzer input PGA settings
569 * --> power down buzzer input pga
570 * D7 = flag, read only
572 * D14 - D8 = 101 1101
575 * --> power up cell phone input PGA
577 val = omap_tsc2101_audio_read(TSC2101_BUZZER_GAIN_CTRL);
579 val = val | 0x5dfe; // bits, D14, D12, D11, D10, D8, D6, D5,D4,D3,D2
580 omap_tsc2101_audio_write(TSC2101_BUZZER_GAIN_CTRL, val);
582 /* D6 - D0 = 000 1001
583 * --> -4.5 db for DAC right channel volume control
585 * --> DAC right channel muted
586 * D14 - D8 = 000 1001
587 * --> -4.5 db for DAC left channel volume control
589 * --> DAC left channel muted
591 //val = omap_tsc2101_audio_read(TSC2101_DAC_GAIN_CTRL);
593 omap_tsc2101_audio_write(TSC2101_DAC_GAIN_CTRL, val);
595 /* 0000 0000 0100 0000
598 * --> GPIO 1 pin output is three stated
600 * --> Disaple GPIO2 for CLKOUT mode
602 * --> Disable GPUI1 for interrupt detection
604 * --> Disable GPIO2 for headset detection interrupt
605 * D5 = reserved, always 0
607 * --> 8 ms clitch detection
608 * D8 = reserved, write only 0
610 * --> 16 ms de bouncing programmatitily
611 * for glitch detection during headset detection
612 * D11 = flag for button press
613 * D12 = flag for headset detection
615 * --> type of headset detected = 00 == no stereo headset deected
617 * --> Disable headset detection
621 omap_tsc2101_audio_write(TSC2101_AUDIO_CTRL_7, val);
625 * Checks whether the headset is detected.
626 * If headset is detected, the type is returned. Type can be
627 * 0x01 = stereo headset detected
628 * 0x02 = cellurar headset detected
629 * 0x03 = stereo + cellurar headset detected
630 * If headset is not detected 0 is returned.
632 u16 get_headset_detected(void)
638 curType = 0; /* not detected */
639 curVal = omap_tsc2101_audio_read(TSC2101_AUDIO_CTRL_7);
640 curDetected = curVal & AC7_HDDETFL;
642 printk("headset detected, checking type from %d \n", curVal);
643 curType = ((curVal & 0x6000) >> 13);
644 printk("headset type detected = %d \n", curType);
647 printk("headset not detected\n");
652 void init_playback_targets(void)
656 set_loudspeaker_to_playback_target();
657 /* Left line input volume control
658 * = SET_LINE in the OSS driver
660 set_mixer_volume_as_headset_gain_control_volume(DEFAULT_INPUT_VOLUME);
662 /* Set headset to be controllable by handset mixer
663 * AGC enable for handset input
664 * Handset input not muted
666 val = omap_tsc2101_audio_read(TSC2101_HANDSET_GAIN_CTRL);
667 val = val | HNGC_AGCEN_HND;
668 val = val & ~HNGC_ADMUT_HND;
669 omap_tsc2101_audio_write(TSC2101_HANDSET_GAIN_CTRL, val);
671 /* mic input volume control
672 * SET_MIC in the OSS driver
674 set_mixer_volume_as_handset_gain_control_volume(DEFAULT_INPUT_VOLUME);
676 /* Left/Right headphone channel volume control
677 * Zero-cross detect on
679 set_mixer_volume_as_dac_gain_control_volume(DEFAULT_OUTPUT_VOLUME, DEFAULT_OUTPUT_VOLUME);
681 dac_gain_control_unmute(1, 1);
685 * Initializes tsc2101 recourd source (to line) and playback target (to loudspeaker)
687 void snd_omap_init_mixer(void)
691 /* Headset/Hook switch detect enabled */
692 omap_tsc2101_audio_write(TSC2101_AUDIO_CTRL_7, AC7_DETECT);
694 /* Select headset to record source (MIC_INHED)*/
695 set_record_source(REC_SRC_SINGLE_ENDED_MICIN_HED);
696 /* Init loudspeaker as a default playback target*/
697 init_playback_targets();
702 static int __pcm_playback_target_info(struct snd_kcontrol *kcontrol,
703 struct snd_ctl_elem_info *uinfo)
705 static char *texts[PLAYBACK_TARGET_COUNT] = {
706 "Loudspeaker", "Headphone", "Cellphone"
709 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
711 uinfo->value.enumerated.items = PLAYBACK_TARGET_COUNT;
712 if (uinfo->value.enumerated.item > PLAYBACK_TARGET_COUNT - 1) {
713 uinfo->value.enumerated.item = PLAYBACK_TARGET_COUNT - 1;
715 strcpy(uinfo->value.enumerated.name,
716 texts[uinfo->value.enumerated.item]);
720 static int __pcm_playback_target_get(struct snd_kcontrol *kcontrol,
721 struct snd_ctl_elem_value *ucontrol)
723 ucontrol->value.integer.value[0] = current_playback_target;
727 static int __pcm_playback_target_put(struct snd_kcontrol *kcontrol,
728 struct snd_ctl_elem_value *ucontrol)
734 curVal = ucontrol->value.integer.value[0];
736 (curVal < PLAYBACK_TARGET_COUNT) &&
737 (curVal != current_playback_target)) {
738 if (curVal == PLAYBACK_TARGET_LOUDSPEAKER) {
739 set_record_source(REC_SRC_SINGLE_ENDED_MICIN_HED);
740 set_loudspeaker_to_playback_target();
742 else if (curVal == PLAYBACK_TARGET_HEADPHONE) {
743 set_record_source(REC_SRC_SINGLE_ENDED_MICIN_HND);
744 set_headphone_to_playback_target();
746 else if (curVal == PLAYBACK_TARGET_CELLPHONE) {
747 set_telephone_to_record_source();
748 set_telephone_to_playback_target();
755 static int __pcm_playback_volume_info(struct snd_kcontrol *kcontrol,
756 struct snd_ctl_elem_info *uinfo)
758 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
760 uinfo->value.integer.min = 0;
761 uinfo->value.integer.max = 100;
766 * Alsa mixer interface function for getting the volume read from the DGC in a
767 * 0 -100 alsa mixer format.
769 static int __pcm_playback_volume_get(struct snd_kcontrol *kcontrol,
770 struct snd_ctl_elem_value *ucontrol)
776 val = omap_tsc2101_audio_read(TSC2101_DAC_GAIN_CTRL);
777 M_DPRINTK("registry value = %d!\n", val);
778 volL = DGC_DALVL_EXTRACT(val);
779 volR = DGC_DARVL_EXTRACT(val);
780 /* make sure that other bits are not on */
781 volL = volL & ~DGC_DALMU;
782 volR = volR & ~DGC_DARMU;
784 volL = get_dac_gain_control_volume_as_mixer_volume(volL);
785 volR = get_dac_gain_control_volume_as_mixer_volume(volR);
787 ucontrol->value.integer.value[0] = volL; /* L */
788 ucontrol->value.integer.value[1] = volR; /* R */
790 M_DPRINTK("mixer volume left = %ld, right = %ld\n", ucontrol->value.integer.value[0], ucontrol->value.integer.value[1]);
794 static int __pcm_playback_volume_put(struct snd_kcontrol *kcontrol,
795 struct snd_ctl_elem_value *ucontrol)
797 return set_mixer_volume_as_dac_gain_control_volume(ucontrol->value.integer.value[0],
798 ucontrol->value.integer.value[1]);
801 static int __pcm_playback_switch_info(struct snd_kcontrol *kcontrol,
802 struct snd_ctl_elem_info *uinfo)
804 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
806 uinfo->value.integer.min = 0;
807 uinfo->value.integer.max = 1;
812 * When DGC_DALMU (bit 15) is 1, the left channel is muted.
813 * When DGC_DALMU is 0, left channel is not muted.
814 * Same logic apply also for the right channel.
816 static int __pcm_playback_switch_get(struct snd_kcontrol *kcontrol,
817 struct snd_ctl_elem_value *ucontrol)
819 u16 val = omap_tsc2101_audio_read(TSC2101_DAC_GAIN_CTRL);
821 ucontrol->value.integer.value[0] = IS_UNMUTED(15, val); // left
822 ucontrol->value.integer.value[1] = IS_UNMUTED(7, val); // right
826 static int __pcm_playback_switch_put(struct snd_kcontrol *kcontrol,
827 struct snd_ctl_elem_value *ucontrol)
829 return dac_gain_control_unmute(ucontrol->value.integer.value[0],
830 ucontrol->value.integer.value[1]);
833 static int __headset_playback_volume_info(struct snd_kcontrol *kcontrol,
834 struct snd_ctl_elem_info *uinfo)
836 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
838 uinfo->value.integer.min = 0;
839 uinfo->value.integer.max = 100;
843 static int __headset_playback_volume_get(struct snd_kcontrol *kcontrol,
844 struct snd_ctl_elem_value *ucontrol)
849 val = omap_tsc2101_audio_read(TSC2101_HEADSET_GAIN_CTRL);
850 M_DPRINTK("registry value = %d\n", val);
851 vol = HGC_ADPGA_HED_EXTRACT(val);
852 vol = vol & ~HGC_ADMUT_HED;
854 vol = get_headset_gain_control_volume_as_mixer_volume(vol);
855 ucontrol->value.integer.value[0] = vol;
857 M_DPRINTK("mixer volume returned = %ld\n", ucontrol->value.integer.value[0]);
861 static int __headset_playback_volume_put(struct snd_kcontrol *kcontrol,
862 struct snd_ctl_elem_value *ucontrol)
864 return set_mixer_volume_as_headset_gain_control_volume(ucontrol->value.integer.value[0]);
867 static int __headset_playback_switch_info(struct snd_kcontrol *kcontrol,
868 struct snd_ctl_elem_info *uinfo)
870 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
872 uinfo->value.integer.min = 0;
873 uinfo->value.integer.max = 1;
877 /* When HGC_ADMUT_HED (bit 15) is 1, the headset is muted.
878 * When HGC_ADMUT_HED is 0, headset is not muted.
880 static int __headset_playback_switch_get(struct snd_kcontrol *kcontrol,
881 struct snd_ctl_elem_value *ucontrol)
883 u16 val = omap_tsc2101_audio_read(TSC2101_HEADSET_GAIN_CTRL);
884 ucontrol->value.integer.value[0] = IS_UNMUTED(15, val);
888 static int __headset_playback_switch_put(struct snd_kcontrol *kcontrol,
889 struct snd_ctl_elem_value *ucontrol)
891 // mute/unmute headset
892 return adc_pga_unmute_control(ucontrol->value.integer.value[0],
893 TSC2101_HEADSET_GAIN_CTRL,
897 static int __handset_playback_volume_info(struct snd_kcontrol *kcontrol,
898 struct snd_ctl_elem_info *uinfo)
900 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
902 uinfo->value.integer.min = 0;
903 uinfo->value.integer.max = 100;
907 static int __handset_playback_volume_get(struct snd_kcontrol *kcontrol,
908 struct snd_ctl_elem_value *ucontrol)
913 val = omap_tsc2101_audio_read(TSC2101_HANDSET_GAIN_CTRL);
914 M_DPRINTK("registry value = %d\n", val);
915 vol = HNGC_ADPGA_HND_EXTRACT(val);
916 vol = vol & ~HNGC_ADMUT_HND;
917 vol = get_handset_gain_control_volume_as_mixer_volume(vol);
918 ucontrol->value.integer.value[0] = vol;
920 M_DPRINTK("mixer volume returned = %ld\n", ucontrol->value.integer.value[0]);
924 static int __handset_playback_volume_put(struct snd_kcontrol *kcontrol,
925 struct snd_ctl_elem_value *ucontrol)
927 return set_mixer_volume_as_handset_gain_control_volume(ucontrol->value.integer.value[0]);
930 static int __handset_playback_switch_info(struct snd_kcontrol *kcontrol,
931 struct snd_ctl_elem_info *uinfo)
933 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
935 uinfo->value.integer.min = 0;
936 uinfo->value.integer.max = 1;
940 /* When HNGC_ADMUT_HND (bit 15) is 1, the handset is muted.
941 * When HNGC_ADMUT_HND is 0, handset is not muted.
943 static int __handset_playback_switch_get(struct snd_kcontrol *kcontrol,
944 struct snd_ctl_elem_value *ucontrol)
946 u16 val = omap_tsc2101_audio_read(TSC2101_HANDSET_GAIN_CTRL);
947 ucontrol->value.integer.value[0] = IS_UNMUTED(15, val);
951 static int __handset_playback_switch_put(struct snd_kcontrol *kcontrol,
952 struct snd_ctl_elem_value *ucontrol)
954 // handset mute/unmute
955 return adc_pga_unmute_control(ucontrol->value.integer.value[0],
956 TSC2101_HANDSET_GAIN_CTRL,
960 static int __cellphone_input_switch_info(struct snd_kcontrol *kcontrol,
961 struct snd_ctl_elem_info *uinfo)
963 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
965 uinfo->value.integer.min = 0;
966 uinfo->value.integer.max = 1;
970 /* When BGC_MUT_CP (bit 15) = 1, power down cellphone input pga.
971 * When BGC_MUT_CP = 0, power up cellphone input pga.
973 static int __cellphone_input_switch_get(struct snd_kcontrol *kcontrol,
974 struct snd_ctl_elem_value *ucontrol)
976 u16 val = omap_tsc2101_audio_read(TSC2101_BUZZER_GAIN_CTRL);
977 ucontrol->value.integer.value[0] = IS_UNMUTED(15, val);
981 static int __cellphone_input_switch_put(struct snd_kcontrol *kcontrol,
982 struct snd_ctl_elem_value *ucontrol)
984 return adc_pga_unmute_control(ucontrol->value.integer.value[0],
985 TSC2101_BUZZER_GAIN_CTRL,
989 static int __buzzer_input_switch_info(struct snd_kcontrol *kcontrol,
990 struct snd_ctl_elem_info *uinfo)
992 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
994 uinfo->value.integer.min = 0;
995 uinfo->value.integer.max = 1;
999 /* When BGC_MUT_BU (bit 6) = 1, power down cellphone input pga.
1000 * When BGC_MUT_BU = 0, power up cellphone input pga.
1002 static int __buzzer_input_switch_get(struct snd_kcontrol *kcontrol,
1003 struct snd_ctl_elem_value *ucontrol)
1005 u16 val = omap_tsc2101_audio_read(TSC2101_BUZZER_GAIN_CTRL);
1006 ucontrol->value.integer.value[0] = IS_UNMUTED(6, val);
1010 static int __buzzer_input_switch_put(struct snd_kcontrol *kcontrol,
1011 struct snd_ctl_elem_value *ucontrol)
1013 return adc_pga_unmute_control(ucontrol->value.integer.value[0],
1014 TSC2101_BUZZER_GAIN_CTRL,
1018 static struct snd_kcontrol_new tsc2101_control[] __devinitdata = {
1020 .name = "Target Playback Route",
1021 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1023 .access= SNDRV_CTL_ELEM_ACCESS_READWRITE,
1024 .info = __pcm_playback_target_info,
1025 .get = __pcm_playback_target_get,
1026 .put = __pcm_playback_target_put,
1028 .name = "Master Playback Volume",
1029 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1031 .access= SNDRV_CTL_ELEM_ACCESS_READWRITE,
1032 .info = __pcm_playback_volume_info,
1033 .get = __pcm_playback_volume_get,
1034 .put = __pcm_playback_volume_put,
1036 .name = "Master Playback Switch",
1037 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1039 .access= SNDRV_CTL_ELEM_ACCESS_READWRITE,
1040 .info = __pcm_playback_switch_info,
1041 .get = __pcm_playback_switch_get,
1042 .put = __pcm_playback_switch_put,
1044 .name = "Headset Playback Volume",
1045 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1047 .access= SNDRV_CTL_ELEM_ACCESS_READWRITE,
1048 .info = __headset_playback_volume_info,
1049 .get = __headset_playback_volume_get,
1050 .put = __headset_playback_volume_put,
1052 .name = "Headset Playback Switch",
1053 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1055 .access= SNDRV_CTL_ELEM_ACCESS_READWRITE,
1056 .info = __headset_playback_switch_info,
1057 .get = __headset_playback_switch_get,
1058 .put = __headset_playback_switch_put,
1060 .name = "Handset Playback Volume",
1061 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1063 .access= SNDRV_CTL_ELEM_ACCESS_READWRITE,
1064 .info = __handset_playback_volume_info,
1065 .get = __handset_playback_volume_get,
1066 .put = __handset_playback_volume_put,
1068 .name = "Handset Playback Switch",
1069 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1071 .access= SNDRV_CTL_ELEM_ACCESS_READWRITE,
1072 .info = __handset_playback_switch_info,
1073 .get = __handset_playback_switch_get,
1074 .put = __handset_playback_switch_put,
1076 .name = "Cellphone Input Switch",
1077 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1079 .access= SNDRV_CTL_ELEM_ACCESS_READWRITE,
1080 .info = __cellphone_input_switch_info,
1081 .get = __cellphone_input_switch_get,
1082 .put = __cellphone_input_switch_put,
1084 .name = "Buzzer Input Switch",
1085 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1087 .access= SNDRV_CTL_ELEM_ACCESS_READWRITE,
1088 .info = __buzzer_input_switch_info,
1089 .get = __buzzer_input_switch_get,
1090 .put = __buzzer_input_switch_put,
1096 void snd_omap_suspend_mixer(void)
1100 void snd_omap_resume_mixer(void)
1102 snd_omap_init_mixer();
1106 int snd_omap_mixer(struct snd_card_omap_codec *tsc2101)
1114 for (i=0; i < ARRAY_SIZE(tsc2101_control); i++) {
1115 if ((err = snd_ctl_add(tsc2101->card,
1116 snd_ctl_new1(&tsc2101_control[i],
1117 tsc2101->card))) < 0) {