Merge remote-tracking branch 'asoc/fix/rt5645' into asoc-linus
authorMark Brown <broonie@kernel.org>
Wed, 10 Feb 2016 19:23:03 +0000 (19:23 +0000)
committerMark Brown <broonie@kernel.org>
Wed, 10 Feb 2016 19:23:03 +0000 (19:23 +0000)
1  2 
sound/soc/codecs/rt5645.c

@@@ -64,6 -64,7 +64,6 @@@ static const struct reg_sequence init_l
        {RT5645_PR_BASE + 0x21, 0x4040},
        {RT5645_PR_BASE + 0x23, 0x0004},
  };
 -#define RT5645_INIT_REG_LEN ARRAY_SIZE(init_list)
  
  static const struct reg_sequence rt5650_init_list[] = {
        {0xf6,  0x0100},
@@@ -225,163 -226,6 +225,163 @@@ static const struct reg_default rt5645_
        { 0xff, 0x6308 },
  };
  
 +static const struct reg_default rt5650_reg[] = {
 +      { 0x00, 0x0000 },
 +      { 0x01, 0xc8c8 },
 +      { 0x02, 0xc8c8 },
 +      { 0x03, 0xc8c8 },
 +      { 0x0a, 0x0002 },
 +      { 0x0b, 0x2827 },
 +      { 0x0c, 0xe000 },
 +      { 0x0d, 0x0000 },
 +      { 0x0e, 0x0000 },
 +      { 0x0f, 0x0808 },
 +      { 0x14, 0x3333 },
 +      { 0x16, 0x4b00 },
 +      { 0x18, 0x018b },
 +      { 0x19, 0xafaf },
 +      { 0x1a, 0xafaf },
 +      { 0x1b, 0x0001 },
 +      { 0x1c, 0x2f2f },
 +      { 0x1d, 0x2f2f },
 +      { 0x1e, 0x0000 },
 +      { 0x20, 0x0000 },
 +      { 0x27, 0x7060 },
 +      { 0x28, 0x7070 },
 +      { 0x29, 0x8080 },
 +      { 0x2a, 0x5656 },
 +      { 0x2b, 0x5454 },
 +      { 0x2c, 0xaaa0 },
 +      { 0x2d, 0x0000 },
 +      { 0x2f, 0x1002 },
 +      { 0x31, 0x5000 },
 +      { 0x32, 0x0000 },
 +      { 0x33, 0x0000 },
 +      { 0x34, 0x0000 },
 +      { 0x35, 0x0000 },
 +      { 0x3b, 0x0000 },
 +      { 0x3c, 0x007f },
 +      { 0x3d, 0x0000 },
 +      { 0x3e, 0x007f },
 +      { 0x3f, 0x0000 },
 +      { 0x40, 0x001f },
 +      { 0x41, 0x0000 },
 +      { 0x42, 0x001f },
 +      { 0x45, 0x6000 },
 +      { 0x46, 0x003e },
 +      { 0x47, 0x003e },
 +      { 0x48, 0xf807 },
 +      { 0x4a, 0x0004 },
 +      { 0x4d, 0x0000 },
 +      { 0x4e, 0x0000 },
 +      { 0x4f, 0x01ff },
 +      { 0x50, 0x0000 },
 +      { 0x51, 0x0000 },
 +      { 0x52, 0x01ff },
 +      { 0x53, 0xf000 },
 +      { 0x56, 0x0111 },
 +      { 0x57, 0x0064 },
 +      { 0x58, 0xef0e },
 +      { 0x59, 0xf0f0 },
 +      { 0x5a, 0xef0e },
 +      { 0x5b, 0xf0f0 },
 +      { 0x5c, 0xef0e },
 +      { 0x5d, 0xf0f0 },
 +      { 0x5e, 0xf000 },
 +      { 0x5f, 0x0000 },
 +      { 0x61, 0x0300 },
 +      { 0x62, 0x0000 },
 +      { 0x63, 0x00c2 },
 +      { 0x64, 0x0000 },
 +      { 0x65, 0x0000 },
 +      { 0x66, 0x0000 },
 +      { 0x6a, 0x0000 },
 +      { 0x6c, 0x0aaa },
 +      { 0x70, 0x8000 },
 +      { 0x71, 0x8000 },
 +      { 0x72, 0x8000 },
 +      { 0x73, 0x7770 },
 +      { 0x74, 0x3e00 },
 +      { 0x75, 0x2409 },
 +      { 0x76, 0x000a },
 +      { 0x77, 0x0c00 },
 +      { 0x78, 0x0000 },
 +      { 0x79, 0x0123 },
 +      { 0x7a, 0x0123 },
 +      { 0x80, 0x0000 },
 +      { 0x81, 0x0000 },
 +      { 0x82, 0x0000 },
 +      { 0x83, 0x0000 },
 +      { 0x84, 0x0000 },
 +      { 0x85, 0x0000 },
 +      { 0x8a, 0x0000 },
 +      { 0x8e, 0x0004 },
 +      { 0x8f, 0x1100 },
 +      { 0x90, 0x0646 },
 +      { 0x91, 0x0c06 },
 +      { 0x93, 0x0000 },
 +      { 0x94, 0x0200 },
 +      { 0x95, 0x0000 },
 +      { 0x9a, 0x2184 },
 +      { 0x9b, 0x010a },
 +      { 0x9c, 0x0aea },
 +      { 0x9d, 0x000c },
 +      { 0x9e, 0x0400 },
 +      { 0xa0, 0xa0a8 },
 +      { 0xa1, 0x0059 },
 +      { 0xa2, 0x0001 },
 +      { 0xae, 0x6000 },
 +      { 0xaf, 0x0000 },
 +      { 0xb0, 0x6000 },
 +      { 0xb1, 0x0000 },
 +      { 0xb2, 0x0000 },
 +      { 0xb3, 0x001f },
 +      { 0xb4, 0x020c },
 +      { 0xb5, 0x1f00 },
 +      { 0xb6, 0x0000 },
 +      { 0xbb, 0x0000 },
 +      { 0xbc, 0x0000 },
 +      { 0xbd, 0x0000 },
 +      { 0xbe, 0x0000 },
 +      { 0xbf, 0x3100 },
 +      { 0xc0, 0x0000 },
 +      { 0xc1, 0x0000 },
 +      { 0xc2, 0x0000 },
 +      { 0xc3, 0x2000 },
 +      { 0xcd, 0x0000 },
 +      { 0xce, 0x0000 },
 +      { 0xcf, 0x1813 },
 +      { 0xd0, 0x0690 },
 +      { 0xd1, 0x1c17 },
 +      { 0xd3, 0xb320 },
 +      { 0xd4, 0x0000 },
 +      { 0xd6, 0x0400 },
 +      { 0xd9, 0x0809 },
 +      { 0xda, 0x0000 },
 +      { 0xdb, 0x0003 },
 +      { 0xdc, 0x0049 },
 +      { 0xdd, 0x001b },
 +      { 0xdf, 0x0008 },
 +      { 0xe0, 0x4000 },
 +      { 0xe6, 0x8000 },
 +      { 0xe7, 0x0200 },
 +      { 0xec, 0xb300 },
 +      { 0xed, 0x0000 },
 +      { 0xf0, 0x001f },
 +      { 0xf1, 0x020c },
 +      { 0xf2, 0x1f00 },
 +      { 0xf3, 0x0000 },
 +      { 0xf4, 0x4000 },
 +      { 0xf8, 0x0000 },
 +      { 0xf9, 0x0000 },
 +      { 0xfa, 0x2060 },
 +      { 0xfb, 0x4040 },
 +      { 0xfc, 0x0000 },
 +      { 0xfd, 0x0002 },
 +      { 0xfe, 0x10ec },
 +      { 0xff, 0x6308 },
 +};
 +
  struct rt5645_eq_param_s {
        unsigned short reg;
        unsigned short val;
@@@ -401,10 -245,9 +401,10 @@@ struct rt5645_priv 
        struct snd_soc_jack *hp_jack;
        struct snd_soc_jack *mic_jack;
        struct snd_soc_jack *btn_jack;
 -      struct delayed_work jack_detect_work;
 +      struct delayed_work jack_detect_work, rcclock_work;
        struct regulator_bulk_data supplies[ARRAY_SIZE(rt5645_supply_names)];
        struct rt5645_eq_param_s *eq_param;
 +      struct timer_list btn_check_timer;
  
        int codec_type;
        int sysclk;
@@@ -722,31 -565,12 +722,31 @@@ static int rt5645_hweq_put(struct snd_k
        .put = rt5645_hweq_put \
  }
  
 +static int rt5645_spk_put_volsw(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);
 +      int ret;
 +
 +      regmap_update_bits(rt5645->regmap, RT5645_MICBIAS,
 +              RT5645_PWR_CLK25M_MASK, RT5645_PWR_CLK25M_PU);
 +
 +      ret = snd_soc_put_volsw(kcontrol, ucontrol);
 +
 +      mod_delayed_work(system_power_efficient_wq, &rt5645->rcclock_work,
 +              msecs_to_jiffies(200));
 +
 +      return ret;
 +}
 +
  static const struct snd_kcontrol_new rt5645_snd_controls[] = {
        /* Speaker Output Volume */
        SOC_DOUBLE("Speaker Channel Switch", RT5645_SPK_VOL,
                RT5645_VOL_L_SFT, RT5645_VOL_R_SFT, 1, 1),
 -      SOC_DOUBLE_TLV("Speaker Playback Volume", RT5645_SPK_VOL,
 -              RT5645_L_VOL_SFT, RT5645_R_VOL_SFT, 39, 1, out_vol_tlv),
 +      SOC_DOUBLE_EXT_TLV("Speaker Playback Volume", RT5645_SPK_VOL,
 +              RT5645_L_VOL_SFT, RT5645_R_VOL_SFT, 39, 1, snd_soc_get_volsw,
 +              rt5645_spk_put_volsw, out_vol_tlv),
  
        /* ClassD modulator Speaker Gain Ratio */
        SOC_SINGLE_TLV("Speaker ClassD Playback Volume", RT5645_SPO_CLSD_RATIO,
  
        /* IN1/IN2 Control */
        SOC_SINGLE_TLV("IN1 Boost", RT5645_IN1_CTRL1,
-               RT5645_BST_SFT1, 8, 0, bst_tlv),
+               RT5645_BST_SFT1, 12, 0, bst_tlv),
        SOC_SINGLE_TLV("IN2 Boost", RT5645_IN2_CTRL,
                RT5645_BST_SFT2, 8, 0, bst_tlv),
  
@@@ -1674,7 -1498,7 +1674,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);
 -                              msleep(40);
 +                              msleep(70);
                                rt5645->hp_on = true;
                        } else {
                                /* depop parameters */
@@@ -1822,13 -1646,9 +1822,13 @@@ static int rt5645_spk_event(struct snd_
                        RT5645_PWR_CLS_D_L,
                        RT5645_PWR_CLS_D | RT5645_PWR_CLS_D_R |
                        RT5645_PWR_CLS_D_L);
 +              snd_soc_update_bits(codec, RT5645_GEN_CTRL3,
 +                      RT5645_DET_CLK_MASK, RT5645_DET_CLK_MODE1);
                break;
  
        case SND_SOC_DAPM_PRE_PMD:
 +              snd_soc_update_bits(codec, RT5645_GEN_CTRL3,
 +                      RT5645_DET_CLK_MASK, RT5645_DET_CLK_DIS);
                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 |
@@@ -3066,7 -2886,6 +3066,7 @@@ static void rt5645_enable_push_button_i
                snd_soc_dapm_force_enable_pin(dapm, "ADC R power");
                snd_soc_dapm_sync(dapm);
  
 +              snd_soc_update_bits(codec, RT5650_4BTN_IL_CMD1, 0x3, 0x3);
                snd_soc_update_bits(codec,
                                        RT5645_INT_IRQ_ST, 0x8, 0x8);
                snd_soc_update_bits(codec,
@@@ -3135,7 -2954,7 +3135,7 @@@ static int rt5645_jack_detect(struct sn
                }
                if (rt5645->pdata.jd_invert)
                        regmap_update_bits(rt5645->regmap, RT5645_IRQ_CTRL2,
 -                              RT5645_JD_1_1_MASK, RT5645_JD_1_1_INV);
 +                              RT5645_JD_1_1_MASK, RT5645_JD_1_1_NOR);
        } else { /* jack out */
                rt5645->jack_type = 0;
  
                snd_soc_dapm_sync(dapm);
                if (rt5645->pdata.jd_invert)
                        regmap_update_bits(rt5645->regmap, RT5645_IRQ_CTRL2,
 -                              RT5645_JD_1_1_MASK, RT5645_JD_1_1_NOR);
 +                              RT5645_JD_1_1_MASK, RT5645_JD_1_1_INV);
        }
  
        return rt5645->jack_type;
@@@ -3280,12 -3099,6 +3280,12 @@@ static void rt5645_jack_detect_work(str
                }
                if (btn_type == 0)/* button release */
                        report =  rt5645->jack_type;
 +              else {
 +                      if (rt5645->pdata.jd_invert) {
 +                              mod_timer(&rt5645->btn_check_timer,
 +                                      msecs_to_jiffies(100));
 +                      }
 +              }
  
                break;
        /* jack out */
                                SND_JACK_BTN_2 | SND_JACK_BTN_3);
  }
  
 +static void rt5645_rcclock_work(struct work_struct *work)
 +{
 +      struct rt5645_priv *rt5645 =
 +              container_of(work, struct rt5645_priv, rcclock_work.work);
 +
 +      regmap_update_bits(rt5645->regmap, RT5645_MICBIAS,
 +              RT5645_PWR_CLK25M_MASK, RT5645_PWR_CLK25M_PD);
 +}
 +
  static irqreturn_t rt5645_irq(int irq, void *data)
  {
        struct rt5645_priv *rt5645 = data;
        return IRQ_HANDLED;
  }
  
 +static void rt5645_btn_check_callback(unsigned long data)
 +{
 +      struct rt5645_priv *rt5645 = (struct rt5645_priv *)data;
 +
 +      queue_delayed_work(system_power_efficient_wq,
 +                 &rt5645->jack_detect_work, msecs_to_jiffies(5));
 +}
 +
  static int rt5645_probe(struct snd_soc_codec *codec)
  {
        struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec);
@@@ -3492,31 -3288,6 +3492,31 @@@ static const struct regmap_config rt564
        .num_ranges = ARRAY_SIZE(rt5645_ranges),
  };
  
 +static const struct regmap_config rt5650_regmap = {
 +      .reg_bits = 8,
 +      .val_bits = 16,
 +      .use_single_rw = true,
 +      .max_register = RT5645_VENDOR_ID2 + 1 + (ARRAY_SIZE(rt5645_ranges) *
 +                                             RT5645_PR_SPACING),
 +      .volatile_reg = rt5645_volatile_register,
 +      .readable_reg = rt5645_readable_register,
 +
 +      .cache_type = REGCACHE_RBTREE,
 +      .reg_defaults = rt5650_reg,
 +      .num_reg_defaults = ARRAY_SIZE(rt5650_reg),
 +      .ranges = rt5645_ranges,
 +      .num_ranges = ARRAY_SIZE(rt5645_ranges),
 +};
 +
 +static const struct regmap_config temp_regmap = {
 +      .name="nocache",
 +      .reg_bits = 8,
 +      .val_bits = 16,
 +      .use_single_rw = true,
 +      .max_register = RT5645_VENDOR_ID2 + 1,
 +      .cache_type = REGCACHE_NONE,
 +};
 +
  static const struct i2c_device_id rt5645_i2c_id[] = {
        { "rt5645", 0 },
        { "rt5650", 0 },
  MODULE_DEVICE_TABLE(i2c, rt5645_i2c_id);
  
  #ifdef CONFIG_ACPI
 -static struct acpi_device_id rt5645_acpi_match[] = {
 +static const struct acpi_device_id rt5645_acpi_match[] = {
        { "10EC5645", 0 },
        { "10EC5650", 0 },
        {},
  MODULE_DEVICE_TABLE(acpi, rt5645_acpi_match);
  #endif
  
 -static struct rt5645_platform_data *rt5645_pdata;
 -
 -static struct rt5645_platform_data strago_platform_data = {
 +static struct rt5645_platform_data general_platform_data = {
        .dmic1_data_pin = RT5645_DMIC1_DISABLE,
        .dmic2_data_pin = RT5645_DMIC_DATA_IN2P,
        .jd_mode = 3,
  };
  
 -static int strago_quirk_cb(const struct dmi_system_id *id)
 -{
 -      rt5645_pdata = &strago_platform_data;
 -
 -      return 1;
 -}
 -
  static const struct dmi_system_id dmi_platform_intel_braswell[] = {
        {
                .ident = "Intel Strago",
 -              .callback = strago_quirk_cb,
                .matches = {
                        DMI_MATCH(DMI_PRODUCT_NAME, "Strago"),
                },
        },
        {
 -              .ident = "Google Celes",
 -              .callback = strago_quirk_cb,
 +              .ident = "Google Chrome",
                .matches = {
 -                      DMI_MATCH(DMI_PRODUCT_NAME, "Celes"),
 -              },
 -      },
 -      {
 -              .ident = "Google Ultima",
 -              .callback = strago_quirk_cb,
 -              .matches = {
 -                      DMI_MATCH(DMI_PRODUCT_NAME, "Ultima"),
 -              },
 -      },
 -      {
 -              .ident = "Google Reks",
 -              .callback = strago_quirk_cb,
 -              .matches = {
 -                      DMI_MATCH(DMI_PRODUCT_NAME, "Reks"),
 +                      DMI_MATCH(DMI_SYS_VENDOR, "GOOGLE"),
                },
        },
        { }
@@@ -3562,9 -3358,17 +3562,9 @@@ static struct rt5645_platform_data budd
        .jd_invert = true,
  };
  
 -static int buddy_quirk_cb(const struct dmi_system_id *id)
 -{
 -      rt5645_pdata = &buddy_platform_data;
 -
 -      return 1;
 -}
 -
  static struct dmi_system_id dmi_platform_intel_broadwell[] = {
        {
                .ident = "Chrome Buddy",
 -              .callback = buddy_quirk_cb,
                .matches = {
                        DMI_MATCH(DMI_PRODUCT_NAME, "Buddy"),
                },
        { }
  };
  
 +static bool rt5645_check_dp(struct device *dev)
 +{
 +      if (device_property_present(dev, "realtek,in2-differential") ||
 +              device_property_present(dev, "realtek,dmic1-data-pin") ||
 +              device_property_present(dev, "realtek,dmic2-data-pin") ||
 +              device_property_present(dev, "realtek,jd-mode"))
 +              return true;
 +
 +      return false;
 +}
  
  static int rt5645_parse_dt(struct rt5645_priv *rt5645, struct device *dev)
  {
@@@ -3604,7 -3398,6 +3604,7 @@@ static int rt5645_i2c_probe(struct i2c_
        struct rt5645_priv *rt5645;
        int ret, i;
        unsigned int val;
 +      struct regmap *regmap;
  
        rt5645 = devm_kzalloc(&i2c->dev, sizeof(struct rt5645_priv),
                                GFP_KERNEL);
  
        if (pdata)
                rt5645->pdata = *pdata;
 -      else if (dmi_check_system(dmi_platform_intel_braswell) ||
 -                      dmi_check_system(dmi_platform_intel_broadwell))
 -              rt5645->pdata = *rt5645_pdata;
 -      else
 +      else if (dmi_check_system(dmi_platform_intel_broadwell))
 +              rt5645->pdata = buddy_platform_data;
 +      else if (rt5645_check_dp(&i2c->dev))
                rt5645_parse_dt(rt5645, &i2c->dev);
 +      else if (dmi_check_system(dmi_platform_intel_braswell))
 +              rt5645->pdata = general_platform_data;
  
        rt5645->gpiod_hp_det = devm_gpiod_get_optional(&i2c->dev, "hp-detect",
                                                       GPIOD_IN);
                return PTR_ERR(rt5645->gpiod_hp_det);
        }
  
 -      rt5645->regmap = devm_regmap_init_i2c(i2c, &rt5645_regmap);
 -      if (IS_ERR(rt5645->regmap)) {
 -              ret = PTR_ERR(rt5645->regmap);
 -              dev_err(&i2c->dev, "Failed to allocate register map: %d\n",
 -                      ret);
 -              return ret;
 -      }
 -
        for (i = 0; i < ARRAY_SIZE(rt5645->supplies); i++)
                rt5645->supplies[i].supply = rt5645_supply_names[i];
  
                return ret;
        }
  
 -      regmap_read(rt5645->regmap, RT5645_VENDOR_ID2, &val);
 +      regmap = devm_regmap_init_i2c(i2c, &temp_regmap);
 +      if (IS_ERR(regmap)) {
 +              ret = PTR_ERR(regmap);
 +              dev_err(&i2c->dev, "Failed to allocate temp register map: %d\n",
 +                      ret);
 +              return ret;
 +      }
 +      regmap_read(regmap, RT5645_VENDOR_ID2, &val);
  
        switch (val) {
        case RT5645_DEVICE_ID:
 +              rt5645->regmap = devm_regmap_init_i2c(i2c, &rt5645_regmap);
                rt5645->codec_type = CODEC_TYPE_RT5645;
                break;
        case RT5650_DEVICE_ID:
 +              rt5645->regmap = devm_regmap_init_i2c(i2c, &rt5650_regmap);
                rt5645->codec_type = CODEC_TYPE_RT5650;
                break;
        default:
                goto err_enable;
        }
  
 +      if (IS_ERR(rt5645->regmap)) {
 +              ret = PTR_ERR(rt5645->regmap);
 +              dev_err(&i2c->dev, "Failed to allocate register map: %d\n",
 +                      ret);
 +              return ret;
 +      }
 +
        regmap_write(rt5645->regmap, RT5645_RESET, 0);
  
        ret = regmap_register_patch(rt5645->regmap, init_list,
                }
        }
  
 +      if (rt5645->pdata.jd_invert) {
 +              regmap_update_bits(rt5645->regmap, RT5645_IRQ_CTRL2,
 +                      RT5645_JD_1_1_MASK, RT5645_JD_1_1_INV);
 +              setup_timer(&rt5645->btn_check_timer,
 +                      rt5645_btn_check_callback, (unsigned long)rt5645);
 +      }
 +
        INIT_DELAYED_WORK(&rt5645->jack_detect_work, rt5645_jack_detect_work);
 +      INIT_DELAYED_WORK(&rt5645->rcclock_work, rt5645_rcclock_work);
  
        if (rt5645->i2c->irq) {
                ret = request_threaded_irq(rt5645->i2c->irq, NULL, rt5645_irq,
@@@ -3845,7 -3621,6 +3845,7 @@@ static int rt5645_i2c_remove(struct i2c
                free_irq(i2c->irq, rt5645);
  
        cancel_delayed_work_sync(&rt5645->jack_detect_work);
 +      cancel_delayed_work_sync(&rt5645->rcclock_work);
  
        snd_soc_unregister_codec(&i2c->dev);
        regulator_bulk_disable(ARRAY_SIZE(rt5645->supplies), rt5645->supplies);