Merge remote-tracking branches 'asoc/topic/88pm860x', 'asoc/topic/ac97', 'asoc/topic...
authorMark Brown <broonie@kernel.org>
Sun, 30 Aug 2015 14:52:21 +0000 (15:52 +0100)
committerMark Brown <broonie@kernel.org>
Sun, 30 Aug 2015 14:52:21 +0000 (15:52 +0100)
18 files changed:
include/sound/ac97_codec.h
include/sound/soc.h
sound/ac97_bus.c
sound/soc/atmel/atmel_ssc_dai.c
sound/soc/codecs/88pm860x-codec.c
sound/soc/codecs/ad1980.c
sound/soc/codecs/ak4642.c
sound/soc/codecs/arizona.c
sound/soc/codecs/arizona.h
sound/soc/codecs/stac9766.c
sound/soc/codecs/wm5102.c
sound/soc/codecs/wm5110.c
sound/soc/codecs/wm8997.c
sound/soc/codecs/wm9705.c
sound/soc/codecs/wm9712.c
sound/soc/codecs/wm9713.c
sound/soc/codecs/wm9713.h
sound/soc/soc-ac97.c

index 0e9d75b49bede16f09a7e96e697a6d9061677c0c..74bc85473b58c18e3bc92e2fcf7c70a232fe75d7 100644 (file)
@@ -584,6 +584,8 @@ static inline int snd_ac97_update_power(struct snd_ac97 *ac97, int reg,
 void snd_ac97_suspend(struct snd_ac97 *ac97);
 void snd_ac97_resume(struct snd_ac97 *ac97);
 #endif
+int snd_ac97_reset(struct snd_ac97 *ac97, bool try_warm, unsigned int id,
+       unsigned int id_mask);
 
 /* quirk types */
 enum {
index ab69e2652b4e8bfe5cb241c1466034504b876b90..73dffc6c7d7278a2b70cf220771f09d1d743d09f 100644 (file)
@@ -526,7 +526,8 @@ int snd_soc_test_bits(struct snd_soc_codec *codec, unsigned int reg,
 
 #ifdef CONFIG_SND_SOC_AC97_BUS
 struct snd_ac97 *snd_soc_alloc_ac97_codec(struct snd_soc_codec *codec);
-struct snd_ac97 *snd_soc_new_ac97_codec(struct snd_soc_codec *codec);
+struct snd_ac97 *snd_soc_new_ac97_codec(struct snd_soc_codec *codec,
+       unsigned int id, unsigned int id_mask);
 void snd_soc_free_ac97_codec(struct snd_ac97 *ac97);
 
 int snd_soc_set_ac97_ops(struct snd_ac97_bus_ops *ops);
index 2b50cbe6aca90089a12cd9b8f774ec59690bbdf4..55791a0b3943c81f5dc5c65133bcc5a8d0d07827 100644 (file)
 #include <linux/string.h>
 #include <sound/ac97_codec.h>
 
+/*
+ * snd_ac97_check_id() - Reads and checks the vendor ID of the device
+ * @ac97: The AC97 device to check
+ * @id: The ID to compare to
+ * @id_mask: Mask that is applied to the device ID before comparing to @id
+ *
+ * If @id is 0 this function returns true if the read device vendor ID is
+ * a valid ID. If @id is non 0 this functions returns true if @id
+ * matches the read vendor ID. Otherwise the function returns false.
+ */
+static bool snd_ac97_check_id(struct snd_ac97 *ac97, unsigned int id,
+       unsigned int id_mask)
+{
+       ac97->id = ac97->bus->ops->read(ac97, AC97_VENDOR_ID1) << 16;
+       ac97->id |= ac97->bus->ops->read(ac97, AC97_VENDOR_ID2);
+
+       if (ac97->id == 0x0 || ac97->id == 0xffffffff)
+               return false;
+
+       if (id != 0 && id != (ac97->id & id_mask))
+               return false;
+
+       return true;
+}
+
+/**
+ * snd_ac97_reset() - Reset AC'97 device
+ * @ac97: The AC'97 device to reset
+ * @try_warm: Try a warm reset first
+ * @id: Expected device vendor ID
+ * @id_mask: Mask that is applied to the device ID before comparing to @id
+ *
+ * This function resets the AC'97 device. If @try_warm is true the function
+ * first performs a warm reset. If the warm reset is successful the function
+ * returns 1. Otherwise or if @try_warm is false the function issues cold reset
+ * followed by a warm reset. If this is successful the function returns 0,
+ * otherwise a negative error code. If @id is 0 any valid device ID will be
+ * accepted, otherwise only the ID that matches @id and @id_mask is accepted.
+ */
+int snd_ac97_reset(struct snd_ac97 *ac97, bool try_warm, unsigned int id,
+       unsigned int id_mask)
+{
+       struct snd_ac97_bus_ops *ops = ac97->bus->ops;
+
+       if (try_warm && ops->warm_reset) {
+               ops->warm_reset(ac97);
+               if (snd_ac97_check_id(ac97, id, id_mask))
+                       return 1;
+       }
+
+       if (ops->reset)
+               ops->reset(ac97);
+       if (ops->warm_reset)
+               ops->warm_reset(ac97);
+
+       if (snd_ac97_check_id(ac97, id, id_mask))
+               return 0;
+
+       return -ENODEV;
+}
+EXPORT_SYMBOL_GPL(snd_ac97_reset);
+
 /*
  * Let drivers decide whether they want to support given codec from their
  * probe method. Drivers have direct access to the struct snd_ac97
index 841d05946b888fc5b905445f61611f44df685ff6..ba8def5665c458842d2f333d35e34c2974b2136e 100644 (file)
@@ -290,7 +290,7 @@ static int atmel_ssc_startup(struct snd_pcm_substream *substream,
        int dir, dir_mask;
        int ret;
 
-       pr_debug("atmel_ssc_startup: SSC_SR=0x%u\n",
+       pr_debug("atmel_ssc_startup: SSC_SR=0x%x\n",
                ssc_readl(ssc_p->ssc->regs, SR));
 
        /* Enable PMC peripheral clock for this SSC */
index 38b3dad9d48ac42c58e2c9d7058c094392889c7a..4d91a6aa696b8ccdc3d9c042823118e18a86fe33 100644 (file)
@@ -1028,10 +1028,8 @@ static int pm860x_set_dai_sysclk(struct snd_soc_dai *codec_dai,
 
        if (dir == PM860X_CLK_DIR_OUT)
                pm860x->dir = PM860X_CLK_DIR_OUT;
-       else {
-               pm860x->dir = PM860X_CLK_DIR_IN;
+       else    /* Slave mode is not supported */
                return -EINVAL;
-       }
 
        return 0;
 }
index 3cc69a626454fce289a497dd92d5c8650cca7388..9ef20dbccbe31c6fd7f82c58da18117b64187a91 100644 (file)
@@ -202,19 +202,21 @@ static struct snd_soc_dai_driver ad1980_dai = {
                .formats = SND_SOC_STD_AC97_FMTS, },
 };
 
+#define AD1980_VENDOR_ID 0x41445300
+#define AD1980_VENDOR_MASK 0xffffff00
+
 static int ad1980_reset(struct snd_soc_codec *codec, int try_warm)
 {
        struct snd_ac97 *ac97 = snd_soc_codec_get_drvdata(codec);
        unsigned int retry_cnt = 0;
+       int ret;
 
        do {
-               if (try_warm && soc_ac97_ops->warm_reset) {
-                       soc_ac97_ops->warm_reset(ac97);
-                       if (snd_soc_read(codec, AC97_RESET) == 0x0090)
-                               return 1;
-               }
+               ret = snd_ac97_reset(ac97, true, AD1980_VENDOR_ID,
+                       AD1980_VENDOR_MASK);
+               if (ret >= 0)
+                       return 0;
 
-               soc_ac97_ops->reset(ac97);
                /*
                 * Set bit 16slot in register 74h, then every slot will has only
                 * 16 bits. This command is sent out in 20bit mode, in which
@@ -223,8 +225,6 @@ static int ad1980_reset(struct snd_soc_codec *codec, int try_warm)
                 */
                snd_soc_write(codec, AC97_AD_SERIAL_CFG, 0x9900);
 
-               if (snd_soc_read(codec, AC97_RESET)  == 0x0090)
-                       return 0;
        } while (retry_cnt++ < 10);
 
        dev_err(codec->dev, "Failed to reset: AC97 link error\n");
@@ -240,7 +240,7 @@ static int ad1980_soc_probe(struct snd_soc_codec *codec)
        u16 vendor_id2;
        u16 ext_status;
 
-       ac97 = snd_soc_new_ac97_codec(codec);
+       ac97 = snd_soc_new_ac97_codec(codec, 0, 0);
        if (IS_ERR(ac97)) {
                ret = PTR_ERR(ac97);
                dev_err(codec->dev, "Failed to register AC97 codec: %d\n", ret);
@@ -260,22 +260,10 @@ static int ad1980_soc_probe(struct snd_soc_codec *codec)
        if (ret < 0)
                goto reset_err;
 
-       /* Read out vendor ID to make sure it is ad1980 */
-       if (snd_soc_read(codec, AC97_VENDOR_ID1) != 0x4144) {
-               ret = -ENODEV;
-               goto reset_err;
-       }
-
        vendor_id2 = snd_soc_read(codec, AC97_VENDOR_ID2);
-
-       if (vendor_id2 != 0x5370) {
-               if (vendor_id2 != 0x5374) {
-                       ret = -ENODEV;
-                       goto reset_err;
-               } else {
-                       dev_warn(codec->dev,
-                               "Found AD1981 - only 2/2 IN/OUT Channels supported\n");
-               }
+       if (vendor_id2 == 0x5374) {
+               dev_warn(codec->dev,
+                       "Found AD1981 - only 2/2 IN/OUT Channels supported\n");
        }
 
        /* unmute captures and playbacks volume */
index 66352f70ac47ffee477ec14b0b741f97a1c565ed..4a90143d0e907b5034d0f4caa506c97000500f71 100644 (file)
 #define FIL1_0         0x1c
 #define FIL1_1         0x1d
 #define FIL1_2         0x1e
-#define FIL1_3         0x1f
+#define FIL1_3         0x1f    /* The maximum valid register for ak4642 */
 #define PW_MGMT4       0x20
 #define MD_CTL5                0x21
 #define LO_MS          0x22
 #define HP_MS          0x23
-#define SPK_MS         0x24
+#define SPK_MS         0x24    /* The maximum valid register for ak4643 */
+#define EQ_FBEQAB      0x25
+#define EQ_FBEQCD      0x26
+#define EQ_FBEQE       0x27    /* The maximum valid register for ak4648 */
 
 /* PW_MGMT1*/
 #define PMVCM          (1 << 6) /* VCOM Power Management */
@@ -241,7 +244,7 @@ static const struct snd_soc_dapm_route ak4642_intercon[] = {
 /*
  * ak4642 register cache
  */
-static const struct reg_default ak4642_reg[] = {
+static const struct reg_default ak4643_reg[] = {
        {  0, 0x00 }, {  1, 0x00 }, {  2, 0x01 }, {  3, 0x00 },
        {  4, 0x02 }, {  5, 0x00 }, {  6, 0x00 }, {  7, 0x00 },
        {  8, 0xe1 }, {  9, 0xe1 }, { 10, 0x18 }, { 11, 0x00 },
@@ -254,6 +257,14 @@ static const struct reg_default ak4642_reg[] = {
        { 36, 0x00 },
 };
 
+/* The default settings for 0x0 ~ 0x1f registers are the same for ak4642
+   and ak4643. So we reuse the ak4643 reg_default for ak4642.
+   The valid registers for ak4642 are 0x0 ~ 0x1f which is a subset of ak4643,
+   so define NUM_AK4642_REG_DEFAULTS for ak4642.
+*/
+#define ak4642_reg ak4643_reg
+#define NUM_AK4642_REG_DEFAULTS        (FIL1_3 + 1)
+
 static const struct reg_default ak4648_reg[] = {
        {  0, 0x00 }, {  1, 0x00 }, {  2, 0x01 }, {  3, 0x00 },
        {  4, 0x02 }, {  5, 0x00 }, {  6, 0x00 }, {  7, 0x00 },
@@ -535,15 +546,23 @@ static struct snd_soc_codec_driver soc_codec_dev_ak4642 = {
 static const struct regmap_config ak4642_regmap = {
        .reg_bits               = 8,
        .val_bits               = 8,
-       .max_register           = ARRAY_SIZE(ak4642_reg) + 1,
+       .max_register           = FIL1_3,
        .reg_defaults           = ak4642_reg,
-       .num_reg_defaults       = ARRAY_SIZE(ak4642_reg),
+       .num_reg_defaults       = NUM_AK4642_REG_DEFAULTS,
+};
+
+static const struct regmap_config ak4643_regmap = {
+       .reg_bits               = 8,
+       .val_bits               = 8,
+       .max_register           = SPK_MS,
+       .reg_defaults           = ak4643_reg,
+       .num_reg_defaults       = ARRAY_SIZE(ak4643_reg),
 };
 
 static const struct regmap_config ak4648_regmap = {
        .reg_bits               = 8,
        .val_bits               = 8,
-       .max_register           = ARRAY_SIZE(ak4648_reg) + 1,
+       .max_register           = EQ_FBEQE,
        .reg_defaults           = ak4648_reg,
        .num_reg_defaults       = ARRAY_SIZE(ak4648_reg),
 };
@@ -553,7 +572,7 @@ static const struct ak4642_drvdata ak4642_drvdata = {
 };
 
 static const struct ak4642_drvdata ak4643_drvdata = {
-       .regmap_config = &ak4642_regmap,
+       .regmap_config = &ak4643_regmap,
 };
 
 static const struct ak4642_drvdata ak4648_drvdata = {
index 4180827a84800e60b2f98aed54884e2f0cc1cdf0..2b55115e94b21f10221f485b2facbafb32d42a81 100644 (file)
@@ -1504,7 +1504,7 @@ static int arizona_hw_params(struct snd_pcm_substream *substream,
        else
                rates = &arizona_48k_bclk_rates[0];
 
-       wl = snd_pcm_format_width(params_format(params));
+       wl = params_width(params);
 
        if (tdm_slots) {
                arizona_aif_dbg(dai, "Configuring for %d %d bit TDM slots\n",
@@ -2304,6 +2304,82 @@ const struct snd_kcontrol_new arizona_adsp2_rate_controls[] = {
 };
 EXPORT_SYMBOL_GPL(arizona_adsp2_rate_controls);
 
+static bool arizona_eq_filter_unstable(bool mode, __be16 _a, __be16 _b)
+{
+       s16 a = be16_to_cpu(_a);
+       s16 b = be16_to_cpu(_b);
+
+       if (!mode) {
+               return abs(a) >= 4096;
+       } else {
+               if (abs(b) >= 4096)
+                       return true;
+
+               return (abs((a << 16) / (4096 - b)) >= 4096 << 4);
+       }
+}
+
+int arizona_eq_coeff_put(struct snd_kcontrol *kcontrol,
+                        struct snd_ctl_elem_value *ucontrol)
+{
+       struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
+       struct arizona *arizona = dev_get_drvdata(codec->dev->parent);
+       struct soc_bytes *params = (void *)kcontrol->private_value;
+       unsigned int val;
+       __be16 *data;
+       int len;
+       int ret;
+
+       len = params->num_regs * regmap_get_val_bytes(arizona->regmap);
+
+       data = kmemdup(ucontrol->value.bytes.data, len, GFP_KERNEL | GFP_DMA);
+       if (!data)
+               return -ENOMEM;
+
+       data[0] &= cpu_to_be16(ARIZONA_EQ1_B1_MODE);
+
+       if (arizona_eq_filter_unstable(!!data[0], data[1], data[2]) ||
+           arizona_eq_filter_unstable(true, data[4], data[5]) ||
+           arizona_eq_filter_unstable(true, data[8], data[9]) ||
+           arizona_eq_filter_unstable(true, data[12], data[13]) ||
+           arizona_eq_filter_unstable(false, data[16], data[17])) {
+               dev_err(arizona->dev, "Rejecting unstable EQ coefficients\n");
+               ret = -EINVAL;
+               goto out;
+       }
+
+       ret = regmap_read(arizona->regmap, params->base, &val);
+       if (ret != 0)
+               goto out;
+
+       val &= ~ARIZONA_EQ1_B1_MODE;
+       data[0] |= cpu_to_be16(val);
+
+       ret = regmap_raw_write(arizona->regmap, params->base, data, len);
+
+out:
+       kfree(data);
+       return ret;
+}
+EXPORT_SYMBOL_GPL(arizona_eq_coeff_put);
+
+int arizona_lhpf_coeff_put(struct snd_kcontrol *kcontrol,
+                          struct snd_ctl_elem_value *ucontrol)
+{
+       struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
+       struct arizona *arizona = dev_get_drvdata(codec->dev->parent);
+       __be16 *data = (__be16 *)ucontrol->value.bytes.data;
+       s16 val = be16_to_cpu(*data);
+
+       if (abs(val) >= 4096) {
+               dev_err(arizona->dev, "Rejecting unstable LHPF coefficients\n");
+               return -EINVAL;
+       }
+
+       return snd_soc_bytes_put(kcontrol, ucontrol);
+}
+EXPORT_SYMBOL_GPL(arizona_lhpf_coeff_put);
+
 MODULE_DESCRIPTION("ASoC Wolfson Arizona class device support");
 MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
 MODULE_LICENSE("GPL");
index 36867d05e0bba998ab04b3595e18630e610abe3a..ada0a418ff4b648034841e9b36f4df598d03fac2 100644 (file)
@@ -194,6 +194,20 @@ extern int arizona_mixer_values[ARIZONA_NUM_MIXER_INPUTS];
        ARIZONA_MIXER_ROUTES(name " Preloader", name "L"), \
        ARIZONA_MIXER_ROUTES(name " Preloader", name "R")
 
+#define ARIZONA_EQ_CONTROL(xname, xbase)                      \
+{      .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname,   \
+       .info = snd_soc_bytes_info, .get = snd_soc_bytes_get, \
+       .put = arizona_eq_coeff_put, .private_value =         \
+       ((unsigned long)&(struct soc_bytes) { .base = xbase,  \
+        .num_regs = 20, .mask = ~ARIZONA_EQ1_B1_MODE }) }
+
+#define ARIZONA_LHPF_CONTROL(xname, xbase)                    \
+{      .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname,   \
+       .info = snd_soc_bytes_info, .get = snd_soc_bytes_get, \
+       .put = arizona_lhpf_coeff_put, .private_value =       \
+       ((unsigned long)&(struct soc_bytes) { .base = xbase,  \
+        .num_regs = 1 }) }
+
 #define ARIZONA_RATE_ENUM_SIZE 4
 extern const char *arizona_rate_text[ARIZONA_RATE_ENUM_SIZE];
 extern const int arizona_rate_val[ARIZONA_RATE_ENUM_SIZE];
@@ -229,6 +243,11 @@ extern int arizona_hp_ev(struct snd_soc_dapm_widget *w,
                         struct snd_kcontrol *kcontrol,
                         int event);
 
+extern int arizona_eq_coeff_put(struct snd_kcontrol *kcontrol,
+                               struct snd_ctl_elem_value *ucontrol);
+extern int arizona_lhpf_coeff_put(struct snd_kcontrol *kcontrol,
+                                 struct snd_ctl_elem_value *ucontrol);
+
 extern int arizona_set_sysclk(struct snd_soc_codec *codec, int clk_id,
                              int source, unsigned int freq, int dir);
 
index ed4cca7f6779937a4e92717cc29209356f9a9e5e..0945c51df003df37f415b4cbf9d9076826f1c7b6 100644 (file)
@@ -28,6 +28,9 @@
 
 #include "stac9766.h"
 
+#define STAC9766_VENDOR_ID 0x83847666
+#define STAC9766_VENDOR_ID_MASK 0xffffffff
+
 /*
  * STAC9766 register cache
  */
@@ -239,45 +242,12 @@ static int stac9766_set_bias_level(struct snd_soc_codec *codec,
        return 0;
 }
 
-static int stac9766_reset(struct snd_soc_codec *codec, int try_warm)
-{
-       struct snd_ac97 *ac97 = snd_soc_codec_get_drvdata(codec);
-
-       if (try_warm && soc_ac97_ops->warm_reset) {
-               soc_ac97_ops->warm_reset(ac97);
-               if (stac9766_ac97_read(codec, 0) == stac9766_reg[0])
-                       return 1;
-       }
-
-       soc_ac97_ops->reset(ac97);
-       if (soc_ac97_ops->warm_reset)
-               soc_ac97_ops->warm_reset(ac97);
-       if (stac9766_ac97_read(codec, 0) != stac9766_reg[0])
-               return -EIO;
-       return 0;
-}
-
 static int stac9766_codec_resume(struct snd_soc_codec *codec)
 {
        struct snd_ac97 *ac97 = snd_soc_codec_get_drvdata(codec);
-       u16 id, reset;
 
-       reset = 0;
-       /* give the codec an AC97 warm reset to start the link */
-reset:
-       if (reset > 5) {
-               dev_err(codec->dev, "Failed to resume\n");
-               return -EIO;
-       }
-       ac97->bus->ops->warm_reset(ac97);
-       id = soc_ac97_ops->read(ac97, AC97_VENDOR_ID2);
-       if (id != 0x4c13) {
-               stac9766_reset(codec, 0);
-               reset++;
-               goto reset;
-       }
-
-       return 0;
+       return snd_ac97_reset(ac97, true, STAC9766_VENDOR_ID,
+               STAC9766_VENDOR_ID_MASK);
 }
 
 static const struct snd_soc_dai_ops stac9766_dai_ops_analog = {
@@ -330,28 +300,15 @@ static struct snd_soc_dai_driver stac9766_dai[] = {
 static int stac9766_codec_probe(struct snd_soc_codec *codec)
 {
        struct snd_ac97 *ac97;
-       int ret = 0;
 
-       ac97 = snd_soc_new_ac97_codec(codec);
+       ac97 = snd_soc_new_ac97_codec(codec, STAC9766_VENDOR_ID,
+                       STAC9766_VENDOR_ID_MASK);
        if (IS_ERR(ac97))
                return PTR_ERR(ac97);
 
        snd_soc_codec_set_drvdata(codec, ac97);
 
-       /* do a cold reset for the controller and then try
-        * a warm reset followed by an optional cold reset for codec */
-       stac9766_reset(codec, 0);
-       ret = stac9766_reset(codec, 1);
-       if (ret < 0) {
-               dev_err(codec->dev, "Failed to reset: AC97 link error\n");
-               goto codec_err;
-       }
-
        return 0;
-
-codec_err:
-       snd_soc_free_ac97_codec(ac97);
-       return ret;
 }
 
 static int stac9766_codec_remove(struct snd_soc_codec *codec)
index d097f09e50f2577fb711677c370d1f6014c408ac..64637d1cf4e5673f17145b13d7c12681bed21d48 100644 (file)
@@ -788,8 +788,7 @@ ARIZONA_MIXER_CONTROLS("EQ2", ARIZONA_EQ2MIX_INPUT_1_SOURCE),
 ARIZONA_MIXER_CONTROLS("EQ3", ARIZONA_EQ3MIX_INPUT_1_SOURCE),
 ARIZONA_MIXER_CONTROLS("EQ4", ARIZONA_EQ4MIX_INPUT_1_SOURCE),
 
-SND_SOC_BYTES("EQ1 Coefficients", ARIZONA_EQ1_3, 19),
-SOC_SINGLE("EQ1 Mode Switch", ARIZONA_EQ1_2, ARIZONA_EQ1_B1_MODE, 1, 0),
+ARIZONA_EQ_CONTROL("EQ1 Coefficients", ARIZONA_EQ1_2),
 SOC_SINGLE_TLV("EQ1 B1 Volume", ARIZONA_EQ1_1, ARIZONA_EQ1_B1_GAIN_SHIFT,
               24, 0, eq_tlv),
 SOC_SINGLE_TLV("EQ1 B2 Volume", ARIZONA_EQ1_1, ARIZONA_EQ1_B2_GAIN_SHIFT,
@@ -801,8 +800,7 @@ SOC_SINGLE_TLV("EQ1 B4 Volume", ARIZONA_EQ1_2, ARIZONA_EQ1_B4_GAIN_SHIFT,
 SOC_SINGLE_TLV("EQ1 B5 Volume", ARIZONA_EQ1_2, ARIZONA_EQ1_B5_GAIN_SHIFT,
               24, 0, eq_tlv),
 
-SND_SOC_BYTES("EQ2 Coefficients", ARIZONA_EQ2_3, 19),
-SOC_SINGLE("EQ2 Mode Switch", ARIZONA_EQ2_2, ARIZONA_EQ2_B1_MODE, 1, 0),
+ARIZONA_EQ_CONTROL("EQ2 Coefficients", ARIZONA_EQ2_2),
 SOC_SINGLE_TLV("EQ2 B1 Volume", ARIZONA_EQ2_1, ARIZONA_EQ2_B1_GAIN_SHIFT,
               24, 0, eq_tlv),
 SOC_SINGLE_TLV("EQ2 B2 Volume", ARIZONA_EQ2_1, ARIZONA_EQ2_B2_GAIN_SHIFT,
@@ -814,8 +812,7 @@ SOC_SINGLE_TLV("EQ2 B4 Volume", ARIZONA_EQ2_2, ARIZONA_EQ2_B4_GAIN_SHIFT,
 SOC_SINGLE_TLV("EQ2 B5 Volume", ARIZONA_EQ2_2, ARIZONA_EQ2_B5_GAIN_SHIFT,
               24, 0, eq_tlv),
 
-SND_SOC_BYTES("EQ3 Coefficients", ARIZONA_EQ3_3, 19),
-SOC_SINGLE("EQ3 Mode Switch", ARIZONA_EQ3_2, ARIZONA_EQ3_B1_MODE, 1, 0),
+ARIZONA_EQ_CONTROL("EQ3 Coefficients", ARIZONA_EQ3_2),
 SOC_SINGLE_TLV("EQ3 B1 Volume", ARIZONA_EQ3_1, ARIZONA_EQ3_B1_GAIN_SHIFT,
               24, 0, eq_tlv),
 SOC_SINGLE_TLV("EQ3 B2 Volume", ARIZONA_EQ3_1, ARIZONA_EQ3_B2_GAIN_SHIFT,
@@ -827,8 +824,7 @@ SOC_SINGLE_TLV("EQ3 B4 Volume", ARIZONA_EQ3_2, ARIZONA_EQ3_B4_GAIN_SHIFT,
 SOC_SINGLE_TLV("EQ3 B5 Volume", ARIZONA_EQ3_2, ARIZONA_EQ3_B5_GAIN_SHIFT,
               24, 0, eq_tlv),
 
-SND_SOC_BYTES("EQ4 Coefficients", ARIZONA_EQ4_3, 19),
-SOC_SINGLE("EQ4 Mode Switch", ARIZONA_EQ4_2, ARIZONA_EQ4_B1_MODE, 1, 0),
+ARIZONA_EQ_CONTROL("EQ4 Coefficients", ARIZONA_EQ4_2),
 SOC_SINGLE_TLV("EQ4 B1 Volume", ARIZONA_EQ4_1, ARIZONA_EQ4_B1_GAIN_SHIFT,
               24, 0, eq_tlv),
 SOC_SINGLE_TLV("EQ4 B2 Volume", ARIZONA_EQ4_1, ARIZONA_EQ4_B2_GAIN_SHIFT,
@@ -851,10 +847,10 @@ ARIZONA_MIXER_CONTROLS("LHPF2", ARIZONA_HPLP2MIX_INPUT_1_SOURCE),
 ARIZONA_MIXER_CONTROLS("LHPF3", ARIZONA_HPLP3MIX_INPUT_1_SOURCE),
 ARIZONA_MIXER_CONTROLS("LHPF4", ARIZONA_HPLP4MIX_INPUT_1_SOURCE),
 
-SND_SOC_BYTES("LHPF1 Coefficients", ARIZONA_HPLPF1_2, 1),
-SND_SOC_BYTES("LHPF2 Coefficients", ARIZONA_HPLPF2_2, 1),
-SND_SOC_BYTES("LHPF3 Coefficients", ARIZONA_HPLPF3_2, 1),
-SND_SOC_BYTES("LHPF4 Coefficients", ARIZONA_HPLPF4_2, 1),
+ARIZONA_LHPF_CONTROL("LHPF1 Coefficients", ARIZONA_HPLPF1_2),
+ARIZONA_LHPF_CONTROL("LHPF2 Coefficients", ARIZONA_HPLPF2_2),
+ARIZONA_LHPF_CONTROL("LHPF3 Coefficients", ARIZONA_HPLPF3_2),
+ARIZONA_LHPF_CONTROL("LHPF4 Coefficients", ARIZONA_HPLPF4_2),
 
 ARIZONA_MIXER_CONTROLS("DSP1L", ARIZONA_DSP1LMIX_INPUT_1_SOURCE),
 ARIZONA_MIXER_CONTROLS("DSP1R", ARIZONA_DSP1RMIX_INPUT_1_SOURCE),
@@ -1883,7 +1879,7 @@ static int wm5102_codec_probe(struct snd_soc_codec *codec)
        ret = snd_soc_add_codec_controls(codec,
                                         arizona_adsp2_rate_controls, 1);
        if (ret)
-               return ret;
+               goto err_adsp2_codec_probe;
 
        arizona_init_spk(codec);
        arizona_init_gpio(codec);
@@ -1893,6 +1889,11 @@ static int wm5102_codec_probe(struct snd_soc_codec *codec)
        priv->core.arizona->dapm = dapm;
 
        return 0;
+
+err_adsp2_codec_probe:
+       wm_adsp2_codec_remove(&priv->core.adsp[0], codec);
+
+       return ret;
 }
 
 static int wm5102_codec_remove(struct snd_soc_codec *codec)
index 709fcc6169d81eda5a9cfcb3f26c55a8f77f6602..2d1168c768d98c09b0a777027e5be8ac6632b491 100644 (file)
@@ -247,8 +247,7 @@ ARIZONA_MIXER_CONTROLS("EQ2", ARIZONA_EQ2MIX_INPUT_1_SOURCE),
 ARIZONA_MIXER_CONTROLS("EQ3", ARIZONA_EQ3MIX_INPUT_1_SOURCE),
 ARIZONA_MIXER_CONTROLS("EQ4", ARIZONA_EQ4MIX_INPUT_1_SOURCE),
 
-SND_SOC_BYTES("EQ1 Coefficients", ARIZONA_EQ1_3, 19),
-SOC_SINGLE("EQ1 Mode Switch", ARIZONA_EQ1_2, ARIZONA_EQ1_B1_MODE, 1, 0),
+ARIZONA_EQ_CONTROL("EQ1 Coefficients", ARIZONA_EQ1_2),
 SOC_SINGLE_TLV("EQ1 B1 Volume", ARIZONA_EQ1_1, ARIZONA_EQ1_B1_GAIN_SHIFT,
               24, 0, eq_tlv),
 SOC_SINGLE_TLV("EQ1 B2 Volume", ARIZONA_EQ1_1, ARIZONA_EQ1_B2_GAIN_SHIFT,
@@ -260,8 +259,7 @@ SOC_SINGLE_TLV("EQ1 B4 Volume", ARIZONA_EQ1_2, ARIZONA_EQ1_B4_GAIN_SHIFT,
 SOC_SINGLE_TLV("EQ1 B5 Volume", ARIZONA_EQ1_2, ARIZONA_EQ1_B5_GAIN_SHIFT,
               24, 0, eq_tlv),
 
-SND_SOC_BYTES("EQ2 Coefficients", ARIZONA_EQ2_3, 19),
-SOC_SINGLE("EQ2 Mode Switch", ARIZONA_EQ2_2, ARIZONA_EQ2_B1_MODE, 1, 0),
+ARIZONA_EQ_CONTROL("EQ2 Coefficients", ARIZONA_EQ2_2),
 SOC_SINGLE_TLV("EQ2 B1 Volume", ARIZONA_EQ2_1, ARIZONA_EQ2_B1_GAIN_SHIFT,
               24, 0, eq_tlv),
 SOC_SINGLE_TLV("EQ2 B2 Volume", ARIZONA_EQ2_1, ARIZONA_EQ2_B2_GAIN_SHIFT,
@@ -273,8 +271,7 @@ SOC_SINGLE_TLV("EQ2 B4 Volume", ARIZONA_EQ2_2, ARIZONA_EQ2_B4_GAIN_SHIFT,
 SOC_SINGLE_TLV("EQ2 B5 Volume", ARIZONA_EQ2_2, ARIZONA_EQ2_B5_GAIN_SHIFT,
               24, 0, eq_tlv),
 
-SND_SOC_BYTES("EQ3 Coefficients", ARIZONA_EQ3_3, 19),
-SOC_SINGLE("EQ3 Mode Switch", ARIZONA_EQ3_2, ARIZONA_EQ3_B1_MODE, 1, 0),
+ARIZONA_EQ_CONTROL("EQ3 Coefficients", ARIZONA_EQ3_2),
 SOC_SINGLE_TLV("EQ3 B1 Volume", ARIZONA_EQ3_1, ARIZONA_EQ3_B1_GAIN_SHIFT,
               24, 0, eq_tlv),
 SOC_SINGLE_TLV("EQ3 B2 Volume", ARIZONA_EQ3_1, ARIZONA_EQ3_B2_GAIN_SHIFT,
@@ -286,8 +283,7 @@ SOC_SINGLE_TLV("EQ3 B4 Volume", ARIZONA_EQ3_2, ARIZONA_EQ3_B4_GAIN_SHIFT,
 SOC_SINGLE_TLV("EQ3 B5 Volume", ARIZONA_EQ3_2, ARIZONA_EQ3_B5_GAIN_SHIFT,
               24, 0, eq_tlv),
 
-SND_SOC_BYTES("EQ4 Coefficients", ARIZONA_EQ4_3, 19),
-SOC_SINGLE("EQ4 Mode Switch", ARIZONA_EQ4_2, ARIZONA_EQ4_B1_MODE, 1, 0),
+ARIZONA_EQ_CONTROL("EQ4 Coefficients", ARIZONA_EQ4_2),
 SOC_SINGLE_TLV("EQ4 B1 Volume", ARIZONA_EQ4_1, ARIZONA_EQ4_B1_GAIN_SHIFT,
               24, 0, eq_tlv),
 SOC_SINGLE_TLV("EQ4 B2 Volume", ARIZONA_EQ4_1, ARIZONA_EQ4_B2_GAIN_SHIFT,
@@ -314,10 +310,10 @@ ARIZONA_MIXER_CONTROLS("LHPF2", ARIZONA_HPLP2MIX_INPUT_1_SOURCE),
 ARIZONA_MIXER_CONTROLS("LHPF3", ARIZONA_HPLP3MIX_INPUT_1_SOURCE),
 ARIZONA_MIXER_CONTROLS("LHPF4", ARIZONA_HPLP4MIX_INPUT_1_SOURCE),
 
-SND_SOC_BYTES("LHPF1 Coefficients", ARIZONA_HPLPF1_2, 1),
-SND_SOC_BYTES("LHPF2 Coefficients", ARIZONA_HPLPF2_2, 1),
-SND_SOC_BYTES("LHPF3 Coefficients", ARIZONA_HPLPF3_2, 1),
-SND_SOC_BYTES("LHPF4 Coefficients", ARIZONA_HPLPF4_2, 1),
+ARIZONA_LHPF_CONTROL("LHPF1 Coefficients", ARIZONA_HPLPF1_2),
+ARIZONA_LHPF_CONTROL("LHPF2 Coefficients", ARIZONA_HPLPF2_2),
+ARIZONA_LHPF_CONTROL("LHPF3 Coefficients", ARIZONA_HPLPF3_2),
+ARIZONA_LHPF_CONTROL("LHPF4 Coefficients", ARIZONA_HPLPF4_2),
 
 SOC_ENUM("LHPF1 Mode", arizona_lhpf1_mode),
 SOC_ENUM("LHPF2 Mode", arizona_lhpf2_mode),
@@ -1611,18 +1607,24 @@ static int wm5110_codec_probe(struct snd_soc_codec *codec)
        for (i = 0; i < WM5110_NUM_ADSP; ++i) {
                ret = wm_adsp2_codec_probe(&priv->core.adsp[i], codec);
                if (ret)
-                       return ret;
+                       goto err_adsp2_codec_probe;
        }
 
        ret = snd_soc_add_codec_controls(codec,
                                         arizona_adsp2_rate_controls,
                                         WM5110_NUM_ADSP);
        if (ret)
-               return ret;
+               goto err_adsp2_codec_probe;
 
        snd_soc_dapm_disable_pin(dapm, "HAPTICS");
 
        return 0;
+
+err_adsp2_codec_probe:
+       for (--i; i >= 0; --i)
+               wm_adsp2_codec_remove(&priv->core.adsp[i], codec);
+
+       return ret;
 }
 
 static int wm5110_codec_remove(struct snd_soc_codec *codec)
index 4134dc7e12434cb1a1e43b723eb43a9e23bcee52..b4dba3a02abafd73044724146601fade748637b4 100644 (file)
@@ -174,8 +174,7 @@ ARIZONA_MIXER_CONTROLS("EQ2", ARIZONA_EQ2MIX_INPUT_1_SOURCE),
 ARIZONA_MIXER_CONTROLS("EQ3", ARIZONA_EQ3MIX_INPUT_1_SOURCE),
 ARIZONA_MIXER_CONTROLS("EQ4", ARIZONA_EQ4MIX_INPUT_1_SOURCE),
 
-SND_SOC_BYTES("EQ1 Coefficients", ARIZONA_EQ1_3, 19),
-SOC_SINGLE("EQ1 Mode Switch", ARIZONA_EQ1_2, ARIZONA_EQ1_B1_MODE, 1, 0),
+ARIZONA_EQ_CONTROL("EQ1 Coefficients", ARIZONA_EQ1_2),
 SOC_SINGLE_TLV("EQ1 B1 Volume", ARIZONA_EQ1_1, ARIZONA_EQ1_B1_GAIN_SHIFT,
               24, 0, eq_tlv),
 SOC_SINGLE_TLV("EQ1 B2 Volume", ARIZONA_EQ1_1, ARIZONA_EQ1_B2_GAIN_SHIFT,
@@ -187,8 +186,7 @@ SOC_SINGLE_TLV("EQ1 B4 Volume", ARIZONA_EQ1_2, ARIZONA_EQ1_B4_GAIN_SHIFT,
 SOC_SINGLE_TLV("EQ1 B5 Volume", ARIZONA_EQ1_2, ARIZONA_EQ1_B5_GAIN_SHIFT,
               24, 0, eq_tlv),
 
-SND_SOC_BYTES("EQ2 Coefficients", ARIZONA_EQ2_3, 19),
-SOC_SINGLE("EQ2 Mode Switch", ARIZONA_EQ2_2, ARIZONA_EQ2_B1_MODE, 1, 0),
+ARIZONA_EQ_CONTROL("EQ2 Coefficients", ARIZONA_EQ2_2),
 SOC_SINGLE_TLV("EQ2 B1 Volume", ARIZONA_EQ2_1, ARIZONA_EQ2_B1_GAIN_SHIFT,
               24, 0, eq_tlv),
 SOC_SINGLE_TLV("EQ2 B2 Volume", ARIZONA_EQ2_1, ARIZONA_EQ2_B2_GAIN_SHIFT,
@@ -200,8 +198,7 @@ SOC_SINGLE_TLV("EQ2 B4 Volume", ARIZONA_EQ2_2, ARIZONA_EQ2_B4_GAIN_SHIFT,
 SOC_SINGLE_TLV("EQ2 B5 Volume", ARIZONA_EQ2_2, ARIZONA_EQ2_B5_GAIN_SHIFT,
               24, 0, eq_tlv),
 
-SND_SOC_BYTES("EQ3 Coefficients", ARIZONA_EQ3_3, 19),
-SOC_SINGLE("EQ3 Mode Switch", ARIZONA_EQ3_2, ARIZONA_EQ3_B1_MODE, 1, 0),
+ARIZONA_EQ_CONTROL("EQ3 Coefficients", ARIZONA_EQ3_2),
 SOC_SINGLE_TLV("EQ3 B1 Volume", ARIZONA_EQ3_1, ARIZONA_EQ3_B1_GAIN_SHIFT,
               24, 0, eq_tlv),
 SOC_SINGLE_TLV("EQ3 B2 Volume", ARIZONA_EQ3_1, ARIZONA_EQ3_B2_GAIN_SHIFT,
@@ -213,8 +210,7 @@ SOC_SINGLE_TLV("EQ3 B4 Volume", ARIZONA_EQ3_2, ARIZONA_EQ3_B4_GAIN_SHIFT,
 SOC_SINGLE_TLV("EQ3 B5 Volume", ARIZONA_EQ3_2, ARIZONA_EQ3_B5_GAIN_SHIFT,
               24, 0, eq_tlv),
 
-SND_SOC_BYTES("EQ4 Coefficients", ARIZONA_EQ4_3, 19),
-SOC_SINGLE("EQ4 Mode Switch", ARIZONA_EQ4_2, ARIZONA_EQ4_B1_MODE, 1, 0),
+ARIZONA_EQ_CONTROL("EQ4 Coefficients", ARIZONA_EQ4_2),
 SOC_SINGLE_TLV("EQ4 B1 Volume", ARIZONA_EQ4_1, ARIZONA_EQ4_B1_GAIN_SHIFT,
               24, 0, eq_tlv),
 SOC_SINGLE_TLV("EQ4 B2 Volume", ARIZONA_EQ4_1, ARIZONA_EQ4_B2_GAIN_SHIFT,
@@ -242,10 +238,10 @@ SOC_ENUM("LHPF2 Mode", arizona_lhpf2_mode),
 SOC_ENUM("LHPF3 Mode", arizona_lhpf3_mode),
 SOC_ENUM("LHPF4 Mode", arizona_lhpf4_mode),
 
-SND_SOC_BYTES("LHPF1 Coefficients", ARIZONA_HPLPF1_2, 1),
-SND_SOC_BYTES("LHPF2 Coefficients", ARIZONA_HPLPF2_2, 1),
-SND_SOC_BYTES("LHPF3 Coefficients", ARIZONA_HPLPF3_2, 1),
-SND_SOC_BYTES("LHPF4 Coefficients", ARIZONA_HPLPF4_2, 1),
+ARIZONA_LHPF_CONTROL("LHPF1 Coefficients", ARIZONA_HPLPF1_2),
+ARIZONA_LHPF_CONTROL("LHPF2 Coefficients", ARIZONA_HPLPF2_2),
+ARIZONA_LHPF_CONTROL("LHPF3 Coefficients", ARIZONA_HPLPF3_2),
+ARIZONA_LHPF_CONTROL("LHPF4 Coefficients", ARIZONA_HPLPF4_2),
 
 SOC_ENUM("ISRC1 FSL", arizona_isrc_fsl[0]),
 SOC_ENUM("ISRC2 FSL", arizona_isrc_fsl[1]),
index 5cc457ef8894f7c69ae7c4981ab7e2d6d08d135b..744842c76a60c3c76c32fa2827482d527f5b327a 100644 (file)
@@ -22,6 +22,9 @@
 
 #include "wm9705.h"
 
+#define WM9705_VENDOR_ID 0x574d4c05
+#define WM9705_VENDOR_ID_MASK 0xffffffff
+
 /*
  * WM9705 register cache
  */
@@ -293,21 +296,6 @@ static struct snd_soc_dai_driver wm9705_dai[] = {
        }
 };
 
-static int wm9705_reset(struct snd_soc_codec *codec)
-{
-       struct snd_ac97 *ac97 = snd_soc_codec_get_drvdata(codec);
-
-       if (soc_ac97_ops->reset) {
-               soc_ac97_ops->reset(ac97);
-               if (ac97_read(codec, 0) == wm9705_reg[0])
-                       return 0; /* Success */
-       }
-
-       dev_err(codec->dev, "Failed to reset: AC97 link error\n");
-
-       return -EIO;
-}
-
 #ifdef CONFIG_PM
 static int wm9705_soc_suspend(struct snd_soc_codec *codec)
 {
@@ -324,7 +312,8 @@ static int wm9705_soc_resume(struct snd_soc_codec *codec)
        int i, ret;
        u16 *cache = codec->reg_cache;
 
-       ret = wm9705_reset(codec);
+       ret = snd_ac97_reset(ac97, true, WM9705_VENDOR_ID,
+               WM9705_VENDOR_ID_MASK);
        if (ret < 0)
                return ret;
 
@@ -342,30 +331,17 @@ static int wm9705_soc_resume(struct snd_soc_codec *codec)
 static int wm9705_soc_probe(struct snd_soc_codec *codec)
 {
        struct snd_ac97 *ac97;
-       int ret = 0;
 
-       ac97 = snd_soc_alloc_ac97_codec(codec);
+       ac97 = snd_soc_new_ac97_codec(codec, WM9705_VENDOR_ID,
+               WM9705_VENDOR_ID_MASK);
        if (IS_ERR(ac97)) {
-               ret = PTR_ERR(ac97);
                dev_err(codec->dev, "Failed to register AC97 codec\n");
-               return ret;
+               return PTR_ERR(ac97);
        }
 
-       ret = wm9705_reset(codec);
-       if (ret)
-               goto err_put_device;
-
-       ret = device_add(&ac97->dev);
-       if (ret)
-               goto err_put_device;
-
        snd_soc_codec_set_drvdata(codec, ac97);
 
        return 0;
-
-err_put_device:
-       put_device(&ac97->dev);
-       return ret;
 }
 
 static int wm9705_soc_remove(struct snd_soc_codec *codec)
index 1fda104dfc455cafcf83e13ed210302f8b825fbe..488a92224249f064922e4c019ab5065f07b87c74 100644 (file)
@@ -23,6 +23,9 @@
 #include <sound/tlv.h>
 #include "wm9712.h"
 
+#define WM9712_VENDOR_ID 0x574d4c12
+#define WM9712_VENDOR_ID_MASK 0xffffffff
+
 struct wm9712_priv {
        struct snd_ac97 *ac97;
        unsigned int hp_mixer[2];
@@ -613,35 +616,14 @@ static int wm9712_set_bias_level(struct snd_soc_codec *codec,
        return 0;
 }
 
-static int wm9712_reset(struct snd_soc_codec *codec, int try_warm)
-{
-       struct wm9712_priv *wm9712 = snd_soc_codec_get_drvdata(codec);
-
-       if (try_warm && soc_ac97_ops->warm_reset) {
-               soc_ac97_ops->warm_reset(wm9712->ac97);
-               if (ac97_read(codec, 0) == wm9712_reg[0])
-                       return 1;
-       }
-
-       soc_ac97_ops->reset(wm9712->ac97);
-       if (soc_ac97_ops->warm_reset)
-               soc_ac97_ops->warm_reset(wm9712->ac97);
-       if (ac97_read(codec, 0) != wm9712_reg[0])
-               goto err;
-       return 0;
-
-err:
-       dev_err(codec->dev, "Failed to reset: AC97 link error\n");
-       return -EIO;
-}
-
 static int wm9712_soc_resume(struct snd_soc_codec *codec)
 {
        struct wm9712_priv *wm9712 = snd_soc_codec_get_drvdata(codec);
        int i, ret;
        u16 *cache = codec->reg_cache;
 
-       ret = wm9712_reset(codec, 1);
+       ret = snd_ac97_reset(wm9712->ac97, true, WM9712_VENDOR_ID,
+               WM9712_VENDOR_ID_MASK);
        if (ret < 0)
                return ret;
 
@@ -663,31 +645,20 @@ static int wm9712_soc_resume(struct snd_soc_codec *codec)
 static int wm9712_soc_probe(struct snd_soc_codec *codec)
 {
        struct wm9712_priv *wm9712 = snd_soc_codec_get_drvdata(codec);
-       int ret = 0;
+       int ret;
 
-       wm9712->ac97 = snd_soc_alloc_ac97_codec(codec);
+       wm9712->ac97 = snd_soc_new_ac97_codec(codec, WM9712_VENDOR_ID,
+               WM9712_VENDOR_ID_MASK);
        if (IS_ERR(wm9712->ac97)) {
                ret = PTR_ERR(wm9712->ac97);
                dev_err(codec->dev, "Failed to register AC97 codec: %d\n", ret);
                return ret;
        }
 
-       ret = wm9712_reset(codec, 0);
-       if (ret < 0)
-               goto err_put_device;
-
-       ret = device_add(&wm9712->ac97->dev);
-       if (ret)
-               goto err_put_device;
-
        /* set alc mux to none */
        ac97_write(codec, AC97_VIDEO, ac97_read(codec, AC97_VIDEO) | 0x3000);
 
        return 0;
-
-err_put_device:
-       put_device(&wm9712->ac97->dev);
-       return ret;
 }
 
 static int wm9712_soc_remove(struct snd_soc_codec *codec)
index 89cd2d6f57c01d46a8eaf8dd24b81f7cb2a054fb..955e6511af56b3ed07de199614a61b4f74581f4b 100644 (file)
@@ -29,6 +29,9 @@
 
 #include "wm9713.h"
 
+#define WM9713_VENDOR_ID 0x574d4c13
+#define WM9713_VENDOR_ID_MASK 0xffffffff
+
 struct wm9713_priv {
        struct snd_ac97 *ac97;
        u32 pll_in; /* PLL input frequency */
@@ -1123,28 +1126,6 @@ static struct snd_soc_dai_driver wm9713_dai[] = {
        },
 };
 
-int wm9713_reset(struct snd_soc_codec *codec, int try_warm)
-{
-       struct wm9713_priv *wm9713 = snd_soc_codec_get_drvdata(codec);
-
-       if (try_warm && soc_ac97_ops->warm_reset) {
-               soc_ac97_ops->warm_reset(wm9713->ac97);
-               if (ac97_read(codec, 0) == wm9713_reg[0])
-                       return 1;
-       }
-
-       soc_ac97_ops->reset(wm9713->ac97);
-       if (soc_ac97_ops->warm_reset)
-               soc_ac97_ops->warm_reset(wm9713->ac97);
-       if (ac97_read(codec, 0) != wm9713_reg[0]) {
-               dev_err(codec->dev, "Failed to reset: AC97 link error\n");
-               return -EIO;
-       }
-
-       return 0;
-}
-EXPORT_SYMBOL_GPL(wm9713_reset);
-
 static int wm9713_set_bias_level(struct snd_soc_codec *codec,
                                 enum snd_soc_bias_level level)
 {
@@ -1196,7 +1177,8 @@ static int wm9713_soc_resume(struct snd_soc_codec *codec)
        int i, ret;
        u16 *cache = codec->reg_cache;
 
-       ret = wm9713_reset(codec, 1);
+       ret = snd_ac97_reset(wm9713->ac97, true, WM9713_VENDOR_ID,
+               WM9713_VENDOR_ID_MASK);
        if (ret < 0)
                return ret;
 
@@ -1222,32 +1204,18 @@ static int wm9713_soc_resume(struct snd_soc_codec *codec)
 static int wm9713_soc_probe(struct snd_soc_codec *codec)
 {
        struct wm9713_priv *wm9713 = snd_soc_codec_get_drvdata(codec);
-       int ret = 0, reg;
+       int reg;
 
-       wm9713->ac97 = snd_soc_alloc_ac97_codec(codec);
+       wm9713->ac97 = snd_soc_new_ac97_codec(codec, WM9713_VENDOR_ID,
+               WM9713_VENDOR_ID_MASK);
        if (IS_ERR(wm9713->ac97))
                return PTR_ERR(wm9713->ac97);
 
-       /* do a cold reset for the controller and then try
-        * a warm reset followed by an optional cold reset for codec */
-       wm9713_reset(codec, 0);
-       ret = wm9713_reset(codec, 1);
-       if (ret < 0)
-               goto err_put_device;
-
-       ret = device_add(&wm9713->ac97->dev);
-       if (ret)
-               goto err_put_device;
-
        /* unmute the adc - move to kcontrol */
        reg = ac97_read(codec, AC97_CD) & 0x7fff;
        ac97_write(codec, AC97_CD, reg);
 
        return 0;
-
-err_put_device:
-       put_device(&wm9713->ac97->dev);
-       return ret;
 }
 
 static int wm9713_soc_remove(struct snd_soc_codec *codec)
index 793da863a03d94096aa130f5f88757ef5f23eb9c..53df11b1f727fae6979b071ea02691293de21c2a 100644 (file)
@@ -45,6 +45,4 @@
 #define WM9713_DAI_AC97_AUX            1
 #define WM9713_DAI_PCM_VOICE   2
 
-int wm9713_reset(struct snd_soc_codec *codec,  int try_warm);
-
 #endif
index 08d7259bbaabad727709281234905011e990f07d..d40efc9fe0a9b4597511b2de2ad02712aa912043 100644 (file)
@@ -85,10 +85,19 @@ EXPORT_SYMBOL(snd_soc_alloc_ac97_codec);
 /**
  * snd_soc_new_ac97_codec - initailise AC97 device
  * @codec: audio codec
+ * @id: The expected device ID
+ * @id_mask: Mask that is applied to the device ID before comparing with @id
  *
  * Initialises AC97 codec resources for use by ad-hoc devices only.
+ *
+ * If @id is not 0 this function will reset the device, then read the ID from
+ * the device and check if it matches the expected ID. If it doesn't match an
+ * error will be returned and device will not be registered.
+ *
+ * Returns: A PTR_ERR() on failure or a valid snd_ac97 struct on success.
  */
-struct snd_ac97 *snd_soc_new_ac97_codec(struct snd_soc_codec *codec)
+struct snd_ac97 *snd_soc_new_ac97_codec(struct snd_soc_codec *codec,
+       unsigned int id, unsigned int id_mask)
 {
        struct snd_ac97 *ac97;
        int ret;
@@ -97,13 +106,24 @@ struct snd_ac97 *snd_soc_new_ac97_codec(struct snd_soc_codec *codec)
        if (IS_ERR(ac97))
                return ac97;
 
-       ret = device_add(&ac97->dev);
-       if (ret) {
-               put_device(&ac97->dev);
-               return ERR_PTR(ret);
+       if (id) {
+               ret = snd_ac97_reset(ac97, false, id, id_mask);
+               if (ret < 0) {
+                       dev_err(codec->dev, "Failed to reset AC97 device: %d\n",
+                               ret);
+                       goto err_put_device;
+               }
        }
 
+       ret = device_add(&ac97->dev);
+       if (ret)
+               goto err_put_device;
+
        return ac97;
+
+err_put_device:
+       put_device(&ac97->dev);
+       return ERR_PTR(ret);
 }
 EXPORT_SYMBOL_GPL(snd_soc_new_ac97_codec);