phonepad: update codec rt5625 driver to support different hardware connect
author宋秀杰 <sxj@rock-chips.com>
Wed, 7 Mar 2012 14:40:12 +0000 (22:40 +0800)
committer宋秀杰 <sxj@rock-chips.com>
Wed, 7 Mar 2012 14:40:12 +0000 (22:40 +0800)
arch/arm/mach-rk29/board-rk29phonepadsdk.c
arch/arm/mach-rk29/include/mach/board.h
sound/soc/codecs/rt5625.c
sound/soc/rk29/Kconfig

index 128e483b3bc21dbeb5fcdb45ec313bfab569da3a..b6c7b3fdb11b5cfd8fa092de50df0e92a92d43bc 100755 (executable)
@@ -911,6 +911,20 @@ static struct wm8994_pdata wm8994_platform_data = {
 };
 #endif 
 
+#if defined (CONFIG_SND_SOC_RT5625_SPK_FORM_SPKOUT) || defined (CONFIG_SND_SOC_RT5625_SPK_FORM_HPOUT)
+
+//please define level value of power amp control
+#define POWER_AMP_ON 0
+#define POWER_AMP_OFF 1
+#define RT5625_POWER_AMP_PIN INVALID_GPIO  //RK29_PIN6_PB6
+
+struct rt5625_platform_data rt5625_platform_data = {
+       .spk_ctr_pin = RT5625_POWER_AMP_PIN,
+       .spk_ctr_on = POWER_AMP_ON,
+       .spk_ctr_off = POWER_AMP_OFF,
+};
+#endif
+
 #ifdef CONFIG_RK_HEADSET_DET
 
 struct rk_headset_pdata rk_headset_info = {
@@ -1104,11 +1118,14 @@ static struct i2c_board_info __initdata board_i2c0_devices[] = {
         },
 #endif
 
-#if defined (CONFIG_SND_SOC_RT5625)
+//note: rt5625 support two hardware connect, select the right config
+
+#if defined (CONFIG_SND_SOC_RT5625_SPK_FORM_SPKOUT) || defined (CONFIG_SND_SOC_RT5625_SPK_FORM_HPOUT)
        {
                .type                   = "rt5625",
                .addr                   = 0x1e,         //need check A1 pin,A1 pin is low,addr=0x1e,A1 pin is high,addr=0x1f.
                .flags                  = 0,
+               .platform_data  = &rt5625_platform_data,
        },
 #endif
 
index 8383843e7e76b6e1e5bfc5bf79482ff8b55949b1..e4fef3087ad1a8ac9459cc516e79e1538b7c76be 100755 (executable)
@@ -320,6 +320,12 @@ struct cs42l52_platform_data {
     void    (*exit_platform_hw)(void);
 };
 
+struct rt5625_platform_data {
+    int spk_ctr_pin;
+       int spk_ctr_on;
+       int spk_ctr_off;
+};
+
 //tcl miaozh add
 /*nas touch */
 struct nas_platform_data {
index c2704cbbc508a26c0f5844239ffd08b70fb79ab8..c79ca0fbd303d08bafd73aa2c4de65349c0befcd 100644 (file)
@@ -24,8 +24,9 @@
 #include <sound/soc-dapm.h>
 #include <sound/initval.h>
 #include <sound/tlv.h>
-
+#include <linux/gpio.h>
 #include "rt5625.h"
+#include <mach/board.h>
 
 #define RT5625_PROC
 #ifdef RT5625_PROC
@@ -63,6 +64,10 @@ struct rt5625_priv {
        unsigned int voice_sysclk;
 
        int vodsp_fun;
+       int spk_ctr_status;
+       int spk_ctr_pin;
+       int spk_ctr_on;
+       int spk_ctr_off;
 #ifdef RT5625_F_SMT_PHO
        int app_bmp;/* bit{0, 1, 2, 3, 4} = {play, rec, 3g, bt, voip} */
        int pll_sel;
@@ -544,6 +549,8 @@ err:
        return ret;
 }
 
+static const char *rt5625_spk_ctr_sel[] = {"Disable", "Enable"};
+
 /* ADCR function select */
 static const char *adcr_fun_sel[] = {
        "Stereo ADC", "Voice ADC", "VoDSP", "PDM Slave"};
@@ -600,6 +607,10 @@ static const char *rt5625_spkamp_ratio[] = {"2.25 Vdd", "2.00 Vdd",
 static const SOC_ENUM_SINGLE_DECL(rt5625_spkamp_ratio_enum,
        RT5625_GEN_CTRL1, RT5625_SPK_R_SFT, rt5625_spkamp_ratio);
 
+static const char *rt5625_Pin_mode[] = {"IRQ Out", "GPIO enable", "Reserved", "VoDSP bypass"};  
+static const char *rt5625_Pin_configuration[] = {"Output", "Input"};
+static const char *rt5625_Pin_level[] = {"Low", "High"};
+
 /* Output/Input Mode */
 //static const char *rt5625_auxout_mode[] = {"Differential", "Single ended"};
 
@@ -617,6 +628,12 @@ static const SOC_ENUM_SINGLE_DECL(rt5625_spkamp_ratio_enum,
 //static const SOC_ENUM_SINGLE_DECL(rt5625_mic2_mode_enum,
 //     RT5625_MIC_VOL, RT5625_MIC2_DIFF_SFT, rt5625_input_mode);
 
+static const struct soc_enum rt5625_gpio2_enum[] = {
+SOC_ENUM_SINGLE(RT5625_GPIO_SHARING, 0, 4, rt5625_Pin_mode),         /*0*/
+SOC_ENUM_SINGLE(RT5625_GPIO_CONFIG, 2, 2, rt5625_Pin_configuration),/*1*/
+SOC_ENUM_SINGLE(RT5625_GPIO_OUT_CTRL, 2, 2, rt5625_Pin_level),        /*2*/
+};
+
 static int rt5625_adcr_fun_sel_put(struct snd_kcontrol *kcontrol,
        struct snd_ctl_elem_value *ucontrol)
 {
@@ -1435,11 +1452,63 @@ static int rt5625_regctl_put(struct snd_kcontrol *kcontrol,
 }
 #endif
 
+/*speaker ext control*/
+static const struct soc_enum spk_ctr_enum =
+       SOC_ENUM_SINGLE(0, 0, ARRAY_SIZE(rt5625_spk_ctr_sel), rt5625_spk_ctr_sel);
+
+static int rt5625_spk_ctr_get(struct snd_kcontrol *kcontrol,
+               struct snd_ctl_elem_value *ucontrol)
+{
+       struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+       struct rt5625_priv *rt5625 = snd_soc_codec_get_drvdata(codec);
+
+       ucontrol->value.integer.value[0] = rt5625->spk_ctr_status;
+       return 0;
+}
+
+static int rt5625_spk_ctr_put(struct snd_kcontrol *kcontrol,
+               struct snd_ctl_elem_value *ucontrol)
+{
+       struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+       struct rt5625_priv *rt5625 = snd_soc_codec_get_drvdata(codec);
+
+       rt5625->spk_ctr_status = ucontrol->value.integer.value[0];
+
+       if(rt5625->spk_ctr_pin != INVALID_GPIO)
+       {
+               if(rt5625->spk_ctr_status)
+                       gpio_set_value(rt5625->spk_ctr_pin,rt5625->spk_ctr_on);
+               else
+                       gpio_set_value(rt5625->spk_ctr_pin,rt5625->spk_ctr_off);
+       }
+       return 0;
+}
+
 static const struct snd_kcontrol_new rt5625_snd_controls[] = {
+
+       #if defined (CONFIG_SND_SOC_RT5625_SPK_FORM_SPKOUT)
        SOC_DOUBLE_TLV("SPKOUT Playback Volume", RT5625_SPK_OUT_VOL,
                RT5625_L_VOL_SFT, RT5625_R_VOL_SFT, 31, 1, out_vol_tlv),
        SOC_DOUBLE("SPKOUT Playback Switch", RT5625_SPK_OUT_VOL,
-                       RT5625_L_MUTE_SFT, RT5625_R_MUTE_SFT, 1, 1),
+               RT5625_L_MUTE_SFT, RT5625_R_MUTE_SFT, 1, 1),
+       SOC_DOUBLE_TLV("Earpiece Playback Volume", RT5625_SPK_OUT_VOL,
+               RT5625_L_VOL_SFT, RT5625_R_VOL_SFT, 31, 1, out_vol_tlv),
+       SOC_DOUBLE("Earpiece Playback Switch", RT5625_SPK_OUT_VOL,
+               RT5625_L_MUTE_SFT, RT5625_R_MUTE_SFT, 1, 1),
+       #endif
+
+       #if defined (CONFIG_SND_SOC_RT5625_SPK_FORM_HPOUT)
+       SOC_DOUBLE_TLV("SPKOUT Playback Volume", RT5625_HP_OUT_VOL,
+               RT5625_L_VOL_SFT, RT5625_R_VOL_SFT, 31, 1, out_vol_tlv),
+       SOC_DOUBLE("SPKOUT Playback Switch", RT5625_HP_OUT_VOL,
+               RT5625_L_MUTE_SFT, RT5625_R_MUTE_SFT, 1, 1),
+       SOC_DOUBLE_TLV("Earpiece Playback Volume", RT5625_HP_OUT_VOL,
+               RT5625_L_VOL_SFT, RT5625_R_VOL_SFT, 31, 1, out_vol_tlv),
+       SOC_DOUBLE("Earpiece Playback Switch", RT5625_HP_OUT_VOL,
+               RT5625_L_MUTE_SFT, RT5625_R_MUTE_SFT, 1, 1),
+       SOC_ENUM_EXT("SPK_CTR",spk_ctr_enum, rt5625_spk_ctr_get, rt5625_spk_ctr_put),
+       #endif
+
        SOC_ENUM("SPK Amp Type", rt5625_spk_out_enum),
        SOC_ENUM("Left SPK Source", rt5625_spkl_src_enum),
        SOC_ENUM("SPK Amp Ratio", rt5625_spkamp_ratio_enum),
@@ -1490,6 +1559,10 @@ static const struct snd_kcontrol_new rt5625_snd_controls[] = {
        SOC_ENUM("VoDSP Reset Pin Control",  rt5625_rst_ctrl_enum),
 
 #ifdef RT5625_F_SMT_PHO
+       SOC_ENUM("GPIO2 mode", rt5625_gpio2_enum[0]),
+       SOC_ENUM("GPIO2 configuration", rt5625_gpio2_enum[1]),
+       SOC_ENUM("GPIO2 level", rt5625_gpio2_enum[2]),
+
        SOC_SINGLE_EXT("VoDSP Dump", 0, 0, 1, 0, rt5625_dump_dsp_get, NULL),
        SOC_SINGLE_EXT("DAC Switch", 0, 0, 1, 0, rt5625_dac_active_get, rt5625_dac_active_put),
        SOC_SINGLE_EXT("ADC Switch", 0, 0, 1, 0, rt5625_adc_active_get, rt5625_adc_active_put),
@@ -2868,11 +2941,23 @@ static int rt5625_i2c_probe(struct i2c_client *i2c,
 {
        struct rt5625_priv *rt5625;
        int ret;
+       struct rt5625_platform_data *pdata = pdata = i2c->dev.platform_data;
 
        rt5625 = kzalloc(sizeof(struct rt5625_priv), GFP_KERNEL);
        if (NULL == rt5625)
                return -ENOMEM;
 
+       rt5625->spk_ctr_pin = pdata->spk_ctr_pin;
+       rt5625->spk_ctr_on = pdata->spk_ctr_on;
+       rt5625->spk_ctr_off = pdata->spk_ctr_off;
+
+       if(rt5625->spk_ctr_pin != INVALID_GPIO)
+       {
+               gpio_request(rt5625->spk_ctr_pin,NULL);
+               gpio_direction_output(rt5625->spk_ctr_pin,rt5625->spk_ctr_off);
+               rt5625->spk_ctr_status = 0;
+       }
+
        i2c_set_clientdata(i2c, rt5625);
 
        ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_rt5625,
index 16a990c0174bc54bfc5c9e0efe0ee60de92dd715..395dac05a32cf4d5262758266dff536ebfdaec51 100755 (executable)
@@ -73,11 +73,27 @@ config SND_RK29_SOC_RT5625
        tristate "SoC I2S Audio support for rockchip - RT5625"
        depends on SND_RK29_SOC && I2C_RK29
        select SND_RK29_SOC_I2S
-       select SND_SOC_RT5625
        help
          Say Y if you want to add support for SoC audio on rockchip
          with the RT5625.
 
+choice
+       depends on SND_RK29_SOC_RT5625
+       prompt  "RT5625 hardware select"
+
+       config SND_SOC_RT5625_SPK_FORM_SPKOUT
+       bool "spk from spkout"
+       select SND_SOC_RT5625
+       help
+         if your codec output hardware connect is spk from spkout, choose it
+
+       config SND_SOC_RT5625_SPK_FORM_HPOUT
+       bool "spk from hpout"
+       select SND_SOC_RT5625
+       help
+         if your codec output hardware connect is spk from spkout, choose it
+endchoice
+
 config SND_RK29_SOC_WM8994
        tristate "SoC I2S Audio support for rockchip - WM8994"
        depends on SND_RK29_SOC && I2C_RK29