Merge tag 'ext4_for_linus_stable' of git://git.kernel.org/pub/scm/linux/kernel/git...
[linux-2.6-microblaze.git] / sound / soc / codecs / rt298.c
index f0e6c06..f80cfe4 100644 (file)
@@ -17,6 +17,7 @@
 #include <linux/i2c.h>
 #include <linux/platform_device.h>
 #include <linux/spi/spi.h>
+#include <linux/dmi.h>
 #include <linux/acpi.h>
 #include <sound/core.h>
 #include <sound/pcm.h>
@@ -275,6 +276,8 @@ static int rt298_jack_detect(struct rt298_priv *rt298, bool *hp, bool *mic)
                } else {
                        *mic = false;
                        regmap_write(rt298->regmap, RT298_SET_MIC1, 0x20);
+                       regmap_update_bits(rt298->regmap,
+                               RT298_CBJ_CTRL1, 0x0400, 0x0000);
                }
        } else {
                regmap_read(rt298->regmap, RT298_GET_HP_SENSE, &buf);
@@ -481,6 +484,26 @@ static int rt298_adc_event(struct snd_soc_dapm_widget *w,
                snd_soc_update_bits(codec,
                        VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, nid, 0),
                        0x7080, 0x7000);
+                /* If MCLK doesn't exist, reset AD filter */
+               if (!(snd_soc_read(codec, RT298_VAD_CTRL) & 0x200)) {
+                       pr_info("NO MCLK\n");
+                       switch (nid) {
+                       case RT298_ADC_IN1:
+                               snd_soc_update_bits(codec,
+                                       RT298_D_FILTER_CTRL, 0x2, 0x2);
+                               mdelay(10);
+                               snd_soc_update_bits(codec,
+                                       RT298_D_FILTER_CTRL, 0x2, 0x0);
+                               break;
+                       case RT298_ADC_IN2:
+                               snd_soc_update_bits(codec,
+                                       RT298_D_FILTER_CTRL, 0x4, 0x4);
+                               mdelay(10);
+                               snd_soc_update_bits(codec,
+                                       RT298_D_FILTER_CTRL, 0x4, 0x0);
+                               break;
+                       }
+               }
                break;
        case SND_SOC_DAPM_PRE_PMD:
                snd_soc_update_bits(codec,
@@ -519,30 +542,12 @@ static int rt298_mic1_event(struct snd_soc_dapm_widget *w,
        return 0;
 }
 
-static int rt298_vref_event(struct snd_soc_dapm_widget *w,
-                            struct snd_kcontrol *kcontrol, int event)
-{
-       struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
-
-       switch (event) {
-       case SND_SOC_DAPM_PRE_PMU:
-               snd_soc_update_bits(codec,
-                       RT298_CBJ_CTRL1, 0x0400, 0x0000);
-               mdelay(50);
-               break;
-       default:
-               return 0;
-       }
-
-       return 0;
-}
-
 static const struct snd_soc_dapm_widget rt298_dapm_widgets[] = {
 
        SND_SOC_DAPM_SUPPLY_S("HV", 1, RT298_POWER_CTRL1,
                12, 1, NULL, 0),
        SND_SOC_DAPM_SUPPLY("VREF", RT298_POWER_CTRL1,
-               0, 1, rt298_vref_event, SND_SOC_DAPM_PRE_PMU),
+               0, 1, NULL, 0),
        SND_SOC_DAPM_SUPPLY_S("BG_MBIAS", 1, RT298_POWER_CTRL2,
                1, 0, NULL, 0),
        SND_SOC_DAPM_SUPPLY_S("LDO1", 1, RT298_POWER_CTRL2,
@@ -933,18 +938,9 @@ static int rt298_set_bias_level(struct snd_soc_codec *codec,
                }
                break;
 
-       case SND_SOC_BIAS_ON:
-               mdelay(30);
-               snd_soc_update_bits(codec,
-                       RT298_CBJ_CTRL1, 0x0400, 0x0400);
-
-               break;
-
        case SND_SOC_BIAS_STANDBY:
                snd_soc_write(codec,
                        RT298_SET_AUDIO_POWER, AC_PWRST_D3);
-               snd_soc_update_bits(codec,
-                       RT298_CBJ_CTRL1, 0x0400, 0x0000);
                break;
 
        default:
@@ -1132,6 +1128,17 @@ static const struct acpi_device_id rt298_acpi_match[] = {
 };
 MODULE_DEVICE_TABLE(acpi, rt298_acpi_match);
 
+static const struct dmi_system_id force_combo_jack_table[] = {
+       {
+               .ident = "Intel Broxton P",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "Intel Corp"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "Broxton P")
+               }
+       },
+       { }
+};
+
 static int rt298_i2c_probe(struct i2c_client *i2c,
                           const struct i2c_device_id *id)
 {
@@ -1184,11 +1191,16 @@ static int rt298_i2c_probe(struct i2c_client *i2c,
 
        /* enable jack combo mode on supported devices */
        acpiid = acpi_match_device(dev->driver->acpi_match_table, dev);
-       if (acpiid) {
+       if (acpiid && acpiid->driver_data) {
                rt298->pdata = *(struct rt298_platform_data *)
                                acpiid->driver_data;
        }
 
+       if (dmi_check_system(force_combo_jack_table)) {
+               rt298->pdata.cbj_en = true;
+               rt298->pdata.gpio2_en = false;
+       }
+
        /* VREF Charging */
        regmap_update_bits(rt298->regmap, 0x04, 0x80, 0x80);
        regmap_update_bits(rt298->regmap, 0x1b, 0x860, 0x860);