]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/commitdiff
h63xx: tsc2101 alsa sound support b2.6.16-omap1-h63xx v2.6.16-omap1-h63xx-1
authorMika Laitio <lamikr@pilppa.org>
Mon, 19 Jan 2009 23:15:09 +0000 (01:15 +0200)
committerMika Laitio <lamikr@pilppa.org>
Mon, 19 Jan 2009 23:15:09 +0000 (01:15 +0200)
arch/arm/configs/omap_h63xx_defconfig
arch/arm/mach-omap1/board-h6300.c
include/asm-arm/arch-omap/omap_serial.h
sound/arm/omap/omap-alsa-tsc2101-mixer.c
sound/arm/omap/omap-alsa-tsc2101-mixer.h
sound/arm/omap/omap-alsa-tsc2101.c
sound/arm/omap/omap-alsa.c
sound/oss/Kconfig
sound/oss/omap-audio-tsc2101.c

index 2bc595da2a8874f4aa224abaeca00da5e22fe85b..b3f0625a22255294def13c2ae4f781c3f0cdbedd 100644 (file)
@@ -1043,7 +1043,49 @@ CONFIG_LCD_DEVICE=y
 #
 # Sound
 #
-# CONFIG_SOUND is not set
+CONFIG_SOUND=m
+
+#
+# Advanced Linux Sound Architecture
+#
+CONFIG_SND=m
+CONFIG_SND_TIMER=m
+CONFIG_SND_PCM=m
+# CONFIG_SND_SEQUENCER is not set
+# CONFIG_SND_MIXER_OSS is not set
+# CONFIG_SND_PCM_OSS is not set
+# CONFIG_SND_DYNAMIC_MINORS is not set
+CONFIG_SND_SUPPORT_OLD_API=y
+# CONFIG_SND_VERBOSE_PRINTK is not set
+# CONFIG_SND_DEBUG is not set
+
+#
+# Generic devices
+#
+# CONFIG_SND_DUMMY is not set
+# CONFIG_SND_MTPAV is not set
+# CONFIG_SND_SERIAL_U16550 is not set
+# CONFIG_SND_MPU401 is not set
+
+#
+# ALSA ARM devices
+#
+# CONFIG_SND_OMAP_AIC23 is not set
+CONFIG_SND_OMAP_TSC2101=m
+
+#
+# USB devices
+#
+# CONFIG_SND_USB_AUDIO is not set
+
+#
+# PCMCIA devices
+#
+
+#
+# Open Sound System
+#
+# CONFIG_SOUND_PRIME is not set
 
 #
 # USB support
@@ -1074,6 +1116,7 @@ CONFIG_USB_OHCI_LITTLE_ENDIAN=y
 #
 # USB Device Class drivers
 #
+# CONFIG_OBSOLETE_OSS_USB_DRIVER is not set
 CONFIG_USB_ACM=y
 # CONFIG_USB_PRINTER is not set
 
index 09f14777f1f4d38db23467e58e23bc320a50ab03..888e654549dac68ebdcbb53260fae154eca568aa 100644 (file)
@@ -29,6 +29,8 @@
 #include <asm/arch/usb.h>
 #include <asm/arch/keypad.h>
 #include <asm/arch/common.h>
+#include <asm/arch/mcbsp.h>
+#include <asm/arch/omap-alsa.h>
 #include <asm/arch/h6300_uart_info.h>
 
 #define _h6300_KEY_CALENDAR    67      // xmodmap 75 aka F9
@@ -117,15 +119,48 @@ static struct platform_omap_serial_funcs h6300_omap_platform__uart_bt_funcs = {
        .get_txrx       = NULL,
 };
 
-struct platform_device btuart_device = {
+struct platform_device h63xx_uart_bt_device = {
        .name   = "h6300_bt",
        .id     = 1,
 };
-EXPORT_SYMBOL(btuart_device);
+EXPORT_SYMBOL(h63xx_uart_bt_device);
+
+static struct omap_mcbsp_reg_cfg mcbsp_regs = { 
+       .spcr2  = 0x0000,
+       .spcr1  = 0x0000,
+       .rcr2   = 0x8041,
+       .rcr1   = 0x0040,
+       .xcr2   = 0x00a1,
+       .xcr1   = 0x00a0,
+       .srgr2  = 0xb000,
+       .srgr1  = 0x0000,
+       .pcr0   = 0x0081,
+};
+
+static struct omap_alsa_codec_config alsa_config = {
+       .name                   = "iPAQ h6300 TSC2101",
+       .mcbsp_regs_alsa        = &mcbsp_regs,
+       .codec_configure_dev    = NULL, //tsc2101_configure,
+       .codec_set_samplerate   = NULL, //tsc2101_set_samplerate,
+       .codec_clock_setup      = NULL, //tsc2101_clock_setup,
+       .codec_clock_on         = NULL, //tsc2101_clock_on,
+       .codec_clock_off        = NULL, //tsc2101_clock_off,
+       .get_default_samplerate = NULL, //tsc2101_get_default_samplerate,
+};
+
+static struct platform_device h6300_mcbsp1_sound_device = {
+       .name   = "omap_alsa_mcbsp",
+       .id     = 1,
+       .dev = {
+               .platform_data  = &alsa_config,
+       },
+};
 
 static struct platform_device *h6300_devices[] __initdata = {
        &h6300_lcd_device,
        &h6300_kp_device,
+       &h63xx_uart_bt_device,
+       &h6300_mcbsp1_sound_device,
 };
 
 static struct omap_lcd_config h6300_lcd_config __initdata = {
index add09dc3580ff2c024f37fd3b20d9d387728cfb9..90e683434aa35432763640630eff5d27fd466a06 100644 (file)
@@ -54,9 +54,8 @@ struct platform_omap_serial_funcs {
 /*
  * The variables below are located in arch/arm/mach-omap/board_h6300.c
  * Machine-specific code may want to put a pointer to a static
- * platform_pxa_serial_funcs structure in the dev.platform_data
- * field of the respective port device.
+ * 63xx_uart_bt_device.dev.platform_data
  */
-extern struct platform_device btuart_device;
+extern struct platform_device h63xx_uart_bt_device;
 
 #endif
index 9dfaea8d7bda6c7ae3f7d4f7c68bb5163c0f9295..0f922661a98de82aaad8c58438ad5845bc76eab4 100644 (file)
 //#define M_DPRINTK(ARGS...)  printk(KERN_INFO "<%s>: ",__FUNCTION__);printk(ARGS)
 #define M_DPRINTK(ARGS...)             /* nop */
 
+#define CHECK_BIT(INDX, ARG) (((ARG) & TSC2101_BIT(INDX)) >> INDX)
+#define IS_UNMUTED(INDX, ARG) (((CHECK_BIT(INDX, ARG)) == 0))
+
 #define DGC_DALVL_EXTRACT(ARG) ((ARG & 0x7f00) >> 8)
 #define DGC_DARVL_EXTRACT(ARG) ((ARG & 0x007f))
-#define GET_DGC_DALMU_BIT_VALUE(ARG)  (((ARG) & TSC2101_BIT(15)) >> 15)
-#define GET_DGC_DARMU_BIT_VALUE(ARG)  (((ARG) & TSC2101_BIT(7)) >> 7)
-#define IS_DGC_DALMU_UNMUTED(ARG)  (((GET_DGC_DALMU_BIT_VALUE(ARG)) == 0))
-#define IS_DGC_DARMU_UNMUTED(ARG) (((GET_DGC_DARMU_BIT_VALUE(ARG)) == 0))
 
 #define HGC_ADPGA_HED_EXTRACT(ARG) ((ARG & 0x7f00) >> 8)
-#define GET_DGC_HGCMU_BIT_VALUE(ARG) (((ARG) & TSC2101_BIT(15)) >> 15)
-#define IS_DGC_HGCMU_UNMUTED(ARG) (((GET_DGC_HGCMU_BIT_VALUE(ARG)) == 0))
-
 #define HNGC_ADPGA_HND_EXTRACT(ARG) ((ARG & 0x7f00) >> 8)
-#define GET_DGC_HNGCMU_BIT_VALUE(ARG) (((ARG) & TSC2101_BIT(15)) >> 15)
-#define IS_DGC_HNGCMU_UNMUTED(ARG) (((GET_DGC_HNGCMU_BIT_VALUE(ARG)) == 0))
+#define BGC_ADPGA_BGC_EXTRACT(ARG) ((ARG & 0x7f00) >> 8)
 
 static int current_playback_target     = PLAYBACK_TARGET_LOUDSPEAKER;
 static int current_rec_src             = REC_SRC_SINGLE_ENDED_MICIN_HED;
 
+/* 
+ * Simplified write for the tsc2101 audio registers.
+ */
+inline void omap_tsc2101_audio_write(u8 address, u16 data)
+{
+       omap_tsc2101_write(PAGE2_AUDIO_CODEC_REGISTERS, address, data);
+}
+
+/* 
+ * Simplified read for the tsc2101 audio registers.
+ */
+inline u16 omap_tsc2101_audio_read(u8 address)
+{
+       return (omap_tsc2101_read(PAGE2_AUDIO_CODEC_REGISTERS, address));
+}
+
 /*
- * Used for switching between TSC2101 recourd sources.
- * Logic is adjusted from the TSC2101 OSS code.
+ * For selecting tsc2101 recourd source.
  */
-static int set_record_source(int val)
+static void set_record_source(int val)
 {
        u16     data;
-       int     maskedVal;
        
-       FN_IN;
-       maskedVal       = 0xe0 & val;   
-
-       data    = omap_tsc2101_read(TSC2101_AUDIO_CODEC_REGISTERS_PAGE2, 
-                               TSC2101_MIXER_PGA_CTRL);
+       /* Mute Analog Sidetone
+        * Analog sidetone gain db?
+        * Input selected by MICSEL connected to ADC
+        */
+       data    = MPC_ASTMU | MPC_ASTG(0x45);
        data    &= ~MPC_MICSEL(7); /* clear all MICSEL bits */
-       data    |= maskedVal;
-       omap_tsc2101_write(TSC2101_AUDIO_CODEC_REGISTERS_PAGE2,
-                               TSC2101_MIXER_PGA_CTRL,
-                               data);
+       data    |= MPC_MICSEL(val);
+       data    |= MPC_MICADC;
+       omap_tsc2101_audio_write(TSC2101_MIXER_PGA_CTRL, data);
+       
        current_rec_src = val;
-
-       FN_OUT(0);
-       return 0;
 }
 
 /*
@@ -147,32 +153,34 @@ int set_mixer_volume_as_dac_gain_control_volume(int mixerVolL, int mixerVolR)
        volL    = get_mixer_volume_as_dac_gain_control_volume(mixerVolL);
        volR    = get_mixer_volume_as_dac_gain_control_volume(mixerVolR);
        
-       val     = omap_tsc2101_read(TSC2101_AUDIO_CODEC_REGISTERS_PAGE2, TSC2101_DAC_GAIN_CTRL);
+       val     = omap_tsc2101_audio_read(TSC2101_DAC_GAIN_CTRL);
        /* keep the old mute bit settings */
        val     &= ~(DGC_DALVL(OUTPUT_VOLUME_MIN) | DGC_DARVL(OUTPUT_VOLUME_MIN));
        val     |= DGC_DALVL(volL) | DGC_DARVL(volR);
        retVal  = 2;
        if (retVal) {
-               omap_tsc2101_write(TSC2101_AUDIO_CODEC_REGISTERS_PAGE2, 
-                               TSC2101_DAC_GAIN_CTRL, 
-                               val);
+               omap_tsc2101_audio_write(TSC2101_DAC_GAIN_CTRL, val);
        }
        M_DPRINTK("to registry: left = %d, right = %d, total = %d\n", DGC_DALVL_EXTRACT(val), DGC_DARVL_EXTRACT(val), val);
        return retVal;
 }
 
-int dac_gain_control_unmute_control(int muteLeft, int muteRight)
+/**
+ * If unmuteLeft/unmuteRight == 0  --> mute
+ * If unmuteLeft/unmuteRight == 1 --> unmute
+ */
+int dac_gain_control_unmute(int unmuteLeft, int unmuteRight)
 {
        u16 val;
        int count;
 
        count   = 0;
-       val     = omap_tsc2101_read(TSC2101_AUDIO_CODEC_REGISTERS_PAGE2, TSC2101_DAC_GAIN_CTRL);
+       val     = omap_tsc2101_audio_read(TSC2101_DAC_GAIN_CTRL);
        /* in alsa mixer 1 --> on, 0 == off. In tsc2101 registry 1 --> off, 0 --> on
         * so if values are same, it's time to change the registry value.
         */
-       if (muteLeft == GET_DGC_DALMU_BIT_VALUE(val)) {
-               if (muteLeft == 0) {
+       if (unmuteLeft != IS_UNMUTED(15, val)) {
+               if (unmuteLeft == 0) {
                        /* mute --> turn bit on */
                        val     = val | DGC_DALMU;
                }
@@ -182,8 +190,8 @@ int dac_gain_control_unmute_control(int muteLeft, int muteRight)
                }
                count++;
        } /* L */
-       if (muteRight == GET_DGC_DARMU_BIT_VALUE(val)) {
-               if (muteRight == 0) {
+       if (unmuteRight != IS_UNMUTED(7, val)) {
+               if (unmuteRight == 0) {
                        /* mute --> turn bit on */
                        val     = val | DGC_DARMU;
                }
@@ -194,14 +202,47 @@ int dac_gain_control_unmute_control(int muteLeft, int muteRight)
                count++;
        } /* R */
        if (count) {
-               omap_tsc2101_write(TSC2101_AUDIO_CODEC_REGISTERS_PAGE2, TSC2101_DAC_GAIN_CTRL, val);
+               omap_tsc2101_audio_write(TSC2101_DAC_GAIN_CTRL, val);
                M_DPRINTK("changed value, is_unmuted left = %d, right = %d\n", 
-                       IS_DGC_DALMU_UNMUTED(val),
-                       IS_DGC_DARMU_UNMUTED(val));
+                       IS_UNMUTED(15, val),
+                       IS_UNMUTED(7, val));
        }
        return count;   
 }
 
+/**
+ * unmute: 0 --> mute, 1 --> unmute
+ * page2RegIndx: Registry index in tsc2101 page2.
+ * muteBitIndx: Index number for the bit in registry that indicates whether muted or unmuted.
+ */
+int adc_pga_unmute_control(int unmute, int page2regIndx, int muteBitIndx)
+{
+       int count;
+       u16 val;
+       
+       count   = 0;
+       val     = omap_tsc2101_audio_read(page2regIndx);
+       /* in alsa mixer 1 --> on, 0 == off. In tsc2101 registry 1 --> off, 0 --> on
+        * so if the values are same, it's time to change the registry value...
+        */
+       if (unmute != IS_UNMUTED(muteBitIndx, val)) {
+               if (unmute == 0) {
+                       /* mute --> turn bit on */
+                       val     = val | TSC2101_BIT(muteBitIndx);
+               }
+               else {
+                       /* unmute --> turn bit off */
+                       val     = val & ~TSC2101_BIT(muteBitIndx);
+               }
+               M_DPRINTK("changed value, is_unmuted = %d\n", IS_UNMUTED(muteBitIndx, val));
+               count++;
+       }
+       if (count) {
+               omap_tsc2101_audio_write(page2regIndx, val);
+       }
+       return count;
+}
+
 /*
  * Converts the DGC registry value read from the TSC2101 registry to 
  * Alsa mixer volume format (0 - 100).
@@ -271,14 +312,11 @@ int set_mixer_volume_as_headset_gain_control_volume(int mixerVol)
        /* Convert 0 -> 100 volume to 0x0(min) -> 0x7D(max) volume range */
        /* NOTE: 0 is minimum volume and not mute */
        volume  = get_mixer_volume_as_headset_gain_control_volume(mixerVol);    
-       val     = omap_tsc2101_read(TSC2101_AUDIO_CODEC_REGISTERS_PAGE2, 
-                               TSC2101_HEADSET_GAIN_CTRL);
+       val     = omap_tsc2101_audio_read(TSC2101_HEADSET_GAIN_CTRL);
        /* preserve the old mute settings */
        val     &= ~(HGC_ADPGA_HED(INPUT_VOLUME_MAX));
        val     |= HGC_ADPGA_HED(volume);
-       omap_tsc2101_write(TSC2101_AUDIO_CODEC_REGISTERS_PAGE2, 
-                       TSC2101_HEADSET_GAIN_CTRL,
-                       val);   
+       omap_tsc2101_audio_write(TSC2101_HEADSET_GAIN_CTRL, val);       
        retVal  = 1;
        
        M_DPRINTK("to registry = %d\n", val);   
@@ -305,71 +343,37 @@ int set_mixer_volume_as_handset_gain_control_volume(int mixerVol)
         * NOTE: 0 is minimum volume and not mute 
         */
        volume  = get_mixer_volume_as_headset_gain_control_volume(mixerVol);
-       val     = omap_tsc2101_read(TSC2101_AUDIO_CODEC_REGISTERS_PAGE2, TSC2101_HANDSET_GAIN_CTRL);
+       val     = omap_tsc2101_audio_read(TSC2101_HANDSET_GAIN_CTRL);
        /* preserve the old mute settigns */
        val     &= ~(HNGC_ADPGA_HND(INPUT_VOLUME_MAX));
        val     |= HNGC_ADPGA_HND(volume);
-       omap_tsc2101_write(TSC2101_AUDIO_CODEC_REGISTERS_PAGE2, 
-                       TSC2101_HANDSET_GAIN_CTRL,
-                       val);
+       omap_tsc2101_audio_write(TSC2101_HANDSET_GAIN_CTRL, val);
        retVal  = 1;
        
        M_DPRINTK("to registry = %d\n", val);   
        return retVal;
 }
 
-void init_record_sources(void)
-{
-       /* Mute Analog Sidetone
-        * analog sidetone gain db?
-        * Cell Phone In not connected to ADC
-        * Input selected by MICSEL connected to ADC
-        */
-       omap_tsc2101_write(TSC2101_AUDIO_CODEC_REGISTERS_PAGE2, 
-                         TSC2101_MIXER_PGA_CTRL,
-                         MPC_ASTMU | MPC_ASTG(0x40) | ~MPC_CPADC | MPC_MICADC);
-       /* Set record source, Select MIC_INHED input for headset */
-       set_record_source(REC_SRC_SINGLE_ENDED_MICIN_HED);      
-}
-
 void set_loudspeaker_to_playback_target(void)
 {
-       u16     val;
-
-       /* power down sp1, sp2 and loudspeaker */
-       omap_tsc2101_write(TSC2101_AUDIO_CODEC_REGISTERS_PAGE2,
-                       TSC2101_CODEC_POWER_CTRL,
+       /* power down SPK1, SPK2 and loudspeaker */
+       omap_tsc2101_audio_write(TSC2101_CODEC_POWER_CTRL,
                        CPC_SP1PWDN | CPC_SP2PWDN | CPC_LDAPWDF);       
        /* ADC, DAC, Analog Sidetone, cellphone, buzzer softstepping enabled
         * 1dB AGC hysteresis
         * MICes bias 2V
         */
-       omap_tsc2101_write(TSC2101_AUDIO_CODEC_REGISTERS_PAGE2, 
-                       TSC2101_AUDIO_CTRL_4, 
-                       AC4_MB_HED(0));
+       omap_tsc2101_audio_write(TSC2101_AUDIO_CTRL_4, AC4_MB_HED(0));
 
        /* DAC left and right routed to SPK1/SPK2
         * SPK1/SPK2 unmuted
-        * keyclicks routed to SPK1/SPK2
-        */
-       val     = AC5_DIFFIN |
+        * Keyclicks routed to SPK1/SPK2 */
+       omap_tsc2101_audio_write(TSC2101_AUDIO_CTRL_5, 
+                       AC5_DIFFIN |
                        AC5_DAC2SPK1(3) | AC5_AST2SPK1 | AC5_KCL2SPK1 |
-                       AC5_DAC2SPK2(3) | AC5_AST2SPK2 | AC5_KCL2SPK2 |
-                       AC5_HDSCPTC;
-       val     = val & ~AC5_HDSCPTC;
-       omap_tsc2101_write(TSC2101_AUDIO_CODEC_REGISTERS_PAGE2,
-                       TSC2101_AUDIO_CTRL_5,
-                       val);
+                       AC5_DAC2SPK2(3) | AC5_AST2SPK2 | AC5_KCL2SPK2);
        
-       /* powerdown spk1/out32n and spk2 */
-       val     = omap_tsc2101_read(TSC2101_AUDIO_CODEC_REGISTERS_PAGE2,
-                               TSC2101_POWERDOWN_STS);
-       val     = val & ~(~PS_SPK1FL | ~PS_HNDFL | PS_LSPKFL);
-       omap_tsc2101_write(TSC2101_AUDIO_CODEC_REGISTERS_PAGE2,
-                       TSC2101_POWERDOWN_STS,
-                       val);
-
-       /* routing selected to SPK1 goes to OUT8P/OUT84 alsa. (loudspeaker)
+       /* routing selected to SPK1 goes also to OUT8P/OUT8N. (loudspeaker)
         * analog sidetone routed to loudspeaker
         * buzzer pga routed to loudspeaker
         * keyclick routing to loudspeaker
@@ -381,43 +385,242 @@ void set_loudspeaker_to_playback_target(void)
         * Enable loudspeaker short protection control (0 = enable protection)
         * VGND short protection control (0 = enable protection)
         */
-       omap_tsc2101_write(TSC2101_AUDIO_CODEC_REGISTERS_PAGE2,
-                       TSC2101_AUDIO_CTRL_6,
+       omap_tsc2101_audio_write(TSC2101_AUDIO_CTRL_6,
                        AC6_SPL2LSK | AC6_AST2LSK | AC6_BUZ2LSK | AC6_KCL2LSK |
-                       AC6_CPI2LSK | AC6_MIC2CPO | AC6_SPL2CPO |
-                       ~AC6_MUTLSPK | ~AC6_MUTSPK2 | ~AC6_LDSCPTC | ~AC6_VGNDSCPTC);
+                       AC6_CPI2LSK | AC6_MIC2CPO | AC6_SPL2CPO);
        current_playback_target = PLAYBACK_TARGET_LOUDSPEAKER;
 }
 
 void set_headphone_to_playback_target(void)
 {
-       /* power down sp1, sp2 and loudspeaker */
-       omap_tsc2101_write(TSC2101_AUDIO_CODEC_REGISTERS_PAGE2,
-                       TSC2101_CODEC_POWER_CTRL,
+       /* power down SPK1, SPK2 and loudspeaker */
+       omap_tsc2101_audio_write(TSC2101_CODEC_POWER_CTRL,
                        CPC_SP1PWDN | CPC_SP2PWDN | CPC_LDAPWDF);
        /* ADC, DAC, Analog Sidetone, cellphone, buzzer softstepping enabled */
        /* 1dB AGC hysteresis */
        /* MICes bias 2V */
-       omap_tsc2101_write(TSC2101_AUDIO_CODEC_REGISTERS_PAGE2,
-                               TSC2101_AUDIO_CTRL_4, 
-                               AC4_MB_HED(0));
-
-       /* DAC left and right routed to SPK2 */
-       /* SPK1/2 unmuted */
-       omap_tsc2101_write(TSC2101_AUDIO_CODEC_REGISTERS_PAGE2,
-                       TSC2101_AUDIO_CTRL_5,
+       omap_tsc2101_audio_write(TSC2101_AUDIO_CTRL_4, AC4_MB_HED(0));
+                               
+       /* DAC left and right routed to SPK1/SPK2
+        * SPK1/SPK2 unmuted
+        * Keyclicks routed to SPK1/SPK2 */
+       omap_tsc2101_audio_write(TSC2101_AUDIO_CTRL_5,
                        AC5_DAC2SPK1(3) | AC5_AST2SPK1 | AC5_KCL2SPK1 |
                        AC5_DAC2SPK2(3) | AC5_AST2SPK2 | AC5_KCL2SPK2 |
                        AC5_HDSCPTC);
-
-       /* OUT8P/N muted, CPOUT muted */
-       omap_tsc2101_write(TSC2101_AUDIO_CODEC_REGISTERS_PAGE2,
-                       TSC2101_AUDIO_CTRL_6,
+                       
+       /* OUT8P/OUT8N muted, CPOUT muted */
+       omap_tsc2101_audio_write(TSC2101_AUDIO_CTRL_6,
                        AC6_MUTLSPK | AC6_MUTSPK2 | AC6_LDSCPTC |
                        AC6_VGNDSCPTC);
        current_playback_target = PLAYBACK_TARGET_HEADPHONE;
 }
 
+void set_telephone_to_playback_target(void)
+{
+       /* 
+        * 0110 1101 0101 1100
+        * power down MICBIAS_HED, Analog sidetone, SPK2, DAC, 
+        * Driver virtual ground, loudspeaker. Values D2-d5 are flags.
+        */      
+       omap_tsc2101_audio_write(TSC2101_CODEC_POWER_CTRL,
+                       CPC_MBIAS_HED | CPC_ASTPWD | CPC_SP2PWDN | CPC_DAPWDN |
+                       CPC_VGPWDN | CPC_LSPWDN);
+                       
+       /* 
+        * 0010 1010 0100 0000
+        * ADC, DAC, Analog Sidetone, cellphone, buzzer softstepping enabled
+        * 1dB AGC hysteresis
+        * MICes bias 2V
+        */
+       omap_tsc2101_audio_write(TSC2101_AUDIO_CTRL_4,
+                       AC4_MB_HND | AC4_MB_HED(0) | AC4_AGCHYS(1) | 
+                       AC4_BISTPD | AC4_ASSTPD | AC4_DASTPD);
+       printk("set_telephone_to_playback_target(), TSC2101_AUDIO_CTRL_4 = %d\n", omap_tsc2101_audio_read(TSC2101_AUDIO_CTRL_4));
+                       
+       /* 
+        * 1110 0010 0000 0010
+        * DAC left and right routed to SPK1/SPK2
+        * SPK1/SPK2 unmuted
+        * keyclicks routed to SPK1/SPK2
+        */      
+       omap_tsc2101_audio_write(TSC2101_AUDIO_CTRL_5,
+                       AC5_DIFFIN | AC5_DAC2SPK1(3) | 
+                       AC5_CPI2SPK1 | AC5_MUTSPK2);
+       
+       omap_tsc2101_audio_write(TSC2101_AUDIO_CTRL_6,
+                       AC6_MIC2CPO | AC6_MUTLSPK | 
+                       AC6_LDSCPTC | AC6_VGNDSCPTC | AC6_CAPINTF);
+       current_playback_target = PLAYBACK_TARGET_CELLPHONE;
+}
+
+/*
+ * 1100 0101 1101 0000
+ * 
+ * #define MPC_ASTMU           TSC2101_BIT(15)
+ * #define MPC_ASTG(ARG)       (((ARG) & 0x7F) << 8)
+ * #define MPC_MICSEL(ARG)     (((ARG) & 0x07) << 5)
+ * #define MPC_MICADC          TSC2101_BIT(4)
+ * #define MPC_CPADC           TSC2101_BIT(3)
+ * #define MPC_ASTGF           (0x01)
+ */
+static void set_telephone_to_record_source(void)
+{
+       u16     val;
+       
+       /* 
+        * D0       = 0: 
+        *              --> AGC is off for handset input.
+        *              --> ADC PGA is controlled by the ADMUT_HDN + ADPGA_HND
+        *          (D15, D14-D8)
+        * D4 - D1  = 0000 
+        *              --> AGC time constant for handset input, 
+        *              attack time = 8 mc, decay time = 100 ms
+        * D7 - D5  = 000
+        *              --> AGC Target gain for handset input = -5.5 db
+        * D14 - D8 = 011 1100
+        *              --> ADC handset PGA settings = 60 = 30 db
+        * D15          = 0
+        *              --> Handset input ON (unmuted)
+        */
+       val     = 0x3c00;       // 0011 1100 0000 0000 = 60 = 30
+       omap_tsc2101_audio_write(TSC2101_HANDSET_GAIN_CTRL, val);
+       
+       /*
+        * D0           = 0
+        *              --> AGC is off for headset/Aux input
+        *              --> ADC headset/Aux PGA is contoller by ADMUT_HED + ADPGA_HED
+        *          (D15, D14-D8)
+        * D4 - D1      = 0000 
+        *              --> Agc constant for headset/Aux input,
+        *              attack time = 8 mc, decay time = 100 ms      
+        * D7 - D5      = 000
+        *              --> AGC target gain for headset input = -5.5 db
+        * D14 - D8 = 000 0000
+        *              --> Adc headset/AUX pga settings = 0 db
+        * D15          = 1
+        *              --> Headset/AUX input muted
+        * 
+        * Mute headset aux input
+        */
+       val     = 0x8000;       // 1000 0000 0000 0000
+       omap_tsc2101_audio_write(TSC2101_HEADSET_GAIN_CTRL, val);
+       set_record_source(REC_SRC_MICIN_HND_AND_AUX1);
+
+       // hacks start
+       /* D0           = flag, Headset/Aux or handset PGA flag
+        *              --> & with 1 (= 1 -->gain applied == pga register settings)
+        * D1           = 0, DAC channel PGA soft stepping control
+        *              --> 0.5 db change every WCLK
+        * D2           = flag, DAC right channel PGA flag
+        *              --> & with 1
+        * D3           = flag, DAC left channel PGA flag
+        *              -- > & with 1
+        * D7 - D4      = 0001, keyclick length
+        *              --> 4 periods key clicks
+        * D10 - D8 = 100, keyclick frequenzy
+        *              --> 1 kHz, 
+        * D11          = 0, Headset/Aux or handset soft stepping control
+        *              --> 0,5 db change every WCLK or ADWS
+        * D14 -D12 = 100, Keyclick applitude control
+        *              --> Medium amplitude
+        * D15          = 0, keyclick disabled
+        */
+       val     = omap_tsc2101_audio_read(TSC2101_AUDIO_CTRL_2);
+       val     = val & 0x441d;
+       val     = val | 0x4410; // D14, D10, D4 bits == 1
+       omap_tsc2101_audio_write(TSC2101_AUDIO_CTRL_2, val);
+
+       /*
+        * D0           = 0     (reserved, write always 0)
+        * D1           = flag,
+        *                      --> & with 1
+        * D2 - D5      = 0000 (reserved, write always 0000)
+        * D6           = 1
+        *                      --> MICBIAS_HND = 2.0 v
+        * D8 - D7      = 00
+        *                      --> MICBIAS_HED = 3.3 v
+        * D10 - D9     = 01, 
+        *                      --> Mic AGC hysteric selection = 2 db
+        * D11          = 1, 
+        *                      --> Disable buzzer PGA soft stepping
+        * D12          = 0,
+        *                      --> Enable CELL phone PGA soft stepping control
+        * D13          = 1
+        *                      --> Disable analog sidetone soft stepping control
+        * D14          = 0
+        *                      --> Enable DAC PGA soft stepping control
+        * D15          = 0,
+        *                      --> Enable headset/Aux or Handset soft stepping control
+        */
+       val     = omap_tsc2101_audio_read(TSC2101_AUDIO_CTRL_4);
+       val     = val & 0x2a42; // 0010 1010 0100 0010
+       val     = val | 0x2a40; // bits D13, D11, D9, D6 == 1
+       omap_tsc2101_audio_write(TSC2101_AUDIO_CTRL_4, val);
+       printk("set_telephone_to_record_source(), TSC2101_AUDIO_CTRL_4 = %d\n", omap_tsc2101_audio_read(TSC2101_AUDIO_CTRL_4));
+       /*
+        * D0           = 0
+        *              --> reserved, write always = 0
+        * D1           = flag, read only
+        *              --> & with 1
+        * D5 - D2      = 1111, Buzzer input PGA settings
+        *              --> 0 db
+        * D6           = 1,
+        *              --> power down buzzer input pga
+        * D7           = flag, read only
+        *              --> & with 1
+        * D14 - D8     = 101 1101
+        *              --> 12 DB
+        * D15          = 0
+        *              --> power up cell phone input PGA
+        */
+       val     = omap_tsc2101_audio_read(TSC2101_BUZZER_GAIN_CTRL);
+       val     = val & 0x5dfe;
+       val     = val | 0x5dfe; // bits, D14, D12, D11, D10, D8, D6, D5,D4,D3,D2
+       omap_tsc2101_audio_write(TSC2101_BUZZER_GAIN_CTRL, val);
+       
+       /* D6 - D0      = 000 1001
+        *              --> -4.5 db for DAC right channel volume control
+        * D7           = 1
+        *              -->  DAC right channel muted
+        * D14 - D8 = 000 1001
+        *              --> -4.5 db for DAC left channel volume control
+        * D15          = 1
+        *              --> DAC left channel muted
+        */
+       //val   = omap_tsc2101_audio_read(TSC2101_DAC_GAIN_CTRL);
+       val     = 0x8989;
+       omap_tsc2101_audio_write(TSC2101_DAC_GAIN_CTRL, val);   
+       
+       /*  0000 0000 0100 0000
+        * 
+        * D1 - D0      = 0
+        *              --> GPIO 1 pin output is three stated
+        * D2           = 0
+        *              --> Disaple GPIO2 for CLKOUT mode
+        * D3           = 0
+        *              --> Disable GPUI1 for interrupt detection
+        * D4           = 0
+        *              --> Disable GPIO2 for headset detection interrupt
+        * D5           = reserved, always 0
+        * D7 - D6      = 01
+        *              --> 8 ms clitch detection
+        * D8           = reserved, write only 0
+        * D10 -D9      = 00
+        *              --> 16 ms de bouncing programmatitily 
+        *          for glitch detection during headset detection
+        * D11          = flag for button press
+        * D12          = flag for headset detection
+        * D14-D13      = 00
+        *              --> type of headset detected = 00 == no stereo headset deected
+        * D15          = 0
+        *              --> Disable headset detection
+        * 
+        * */
+       val     = 0x40;
+       omap_tsc2101_audio_write(TSC2101_AUDIO_CTRL_7, val);    
+}
+
 /*
  * Checks whether the headset is detected.
  * If headset is detected, the type is returned. Type can be
@@ -433,8 +636,7 @@ u16 get_headset_detected(void)
        u16     curVal;
        
        curType = 0;    /* not detected */
-       curVal  = omap_tsc2101_read(TSC2101_AUDIO_CODEC_REGISTERS_PAGE2, 
-                                       TSC2101_AUDIO_CTRL_7);
+       curVal  = omap_tsc2101_audio_read(TSC2101_AUDIO_CTRL_7);
        curDetected     = curVal & AC7_HDDETFL;
        if (curDetected) {
                printk("headset detected, checking type from %d \n", curVal);
@@ -461,13 +663,10 @@ void init_playback_targets(void)
         * AGC enable for handset input
         * Handset input not muted
         */
-       val     = omap_tsc2101_read(TSC2101_AUDIO_CODEC_REGISTERS_PAGE2, 
-                               TSC2101_HANDSET_GAIN_CTRL);
+       val     = omap_tsc2101_audio_read(TSC2101_HANDSET_GAIN_CTRL);
        val     = val | HNGC_AGCEN_HND; 
        val     = val & ~HNGC_ADMUT_HND;
-       omap_tsc2101_write(TSC2101_AUDIO_CODEC_REGISTERS_PAGE2, 
-                       TSC2101_HANDSET_GAIN_CTRL,
-                       val);   
+       omap_tsc2101_audio_write(TSC2101_HANDSET_GAIN_CTRL, val);       
                        
        /* mic input volume control
         * SET_MIC in the OSS driver 
@@ -479,7 +678,7 @@ void init_playback_targets(void)
         */
        set_mixer_volume_as_dac_gain_control_volume(DEFAULT_OUTPUT_VOLUME, DEFAULT_OUTPUT_VOLUME);      
        /* unmute */
-       dac_gain_control_unmute_control(1, 1);
+       dac_gain_control_unmute(1, 1);
 }
 
 /*
@@ -490,11 +689,11 @@ void snd_omap_init_mixer(void)
        FN_IN;
        
        /* Headset/Hook switch detect enabled */
-       omap_tsc2101_write(TSC2101_AUDIO_CODEC_REGISTERS_PAGE2,
-                       TSC2101_AUDIO_CTRL_7,
-                       AC7_DETECT);
+       omap_tsc2101_audio_write(TSC2101_AUDIO_CTRL_7, AC7_DETECT);
 
-       init_record_sources();
+       /* Select headset to record source (MIC_INHED)*/
+       set_record_source(REC_SRC_SINGLE_ENDED_MICIN_HED);
+       /* Init loudspeaker as a default playback target*/
        init_playback_targets();
 
        FN_OUT(0);
@@ -503,7 +702,7 @@ void snd_omap_init_mixer(void)
 static int __pcm_playback_target_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo) 
 {
        static char *texts[PLAYBACK_TARGET_COUNT] = {
-               "Loudspeaker", "Headphone"
+               "Loudspeaker", "Headphone", "Cellphone"
        };
 
        uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
@@ -533,12 +732,18 @@ static int __pcm_playback_target_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_valu
        if ((curVal >= 0) &&
            (curVal < PLAYBACK_TARGET_COUNT) &&
            (curVal != current_playback_target)) {              
-               if (curVal == 0) {
-                       set_loudspeaker_to_playback_target();           
+               if (curVal == PLAYBACK_TARGET_LOUDSPEAKER) {
+                       set_record_source(REC_SRC_SINGLE_ENDED_MICIN_HED);
+                       set_loudspeaker_to_playback_target();
                }
-               else {
+               else if (curVal == PLAYBACK_TARGET_HEADPHONE) {
+                       set_record_source(REC_SRC_SINGLE_ENDED_MICIN_HND);
                        set_headphone_to_playback_target();
                }
+               else if (curVal == PLAYBACK_TARGET_CELLPHONE) {
+                       set_telephone_to_record_source();
+                       set_telephone_to_playback_target();
+               }
                retVal  = 1;
        }
        return retVal;
@@ -563,7 +768,7 @@ static int __pcm_playback_volume_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_valu
        u16 volR;       
        u16 val;
        
-       val     = omap_tsc2101_read(TSC2101_AUDIO_CODEC_REGISTERS_PAGE2, TSC2101_DAC_GAIN_CTRL);
+       val     = omap_tsc2101_audio_read(TSC2101_DAC_GAIN_CTRL);
        M_DPRINTK("registry value = %d!\n", val);
        volL    = DGC_DALVL_EXTRACT(val);
        volR    = DGC_DARVL_EXTRACT(val);
@@ -603,16 +808,16 @@ static int __pcm_playback_switch_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_inf
  */
 static int __pcm_playback_switch_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) 
 {
-       u16 val = omap_tsc2101_read(TSC2101_AUDIO_CODEC_REGISTERS_PAGE2, TSC2101_DAC_GAIN_CTRL);
+       u16 val = omap_tsc2101_audio_read(TSC2101_DAC_GAIN_CTRL);
        
-       ucontrol->value.integer.value[0]        = IS_DGC_DALMU_UNMUTED(val);
-       ucontrol->value.integer.value[1]        = IS_DGC_DARMU_UNMUTED(val);
+       ucontrol->value.integer.value[0]        = IS_UNMUTED(15, val);  // left
+       ucontrol->value.integer.value[1]        = IS_UNMUTED(7, val);   // right
        return 0;
 }
 
 static int __pcm_playback_switch_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) 
 {
-       return dac_gain_control_unmute_control(ucontrol->value.integer.value[0], 
+       return dac_gain_control_unmute(ucontrol->value.integer.value[0], 
                                        ucontrol->value.integer.value[1]);
 }
 
@@ -630,8 +835,7 @@ static int __headset_playback_volume_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_
        u16 val;
        u16 vol;
        
-       val     = omap_tsc2101_read(TSC2101_AUDIO_CODEC_REGISTERS_PAGE2, 
-                               TSC2101_HEADSET_GAIN_CTRL);
+       val     = omap_tsc2101_audio_read(TSC2101_HEADSET_GAIN_CTRL);
        M_DPRINTK("registry value = %d\n", val);
        vol     = HGC_ADPGA_HED_EXTRACT(val);
        vol     = vol & ~HGC_ADMUT_HED;
@@ -662,38 +866,17 @@ static int __headset_playback_switch_info(snd_kcontrol_t *kcontrol, snd_ctl_elem
  */
 static int __headset_playback_switch_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) 
 {
-       u16 val = omap_tsc2101_read(TSC2101_AUDIO_CODEC_REGISTERS_PAGE2, 
-                               TSC2101_HEADSET_GAIN_CTRL);
-       ucontrol->value.integer.value[0]        = IS_DGC_HGCMU_UNMUTED(val);
+       u16 val = omap_tsc2101_audio_read(TSC2101_HEADSET_GAIN_CTRL);
+       ucontrol->value.integer.value[0]        = IS_UNMUTED(15, val);
        return 0;
 }
 
 static int __headset_playback_switch_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) 
 {
-       int count = 0;
-       u16 val = omap_tsc2101_read(TSC2101_AUDIO_CODEC_REGISTERS_PAGE2, 
-                               TSC2101_HEADSET_GAIN_CTRL);
-       /* in alsa mixer 1 --> on, 0 == off. In tsc2101 registry 1 --> off, 0 --> on
-        * so if values are same, it's time to change the registry value...
-        */
-       if (ucontrol->value.integer.value[0] == GET_DGC_HGCMU_BIT_VALUE(val)) {
-               if (ucontrol->value.integer.value[0] == 0) {
-                       /* mute --> turn bit on */
-                       val     = val | HGC_ADMUT_HED;
-               }
-               else {
-                       /* unmute --> turn bit off */
-                       val     = val & ~HGC_ADMUT_HED;
-               }
-               count++;
-               M_DPRINTK("changed value, is_unmuted = %d\n", IS_DGC_HGCMU_UNMUTED(val));
-       }
-       if (count) {
-               omap_tsc2101_write(TSC2101_AUDIO_CODEC_REGISTERS_PAGE2, 
-                               TSC2101_HEADSET_GAIN_CTRL, 
-                               val);
-       }
-       return count;
+       // mute/unmute headset
+       return adc_pga_unmute_control(ucontrol->value.integer.value[0],
+                               TSC2101_HEADSET_GAIN_CTRL,
+                               15);
 }
 
 static int __handset_playback_volume_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo) 
@@ -710,7 +893,7 @@ static int __handset_playback_volume_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_
        u16 val;
        u16 vol;
        
-       val     = omap_tsc2101_read(TSC2101_AUDIO_CODEC_REGISTERS_PAGE2, TSC2101_HANDSET_GAIN_CTRL);
+       val     = omap_tsc2101_audio_read(TSC2101_HANDSET_GAIN_CTRL);
        M_DPRINTK("registry value = %d\n", val);
        vol     = HNGC_ADPGA_HND_EXTRACT(val);
        vol     = vol & ~HNGC_ADMUT_HND;
@@ -740,42 +923,74 @@ static int __handset_playback_switch_info(snd_kcontrol_t *kcontrol, snd_ctl_elem
  */
 static int __handset_playback_switch_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) 
 {
-       u16 val = omap_tsc2101_read(TSC2101_AUDIO_CODEC_REGISTERS_PAGE2, TSC2101_HANDSET_GAIN_CTRL);
-       ucontrol->value.integer.value[0]        = IS_DGC_HNGCMU_UNMUTED(val);
+       u16 val = omap_tsc2101_audio_read(TSC2101_HANDSET_GAIN_CTRL);
+       ucontrol->value.integer.value[0]        = IS_UNMUTED(15, val);
        return 0;
 }
 
 static int __handset_playback_switch_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) 
 {
-       int count = 0;
-       u16 val = omap_tsc2101_read(TSC2101_AUDIO_CODEC_REGISTERS_PAGE2, TSC2101_HANDSET_GAIN_CTRL);
-       
-       /* in alsa mixer 1 --> on, 0 == off. In tsc2101 registry 1 --> off, 0 --> on
-        * so if values are same, it's time to change the registry value...
-        */
-       if (ucontrol->value.integer.value[0] == GET_DGC_HNGCMU_BIT_VALUE(val)) {
-               if (ucontrol->value.integer.value[0] == 0) {
-                       /* mute --> turn bit on */
-                       val     = val | HNGC_ADMUT_HND;
-               }
-               else {
-                       /* unmute --> turn bit off */
-                       val     = val & ~HNGC_ADMUT_HND;
-               }
-               M_DPRINTK("changed value, is_unmuted = %d\n", IS_DGC_HNGCMU_UNMUTED(val));
-               count++;
-       }
-       if (count) {
-               omap_tsc2101_write(TSC2101_AUDIO_CODEC_REGISTERS_PAGE2, 
-                               TSC2101_HANDSET_GAIN_CTRL, 
-                               val);
-       }
-       return count;
+       // handset mute/unmute
+       return adc_pga_unmute_control(ucontrol->value.integer.value[0],
+                               TSC2101_HANDSET_GAIN_CTRL,
+                               15);
+}
+
+static int __cellphone_input_switch_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo) 
+{
+       uinfo->type                     = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
+       uinfo->count                    = 1;
+       uinfo->value.integer.min        = 0;
+       uinfo->value.integer.max        = 1;
+       return 0;
+}
+
+/* When BGC_MUT_CP (bit 15) = 1, power down cellphone input pga.
+ * When BGC_MUT_CP = 0, power up cellphone input pga.
+ */
+static int __cellphone_input_switch_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) 
+{
+       u16 val = omap_tsc2101_audio_read(TSC2101_BUZZER_GAIN_CTRL);
+       ucontrol->value.integer.value[0]        = IS_UNMUTED(15, val);
+       return 0;
+}
+
+static int __cellphone_input_switch_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) 
+{
+       return adc_pga_unmute_control(ucontrol->value.integer.value[0],
+                               TSC2101_BUZZER_GAIN_CTRL,
+                               15);    
+}
+
+static int __buzzer_input_switch_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo) 
+{
+       uinfo->type                     = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
+       uinfo->count                    = 1;
+       uinfo->value.integer.min        = 0;
+       uinfo->value.integer.max        = 1;
+       return 0;
+}
+
+/* When BGC_MUT_BU (bit 6) = 1, power down cellphone input pga.
+ * When BGC_MUT_BU = 0, power up cellphone input pga.
+ */
+static int __buzzer_input_switch_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) 
+{
+       u16 val = omap_tsc2101_audio_read(TSC2101_BUZZER_GAIN_CTRL);
+       ucontrol->value.integer.value[0]        = IS_UNMUTED(6, val);
+       return 0;
+}
+
+static int __buzzer_input_switch_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) 
+{
+       return adc_pga_unmute_control(ucontrol->value.integer.value[0],
+                               TSC2101_BUZZER_GAIN_CTRL,
+                               6);     
 }
 
 static snd_kcontrol_new_t tsc2101_control[] __devinitdata = {
        {
-               .name  = "Playback Playback Route",
+               .name  = "Target Playback Route",
                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
                .index = 0,
                .access= SNDRV_CTL_ELEM_ACCESS_READWRITE,
@@ -801,7 +1016,7 @@ static snd_kcontrol_new_t tsc2101_control[] __devinitdata = {
        }, {
                .name  = "Headset Playback Volume",
                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-               .index = 1,
+               .index = 0,
                .access= SNDRV_CTL_ELEM_ACCESS_READWRITE,
                .info  = __headset_playback_volume_info,
                .get   = __headset_playback_volume_get,
@@ -809,7 +1024,7 @@ static snd_kcontrol_new_t tsc2101_control[] __devinitdata = {
        }, {
                .name  = "Headset Playback Switch",
                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-               .index = 1,
+               .index = 0,
                .access= SNDRV_CTL_ELEM_ACCESS_READWRITE,
                .info  = __headset_playback_switch_info,
                .get   = __headset_playback_switch_get,
@@ -817,7 +1032,7 @@ static snd_kcontrol_new_t tsc2101_control[] __devinitdata = {
        }, {
                .name  = "Handset Playback Volume",
                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-               .index = 2,
+               .index = 0,
                .access= SNDRV_CTL_ELEM_ACCESS_READWRITE,
                .info  = __handset_playback_volume_info,
                .get   = __handset_playback_volume_get,
@@ -825,12 +1040,28 @@ static snd_kcontrol_new_t tsc2101_control[] __devinitdata = {
        }, {
                .name  = "Handset Playback Switch",
                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-               .index = 2,
+               .index = 0,
                .access= SNDRV_CTL_ELEM_ACCESS_READWRITE,
                .info  = __handset_playback_switch_info,
                .get   = __handset_playback_switch_get,
                .put   = __handset_playback_switch_put,
-       }       
+       }, {
+               .name  = "Cellphone Input Switch",
+               .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+               .index = 0,
+               .access= SNDRV_CTL_ELEM_ACCESS_READWRITE,
+               .info  = __cellphone_input_switch_info,
+               .get   = __cellphone_input_switch_get,
+               .put   = __cellphone_input_switch_put,
+       }, {
+               .name  = "Buzzer Input Switch",
+               .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+               .index = 0,
+               .access= SNDRV_CTL_ELEM_ACCESS_READWRITE,
+               .info  = __buzzer_input_switch_info,
+               .get   = __buzzer_input_switch_get,
+               .put   = __buzzer_input_switch_put,
+       }
 };
 
 #ifdef CONFIG_PM
index f68f33dd8640358bc66369f33516bb170a8ebb41..3f27e27df6eb7488deff7494ff928088497f6eff 100644 (file)
 #define INPUT_VOLUME_MAX               0x7D
 #define INPUT_VOLUME_RANGE             (INPUT_VOLUME_MAX - INPUT_VOLUME_MIN)
 
-#define PLAYBACK_TARGET_COUNT          0x02
+#define PLAYBACK_TARGET_COUNT          0x03
 #define PLAYBACK_TARGET_LOUDSPEAKER    0x00
 #define PLAYBACK_TARGET_HEADPHONE      0x01
+#define PLAYBACK_TARGET_CELLPHONE      0x02
 
 /* following are used for register 03h Mixer PGA control bits D7-D5 for selecting record source */
 #define REC_SRC_TARGET_COUNT           0x08
-#define REC_SRC_SINGLE_ENDED_MICIN_HED MPC_MICSEL(0)   // oss code referred to MIXER_LINE
-#define REC_SRC_SINGLE_ENDED_MICIN_HND MPC_MICSEL(1)   // oss code referred to MIXER_MIC
-#define REC_SRC_SINGLE_ENDED_AUX1      MPC_MICSEL(2)
-#define REC_SRC_SINGLE_ENDED_AUX2      MPC_MICSEL(3)
-#define REC_SRC_MICIN_HED_AND_AUX1     MPC_MICSEL(4)
-#define REC_SRC_MICIN_HED_AND_AUX2     MPC_MICSEL(5)
-#define REC_SRC_MICIN_HND_AND_AUX1     MPC_MICSEL(6)
-#define REC_SRC_MICIN_HND_AND_AUX2     MPC_MICSEL(7)
+#define REC_SRC_SINGLE_ENDED_MICIN_HED 0x00    // oss code referred to MIXER_LINE
+#define REC_SRC_SINGLE_ENDED_MICIN_HND 0x01    // oss code referred to MIXER_MIC
+#define REC_SRC_SINGLE_ENDED_AUX1      0x02
+#define REC_SRC_SINGLE_ENDED_AUX2      0x03
+#define REC_SRC_MICIN_HED_AND_AUX1     0x04
+#define REC_SRC_MICIN_HED_AND_AUX2     0x05
+#define REC_SRC_MICIN_HND_AND_AUX1     0x06
+#define REC_SRC_MICIN_HND_AND_AUX2     0x07
 
 #define DEFAULT_OUTPUT_VOLUME          90      // default output volume to dac dgc
 #define DEFAULT_INPUT_VOLUME           20      // default record volume
index a0096cb62fce5c8beee1c63dd8baa2ba4039529a..14afcc6550f750958eaa4b110556a91918841423 100644 (file)
@@ -96,7 +96,11 @@ static const struct tsc2101_samplerate_reg_info
 static snd_pcm_hardware_t tsc2101_snd_omap_alsa_playback = {
        .info = (SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER |
                 SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID),      
-       .formats = (SNDRV_PCM_FMTBIT_S16_LE),
+#ifdef CONFIG_MACH_OMAP_H6300
+       .formats = (SNDRV_PCM_FMTBIT_S8),
+#else
+       .formats = (SNDRV_PCM_FMTBIT_S16_LE),
+#endif
        .rates = (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |
                  SNDRV_PCM_RATE_16000 |
                  SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_32000 |
@@ -136,7 +140,7 @@ static snd_pcm_hardware_t tsc2101_snd_omap_alsa_capture = {
 };
 
 /* 
- * Simplified write for tsc Audio
+ * Simplified write for tsc2101 audio registers.
  */
 inline void tsc2101_audio_write(u8 address, u16 data)
 {
@@ -144,7 +148,7 @@ inline void tsc2101_audio_write(u8 address, u16 data)
 }
 
 /* 
- * Simplified read for tsc  Audio
+ * Simplified read for tsc2101 audio registers.
  */
 inline u16 tsc2101_audio_read(u8 address)
 {
@@ -246,14 +250,17 @@ void tsc2101_set_samplerate(long sample_rate)
 #endif                         /* #ifdef TSC_MASTER */
        tsc2101_audio_write(TSC2101_AUDIO_CTRL_3, data);
 
-       /* program the PLLs */
+       /* Program the PLLs. This code assumes that the 12 Mhz MCLK is in use.
+         * If MCLK rate is something else, these values must be changed.
+        * See the tsc2101 specification for the details.
+        */
        if (rate_reg_info[count].fs_44kHz) {
-               /* 44.1 khz - 12 MHz Mclk */
+               /* samplerate = (44.1kHZ / x), where x is int. */
                tsc2101_audio_write(TSC2101_PLL_PROG_1, PLL1_PLLSEL |
                                PLL1_PVAL(1) | PLL1_I_VAL(7));  /* PVAL 1; I_VAL 7 */
                tsc2101_audio_write(TSC2101_PLL_PROG_2, PLL2_D_VAL(0x1490));    /* D_VAL 5264 */
        } else {
-               /* 48 khz - 12 Mhz Mclk */
+               /* samplerate = (48.kHZ / x), where x is int. */
                tsc2101_audio_write(TSC2101_PLL_PROG_1, PLL1_PLLSEL |
                               PLL1_PVAL(1) | PLL1_I_VAL(8));   /* PVAL 1; I_VAL 8 */
                tsc2101_audio_write(TSC2101_PLL_PROG_2, PLL2_D_VAL(0x780));     /* D_VAL 1920 */
@@ -317,21 +324,14 @@ int tsc2101_clock_on(void)
                       CODEC_CLOCK);
        }
        curRate = (uint)clk_get_rate(tsc2101_mclk);
-       DPRINTK("old clock rate = %d\n", curRate);
        if (curRate != CODEC_CLOCK) {
                err     = clk_set_rate(tsc2101_mclk, CODEC_CLOCK);
                if (err) {
                        printk(KERN_WARNING
                               "Cannot set MCLK clock rate for TSC2101 CODEC, error code = %d\n", err);
-                       //return -ECANCELED;
+                       return -ECANCELED;
                }
        }
-       else
-       {
-               printk(KERN_INFO
-                      "omap_alsa_tsc2101_clock_on(), no need to change rate, no need to change clock rate, rate already %d Hz.\n",
-                      CODEC_CLOCK);
-       }
        err             = clk_enable(tsc2101_mclk);
        curRate         = (uint)clk_get_rate(tsc2101_mclk);
        curUseCount     = clk_get_usecount(tsc2101_mclk);
@@ -349,8 +349,7 @@ int tsc2101_clock_on(void)
 }
 
 /*
- * Do some sanity check, turn clock off and then turn
- *  codec audio off
+ * Do some sanity check, turn clock off and then turn codec audio off
  */
 int tsc2101_clock_off(void) 
 {
@@ -374,10 +373,6 @@ int tsc2101_clock_off(void)
        tsc2101_audio_write(TSC2101_CODEC_POWER_CTRL,
                            ~(CPC_SP1PWDN | CPC_SP2PWDN | CPC_BASSBC));
        DPRINTK("audio codec off\n");
-#ifdef DUMP_TSC2101_AUDIO_REGISTERS
-       printk("tsc2101_clock_off()\n");
-       dump_tsc2101_audio_reg();
-#endif 
        return 0;       
 }
 
@@ -420,18 +415,22 @@ static struct platform_driver omap_alsa_driver = {
 };
 
 static int __init omap_alsa_tsc2101_init(void)
-{
-       int err;
-       
+{      
        ADEBUG();
-       err = platform_driver_register(&omap_alsa_driver);
-
-       return err;
+#ifdef DUMP_TSC2101_AUDIO_REGISTERS
+       printk("omap_alsa_tsc2101_init()\n");
+       dump_tsc2101_audio_reg();
+#endif
+       return platform_driver_register(&omap_alsa_driver);
 }
 
 static void __exit omap_alsa_tsc2101_exit(void)
 {
        ADEBUG();
+#ifdef DUMP_TSC2101_AUDIO_REGISTERS
+       printk("omap_alsa_tsc2101_exit()\n");
+       dump_tsc2101_audio_reg();
+#endif
        platform_driver_unregister(&omap_alsa_driver);
 }
 
index 328003be2bcaa86c2ede90af9f7d0dd123db83e8..5a68471efdda960ed57a0eb7703c6d0ee53deddd 100644 (file)
@@ -190,7 +190,7 @@ static void audio_process_dma(struct audio_stream *s)
        unsigned int dma_size;
        unsigned int offset;
        int ret;
-#ifdef CONFIG_MACH_OMAP_H6300
+#ifdef CONFIG_ARCH_OMAP15XX
        unsigned long flags;
 #endif
        
@@ -200,7 +200,13 @@ static void audio_process_dma(struct audio_stream *s)
                dma_size = frames_to_bytes(runtime, runtime->period_size);
                offset = dma_size * s->period;
                snd_assert(dma_size <= DMA_BUF_SIZE,);
-#ifdef CONFIG_MACH_OMAP_H6300
+#ifdef CONFIG_ARCH_OMAP15XX
+               /*
+                * On omap1510 based devices, we need to call the stop_dma
+                * before calling the start_dma or we will not receive the
+                * irq from DMA after the first transfered/played buffer.
+                * (invocation of callback_omap_alsa_sound_dma() method).
+                */
                spin_lock_irqsave(&s->dma_lock, flags);
                omap_stop_alsa_sound_dma(s);
                spin_unlock_irqrestore(&s->dma_lock, flags);
index 448f50f54e79ec2991e581bba08d427733b50de1..74cbb833a0c39cd4ca4cc63360780337ad068578 100644 (file)
@@ -13,8 +13,8 @@ config SOUND_OMAP
 
 config SOUND_OMAP_TSC2101
        tristate "TSC2101 Stereo Codec"
-       depends on SOUND_OMAP && ( MACH_OMAP_H2 || MACH_OMAP_H3 || MACH_OMAP_H4 || MACH_OMAP_APOLLON)
-       select OMAP_TSC2101 if ( MACH_OMAP_H2 || MACH_OMAP_H3 )
+       depends on SOUND_OMAP && ( MACH_OMAP_H2 || MACH_OMAP_H3 || MACH_OMAP_H4 || MACH_OMAP_APOLLON || MACH_OMAP_H6300)
+       select OMAP_TSC2101 if ( MACH_OMAP_H2 || MACH_OMAP_H3 || MACH_OMAP_H6300 )
        select OMAP_UWIRE if ARCH_OMAP1
        ---help---
          Tsc2101 Audio Codec Driver for OMAP will be enabled.
index f8e6dacf1ff79609cac92972ecc4aa28f0abe50d..55d131a832dd9c0f0de764b2b80dfa576db70429 100644 (file)
@@ -48,7 +48,7 @@
 #include "omap-audio.h"
 #include "omap-audio-dma-intfc.h"
 #include <asm/arch/mcbsp.h>
-#ifdef CONFIG_ARCH_OMAP16XX
+#if defined(CONFIG_ARCH_OMAP16XX) || defined(CONFIG_MACH_OMAP_H6300)
 #include <../drivers/ssi/omap-uwire.h>
 #include <asm/arch/dsp_common.h>
 #elif defined(CONFIG_ARCH_OMAP24XX)
 
 #ifdef CONFIG_ARCH_OMAP16XX
 #define PLATFORM_NAME "OMAP16XX"
+#elif CONFIG_MACH_OMAP_H6300
+#define PLATFORM_NAME "OMAP15XX"
 #elif defined(CONFIG_ARCH_OMAP24XX)
 #define PLATFORM_NAME "OMAP2"
 #endif
 
+#if CONFIG_ARCH_OMAP16XX
+#define OMAP_DSP_BASE        0xE0000000
+#endif
+
 /* Define to set the tsc as the master w.r.t McBSP */
 #define TSC_MASTER
 
 /*********** Debug Macros ********/
 /* To Generate a rather shrill tone -test the entire path */
 //#define TONE_GEN
-/* To Generate a tone for each keyclick - test the tsc,spi paths*/
+///* To Generate a tone for each keyclick - test the tsc,spi paths*/
 //#define TEST_KEYCLICK
 /* To dump the tsc registers for debug */
 //#define TSC_DUMP_REGISTERS
@@ -230,6 +236,17 @@ static const struct sample_rate_reg_info
 };
 
 static struct omap_mcbsp_reg_cfg initial_config = {
+#ifdef CONFIG_MACH_OMAP_H6300
+       .spcr2 = 0x0005,
+       .spcr1 = 0x0005,
+       .rcr2  = 0x8041,
+       .rcr1  = 0x8041,
+       .xcr2  = 0x00a1,
+       .xcr1  = 0x00a1,
+       .srgr2 = 0xb000,
+       .srgr1 = 0xb000,
+       .pcr0  = 0x0081,
+#else
        .spcr2 = FREE | FRST | GRST | XRST | XINTM(3),
        .spcr1 = RINTM(3) | RRST,
        .rcr2  = RPHASE | RFRLEN2(OMAP_MCBSP_WORD_8) |
@@ -253,6 +270,7 @@ static struct omap_mcbsp_reg_cfg initial_config = {
 #endif                         /* tsc Master defs */
 
 #endif                         /* platform specific inits */
+#endif /* CONFIG_MACH_OMAP_H6300 */
 };
 
 /***************************** MODULES SPECIFIC FUNCTION PROTOTYPES ********************/