Merge remote-tracking branch 'asoc/topic/rt5645' into asoc-next
authorMark Brown <broonie@kernel.org>
Mon, 26 Oct 2015 02:15:58 +0000 (11:15 +0900)
committerMark Brown <broonie@kernel.org>
Mon, 26 Oct 2015 02:15:58 +0000 (11:15 +0900)
1  2 
sound/soc/codecs/rt5645.c
sound/soc/codecs/rt5645.h

index 080cc1ce3963c834a82e3ba5f73e2ffd9b8af6dc,f046bb83fd9711332880ee93ab3a985476e42e12..28132375e4274a6e94e830c2fe1e8fcddd255747
@@@ -42,6 -42,8 +42,8 @@@
  
  #define RT5645_PR_BASE (RT5645_PR_RANGE_BASE + (0 * RT5645_PR_SPACING))
  
+ #define RT5645_HWEQ_NUM 57
  static const struct regmap_range_cfg rt5645_ranges[] = {
        {
                .name = "PR",
@@@ -224,6 -226,11 +226,11 @@@ static const struct reg_default rt5645_
        { 0xff, 0x6308 },
  };
  
+ struct rt5645_eq_param_s {
+       unsigned short reg;
+       unsigned short val;
+ };
  static const char *const rt5645_supply_names[] = {
        "avdd",
        "cpvdd",
@@@ -240,6 -247,7 +247,7 @@@ struct rt5645_priv 
        struct snd_soc_jack *btn_jack;
        struct delayed_work jack_detect_work;
        struct regulator_bulk_data supplies[ARRAY_SIZE(rt5645_supply_names)];
+       struct rt5645_eq_param_s *eq_param;
  
        int codec_type;
        int sysclk;
@@@ -469,6 -477,94 +477,94 @@@ static const DECLARE_TLV_DB_RANGE(bst_t
        8, 8, TLV_DB_SCALE_ITEM(5200, 0, 0)
  );
  
+ /* {-6, -4.5, -3, -1.5, 0, 0.82, 1.58, 2.28} dB */
+ static const DECLARE_TLV_DB_RANGE(spk_clsd_tlv,
+       0, 4, TLV_DB_SCALE_ITEM(-600, 150, 0),
+       5, 5, TLV_DB_SCALE_ITEM(82, 0, 0),
+       6, 6, TLV_DB_SCALE_ITEM(158, 0, 0),
+       7, 7, TLV_DB_SCALE_ITEM(228, 0, 0)
+ );
+ static int rt5645_hweq_info(struct snd_kcontrol *kcontrol,
+                        struct snd_ctl_elem_info *uinfo)
+ {
+       uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES;
+       uinfo->count = RT5645_HWEQ_NUM * sizeof(struct rt5645_eq_param_s);
+       return 0;
+ }
+ static int rt5645_hweq_get(struct snd_kcontrol *kcontrol,
+                       struct snd_ctl_elem_value *ucontrol)
+ {
+       struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
+       struct rt5645_priv *rt5645 = snd_soc_component_get_drvdata(component);
+       struct rt5645_eq_param_s *eq_param =
+               (struct rt5645_eq_param_s *)ucontrol->value.bytes.data;
+       int i;
+       for (i = 0; i < RT5645_HWEQ_NUM; i++) {
+               eq_param[i].reg = cpu_to_be16(rt5645->eq_param[i].reg);
+               eq_param[i].val = cpu_to_be16(rt5645->eq_param[i].val);
+       }
+       return 0;
+ }
+ static bool rt5645_validate_hweq(unsigned short reg)
+ {
+       if ((reg >= 0x1a4 && reg <= 0x1cd) | (reg >= 0x1e5 && reg <= 0x1f8) |
+               (reg == RT5645_EQ_CTRL2))
+               return true;
+       return false;
+ }
+ static int rt5645_hweq_put(struct snd_kcontrol *kcontrol,
+                       struct snd_ctl_elem_value *ucontrol)
+ {
+       struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
+       struct rt5645_priv *rt5645 = snd_soc_component_get_drvdata(component);
+       struct rt5645_eq_param_s *eq_param =
+               (struct rt5645_eq_param_s *)ucontrol->value.bytes.data;
+       int i;
+       for (i = 0; i < RT5645_HWEQ_NUM; i++) {
+               eq_param[i].reg = be16_to_cpu(eq_param[i].reg);
+               eq_param[i].val = be16_to_cpu(eq_param[i].val);
+       }
+       /* The final setting of the table should be RT5645_EQ_CTRL2 */
+       for (i = RT5645_HWEQ_NUM - 1; i >= 0; i--) {
+               if (eq_param[i].reg == 0)
+                       continue;
+               else if (eq_param[i].reg != RT5645_EQ_CTRL2)
+                       return 0;
+               else
+                       break;
+       }
+       for (i = 0; i < RT5645_HWEQ_NUM; i++) {
+               if (!rt5645_validate_hweq(eq_param[i].reg) &&
+                       eq_param[i].reg != 0)
+                       return 0;
+               else if (eq_param[i].reg == 0)
+                       break;
+       }
+       memcpy(rt5645->eq_param, eq_param,
+               RT5645_HWEQ_NUM * sizeof(struct rt5645_eq_param_s));
+       return 0;
+ }
+ #define RT5645_HWEQ(xname) \
+ {     .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
+       .info = rt5645_hweq_info, \
+       .get = rt5645_hweq_get, \
+       .put = rt5645_hweq_put \
+ }
  static const struct snd_kcontrol_new rt5645_snd_controls[] = {
        /* Speaker Output Volume */
        SOC_DOUBLE("Speaker Channel Switch", RT5645_SPK_VOL,
        SOC_DOUBLE_TLV("Speaker Playback Volume", RT5645_SPK_VOL,
                RT5645_L_VOL_SFT, RT5645_R_VOL_SFT, 39, 1, out_vol_tlv),
  
+       /* ClassD modulator Speaker Gain Ratio */
+       SOC_SINGLE_TLV("Speaker ClassD Playback Volume", RT5645_SPO_CLSD_RATIO,
+               RT5645_SPK_G_CLSD_SFT, 7, 0, spk_clsd_tlv),
        /* Headphone Output Volume */
        SOC_DOUBLE("Headphone Channel Switch", RT5645_HP_VOL,
                RT5645_VOL_L_SFT, RT5645_VOL_R_SFT, 1, 1),
                RT5645_L_VOL_SFT + 1, RT5645_R_VOL_SFT + 1, 63, 0, adc_vol_tlv),
  
        /* ADC Boost Volume Control */
 -      SOC_DOUBLE_TLV("STO1 ADC Boost Gain", RT5645_ADC_BST_VOL1,
 +      SOC_DOUBLE_TLV("ADC Boost Capture Volume", RT5645_ADC_BST_VOL1,
                RT5645_STO1_ADC_L_BST_SFT, RT5645_STO1_ADC_R_BST_SFT, 3, 0,
                adc_bst_tlv),
 -      SOC_DOUBLE_TLV("STO2 ADC Boost Gain", RT5645_ADC_BST_VOL1,
 -              RT5645_STO2_ADC_L_BST_SFT, RT5645_STO2_ADC_R_BST_SFT, 3, 0,
 +      SOC_DOUBLE_TLV("Mono ADC Boost Capture Volume", RT5645_ADC_BST_VOL2,
 +              RT5645_MONO_ADC_L_BST_SFT, RT5645_MONO_ADC_R_BST_SFT, 3, 0,
                adc_bst_tlv),
  
        /* I2S2 function select */
        SOC_SINGLE("I2S2 Func Switch", RT5645_GPIO_CTRL1, RT5645_I2S2_SEL_SFT,
                1, 1),
+       RT5645_HWEQ("Speaker HWEQ"),
  };
  
  /**
@@@ -619,6 -720,22 +720,22 @@@ static int is_using_asrc(struct snd_soc
  
  }
  
+ static int rt5645_enable_hweq(struct snd_soc_codec *codec)
+ {
+       struct rt5645_priv *rt5645 = snd_soc_codec_get_drvdata(codec);
+       int i;
+       for (i = 0; i < RT5645_HWEQ_NUM; i++) {
+               if (rt5645_validate_hweq(rt5645->eq_param[i].reg))
+                       regmap_write(rt5645->regmap, rt5645->eq_param[i].reg,
+                                       rt5645->eq_param[i].val);
+               else
+                       break;
+       }
+       return 0;
+ }
  /**
   * rt5645_sel_asrc_clk_src - select ASRC clock source for a set of filters
   * @codec: SoC audio codec device.
@@@ -732,14 -849,14 +849,14 @@@ static const struct snd_kcontrol_new rt
  static const struct snd_kcontrol_new rt5645_dac_l_mix[] = {
        SOC_DAPM_SINGLE("Stereo ADC Switch", RT5645_AD_DA_MIXER,
                        RT5645_M_ADCMIX_L_SFT, 1, 1),
 -      SOC_DAPM_SINGLE("DAC1 Switch", RT5645_AD_DA_MIXER,
 +      SOC_DAPM_SINGLE_AUTODISABLE("DAC1 Switch", RT5645_AD_DA_MIXER,
                        RT5645_M_DAC1_L_SFT, 1, 1),
  };
  
  static const struct snd_kcontrol_new rt5645_dac_r_mix[] = {
        SOC_DAPM_SINGLE("Stereo ADC Switch", RT5645_AD_DA_MIXER,
                        RT5645_M_ADCMIX_R_SFT, 1, 1),
 -      SOC_DAPM_SINGLE("DAC1 Switch", RT5645_AD_DA_MIXER,
 +      SOC_DAPM_SINGLE_AUTODISABLE("DAC1 Switch", RT5645_AD_DA_MIXER,
                        RT5645_M_DAC1_R_SFT, 1, 1),
  };
  
@@@ -1381,7 -1498,7 +1498,7 @@@ static void hp_amp_power(struct snd_soc
                                regmap_write(rt5645->regmap, RT5645_PR_BASE +
                                        RT5645_MAMP_INT_REG2, 0xfc00);
                                snd_soc_write(codec, RT5645_DEPOP_M2, 0x1140);
 -                              mdelay(5);
 +                              msleep(40);
                                rt5645->hp_on = true;
                        } else {
                                /* depop parameters */
@@@ -1523,6 -1640,7 +1640,7 @@@ static int rt5645_spk_event(struct snd_
  
        switch (event) {
        case SND_SOC_DAPM_POST_PMU:
+               rt5645_enable_hweq(codec);
                snd_soc_update_bits(codec, RT5645_PWR_DIG1,
                        RT5645_PWR_CLS_D | RT5645_PWR_CLS_D_R |
                        RT5645_PWR_CLS_D_L,
                break;
  
        case SND_SOC_DAPM_PRE_PMD:
+               snd_soc_write(codec, RT5645_EQ_CTRL2, 0);
                snd_soc_update_bits(codec, RT5645_PWR_DIG1,
                        RT5645_PWR_CLS_D | RT5645_PWR_CLS_D_R |
                        RT5645_PWR_CLS_D_L, 0);
@@@ -2733,6 -2852,10 +2852,10 @@@ static int rt5645_set_bias_level(struc
                snd_soc_update_bits(codec, RT5645_PWR_ANLG1,
                        RT5645_PWR_FV1 | RT5645_PWR_FV2,
                        RT5645_PWR_FV1 | RT5645_PWR_FV2);
+               if (rt5645->en_button_func &&
+                       snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_OFF)
+                       queue_delayed_work(system_power_efficient_wq,
+                               &rt5645->jack_detect_work, msecs_to_jiffies(0));
                break;
  
        case SND_SOC_BIAS_OFF:
@@@ -2835,9 -2958,6 +2958,9 @@@ static int rt5645_jack_detect(struct sn
        } else { /* jack out */
                rt5645->jack_type = 0;
  
 +              regmap_update_bits(rt5645->regmap, RT5645_HP_VOL,
 +                      RT5645_L_MUTE | RT5645_R_MUTE,
 +                      RT5645_L_MUTE | RT5645_R_MUTE);
                regmap_update_bits(rt5645->regmap, RT5645_IN1_CTRL2,
                        RT5645_CBJ_MN_JD, RT5645_CBJ_MN_JD);
                regmap_update_bits(rt5645->regmap, RT5645_IN1_CTRL1,
@@@ -3044,6 -3164,9 +3167,9 @@@ static int rt5645_probe(struct snd_soc_
                snd_soc_dapm_sync(dapm);
        }
  
+       rt5645->eq_param = devm_kzalloc(codec->dev,
+               RT5645_HWEQ_NUM * sizeof(struct rt5645_eq_param_s), GFP_KERNEL);
        return 0;
  }
  
@@@ -3104,7 -3227,7 +3230,7 @@@ static struct snd_soc_dai_driver rt5645
                .capture = {
                        .stream_name = "AIF1 Capture",
                        .channels_min = 1,
-                       .channels_max = 2,
+                       .channels_max = 4,
                        .rates = RT5645_STEREO_RATES,
                        .formats = RT5645_FORMATS,
                },
@@@ -3215,6 -3338,13 +3341,13 @@@ static const struct dmi_system_id dmi_p
                        DMI_MATCH(DMI_PRODUCT_NAME, "Ultima"),
                },
        },
+       {
+               .ident = "Google Reks",
+               .callback = strago_quirk_cb,
+               .matches = {
+                       DMI_MATCH(DMI_PRODUCT_NAME, "Reks"),
+               },
+       },
        { }
  };
  
@@@ -3232,7 -3362,7 +3365,7 @@@ static int buddy_quirk_cb(const struct 
        return 1;
  }
  
- static struct dmi_system_id dmi_platform_intel_broadwell[] __initdata = {
+ static struct dmi_system_id dmi_platform_intel_broadwell[] = {
        {
                .ident = "Chrome Buddy",
                .callback = buddy_quirk_cb,
@@@ -3505,6 -3635,8 +3638,8 @@@ static void rt5645_i2c_shutdown(struct 
                RT5645_CBJ_MN_JD);
        regmap_update_bits(rt5645->regmap, RT5645_IN1_CTRL1, RT5645_CBJ_BST1_EN,
                0);
+       msleep(20);
+       regmap_write(rt5645->regmap, RT5645_RESET, 0);
  }
  
  static struct i2c_driver rt5645_i2c_driver = {
index 61bc8ab776468e8857664ef7ea32646b30c089a7,7cea2826279d7d20cb5f6f4dbb8d6a42abfd1502..093e46d559fbab24aa05efc5c74a2e8488fa49d0
@@@ -39,8 -39,8 +39,8 @@@
  #define RT5645_STO1_ADC_DIG_VOL                       0x1c
  #define RT5645_MONO_ADC_DIG_VOL                       0x1d
  #define RT5645_ADC_BST_VOL1                   0x1e
 -/* Mixer - D-D */
  #define RT5645_ADC_BST_VOL2                   0x20
 +/* Mixer - D-D */
  #define RT5645_STO1_ADC_MIXER                 0x27
  #define RT5645_MONO_ADC_MIXER                 0x28
  #define RT5645_AD_DA_MIXER                    0x29
  #define RT5645_STO1_ADC_R_BST_SFT             12
  #define RT5645_STO1_ADC_COMP_MASK             (0x3 << 10)
  #define RT5645_STO1_ADC_COMP_SFT              10
 -#define RT5645_STO2_ADC_L_BST_MASK            (0x3 << 8)
 -#define RT5645_STO2_ADC_L_BST_SFT             8
 -#define RT5645_STO2_ADC_R_BST_MASK            (0x3 << 6)
 -#define RT5645_STO2_ADC_R_BST_SFT             6
 -#define RT5645_STO2_ADC_COMP_MASK             (0x3 << 4)
 -#define RT5645_STO2_ADC_COMP_SFT              4
 +
 +/* ADC Boost Volume Control (0x20) */
 +#define RT5645_MONO_ADC_L_BST_MASK            (0x3 << 14)
 +#define RT5645_MONO_ADC_L_BST_SFT             14
 +#define RT5645_MONO_ADC_R_BST_MASK            (0x3 << 12)
 +#define RT5645_MONO_ADC_R_BST_SFT             12
 +#define RT5645_MONO_ADC_COMP_MASK             (0x3 << 10)
 +#define RT5645_MONO_ADC_COMP_SFT              10
  
  /* Stereo2 ADC Mixer Control (0x26) */
  #define RT5645_STO2_ADC_SRC_MASK              (0x1 << 15)
  #define RT5645_G_OM_L_SM_L_SFT                        6
  #define RT5645_M_BST1_L_SM_L                  (0x1 << 5)
  #define RT5645_M_BST1_L_SM_L_SFT              5
+ #define RT5645_M_BST3_L_SM_L                  (0x1 << 4)
+ #define RT5645_M_BST3_L_SM_L_SFT              4
  #define RT5645_M_IN_L_SM_L                    (0x1 << 3)
  #define RT5645_M_IN_L_SM_L_SFT                        3
- #define RT5645_M_DAC_L1_SM_L                  (0x1 << 1)
- #define RT5645_M_DAC_L1_SM_L_SFT              1
  #define RT5645_M_DAC_L2_SM_L                  (0x1 << 2)
  #define RT5645_M_DAC_L2_SM_L_SFT              2
- #define RT5645_M_BST3_L_SM_L                  (0x1 << 4)
- #define RT5645_M_BST3_L_SM_L_SFT              4
+ #define RT5645_M_DAC_L1_SM_L                  (0x1 << 1)
+ #define RT5645_M_DAC_L1_SM_L_SFT              1
  
  /* SPK Right Mixer Control (0x47) */
  #define RT5645_G_RM_R_SM_R_MASK                       (0x3 << 14)
  #define RT5645_G_OM_R_SM_R_SFT                        6
  #define RT5645_M_BST2_R_SM_R                  (0x1 << 5)
  #define RT5645_M_BST2_R_SM_R_SFT              5
+ #define RT5645_M_BST3_R_SM_R                  (0x1 << 4)
+ #define RT5645_M_BST3_R_SM_R_SFT              4
  #define RT5645_M_IN_R_SM_R                    (0x1 << 3)
  #define RT5645_M_IN_R_SM_R_SFT                        3
- #define RT5645_M_DAC_R1_SM_R                  (0x1 << 1)
- #define RT5645_M_DAC_R1_SM_R_SFT              1
  #define RT5645_M_DAC_R2_SM_R                  (0x1 << 2)
  #define RT5645_M_DAC_R2_SM_R_SFT              2
- #define RT5645_M_BST3_R_SM_R                  (0x1 << 4)
- #define RT5645_M_BST3_R_SM_R_SFT              4
+ #define RT5645_M_DAC_R1_SM_R                  (0x1 << 1)
+ #define RT5645_M_DAC_R1_SM_R_SFT              1
  
  /* SPOLMIX Control (0x48) */
  #define RT5645_M_DAC_L1_SPM_L                 (0x1 << 15)
  #define RT5645_M_SV_R_SPM_R                   (0x1 << 0)
  #define RT5645_M_SV_R_SPM_R_SFT                       0
  
+ /* SPOMIX Ratio Control (0x4a) */
+ #define RT5645_SPK_G_CLSD_MASK                        (0x7 << 0)
+ #define RT5645_SPK_G_CLSD_SFT                 0
  /* Mono Output Mixer Control (0x4c) */
+ #define RT5645_G_MONOMIX_MASK                 (0x1 << 10)
+ #define RT5645_G_MONOMIX_SFT                  10
  #define RT5645_M_OV_L_MM                      (0x1 << 9)
  #define RT5645_M_OV_L_MM_SFT                  9
  #define RT5645_M_DAC_L2_MA                    (0x1 << 8)
  #define RT5645_M_DAC_L2_MA_SFT                        8
- #define RT5645_G_MONOMIX_MASK                 (0x1 << 10)
- #define RT5645_G_MONOMIX_SFT                  10
  #define RT5645_M_BST2_MM                      (0x1 << 4)
  #define RT5645_M_BST2_MM_SFT                  4
  #define RT5645_M_DAC_R1_MM                    (0x1 << 3)