diff options
-rw-r--r-- | include/sound/ac97_codec.h | 2 | ||||
-rw-r--r-- | include/sound/soc.h | 3 | ||||
-rw-r--r-- | sound/ac97_bus.c | 62 | ||||
-rw-r--r-- | sound/soc/atmel/atmel_ssc_dai.c | 2 | ||||
-rw-r--r-- | sound/soc/codecs/88pm860x-codec.c | 4 | ||||
-rw-r--r-- | sound/soc/codecs/ad1980.c | 36 | ||||
-rw-r--r-- | sound/soc/codecs/ak4642.c | 33 | ||||
-rw-r--r-- | sound/soc/codecs/arizona.c | 78 | ||||
-rw-r--r-- | sound/soc/codecs/arizona.h | 19 | ||||
-rw-r--r-- | sound/soc/codecs/stac9766.c | 57 | ||||
-rw-r--r-- | sound/soc/codecs/wm5102.c | 27 | ||||
-rw-r--r-- | sound/soc/codecs/wm5110.c | 30 | ||||
-rw-r--r-- | sound/soc/codecs/wm8997.c | 20 | ||||
-rw-r--r-- | sound/soc/codecs/wm9705.c | 40 | ||||
-rw-r--r-- | sound/soc/codecs/wm9712.c | 45 | ||||
-rw-r--r-- | sound/soc/codecs/wm9713.c | 48 | ||||
-rw-r--r-- | sound/soc/codecs/wm9713.h | 2 | ||||
-rw-r--r-- | sound/soc/soc-ac97.c | 30 |
18 files changed, 296 insertions, 242 deletions
diff --git a/include/sound/ac97_codec.h b/include/sound/ac97_codec.h index 0e9d75b49bed..74bc85473b58 100644 --- a/include/sound/ac97_codec.h +++ b/include/sound/ac97_codec.h @@ -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 { diff --git a/include/sound/soc.h b/include/sound/soc.h index ab69e2652b4e..73dffc6c7d72 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -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); diff --git a/sound/ac97_bus.c b/sound/ac97_bus.c index 2b50cbe6aca9..55791a0b3943 100644 --- a/sound/ac97_bus.c +++ b/sound/ac97_bus.c @@ -18,6 +18,68 @@ #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 * structure and may decide based on the id field amongst other things. diff --git a/sound/soc/atmel/atmel_ssc_dai.c b/sound/soc/atmel/atmel_ssc_dai.c index 841d05946b88..ba8def5665c4 100644 --- a/sound/soc/atmel/atmel_ssc_dai.c +++ b/sound/soc/atmel/atmel_ssc_dai.c @@ -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 */ diff --git a/sound/soc/codecs/88pm860x-codec.c b/sound/soc/codecs/88pm860x-codec.c index 38b3dad9d48a..4d91a6aa696b 100644 --- a/sound/soc/codecs/88pm860x-codec.c +++ b/sound/soc/codecs/88pm860x-codec.c @@ -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; } diff --git a/sound/soc/codecs/ad1980.c b/sound/soc/codecs/ad1980.c index 3cc69a626454..9ef20dbccbe3 100644 --- a/sound/soc/codecs/ad1980.c +++ b/sound/soc/codecs/ad1980.c @@ -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 */ diff --git a/sound/soc/codecs/ak4642.c b/sound/soc/codecs/ak4642.c index 66352f70ac47..4a90143d0e90 100644 --- a/sound/soc/codecs/ak4642.c +++ b/sound/soc/codecs/ak4642.c @@ -64,12 +64,15 @@ #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 = { diff --git a/sound/soc/codecs/arizona.c b/sound/soc/codecs/arizona.c index 4180827a8480..2b55115e94b2 100644 --- a/sound/soc/codecs/arizona.c +++ b/sound/soc/codecs/arizona.c @@ -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"); diff --git a/sound/soc/codecs/arizona.h b/sound/soc/codecs/arizona.h index 36867d05e0bb..ada0a418ff4b 100644 --- a/sound/soc/codecs/arizona.h +++ b/sound/soc/codecs/arizona.h @@ -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); diff --git a/sound/soc/codecs/stac9766.c b/sound/soc/codecs/stac9766.c index ed4cca7f6779..0945c51df003 100644 --- a/sound/soc/codecs/stac9766.c +++ b/sound/soc/codecs/stac9766.c @@ -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) diff --git a/sound/soc/codecs/wm5102.c b/sound/soc/codecs/wm5102.c index d097f09e50f2..64637d1cf4e5 100644 --- a/sound/soc/codecs/wm5102.c +++ b/sound/soc/codecs/wm5102.c @@ -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) diff --git a/sound/soc/codecs/wm5110.c b/sound/soc/codecs/wm5110.c index 709fcc6169d8..2d1168c768d9 100644 --- a/sound/soc/codecs/wm5110.c +++ b/sound/soc/codecs/wm5110.c @@ -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) diff --git a/sound/soc/codecs/wm8997.c b/sound/soc/codecs/wm8997.c index 4134dc7e1243..b4dba3a02aba 100644 --- a/sound/soc/codecs/wm8997.c +++ b/sound/soc/codecs/wm8997.c @@ -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]), diff --git a/sound/soc/codecs/wm9705.c b/sound/soc/codecs/wm9705.c index 5cc457ef8894..744842c76a60 100644 --- a/sound/soc/codecs/wm9705.c +++ b/sound/soc/codecs/wm9705.c @@ -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) diff --git a/sound/soc/codecs/wm9712.c b/sound/soc/codecs/wm9712.c index 1fda104dfc45..488a92224249 100644 --- a/sound/soc/codecs/wm9712.c +++ b/sound/soc/codecs/wm9712.c @@ -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) diff --git a/sound/soc/codecs/wm9713.c b/sound/soc/codecs/wm9713.c index 89cd2d6f57c0..955e6511af56 100644 --- a/sound/soc/codecs/wm9713.c +++ b/sound/soc/codecs/wm9713.c @@ -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) diff --git a/sound/soc/codecs/wm9713.h b/sound/soc/codecs/wm9713.h index 793da863a03d..53df11b1f727 100644 --- a/sound/soc/codecs/wm9713.h +++ b/sound/soc/codecs/wm9713.h @@ -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 diff --git a/sound/soc/soc-ac97.c b/sound/soc/soc-ac97.c index 08d7259bbaab..d40efc9fe0a9 100644 --- a/sound/soc/soc-ac97.c +++ b/sound/soc/soc-ac97.c @@ -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); |