aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/codecs
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc/codecs')
-rw-r--r--sound/soc/codecs/88pm860x-codec.c6
-rw-r--r--sound/soc/codecs/Kconfig16
-rw-r--r--sound/soc/codecs/Makefile6
-rw-r--r--sound/soc/codecs/ab8500-codec.c8
-rw-r--r--sound/soc/codecs/ac97.c6
-rw-r--r--sound/soc/codecs/ad1836.c6
-rw-r--r--sound/soc/codecs/ad193x.c14
-rw-r--r--sound/soc/codecs/ad1980.c6
-rw-r--r--sound/soc/codecs/ad73311.c4
-rw-r--r--sound/soc/codecs/adau1373.c8
-rw-r--r--sound/soc/codecs/adau1701.c8
-rw-r--r--sound/soc/codecs/adav80x.c20
-rw-r--r--sound/soc/codecs/ads117x.c6
-rw-r--r--sound/soc/codecs/ak4104.c69
-rw-r--r--sound/soc/codecs/ak4535.c15
-rw-r--r--sound/soc/codecs/ak4641.c8
-rw-r--r--sound/soc/codecs/ak4642.c31
-rw-r--r--sound/soc/codecs/ak4671.c8
-rw-r--r--sound/soc/codecs/alc5623.c8
-rw-r--r--sound/soc/codecs/alc5632.c8
-rw-r--r--sound/soc/codecs/arizona.c53
-rw-r--r--sound/soc/codecs/arizona.h71
-rw-r--r--sound/soc/codecs/cq93vc.c2
-rw-r--r--sound/soc/codecs/cs4271.c35
-rw-r--r--sound/soc/codecs/cs42l52.c2
-rw-r--r--sound/soc/codecs/cs42l73.c8
-rw-r--r--sound/soc/codecs/da7210.c38
-rw-r--r--sound/soc/codecs/da732x.c8
-rw-r--r--sound/soc/codecs/da9055.c51
-rw-r--r--sound/soc/codecs/dfbmcs320.c6
-rw-r--r--sound/soc/codecs/dmic.c6
-rw-r--r--sound/soc/codecs/isabelle.c8
-rw-r--r--sound/soc/codecs/jz4740.c148
-rw-r--r--sound/soc/codecs/lm4857.c8
-rw-r--r--sound/soc/codecs/lm49453.c18
-rw-r--r--sound/soc/codecs/max9768.c15
-rw-r--r--sound/soc/codecs/max98088.c16
-rw-r--r--sound/soc/codecs/max98090.c577
-rw-r--r--sound/soc/codecs/max98095.c4
-rw-r--r--sound/soc/codecs/max9850.c8
-rw-r--r--sound/soc/codecs/max9877.c8
-rw-r--r--sound/soc/codecs/mc13783.c2
-rw-r--r--sound/soc/codecs/ml26124.c8
-rw-r--r--sound/soc/codecs/omap-hdmi.c6
-rw-r--r--sound/soc/codecs/pcm3008.c6
-rw-r--r--sound/soc/codecs/rt5631.c6
-rw-r--r--sound/soc/codecs/sgtl5000.c8
-rw-r--r--sound/soc/codecs/si476x.c255
-rw-r--r--sound/soc/codecs/sn95031.c6
-rw-r--r--sound/soc/codecs/ssm2602.c12
-rw-r--r--sound/soc/codecs/sta32x.c8
-rw-r--r--sound/soc/codecs/sta529.c8
-rw-r--r--sound/soc/codecs/stac9766.c6
-rw-r--r--sound/soc/codecs/tlv320aic32x4.c32
-rw-r--r--sound/soc/codecs/tlv320aic32x4.h3
-rw-r--r--sound/soc/codecs/tlv320dac33.c8
-rw-r--r--sound/soc/codecs/tpa6130a2.c8
-rw-r--r--sound/soc/codecs/twl4030.c6
-rw-r--r--sound/soc/codecs/twl6040.c6
-rw-r--r--sound/soc/codecs/uda134x.c6
-rw-r--r--sound/soc/codecs/uda1380.c8
-rw-r--r--sound/soc/codecs/wl1273.c6
-rw-r--r--sound/soc/codecs/wm0010.c425
-rw-r--r--sound/soc/codecs/wm1250-ev1.c10
-rw-r--r--sound/soc/codecs/wm2000.c10
-rw-r--r--sound/soc/codecs/wm2200.c277
-rw-r--r--sound/soc/codecs/wm5100.c10
-rw-r--r--sound/soc/codecs/wm5102.c144
-rw-r--r--sound/soc/codecs/wm5110.c75
-rw-r--r--sound/soc/codecs/wm8350.c10
-rw-r--r--sound/soc/codecs/wm8400.c20
-rw-r--r--sound/soc/codecs/wm8510.c17
-rw-r--r--sound/soc/codecs/wm8523.c8
-rw-r--r--sound/soc/codecs/wm8711.c14
-rw-r--r--sound/soc/codecs/wm8727.c6
-rw-r--r--sound/soc/codecs/wm8728.c14
-rw-r--r--sound/soc/codecs/wm8731.c14
-rw-r--r--sound/soc/codecs/wm8737.c14
-rw-r--r--sound/soc/codecs/wm8741.c10
-rw-r--r--sound/soc/codecs/wm8750.c100
-rw-r--r--sound/soc/codecs/wm8753.c47
-rw-r--r--sound/soc/codecs/wm8770.c223
-rw-r--r--sound/soc/codecs/wm8776.c14
-rw-r--r--sound/soc/codecs/wm8782.c6
-rw-r--r--sound/soc/codecs/wm8804.c31
-rw-r--r--sound/soc/codecs/wm8900.c14
-rw-r--r--sound/soc/codecs/wm8903.c8
-rw-r--r--sound/soc/codecs/wm8904.c8
-rw-r--r--sound/soc/codecs/wm8940.c8
-rw-r--r--sound/soc/codecs/wm8955.c19
-rw-r--r--sound/soc/codecs/wm8958-dsp2.c79
-rw-r--r--sound/soc/codecs/wm8960.c10
-rw-r--r--sound/soc/codecs/wm8961.c8
-rw-r--r--sound/soc/codecs/wm8962.c32
-rw-r--r--sound/soc/codecs/wm8971.c88
-rw-r--r--sound/soc/codecs/wm8974.c8
-rw-r--r--sound/soc/codecs/wm8978.c24
-rw-r--r--sound/soc/codecs/wm8983.c14
-rw-r--r--sound/soc/codecs/wm8985.c44
-rw-r--r--sound/soc/codecs/wm8988.c28
-rw-r--r--sound/soc/codecs/wm8990.c8
-rw-r--r--sound/soc/codecs/wm8991.c8
-rw-r--r--sound/soc/codecs/wm8993.c22
-rw-r--r--sound/soc/codecs/wm8994.c349
-rw-r--r--sound/soc/codecs/wm8994.h13
-rw-r--r--sound/soc/codecs/wm8995.c54
-rw-r--r--sound/soc/codecs/wm8996.c8
-rw-r--r--sound/soc/codecs/wm9081.c30
-rw-r--r--sound/soc/codecs/wm9090.c24
-rw-r--r--sound/soc/codecs/wm9705.c6
-rw-r--r--sound/soc/codecs/wm9712.c6
-rw-r--r--sound/soc/codecs/wm9713.c6
-rw-r--r--sound/soc/codecs/wm_adsp.c699
-rw-r--r--sound/soc/codecs/wm_adsp.h59
-rw-r--r--sound/soc/codecs/wmfw.h128
115 files changed, 3648 insertions, 1428 deletions
diff --git a/sound/soc/codecs/88pm860x-codec.c b/sound/soc/codecs/88pm860x-codec.c
index 9fd3b6827bba..60159c07448d 100644
--- a/sound/soc/codecs/88pm860x-codec.c
+++ b/sound/soc/codecs/88pm860x-codec.c
@@ -1423,7 +1423,7 @@ static struct snd_soc_codec_driver soc_codec_dev_pm860x = {
.num_dapm_routes = ARRAY_SIZE(pm860x_dapm_routes),
};
-static int __devinit pm860x_codec_probe(struct platform_device *pdev)
+static int pm860x_codec_probe(struct platform_device *pdev)
{
struct pm860x_chip *chip = dev_get_drvdata(pdev->dev.parent);
struct pm860x_priv *pm860x;
@@ -1463,7 +1463,7 @@ out:
return -EINVAL;
}
-static int __devexit pm860x_codec_remove(struct platform_device *pdev)
+static int pm860x_codec_remove(struct platform_device *pdev)
{
snd_soc_unregister_codec(&pdev->dev);
platform_set_drvdata(pdev, NULL);
@@ -1476,7 +1476,7 @@ static struct platform_driver pm860x_codec_driver = {
.owner = THIS_MODULE,
},
.probe = pm860x_codec_probe,
- .remove = __devexit_p(pm860x_codec_remove),
+ .remove = pm860x_codec_remove,
};
module_platform_driver(pm860x_codec_driver);
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
index b92759a39361..3a847828932a 100644
--- a/sound/soc/codecs/Kconfig
+++ b/sound/soc/codecs/Kconfig
@@ -44,6 +44,7 @@ config SND_SOC_ALL_CODECS
select SND_SOC_LM4857 if I2C
select SND_SOC_LM49453 if I2C
select SND_SOC_MAX98088 if I2C
+ select SND_SOC_MAX98090 if I2C
select SND_SOC_MAX98095 if I2C
select SND_SOC_MAX9850 if I2C
select SND_SOC_MAX9768 if I2C
@@ -54,6 +55,7 @@ config SND_SOC_ALL_CODECS
select SND_SOC_PCM3008
select SND_SOC_RT5631 if I2C
select SND_SOC_SGTL5000 if I2C
+ select SND_SOC_SI476X if MFD_SI476X_CORE
select SND_SOC_SN95031 if INTEL_SCU_IPC
select SND_SOC_SPDIF
select SND_SOC_SSM2602 if SND_SOC_I2C_AND_SPI
@@ -146,6 +148,13 @@ config SND_SOC_WM_HUBS
default y if SND_SOC_WM8993=y || SND_SOC_WM8994=y
default m if SND_SOC_WM8993=m || SND_SOC_WM8994=m
+config SND_SOC_WM_ADSP
+ tristate
+ default y if SND_SOC_WM5102=y
+ default y if SND_SOC_WM2200=y
+ default m if SND_SOC_WM5102=m
+ default m if SND_SOC_WM2200=m
+
config SND_SOC_AB8500_CODEC
tristate
@@ -229,6 +238,7 @@ config SND_SOC_CX20442
tristate
config SND_SOC_JZ4740_CODEC
+ select REGMAP_MMIO
tristate
config SND_SOC_L3
@@ -258,6 +268,9 @@ config SND_SOC_LM49453
config SND_SOC_MAX98088
tristate
+config SND_SOC_MAX98090
+ tristate
+
config SND_SOC_MAX98095
tristate
@@ -277,6 +290,9 @@ config SND_SOC_RT5631
config SND_SOC_SGTL5000
tristate
+config SND_SOC_SI476X
+ tristate
+
config SND_SOC_SIGMADSP
tristate
select CRC32
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile
index 9bd4d95aab4f..f6e8e36cceb7 100644
--- a/sound/soc/codecs/Makefile
+++ b/sound/soc/codecs/Makefile
@@ -34,6 +34,7 @@ snd-soc-lm4857-objs := lm4857.o
snd-soc-lm49453-objs := lm49453.o
snd-soc-max9768-objs := max9768.o
snd-soc-max98088-objs := max98088.o
+snd-soc-max98090-objs := max98090.o
snd-soc-max98095-objs := max98095.o
snd-soc-max9850-objs := max9850.o
snd-soc-mc13783-objs := mc13783.o
@@ -45,6 +46,7 @@ snd-soc-sgtl5000-objs := sgtl5000.o
snd-soc-alc5623-objs := alc5623.o
snd-soc-alc5632-objs := alc5632.o
snd-soc-sigmadsp-objs := sigmadsp.o
+snd-soc-si476x-objs := si476x.o
snd-soc-sn95031-objs := sn95031.o
snd-soc-spdif-tx-objs := spdif_transciever.o
snd-soc-spdif-rx-objs := spdif_receiver.o
@@ -62,6 +64,7 @@ snd-soc-twl6040-objs := twl6040.o
snd-soc-uda134x-objs := uda134x.o
snd-soc-uda1380-objs := uda1380.o
snd-soc-wl1273-objs := wl1273.o
+snd-soc-wm-adsp-objs := wm_adsp.o
snd-soc-wm0010-objs := wm0010.o
snd-soc-wm1250-ev1-objs := wm1250-ev1.o
snd-soc-wm2000-objs := wm2000.o
@@ -155,6 +158,7 @@ obj-$(CONFIG_SND_SOC_LM4857) += snd-soc-lm4857.o
obj-$(CONFIG_SND_SOC_LM49453) += snd-soc-lm49453.o
obj-$(CONFIG_SND_SOC_MAX9768) += snd-soc-max9768.o
obj-$(CONFIG_SND_SOC_MAX98088) += snd-soc-max98088.o
+obj-$(CONFIG_SND_SOC_MAX98090) += snd-soc-max98090.o
obj-$(CONFIG_SND_SOC_MAX98095) += snd-soc-max98095.o
obj-$(CONFIG_SND_SOC_MAX9850) += snd-soc-max9850.o
obj-$(CONFIG_SND_SOC_MC13783) += snd-soc-mc13783.o
@@ -164,6 +168,7 @@ obj-$(CONFIG_SND_SOC_PCM3008) += snd-soc-pcm3008.o
obj-$(CONFIG_SND_SOC_RT5631) += snd-soc-rt5631.o
obj-$(CONFIG_SND_SOC_SGTL5000) += snd-soc-sgtl5000.o
obj-$(CONFIG_SND_SOC_SIGMADSP) += snd-soc-sigmadsp.o
+obj-$(CONFIG_SND_SOC_SI476X) += snd-soc-si476x.o
obj-$(CONFIG_SND_SOC_SN95031) +=snd-soc-sn95031.o
obj-$(CONFIG_SND_SOC_SPDIF) += snd-soc-spdif-rx.o snd-soc-spdif-tx.o
obj-$(CONFIG_SND_SOC_SSM2602) += snd-soc-ssm2602.o
@@ -229,6 +234,7 @@ obj-$(CONFIG_SND_SOC_WM9090) += snd-soc-wm9090.o
obj-$(CONFIG_SND_SOC_WM9705) += snd-soc-wm9705.o
obj-$(CONFIG_SND_SOC_WM9712) += snd-soc-wm9712.o
obj-$(CONFIG_SND_SOC_WM9713) += snd-soc-wm9713.o
+obj-$(CONFIG_SND_SOC_WM_ADSP) += snd-soc-wm-adsp.o
obj-$(CONFIG_SND_SOC_WM_HUBS) += snd-soc-wm-hubs.o
# Amp
diff --git a/sound/soc/codecs/ab8500-codec.c b/sound/soc/codecs/ab8500-codec.c
index af547490b4f7..6c12ac206ee9 100644
--- a/sound/soc/codecs/ab8500-codec.c
+++ b/sound/soc/codecs/ab8500-codec.c
@@ -2356,7 +2356,7 @@ static int ab8500_codec_set_dai_tdm_slot(struct snd_soc_dai *dai,
return 0;
}
-struct snd_soc_dai_driver ab8500_codec_dai[] = {
+static struct snd_soc_dai_driver ab8500_codec_dai[] = {
{
.name = "ab8500-codec-dai.0",
.id = 0,
@@ -2554,7 +2554,7 @@ static struct snd_soc_codec_driver ab8500_codec_driver = {
.num_dapm_routes = ARRAY_SIZE(ab8500_dapm_routes),
};
-static int __devinit ab8500_codec_driver_probe(struct platform_device *pdev)
+static int ab8500_codec_driver_probe(struct platform_device *pdev)
{
int status;
struct ab8500_codec_drvdata *drvdata;
@@ -2580,7 +2580,7 @@ static int __devinit ab8500_codec_driver_probe(struct platform_device *pdev)
return status;
}
-static int __devexit ab8500_codec_driver_remove(struct platform_device *pdev)
+static int ab8500_codec_driver_remove(struct platform_device *pdev)
{
dev_info(&pdev->dev, "%s Enter.\n", __func__);
@@ -2595,7 +2595,7 @@ static struct platform_driver ab8500_codec_platform_driver = {
.owner = THIS_MODULE,
},
.probe = ab8500_codec_driver_probe,
- .remove = __devexit_p(ab8500_codec_driver_remove),
+ .remove = ab8500_codec_driver_remove,
.suspend = NULL,
.resume = NULL,
};
diff --git a/sound/soc/codecs/ac97.c b/sound/soc/codecs/ac97.c
index ea06b834a7de..ef2ae32ffc66 100644
--- a/sound/soc/codecs/ac97.c
+++ b/sound/soc/codecs/ac97.c
@@ -118,13 +118,13 @@ static struct snd_soc_codec_driver soc_codec_dev_ac97 = {
.resume = ac97_soc_resume,
};
-static __devinit int ac97_probe(struct platform_device *pdev)
+static int ac97_probe(struct platform_device *pdev)
{
return snd_soc_register_codec(&pdev->dev,
&soc_codec_dev_ac97, &ac97_dai, 1);
}
-static int __devexit ac97_remove(struct platform_device *pdev)
+static int ac97_remove(struct platform_device *pdev)
{
snd_soc_unregister_codec(&pdev->dev);
return 0;
@@ -137,7 +137,7 @@ static struct platform_driver ac97_codec_driver = {
},
.probe = ac97_probe,
- .remove = __devexit_p(ac97_remove),
+ .remove = ac97_remove,
};
module_platform_driver(ac97_codec_driver);
diff --git a/sound/soc/codecs/ad1836.c b/sound/soc/codecs/ad1836.c
index dce6ebeef452..9a92b7962f41 100644
--- a/sound/soc/codecs/ad1836.c
+++ b/sound/soc/codecs/ad1836.c
@@ -360,7 +360,7 @@ static const struct regmap_config ad1836_regmap_config = {
.cache_type = REGCACHE_RBTREE,
};
-static int __devinit ad1836_spi_probe(struct spi_device *spi)
+static int ad1836_spi_probe(struct spi_device *spi)
{
struct ad1836_priv *ad1836;
int ret;
@@ -383,7 +383,7 @@ static int __devinit ad1836_spi_probe(struct spi_device *spi)
return ret;
}
-static int __devexit ad1836_spi_remove(struct spi_device *spi)
+static int ad1836_spi_remove(struct spi_device *spi)
{
snd_soc_unregister_codec(&spi->dev);
return 0;
@@ -405,7 +405,7 @@ static struct spi_driver ad1836_spi_driver = {
.owner = THIS_MODULE,
},
.probe = ad1836_spi_probe,
- .remove = __devexit_p(ad1836_spi_remove),
+ .remove = ad1836_spi_remove,
.id_table = ad1836_ids,
};
diff --git a/sound/soc/codecs/ad193x.c b/sound/soc/codecs/ad193x.c
index 2f752660f678..aea7e52cf714 100644
--- a/sound/soc/codecs/ad193x.c
+++ b/sound/soc/codecs/ad193x.c
@@ -378,7 +378,7 @@ static const struct regmap_config ad193x_spi_regmap_config = {
.volatile_reg = adau193x_reg_volatile,
};
-static int __devinit ad193x_spi_probe(struct spi_device *spi)
+static int ad193x_spi_probe(struct spi_device *spi)
{
struct ad193x_priv *ad193x;
@@ -397,7 +397,7 @@ static int __devinit ad193x_spi_probe(struct spi_device *spi)
&ad193x_dai, 1);
}
-static int __devexit ad193x_spi_remove(struct spi_device *spi)
+static int ad193x_spi_remove(struct spi_device *spi)
{
snd_soc_unregister_codec(&spi->dev);
return 0;
@@ -409,7 +409,7 @@ static struct spi_driver ad193x_spi_driver = {
.owner = THIS_MODULE,
},
.probe = ad193x_spi_probe,
- .remove = __devexit_p(ad193x_spi_remove),
+ .remove = ad193x_spi_remove,
};
#endif
@@ -430,8 +430,8 @@ static const struct i2c_device_id ad193x_id[] = {
};
MODULE_DEVICE_TABLE(i2c, ad193x_id);
-static int __devinit ad193x_i2c_probe(struct i2c_client *client,
- const struct i2c_device_id *id)
+static int ad193x_i2c_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
{
struct ad193x_priv *ad193x;
@@ -450,7 +450,7 @@ static int __devinit ad193x_i2c_probe(struct i2c_client *client,
&ad193x_dai, 1);
}
-static int __devexit ad193x_i2c_remove(struct i2c_client *client)
+static int ad193x_i2c_remove(struct i2c_client *client)
{
snd_soc_unregister_codec(&client->dev);
return 0;
@@ -461,7 +461,7 @@ static struct i2c_driver ad193x_i2c_driver = {
.name = "ad193x",
},
.probe = ad193x_i2c_probe,
- .remove = __devexit_p(ad193x_i2c_remove),
+ .remove = ad193x_i2c_remove,
.id_table = ad193x_id,
};
#endif
diff --git a/sound/soc/codecs/ad1980.c b/sound/soc/codecs/ad1980.c
index 8c39dddd7d00..f385342947d3 100644
--- a/sound/soc/codecs/ad1980.c
+++ b/sound/soc/codecs/ad1980.c
@@ -255,13 +255,13 @@ static struct snd_soc_codec_driver soc_codec_dev_ad1980 = {
.read = ac97_read,
};
-static __devinit int ad1980_probe(struct platform_device *pdev)
+static int ad1980_probe(struct platform_device *pdev)
{
return snd_soc_register_codec(&pdev->dev,
&soc_codec_dev_ad1980, &ad1980_dai, 1);
}
-static int __devexit ad1980_remove(struct platform_device *pdev)
+static int ad1980_remove(struct platform_device *pdev)
{
snd_soc_unregister_codec(&pdev->dev);
return 0;
@@ -274,7 +274,7 @@ static struct platform_driver ad1980_codec_driver = {
},
.probe = ad1980_probe,
- .remove = __devexit_p(ad1980_remove),
+ .remove = ad1980_remove,
};
module_platform_driver(ad1980_codec_driver);
diff --git a/sound/soc/codecs/ad73311.c b/sound/soc/codecs/ad73311.c
index ee7a68dcefd2..b1f2baf42b48 100644
--- a/sound/soc/codecs/ad73311.c
+++ b/sound/soc/codecs/ad73311.c
@@ -47,7 +47,7 @@ static int ad73311_probe(struct platform_device *pdev)
&soc_codec_dev_ad73311, &ad73311_dai, 1);
}
-static int __devexit ad73311_remove(struct platform_device *pdev)
+static int ad73311_remove(struct platform_device *pdev)
{
snd_soc_unregister_codec(&pdev->dev);
return 0;
@@ -60,7 +60,7 @@ static struct platform_driver ad73311_codec_driver = {
},
.probe = ad73311_probe,
- .remove = __devexit_p(ad73311_remove),
+ .remove = ad73311_remove,
};
module_platform_driver(ad73311_codec_driver);
diff --git a/sound/soc/codecs/adau1373.c b/sound/soc/codecs/adau1373.c
index 704544bfc90d..068b3ae56a17 100644
--- a/sound/soc/codecs/adau1373.c
+++ b/sound/soc/codecs/adau1373.c
@@ -1353,8 +1353,8 @@ static struct snd_soc_codec_driver adau1373_codec_driver = {
.num_dapm_routes = ARRAY_SIZE(adau1373_dapm_routes),
};
-static int __devinit adau1373_i2c_probe(struct i2c_client *client,
- const struct i2c_device_id *id)
+static int adau1373_i2c_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
{
struct adau1373 *adau1373;
int ret;
@@ -1370,7 +1370,7 @@ static int __devinit adau1373_i2c_probe(struct i2c_client *client,
return ret;
}
-static int __devexit adau1373_i2c_remove(struct i2c_client *client)
+static int adau1373_i2c_remove(struct i2c_client *client)
{
snd_soc_unregister_codec(&client->dev);
return 0;
@@ -1388,7 +1388,7 @@ static struct i2c_driver adau1373_i2c_driver = {
.owner = THIS_MODULE,
},
.probe = adau1373_i2c_probe,
- .remove = __devexit_p(adau1373_i2c_remove),
+ .remove = adau1373_i2c_remove,
.id_table = adau1373_i2c_id,
};
diff --git a/sound/soc/codecs/adau1701.c b/sound/soc/codecs/adau1701.c
index 51f2f3cd8136..dafdbe87edeb 100644
--- a/sound/soc/codecs/adau1701.c
+++ b/sound/soc/codecs/adau1701.c
@@ -489,8 +489,8 @@ static struct snd_soc_codec_driver adau1701_codec_drv = {
.set_sysclk = adau1701_set_sysclk,
};
-static __devinit int adau1701_i2c_probe(struct i2c_client *client,
- const struct i2c_device_id *id)
+static int adau1701_i2c_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
{
struct adau1701 *adau1701;
int ret;
@@ -505,7 +505,7 @@ static __devinit int adau1701_i2c_probe(struct i2c_client *client,
return ret;
}
-static __devexit int adau1701_i2c_remove(struct i2c_client *client)
+static int adau1701_i2c_remove(struct i2c_client *client)
{
snd_soc_unregister_codec(&client->dev);
return 0;
@@ -523,7 +523,7 @@ static struct i2c_driver adau1701_i2c_driver = {
.owner = THIS_MODULE,
},
.probe = adau1701_i2c_probe,
- .remove = __devexit_p(adau1701_i2c_remove),
+ .remove = adau1701_i2c_remove,
.id_table = adau1701_i2c_id,
};
diff --git a/sound/soc/codecs/adav80x.c b/sound/soc/codecs/adav80x.c
index ebd7b37b902b..3c839cc4e00e 100644
--- a/sound/soc/codecs/adav80x.c
+++ b/sound/soc/codecs/adav80x.c
@@ -839,8 +839,8 @@ static struct snd_soc_codec_driver adav80x_codec_driver = {
.num_dapm_routes = ARRAY_SIZE(adav80x_dapm_routes),
};
-static int __devinit adav80x_bus_probe(struct device *dev,
- enum snd_soc_control_type control_type)
+static int adav80x_bus_probe(struct device *dev,
+ enum snd_soc_control_type control_type)
{
struct adav80x *adav80x;
int ret;
@@ -860,7 +860,7 @@ static int __devinit adav80x_bus_probe(struct device *dev,
return ret;
}
-static int __devexit adav80x_bus_remove(struct device *dev)
+static int adav80x_bus_remove(struct device *dev)
{
snd_soc_unregister_codec(dev);
kfree(dev_get_drvdata(dev));
@@ -868,12 +868,12 @@ static int __devexit adav80x_bus_remove(struct device *dev)
}
#if defined(CONFIG_SPI_MASTER)
-static int __devinit adav80x_spi_probe(struct spi_device *spi)
+static int adav80x_spi_probe(struct spi_device *spi)
{
return adav80x_bus_probe(&spi->dev, SND_SOC_SPI);
}
-static int __devexit adav80x_spi_remove(struct spi_device *spi)
+static int adav80x_spi_remove(struct spi_device *spi)
{
return adav80x_bus_remove(&spi->dev);
}
@@ -884,7 +884,7 @@ static struct spi_driver adav80x_spi_driver = {
.owner = THIS_MODULE,
},
.probe = adav80x_spi_probe,
- .remove = __devexit_p(adav80x_spi_remove),
+ .remove = adav80x_spi_remove,
};
#endif
@@ -895,13 +895,13 @@ static const struct i2c_device_id adav80x_id[] = {
};
MODULE_DEVICE_TABLE(i2c, adav80x_id);
-static int __devinit adav80x_i2c_probe(struct i2c_client *client,
- const struct i2c_device_id *id)
+static int adav80x_i2c_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
{
return adav80x_bus_probe(&client->dev, SND_SOC_I2C);
}
-static int __devexit adav80x_i2c_remove(struct i2c_client *client)
+static int adav80x_i2c_remove(struct i2c_client *client)
{
return adav80x_bus_remove(&client->dev);
}
@@ -912,7 +912,7 @@ static struct i2c_driver adav80x_i2c_driver = {
.owner = THIS_MODULE,
},
.probe = adav80x_i2c_probe,
- .remove = __devexit_p(adav80x_i2c_remove),
+ .remove = adav80x_i2c_remove,
.id_table = adav80x_id,
};
#endif
diff --git a/sound/soc/codecs/ads117x.c b/sound/soc/codecs/ads117x.c
index 8103b938b8c0..506d474c4d22 100644
--- a/sound/soc/codecs/ads117x.c
+++ b/sound/soc/codecs/ads117x.c
@@ -36,13 +36,13 @@ static struct snd_soc_dai_driver ads117x_dai = {
static struct snd_soc_codec_driver soc_codec_dev_ads117x;
-static __devinit int ads117x_probe(struct platform_device *pdev)
+static int ads117x_probe(struct platform_device *pdev)
{
return snd_soc_register_codec(&pdev->dev,
&soc_codec_dev_ads117x, &ads117x_dai, 1);
}
-static int __devexit ads117x_remove(struct platform_device *pdev)
+static int ads117x_remove(struct platform_device *pdev)
{
snd_soc_unregister_codec(&pdev->dev);
return 0;
@@ -55,7 +55,7 @@ static struct platform_driver ads117x_codec_driver = {
},
.probe = ads117x_probe,
- .remove = __devexit_p(ads117x_remove),
+ .remove = ads117x_remove,
};
module_platform_driver(ads117x_codec_driver);
diff --git a/sound/soc/codecs/ak4104.c b/sound/soc/codecs/ak4104.c
index 31d4483245d0..6f6c335a5baa 100644
--- a/sound/soc/codecs/ak4104.c
+++ b/sound/soc/codecs/ak4104.c
@@ -15,6 +15,8 @@
#include <sound/soc.h>
#include <sound/initval.h>
#include <linux/spi/spi.h>
+#include <linux/of_device.h>
+#include <linux/of_gpio.h>
#include <sound/asoundef.h>
/* AK4104 registers addresses */
@@ -98,14 +100,32 @@ static int ak4104_hw_params(struct snd_pcm_substream *substream,
val = 0;
switch (params_rate(params)) {
+ case 22050:
+ val |= IEC958_AES3_CON_FS_22050;
+ break;
+ case 24000:
+ val |= IEC958_AES3_CON_FS_24000;
+ break;
+ case 32000:
+ val |= IEC958_AES3_CON_FS_32000;
+ break;
case 44100:
val |= IEC958_AES3_CON_FS_44100;
break;
case 48000:
val |= IEC958_AES3_CON_FS_48000;
break;
- case 32000:
- val |= IEC958_AES3_CON_FS_32000;
+ case 88200:
+ val |= IEC958_AES3_CON_FS_88200;
+ break;
+ case 96000:
+ val |= IEC958_AES3_CON_FS_96000;
+ break;
+ case 176400:
+ val |= IEC958_AES3_CON_FS_176400;
+ break;
+ case 192000:
+ val |= IEC958_AES3_CON_FS_192000;
break;
default:
dev_err(codec->dev, "unsupported sampling rate\n");
@@ -186,6 +206,7 @@ static const struct regmap_config ak4104_regmap = {
static int ak4104_spi_probe(struct spi_device *spi)
{
+ struct device_node *np = spi->dev.of_node;
struct ak4104_private *ak4104;
unsigned int val;
int ret;
@@ -201,52 +222,62 @@ static int ak4104_spi_probe(struct spi_device *spi)
if (ak4104 == NULL)
return -ENOMEM;
- ak4104->regmap = regmap_init_spi(spi, &ak4104_regmap);
+ ak4104->regmap = devm_regmap_init_spi(spi, &ak4104_regmap);
if (IS_ERR(ak4104->regmap)) {
ret = PTR_ERR(ak4104->regmap);
return ret;
}
+ if (np) {
+ enum of_gpio_flags flags;
+ int gpio = of_get_named_gpio_flags(np, "reset-gpio", 0, &flags);
+
+ if (gpio_is_valid(gpio)) {
+ ret = devm_gpio_request_one(&spi->dev, gpio,
+ flags & OF_GPIO_ACTIVE_LOW ?
+ GPIOF_OUT_INIT_LOW : GPIOF_OUT_INIT_HIGH,
+ "ak4104 reset");
+ if (ret < 0)
+ return ret;
+ }
+ }
+
/* read the 'reserved' register - according to the datasheet, it
* should contain 0x5b. Not a good way to verify the presence of
* the device, but there is no hardware ID register. */
ret = regmap_read(ak4104->regmap, AK4104_REG_RESERVED, &val);
if (ret != 0)
- goto err;
- if (val != AK4104_RESERVED_VAL) {
- ret = -ENODEV;
- goto err;
- }
+ return ret;
+ if (val != AK4104_RESERVED_VAL)
+ return -ENODEV;
spi_set_drvdata(spi, ak4104);
ret = snd_soc_register_codec(&spi->dev,
&soc_codec_device_ak4104, &ak4104_dai, 1);
- if (ret != 0)
- goto err;
-
- return 0;
-
-err:
- regmap_exit(ak4104->regmap);
return ret;
}
-static int __devexit ak4104_spi_remove(struct spi_device *spi)
+static int ak4104_spi_remove(struct spi_device *spi)
{
- struct ak4104_private *ak4101 = spi_get_drvdata(spi);
- regmap_exit(ak4101->regmap);
snd_soc_unregister_codec(&spi->dev);
return 0;
}
+static const struct of_device_id ak4104_of_match[] = {
+ { .compatible = "asahi-kasei,ak4104", },
+ { }
+};
+MODULE_DEVICE_TABLE(of, ak4104_of_match);
+
static struct spi_driver ak4104_spi_driver = {
.driver = {
.name = DRV_NAME,
.owner = THIS_MODULE,
+ .of_match_table = ak4104_of_match,
},
.probe = ak4104_spi_probe,
- .remove = __devexit_p(ak4104_spi_remove),
+ .remove = ak4104_spi_remove,
};
module_spi_driver(ak4104_spi_driver);
diff --git a/sound/soc/codecs/ak4535.c b/sound/soc/codecs/ak4535.c
index 618fdc30f73e..684fe910669f 100644
--- a/sound/soc/codecs/ak4535.c
+++ b/sound/soc/codecs/ak4535.c
@@ -436,8 +436,8 @@ static struct snd_soc_codec_driver soc_codec_dev_ak4535 = {
.num_dapm_routes = ARRAY_SIZE(ak4535_audio_map),
};
-static __devinit int ak4535_i2c_probe(struct i2c_client *i2c,
- const struct i2c_device_id *id)
+static int ak4535_i2c_probe(struct i2c_client *i2c,
+ const struct i2c_device_id *id)
{
struct ak4535_priv *ak4535;
int ret;
@@ -447,7 +447,7 @@ static __devinit int ak4535_i2c_probe(struct i2c_client *i2c,
if (ak4535 == NULL)
return -ENOMEM;
- ak4535->regmap = regmap_init_i2c(i2c, &ak4535_regmap);
+ ak4535->regmap = devm_regmap_init_i2c(i2c, &ak4535_regmap);
if (IS_ERR(ak4535->regmap)) {
ret = PTR_ERR(ak4535->regmap);
dev_err(&i2c->dev, "Failed to init regmap: %d\n", ret);
@@ -458,18 +458,13 @@ static __devinit int ak4535_i2c_probe(struct i2c_client *i2c,
ret = snd_soc_register_codec(&i2c->dev,
&soc_codec_dev_ak4535, &ak4535_dai, 1);
- if (ret != 0)
- regmap_exit(ak4535->regmap);
return ret;
}
-static __devexit int ak4535_i2c_remove(struct i2c_client *client)
+static int ak4535_i2c_remove(struct i2c_client *client)
{
- struct ak4535_priv *ak4535 = i2c_get_clientdata(client);
-
snd_soc_unregister_codec(&client->dev);
- regmap_exit(ak4535->regmap);
return 0;
}
@@ -485,7 +480,7 @@ static struct i2c_driver ak4535_i2c_driver = {
.owner = THIS_MODULE,
},
.probe = ak4535_i2c_probe,
- .remove = __devexit_p(ak4535_i2c_remove),
+ .remove = ak4535_i2c_remove,
.id_table = ak4535_i2c_id,
};
diff --git a/sound/soc/codecs/ak4641.c b/sound/soc/codecs/ak4641.c
index 543a12f471be..5f9af1fb76e8 100644
--- a/sound/soc/codecs/ak4641.c
+++ b/sound/soc/codecs/ak4641.c
@@ -557,8 +557,8 @@ static struct snd_soc_codec_driver soc_codec_dev_ak4641 = {
};
-static int __devinit ak4641_i2c_probe(struct i2c_client *i2c,
- const struct i2c_device_id *id)
+static int ak4641_i2c_probe(struct i2c_client *i2c,
+ const struct i2c_device_id *id)
{
struct ak4641_platform_data *pdata = i2c->dev.platform_data;
struct ak4641_priv *ak4641;
@@ -610,7 +610,7 @@ err_out:
return ret;
}
-static int __devexit ak4641_i2c_remove(struct i2c_client *i2c)
+static int ak4641_i2c_remove(struct i2c_client *i2c)
{
struct ak4641_platform_data *pdata = i2c->dev.platform_data;
@@ -640,7 +640,7 @@ static struct i2c_driver ak4641_i2c_driver = {
.owner = THIS_MODULE,
},
.probe = ak4641_i2c_probe,
- .remove = __devexit_p(ak4641_i2c_remove),
+ .remove = ak4641_i2c_remove,
.id_table = ak4641_i2c_id,
};
diff --git a/sound/soc/codecs/ak4642.c b/sound/soc/codecs/ak4642.c
index b3e24f289421..1f0cdab03294 100644
--- a/sound/soc/codecs/ak4642.c
+++ b/sound/soc/codecs/ak4642.c
@@ -194,12 +194,6 @@ static const struct snd_soc_dapm_route ak4642_intercon[] = {
{"LINEOUT Mixer", "DACL", "DAC"},
};
-/* codec private data */
-struct ak4642_priv {
- unsigned int sysclk;
- enum snd_soc_control_type control_type;
-};
-
/*
* ak4642 register cache
*/
@@ -468,10 +462,9 @@ static int ak4642_resume(struct snd_soc_codec *codec)
static int ak4642_probe(struct snd_soc_codec *codec)
{
- struct ak4642_priv *ak4642 = snd_soc_codec_get_drvdata(codec);
int ret;
- ret = snd_soc_codec_set_cache_io(codec, 8, 8, ak4642->control_type);
+ ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_I2C);
if (ret < 0) {
dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
return ret;
@@ -520,27 +513,15 @@ static struct snd_soc_codec_driver soc_codec_dev_ak4648 = {
};
#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
-static __devinit int ak4642_i2c_probe(struct i2c_client *i2c,
- const struct i2c_device_id *id)
+static int ak4642_i2c_probe(struct i2c_client *i2c,
+ const struct i2c_device_id *id)
{
- struct ak4642_priv *ak4642;
- int ret;
-
- ak4642 = devm_kzalloc(&i2c->dev, sizeof(struct ak4642_priv),
- GFP_KERNEL);
- if (!ak4642)
- return -ENOMEM;
-
- i2c_set_clientdata(i2c, ak4642);
- ak4642->control_type = SND_SOC_I2C;
-
- ret = snd_soc_register_codec(&i2c->dev,
+ return snd_soc_register_codec(&i2c->dev,
(struct snd_soc_codec_driver *)id->driver_data,
&ak4642_dai, 1);
- return ret;
}
-static __devexit int ak4642_i2c_remove(struct i2c_client *client)
+static int ak4642_i2c_remove(struct i2c_client *client)
{
snd_soc_unregister_codec(&client->dev);
return 0;
@@ -560,7 +541,7 @@ static struct i2c_driver ak4642_i2c_driver = {
.owner = THIS_MODULE,
},
.probe = ak4642_i2c_probe,
- .remove = __devexit_p(ak4642_i2c_remove),
+ .remove = ak4642_i2c_remove,
.id_table = ak4642_i2c_id,
};
#endif
diff --git a/sound/soc/codecs/ak4671.c b/sound/soc/codecs/ak4671.c
index 2b457976a7bf..25bdf6ad4a54 100644
--- a/sound/soc/codecs/ak4671.c
+++ b/sound/soc/codecs/ak4671.c
@@ -655,8 +655,8 @@ static struct snd_soc_codec_driver soc_codec_dev_ak4671 = {
.num_dapm_routes = ARRAY_SIZE(ak4671_intercon),
};
-static int __devinit ak4671_i2c_probe(struct i2c_client *client,
- const struct i2c_device_id *id)
+static int ak4671_i2c_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
{
struct ak4671_priv *ak4671;
int ret;
@@ -674,7 +674,7 @@ static int __devinit ak4671_i2c_probe(struct i2c_client *client,
return ret;
}
-static __devexit int ak4671_i2c_remove(struct i2c_client *client)
+static int ak4671_i2c_remove(struct i2c_client *client)
{
snd_soc_unregister_codec(&client->dev);
return 0;
@@ -692,7 +692,7 @@ static struct i2c_driver ak4671_i2c_driver = {
.owner = THIS_MODULE,
},
.probe = ak4671_i2c_probe,
- .remove = __devexit_p(ak4671_i2c_remove),
+ .remove = ak4671_i2c_remove,
.id_table = ak4671_i2c_id,
};
diff --git a/sound/soc/codecs/alc5623.c b/sound/soc/codecs/alc5623.c
index 1960478ce6bb..256c364193a5 100644
--- a/sound/soc/codecs/alc5623.c
+++ b/sound/soc/codecs/alc5623.c
@@ -991,8 +991,8 @@ static struct snd_soc_codec_driver soc_codec_device_alc5623 = {
* low = 0x1a
* high = 0x1b
*/
-static __devinit int alc5623_i2c_probe(struct i2c_client *client,
- const struct i2c_device_id *id)
+static int alc5623_i2c_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
{
struct alc5623_platform_data *pdata;
struct alc5623_priv *alc5623;
@@ -1058,7 +1058,7 @@ static __devinit int alc5623_i2c_probe(struct i2c_client *client,
return ret;
}
-static __devexit int alc5623_i2c_remove(struct i2c_client *client)
+static int alc5623_i2c_remove(struct i2c_client *client)
{
snd_soc_unregister_codec(&client->dev);
return 0;
@@ -1079,7 +1079,7 @@ static struct i2c_driver alc5623_i2c_driver = {
.owner = THIS_MODULE,
},
.probe = alc5623_i2c_probe,
- .remove = __devexit_p(alc5623_i2c_remove),
+ .remove = alc5623_i2c_remove,
.id_table = alc5623_i2c_table,
};
diff --git a/sound/soc/codecs/alc5632.c b/sound/soc/codecs/alc5632.c
index 7dd02420b36d..f2e62e45f912 100644
--- a/sound/soc/codecs/alc5632.c
+++ b/sound/soc/codecs/alc5632.c
@@ -1116,8 +1116,8 @@ static struct regmap_config alc5632_regmap = {
* low = 0x1a
* high = 0x1b
*/
-static __devinit int alc5632_i2c_probe(struct i2c_client *client,
- const struct i2c_device_id *id)
+static int alc5632_i2c_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
{
struct alc5632_priv *alc5632;
int ret, ret1, ret2;
@@ -1179,7 +1179,7 @@ static __devinit int alc5632_i2c_probe(struct i2c_client *client,
return ret;
}
-static __devexit int alc5632_i2c_remove(struct i2c_client *client)
+static int alc5632_i2c_remove(struct i2c_client *client)
{
snd_soc_unregister_codec(&client->dev);
return 0;
@@ -1198,7 +1198,7 @@ static struct i2c_driver alc5632_i2c_driver = {
.owner = THIS_MODULE,
},
.probe = alc5632_i2c_probe,
- .remove = __devexit_p(alc5632_i2c_remove),
+ .remove = alc5632_i2c_remove,
.id_table = alc5632_i2c_table,
};
diff --git a/sound/soc/codecs/arizona.c b/sound/soc/codecs/arizona.c
index 054967d8bac2..adf397b9d0e6 100644
--- a/sound/soc/codecs/arizona.c
+++ b/sound/soc/codecs/arizona.c
@@ -226,6 +226,31 @@ EXPORT_SYMBOL_GPL(arizona_mixer_values);
const DECLARE_TLV_DB_SCALE(arizona_mixer_tlv, -3200, 100, 0);
EXPORT_SYMBOL_GPL(arizona_mixer_tlv);
+static const char *arizona_vol_ramp_text[] = {
+ "0ms/6dB", "0.5ms/6dB", "1ms/6dB", "2ms/6dB", "4ms/6dB", "8ms/6dB",
+ "15ms/6dB", "30ms/6dB",
+};
+
+const struct soc_enum arizona_in_vd_ramp =
+ SOC_ENUM_SINGLE(ARIZONA_INPUT_VOLUME_RAMP,
+ ARIZONA_IN_VD_RAMP_SHIFT, 7, arizona_vol_ramp_text);
+EXPORT_SYMBOL_GPL(arizona_in_vd_ramp);
+
+const struct soc_enum arizona_in_vi_ramp =
+ SOC_ENUM_SINGLE(ARIZONA_INPUT_VOLUME_RAMP,
+ ARIZONA_IN_VI_RAMP_SHIFT, 7, arizona_vol_ramp_text);
+EXPORT_SYMBOL_GPL(arizona_in_vi_ramp);
+
+const struct soc_enum arizona_out_vd_ramp =
+ SOC_ENUM_SINGLE(ARIZONA_OUTPUT_VOLUME_RAMP,
+ ARIZONA_OUT_VD_RAMP_SHIFT, 7, arizona_vol_ramp_text);
+EXPORT_SYMBOL_GPL(arizona_out_vd_ramp);
+
+const struct soc_enum arizona_out_vi_ramp =
+ SOC_ENUM_SINGLE(ARIZONA_OUTPUT_VOLUME_RAMP,
+ ARIZONA_OUT_VI_RAMP_SHIFT, 7, arizona_vol_ramp_text);
+EXPORT_SYMBOL_GPL(arizona_out_vi_ramp);
+
static const char *arizona_lhpf_mode_text[] = {
"Low-pass", "High-pass"
};
@@ -380,6 +405,18 @@ int arizona_set_sysclk(struct snd_soc_codec *codec, int clk_id,
case 49152000:
val |= 3 << ARIZONA_SYSCLK_FREQ_SHIFT;
break;
+ case 67737600:
+ case 73728000:
+ val |= 4 << ARIZONA_SYSCLK_FREQ_SHIFT;
+ break;
+ case 90316800:
+ case 98304000:
+ val |= 5 << ARIZONA_SYSCLK_FREQ_SHIFT;
+ break;
+ case 135475200:
+ case 147456000:
+ val |= 6 << ARIZONA_SYSCLK_FREQ_SHIFT;
+ break;
default:
return -EINVAL;
}
@@ -737,6 +774,9 @@ static int arizona_dai_set_sysclk(struct snd_soc_dai *dai,
return -EBUSY;
}
+ dev_dbg(codec->dev, "Setting AIF%d to %s\n", dai->id + 1,
+ arizona_dai_clk_str(clk_id));
+
memset(&routes, 0, sizeof(routes));
routes[0].sink = dai->driver->capture.stream_name;
routes[1].sink = dai->driver->playback.stream_name;
@@ -749,6 +789,8 @@ static int arizona_dai_set_sysclk(struct snd_soc_dai *dai,
routes[1].source = arizona_dai_clk_str(clk_id);
snd_soc_dapm_add_routes(&codec->dapm, routes, ARRAY_SIZE(routes));
+ dai_priv->clk = clk_id;
+
return snd_soc_dapm_sync(&codec->dapm);
}
@@ -925,6 +967,9 @@ int arizona_set_fll(struct arizona_fll *fll, int source,
bool ena;
int ret;
+ if (fll->fref == Fref && fll->fout == Fout)
+ return 0;
+
ret = regmap_read(arizona->regmap, fll->base + 1, &reg);
if (ret != 0) {
arizona_fll_err(fll, "Failed to read current state: %d\n",
@@ -970,6 +1015,9 @@ int arizona_set_fll(struct arizona_fll *fll, int source,
if (ena)
pm_runtime_put_autosuspend(arizona->dev);
+ fll->fref = Fref;
+ fll->fout = Fout;
+
return 0;
}
@@ -998,10 +1046,13 @@ int arizona_set_fll(struct arizona_fll *fll, int source,
ARIZONA_FLL1_SYNC_ENA);
ret = wait_for_completion_timeout(&fll->ok,
- msecs_to_jiffies(25));
+ msecs_to_jiffies(250));
if (ret == 0)
arizona_fll_warn(fll, "Timed out waiting for lock\n");
+ fll->fref = Fref;
+ fll->fout = Fout;
+
return 0;
}
EXPORT_SYMBOL_GPL(arizona_set_fll);
diff --git a/sound/soc/codecs/arizona.h b/sound/soc/codecs/arizona.h
index 36ec64946120..41dae1ed3b71 100644
--- a/sound/soc/codecs/arizona.h
+++ b/sound/soc/codecs/arizona.h
@@ -17,6 +17,8 @@
#include <sound/soc.h>
+#include "wm_adsp.h"
+
#define ARIZONA_CLK_SYSCLK 1
#define ARIZONA_CLK_ASYNCCLK 2
#define ARIZONA_CLK_OPCLK 3
@@ -46,15 +48,18 @@
#define ARIZONA_MIXER_VOL_SHIFT 1
#define ARIZONA_MIXER_VOL_WIDTH 7
-#define ARIZONA_MAX_DAI 3
+#define ARIZONA_MAX_DAI 4
+#define ARIZONA_MAX_ADSP 4
struct arizona;
+struct wm_adsp;
struct arizona_dai_priv {
int clk;
};
struct arizona_priv {
+ struct wm_adsp adsp[ARIZONA_MAX_ADSP];
struct arizona *arizona;
int sysclk;
int asyncclk;
@@ -89,19 +94,30 @@ extern int arizona_mixer_values[ARIZONA_NUM_MIXER_INPUTS];
const struct snd_kcontrol_new name##_mux = \
SOC_DAPM_VALUE_ENUM("Route", name##_enum)
+#define ARIZONA_MUX_ENUMS(name, base_reg) \
+ static ARIZONA_MUX_ENUM_DECL(name##_enum, base_reg); \
+ static ARIZONA_MUX_CTL_DECL(name)
+
#define ARIZONA_MIXER_ENUMS(name, base_reg) \
- static ARIZONA_MUX_ENUM_DECL(name##_in1_enum, base_reg); \
- static ARIZONA_MUX_ENUM_DECL(name##_in2_enum, base_reg + 2); \
- static ARIZONA_MUX_ENUM_DECL(name##_in3_enum, base_reg + 4); \
- static ARIZONA_MUX_ENUM_DECL(name##_in4_enum, base_reg + 6); \
- static ARIZONA_MUX_CTL_DECL(name##_in1); \
- static ARIZONA_MUX_CTL_DECL(name##_in2); \
- static ARIZONA_MUX_CTL_DECL(name##_in3); \
- static ARIZONA_MUX_CTL_DECL(name##_in4)
+ ARIZONA_MUX_ENUMS(name##_in1, base_reg); \
+ ARIZONA_MUX_ENUMS(name##_in2, base_reg + 2); \
+ ARIZONA_MUX_ENUMS(name##_in3, base_reg + 4); \
+ ARIZONA_MUX_ENUMS(name##_in4, base_reg + 6)
+
+#define ARIZONA_DSP_AUX_ENUMS(name, base_reg) \
+ ARIZONA_MUX_ENUMS(name##_aux1, base_reg); \
+ ARIZONA_MUX_ENUMS(name##_aux2, base_reg + 8); \
+ ARIZONA_MUX_ENUMS(name##_aux3, base_reg + 16); \
+ ARIZONA_MUX_ENUMS(name##_aux4, base_reg + 24); \
+ ARIZONA_MUX_ENUMS(name##_aux5, base_reg + 32); \
+ ARIZONA_MUX_ENUMS(name##_aux6, base_reg + 40)
#define ARIZONA_MUX(name, ctrl) \
SND_SOC_DAPM_VALUE_MUX(name, SND_SOC_NOPM, 0, 0, ctrl)
+#define ARIZONA_MUX_WIDGETS(name, name_str) \
+ ARIZONA_MUX(name_str " Input", &name##_mux)
+
#define ARIZONA_MIXER_WIDGETS(name, name_str) \
ARIZONA_MUX(name_str " Input 1", &name##_in1_mux), \
ARIZONA_MUX(name_str " Input 2", &name##_in2_mux), \
@@ -109,6 +125,19 @@ extern int arizona_mixer_values[ARIZONA_NUM_MIXER_INPUTS];
ARIZONA_MUX(name_str " Input 4", &name##_in4_mux), \
SND_SOC_DAPM_MIXER(name_str " Mixer", SND_SOC_NOPM, 0, 0, NULL, 0)
+#define ARIZONA_DSP_WIDGETS(name, name_str) \
+ ARIZONA_MIXER_WIDGETS(name##L, name_str "L"), \
+ ARIZONA_MIXER_WIDGETS(name##R, name_str "R"), \
+ ARIZONA_MUX(name_str " Aux 1", &name##_aux1_mux), \
+ ARIZONA_MUX(name_str " Aux 2", &name##_aux2_mux), \
+ ARIZONA_MUX(name_str " Aux 3", &name##_aux3_mux), \
+ ARIZONA_MUX(name_str " Aux 4", &name##_aux4_mux), \
+ ARIZONA_MUX(name_str " Aux 5", &name##_aux5_mux), \
+ ARIZONA_MUX(name_str " Aux 6", &name##_aux6_mux)
+
+#define ARIZONA_MUX_ROUTES(name) \
+ ARIZONA_MIXER_INPUT_ROUTES(name " Input")
+
#define ARIZONA_MIXER_ROUTES(widget, name) \
{ widget, NULL, name " Mixer" }, \
{ name " Mixer", NULL, name " Input 1" }, \
@@ -120,6 +149,28 @@ extern int arizona_mixer_values[ARIZONA_NUM_MIXER_INPUTS];
ARIZONA_MIXER_INPUT_ROUTES(name " Input 3"), \
ARIZONA_MIXER_INPUT_ROUTES(name " Input 4")
+#define ARIZONA_DSP_ROUTES(name) \
+ { name, NULL, name " Aux 1" }, \
+ { name, NULL, name " Aux 2" }, \
+ { name, NULL, name " Aux 3" }, \
+ { name, NULL, name " Aux 4" }, \
+ { name, NULL, name " Aux 5" }, \
+ { name, NULL, name " Aux 6" }, \
+ ARIZONA_MIXER_INPUT_ROUTES(name " Aux 1"), \
+ ARIZONA_MIXER_INPUT_ROUTES(name " Aux 2"), \
+ ARIZONA_MIXER_INPUT_ROUTES(name " Aux 3"), \
+ ARIZONA_MIXER_INPUT_ROUTES(name " Aux 4"), \
+ ARIZONA_MIXER_INPUT_ROUTES(name " Aux 5"), \
+ ARIZONA_MIXER_INPUT_ROUTES(name " Aux 6"), \
+ ARIZONA_MIXER_ROUTES(name, name "L"), \
+ ARIZONA_MIXER_ROUTES(name, name "R")
+
+extern const struct soc_enum arizona_in_vi_ramp;
+extern const struct soc_enum arizona_in_vd_ramp;
+
+extern const struct soc_enum arizona_out_vi_ramp;
+extern const struct soc_enum arizona_out_vd_ramp;
+
extern const struct soc_enum arizona_lhpf1_mode;
extern const struct soc_enum arizona_lhpf2_mode;
extern const struct soc_enum arizona_lhpf3_mode;
@@ -146,6 +197,8 @@ struct arizona_fll {
unsigned int vco_mult;
struct completion lock;
struct completion ok;
+ unsigned int fref;
+ unsigned int fout;
char lock_name[ARIZONA_FLL_NAME_LEN];
char clock_ok_name[ARIZONA_FLL_NAME_LEN];
diff --git a/sound/soc/codecs/cq93vc.c b/sound/soc/codecs/cq93vc.c
index 064cd6a93516..23316c887b19 100644
--- a/sound/soc/codecs/cq93vc.c
+++ b/sound/soc/codecs/cq93vc.c
@@ -201,7 +201,7 @@ static struct platform_driver cq93vc_codec_driver = {
},
.probe = cq93vc_platform_probe,
- .remove = __devexit_p(cq93vc_platform_remove),
+ .remove = cq93vc_platform_remove,
};
module_platform_driver(cq93vc_codec_driver);
diff --git a/sound/soc/codecs/cs4271.c b/sound/soc/codecs/cs4271.c
index e3f0a7f3131e..4f1127935fdf 100644
--- a/sound/soc/codecs/cs4271.c
+++ b/sound/soc/codecs/cs4271.c
@@ -474,15 +474,25 @@ static int cs4271_probe(struct snd_soc_codec *codec)
struct cs4271_platform_data *cs4271plat = codec->dev->platform_data;
int ret;
int gpio_nreset = -EINVAL;
+ int amutec_eq_bmutec = 0;
#ifdef CONFIG_OF
- if (of_match_device(cs4271_dt_ids, codec->dev))
+ if (of_match_device(cs4271_dt_ids, codec->dev)) {
gpio_nreset = of_get_named_gpio(codec->dev->of_node,
"reset-gpio", 0);
+
+ if (!of_get_property(codec->dev->of_node,
+ "cirrus,amutec-eq-bmutec", NULL))
+ amutec_eq_bmutec = 1;
+ }
#endif
- if (cs4271plat && gpio_is_valid(cs4271plat->gpio_nreset))
- gpio_nreset = cs4271plat->gpio_nreset;
+ if (cs4271plat) {
+ if (gpio_is_valid(cs4271plat->gpio_nreset))
+ gpio_nreset = cs4271plat->gpio_nreset;
+
+ amutec_eq_bmutec = cs4271plat->amutec_eq_bmutec;
+ }
if (gpio_nreset >= 0)
if (devm_gpio_request(codec->dev, gpio_nreset, "CS4271 Reset"))
@@ -528,6 +538,11 @@ static int cs4271_probe(struct snd_soc_codec *codec)
/* Power-up sequence requires 85 uS */
udelay(85);
+ if (amutec_eq_bmutec)
+ snd_soc_update_bits(codec, CS4271_MODE2,
+ CS4271_MODE2_MUTECAEQUB,
+ CS4271_MODE2_MUTECAEQUB);
+
return snd_soc_add_codec_controls(codec, cs4271_snd_controls,
ARRAY_SIZE(cs4271_snd_controls));
}
@@ -555,7 +570,7 @@ static struct snd_soc_codec_driver soc_codec_dev_cs4271 = {
};
#if defined(CONFIG_SPI_MASTER)
-static int __devinit cs4271_spi_probe(struct spi_device *spi)
+static int cs4271_spi_probe(struct spi_device *spi)
{
struct cs4271_private *cs4271;
@@ -570,7 +585,7 @@ static int __devinit cs4271_spi_probe(struct spi_device *spi)
&cs4271_dai, 1);
}
-static int __devexit cs4271_spi_remove(struct spi_device *spi)
+static int cs4271_spi_remove(struct spi_device *spi)
{
snd_soc_unregister_codec(&spi->dev);
return 0;
@@ -583,7 +598,7 @@ static struct spi_driver cs4271_spi_driver = {
.of_match_table = of_match_ptr(cs4271_dt_ids),
},
.probe = cs4271_spi_probe,
- .remove = __devexit_p(cs4271_spi_remove),
+ .remove = cs4271_spi_remove,
};
#endif /* defined(CONFIG_SPI_MASTER) */
@@ -594,8 +609,8 @@ static const struct i2c_device_id cs4271_i2c_id[] = {
};
MODULE_DEVICE_TABLE(i2c, cs4271_i2c_id);
-static int __devinit cs4271_i2c_probe(struct i2c_client *client,
- const struct i2c_device_id *id)
+static int cs4271_i2c_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
{
struct cs4271_private *cs4271;
@@ -610,7 +625,7 @@ static int __devinit cs4271_i2c_probe(struct i2c_client *client,
&cs4271_dai, 1);
}
-static int __devexit cs4271_i2c_remove(struct i2c_client *client)
+static int cs4271_i2c_remove(struct i2c_client *client)
{
snd_soc_unregister_codec(&client->dev);
return 0;
@@ -624,7 +639,7 @@ static struct i2c_driver cs4271_i2c_driver = {
},
.id_table = cs4271_i2c_id,
.probe = cs4271_i2c_probe,
- .remove = __devexit_p(cs4271_i2c_remove),
+ .remove = cs4271_i2c_remove,
};
#endif /* defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) */
diff --git a/sound/soc/codecs/cs42l52.c b/sound/soc/codecs/cs42l52.c
index 97a81051e88d..99bb1c69499e 100644
--- a/sound/soc/codecs/cs42l52.c
+++ b/sound/soc/codecs/cs42l52.c
@@ -1271,7 +1271,7 @@ static struct i2c_driver cs42l52_i2c_driver = {
},
.id_table = cs42l52_id,
.probe = cs42l52_i2c_probe,
- .remove = __devexit_p(cs42l52_i2c_remove),
+ .remove = cs42l52_i2c_remove,
};
module_i2c_driver(cs42l52_i2c_driver);
diff --git a/sound/soc/codecs/cs42l73.c b/sound/soc/codecs/cs42l73.c
index 2c08c4cb465a..a0791ecf6d95 100644
--- a/sound/soc/codecs/cs42l73.c
+++ b/sound/soc/codecs/cs42l73.c
@@ -1345,8 +1345,8 @@ static struct regmap_config cs42l73_regmap = {
.cache_type = REGCACHE_RBTREE,
};
-static __devinit int cs42l73_i2c_probe(struct i2c_client *i2c_client,
- const struct i2c_device_id *id)
+static int cs42l73_i2c_probe(struct i2c_client *i2c_client,
+ const struct i2c_device_id *id)
{
struct cs42l73_private *cs42l73;
int ret;
@@ -1406,7 +1406,7 @@ static __devinit int cs42l73_i2c_probe(struct i2c_client *i2c_client,
return 0;
}
-static __devexit int cs42l73_i2c_remove(struct i2c_client *client)
+static int cs42l73_i2c_remove(struct i2c_client *client)
{
snd_soc_unregister_codec(&client->dev);
return 0;
@@ -1426,7 +1426,7 @@ static struct i2c_driver cs42l73_i2c_driver = {
},
.id_table = cs42l73_id,
.probe = cs42l73_i2c_probe,
- .remove = __devexit_p(cs42l73_i2c_remove),
+ .remove = cs42l73_i2c_remove,
};
diff --git a/sound/soc/codecs/da7210.c b/sound/soc/codecs/da7210.c
index af5db7080519..9c1231456502 100644
--- a/sound/soc/codecs/da7210.c
+++ b/sound/soc/codecs/da7210.c
@@ -1218,8 +1218,8 @@ static const struct regmap_config da7210_regmap_config_i2c = {
.cache_type = REGCACHE_RBTREE,
};
-static int __devinit da7210_i2c_probe(struct i2c_client *i2c,
- const struct i2c_device_id *id)
+static int da7210_i2c_probe(struct i2c_client *i2c,
+ const struct i2c_device_id *id)
{
struct da7210_priv *da7210;
int ret;
@@ -1231,7 +1231,7 @@ static int __devinit da7210_i2c_probe(struct i2c_client *i2c,
i2c_set_clientdata(i2c, da7210);
- da7210->regmap = regmap_init_i2c(i2c, &da7210_regmap_config_i2c);
+ da7210->regmap = devm_regmap_init_i2c(i2c, &da7210_regmap_config_i2c);
if (IS_ERR(da7210->regmap)) {
ret = PTR_ERR(da7210->regmap);
dev_err(&i2c->dev, "regmap_init() failed: %d\n", ret);
@@ -1245,24 +1245,15 @@ static int __devinit da7210_i2c_probe(struct i2c_client *i2c,
ret = snd_soc_register_codec(&i2c->dev,
&soc_codec_dev_da7210, &da7210_dai, 1);
- if (ret < 0) {
+ if (ret < 0)
dev_err(&i2c->dev, "Failed to register codec: %d\n", ret);
- goto err_regmap;
- }
- return ret;
-
-err_regmap:
- regmap_exit(da7210->regmap);
return ret;
}
-static int __devexit da7210_i2c_remove(struct i2c_client *client)
+static int da7210_i2c_remove(struct i2c_client *client)
{
- struct da7210_priv *da7210 = i2c_get_clientdata(client);
-
snd_soc_unregister_codec(&client->dev);
- regmap_exit(da7210->regmap);
return 0;
}
@@ -1279,7 +1270,7 @@ static struct i2c_driver da7210_i2c_driver = {
.owner = THIS_MODULE,
},
.probe = da7210_i2c_probe,
- .remove = __devexit_p(da7210_i2c_remove),
+ .remove = da7210_i2c_remove,
.id_table = da7210_i2c_id,
};
#endif
@@ -1323,7 +1314,7 @@ static const struct regmap_config da7210_regmap_config_spi = {
.cache_type = REGCACHE_RBTREE,
};
-static int __devinit da7210_spi_probe(struct spi_device *spi)
+static int da7210_spi_probe(struct spi_device *spi)
{
struct da7210_priv *da7210;
int ret;
@@ -1346,24 +1337,15 @@ static int __devinit da7210_spi_probe(struct spi_device *spi)
if (ret != 0)
dev_warn(&spi->dev, "Failed to apply regmap patch: %d\n", ret);
- ret = snd_soc_register_codec(&spi->dev,
+ ret = snd_soc_register_codec(&spi->dev,
&soc_codec_dev_da7210, &da7210_dai, 1);
- if (ret < 0)
- goto err_regmap;
-
- return ret;
-
-err_regmap:
- regmap_exit(da7210->regmap);
return ret;
}
-static int __devexit da7210_spi_remove(struct spi_device *spi)
+static int da7210_spi_remove(struct spi_device *spi)
{
- struct da7210_priv *da7210 = spi_get_drvdata(spi);
snd_soc_unregister_codec(&spi->dev);
- regmap_exit(da7210->regmap);
return 0;
}
@@ -1373,7 +1355,7 @@ static struct spi_driver da7210_spi_driver = {
.owner = THIS_MODULE,
},
.probe = da7210_spi_probe,
- .remove = __devexit_p(da7210_spi_remove)
+ .remove = da7210_spi_remove
};
#endif
diff --git a/sound/soc/codecs/da732x.c b/sound/soc/codecs/da732x.c
index 01be2a320e21..dc0284dc9e6f 100644
--- a/sound/soc/codecs/da732x.c
+++ b/sound/soc/codecs/da732x.c
@@ -1557,8 +1557,8 @@ static struct snd_soc_codec_driver soc_codec_dev_da732x = {
.reg_cache_size = ARRAY_SIZE(da732x_reg_cache),
};
-static __devinit int da732x_i2c_probe(struct i2c_client *i2c,
- const struct i2c_device_id *id)
+static int da732x_i2c_probe(struct i2c_client *i2c,
+ const struct i2c_device_id *id)
{
struct da732x_priv *da732x;
unsigned int reg;
@@ -1596,7 +1596,7 @@ err:
return ret;
}
-static __devexit int da732x_i2c_remove(struct i2c_client *client)
+static int da732x_i2c_remove(struct i2c_client *client)
{
snd_soc_unregister_codec(&client->dev);
@@ -1615,7 +1615,7 @@ static struct i2c_driver da732x_i2c_driver = {
.owner = THIS_MODULE,
},
.probe = da732x_i2c_probe,
- .remove = __devexit_p(da732x_i2c_remove),
+ .remove = da732x_i2c_remove,
.id_table = da732x_i2c_id,
};
diff --git a/sound/soc/codecs/da9055.c b/sound/soc/codecs/da9055.c
index f379b085c392..fc9802d1281d 100644
--- a/sound/soc/codecs/da9055.c
+++ b/sound/soc/codecs/da9055.c
@@ -173,6 +173,7 @@
#define DA9055_AIF_FORMAT_I2S_MODE (0 << 0)
#define DA9055_AIF_FORMAT_LEFT_J (1 << 0)
#define DA9055_AIF_FORMAT_RIGHT_J (2 << 0)
+#define DA9055_AIF_FORMAT_DSP (3 << 0)
#define DA9055_AIF_WORD_S16_LE (0 << 2)
#define DA9055_AIF_WORD_S20_3LE (1 << 2)
#define DA9055_AIF_WORD_S24_LE (2 << 2)
@@ -752,6 +753,17 @@ static const struct snd_kcontrol_new da9055_dapm_mixoutr_controls[] = {
6, 1, 0),
};
+/* Headphone Output Enable */
+static const struct snd_kcontrol_new da9055_dapm_hp_l_control =
+SOC_DAPM_SINGLE("Switch", DA9055_HP_L_CTRL, 3, 1, 0);
+
+static const struct snd_kcontrol_new da9055_dapm_hp_r_control =
+SOC_DAPM_SINGLE("Switch", DA9055_HP_R_CTRL, 3, 1, 0);
+
+/* Lineout Output Enable */
+static const struct snd_kcontrol_new da9055_dapm_lineout_control =
+SOC_DAPM_SINGLE("Switch", DA9055_LINE_CTRL, 3, 1, 0);
+
/* DAPM widgets */
static const struct snd_soc_dapm_widget da9055_dapm_widgets[] = {
/* Input Side */
@@ -816,6 +828,14 @@ static const struct snd_soc_dapm_widget da9055_dapm_widgets[] = {
&da9055_dapm_mixoutr_controls[0],
ARRAY_SIZE(da9055_dapm_mixoutr_controls)),
+ /* Output Enable Switches */
+ SND_SOC_DAPM_SWITCH("Headphone Left Enable", SND_SOC_NOPM, 0, 0,
+ &da9055_dapm_hp_l_control),
+ SND_SOC_DAPM_SWITCH("Headphone Right Enable", SND_SOC_NOPM, 0, 0,
+ &da9055_dapm_hp_r_control),
+ SND_SOC_DAPM_SWITCH("Lineout Enable", SND_SOC_NOPM, 0, 0,
+ &da9055_dapm_lineout_control),
+
/* Output PGAs */
SND_SOC_DAPM_PGA("MIXOUT Left", DA9055_MIXOUT_L_CTRL, 7, 0, NULL, 0),
SND_SOC_DAPM_PGA("MIXOUT Right", DA9055_MIXOUT_R_CTRL, 7, 0, NULL, 0),
@@ -901,17 +921,20 @@ static const struct snd_soc_dapm_route da9055_audio_map[] = {
{"Out Mixer Right", "DAC Right Switch", "DAC Right"},
{"MIXOUT Left", NULL, "Out Mixer Left"},
- {"Headphone Left", NULL, "MIXOUT Left"},
+ {"Headphone Left Enable", "Switch", "MIXOUT Left"},
+ {"Headphone Left", NULL, "Headphone Left Enable"},
{"Headphone Left", NULL, "Charge Pump"},
{"HPL", NULL, "Headphone Left"},
{"MIXOUT Right", NULL, "Out Mixer Right"},
- {"Headphone Right", NULL, "MIXOUT Right"},
+ {"Headphone Right Enable", "Switch", "MIXOUT Right"},
+ {"Headphone Right", NULL, "Headphone Right Enable"},
{"Headphone Right", NULL, "Charge Pump"},
{"HPR", NULL, "Headphone Right"},
{"MIXOUT Right", NULL, "Out Mixer Right"},
- {"Lineout", NULL, "MIXOUT Right"},
+ {"Lineout Enable", "Switch", "MIXOUT Right"},
+ {"Lineout", NULL, "Lineout Enable"},
{"LINE", NULL, "Lineout"},
};
@@ -1175,6 +1198,9 @@ static int da9055_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt)
case SND_SOC_DAIFMT_RIGHT_J:
aif_ctrl = DA9055_AIF_FORMAT_RIGHT_J;
break;
+ case SND_SOC_DAIFMT_DSP_A:
+ aif_ctrl = DA9055_AIF_FORMAT_DSP;
+ break;
default:
return -EINVAL;
}
@@ -1390,8 +1416,7 @@ static int da9055_probe(struct snd_soc_codec *codec)
DA9055_GAIN_RAMPING_EN, DA9055_GAIN_RAMPING_EN);
/*
- * There are two separate control bits for input and output mixers as
- * well as headphone and line outs.
+ * There are two separate control bits for input and output mixers.
* One to enable corresponding amplifier and other to enable its
* output. As amplifier bits are related to power control, they are
* being managed by DAPM while other (non power related) bits are
@@ -1407,14 +1432,6 @@ static int da9055_probe(struct snd_soc_codec *codec)
snd_soc_update_bits(codec, DA9055_MIXOUT_R_CTRL,
DA9055_MIXOUT_R_MIX_EN, DA9055_MIXOUT_R_MIX_EN);
- snd_soc_update_bits(codec, DA9055_HP_L_CTRL,
- DA9055_HP_L_AMP_OE, DA9055_HP_L_AMP_OE);
- snd_soc_update_bits(codec, DA9055_HP_R_CTRL,
- DA9055_HP_R_AMP_OE, DA9055_HP_R_AMP_OE);
-
- snd_soc_update_bits(codec, DA9055_LINE_CTRL,
- DA9055_LINE_AMP_OE, DA9055_LINE_AMP_OE);
-
/* Set this as per your system configuration */
snd_soc_write(codec, DA9055_PLL_CTRL, DA9055_PLL_INDIV_10_20_MHZ);
@@ -1467,8 +1484,8 @@ static const struct regmap_config da9055_regmap_config = {
.cache_type = REGCACHE_RBTREE,
};
-static int __devinit da9055_i2c_probe(struct i2c_client *i2c,
- const struct i2c_device_id *id)
+static int da9055_i2c_probe(struct i2c_client *i2c,
+ const struct i2c_device_id *id)
{
struct da9055_priv *da9055;
struct da9055_platform_data *pdata = dev_get_platdata(&i2c->dev);
@@ -1500,7 +1517,7 @@ static int __devinit da9055_i2c_probe(struct i2c_client *i2c,
return ret;
}
-static int __devexit da9055_remove(struct i2c_client *client)
+static int da9055_remove(struct i2c_client *client)
{
snd_soc_unregister_codec(&client->dev);
return 0;
@@ -1519,7 +1536,7 @@ static struct i2c_driver da9055_i2c_driver = {
.owner = THIS_MODULE,
},
.probe = da9055_i2c_probe,
- .remove = __devexit_p(da9055_remove),
+ .remove = da9055_remove,
.id_table = da9055_i2c_id,
};
diff --git a/sound/soc/codecs/dfbmcs320.c b/sound/soc/codecs/dfbmcs320.c
index bfe46aa90362..4f4f7f41a7d1 100644
--- a/sound/soc/codecs/dfbmcs320.c
+++ b/sound/soc/codecs/dfbmcs320.c
@@ -33,13 +33,13 @@ static struct snd_soc_dai_driver dfbmcs320_dai = {
static struct snd_soc_codec_driver soc_codec_dev_dfbmcs320;
-static int __devinit dfbmcs320_probe(struct platform_device *pdev)
+static int dfbmcs320_probe(struct platform_device *pdev)
{
return snd_soc_register_codec(&pdev->dev, &soc_codec_dev_dfbmcs320,
&dfbmcs320_dai, 1);
}
-static int __devexit dfbmcs320_remove(struct platform_device *pdev)
+static int dfbmcs320_remove(struct platform_device *pdev)
{
snd_soc_unregister_codec(&pdev->dev);
@@ -52,7 +52,7 @@ static struct platform_driver dfmcs320_driver = {
.owner = THIS_MODULE,
},
.probe = dfbmcs320_probe,
- .remove = __devexit_p(dfbmcs320_remove),
+ .remove = dfbmcs320_remove,
};
module_platform_driver(dfmcs320_driver);
diff --git a/sound/soc/codecs/dmic.c b/sound/soc/codecs/dmic.c
index 3e929f079a1f..66967ba6f757 100644
--- a/sound/soc/codecs/dmic.c
+++ b/sound/soc/codecs/dmic.c
@@ -66,13 +66,13 @@ static struct snd_soc_codec_driver soc_dmic = {
.probe = dmic_probe,
};
-static int __devinit dmic_dev_probe(struct platform_device *pdev)
+static int dmic_dev_probe(struct platform_device *pdev)
{
return snd_soc_register_codec(&pdev->dev,
&soc_dmic, &dmic_dai, 1);
}
-static int __devexit dmic_dev_remove(struct platform_device *pdev)
+static int dmic_dev_remove(struct platform_device *pdev)
{
snd_soc_unregister_codec(&pdev->dev);
return 0;
@@ -86,7 +86,7 @@ static struct platform_driver dmic_driver = {
.owner = THIS_MODULE,
},
.probe = dmic_dev_probe,
- .remove = __devexit_p(dmic_dev_remove),
+ .remove = dmic_dev_remove,
};
module_platform_driver(dmic_driver);
diff --git a/sound/soc/codecs/isabelle.c b/sound/soc/codecs/isabelle.c
index 1bf55602c9eb..53b455b8c07a 100644
--- a/sound/soc/codecs/isabelle.c
+++ b/sound/soc/codecs/isabelle.c
@@ -1119,8 +1119,8 @@ static const struct regmap_config isabelle_regmap_config = {
.cache_type = REGCACHE_RBTREE,
};
-static int __devinit isabelle_i2c_probe(struct i2c_client *i2c,
- const struct i2c_device_id *id)
+static int isabelle_i2c_probe(struct i2c_client *i2c,
+ const struct i2c_device_id *id)
{
struct regmap *isabelle_regmap;
int ret = 0;
@@ -1145,7 +1145,7 @@ static int __devinit isabelle_i2c_probe(struct i2c_client *i2c,
return ret;
}
-static int __devexit isabelle_i2c_remove(struct i2c_client *client)
+static int isabelle_i2c_remove(struct i2c_client *client)
{
snd_soc_unregister_codec(&client->dev);
return 0;
@@ -1163,7 +1163,7 @@ static struct i2c_driver isabelle_i2c_driver = {
.owner = THIS_MODULE,
},
.probe = isabelle_i2c_probe,
- .remove = __devexit_p(isabelle_i2c_remove),
+ .remove = isabelle_i2c_remove,
.id_table = isabelle_i2c_id,
};
diff --git a/sound/soc/codecs/jz4740.c b/sound/soc/codecs/jz4740.c
index 85d9cabe6d55..d991529e1aff 100644
--- a/sound/soc/codecs/jz4740.c
+++ b/sound/soc/codecs/jz4740.c
@@ -16,6 +16,7 @@
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/io.h>
+#include <linux/regmap.h>
#include <linux/delay.h>
@@ -24,9 +25,10 @@
#include <sound/pcm_params.h>
#include <sound/initval.h>
#include <sound/soc.h>
+#include <sound/tlv.h>
#define JZ4740_REG_CODEC_1 0x0
-#define JZ4740_REG_CODEC_2 0x1
+#define JZ4740_REG_CODEC_2 0x4
#define JZ4740_CODEC_1_LINE_ENABLE BIT(29)
#define JZ4740_CODEC_1_MIC_ENABLE BIT(28)
@@ -67,43 +69,36 @@
#define JZ4740_CODEC_2_MIC_BOOST_GAIN_OFFSET 4
#define JZ4740_CODEC_2_HEADPHONE_VOLUME_OFFSET 0
-static const uint32_t jz4740_codec_regs[] = {
- 0x021b2302, 0x00170803,
+static const struct reg_default jz4740_codec_reg_defaults[] = {
+ { JZ4740_REG_CODEC_1, 0x021b2302 },
+ { JZ4740_REG_CODEC_2, 0x00170803 },
};
struct jz4740_codec {
- void __iomem *base;
- struct resource *mem;
+ struct regmap *regmap;
};
-static unsigned int jz4740_codec_read(struct snd_soc_codec *codec,
- unsigned int reg)
-{
- struct jz4740_codec *jz4740_codec = snd_soc_codec_get_drvdata(codec);
- return readl(jz4740_codec->base + (reg << 2));
-}
-
-static int jz4740_codec_write(struct snd_soc_codec *codec, unsigned int reg,
- unsigned int val)
-{
- struct jz4740_codec *jz4740_codec = snd_soc_codec_get_drvdata(codec);
- u32 *cache = codec->reg_cache;
-
- cache[reg] = val;
- writel(val, jz4740_codec->base + (reg << 2));
+static const unsigned int jz4740_mic_tlv[] = {
+ TLV_DB_RANGE_HEAD(2),
+ 0, 2, TLV_DB_SCALE_ITEM(0, 600, 0),
+ 3, 3, TLV_DB_SCALE_ITEM(2000, 0, 0),
+};
- return 0;
-}
+static const DECLARE_TLV_DB_SCALE(jz4740_out_tlv, 0, 200, 0);
+static const DECLARE_TLV_DB_SCALE(jz4740_in_tlv, -3450, 150, 0);
static const struct snd_kcontrol_new jz4740_codec_controls[] = {
- SOC_SINGLE("Master Playback Volume", JZ4740_REG_CODEC_2,
- JZ4740_CODEC_2_HEADPHONE_VOLUME_OFFSET, 3, 0),
- SOC_SINGLE("Master Capture Volume", JZ4740_REG_CODEC_2,
- JZ4740_CODEC_2_INPUT_VOLUME_OFFSET, 31, 0),
+ SOC_SINGLE_TLV("Master Playback Volume", JZ4740_REG_CODEC_2,
+ JZ4740_CODEC_2_HEADPHONE_VOLUME_OFFSET, 3, 0,
+ jz4740_out_tlv),
+ SOC_SINGLE_TLV("Master Capture Volume", JZ4740_REG_CODEC_2,
+ JZ4740_CODEC_2_INPUT_VOLUME_OFFSET, 31, 0,
+ jz4740_in_tlv),
SOC_SINGLE("Master Playback Switch", JZ4740_REG_CODEC_1,
JZ4740_CODEC_1_HEADPHONE_DISABLE_OFFSET, 1, 1),
- SOC_SINGLE("Mic Capture Volume", JZ4740_REG_CODEC_2,
- JZ4740_CODEC_2_MIC_BOOST_GAIN_OFFSET, 3, 0),
+ SOC_SINGLE_TLV("Mic Capture Volume", JZ4740_REG_CODEC_2,
+ JZ4740_CODEC_2_MIC_BOOST_GAIN_OFFSET, 3, 0,
+ jz4740_mic_tlv),
};
static const struct snd_kcontrol_new jz4740_codec_output_controls[] = {
@@ -163,8 +158,8 @@ static const struct snd_soc_dapm_route jz4740_codec_dapm_routes[] = {
static int jz4740_codec_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params, struct snd_soc_dai *dai)
{
+ struct jz4740_codec *jz4740_codec = snd_soc_codec_get_drvdata(dai->codec);
uint32_t val;
- struct snd_soc_codec *codec = dai->codec;
switch (params_rate(params)) {
case 8000:
@@ -200,7 +195,7 @@ static int jz4740_codec_hw_params(struct snd_pcm_substream *substream,
val <<= JZ4740_CODEC_2_SAMPLE_RATE_OFFSET;
- snd_soc_update_bits(codec, JZ4740_REG_CODEC_2,
+ regmap_update_bits(jz4740_codec->regmap, JZ4740_REG_CODEC_2,
JZ4740_CODEC_2_SAMPLE_RATE_MASK, val);
return 0;
@@ -230,25 +225,23 @@ static struct snd_soc_dai_driver jz4740_codec_dai = {
.symmetric_rates = 1,
};
-static void jz4740_codec_wakeup(struct snd_soc_codec *codec)
+static void jz4740_codec_wakeup(struct regmap *regmap)
{
- int i;
- uint32_t *cache = codec->reg_cache;
-
- snd_soc_update_bits(codec, JZ4740_REG_CODEC_1,
+ regmap_update_bits(regmap, JZ4740_REG_CODEC_1,
JZ4740_CODEC_1_RESET, JZ4740_CODEC_1_RESET);
udelay(2);
- snd_soc_update_bits(codec, JZ4740_REG_CODEC_1,
+ regmap_update_bits(regmap, JZ4740_REG_CODEC_1,
JZ4740_CODEC_1_SUSPEND | JZ4740_CODEC_1_RESET, 0);
- for (i = 0; i < ARRAY_SIZE(jz4740_codec_regs); ++i)
- jz4740_codec_write(codec, i, cache[i]);
+ regcache_sync(regmap);
}
static int jz4740_codec_set_bias_level(struct snd_soc_codec *codec,
enum snd_soc_bias_level level)
{
+ struct jz4740_codec *jz4740_codec = snd_soc_codec_get_drvdata(codec);
+ struct regmap *regmap = jz4740_codec->regmap;
unsigned int mask;
unsigned int value;
@@ -261,12 +254,12 @@ static int jz4740_codec_set_bias_level(struct snd_soc_codec *codec,
JZ4740_CODEC_1_HEADPHONE_POWERDOWN_M;
value = 0;
- snd_soc_update_bits(codec, JZ4740_REG_CODEC_1, mask, value);
+ regmap_update_bits(regmap, JZ4740_REG_CODEC_1, mask, value);
break;
case SND_SOC_BIAS_STANDBY:
/* The only way to clear the suspend flag is to reset the codec */
if (codec->dapm.bias_level == SND_SOC_BIAS_OFF)
- jz4740_codec_wakeup(codec);
+ jz4740_codec_wakeup(regmap);
mask = JZ4740_CODEC_1_VREF_DISABLE |
JZ4740_CODEC_1_VREF_AMP_DISABLE |
@@ -275,13 +268,14 @@ static int jz4740_codec_set_bias_level(struct snd_soc_codec *codec,
JZ4740_CODEC_1_VREF_AMP_DISABLE |
JZ4740_CODEC_1_HEADPHONE_POWERDOWN_M;
- snd_soc_update_bits(codec, JZ4740_REG_CODEC_1, mask, value);
+ regmap_update_bits(regmap, JZ4740_REG_CODEC_1, mask, value);
break;
case SND_SOC_BIAS_OFF:
mask = JZ4740_CODEC_1_SUSPEND;
value = JZ4740_CODEC_1_SUSPEND;
- snd_soc_update_bits(codec, JZ4740_REG_CODEC_1, mask, value);
+ regmap_update_bits(regmap, JZ4740_REG_CODEC_1, mask, value);
+ regcache_mark_dirty(regmap);
break;
default:
break;
@@ -294,7 +288,9 @@ static int jz4740_codec_set_bias_level(struct snd_soc_codec *codec,
static int jz4740_codec_dev_probe(struct snd_soc_codec *codec)
{
- snd_soc_update_bits(codec, JZ4740_REG_CODEC_1,
+ struct jz4740_codec *jz4740_codec = snd_soc_codec_get_drvdata(codec);
+
+ regmap_update_bits(jz4740_codec->regmap, JZ4740_REG_CODEC_1,
JZ4740_CODEC_1_SW2_ENABLE, JZ4740_CODEC_1_SW2_ENABLE);
jz4740_codec_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
@@ -331,12 +327,7 @@ static struct snd_soc_codec_driver soc_codec_dev_jz4740_codec = {
.remove = jz4740_codec_dev_remove,
.suspend = jz4740_codec_suspend,
.resume = jz4740_codec_resume,
- .read = jz4740_codec_read,
- .write = jz4740_codec_write,
.set_bias_level = jz4740_codec_set_bias_level,
- .reg_cache_default = jz4740_codec_regs,
- .reg_word_size = sizeof(u32),
- .reg_cache_size = 2,
.controls = jz4740_codec_controls,
.num_controls = ARRAY_SIZE(jz4740_codec_controls),
@@ -346,11 +337,23 @@ static struct snd_soc_codec_driver soc_codec_dev_jz4740_codec = {
.num_dapm_routes = ARRAY_SIZE(jz4740_codec_dapm_routes),
};
-static int __devinit jz4740_codec_probe(struct platform_device *pdev)
+static const struct regmap_config jz4740_codec_regmap_config = {
+ .reg_bits = 32,
+ .reg_stride = 4,
+ .val_bits = 32,
+ .max_register = JZ4740_REG_CODEC_2,
+
+ .reg_defaults = jz4740_codec_reg_defaults,
+ .num_reg_defaults = ARRAY_SIZE(jz4740_codec_reg_defaults),
+ .cache_type = REGCACHE_RBTREE,
+};
+
+static int jz4740_codec_probe(struct platform_device *pdev)
{
int ret;
struct jz4740_codec *jz4740_codec;
struct resource *mem;
+ void __iomem *base;
jz4740_codec = devm_kzalloc(&pdev->dev, sizeof(*jz4740_codec),
GFP_KERNEL);
@@ -358,56 +361,29 @@ static int __devinit jz4740_codec_probe(struct platform_device *pdev)
return -ENOMEM;
mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!mem) {
- dev_err(&pdev->dev, "Failed to get mmio memory resource\n");
- ret = -ENOENT;
- goto err_out;
- }
-
- mem = request_mem_region(mem->start, resource_size(mem), pdev->name);
- if (!mem) {
- dev_err(&pdev->dev, "Failed to request mmio memory region\n");
- ret = -EBUSY;
- goto err_out;
- }
+ base = devm_request_and_ioremap(&pdev->dev, mem);
+ if (!base)
+ return -EBUSY;
- jz4740_codec->base = ioremap(mem->start, resource_size(mem));
- if (!jz4740_codec->base) {
- dev_err(&pdev->dev, "Failed to ioremap mmio memory\n");
- ret = -EBUSY;
- goto err_release_mem_region;
- }
- jz4740_codec->mem = mem;
+ jz4740_codec->regmap = devm_regmap_init_mmio(&pdev->dev, base,
+ &jz4740_codec_regmap_config);
+ if (IS_ERR(jz4740_codec->regmap))
+ return PTR_ERR(jz4740_codec->regmap);
platform_set_drvdata(pdev, jz4740_codec);
ret = snd_soc_register_codec(&pdev->dev,
&soc_codec_dev_jz4740_codec, &jz4740_codec_dai, 1);
- if (ret) {
+ if (ret)
dev_err(&pdev->dev, "Failed to register codec\n");
- goto err_iounmap;
- }
- return 0;
-
-err_iounmap:
- iounmap(jz4740_codec->base);
-err_release_mem_region:
- release_mem_region(mem->start, resource_size(mem));
-err_out:
return ret;
}
-static int __devexit jz4740_codec_remove(struct platform_device *pdev)
+static int jz4740_codec_remove(struct platform_device *pdev)
{
- struct jz4740_codec *jz4740_codec = platform_get_drvdata(pdev);
- struct resource *mem = jz4740_codec->mem;
-
snd_soc_unregister_codec(&pdev->dev);
- iounmap(jz4740_codec->base);
- release_mem_region(mem->start, resource_size(mem));
-
platform_set_drvdata(pdev, NULL);
return 0;
@@ -415,7 +391,7 @@ static int __devexit jz4740_codec_remove(struct platform_device *pdev)
static struct platform_driver jz4740_codec_driver = {
.probe = jz4740_codec_probe,
- .remove = __devexit_p(jz4740_codec_remove),
+ .remove = jz4740_codec_remove,
.driver = {
.name = "jz4740-codec",
.owner = THIS_MODULE,
diff --git a/sound/soc/codecs/lm4857.c b/sound/soc/codecs/lm4857.c
index 81a328c78838..9f9f59573f72 100644
--- a/sound/soc/codecs/lm4857.c
+++ b/sound/soc/codecs/lm4857.c
@@ -209,8 +209,8 @@ static struct snd_soc_codec_driver soc_codec_dev_lm4857 = {
.set_bias_level = lm4857_set_bias_level,
};
-static int __devinit lm4857_i2c_probe(struct i2c_client *i2c,
- const struct i2c_device_id *id)
+static int lm4857_i2c_probe(struct i2c_client *i2c,
+ const struct i2c_device_id *id)
{
struct lm4857 *lm4857;
int ret;
@@ -228,7 +228,7 @@ static int __devinit lm4857_i2c_probe(struct i2c_client *i2c,
return ret;
}
-static int __devexit lm4857_i2c_remove(struct i2c_client *i2c)
+static int lm4857_i2c_remove(struct i2c_client *i2c)
{
snd_soc_unregister_codec(&i2c->dev);
return 0;
@@ -246,7 +246,7 @@ static struct i2c_driver lm4857_i2c_driver = {
.owner = THIS_MODULE,
},
.probe = lm4857_i2c_probe,
- .remove = __devexit_p(lm4857_i2c_remove),
+ .remove = lm4857_i2c_remove,
.id_table = lm4857_i2c_id,
};
diff --git a/sound/soc/codecs/lm49453.c b/sound/soc/codecs/lm49453.c
index 99b0a9dcff34..d75257d40a49 100644
--- a/sound/soc/codecs/lm49453.c
+++ b/sound/soc/codecs/lm49453.c
@@ -1483,8 +1483,8 @@ static const struct regmap_config lm49453_regmap_config = {
.cache_type = REGCACHE_RBTREE,
};
-static __devinit int lm49453_i2c_probe(struct i2c_client *i2c,
- const struct i2c_device_id *id)
+static int lm49453_i2c_probe(struct i2c_client *i2c,
+ const struct i2c_device_id *id)
{
struct lm49453_priv *lm49453;
int ret = 0;
@@ -1497,7 +1497,7 @@ static __devinit int lm49453_i2c_probe(struct i2c_client *i2c,
i2c_set_clientdata(i2c, lm49453);
- lm49453->regmap = regmap_init_i2c(i2c, &lm49453_regmap_config);
+ lm49453->regmap = devm_regmap_init_i2c(i2c, &lm49453_regmap_config);
if (IS_ERR(lm49453->regmap)) {
ret = PTR_ERR(lm49453->regmap);
dev_err(&i2c->dev, "Failed to allocate register map: %d\n",
@@ -1508,21 +1508,15 @@ static __devinit int lm49453_i2c_probe(struct i2c_client *i2c,
ret = snd_soc_register_codec(&i2c->dev,
&soc_codec_dev_lm49453,
lm49453_dai, ARRAY_SIZE(lm49453_dai));
- if (ret < 0) {
+ if (ret < 0)
dev_err(&i2c->dev, "Failed to register codec: %d\n", ret);
- regmap_exit(lm49453->regmap);
- return ret;
- }
return ret;
}
-static int __devexit lm49453_i2c_remove(struct i2c_client *client)
+static int lm49453_i2c_remove(struct i2c_client *client)
{
- struct lm49453_priv *lm49453 = i2c_get_clientdata(client);
-
snd_soc_unregister_codec(&client->dev);
- regmap_exit(lm49453->regmap);
return 0;
}
@@ -1538,7 +1532,7 @@ static struct i2c_driver lm49453_i2c_driver = {
.owner = THIS_MODULE,
},
.probe = lm49453_i2c_probe,
- .remove = __devexit_p(lm49453_i2c_remove),
+ .remove = lm49453_i2c_remove,
.id_table = lm49453_i2c_id,
};
diff --git a/sound/soc/codecs/max9768.c b/sound/soc/codecs/max9768.c
index 17b3ec2d05cb..a6ac2313047d 100644
--- a/sound/soc/codecs/max9768.c
+++ b/sound/soc/codecs/max9768.c
@@ -159,8 +159,8 @@ static const struct regmap_config max9768_i2c_regmap_config = {
.cache_type = REGCACHE_RBTREE,
};
-static int __devinit max9768_i2c_probe(struct i2c_client *client,
- const struct i2c_device_id *id)
+static int max9768_i2c_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
{
struct max9768 *max9768;
struct max9768_pdata *pdata = client->dev.platform_data;
@@ -187,7 +187,7 @@ static int __devinit max9768_i2c_probe(struct i2c_client *client,
i2c_set_clientdata(client, max9768);
- max9768->regmap = regmap_init_i2c(client, &max9768_i2c_regmap_config);
+ max9768->regmap = devm_regmap_init_i2c(client, &max9768_i2c_regmap_config);
if (IS_ERR(max9768->regmap)) {
err = PTR_ERR(max9768->regmap);
goto err_gpio_free;
@@ -195,12 +195,10 @@ static int __devinit max9768_i2c_probe(struct i2c_client *client,
err = snd_soc_register_codec(&client->dev, &max9768_codec_driver, NULL, 0);
if (err)
- goto err_regmap_free;
+ goto err_gpio_free;
return 0;
- err_regmap_free:
- regmap_exit(max9768->regmap);
err_gpio_free:
if (gpio_is_valid(max9768->shdn_gpio))
gpio_free(max9768->shdn_gpio);
@@ -210,12 +208,11 @@ static int __devinit max9768_i2c_probe(struct i2c_client *client,
return err;
}
-static int __devexit max9768_i2c_remove(struct i2c_client *client)
+static int max9768_i2c_remove(struct i2c_client *client)
{
struct max9768 *max9768 = i2c_get_clientdata(client);
snd_soc_unregister_codec(&client->dev);
- regmap_exit(max9768->regmap);
if (gpio_is_valid(max9768->shdn_gpio))
gpio_free(max9768->shdn_gpio);
@@ -237,7 +234,7 @@ static struct i2c_driver max9768_i2c_driver = {
.owner = THIS_MODULE,
},
.probe = max9768_i2c_probe,
- .remove = __devexit_p(max9768_i2c_remove),
+ .remove = max9768_i2c_remove,
.id_table = max9768_i2c_id,
};
module_i2c_driver(max9768_i2c_driver);
diff --git a/sound/soc/codecs/max98088.c b/sound/soc/codecs/max98088.c
index 3264a5169306..a4c16fd70f77 100644
--- a/sound/soc/codecs/max98088.c
+++ b/sound/soc/codecs/max98088.c
@@ -2084,7 +2084,7 @@ static int max98088_i2c_probe(struct i2c_client *i2c,
return ret;
}
-static int __devexit max98088_i2c_remove(struct i2c_client *client)
+static int max98088_i2c_remove(struct i2c_client *client)
{
snd_soc_unregister_codec(&client->dev);
return 0;
@@ -2098,13 +2098,13 @@ static const struct i2c_device_id max98088_i2c_id[] = {
MODULE_DEVICE_TABLE(i2c, max98088_i2c_id);
static struct i2c_driver max98088_i2c_driver = {
- .driver = {
- .name = "max98088",
- .owner = THIS_MODULE,
- },
- .probe = max98088_i2c_probe,
- .remove = __devexit_p(max98088_i2c_remove),
- .id_table = max98088_i2c_id,
+ .driver = {
+ .name = "max98088",
+ .owner = THIS_MODULE,
+ },
+ .probe = max98088_i2c_probe,
+ .remove = max98088_i2c_remove,
+ .id_table = max98088_i2c_id,
};
module_i2c_driver(max98088_i2c_driver);
diff --git a/sound/soc/codecs/max98090.c b/sound/soc/codecs/max98090.c
new file mode 100644
index 000000000000..c9772ca3da4f
--- /dev/null
+++ b/sound/soc/codecs/max98090.c
@@ -0,0 +1,577 @@
+/*
+ * max98090.c -- MAX98090 ALSA SoC Audio driver
+ * based on Rev0p8 datasheet
+ *
+ * Copyright (C) 2012 Renesas Solutions Corp.
+ * Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+ *
+ * Based on
+ *
+ * max98095.c
+ * Copyright 2011 Maxim Integrated Products
+ *
+ * https://github.com/hardkernel/linux/commit/\
+ * 3417d7166b17113b3b33b0a337c74d1c7cc313df#sound/soc/codecs/max98090.c
+ * Copyright 2011 Maxim Integrated Products
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/i2c.h>
+#include <linux/module.h>
+#include <linux/regmap.h>
+#include <sound/soc.h>
+#include <sound/tlv.h>
+
+/*
+ *
+ * MAX98090 Registers Definition
+ *
+ */
+
+/* RESET / STATUS / INTERRUPT REGISTERS */
+#define MAX98090_0x00_SW_RESET 0x00
+#define MAX98090_0x01_INT_STS 0x01
+#define MAX98090_0x02_JACK_STS 0x02
+#define MAX98090_0x03_INT_MASK 0x03
+
+/* QUICK SETUP REGISTERS */
+#define MAX98090_0x04_SYS_CLK 0x04
+#define MAX98090_0x05_SAMPLE_RATE 0x05
+#define MAX98090_0x06_DAI_IF 0x06
+#define MAX98090_0x07_DAC_PATH 0x07
+#define MAX98090_0x08_MIC_TO_ADC 0x08
+#define MAX98090_0x09_LINE_TO_ADC 0x09
+#define MAX98090_0x0A_ANALOG_MIC_LOOP 0x0A
+#define MAX98090_0x0B_ANALOG_LINE_LOOP 0x0B
+
+/* ANALOG INPUT CONFIGURATION REGISTERS */
+#define MAX98090_0x0D_INPUT_CONFIG 0x0D
+#define MAX98090_0x0E_LINE_IN_LVL 0x0E
+#define MAX98090_0x0F_LINI_IN_CFG 0x0F
+#define MAX98090_0x10_MIC1_IN_LVL 0x10
+#define MAX98090_0x11_MIC2_IN_LVL 0x11
+
+/* MICROPHONE CONFIGURATION REGISTERS */
+#define MAX98090_0x12_MIC_BIAS_VOL 0x12
+#define MAX98090_0x13_DIGITAL_MIC_CFG 0x13
+#define MAX98090_0x14_DIGITAL_MIC_MODE 0x14
+
+/* ADC PATH AND CONFIGURATION REGISTERS */
+#define MAX98090_0x15_L_ADC_MIX 0x15
+#define MAX98090_0x16_R_ADC_MIX 0x16
+#define MAX98090_0x17_L_ADC_LVL 0x17
+#define MAX98090_0x18_R_ADC_LVL 0x18
+#define MAX98090_0x19_ADC_BIQUAD_LVL 0x19
+#define MAX98090_0x1A_ADC_SIDETONE 0x1A
+
+/* CLOCK CONFIGURATION REGISTERS */
+#define MAX98090_0x1B_SYS_CLK 0x1B
+#define MAX98090_0x1C_CLK_MODE 0x1C
+#define MAX98090_0x1D_ANY_CLK1 0x1D
+#define MAX98090_0x1E_ANY_CLK2 0x1E
+#define MAX98090_0x1F_ANY_CLK3 0x1F
+#define MAX98090_0x20_ANY_CLK4 0x20
+#define MAX98090_0x21_MASTER_MODE 0x21
+
+/* INTERFACE CONTROL REGISTERS */
+#define MAX98090_0x22_DAI_IF_FMT 0x22
+#define MAX98090_0x23_DAI_TDM_FMT1 0x23
+#define MAX98090_0x24_DAI_TDM_FMT2 0x24
+#define MAX98090_0x25_DAI_IO_CFG 0x25
+#define MAX98090_0x26_FILTER_CFG 0x26
+#define MAX98090_0x27_DAI_PLAYBACK_LVL 0x27
+#define MAX98090_0x28_EQ_PLAYBACK_LVL 0x28
+
+/* HEADPHONE CONTROL REGISTERS */
+#define MAX98090_0x29_L_HP_MIX 0x29
+#define MAX98090_0x2A_R_HP_MIX 0x2A
+#define MAX98090_0x2B_HP_CTR 0x2B
+#define MAX98090_0x2C_L_HP_VOL 0x2C
+#define MAX98090_0x2D_R_HP_VOL 0x2D
+
+/* SPEAKER CONFIGURATION REGISTERS */
+#define MAX98090_0x2E_L_SPK_MIX 0x2E
+#define MAX98090_0x2F_R_SPK_MIX 0x2F
+#define MAX98090_0x30_SPK_CTR 0x30
+#define MAX98090_0x31_L_SPK_VOL 0x31
+#define MAX98090_0x32_R_SPK_VOL 0x32
+
+/* ALC CONFIGURATION REGISTERS */
+#define MAX98090_0x33_ALC_TIMING 0x33
+#define MAX98090_0x34_ALC_COMPRESSOR 0x34
+#define MAX98090_0x35_ALC_EXPANDER 0x35
+#define MAX98090_0x36_ALC_GAIN 0x36
+
+/* RECEIVER AND LINE_OUTPUT REGISTERS */
+#define MAX98090_0x37_RCV_LOUT_L_MIX 0x37
+#define MAX98090_0x38_RCV_LOUT_L_CNTL 0x38
+#define MAX98090_0x39_RCV_LOUT_L_VOL 0x39
+#define MAX98090_0x3A_LOUT_R_MIX 0x3A
+#define MAX98090_0x3B_LOUT_R_CNTL 0x3B
+#define MAX98090_0x3C_LOUT_R_VOL 0x3C
+
+/* JACK DETECT AND ENABLE REGISTERS */
+#define MAX98090_0x3D_JACK_DETECT 0x3D
+#define MAX98090_0x3E_IN_ENABLE 0x3E
+#define MAX98090_0x3F_OUT_ENABLE 0x3F
+#define MAX98090_0x40_LVL_CTR 0x40
+#define MAX98090_0x41_DSP_FILTER_ENABLE 0x41
+
+/* BIAS AND POWER MODE CONFIGURATION REGISTERS */
+#define MAX98090_0x42_BIAS_CTR 0x42
+#define MAX98090_0x43_DAC_CTR 0x43
+#define MAX98090_0x44_ADC_CTR 0x44
+#define MAX98090_0x45_DEV_SHUTDOWN 0x45
+
+/* REVISION ID REGISTER */
+#define MAX98090_0xFF_REV_ID 0xFF
+
+#define MAX98090_REG_MAX_CACHED 0x45
+#define MAX98090_REG_END 0xFF
+
+/*
+ *
+ * MAX98090 Registers Bit Fields
+ *
+ */
+
+/* MAX98090_0x06_DAI_IF */
+#define MAX98090_DAI_IF_MASK 0x3F
+#define MAX98090_RJ_M (1 << 5)
+#define MAX98090_RJ_S (1 << 4)
+#define MAX98090_LJ_M (1 << 3)
+#define MAX98090_LJ_S (1 << 2)
+#define MAX98090_I2S_M (1 << 1)
+#define MAX98090_I2S_S (1 << 0)
+
+/* MAX98090_0x45_DEV_SHUTDOWN */
+#define MAX98090_SHDNRUN (1 << 7)
+
+/* codec private data */
+struct max98090_priv {
+ struct regmap *regmap;
+};
+
+static const struct reg_default max98090_reg_defaults[] = {
+ /* RESET / STATUS / INTERRUPT REGISTERS */
+ {MAX98090_0x00_SW_RESET, 0x00},
+ {MAX98090_0x01_INT_STS, 0x00},
+ {MAX98090_0x02_JACK_STS, 0x00},
+ {MAX98090_0x03_INT_MASK, 0x04},
+
+ /* QUICK SETUP REGISTERS */
+ {MAX98090_0x04_SYS_CLK, 0x00},
+ {MAX98090_0x05_SAMPLE_RATE, 0x00},
+ {MAX98090_0x06_DAI_IF, 0x00},
+ {MAX98090_0x07_DAC_PATH, 0x00},
+ {MAX98090_0x08_MIC_TO_ADC, 0x00},
+ {MAX98090_0x09_LINE_TO_ADC, 0x00},
+ {MAX98090_0x0A_ANALOG_MIC_LOOP, 0x00},
+ {MAX98090_0x0B_ANALOG_LINE_LOOP, 0x00},
+
+ /* ANALOG INPUT CONFIGURATION REGISTERS */
+ {MAX98090_0x0D_INPUT_CONFIG, 0x00},
+ {MAX98090_0x0E_LINE_IN_LVL, 0x1B},
+ {MAX98090_0x0F_LINI_IN_CFG, 0x00},
+ {MAX98090_0x10_MIC1_IN_LVL, 0x11},
+ {MAX98090_0x11_MIC2_IN_LVL, 0x11},
+
+ /* MICROPHONE CONFIGURATION REGISTERS */
+ {MAX98090_0x12_MIC_BIAS_VOL, 0x00},
+ {MAX98090_0x13_DIGITAL_MIC_CFG, 0x00},
+ {MAX98090_0x14_DIGITAL_MIC_MODE, 0x00},
+
+ /* ADC PATH AND CONFIGURATION REGISTERS */
+ {MAX98090_0x15_L_ADC_MIX, 0x00},
+ {MAX98090_0x16_R_ADC_MIX, 0x00},
+ {MAX98090_0x17_L_ADC_LVL, 0x03},
+ {MAX98090_0x18_R_ADC_LVL, 0x03},
+ {MAX98090_0x19_ADC_BIQUAD_LVL, 0x00},
+ {MAX98090_0x1A_ADC_SIDETONE, 0x00},
+
+ /* CLOCK CONFIGURATION REGISTERS */
+ {MAX98090_0x1B_SYS_CLK, 0x00},
+ {MAX98090_0x1C_CLK_MODE, 0x00},
+ {MAX98090_0x1D_ANY_CLK1, 0x00},
+ {MAX98090_0x1E_ANY_CLK2, 0x00},
+ {MAX98090_0x1F_ANY_CLK3, 0x00},
+ {MAX98090_0x20_ANY_CLK4, 0x00},
+ {MAX98090_0x21_MASTER_MODE, 0x00},
+
+ /* INTERFACE CONTROL REGISTERS */
+ {MAX98090_0x22_DAI_IF_FMT, 0x00},
+ {MAX98090_0x23_DAI_TDM_FMT1, 0x00},
+ {MAX98090_0x24_DAI_TDM_FMT2, 0x00},
+ {MAX98090_0x25_DAI_IO_CFG, 0x00},
+ {MAX98090_0x26_FILTER_CFG, 0x80},
+ {MAX98090_0x27_DAI_PLAYBACK_LVL, 0x00},
+ {MAX98090_0x28_EQ_PLAYBACK_LVL, 0x00},
+
+ /* HEADPHONE CONTROL REGISTERS */
+ {MAX98090_0x29_L_HP_MIX, 0x00},
+ {MAX98090_0x2A_R_HP_MIX, 0x00},
+ {MAX98090_0x2B_HP_CTR, 0x00},
+ {MAX98090_0x2C_L_HP_VOL, 0x1A},
+ {MAX98090_0x2D_R_HP_VOL, 0x1A},
+
+ /* SPEAKER CONFIGURATION REGISTERS */
+ {MAX98090_0x2E_L_SPK_MIX, 0x00},
+ {MAX98090_0x2F_R_SPK_MIX, 0x00},
+ {MAX98090_0x30_SPK_CTR, 0x00},
+ {MAX98090_0x31_L_SPK_VOL, 0x2C},
+ {MAX98090_0x32_R_SPK_VOL, 0x2C},
+
+ /* ALC CONFIGURATION REGISTERS */
+ {MAX98090_0x33_ALC_TIMING, 0x00},
+ {MAX98090_0x34_ALC_COMPRESSOR, 0x00},
+ {MAX98090_0x35_ALC_EXPANDER, 0x00},
+ {MAX98090_0x36_ALC_GAIN, 0x00},
+
+ /* RECEIVER AND LINE_OUTPUT REGISTERS */
+ {MAX98090_0x37_RCV_LOUT_L_MIX, 0x00},
+ {MAX98090_0x38_RCV_LOUT_L_CNTL, 0x00},
+ {MAX98090_0x39_RCV_LOUT_L_VOL, 0x15},
+ {MAX98090_0x3A_LOUT_R_MIX, 0x00},
+ {MAX98090_0x3B_LOUT_R_CNTL, 0x00},
+ {MAX98090_0x3C_LOUT_R_VOL, 0x15},
+
+ /* JACK DETECT AND ENABLE REGISTERS */
+ {MAX98090_0x3D_JACK_DETECT, 0x00},
+ {MAX98090_0x3E_IN_ENABLE, 0x00},
+ {MAX98090_0x3F_OUT_ENABLE, 0x00},
+ {MAX98090_0x40_LVL_CTR, 0x00},
+ {MAX98090_0x41_DSP_FILTER_ENABLE, 0x00},
+
+ /* BIAS AND POWER MODE CONFIGURATION REGISTERS */
+ {MAX98090_0x42_BIAS_CTR, 0x00},
+ {MAX98090_0x43_DAC_CTR, 0x00},
+ {MAX98090_0x44_ADC_CTR, 0x06},
+ {MAX98090_0x45_DEV_SHUTDOWN, 0x00},
+};
+
+static const unsigned int max98090_hp_tlv[] = {
+ TLV_DB_RANGE_HEAD(5),
+ 0x0, 0x6, TLV_DB_SCALE_ITEM(-6700, 400, 0),
+ 0x7, 0xE, TLV_DB_SCALE_ITEM(-4000, 300, 0),
+ 0xF, 0x15, TLV_DB_SCALE_ITEM(-1700, 200, 0),
+ 0x16, 0x1B, TLV_DB_SCALE_ITEM(-400, 100, 0),
+ 0x1C, 0x1F, TLV_DB_SCALE_ITEM(150, 50, 0),
+};
+
+static struct snd_kcontrol_new max98090_snd_controls[] = {
+ SOC_DOUBLE_R_TLV("Headphone Volume", MAX98090_0x2C_L_HP_VOL,
+ MAX98090_0x2D_R_HP_VOL, 0, 31, 0, max98090_hp_tlv),
+};
+
+/* Left HeadPhone Mixer Switch */
+static struct snd_kcontrol_new max98090_left_hp_mixer_controls[] = {
+ SOC_DAPM_SINGLE("DACR Switch", MAX98090_0x29_L_HP_MIX, 1, 1, 0),
+ SOC_DAPM_SINGLE("DACL Switch", MAX98090_0x29_L_HP_MIX, 0, 1, 0),
+};
+
+/* Right HeadPhone Mixer Switch */
+static struct snd_kcontrol_new max98090_right_hp_mixer_controls[] = {
+ SOC_DAPM_SINGLE("DACR Switch", MAX98090_0x2A_R_HP_MIX, 1, 1, 0),
+ SOC_DAPM_SINGLE("DACL Switch", MAX98090_0x2A_R_HP_MIX, 0, 1, 0),
+};
+
+static struct snd_soc_dapm_widget max98090_dapm_widgets[] = {
+ /* Output */
+ SND_SOC_DAPM_OUTPUT("HPL"),
+ SND_SOC_DAPM_OUTPUT("HPR"),
+
+ /* PGA */
+ SND_SOC_DAPM_PGA("HPL Out", MAX98090_0x3F_OUT_ENABLE, 7, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("HPR Out", MAX98090_0x3F_OUT_ENABLE, 6, 0, NULL, 0),
+
+ /* Mixer */
+ SND_SOC_DAPM_MIXER("HPL Mixer", SND_SOC_NOPM, 0, 0,
+ max98090_left_hp_mixer_controls,
+ ARRAY_SIZE(max98090_left_hp_mixer_controls)),
+
+ SND_SOC_DAPM_MIXER("HPR Mixer", SND_SOC_NOPM, 0, 0,
+ max98090_right_hp_mixer_controls,
+ ARRAY_SIZE(max98090_right_hp_mixer_controls)),
+
+ /* DAC */
+ SND_SOC_DAPM_DAC("DACL", "Hifi Playback", MAX98090_0x3F_OUT_ENABLE, 0, 0),
+ SND_SOC_DAPM_DAC("DACR", "Hifi Playback", MAX98090_0x3F_OUT_ENABLE, 1, 0),
+};
+
+static struct snd_soc_dapm_route max98090_audio_map[] = {
+ /* Output */
+ {"HPL", NULL, "HPL Out"},
+ {"HPR", NULL, "HPR Out"},
+
+ /* PGA */
+ {"HPL Out", NULL, "HPL Mixer"},
+ {"HPR Out", NULL, "HPR Mixer"},
+
+ /* Mixer*/
+ {"HPL Mixer", "DACR Switch", "DACR"},
+ {"HPL Mixer", "DACL Switch", "DACL"},
+
+ {"HPR Mixer", "DACR Switch", "DACR"},
+ {"HPR Mixer", "DACL Switch", "DACL"},
+};
+
+static bool max98090_volatile(struct device *dev, unsigned int reg)
+{
+ if ((reg == MAX98090_0x01_INT_STS) ||
+ (reg == MAX98090_0x02_JACK_STS) ||
+ (reg > MAX98090_REG_MAX_CACHED))
+ return true;
+
+ return false;
+}
+
+static int max98090_dai_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai)
+{
+ struct snd_soc_codec *codec = dai->codec;
+ unsigned int val;
+
+ switch (params_rate(params)) {
+ case 96000:
+ val = 1 << 5;
+ break;
+ case 32000:
+ val = 1 << 4;
+ break;
+ case 48000:
+ val = 1 << 3;
+ break;
+ case 44100:
+ val = 1 << 2;
+ break;
+ case 16000:
+ val = 1 << 1;
+ break;
+ case 8000:
+ val = 1 << 0;
+ break;
+ default:
+ dev_err(codec->dev, "unsupported rate\n");
+ return -EINVAL;
+ }
+ snd_soc_update_bits(codec, MAX98090_0x05_SAMPLE_RATE, 0x03F, val);
+
+ return 0;
+}
+
+static int max98090_dai_set_sysclk(struct snd_soc_dai *dai,
+ int clk_id, unsigned int freq, int dir)
+{
+ struct snd_soc_codec *codec = dai->codec;
+ unsigned int val;
+
+ snd_soc_update_bits(codec, MAX98090_0x45_DEV_SHUTDOWN,
+ MAX98090_SHDNRUN, 0);
+
+ switch (freq) {
+ case 26000000:
+ val = 1 << 7;
+ break;
+ case 19200000:
+ val = 1 << 6;
+ break;
+ case 13000000:
+ val = 1 << 5;
+ break;
+ case 12288000:
+ val = 1 << 4;
+ break;
+ case 12000000:
+ val = 1 << 3;
+ break;
+ case 11289600:
+ val = 1 << 2;
+ break;
+ default:
+ dev_err(codec->dev, "Invalid master clock frequency\n");
+ return -EINVAL;
+ }
+ snd_soc_update_bits(codec, MAX98090_0x04_SYS_CLK, 0xFD, val);
+
+ snd_soc_update_bits(codec, MAX98090_0x45_DEV_SHUTDOWN,
+ MAX98090_SHDNRUN, MAX98090_SHDNRUN);
+
+ dev_dbg(dai->dev, "sysclk is %uHz\n", freq);
+
+ return 0;
+}
+
+static int max98090_dai_set_fmt(struct snd_soc_dai *dai,
+ unsigned int fmt)
+{
+ struct snd_soc_codec *codec = dai->codec;
+ int is_master;
+ u8 val;
+
+ /* master/slave mode */
+ switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+ case SND_SOC_DAIFMT_CBM_CFM:
+ is_master = 1;
+ break;
+ case SND_SOC_DAIFMT_CBS_CFS:
+ is_master = 0;
+ break;
+ default:
+ dev_err(codec->dev, "unsupported clock\n");
+ return -EINVAL;
+ }
+
+ /* format */
+ switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+ case SND_SOC_DAIFMT_I2S:
+ val = (is_master) ? MAX98090_I2S_M : MAX98090_I2S_S;
+ break;
+ case SND_SOC_DAIFMT_RIGHT_J:
+ val = (is_master) ? MAX98090_RJ_M : MAX98090_RJ_S;
+ break;
+ case SND_SOC_DAIFMT_LEFT_J:
+ val = (is_master) ? MAX98090_LJ_M : MAX98090_LJ_S;
+ break;
+ default:
+ dev_err(codec->dev, "unsupported format\n");
+ return -EINVAL;
+ }
+ snd_soc_update_bits(codec, MAX98090_0x06_DAI_IF,
+ MAX98090_DAI_IF_MASK, val);
+
+ return 0;
+}
+
+#define MAX98090_RATES SNDRV_PCM_RATE_8000_96000
+#define MAX98090_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE)
+
+static struct snd_soc_dai_ops max98090_dai_ops = {
+ .set_sysclk = max98090_dai_set_sysclk,
+ .set_fmt = max98090_dai_set_fmt,
+ .hw_params = max98090_dai_hw_params,
+};
+
+static struct snd_soc_dai_driver max98090_dai = {
+ .name = "max98090-Hifi",
+ .playback = {
+ .stream_name = "Playback",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = MAX98090_RATES,
+ .formats = MAX98090_FORMATS,
+ },
+ .ops = &max98090_dai_ops,
+};
+
+static int max98090_probe(struct snd_soc_codec *codec)
+{
+ struct max98090_priv *priv = snd_soc_codec_get_drvdata(codec);
+ struct device *dev = codec->dev;
+ int ret;
+
+ codec->control_data = priv->regmap;
+ ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP);
+ if (ret < 0) {
+ dev_err(dev, "Failed to set cache I/O: %d\n", ret);
+ return ret;
+ }
+
+ /* Device active */
+ snd_soc_update_bits(codec, MAX98090_0x45_DEV_SHUTDOWN,
+ MAX98090_SHDNRUN, MAX98090_SHDNRUN);
+
+ return 0;
+}
+
+static int max98090_remove(struct snd_soc_codec *codec)
+{
+ return 0;
+}
+
+static struct snd_soc_codec_driver soc_codec_dev_max98090 = {
+ .probe = max98090_probe,
+ .remove = max98090_remove,
+ .controls = max98090_snd_controls,
+ .num_controls = ARRAY_SIZE(max98090_snd_controls),
+ .dapm_widgets = max98090_dapm_widgets,
+ .num_dapm_widgets = ARRAY_SIZE(max98090_dapm_widgets),
+ .dapm_routes = max98090_audio_map,
+ .num_dapm_routes = ARRAY_SIZE(max98090_audio_map),
+};
+
+static const struct regmap_config max98090_regmap = {
+ .reg_bits = 8,
+ .val_bits = 8,
+ .max_register = MAX98090_REG_END,
+ .volatile_reg = max98090_volatile,
+ .cache_type = REGCACHE_RBTREE,
+ .reg_defaults = max98090_reg_defaults,
+ .num_reg_defaults = ARRAY_SIZE(max98090_reg_defaults),
+};
+
+static int max98090_i2c_probe(struct i2c_client *i2c,
+ const struct i2c_device_id *id)
+{
+ struct max98090_priv *priv;
+ struct device *dev = &i2c->dev;
+ unsigned int val;
+ int ret;
+
+ priv = devm_kzalloc(dev, sizeof(struct max98090_priv),
+ GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ priv->regmap = devm_regmap_init_i2c(i2c, &max98090_regmap);
+ if (IS_ERR(priv->regmap)) {
+ ret = PTR_ERR(priv->regmap);
+ dev_err(dev, "Failed to init regmap: %d\n", ret);
+ return ret;
+ }
+
+ i2c_set_clientdata(i2c, priv);
+
+ ret = regmap_read(priv->regmap, MAX98090_0xFF_REV_ID, &val);
+ if (ret < 0) {
+ dev_err(dev, "Failed to read device revision: %d\n", ret);
+ return ret;
+ }
+ dev_info(dev, "revision 0x%02x\n", val);
+
+ ret = snd_soc_register_codec(dev,
+ &soc_codec_dev_max98090,
+ &max98090_dai, 1);
+
+ return ret;
+}
+
+static int max98090_i2c_remove(struct i2c_client *client)
+{
+ snd_soc_unregister_codec(&client->dev);
+ return 0;
+}
+
+static const struct i2c_device_id max98090_i2c_id[] = {
+ { "max98090", 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, max98090_i2c_id);
+
+static struct i2c_driver max98090_i2c_driver = {
+ .driver = {
+ .name = "max98090",
+ .owner = THIS_MODULE,
+ },
+ .probe = max98090_i2c_probe,
+ .remove = max98090_i2c_remove,
+ .id_table = max98090_i2c_id,
+};
+module_i2c_driver(max98090_i2c_driver);
+
+MODULE_DESCRIPTION("ALSA SoC MAX98090 driver");
+MODULE_AUTHOR("Peter Hsiang, Kuninori Morimoto");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/max98095.c b/sound/soc/codecs/max98095.c
index 38d43c59d3f4..41cdd1642970 100644
--- a/sound/soc/codecs/max98095.c
+++ b/sound/soc/codecs/max98095.c
@@ -2511,7 +2511,7 @@ static int max98095_i2c_probe(struct i2c_client *i2c,
return ret;
}
-static int __devexit max98095_i2c_remove(struct i2c_client *client)
+static int max98095_i2c_remove(struct i2c_client *client)
{
snd_soc_unregister_codec(&client->dev);
return 0;
@@ -2529,7 +2529,7 @@ static struct i2c_driver max98095_i2c_driver = {
.owner = THIS_MODULE,
},
.probe = max98095_i2c_probe,
- .remove = __devexit_p(max98095_i2c_remove),
+ .remove = max98095_i2c_remove,
.id_table = max98095_i2c_id,
};
diff --git a/sound/soc/codecs/max9850.c b/sound/soc/codecs/max9850.c
index efe535c37b39..58c38a5b481c 100644
--- a/sound/soc/codecs/max9850.c
+++ b/sound/soc/codecs/max9850.c
@@ -329,8 +329,8 @@ static struct snd_soc_codec_driver soc_codec_dev_max9850 = {
.num_dapm_routes = ARRAY_SIZE(max9850_dapm_routes),
};
-static int __devinit max9850_i2c_probe(struct i2c_client *i2c,
- const struct i2c_device_id *id)
+static int max9850_i2c_probe(struct i2c_client *i2c,
+ const struct i2c_device_id *id)
{
struct max9850_priv *max9850;
int ret;
@@ -347,7 +347,7 @@ static int __devinit max9850_i2c_probe(struct i2c_client *i2c,
return ret;
}
-static __devexit int max9850_i2c_remove(struct i2c_client *client)
+static int max9850_i2c_remove(struct i2c_client *client)
{
snd_soc_unregister_codec(&client->dev);
return 0;
@@ -365,7 +365,7 @@ static struct i2c_driver max9850_i2c_driver = {
.owner = THIS_MODULE,
},
.probe = max9850_i2c_probe,
- .remove = __devexit_p(max9850_i2c_remove),
+ .remove = max9850_i2c_remove,
.id_table = max9850_i2c_id,
};
diff --git a/sound/soc/codecs/max9877.c b/sound/soc/codecs/max9877.c
index d15e5943c85e..6b6c74cd83e2 100644
--- a/sound/soc/codecs/max9877.c
+++ b/sound/soc/codecs/max9877.c
@@ -258,8 +258,8 @@ int max9877_add_controls(struct snd_soc_codec *codec)
}
EXPORT_SYMBOL_GPL(max9877_add_controls);
-static int __devinit max9877_i2c_probe(struct i2c_client *client,
- const struct i2c_device_id *id)
+static int max9877_i2c_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
{
i2c = client;
@@ -268,7 +268,7 @@ static int __devinit max9877_i2c_probe(struct i2c_client *client,
return 0;
}
-static __devexit int max9877_i2c_remove(struct i2c_client *client)
+static int max9877_i2c_remove(struct i2c_client *client)
{
i2c = NULL;
@@ -287,7 +287,7 @@ static struct i2c_driver max9877_i2c_driver = {
.owner = THIS_MODULE,
},
.probe = max9877_i2c_probe,
- .remove = __devexit_p(max9877_i2c_remove),
+ .remove = max9877_i2c_remove,
.id_table = max9877_i2c_id,
};
diff --git a/sound/soc/codecs/mc13783.c b/sound/soc/codecs/mc13783.c
index bc955999c8aa..5402dfbbb716 100644
--- a/sound/soc/codecs/mc13783.c
+++ b/sound/soc/codecs/mc13783.c
@@ -779,7 +779,7 @@ static struct platform_driver mc13783_codec_driver = {
.owner = THIS_MODULE,
},
.probe = mc13783_codec_probe,
- .remove = __devexit_p(mc13783_codec_remove),
+ .remove = mc13783_codec_remove,
};
module_platform_driver(mc13783_codec_driver);
diff --git a/sound/soc/codecs/ml26124.c b/sound/soc/codecs/ml26124.c
index 96aa5fa05160..26118828782b 100644
--- a/sound/soc/codecs/ml26124.c
+++ b/sound/soc/codecs/ml26124.c
@@ -626,8 +626,8 @@ static const struct regmap_config ml26124_i2c_regmap = {
.write_flag_mask = 0x01,
};
-static __devinit int ml26124_i2c_probe(struct i2c_client *i2c,
- const struct i2c_device_id *id)
+static int ml26124_i2c_probe(struct i2c_client *i2c,
+ const struct i2c_device_id *id)
{
struct ml26124_priv *priv;
int ret;
@@ -649,7 +649,7 @@ static __devinit int ml26124_i2c_probe(struct i2c_client *i2c,
&soc_codec_dev_ml26124, &ml26124_dai, 1);
}
-static __devexit int ml26124_i2c_remove(struct i2c_client *client)
+static int ml26124_i2c_remove(struct i2c_client *client)
{
snd_soc_unregister_codec(&client->dev);
return 0;
@@ -667,7 +667,7 @@ static struct i2c_driver ml26124_i2c_driver = {
.owner = THIS_MODULE,
},
.probe = ml26124_i2c_probe,
- .remove = __devexit_p(ml26124_i2c_remove),
+ .remove = ml26124_i2c_remove,
.id_table = ml26124_i2c_id,
};
diff --git a/sound/soc/codecs/omap-hdmi.c b/sound/soc/codecs/omap-hdmi.c
index 1bf5c74f5f96..529d06444c54 100644
--- a/sound/soc/codecs/omap-hdmi.c
+++ b/sound/soc/codecs/omap-hdmi.c
@@ -39,13 +39,13 @@ static struct snd_soc_dai_driver omap_hdmi_codec_dai = {
},
};
-static __devinit int omap_hdmi_codec_probe(struct platform_device *pdev)
+static int omap_hdmi_codec_probe(struct platform_device *pdev)
{
return snd_soc_register_codec(&pdev->dev, &omap_hdmi_codec,
&omap_hdmi_codec_dai, 1);
}
-static __devexit int omap_hdmi_codec_remove(struct platform_device *pdev)
+static int omap_hdmi_codec_remove(struct platform_device *pdev)
{
snd_soc_unregister_codec(&pdev->dev);
return 0;
@@ -58,7 +58,7 @@ static struct platform_driver omap_hdmi_codec_driver = {
},
.probe = omap_hdmi_codec_probe,
- .remove = __devexit_p(omap_hdmi_codec_remove),
+ .remove = omap_hdmi_codec_remove,
};
module_platform_driver(omap_hdmi_codec_driver);
diff --git a/sound/soc/codecs/pcm3008.c b/sound/soc/codecs/pcm3008.c
index edcaa7ea5487..f2a6282b41f4 100644
--- a/sound/soc/codecs/pcm3008.c
+++ b/sound/soc/codecs/pcm3008.c
@@ -149,13 +149,13 @@ static struct snd_soc_codec_driver soc_codec_dev_pcm3008 = {
.resume = pcm3008_soc_resume,
};
-static int __devinit pcm3008_codec_probe(struct platform_device *pdev)
+static int pcm3008_codec_probe(struct platform_device *pdev)
{
return snd_soc_register_codec(&pdev->dev,
&soc_codec_dev_pcm3008, &pcm3008_dai, 1);
}
-static int __devexit pcm3008_codec_remove(struct platform_device *pdev)
+static int pcm3008_codec_remove(struct platform_device *pdev)
{
snd_soc_unregister_codec(&pdev->dev);
return 0;
@@ -165,7 +165,7 @@ MODULE_ALIAS("platform:pcm3008-codec");
static struct platform_driver pcm3008_codec_driver = {
.probe = pcm3008_codec_probe,
- .remove = __devexit_p(pcm3008_codec_remove),
+ .remove = pcm3008_codec_remove,
.driver = {
.name = "pcm3008-codec",
.owner = THIS_MODULE,
diff --git a/sound/soc/codecs/rt5631.c b/sound/soc/codecs/rt5631.c
index 960d0e93cce9..912c9cbc2724 100644
--- a/sound/soc/codecs/rt5631.c
+++ b/sound/soc/codecs/rt5631.c
@@ -1382,7 +1382,7 @@ static int rt5631_hifi_pcm_params(struct snd_pcm_substream *substream,
timesofbclk);
if (coeff < 0) {
dev_err(codec->dev, "Fail to get coeff\n");
- return -EINVAL;
+ return coeff;
}
switch (params_format(params)) {
@@ -1748,7 +1748,7 @@ static int rt5631_i2c_probe(struct i2c_client *i2c,
return ret;
}
-static __devexit int rt5631_i2c_remove(struct i2c_client *client)
+static int rt5631_i2c_remove(struct i2c_client *client)
{
snd_soc_unregister_codec(&client->dev);
return 0;
@@ -1760,7 +1760,7 @@ static struct i2c_driver rt5631_i2c_driver = {
.owner = THIS_MODULE,
},
.probe = rt5631_i2c_probe,
- .remove = __devexit_p(rt5631_i2c_remove),
+ .remove = rt5631_i2c_remove,
.id_table = rt5631_i2c_id,
};
diff --git a/sound/soc/codecs/sgtl5000.c b/sound/soc/codecs/sgtl5000.c
index df2f99d1d428..cb1675cd8e1c 100644
--- a/sound/soc/codecs/sgtl5000.c
+++ b/sound/soc/codecs/sgtl5000.c
@@ -1404,8 +1404,8 @@ static struct snd_soc_codec_driver sgtl5000_driver = {
.num_dapm_routes = ARRAY_SIZE(sgtl5000_dapm_routes),
};
-static __devinit int sgtl5000_i2c_probe(struct i2c_client *client,
- const struct i2c_device_id *id)
+static int sgtl5000_i2c_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
{
struct sgtl5000_priv *sgtl5000;
int ret;
@@ -1422,7 +1422,7 @@ static __devinit int sgtl5000_i2c_probe(struct i2c_client *client,
return ret;
}
-static __devexit int sgtl5000_i2c_remove(struct i2c_client *client)
+static int sgtl5000_i2c_remove(struct i2c_client *client)
{
snd_soc_unregister_codec(&client->dev);
@@ -1449,7 +1449,7 @@ static struct i2c_driver sgtl5000_i2c_driver = {
.of_match_table = sgtl5000_dt_ids,
},
.probe = sgtl5000_i2c_probe,
- .remove = __devexit_p(sgtl5000_i2c_remove),
+ .remove = sgtl5000_i2c_remove,
.id_table = sgtl5000_id,
};
diff --git a/sound/soc/codecs/si476x.c b/sound/soc/codecs/si476x.c
new file mode 100644
index 000000000000..f2d61a187830
--- /dev/null
+++ b/sound/soc/codecs/si476x.c
@@ -0,0 +1,255 @@
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/initval.h>
+
+#include <linux/i2c.h>
+
+#include <linux/mfd/si476x-core.h>
+
+enum si476x_audio_registers {
+ SI476X_DIGITAL_IO_OUTPUT_FORMAT = 0x0203,
+ SI476X_DIGITAL_IO_OUTPUT_SAMPLE_RATE = 0x0202,
+};
+
+enum si476x_digital_io_output_format {
+ SI476X_DIGITAL_IO_SLOT_SIZE_SHIFT = 11,
+ SI476X_DIGITAL_IO_SAMPLE_SIZE_SHIFT = 8,
+};
+
+#define SI476X_DIGITAL_IO_OUTPUT_WIDTH_MASK ((0b111 << SI476X_DIGITAL_IO_SLOT_SIZE_SHIFT) | \
+ (0b111 << SI476X_DIGITAL_IO_SAMPLE_SIZE_SHIFT))
+#define SI476X_DIGITAL_IO_OUTPUT_FORMAT_MASK (0b1111110)
+
+enum si476x_daudio_formats {
+ SI476X_DAUDIO_MODE_I2S = (0x0 << 1),
+ SI476X_DAUDIO_MODE_DSP_A = (0x6 << 1),
+ SI476X_DAUDIO_MODE_DSP_B = (0x7 << 1),
+ SI476X_DAUDIO_MODE_LEFT_J = (0x8 << 1),
+ SI476X_DAUDIO_MODE_RIGHT_J = (0x9 << 1),
+
+ SI476X_DAUDIO_MODE_IB = (1 << 5),
+ SI476X_DAUDIO_MODE_IF = (1 << 6),
+};
+
+enum si476x_pcm_format {
+ SI476X_PCM_FORMAT_S8 = 2,
+ SI476X_PCM_FORMAT_S16_LE = 4,
+ SI476X_PCM_FORMAT_S20_3LE = 5,
+ SI476X_PCM_FORMAT_S24_LE = 6,
+};
+
+static unsigned int si476x_codec_read(struct snd_soc_codec *codec,
+ unsigned int reg)
+{
+ int err;
+ struct si476x_core *core = codec->control_data;
+
+ si476x_core_lock(core);
+ err = si476x_core_cmd_get_property(core, reg);
+ si476x_core_unlock(core);
+
+ return err;
+}
+
+static int si476x_codec_write(struct snd_soc_codec *codec,
+ unsigned int reg, unsigned int val)
+{
+ int err;
+ struct si476x_core *core = codec->control_data;
+
+ si476x_core_lock(core);
+ err = si476x_core_cmd_set_property(core, reg, val);
+ si476x_core_unlock(core);
+
+ return err;
+}
+
+static int si476x_codec_set_dai_fmt(struct snd_soc_dai *codec_dai,
+ unsigned int fmt)
+{
+ int err;
+ u16 format = 0;
+
+ if ((fmt & SND_SOC_DAIFMT_MASTER_MASK) != SND_SOC_DAIFMT_CBS_CFS)
+ return -EINVAL;
+
+ switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+ case SND_SOC_DAIFMT_DSP_A:
+ format |= SI476X_DAUDIO_MODE_DSP_A;
+ break;
+ case SND_SOC_DAIFMT_DSP_B:
+ format |= SI476X_DAUDIO_MODE_DSP_B;
+ break;
+ case SND_SOC_DAIFMT_I2S:
+ format |= SI476X_DAUDIO_MODE_I2S;
+ break;
+ case SND_SOC_DAIFMT_RIGHT_J:
+ format |= SI476X_DAUDIO_MODE_RIGHT_J;
+ break;
+ case SND_SOC_DAIFMT_LEFT_J:
+ format |= SI476X_DAUDIO_MODE_LEFT_J;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+ case SND_SOC_DAIFMT_DSP_A:
+ case SND_SOC_DAIFMT_DSP_B:
+ switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
+ case SND_SOC_DAIFMT_NB_NF:
+ break;
+ case SND_SOC_DAIFMT_IB_NF:
+ format |= SI476X_DAUDIO_MODE_IB;
+ break;
+ default:
+ return -EINVAL;
+ }
+ break;
+ case SND_SOC_DAIFMT_I2S:
+ case SND_SOC_DAIFMT_RIGHT_J:
+ case SND_SOC_DAIFMT_LEFT_J:
+ switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
+ case SND_SOC_DAIFMT_NB_NF:
+ break;
+ case SND_SOC_DAIFMT_IB_IF:
+ format |= SI476X_DAUDIO_MODE_IB |
+ SI476X_DAUDIO_MODE_IF;
+ break;
+ case SND_SOC_DAIFMT_IB_NF:
+ format |= SI476X_DAUDIO_MODE_IB;
+ break;
+ case SND_SOC_DAIFMT_NB_IF:
+ format |= SI476X_DAUDIO_MODE_IF;
+ break;
+ default:
+ return -EINVAL;
+ }
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ err = snd_soc_update_bits(codec_dai->codec, SI476X_DIGITAL_IO_OUTPUT_FORMAT,
+ SI476X_DIGITAL_IO_OUTPUT_FORMAT_MASK,
+ format);
+ if (err < 0) {
+ dev_err(codec_dai->codec->dev, "Failed to set output format\n");
+ return err;
+ }
+
+ return 0;
+}
+
+static int si476x_codec_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai)
+{
+ int rate, width, err;
+
+ rate = params_rate(params);
+ if (rate < 32000 || rate > 48000) {
+ dev_err(dai->codec->dev, "Rate: %d is not supported\n", rate);
+ return -EINVAL;
+ }
+
+ switch (params_format(params)) {
+ case SNDRV_PCM_FORMAT_S8:
+ width = SI476X_PCM_FORMAT_S8;
+ case SNDRV_PCM_FORMAT_S16_LE:
+ width = SI476X_PCM_FORMAT_S16_LE;
+ break;
+ case SNDRV_PCM_FORMAT_S20_3LE:
+ width = SI476X_PCM_FORMAT_S20_3LE;
+ break;
+ case SNDRV_PCM_FORMAT_S24_LE:
+ width = SI476X_PCM_FORMAT_S24_LE;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ err = snd_soc_write(dai->codec, SI476X_DIGITAL_IO_OUTPUT_SAMPLE_RATE,
+ rate);
+ if (err < 0) {
+ dev_err(dai->codec->dev, "Failed to set sample rate\n");
+ return err;
+ }
+
+ err = snd_soc_update_bits(dai->codec, SI476X_DIGITAL_IO_OUTPUT_FORMAT,
+ SI476X_DIGITAL_IO_OUTPUT_WIDTH_MASK,
+ (width << SI476X_DIGITAL_IO_SLOT_SIZE_SHIFT) |
+ (width << SI476X_DIGITAL_IO_SAMPLE_SIZE_SHIFT));
+ if (err < 0) {
+ dev_err(dai->codec->dev, "Failed to set output width\n");
+ return err;
+ }
+
+ return 0;
+}
+
+static int si476x_codec_probe(struct snd_soc_codec *codec)
+{
+ codec->control_data = i2c_mfd_cell_to_core(codec->dev);
+ return 0;
+}
+
+static struct snd_soc_dai_ops si476x_dai_ops = {
+ .hw_params = si476x_codec_hw_params,
+ .set_fmt = si476x_codec_set_dai_fmt,
+};
+
+static struct snd_soc_dai_driver si476x_dai = {
+ .name = "si476x-codec",
+ .capture = {
+ .stream_name = "Capture",
+ .channels_min = 2,
+ .channels_max = 2,
+
+ .rates = SNDRV_PCM_RATE_32000 |
+ SNDRV_PCM_RATE_44100 |
+ SNDRV_PCM_RATE_48000,
+ .formats = SNDRV_PCM_FMTBIT_S8 |
+ SNDRV_PCM_FMTBIT_S16_LE |
+ SNDRV_PCM_FMTBIT_S20_3LE |
+ SNDRV_PCM_FMTBIT_S24_LE
+ },
+ .ops = &si476x_dai_ops,
+};
+
+static struct snd_soc_codec_driver soc_codec_dev_si476x = {
+ .probe = si476x_codec_probe,
+ .read = si476x_codec_read,
+ .write = si476x_codec_write,
+};
+
+static int si476x_platform_probe(struct platform_device *pdev)
+{
+ return snd_soc_register_codec(&pdev->dev, &soc_codec_dev_si476x,
+ &si476x_dai, 1);
+}
+
+static int si476x_platform_remove(struct platform_device *pdev)
+{
+ snd_soc_unregister_codec(&pdev->dev);
+ return 0;
+}
+
+MODULE_ALIAS("platform:si476x-codec");
+
+static struct platform_driver si476x_platform_driver = {
+ .driver = {
+ .name = "si476x-codec",
+ .owner = THIS_MODULE,
+ },
+ .probe = si476x_platform_probe,
+ .remove = si476x_platform_remove,
+};
+module_platform_driver(si476x_platform_driver);
+
+MODULE_AUTHOR("Andrey Smirnov <andrey.smirnov@convergeddevices.net>");
+MODULE_DESCRIPTION("ASoC Si4761/64 codec driver");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/sn95031.c b/sound/soc/codecs/sn95031.c
index 50dbdb9357ea..d1ae869d3181 100644
--- a/sound/soc/codecs/sn95031.c
+++ b/sound/soc/codecs/sn95031.c
@@ -896,14 +896,14 @@ struct snd_soc_codec_driver sn95031_codec = {
.num_dapm_routes = ARRAY_SIZE(sn95031_audio_map),
};
-static int __devinit sn95031_device_probe(struct platform_device *pdev)
+static int sn95031_device_probe(struct platform_device *pdev)
{
pr_debug("codec device probe called for %s\n", dev_name(&pdev->dev));
return snd_soc_register_codec(&pdev->dev, &sn95031_codec,
sn95031_dais, ARRAY_SIZE(sn95031_dais));
}
-static int __devexit sn95031_device_remove(struct platform_device *pdev)
+static int sn95031_device_remove(struct platform_device *pdev)
{
pr_debug("codec device remove called\n");
snd_soc_unregister_codec(&pdev->dev);
@@ -916,7 +916,7 @@ static struct platform_driver sn95031_codec_driver = {
.owner = THIS_MODULE,
},
.probe = sn95031_device_probe,
- .remove = __devexit_p(sn95031_device_remove),
+ .remove = sn95031_device_remove,
};
module_platform_driver(sn95031_codec_driver);
diff --git a/sound/soc/codecs/ssm2602.c b/sound/soc/codecs/ssm2602.c
index 079066fef425..f8d30e5f6371 100644
--- a/sound/soc/codecs/ssm2602.c
+++ b/sound/soc/codecs/ssm2602.c
@@ -691,7 +691,7 @@ static const struct regmap_config ssm2602_regmap_config = {
};
#if defined(CONFIG_SPI_MASTER)
-static int __devinit ssm2602_spi_probe(struct spi_device *spi)
+static int ssm2602_spi_probe(struct spi_device *spi)
{
struct ssm2602_priv *ssm2602;
int ret;
@@ -713,7 +713,7 @@ static int __devinit ssm2602_spi_probe(struct spi_device *spi)
return ret;
}
-static int __devexit ssm2602_spi_remove(struct spi_device *spi)
+static int ssm2602_spi_remove(struct spi_device *spi)
{
snd_soc_unregister_codec(&spi->dev);
return 0;
@@ -725,7 +725,7 @@ static struct spi_driver ssm2602_spi_driver = {
.owner = THIS_MODULE,
},
.probe = ssm2602_spi_probe,
- .remove = __devexit_p(ssm2602_spi_remove),
+ .remove = ssm2602_spi_remove,
};
#endif
@@ -736,7 +736,7 @@ static struct spi_driver ssm2602_spi_driver = {
* low = 0x1a
* high = 0x1b
*/
-static int __devinit ssm2602_i2c_probe(struct i2c_client *i2c,
+static int ssm2602_i2c_probe(struct i2c_client *i2c,
const struct i2c_device_id *id)
{
struct ssm2602_priv *ssm2602;
@@ -759,7 +759,7 @@ static int __devinit ssm2602_i2c_probe(struct i2c_client *i2c,
return ret;
}
-static int __devexit ssm2602_i2c_remove(struct i2c_client *client)
+static int ssm2602_i2c_remove(struct i2c_client *client)
{
snd_soc_unregister_codec(&client->dev);
return 0;
@@ -780,7 +780,7 @@ static struct i2c_driver ssm2602_i2c_driver = {
.owner = THIS_MODULE,
},
.probe = ssm2602_i2c_probe,
- .remove = __devexit_p(ssm2602_i2c_remove),
+ .remove = ssm2602_i2c_remove,
.id_table = ssm2602_i2c_id,
};
#endif
diff --git a/sound/soc/codecs/sta32x.c b/sound/soc/codecs/sta32x.c
index 0935bfe62471..cfb55fe35e98 100644
--- a/sound/soc/codecs/sta32x.c
+++ b/sound/soc/codecs/sta32x.c
@@ -995,8 +995,8 @@ static const struct regmap_config sta32x_regmap = {
.volatile_reg = sta32x_reg_is_volatile,
};
-static __devinit int sta32x_i2c_probe(struct i2c_client *i2c,
- const struct i2c_device_id *id)
+static int sta32x_i2c_probe(struct i2c_client *i2c,
+ const struct i2c_device_id *id)
{
struct sta32x_priv *sta32x;
int ret, i;
@@ -1033,7 +1033,7 @@ static __devinit int sta32x_i2c_probe(struct i2c_client *i2c,
return ret;
}
-static __devexit int sta32x_i2c_remove(struct i2c_client *client)
+static int sta32x_i2c_remove(struct i2c_client *client)
{
snd_soc_unregister_codec(&client->dev);
return 0;
@@ -1053,7 +1053,7 @@ static struct i2c_driver sta32x_i2c_driver = {
.owner = THIS_MODULE,
},
.probe = sta32x_i2c_probe,
- .remove = __devexit_p(sta32x_i2c_remove),
+ .remove = sta32x_i2c_remove,
.id_table = sta32x_i2c_id,
};
diff --git a/sound/soc/codecs/sta529.c b/sound/soc/codecs/sta529.c
index 9e3144862386..ab355c4f0b2d 100644
--- a/sound/soc/codecs/sta529.c
+++ b/sound/soc/codecs/sta529.c
@@ -380,8 +380,8 @@ static const struct regmap_config sta529_regmap = {
.num_reg_defaults = ARRAY_SIZE(sta529_reg_defaults),
};
-static __devinit int sta529_i2c_probe(struct i2c_client *i2c,
- const struct i2c_device_id *id)
+static int sta529_i2c_probe(struct i2c_client *i2c,
+ const struct i2c_device_id *id)
{
struct sta529 *sta529;
int ret;
@@ -412,7 +412,7 @@ static __devinit int sta529_i2c_probe(struct i2c_client *i2c,
return ret;
}
-static int __devexit sta529_i2c_remove(struct i2c_client *client)
+static int sta529_i2c_remove(struct i2c_client *client)
{
snd_soc_unregister_codec(&client->dev);
@@ -431,7 +431,7 @@ static struct i2c_driver sta529_i2c_driver = {
.owner = THIS_MODULE,
},
.probe = sta529_i2c_probe,
- .remove = __devexit_p(sta529_i2c_remove),
+ .remove = sta529_i2c_remove,
.id_table = sta529_i2c_id,
};
diff --git a/sound/soc/codecs/stac9766.c b/sound/soc/codecs/stac9766.c
index 982e437799a8..2eda85ba79ac 100644
--- a/sound/soc/codecs/stac9766.c
+++ b/sound/soc/codecs/stac9766.c
@@ -385,13 +385,13 @@ static struct snd_soc_codec_driver soc_codec_dev_stac9766 = {
.reg_cache_default = stac9766_reg,
};
-static __devinit int stac9766_probe(struct platform_device *pdev)
+static int stac9766_probe(struct platform_device *pdev)
{
return snd_soc_register_codec(&pdev->dev,
&soc_codec_dev_stac9766, stac9766_dai, ARRAY_SIZE(stac9766_dai));
}
-static int __devexit stac9766_remove(struct platform_device *pdev)
+static int stac9766_remove(struct platform_device *pdev)
{
snd_soc_unregister_codec(&pdev->dev);
return 0;
@@ -404,7 +404,7 @@ static struct platform_driver stac9766_codec_driver = {
},
.probe = stac9766_probe,
- .remove = __devexit_p(stac9766_remove),
+ .remove = stac9766_remove,
};
module_platform_driver(stac9766_codec_driver);
diff --git a/sound/soc/codecs/tlv320aic32x4.c b/sound/soc/codecs/tlv320aic32x4.c
index f230292ba96b..17df4e32feac 100644
--- a/sound/soc/codecs/tlv320aic32x4.c
+++ b/sound/soc/codecs/tlv320aic32x4.c
@@ -28,6 +28,7 @@
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/pm.h>
+#include <linux/gpio.h>
#include <linux/i2c.h>
#include <linux/cdev.h>
#include <linux/slab.h>
@@ -65,6 +66,7 @@ struct aic32x4_priv {
u32 power_cfg;
u32 micpga_routing;
bool swapdacs;
+ int rstn_gpio;
};
/* 0dB min, 1dB steps */
@@ -627,10 +629,20 @@ static int aic32x4_probe(struct snd_soc_codec *codec)
{
struct aic32x4_priv *aic32x4 = snd_soc_codec_get_drvdata(codec);
u32 tmp_reg;
+ int ret;
codec->hw_write = (hw_write_t) i2c_master_send;
codec->control_data = aic32x4->control_data;
+ if (aic32x4->rstn_gpio >= 0) {
+ ret = devm_gpio_request_one(codec->dev, aic32x4->rstn_gpio,
+ GPIOF_OUT_INIT_LOW, "tlv320aic32x4 rstn");
+ if (ret != 0)
+ return ret;
+ ndelay(10);
+ gpio_set_value(aic32x4->rstn_gpio, 1);
+ }
+
snd_soc_write(codec, AIC32X4_RESET, 0x01);
/* Power platform configuration */
@@ -675,6 +687,16 @@ static int aic32x4_probe(struct snd_soc_codec *codec)
ARRAY_SIZE(aic32x4_snd_controls));
aic32x4_add_widgets(codec);
+ /*
+ * Workaround: for an unknown reason, the ADC needs to be powered up
+ * and down for the first capture to work properly. It seems related to
+ * a HW BUG or some kind of behavior not documented in the datasheet.
+ */
+ tmp_reg = snd_soc_read(codec, AIC32X4_ADCSETUP);
+ snd_soc_write(codec, AIC32X4_ADCSETUP, tmp_reg |
+ AIC32X4_LADC_EN | AIC32X4_RADC_EN);
+ snd_soc_write(codec, AIC32X4_ADCSETUP, tmp_reg);
+
return 0;
}
@@ -694,8 +716,8 @@ static struct snd_soc_codec_driver soc_codec_dev_aic32x4 = {
.set_bias_level = aic32x4_set_bias_level,
};
-static __devinit int aic32x4_i2c_probe(struct i2c_client *i2c,
- const struct i2c_device_id *id)
+static int aic32x4_i2c_probe(struct i2c_client *i2c,
+ const struct i2c_device_id *id)
{
struct aic32x4_pdata *pdata = i2c->dev.platform_data;
struct aic32x4_priv *aic32x4;
@@ -713,10 +735,12 @@ static __devinit int aic32x4_i2c_probe(struct i2c_client *i2c,
aic32x4->power_cfg = pdata->power_cfg;
aic32x4->swapdacs = pdata->swapdacs;
aic32x4->micpga_routing = pdata->micpga_routing;
+ aic32x4->rstn_gpio = pdata->rstn_gpio;
} else {
aic32x4->power_cfg = 0;
aic32x4->swapdacs = false;
aic32x4->micpga_routing = 0;
+ aic32x4->rstn_gpio = -1;
}
ret = snd_soc_register_codec(&i2c->dev,
@@ -724,7 +748,7 @@ static __devinit int aic32x4_i2c_probe(struct i2c_client *i2c,
return ret;
}
-static __devexit int aic32x4_i2c_remove(struct i2c_client *client)
+static int aic32x4_i2c_remove(struct i2c_client *client)
{
snd_soc_unregister_codec(&client->dev);
return 0;
@@ -742,7 +766,7 @@ static struct i2c_driver aic32x4_i2c_driver = {
.owner = THIS_MODULE,
},
.probe = aic32x4_i2c_probe,
- .remove = __devexit_p(aic32x4_i2c_remove),
+ .remove = aic32x4_i2c_remove,
.id_table = aic32x4_i2c_id,
};
diff --git a/sound/soc/codecs/tlv320aic32x4.h b/sound/soc/codecs/tlv320aic32x4.h
index aae2b2440398..35774223fd91 100644
--- a/sound/soc/codecs/tlv320aic32x4.h
+++ b/sound/soc/codecs/tlv320aic32x4.h
@@ -94,6 +94,9 @@
#define AIC32X4_WORD_LEN_24BITS 0x02
#define AIC32X4_WORD_LEN_32BITS 0x03
+#define AIC32X4_LADC_EN (1 << 7)
+#define AIC32X4_RADC_EN (1 << 6)
+
#define AIC32X4_I2S_MODE 0x00
#define AIC32X4_DSP_MODE 0x01
#define AIC32X4_RIGHT_JUSTIFIED_MODE 0x02
diff --git a/sound/soc/codecs/tlv320dac33.c b/sound/soc/codecs/tlv320dac33.c
index d2e16c5d7d1f..782b0cded2e6 100644
--- a/sound/soc/codecs/tlv320dac33.c
+++ b/sound/soc/codecs/tlv320dac33.c
@@ -1514,8 +1514,8 @@ static struct snd_soc_dai_driver dac33_dai = {
.ops = &dac33_dai_ops,
};
-static int __devinit dac33_i2c_probe(struct i2c_client *client,
- const struct i2c_device_id *id)
+static int dac33_i2c_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
{
struct tlv320dac33_platform_data *pdata;
struct tlv320dac33_priv *dac33;
@@ -1586,7 +1586,7 @@ err_gpio:
return ret;
}
-static int __devexit dac33_i2c_remove(struct i2c_client *client)
+static int dac33_i2c_remove(struct i2c_client *client)
{
struct tlv320dac33_priv *dac33 = i2c_get_clientdata(client);
@@ -1617,7 +1617,7 @@ static struct i2c_driver tlv320dac33_i2c_driver = {
.owner = THIS_MODULE,
},
.probe = dac33_i2c_probe,
- .remove = __devexit_p(dac33_i2c_remove),
+ .remove = dac33_i2c_remove,
.id_table = tlv320dac33_i2c_id,
};
diff --git a/sound/soc/codecs/tpa6130a2.c b/sound/soc/codecs/tpa6130a2.c
index 565ff39ad3a3..8d75aa152c8c 100644
--- a/sound/soc/codecs/tpa6130a2.c
+++ b/sound/soc/codecs/tpa6130a2.c
@@ -359,8 +359,8 @@ int tpa6130a2_add_controls(struct snd_soc_codec *codec)
}
EXPORT_SYMBOL_GPL(tpa6130a2_add_controls);
-static int __devinit tpa6130a2_probe(struct i2c_client *client,
- const struct i2c_device_id *id)
+static int tpa6130a2_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
{
struct device *dev;
struct tpa6130a2_data *data;
@@ -455,7 +455,7 @@ err_gpio:
return ret;
}
-static int __devexit tpa6130a2_remove(struct i2c_client *client)
+static int tpa6130a2_remove(struct i2c_client *client)
{
struct tpa6130a2_data *data = i2c_get_clientdata(client);
@@ -483,7 +483,7 @@ static struct i2c_driver tpa6130a2_i2c_driver = {
.owner = THIS_MODULE,
},
.probe = tpa6130a2_probe,
- .remove = __devexit_p(tpa6130a2_remove),
+ .remove = tpa6130a2_remove,
.id_table = tpa6130a2_id,
};
diff --git a/sound/soc/codecs/twl4030.c b/sound/soc/codecs/twl4030.c
index e7f608996c41..63b280b06035 100644
--- a/sound/soc/codecs/twl4030.c
+++ b/sound/soc/codecs/twl4030.c
@@ -2334,13 +2334,13 @@ static struct snd_soc_codec_driver soc_codec_dev_twl4030 = {
.num_dapm_routes = ARRAY_SIZE(intercon),
};
-static int __devinit twl4030_codec_probe(struct platform_device *pdev)
+static int twl4030_codec_probe(struct platform_device *pdev)
{
return snd_soc_register_codec(&pdev->dev, &soc_codec_dev_twl4030,
twl4030_dai, ARRAY_SIZE(twl4030_dai));
}
-static int __devexit twl4030_codec_remove(struct platform_device *pdev)
+static int twl4030_codec_remove(struct platform_device *pdev)
{
snd_soc_unregister_codec(&pdev->dev);
return 0;
@@ -2350,7 +2350,7 @@ MODULE_ALIAS("platform:twl4030-codec");
static struct platform_driver twl4030_codec_driver = {
.probe = twl4030_codec_probe,
- .remove = __devexit_p(twl4030_codec_remove),
+ .remove = twl4030_codec_remove,
.driver = {
.name = "twl4030-codec",
.owner = THIS_MODULE,
diff --git a/sound/soc/codecs/twl6040.c b/sound/soc/codecs/twl6040.c
index 00b85cc1b9a3..3fc3fc64dd8b 100644
--- a/sound/soc/codecs/twl6040.c
+++ b/sound/soc/codecs/twl6040.c
@@ -1229,13 +1229,13 @@ static struct snd_soc_codec_driver soc_codec_dev_twl6040 = {
.num_dapm_routes = ARRAY_SIZE(intercon),
};
-static int __devinit twl6040_codec_probe(struct platform_device *pdev)
+static int twl6040_codec_probe(struct platform_device *pdev)
{
return snd_soc_register_codec(&pdev->dev, &soc_codec_dev_twl6040,
twl6040_dai, ARRAY_SIZE(twl6040_dai));
}
-static int __devexit twl6040_codec_remove(struct platform_device *pdev)
+static int twl6040_codec_remove(struct platform_device *pdev)
{
snd_soc_unregister_codec(&pdev->dev);
return 0;
@@ -1247,7 +1247,7 @@ static struct platform_driver twl6040_codec_driver = {
.owner = THIS_MODULE,
},
.probe = twl6040_codec_probe,
- .remove = __devexit_p(twl6040_codec_remove),
+ .remove = twl6040_codec_remove,
};
module_platform_driver(twl6040_codec_driver);
diff --git a/sound/soc/codecs/uda134x.c b/sound/soc/codecs/uda134x.c
index 6c3d43b8ee85..6d0aa44c3757 100644
--- a/sound/soc/codecs/uda134x.c
+++ b/sound/soc/codecs/uda134x.c
@@ -601,13 +601,13 @@ static struct snd_soc_codec_driver soc_codec_dev_uda134x = {
.set_bias_level = uda134x_set_bias_level,
};
-static int __devinit uda134x_codec_probe(struct platform_device *pdev)
+static int uda134x_codec_probe(struct platform_device *pdev)
{
return snd_soc_register_codec(&pdev->dev,
&soc_codec_dev_uda134x, &uda134x_dai, 1);
}
-static int __devexit uda134x_codec_remove(struct platform_device *pdev)
+static int uda134x_codec_remove(struct platform_device *pdev)
{
snd_soc_unregister_codec(&pdev->dev);
return 0;
@@ -619,7 +619,7 @@ static struct platform_driver uda134x_codec_driver = {
.owner = THIS_MODULE,
},
.probe = uda134x_codec_probe,
- .remove = __devexit_p(uda134x_codec_remove),
+ .remove = uda134x_codec_remove,
};
module_platform_driver(uda134x_codec_driver);
diff --git a/sound/soc/codecs/uda1380.c b/sound/soc/codecs/uda1380.c
index 2502214b84ab..fd0a314bc209 100644
--- a/sound/soc/codecs/uda1380.c
+++ b/sound/soc/codecs/uda1380.c
@@ -795,8 +795,8 @@ static struct snd_soc_codec_driver soc_codec_dev_uda1380 = {
};
#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
-static __devinit int uda1380_i2c_probe(struct i2c_client *i2c,
- const struct i2c_device_id *id)
+static int uda1380_i2c_probe(struct i2c_client *i2c,
+ const struct i2c_device_id *id)
{
struct uda1380_priv *uda1380;
int ret;
@@ -814,7 +814,7 @@ static __devinit int uda1380_i2c_probe(struct i2c_client *i2c,
return ret;
}
-static int __devexit uda1380_i2c_remove(struct i2c_client *i2c)
+static int uda1380_i2c_remove(struct i2c_client *i2c)
{
snd_soc_unregister_codec(&i2c->dev);
return 0;
@@ -832,7 +832,7 @@ static struct i2c_driver uda1380_i2c_driver = {
.owner = THIS_MODULE,
},
.probe = uda1380_i2c_probe,
- .remove = __devexit_p(uda1380_i2c_remove),
+ .remove = uda1380_i2c_remove,
.id_table = uda1380_i2c_id,
};
#endif
diff --git a/sound/soc/codecs/wl1273.c b/sound/soc/codecs/wl1273.c
index 7b24d6d192e1..54cd3da09abd 100644
--- a/sound/soc/codecs/wl1273.c
+++ b/sound/soc/codecs/wl1273.c
@@ -485,13 +485,13 @@ static struct snd_soc_codec_driver soc_codec_dev_wl1273 = {
.remove = wl1273_remove,
};
-static int __devinit wl1273_platform_probe(struct platform_device *pdev)
+static int wl1273_platform_probe(struct platform_device *pdev)
{
return snd_soc_register_codec(&pdev->dev, &soc_codec_dev_wl1273,
&wl1273_dai, 1);
}
-static int __devexit wl1273_platform_remove(struct platform_device *pdev)
+static int wl1273_platform_remove(struct platform_device *pdev)
{
snd_soc_unregister_codec(&pdev->dev);
return 0;
@@ -505,7 +505,7 @@ static struct platform_driver wl1273_platform_driver = {
.owner = THIS_MODULE,
},
.probe = wl1273_platform_probe,
- .remove = __devexit_p(wl1273_platform_remove),
+ .remove = wl1273_platform_remove,
};
module_platform_driver(wl1273_platform_driver);
diff --git a/sound/soc/codecs/wm0010.c b/sound/soc/codecs/wm0010.c
index 99afc003a084..ad2fee4bb4cd 100644
--- a/sound/soc/codecs/wm0010.c
+++ b/sound/soc/codecs/wm0010.c
@@ -31,6 +31,9 @@
#define DEVICE_ID_WM0010 10
+/* We only support v1 of the .dfw INFO record */
+#define INFO_VERSION 1
+
enum dfw_cmd {
DFW_CMD_FUSE = 0x01,
DFW_CMD_CODE_HDR,
@@ -46,6 +49,13 @@ struct dfw_binrec {
uint8_t data[0];
} __packed;
+struct dfw_inforec {
+ u8 info_version;
+ u8 tool_major_version;
+ u8 tool_minor_version;
+ u8 dsp_target;
+};
+
struct dfw_pllrec {
u8 command;
u32 length:24;
@@ -97,7 +107,6 @@ struct wm0010_priv {
enum wm0010_state state;
bool boot_failed;
- int boot_done;
bool ready;
bool pll_running;
int max_spi_freq;
@@ -234,7 +243,7 @@ static void wm0010_boot_xfer_complete(void *data)
break;
case 0x55555555:
- if (wm0010->boot_done == 0)
+ if (wm0010->state < WM0010_STAGE2)
break;
dev_err(codec->dev,
"%d: ROM bootloader running in stage 2\n", i);
@@ -321,7 +330,6 @@ static void wm0010_boot_xfer_complete(void *data)
break;
}
- wm0010->boot_done++;
if (xfer->done)
complete(xfer->done);
}
@@ -334,94 +342,198 @@ static void byte_swap_64(u64 *data_in, u64 *data_out, u32 len)
data_out[i] = cpu_to_be64(le64_to_cpu(data_in[i]));
}
-static int wm0010_boot(struct snd_soc_codec *codec)
+static int wm0010_firmware_load(char *name, struct snd_soc_codec *codec)
{
struct spi_device *spi = to_spi_device(codec->dev);
struct wm0010_priv *wm0010 = snd_soc_codec_get_drvdata(codec);
- unsigned long flags;
struct list_head xfer_list;
struct wm0010_boot_xfer *xfer;
int ret;
struct completion done;
const struct firmware *fw;
const struct dfw_binrec *rec;
- struct spi_message m;
- struct spi_transfer t;
- struct dfw_pllrec pll_rec;
- u32 *img, *p;
- u64 *img_swap;
- u8 *out;
+ const struct dfw_inforec *inforec;
+ u64 *img;
+ u8 *out, dsp;
u32 len, offset;
- int i;
- spin_lock_irqsave(&wm0010->irq_lock, flags);
- if (wm0010->state != WM0010_POWER_OFF)
- dev_warn(wm0010->dev, "DSP already powered up!\n");
- spin_unlock_irqrestore(&wm0010->irq_lock, flags);
+ INIT_LIST_HEAD(&xfer_list);
- if (wm0010->sysclk > 26000000) {
- dev_err(codec->dev, "Max DSP clock frequency is 26MHz\n");
- ret = -ECANCELED;
- goto err;
+ ret = request_firmware(&fw, name, codec->dev);
+ if (ret != 0) {
+ dev_err(codec->dev, "Failed to request application: %d\n",
+ ret);
+ return ret;
}
- INIT_LIST_HEAD(&xfer_list);
+ rec = (const struct dfw_binrec *)fw->data;
+ inforec = (const struct dfw_inforec *)rec->data;
+ offset = 0;
+ dsp = inforec->dsp_target;
+ wm0010->boot_failed = false;
+ BUG_ON(!list_empty(&xfer_list));
+ init_completion(&done);
- mutex_lock(&wm0010->lock);
- wm0010->pll_running = false;
+ /* First record should be INFO */
+ if (rec->command != DFW_CMD_INFO) {
+ dev_err(codec->dev, "First record not INFO\r\n");
+ ret = -EINVAL;
+ goto abort;
+ }
- dev_dbg(codec->dev, "max_spi_freq: %d\n", wm0010->max_spi_freq);
+ if (inforec->info_version != INFO_VERSION) {
+ dev_err(codec->dev,
+ "Unsupported version (%02d) of INFO record\r\n",
+ inforec->info_version);
+ ret = -EINVAL;
+ goto abort;
+ }
- ret = regulator_bulk_enable(ARRAY_SIZE(wm0010->core_supplies),
- wm0010->core_supplies);
- if (ret != 0) {
- dev_err(&spi->dev, "Failed to enable core supplies: %d\n",
- ret);
- mutex_unlock(&wm0010->lock);
- goto err;
+ dev_dbg(codec->dev, "Version v%02d INFO record found\r\n",
+ inforec->info_version);
+
+ /* Check it's a DSP file */
+ if (dsp != DEVICE_ID_WM0010) {
+ dev_err(codec->dev, "Not a WM0010 firmware file.\r\n");
+ ret = -EINVAL;
+ goto abort;
}
- ret = regulator_enable(wm0010->dbvdd);
- if (ret != 0) {
- dev_err(&spi->dev, "Failed to enable DBVDD: %d\n", ret);
- goto err_core;
+ /* Skip the info record as we don't need to send it */
+ offset += ((rec->length) + 8);
+ rec = (void *)&rec->data[rec->length];
+
+ while (offset < fw->size) {
+ dev_dbg(codec->dev,
+ "Packet: command %d, data length = 0x%x\r\n",
+ rec->command, rec->length);
+ len = rec->length + 8;
+
+ out = kzalloc(len, GFP_KERNEL);
+ if (!out) {
+ dev_err(codec->dev,
+ "Failed to allocate RX buffer\n");
+ ret = -ENOMEM;
+ goto abort1;
+ }
+
+ img = kzalloc(len, GFP_KERNEL);
+ if (!img) {
+ dev_err(codec->dev,
+ "Failed to allocate image buffer\n");
+ ret = -ENOMEM;
+ goto abort1;
+ }
+
+ byte_swap_64((u64 *)&rec->command, img, len);
+
+ xfer = kzalloc(sizeof(*xfer), GFP_KERNEL);
+ if (!xfer) {
+ dev_err(codec->dev, "Failed to allocate xfer\n");
+ ret = -ENOMEM;
+ goto abort1;
+ }
+
+ xfer->codec = codec;
+ list_add_tail(&xfer->list, &xfer_list);
+
+ spi_message_init(&xfer->m);
+ xfer->m.complete = wm0010_boot_xfer_complete;
+ xfer->m.context = xfer;
+ xfer->t.tx_buf = img;
+ xfer->t.rx_buf = out;
+ xfer->t.len = len;
+ xfer->t.bits_per_word = 8;
+
+ if (!wm0010->pll_running) {
+ xfer->t.speed_hz = wm0010->sysclk / 6;
+ } else {
+ xfer->t.speed_hz = wm0010->max_spi_freq;
+
+ if (wm0010->board_max_spi_speed &&
+ (wm0010->board_max_spi_speed < wm0010->max_spi_freq))
+ xfer->t.speed_hz = wm0010->board_max_spi_speed;
+ }
+
+ /* Store max usable spi frequency for later use */
+ wm0010->max_spi_freq = xfer->t.speed_hz;
+
+ spi_message_add_tail(&xfer->t, &xfer->m);
+
+ offset += ((rec->length) + 8);
+ rec = (void *)&rec->data[rec->length];
+
+ if (offset >= fw->size) {
+ dev_dbg(codec->dev, "All transfers scheduled\n");
+ xfer->done = &done;
+ }
+
+ ret = spi_async(spi, &xfer->m);
+ if (ret != 0) {
+ dev_err(codec->dev, "Write failed: %d\n", ret);
+ goto abort1;
+ }
+
+ if (wm0010->boot_failed) {
+ dev_dbg(codec->dev, "Boot fail!\n");
+ ret = -EINVAL;
+ goto abort1;
+ }
}
- /* Release reset */
- gpio_set_value_cansleep(wm0010->gpio_reset, !wm0010->gpio_reset_value);
- spin_lock_irqsave(&wm0010->irq_lock, flags);
- wm0010->state = WM0010_OUT_OF_RESET;
- spin_unlock_irqrestore(&wm0010->irq_lock, flags);
+ wait_for_completion(&done);
+
+ ret = 0;
+
+abort1:
+ while (!list_empty(&xfer_list)) {
+ xfer = list_first_entry(&xfer_list, struct wm0010_boot_xfer,
+ list);
+ kfree(xfer->t.rx_buf);
+ kfree(xfer->t.tx_buf);
+ list_del(&xfer->list);
+ kfree(xfer);
+ }
+
+abort:
+ release_firmware(fw);
+ return ret;
+}
+
+static int wm0010_stage2_load(struct snd_soc_codec *codec)
+{
+ struct spi_device *spi = to_spi_device(codec->dev);
+ struct wm0010_priv *wm0010 = snd_soc_codec_get_drvdata(codec);
+ const struct firmware *fw;
+ struct spi_message m;
+ struct spi_transfer t;
+ u32 *img;
+ u8 *out;
+ int i;
+ int ret = 0;
- /* First the bootloader */
ret = request_firmware(&fw, "wm0010_stage2.bin", codec->dev);
if (ret != 0) {
dev_err(codec->dev, "Failed to request stage2 loader: %d\n",
ret);
- goto abort;
+ return ret;
}
- if (!wait_for_completion_timeout(&wm0010->boot_completion,
- msecs_to_jiffies(10)))
- dev_err(codec->dev, "Failed to get interrupt from DSP\n");
-
- spin_lock_irqsave(&wm0010->irq_lock, flags);
- wm0010->state = WM0010_BOOTROM;
- spin_unlock_irqrestore(&wm0010->irq_lock, flags);
-
dev_dbg(codec->dev, "Downloading %zu byte stage 2 loader\n", fw->size);
/* Copy to local buffer first as vmalloc causes problems for dma */
img = kzalloc(fw->size, GFP_KERNEL);
if (!img) {
dev_err(codec->dev, "Failed to allocate image buffer\n");
- goto abort;
+ ret = -ENOMEM;
+ goto abort2;
}
out = kzalloc(fw->size, GFP_KERNEL);
if (!out) {
dev_err(codec->dev, "Failed to allocate output buffer\n");
- goto abort;
+ ret = -ENOMEM;
+ goto abort1;
}
memcpy(img, &fw->data[0], fw->size);
@@ -447,20 +559,97 @@ static int wm0010_boot(struct snd_soc_codec *codec)
/* Look for errors from the boot ROM */
for (i = 0; i < fw->size; i++) {
if (out[i] != 0x55) {
- ret = -EBUSY;
dev_err(codec->dev, "Boot ROM error: %x in %d\n",
out[i], i);
wm0010_mark_boot_failure(wm0010);
+ ret = -EBUSY;
goto abort;
}
}
-
- release_firmware(fw);
- kfree(img);
+abort:
kfree(out);
+abort1:
+ kfree(img);
+abort2:
+ release_firmware(fw);
+
+ return ret;
+}
+
+static int wm0010_boot(struct snd_soc_codec *codec)
+{
+ struct spi_device *spi = to_spi_device(codec->dev);
+ struct wm0010_priv *wm0010 = snd_soc_codec_get_drvdata(codec);
+ unsigned long flags;
+ int ret;
+ const struct firmware *fw;
+ struct spi_message m;
+ struct spi_transfer t;
+ struct dfw_pllrec pll_rec;
+ u32 *p, len;
+ u64 *img_swap;
+ u8 *out;
+ int i;
+
+ spin_lock_irqsave(&wm0010->irq_lock, flags);
+ if (wm0010->state != WM0010_POWER_OFF)
+ dev_warn(wm0010->dev, "DSP already powered up!\n");
+ spin_unlock_irqrestore(&wm0010->irq_lock, flags);
+
+ if (wm0010->sysclk > 26000000) {
+ dev_err(codec->dev, "Max DSP clock frequency is 26MHz\n");
+ ret = -ECANCELED;
+ goto err;
+ }
+
+ mutex_lock(&wm0010->lock);
+ wm0010->pll_running = false;
+
+ dev_dbg(codec->dev, "max_spi_freq: %d\n", wm0010->max_spi_freq);
+
+ ret = regulator_bulk_enable(ARRAY_SIZE(wm0010->core_supplies),
+ wm0010->core_supplies);
+ if (ret != 0) {
+ dev_err(&spi->dev, "Failed to enable core supplies: %d\n",
+ ret);
+ mutex_unlock(&wm0010->lock);
+ goto err;
+ }
+
+ ret = regulator_enable(wm0010->dbvdd);
+ if (ret != 0) {
+ dev_err(&spi->dev, "Failed to enable DBVDD: %d\n", ret);
+ goto err_core;
+ }
+
+ /* Release reset */
+ gpio_set_value_cansleep(wm0010->gpio_reset, !wm0010->gpio_reset_value);
+ spin_lock_irqsave(&wm0010->irq_lock, flags);
+ wm0010->state = WM0010_OUT_OF_RESET;
+ spin_unlock_irqrestore(&wm0010->irq_lock, flags);
+
+ /* First the bootloader */
+ ret = request_firmware(&fw, "wm0010_stage2.bin", codec->dev);
+ if (ret != 0) {
+ dev_err(codec->dev, "Failed to request stage2 loader: %d\n",
+ ret);
+ goto abort;
+ }
+
+ if (!wait_for_completion_timeout(&wm0010->boot_completion,
+ msecs_to_jiffies(20)))
+ dev_err(codec->dev, "Failed to get interrupt from DSP\n");
+
+ spin_lock_irqsave(&wm0010->irq_lock, flags);
+ wm0010->state = WM0010_BOOTROM;
+ spin_unlock_irqrestore(&wm0010->irq_lock, flags);
+
+ ret = wm0010_stage2_load(codec);
+ if (ret)
+ goto abort;
if (!wait_for_completion_timeout(&wm0010->boot_completion,
- msecs_to_jiffies(10)))
+ msecs_to_jiffies(20)))
dev_err(codec->dev, "Failed to get interrupt from DSP loader.\n");
spin_lock_irqsave(&wm0010->irq_lock, flags);
@@ -535,110 +724,10 @@ static int wm0010_boot(struct snd_soc_codec *codec)
} else
dev_dbg(codec->dev, "Not enabling DSP PLL.");
- ret = request_firmware(&fw, "wm0010.dfw", codec->dev);
- if (ret != 0) {
- dev_err(codec->dev, "Failed to request application: %d\n",
- ret);
- goto abort;
- }
-
- rec = (const struct dfw_binrec *)fw->data;
- offset = 0;
- wm0010->boot_done = 0;
- wm0010->boot_failed = false;
- BUG_ON(!list_empty(&xfer_list));
- init_completion(&done);
+ ret = wm0010_firmware_load("wm0010.dfw", codec);
- /* First record should be INFO */
- if (rec->command != DFW_CMD_INFO) {
- dev_err(codec->dev, "First record not INFO\r\n");
- goto abort;
- }
-
- /* Check it's a 0010 file */
- if (rec->data[0] != DEVICE_ID_WM0010) {
- dev_err(codec->dev, "Not a WM0010 firmware file.\r\n");
+ if (ret != 0)
goto abort;
- }
-
- /* Skip the info record as we don't need to send it */
- offset += ((rec->length) + 8);
- rec = (void *)&rec->data[rec->length];
-
- while (offset < fw->size) {
- dev_dbg(codec->dev,
- "Packet: command %d, data length = 0x%x\r\n",
- rec->command, rec->length);
- len = rec->length + 8;
-
- out = kzalloc(len, GFP_KERNEL);
- if (!out) {
- dev_err(codec->dev,
- "Failed to allocate RX buffer\n");
- goto abort;
- }
-
- img_swap = kzalloc(len, GFP_KERNEL);
- if (!img_swap) {
- dev_err(codec->dev,
- "Failed to allocate image buffer\n");
- goto abort;
- }
-
- /* We need to re-order for 0010 */
- byte_swap_64((u64 *)&rec->command, img_swap, len);
-
- xfer = kzalloc(sizeof(*xfer), GFP_KERNEL);
- if (!xfer) {
- dev_err(codec->dev, "Failed to allocate xfer\n");
- goto abort;
- }
-
- xfer->codec = codec;
- list_add_tail(&xfer->list, &xfer_list);
-
- spi_message_init(&xfer->m);
- xfer->m.complete = wm0010_boot_xfer_complete;
- xfer->m.context = xfer;
- xfer->t.tx_buf = img_swap;
- xfer->t.rx_buf = out;
- xfer->t.len = len;
- xfer->t.bits_per_word = 8;
-
- if (!wm0010->pll_running) {
- xfer->t.speed_hz = wm0010->sysclk / 6;
- } else {
- xfer->t.speed_hz = wm0010->max_spi_freq;
-
- if (wm0010->board_max_spi_speed &&
- (wm0010->board_max_spi_speed < wm0010->max_spi_freq))
- xfer->t.speed_hz = wm0010->board_max_spi_speed;
- }
-
- /* Store max usable spi frequency for later use */
- wm0010->max_spi_freq = xfer->t.speed_hz;
-
- spi_message_add_tail(&xfer->t, &xfer->m);
-
- offset += ((rec->length) + 8);
- rec = (void *)&rec->data[rec->length];
-
- if (offset >= fw->size) {
- dev_dbg(codec->dev, "All transfers scheduled\n");
- xfer->done = &done;
- }
-
- ret = spi_async(spi, &xfer->m);
- if (ret != 0) {
- dev_err(codec->dev, "Write failed: %d\n", ret);
- goto abort;
- }
-
- if (wm0010->boot_failed)
- goto abort;
- }
-
- wait_for_completion(&done);
spin_lock_irqsave(&wm0010->irq_lock, flags);
wm0010->state = WM0010_FIRMWARE;
@@ -646,17 +735,6 @@ static int wm0010_boot(struct snd_soc_codec *codec)
mutex_unlock(&wm0010->lock);
- release_firmware(fw);
-
- while (!list_empty(&xfer_list)) {
- xfer = list_first_entry(&xfer_list, struct wm0010_boot_xfer,
- list);
- kfree(xfer->t.rx_buf);
- kfree(xfer->t.tx_buf);
- list_del(&xfer->list);
- kfree(xfer);
- }
-
return 0;
abort:
@@ -784,7 +862,6 @@ static irqreturn_t wm0010_irq(int irq, void *data)
struct wm0010_priv *wm0010 = data;
switch (wm0010->state) {
- case WM0010_POWER_OFF:
case WM0010_OUT_OF_RESET:
case WM0010_BOOTROM:
case WM0010_STAGE2:
@@ -808,7 +885,7 @@ static int wm0010_probe(struct snd_soc_codec *codec)
return 0;
}
-static int __devinit wm0010_spi_probe(struct spi_device *spi)
+static int wm0010_spi_probe(struct spi_device *spi)
{
unsigned long gpio_flags;
int ret;
@@ -908,7 +985,7 @@ static int __devinit wm0010_spi_probe(struct spi_device *spi)
return 0;
}
-static int __devexit wm0010_spi_remove(struct spi_device *spi)
+static int wm0010_spi_remove(struct spi_device *spi)
{
struct wm0010_priv *wm0010 = spi_get_drvdata(spi);
@@ -930,7 +1007,7 @@ static struct spi_driver wm0010_spi_driver = {
.owner = THIS_MODULE,
},
.probe = wm0010_spi_probe,
- .remove = __devexit_p(wm0010_spi_remove),
+ .remove = wm0010_spi_remove,
};
module_spi_driver(wm0010_spi_driver);
diff --git a/sound/soc/codecs/wm1250-ev1.c b/sound/soc/codecs/wm1250-ev1.c
index 951d7b49476a..6e6b93d4696e 100644
--- a/sound/soc/codecs/wm1250-ev1.c
+++ b/sound/soc/codecs/wm1250-ev1.c
@@ -153,7 +153,7 @@ static struct snd_soc_codec_driver soc_codec_dev_wm1250_ev1 = {
.idle_bias_off = true,
};
-static int __devinit wm1250_ev1_pdata(struct i2c_client *i2c)
+static int wm1250_ev1_pdata(struct i2c_client *i2c)
{
struct wm1250_ev1_pdata *pdata = dev_get_platdata(&i2c->dev);
struct wm1250_priv *wm1250;
@@ -199,8 +199,8 @@ static void wm1250_ev1_free(struct i2c_client *i2c)
gpio_free_array(wm1250->gpios, ARRAY_SIZE(wm1250->gpios));
}
-static int __devinit wm1250_ev1_probe(struct i2c_client *i2c,
- const struct i2c_device_id *i2c_id)
+static int wm1250_ev1_probe(struct i2c_client *i2c,
+ const struct i2c_device_id *i2c_id)
{
int id, board, rev, ret;
@@ -237,7 +237,7 @@ static int __devinit wm1250_ev1_probe(struct i2c_client *i2c,
return 0;
}
-static int __devexit wm1250_ev1_remove(struct i2c_client *i2c)
+static int wm1250_ev1_remove(struct i2c_client *i2c)
{
snd_soc_unregister_codec(&i2c->dev);
wm1250_ev1_free(i2c);
@@ -257,7 +257,7 @@ static struct i2c_driver wm1250_ev1_i2c_driver = {
.owner = THIS_MODULE,
},
.probe = wm1250_ev1_probe,
- .remove = __devexit_p(wm1250_ev1_remove),
+ .remove = wm1250_ev1_remove,
.id_table = wm1250_ev1_i2c_id,
};
diff --git a/sound/soc/codecs/wm2000.c b/sound/soc/codecs/wm2000.c
index 683dc43b1d87..1cbe88f01d63 100644
--- a/sound/soc/codecs/wm2000.c
+++ b/sound/soc/codecs/wm2000.c
@@ -646,7 +646,7 @@ static const struct snd_kcontrol_new wm2000_controls[] = {
static int wm2000_anc_power_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_codec *codec = w->codec;
struct wm2000_priv *wm2000 = dev_get_drvdata(codec->dev);
if (SND_SOC_DAPM_EVENT_ON(event))
@@ -764,8 +764,8 @@ static struct snd_soc_codec_driver soc_codec_dev_wm2000 = {
.num_controls = ARRAY_SIZE(wm2000_controls),
};
-static int __devinit wm2000_i2c_probe(struct i2c_client *i2c,
- const struct i2c_device_id *i2c_id)
+static int wm2000_i2c_probe(struct i2c_client *i2c,
+ const struct i2c_device_id *i2c_id)
{
struct wm2000_priv *wm2000;
struct wm2000_platform_data *pdata;
@@ -871,7 +871,7 @@ out:
return ret;
}
-static __devexit int wm2000_i2c_remove(struct i2c_client *i2c)
+static int wm2000_i2c_remove(struct i2c_client *i2c)
{
snd_soc_unregister_codec(&i2c->dev);
@@ -890,7 +890,7 @@ static struct i2c_driver wm2000_i2c_driver = {
.owner = THIS_MODULE,
},
.probe = wm2000_i2c_probe,
- .remove = __devexit_p(wm2000_i2c_remove),
+ .remove = wm2000_i2c_remove,
.id_table = wm2000_i2c_id,
};
diff --git a/sound/soc/codecs/wm2200.c b/sound/soc/codecs/wm2200.c
index eab64a193989..afcf31df77e0 100644
--- a/sound/soc/codecs/wm2200.c
+++ b/sound/soc/codecs/wm2200.c
@@ -15,6 +15,7 @@
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/pm.h>
+#include <linux/firmware.h>
#include <linux/gcd.h>
#include <linux/gpio.h>
#include <linux/i2c.h>
@@ -32,6 +33,40 @@
#include <sound/wm2200.h>
#include "wm2200.h"
+#include "wmfw.h"
+#include "wm_adsp.h"
+
+#define WM2200_DSP_CONTROL_1 0x00
+#define WM2200_DSP_CONTROL_2 0x02
+#define WM2200_DSP_CONTROL_3 0x03
+#define WM2200_DSP_CONTROL_4 0x04
+#define WM2200_DSP_CONTROL_5 0x06
+#define WM2200_DSP_CONTROL_6 0x07
+#define WM2200_DSP_CONTROL_7 0x08
+#define WM2200_DSP_CONTROL_8 0x09
+#define WM2200_DSP_CONTROL_9 0x0A
+#define WM2200_DSP_CONTROL_10 0x0B
+#define WM2200_DSP_CONTROL_11 0x0C
+#define WM2200_DSP_CONTROL_12 0x0D
+#define WM2200_DSP_CONTROL_13 0x0F
+#define WM2200_DSP_CONTROL_14 0x10
+#define WM2200_DSP_CONTROL_15 0x11
+#define WM2200_DSP_CONTROL_16 0x12
+#define WM2200_DSP_CONTROL_17 0x13
+#define WM2200_DSP_CONTROL_18 0x14
+#define WM2200_DSP_CONTROL_19 0x16
+#define WM2200_DSP_CONTROL_20 0x17
+#define WM2200_DSP_CONTROL_21 0x18
+#define WM2200_DSP_CONTROL_22 0x1A
+#define WM2200_DSP_CONTROL_23 0x1B
+#define WM2200_DSP_CONTROL_24 0x1C
+#define WM2200_DSP_CONTROL_25 0x1E
+#define WM2200_DSP_CONTROL_26 0x20
+#define WM2200_DSP_CONTROL_27 0x21
+#define WM2200_DSP_CONTROL_28 0x22
+#define WM2200_DSP_CONTROL_29 0x23
+#define WM2200_DSP_CONTROL_30 0x24
+#define WM2200_DSP_CONTROL_31 0x26
/* The code assumes DCVDD is generated internally */
#define WM2200_NUM_CORE_SUPPLIES 2
@@ -49,6 +84,7 @@ struct wm2200_fll {
/* codec private data */
struct wm2200_priv {
+ struct wm_adsp dsp[2];
struct regmap *regmap;
struct device *dev;
struct snd_soc_codec *codec;
@@ -64,6 +100,72 @@ struct wm2200_priv {
int sysclk;
};
+#define WM2200_DSP_RANGE_BASE (WM2200_MAX_REGISTER + 1)
+#define WM2200_DSP_SPACING 12288
+
+#define WM2200_DSP1_DM_BASE (WM2200_DSP_RANGE_BASE + (0 * WM2200_DSP_SPACING))
+#define WM2200_DSP1_PM_BASE (WM2200_DSP_RANGE_BASE + (1 * WM2200_DSP_SPACING))
+#define WM2200_DSP1_ZM_BASE (WM2200_DSP_RANGE_BASE + (2 * WM2200_DSP_SPACING))
+#define WM2200_DSP2_DM_BASE (WM2200_DSP_RANGE_BASE + (3 * WM2200_DSP_SPACING))
+#define WM2200_DSP2_PM_BASE (WM2200_DSP_RANGE_BASE + (4 * WM2200_DSP_SPACING))
+#define WM2200_DSP2_ZM_BASE (WM2200_DSP_RANGE_BASE + (5 * WM2200_DSP_SPACING))
+
+static const struct regmap_range_cfg wm2200_ranges[] = {
+ { .name = "DSP1DM", .range_min = WM2200_DSP1_DM_BASE,
+ .range_max = WM2200_DSP1_DM_BASE + 12287,
+ .selector_reg = WM2200_DSP1_CONTROL_3,
+ .selector_mask = WM2200_DSP1_PAGE_BASE_DM_0_MASK,
+ .selector_shift = WM2200_DSP1_PAGE_BASE_DM_0_SHIFT,
+ .window_start = WM2200_DSP1_DM_0, .window_len = 2048, },
+
+ { .name = "DSP1PM", .range_min = WM2200_DSP1_PM_BASE,
+ .range_max = WM2200_DSP1_PM_BASE + 12287,
+ .selector_reg = WM2200_DSP1_CONTROL_2,
+ .selector_mask = WM2200_DSP1_PAGE_BASE_PM_0_MASK,
+ .selector_shift = WM2200_DSP1_PAGE_BASE_PM_0_SHIFT,
+ .window_start = WM2200_DSP1_PM_0, .window_len = 768, },
+
+ { .name = "DSP1ZM", .range_min = WM2200_DSP1_ZM_BASE,
+ .range_max = WM2200_DSP1_ZM_BASE + 2047,
+ .selector_reg = WM2200_DSP1_CONTROL_4,
+ .selector_mask = WM2200_DSP1_PAGE_BASE_ZM_0_MASK,
+ .selector_shift = WM2200_DSP1_PAGE_BASE_ZM_0_SHIFT,
+ .window_start = WM2200_DSP1_ZM_0, .window_len = 1024, },
+
+ { .name = "DSP2DM", .range_min = WM2200_DSP2_DM_BASE,
+ .range_max = WM2200_DSP2_DM_BASE + 4095,
+ .selector_reg = WM2200_DSP2_CONTROL_3,
+ .selector_mask = WM2200_DSP2_PAGE_BASE_DM_0_MASK,
+ .selector_shift = WM2200_DSP2_PAGE_BASE_DM_0_SHIFT,
+ .window_start = WM2200_DSP2_DM_0, .window_len = 2048, },
+
+ { .name = "DSP2PM", .range_min = WM2200_DSP2_PM_BASE,
+ .range_max = WM2200_DSP2_PM_BASE + 11287,
+ .selector_reg = WM2200_DSP2_CONTROL_2,
+ .selector_mask = WM2200_DSP2_PAGE_BASE_PM_0_MASK,
+ .selector_shift = WM2200_DSP2_PAGE_BASE_PM_0_SHIFT,
+ .window_start = WM2200_DSP2_PM_0, .window_len = 768, },
+
+ { .name = "DSP2ZM", .range_min = WM2200_DSP2_ZM_BASE,
+ .range_max = WM2200_DSP2_ZM_BASE + 2047,
+ .selector_reg = WM2200_DSP2_CONTROL_4,
+ .selector_mask = WM2200_DSP2_PAGE_BASE_ZM_0_MASK,
+ .selector_shift = WM2200_DSP2_PAGE_BASE_ZM_0_SHIFT,
+ .window_start = WM2200_DSP2_ZM_0, .window_len = 1024, },
+};
+
+static const struct wm_adsp_region wm2200_dsp1_regions[] = {
+ { .type = WMFW_ADSP1_PM, .base = WM2200_DSP1_PM_BASE },
+ { .type = WMFW_ADSP1_DM, .base = WM2200_DSP1_DM_BASE },
+ { .type = WMFW_ADSP1_ZM, .base = WM2200_DSP1_ZM_BASE },
+};
+
+static const struct wm_adsp_region wm2200_dsp2_regions[] = {
+ { .type = WMFW_ADSP1_PM, .base = WM2200_DSP2_PM_BASE },
+ { .type = WMFW_ADSP1_DM, .base = WM2200_DSP2_DM_BASE },
+ { .type = WMFW_ADSP1_ZM, .base = WM2200_DSP2_ZM_BASE },
+};
+
static struct reg_default wm2200_reg_defaults[] = {
{ 0x000B, 0x0000 }, /* R11 - Tone Generator 1 */
{ 0x0102, 0x0000 }, /* R258 - Clocking 3 */
@@ -407,6 +509,16 @@ static struct reg_default wm2200_reg_defaults[] = {
static bool wm2200_volatile_register(struct device *dev, unsigned int reg)
{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(wm2200_ranges); i++)
+ if ((reg >= wm2200_ranges[i].window_start &&
+ reg <= wm2200_ranges[i].window_start +
+ wm2200_ranges[i].window_len) ||
+ (reg >= wm2200_ranges[i].range_min &&
+ reg <= wm2200_ranges[i].range_max))
+ return true;
+
switch (reg) {
case WM2200_SOFTWARE_RESET:
case WM2200_DEVICE_REVISION:
@@ -423,6 +535,16 @@ static bool wm2200_volatile_register(struct device *dev, unsigned int reg)
static bool wm2200_readable_register(struct device *dev, unsigned int reg)
{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(wm2200_ranges); i++)
+ if ((reg >= wm2200_ranges[i].window_start &&
+ reg <= wm2200_ranges[i].window_start +
+ wm2200_ranges[i].window_len) ||
+ (reg >= wm2200_ranges[i].range_min &&
+ reg <= wm2200_ranges[i].range_max))
+ return true;
+
switch (reg) {
case WM2200_SOFTWARE_RESET:
case WM2200_DEVICE_REVISION:
@@ -880,7 +1002,7 @@ static DECLARE_TLV_DB_SCALE(out_tlv, -6400, 100, 0);
static const char *wm2200_mixer_texts[] = {
"None",
"Tone Generator",
- "AEC loopback",
+ "AEC Loopback",
"IN1L",
"IN1R",
"IN2L",
@@ -976,6 +1098,20 @@ static int wm2200_mixer_values[] = {
static WM2200_MUX_CTL_DECL(name##_in3); \
static WM2200_MUX_CTL_DECL(name##_in4)
+#define WM2200_DSP_ENUMS(name, base_reg) \
+ static WM2200_MUX_ENUM_DECL(name##_aux1_enum, base_reg); \
+ static WM2200_MUX_ENUM_DECL(name##_aux2_enum, base_reg + 1); \
+ static WM2200_MUX_ENUM_DECL(name##_aux3_enum, base_reg + 2); \
+ static WM2200_MUX_ENUM_DECL(name##_aux4_enum, base_reg + 3); \
+ static WM2200_MUX_ENUM_DECL(name##_aux5_enum, base_reg + 4); \
+ static WM2200_MUX_ENUM_DECL(name##_aux6_enum, base_reg + 5); \
+ static WM2200_MUX_CTL_DECL(name##_aux1); \
+ static WM2200_MUX_CTL_DECL(name##_aux2); \
+ static WM2200_MUX_CTL_DECL(name##_aux3); \
+ static WM2200_MUX_CTL_DECL(name##_aux4); \
+ static WM2200_MUX_CTL_DECL(name##_aux5); \
+ static WM2200_MUX_CTL_DECL(name##_aux6);
+
static const struct snd_kcontrol_new wm2200_snd_controls[] = {
SOC_SINGLE("IN1 High Performance Switch", WM2200_IN1L_CONTROL,
WM2200_IN1_OSR_SHIFT, 1, 0),
@@ -1051,6 +1187,9 @@ WM2200_MIXER_ENUMS(DSP1R, WM2200_DSP1RMIX_INPUT_1_SOURCE);
WM2200_MIXER_ENUMS(DSP2L, WM2200_DSP2LMIX_INPUT_1_SOURCE);
WM2200_MIXER_ENUMS(DSP2R, WM2200_DSP2RMIX_INPUT_1_SOURCE);
+WM2200_DSP_ENUMS(DSP1, WM2200_DSP1AUX1MIX_INPUT_1_SOURCE);
+WM2200_DSP_ENUMS(DSP2, WM2200_DSP2AUX1MIX_INPUT_1_SOURCE);
+
WM2200_MIXER_ENUMS(LHPF1, WM2200_LHPF1MIX_INPUT_1_SOURCE);
WM2200_MIXER_ENUMS(LHPF2, WM2200_LHPF2MIX_INPUT_1_SOURCE);
@@ -1064,8 +1203,19 @@ WM2200_MIXER_ENUMS(LHPF2, WM2200_LHPF2MIX_INPUT_1_SOURCE);
WM2200_MUX(name_str " Input 4", &name##_in4_mux), \
SND_SOC_DAPM_MIXER(name_str " Mixer", SND_SOC_NOPM, 0, 0, NULL, 0)
+#define WM2200_DSP_WIDGETS(name, name_str) \
+ WM2200_MIXER_WIDGETS(name##L, name_str "L"), \
+ WM2200_MIXER_WIDGETS(name##R, name_str "R"), \
+ WM2200_MUX(name_str " Aux 1", &name##_aux1_mux), \
+ WM2200_MUX(name_str " Aux 2", &name##_aux2_mux), \
+ WM2200_MUX(name_str " Aux 3", &name##_aux3_mux), \
+ WM2200_MUX(name_str " Aux 4", &name##_aux4_mux), \
+ WM2200_MUX(name_str " Aux 5", &name##_aux5_mux), \
+ WM2200_MUX(name_str " Aux 6", &name##_aux6_mux)
+
#define WM2200_MIXER_INPUT_ROUTES(name) \
{ name, "Tone Generator", "Tone Generator" }, \
+ { name, "AEC Loopback", "AEC Loopback" }, \
{ name, "IN1L", "IN1L PGA" }, \
{ name, "IN1R", "IN1R PGA" }, \
{ name, "IN2L", "IN2L PGA" }, \
@@ -1106,6 +1256,33 @@ WM2200_MIXER_ENUMS(LHPF2, WM2200_LHPF2MIX_INPUT_1_SOURCE);
WM2200_MIXER_INPUT_ROUTES(name " Input 3"), \
WM2200_MIXER_INPUT_ROUTES(name " Input 4")
+#define WM2200_DSP_AUX_ROUTES(name) \
+ { name, NULL, name " Aux 1" }, \
+ { name, NULL, name " Aux 2" }, \
+ { name, NULL, name " Aux 3" }, \
+ { name, NULL, name " Aux 4" }, \
+ { name, NULL, name " Aux 5" }, \
+ { name, NULL, name " Aux 6" }, \
+ WM2200_MIXER_INPUT_ROUTES(name " Aux 1"), \
+ WM2200_MIXER_INPUT_ROUTES(name " Aux 2"), \
+ WM2200_MIXER_INPUT_ROUTES(name " Aux 3"), \
+ WM2200_MIXER_INPUT_ROUTES(name " Aux 4"), \
+ WM2200_MIXER_INPUT_ROUTES(name " Aux 5"), \
+ WM2200_MIXER_INPUT_ROUTES(name " Aux 6")
+
+static const char *wm2200_aec_loopback_texts[] = {
+ "OUT1L", "OUT1R", "OUT2L", "OUT2R",
+};
+
+static const struct soc_enum wm2200_aec_loopback =
+ SOC_ENUM_SINGLE(WM2200_DAC_AEC_CONTROL_1,
+ WM2200_AEC_LOOPBACK_SRC_SHIFT,
+ ARRAY_SIZE(wm2200_aec_loopback_texts),
+ wm2200_aec_loopback_texts);
+
+static const struct snd_kcontrol_new wm2200_aec_loopback_mux =
+ SOC_DAPM_ENUM("AEC Loopback", wm2200_aec_loopback);
+
static const struct snd_soc_dapm_widget wm2200_dapm_widgets[] = {
SND_SOC_DAPM_SUPPLY("SYSCLK", WM2200_CLOCKING_3, WM2200_SYSCLK_ENA_SHIFT, 0,
NULL, 0),
@@ -1165,8 +1342,8 @@ SND_SOC_DAPM_PGA("LHPF1", WM2200_HPLPF1_1, WM2200_LHPF1_ENA_SHIFT, 0,
SND_SOC_DAPM_PGA("LHPF2", WM2200_HPLPF2_1, WM2200_LHPF2_ENA_SHIFT, 0,
NULL, 0),
-SND_SOC_DAPM_PGA_E("DSP1", SND_SOC_NOPM, 0, 0, NULL, 0, NULL, 0),
-SND_SOC_DAPM_PGA_E("DSP2", SND_SOC_NOPM, 1, 0, NULL, 0, NULL, 0),
+WM_ADSP1("DSP1", 0),
+WM_ADSP1("DSP2", 1),
SND_SOC_DAPM_AIF_OUT("AIF1TX1", "Capture", 0,
WM2200_AUDIO_IF_1_22, WM2200_AIF1TX1_ENA_SHIFT, 0),
@@ -1181,6 +1358,9 @@ SND_SOC_DAPM_AIF_OUT("AIF1TX5", "Capture", 4,
SND_SOC_DAPM_AIF_OUT("AIF1TX6", "Capture", 5,
WM2200_AUDIO_IF_1_22, WM2200_AIF1TX6_ENA_SHIFT, 0),
+SND_SOC_DAPM_MUX("AEC Loopback", WM2200_DAC_AEC_CONTROL_1,
+ WM2200_AEC_LOOPBACK_ENA_SHIFT, 0, &wm2200_aec_loopback_mux),
+
SND_SOC_DAPM_PGA_S("OUT1L", 0, WM2200_OUTPUT_ENABLES,
WM2200_OUT1L_ENA_SHIFT, 0, NULL, 0),
SND_SOC_DAPM_PGA_S("OUT1R", 0, WM2200_OUTPUT_ENABLES,
@@ -1231,10 +1411,8 @@ WM2200_MIXER_WIDGETS(EQR, "EQR"),
WM2200_MIXER_WIDGETS(LHPF1, "LHPF1"),
WM2200_MIXER_WIDGETS(LHPF2, "LHPF2"),
-WM2200_MIXER_WIDGETS(DSP1L, "DSP1L"),
-WM2200_MIXER_WIDGETS(DSP1R, "DSP1R"),
-WM2200_MIXER_WIDGETS(DSP2L, "DSP2L"),
-WM2200_MIXER_WIDGETS(DSP2R, "DSP2R"),
+WM2200_DSP_WIDGETS(DSP1, "DSP1"),
+WM2200_DSP_WIDGETS(DSP2, "DSP2"),
WM2200_MIXER_WIDGETS(AIF1TX1, "AIF1TX1"),
WM2200_MIXER_WIDGETS(AIF1TX2, "AIF1TX2"),
@@ -1326,11 +1504,19 @@ static const struct snd_soc_dapm_route wm2200_dapm_routes[] = {
{ "SPK", NULL, "OUT2L" },
{ "SPK", NULL, "OUT2R" },
+ { "AEC Loopback", "OUT1L", "OUT1L" },
+ { "AEC Loopback", "OUT1R", "OUT1R" },
+ { "AEC Loopback", "OUT2L", "OUT2L" },
+ { "AEC Loopback", "OUT2R", "OUT2R" },
+
WM2200_MIXER_ROUTES("DSP1", "DSP1L"),
WM2200_MIXER_ROUTES("DSP1", "DSP1R"),
WM2200_MIXER_ROUTES("DSP2", "DSP2L"),
WM2200_MIXER_ROUTES("DSP2", "DSP2R"),
+ WM2200_DSP_AUX_ROUTES("DSP1"),
+ WM2200_DSP_AUX_ROUTES("DSP2"),
+
WM2200_MIXER_ROUTES("OUT1L", "OUT1L"),
WM2200_MIXER_ROUTES("OUT1R", "OUT1R"),
WM2200_MIXER_ROUTES("OUT2L", "OUT2L"),
@@ -1968,12 +2154,15 @@ static const struct regmap_config wm2200_regmap = {
.reg_bits = 16,
.val_bits = 16,
- .max_register = WM2200_MAX_REGISTER,
+ .max_register = WM2200_MAX_REGISTER + (ARRAY_SIZE(wm2200_ranges) *
+ WM2200_DSP_SPACING),
.reg_defaults = wm2200_reg_defaults,
.num_reg_defaults = ARRAY_SIZE(wm2200_reg_defaults),
.volatile_reg = wm2200_volatile_register,
.readable_reg = wm2200_readable_register,
.cache_type = REGCACHE_RBTREE,
+ .ranges = wm2200_ranges,
+ .num_ranges = ARRAY_SIZE(wm2200_ranges),
};
static const unsigned int wm2200_dig_vu[] = {
@@ -1995,8 +2184,8 @@ static const unsigned int wm2200_mic_ctrl_reg[] = {
WM2200_IN3L_CONTROL,
};
-static __devinit int wm2200_i2c_probe(struct i2c_client *i2c,
- const struct i2c_device_id *id)
+static int wm2200_i2c_probe(struct i2c_client *i2c,
+ const struct i2c_device_id *id)
{
struct wm2200_pdata *pdata = dev_get_platdata(&i2c->dev);
struct wm2200_priv *wm2200;
@@ -2011,14 +2200,30 @@ static __devinit int wm2200_i2c_probe(struct i2c_client *i2c,
wm2200->dev = &i2c->dev;
init_completion(&wm2200->fll_lock);
- wm2200->regmap = regmap_init_i2c(i2c, &wm2200_regmap);
+ wm2200->regmap = devm_regmap_init_i2c(i2c, &wm2200_regmap);
if (IS_ERR(wm2200->regmap)) {
ret = PTR_ERR(wm2200->regmap);
dev_err(&i2c->dev, "Failed to allocate register map: %d\n",
ret);
- goto err;
+ return ret;
+ }
+
+ for (i = 0; i < 2; i++) {
+ wm2200->dsp[i].type = WMFW_ADSP1;
+ wm2200->dsp[i].part = "wm2200";
+ wm2200->dsp[i].num = i + 1;
+ wm2200->dsp[i].dev = &i2c->dev;
+ wm2200->dsp[i].regmap = wm2200->regmap;
}
+ wm2200->dsp[0].base = WM2200_DSP1_CONTROL_1;
+ wm2200->dsp[0].mem = wm2200_dsp1_regions;
+ wm2200->dsp[0].num_mems = ARRAY_SIZE(wm2200_dsp1_regions);
+
+ wm2200->dsp[1].base = WM2200_DSP2_CONTROL_1;
+ wm2200->dsp[1].mem = wm2200_dsp2_regions;
+ wm2200->dsp[1].num_mems = ARRAY_SIZE(wm2200_dsp2_regions);
+
if (pdata)
wm2200->pdata = *pdata;
@@ -2027,12 +2232,13 @@ static __devinit int wm2200_i2c_probe(struct i2c_client *i2c,
for (i = 0; i < ARRAY_SIZE(wm2200->core_supplies); i++)
wm2200->core_supplies[i].supply = wm2200_core_supply_names[i];
- ret = regulator_bulk_get(&i2c->dev, ARRAY_SIZE(wm2200->core_supplies),
- wm2200->core_supplies);
+ ret = devm_regulator_bulk_get(&i2c->dev,
+ ARRAY_SIZE(wm2200->core_supplies),
+ wm2200->core_supplies);
if (ret != 0) {
dev_err(&i2c->dev, "Failed to request core supplies: %d\n",
ret);
- goto err_regmap;
+ return ret;
}
ret = regulator_bulk_enable(ARRAY_SIZE(wm2200->core_supplies),
@@ -2040,12 +2246,13 @@ static __devinit int wm2200_i2c_probe(struct i2c_client *i2c,
if (ret != 0) {
dev_err(&i2c->dev, "Failed to enable core supplies: %d\n",
ret);
- goto err_core;
+ return ret;
}
if (wm2200->pdata.ldo_ena) {
- ret = gpio_request_one(wm2200->pdata.ldo_ena,
- GPIOF_OUT_INIT_HIGH, "WM2200 LDOENA");
+ ret = devm_gpio_request_one(&i2c->dev, wm2200->pdata.ldo_ena,
+ GPIOF_OUT_INIT_HIGH,
+ "WM2200 LDOENA");
if (ret < 0) {
dev_err(&i2c->dev, "Failed to request LDOENA %d: %d\n",
wm2200->pdata.ldo_ena, ret);
@@ -2055,8 +2262,9 @@ static __devinit int wm2200_i2c_probe(struct i2c_client *i2c,
}
if (wm2200->pdata.reset) {
- ret = gpio_request_one(wm2200->pdata.reset,
- GPIOF_OUT_INIT_HIGH, "WM2200 /RESET");
+ ret = devm_gpio_request_one(&i2c->dev, wm2200->pdata.reset,
+ GPIOF_OUT_INIT_HIGH,
+ "WM2200 /RESET");
if (ret < 0) {
dev_err(&i2c->dev, "Failed to request /RESET %d: %d\n",
wm2200->pdata.reset, ret);
@@ -2166,45 +2374,28 @@ static __devinit int wm2200_i2c_probe(struct i2c_client *i2c,
err_pm_runtime:
pm_runtime_disable(&i2c->dev);
err_reset:
- if (wm2200->pdata.reset) {
+ if (wm2200->pdata.reset)
gpio_set_value_cansleep(wm2200->pdata.reset, 0);
- gpio_free(wm2200->pdata.reset);
- }
err_ldo:
- if (wm2200->pdata.ldo_ena) {
+ if (wm2200->pdata.ldo_ena)
gpio_set_value_cansleep(wm2200->pdata.ldo_ena, 0);
- gpio_free(wm2200->pdata.ldo_ena);
- }
err_enable:
regulator_bulk_disable(ARRAY_SIZE(wm2200->core_supplies),
wm2200->core_supplies);
-err_core:
- regulator_bulk_free(ARRAY_SIZE(wm2200->core_supplies),
- wm2200->core_supplies);
-err_regmap:
- regmap_exit(wm2200->regmap);
-err:
return ret;
}
-static __devexit int wm2200_i2c_remove(struct i2c_client *i2c)
+static int wm2200_i2c_remove(struct i2c_client *i2c)
{
struct wm2200_priv *wm2200 = i2c_get_clientdata(i2c);
snd_soc_unregister_codec(&i2c->dev);
if (i2c->irq)
free_irq(i2c->irq, wm2200);
- if (wm2200->pdata.reset) {
+ if (wm2200->pdata.reset)
gpio_set_value_cansleep(wm2200->pdata.reset, 0);
- gpio_free(wm2200->pdata.reset);
- }
- if (wm2200->pdata.ldo_ena) {
+ if (wm2200->pdata.ldo_ena)
gpio_set_value_cansleep(wm2200->pdata.ldo_ena, 0);
- gpio_free(wm2200->pdata.ldo_ena);
- }
- regulator_bulk_free(ARRAY_SIZE(wm2200->core_supplies),
- wm2200->core_supplies);
- regmap_exit(wm2200->regmap);
return 0;
}
@@ -2267,7 +2458,7 @@ static struct i2c_driver wm2200_i2c_driver = {
.pm = &wm2200_pm,
},
.probe = wm2200_i2c_probe,
- .remove = __devexit_p(wm2200_i2c_remove),
+ .remove = wm2200_i2c_remove,
.id_table = wm2200_i2c_id,
};
diff --git a/sound/soc/codecs/wm5100.c b/sound/soc/codecs/wm5100.c
index 7f567585832e..5a5f36936235 100644
--- a/sound/soc/codecs/wm5100.c
+++ b/sound/soc/codecs/wm5100.c
@@ -1233,7 +1233,7 @@ static const struct snd_soc_dapm_route wm5100_dapm_routes[] = {
{ "PWM2", NULL, "PWM2 Driver" },
};
-static const __devinitconst struct reg_default wm5100_reva_patches[] = {
+static const struct reg_default wm5100_reva_patches[] = {
{ WM5100_AUDIO_IF_1_10, 0 },
{ WM5100_AUDIO_IF_1_11, 1 },
{ WM5100_AUDIO_IF_1_12, 2 },
@@ -2414,8 +2414,8 @@ static const unsigned int wm5100_mic_ctrl_reg[] = {
WM5100_IN4L_CONTROL,
};
-static __devinit int wm5100_i2c_probe(struct i2c_client *i2c,
- const struct i2c_device_id *id)
+static int wm5100_i2c_probe(struct i2c_client *i2c,
+ const struct i2c_device_id *id)
{
struct wm5100_pdata *pdata = dev_get_platdata(&i2c->dev);
struct wm5100_priv *wm5100;
@@ -2639,7 +2639,7 @@ err:
return ret;
}
-static __devexit int wm5100_i2c_remove(struct i2c_client *i2c)
+static int wm5100_i2c_remove(struct i2c_client *i2c)
{
struct wm5100_priv *wm5100 = i2c_get_clientdata(i2c);
@@ -2717,7 +2717,7 @@ static struct i2c_driver wm5100_i2c_driver = {
.pm = &wm5100_pm,
},
.probe = wm5100_i2c_probe,
- .remove = __devexit_p(wm5100_i2c_remove),
+ .remove = wm5100_i2c_remove,
.id_table = wm5100_i2c_id,
};
diff --git a/sound/soc/codecs/wm5102.c b/sound/soc/codecs/wm5102.c
index 7394e73fa43c..688ade080589 100644
--- a/sound/soc/codecs/wm5102.c
+++ b/sound/soc/codecs/wm5102.c
@@ -31,6 +31,7 @@
#include "arizona.h"
#include "wm5102.h"
+#include "wm_adsp.h"
struct wm5102_priv {
struct arizona_priv core;
@@ -42,6 +43,13 @@ static DECLARE_TLV_DB_SCALE(eq_tlv, -1200, 100, 0);
static DECLARE_TLV_DB_SCALE(digital_tlv, -6400, 50, 0);
static DECLARE_TLV_DB_SCALE(noise_tlv, 0, 600, 0);
+static const struct wm_adsp_region wm5102_dsp1_regions[] = {
+ { .type = WMFW_ADSP2_PM, .base = 0x100000 },
+ { .type = WMFW_ADSP2_ZM, .base = 0x180000 },
+ { .type = WMFW_ADSP2_XM, .base = 0x190000 },
+ { .type = WMFW_ADSP2_YM, .base = 0x1a8000 },
+};
+
static const struct reg_default wm5102_sysclk_reva_patch[] = {
{ 0x3000, 0x2225 },
{ 0x3001, 0x3a03 },
@@ -627,11 +635,23 @@ SOC_DOUBLE_R_TLV("IN3 Digital Volume", ARIZONA_ADC_DIGITAL_VOLUME_3L,
ARIZONA_ADC_DIGITAL_VOLUME_3R, ARIZONA_IN3L_DIG_VOL_SHIFT,
0xbf, 0, digital_tlv),
+SOC_ENUM("Input Ramp Up", arizona_in_vi_ramp),
+SOC_ENUM("Input Ramp Down", arizona_in_vd_ramp),
+
ARIZONA_MIXER_CONTROLS("EQ1", ARIZONA_EQ1MIX_INPUT_1_SOURCE),
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_MASK("EQ1 Coefficeints", ARIZONA_EQ1_1, 21,
+ ARIZONA_EQ1_ENA_MASK),
+SND_SOC_BYTES_MASK("EQ2 Coefficeints", ARIZONA_EQ2_1, 21,
+ ARIZONA_EQ2_ENA_MASK),
+SND_SOC_BYTES_MASK("EQ3 Coefficeints", ARIZONA_EQ3_1, 21,
+ ARIZONA_EQ3_ENA_MASK),
+SND_SOC_BYTES_MASK("EQ4 Coefficeints", ARIZONA_EQ4_1, 21,
+ ARIZONA_EQ4_ENA_MASK),
+
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,
@@ -687,6 +707,14 @@ 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_MIXER_CONTROLS("DSP1L", ARIZONA_DSP1LMIX_INPUT_1_SOURCE),
+ARIZONA_MIXER_CONTROLS("DSP1R", ARIZONA_DSP1RMIX_INPUT_1_SOURCE),
+
SOC_ENUM("LHPF1 Mode", arizona_lhpf1_mode),
SOC_ENUM("LHPF2 Mode", arizona_lhpf2_mode),
SOC_ENUM("LHPF3 Mode", arizona_lhpf3_mode),
@@ -708,14 +736,6 @@ ARIZONA_MIXER_CONTROLS("SPKOUTR", ARIZONA_OUT4RMIX_INPUT_1_SOURCE),
ARIZONA_MIXER_CONTROLS("SPKDAT1L", ARIZONA_OUT5LMIX_INPUT_1_SOURCE),
ARIZONA_MIXER_CONTROLS("SPKDAT1R", ARIZONA_OUT5RMIX_INPUT_1_SOURCE),
-SOC_SINGLE("HPOUT1 High Performance Switch", ARIZONA_OUTPUT_PATH_CONFIG_1L,
- ARIZONA_OUT1_OSR_SHIFT, 1, 0),
-SOC_SINGLE("OUT2 High Performance Switch", ARIZONA_OUTPUT_PATH_CONFIG_2L,
- ARIZONA_OUT2_OSR_SHIFT, 1, 0),
-SOC_SINGLE("EPOUT High Performance Switch", ARIZONA_OUTPUT_PATH_CONFIG_3L,
- ARIZONA_OUT3_OSR_SHIFT, 1, 0),
-SOC_SINGLE("Speaker High Performance Switch", ARIZONA_OUTPUT_PATH_CONFIG_4L,
- ARIZONA_OUT4_OSR_SHIFT, 1, 0),
SOC_SINGLE("SPKDAT1 High Performance Switch", ARIZONA_OUTPUT_PATH_CONFIG_5L,
ARIZONA_OUT5_OSR_SHIFT, 1, 0),
@@ -745,16 +765,8 @@ SOC_DOUBLE_R_TLV("SPKDAT1 Digital Volume", ARIZONA_DAC_DIGITAL_VOLUME_5L,
ARIZONA_DAC_DIGITAL_VOLUME_5R, ARIZONA_OUT5L_VOL_SHIFT,
0xbf, 0, digital_tlv),
-SOC_DOUBLE_R_RANGE_TLV("HPOUT1 Volume", ARIZONA_OUTPUT_PATH_CONFIG_1L,
- ARIZONA_OUTPUT_PATH_CONFIG_1R,
- ARIZONA_OUT1L_PGA_VOL_SHIFT,
- 0x34, 0x40, 0, ana_tlv),
-SOC_DOUBLE_R_RANGE_TLV("OUT2 Volume", ARIZONA_OUTPUT_PATH_CONFIG_2L,
- ARIZONA_OUTPUT_PATH_CONFIG_2R,
- ARIZONA_OUT2L_PGA_VOL_SHIFT,
- 0x34, 0x40, 0, ana_tlv),
-SOC_SINGLE_RANGE_TLV("EPOUT Volume", ARIZONA_OUTPUT_PATH_CONFIG_3L,
- ARIZONA_OUT3L_PGA_VOL_SHIFT, 0x34, 0x40, 0, ana_tlv),
+SOC_ENUM("Output Ramp Up", arizona_out_vi_ramp),
+SOC_ENUM("Output Ramp Down", arizona_out_vd_ramp),
SOC_DOUBLE("SPKDAT1 Switch", ARIZONA_PDM_SPK1_CTRL_1, ARIZONA_SPK1L_MUTE_SHIFT,
ARIZONA_SPK1R_MUTE_SHIFT, 1, 1),
@@ -819,11 +831,15 @@ ARIZONA_MIXER_ENUMS(AIF2TX2, ARIZONA_AIF2TX2MIX_INPUT_1_SOURCE);
ARIZONA_MIXER_ENUMS(AIF3TX1, ARIZONA_AIF3TX1MIX_INPUT_1_SOURCE);
ARIZONA_MIXER_ENUMS(AIF3TX2, ARIZONA_AIF3TX2MIX_INPUT_1_SOURCE);
-ARIZONA_MIXER_ENUMS(ASRC1L, ARIZONA_ASRC1LMIX_INPUT_1_SOURCE);
-ARIZONA_MIXER_ENUMS(ASRC1R, ARIZONA_ASRC1RMIX_INPUT_1_SOURCE);
-ARIZONA_MIXER_ENUMS(ASRC2L, ARIZONA_ASRC2LMIX_INPUT_1_SOURCE);
-ARIZONA_MIXER_ENUMS(ASRC2R, ARIZONA_ASRC2RMIX_INPUT_1_SOURCE);
+ARIZONA_MUX_ENUMS(ASRC1L, ARIZONA_ASRC1LMIX_INPUT_1_SOURCE);
+ARIZONA_MUX_ENUMS(ASRC1R, ARIZONA_ASRC1RMIX_INPUT_1_SOURCE);
+ARIZONA_MUX_ENUMS(ASRC2L, ARIZONA_ASRC2LMIX_INPUT_1_SOURCE);
+ARIZONA_MUX_ENUMS(ASRC2R, ARIZONA_ASRC2RMIX_INPUT_1_SOURCE);
+
+ARIZONA_MIXER_ENUMS(DSP1L, ARIZONA_DSP1LMIX_INPUT_1_SOURCE);
+ARIZONA_MIXER_ENUMS(DSP1R, ARIZONA_DSP1RMIX_INPUT_1_SOURCE);
+ARIZONA_DSP_AUX_ENUMS(DSP1, ARIZONA_DSP1AUX1MIX_INPUT_1_SOURCE);
static const char *wm5102_aec_loopback_texts[] = {
"HPOUT1L", "HPOUT1R", "HPOUT2L", "HPOUT2R", "EPOUT",
@@ -864,6 +880,7 @@ SND_SOC_DAPM_REGULATOR_SUPPLY("SPKVDDR", 0, 0),
SND_SOC_DAPM_SIGGEN("TONE"),
SND_SOC_DAPM_SIGGEN("NOISE"),
+SND_SOC_DAPM_SIGGEN("HAPTICS"),
SND_SOC_DAPM_INPUT("IN1L"),
SND_SOC_DAPM_INPUT("IN1R"),
@@ -894,9 +911,9 @@ SND_SOC_DAPM_PGA_E("IN3R PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN3R_ENA_SHIFT,
SND_SOC_DAPM_SUPPLY("MICBIAS1", ARIZONA_MIC_BIAS_CTRL_1,
ARIZONA_MICB1_ENA_SHIFT, 0, NULL, 0),
SND_SOC_DAPM_SUPPLY("MICBIAS2", ARIZONA_MIC_BIAS_CTRL_2,
- ARIZONA_MICB1_ENA_SHIFT, 0, NULL, 0),
+ ARIZONA_MICB2_ENA_SHIFT, 0, NULL, 0),
SND_SOC_DAPM_SUPPLY("MICBIAS3", ARIZONA_MIC_BIAS_CTRL_3,
- ARIZONA_MICB1_ENA_SHIFT, 0, NULL, 0),
+ ARIZONA_MICB3_ENA_SHIFT, 0, NULL, 0),
SND_SOC_DAPM_PGA("Noise Generator", ARIZONA_COMFORT_NOISE_GENERATOR,
ARIZONA_NOISE_GEN_ENA_SHIFT, 0, NULL, 0),
@@ -996,6 +1013,8 @@ SND_SOC_DAPM_AIF_IN("AIF3RX1", NULL, 0,
SND_SOC_DAPM_AIF_IN("AIF3RX2", NULL, 0,
ARIZONA_AIF3_RX_ENABLES, ARIZONA_AIF3RX2_ENA_SHIFT, 0),
+ARIZONA_DSP_WIDGETS(DSP1, "DSP1"),
+
SND_SOC_DAPM_VALUE_MUX("AEC Loopback", ARIZONA_DAC_AEC_CONTROL_1,
ARIZONA_AEC_LOOPBACK_ENA, 0, &wm5102_aec_loopback_mux),
@@ -1071,10 +1090,12 @@ ARIZONA_MIXER_WIDGETS(AIF2TX2, "AIF2TX2"),
ARIZONA_MIXER_WIDGETS(AIF3TX1, "AIF3TX1"),
ARIZONA_MIXER_WIDGETS(AIF3TX2, "AIF3TX2"),
-ARIZONA_MIXER_WIDGETS(ASRC1L, "ASRC1L"),
-ARIZONA_MIXER_WIDGETS(ASRC1R, "ASRC1R"),
-ARIZONA_MIXER_WIDGETS(ASRC2L, "ASRC2L"),
-ARIZONA_MIXER_WIDGETS(ASRC2R, "ASRC2R"),
+ARIZONA_MUX_WIDGETS(ASRC1L, "ASRC1L"),
+ARIZONA_MUX_WIDGETS(ASRC1R, "ASRC1R"),
+ARIZONA_MUX_WIDGETS(ASRC2L, "ASRC2L"),
+ARIZONA_MUX_WIDGETS(ASRC2R, "ASRC2R"),
+
+WM_ADSP2("DSP1", 0),
SND_SOC_DAPM_OUTPUT("HPOUT1L"),
SND_SOC_DAPM_OUTPUT("HPOUT1R"),
@@ -1094,6 +1115,7 @@ SND_SOC_DAPM_OUTPUT("SPKDAT1R"),
{ name, "Noise Generator", "Noise Generator" }, \
{ name, "Tone Generator 1", "Tone Generator 1" }, \
{ name, "Tone Generator 2", "Tone Generator 2" }, \
+ { name, "Haptics", "HAPTICS" }, \
{ name, "AEC", "AEC Loopback" }, \
{ name, "IN1L", "IN1L PGA" }, \
{ name, "IN1R", "IN1R PGA" }, \
@@ -1127,7 +1149,13 @@ SND_SOC_DAPM_OUTPUT("SPKDAT1R"),
{ name, "ASRC1L", "ASRC1L" }, \
{ name, "ASRC1R", "ASRC1R" }, \
{ name, "ASRC2L", "ASRC2L" }, \
- { name, "ASRC2R", "ASRC2R" }
+ { name, "ASRC2R", "ASRC2R" }, \
+ { name, "DSP1.1", "DSP1" }, \
+ { name, "DSP1.2", "DSP1" }, \
+ { name, "DSP1.3", "DSP1" }, \
+ { name, "DSP1.4", "DSP1" }, \
+ { name, "DSP1.5", "DSP1" }, \
+ { name, "DSP1.6", "DSP1" }
static const struct snd_soc_dapm_route wm5102_dapm_routes[] = {
{ "AIF2 Capture", NULL, "DBVDD2" },
@@ -1213,6 +1241,11 @@ static const struct snd_soc_dapm_route wm5102_dapm_routes[] = {
{ "IN3L PGA", NULL, "IN3L" },
{ "IN3R PGA", NULL, "IN3R" },
+ { "ASRC1L", NULL, "ASRC1L Input" },
+ { "ASRC1R", NULL, "ASRC1R Input" },
+ { "ASRC2L", NULL, "ASRC2L Input" },
+ { "ASRC2R", NULL, "ASRC2R Input" },
+
ARIZONA_MIXER_ROUTES("OUT1L", "HPOUT1L"),
ARIZONA_MIXER_ROUTES("OUT1R", "HPOUT1R"),
ARIZONA_MIXER_ROUTES("OUT2L", "HPOUT2L"),
@@ -1255,10 +1288,12 @@ static const struct snd_soc_dapm_route wm5102_dapm_routes[] = {
ARIZONA_MIXER_ROUTES("LHPF3", "LHPF3"),
ARIZONA_MIXER_ROUTES("LHPF4", "LHPF4"),
- ARIZONA_MIXER_ROUTES("ASRC1L", "ASRC1L"),
- ARIZONA_MIXER_ROUTES("ASRC1R", "ASRC1R"),
- ARIZONA_MIXER_ROUTES("ASRC2L", "ASRC2L"),
- ARIZONA_MIXER_ROUTES("ASRC2R", "ASRC2R"),
+ ARIZONA_MUX_ROUTES("ASRC1L"),
+ ARIZONA_MUX_ROUTES("ASRC1R"),
+ ARIZONA_MUX_ROUTES("ASRC2L"),
+ ARIZONA_MUX_ROUTES("ASRC2R"),
+
+ ARIZONA_DSP_ROUTES("DSP1"),
{ "AEC Loopback", "HPOUT1L", "OUT1L" },
{ "AEC Loopback", "HPOUT1R", "OUT1R" },
@@ -1377,9 +1412,28 @@ static struct snd_soc_dai_driver wm5102_dai[] = {
static int wm5102_codec_probe(struct snd_soc_codec *codec)
{
struct wm5102_priv *priv = snd_soc_codec_get_drvdata(codec);
+ int ret;
codec->control_data = priv->core.arizona->regmap;
- return snd_soc_codec_set_cache_io(codec, 32, 16, SND_SOC_REGMAP);
+
+ ret = snd_soc_codec_set_cache_io(codec, 32, 16, SND_SOC_REGMAP);
+ if (ret != 0)
+ return ret;
+
+ snd_soc_dapm_disable_pin(&codec->dapm, "HAPTICS");
+
+ priv->core.arizona->dapm = &codec->dapm;
+
+ return 0;
+}
+
+static int wm5102_codec_remove(struct snd_soc_codec *codec)
+{
+ struct wm5102_priv *priv = snd_soc_codec_get_drvdata(codec);
+
+ priv->core.arizona->dapm = NULL;
+
+ return 0;
}
#define WM5102_DIG_VU 0x0200
@@ -1406,6 +1460,7 @@ static unsigned int wm5102_digital_vu[] = {
static struct snd_soc_codec_driver soc_codec_dev_wm5102 = {
.probe = wm5102_codec_probe,
+ .remove = wm5102_codec_remove,
.idle_bias_off = true,
@@ -1420,11 +1475,11 @@ static struct snd_soc_codec_driver soc_codec_dev_wm5102 = {
.num_dapm_routes = ARRAY_SIZE(wm5102_dapm_routes),
};
-static int __devinit wm5102_probe(struct platform_device *pdev)
+static int wm5102_probe(struct platform_device *pdev)
{
struct arizona *arizona = dev_get_drvdata(pdev->dev.parent);
struct wm5102_priv *wm5102;
- int i;
+ int i, ret;
wm5102 = devm_kzalloc(&pdev->dev, sizeof(struct wm5102_priv),
GFP_KERNEL);
@@ -1434,6 +1489,19 @@ static int __devinit wm5102_probe(struct platform_device *pdev)
wm5102->core.arizona = arizona;
+ wm5102->core.adsp[0].part = "wm5102";
+ wm5102->core.adsp[0].num = 1;
+ wm5102->core.adsp[0].type = WMFW_ADSP2;
+ wm5102->core.adsp[0].base = ARIZONA_DSP1_CONTROL_1;
+ wm5102->core.adsp[0].dev = arizona->dev;
+ wm5102->core.adsp[0].regmap = arizona->regmap;
+ wm5102->core.adsp[0].mem = wm5102_dsp1_regions;
+ wm5102->core.adsp[0].num_mems = ARRAY_SIZE(wm5102_dsp1_regions);
+
+ ret = wm_adsp2_init(&wm5102->core.adsp[0], true);
+ if (ret != 0)
+ return ret;
+
for (i = 0; i < ARRAY_SIZE(wm5102->fll); i++)
wm5102->fll[i].vco_mult = 1;
@@ -1459,7 +1527,7 @@ static int __devinit wm5102_probe(struct platform_device *pdev)
wm5102_dai, ARRAY_SIZE(wm5102_dai));
}
-static int __devexit wm5102_remove(struct platform_device *pdev)
+static int wm5102_remove(struct platform_device *pdev)
{
snd_soc_unregister_codec(&pdev->dev);
pm_runtime_disable(&pdev->dev);
@@ -1473,7 +1541,7 @@ static struct platform_driver wm5102_codec_driver = {
.owner = THIS_MODULE,
},
.probe = wm5102_probe,
- .remove = __devexit_p(wm5102_remove),
+ .remove = wm5102_remove,
};
module_platform_driver(wm5102_codec_driver);
diff --git a/sound/soc/codecs/wm5110.c b/sound/soc/codecs/wm5110.c
index 9211e4192f71..ae80c8c28536 100644
--- a/sound/soc/codecs/wm5110.c
+++ b/sound/soc/codecs/wm5110.c
@@ -84,11 +84,23 @@ SOC_DOUBLE_R_TLV("IN4 Digital Volume", ARIZONA_ADC_DIGITAL_VOLUME_4L,
ARIZONA_ADC_DIGITAL_VOLUME_4R, ARIZONA_IN4L_DIG_VOL_SHIFT,
0xbf, 0, digital_tlv),
+SOC_ENUM("Input Ramp Up", arizona_in_vi_ramp),
+SOC_ENUM("Input Ramp Down", arizona_in_vd_ramp),
+
ARIZONA_MIXER_CONTROLS("EQ1", ARIZONA_EQ1MIX_INPUT_1_SOURCE),
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_MASK("EQ1 Coefficeints", ARIZONA_EQ1_1, 21,
+ ARIZONA_EQ1_ENA_MASK),
+SND_SOC_BYTES_MASK("EQ2 Coefficeints", ARIZONA_EQ2_1, 21,
+ ARIZONA_EQ2_ENA_MASK),
+SND_SOC_BYTES_MASK("EQ3 Coefficeints", ARIZONA_EQ3_1, 21,
+ ARIZONA_EQ3_ENA_MASK),
+SND_SOC_BYTES_MASK("EQ4 Coefficeints", ARIZONA_EQ4_1, 21,
+ ARIZONA_EQ4_ENA_MASK),
+
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,
@@ -148,6 +160,11 @@ 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),
+
SOC_ENUM("LHPF1 Mode", arizona_lhpf1_mode),
SOC_ENUM("LHPF2 Mode", arizona_lhpf2_mode),
SOC_ENUM("LHPF3 Mode", arizona_lhpf3_mode),
@@ -243,6 +260,9 @@ SOC_DOUBLE("SPKDAT1 Switch", ARIZONA_PDM_SPK1_CTRL_1, ARIZONA_SPK1L_MUTE_SHIFT,
SOC_DOUBLE("SPKDAT2 Switch", ARIZONA_PDM_SPK2_CTRL_1, ARIZONA_SPK2L_MUTE_SHIFT,
ARIZONA_SPK2R_MUTE_SHIFT, 1, 1),
+SOC_ENUM("Output Ramp Up", arizona_out_vi_ramp),
+SOC_ENUM("Output Ramp Down", arizona_out_vd_ramp),
+
ARIZONA_MIXER_CONTROLS("AIF1TX1", ARIZONA_AIF1TX1MIX_INPUT_1_SOURCE),
ARIZONA_MIXER_CONTROLS("AIF1TX2", ARIZONA_AIF1TX2MIX_INPUT_1_SOURCE),
ARIZONA_MIXER_CONTROLS("AIF1TX3", ARIZONA_AIF1TX3MIX_INPUT_1_SOURCE),
@@ -308,10 +328,10 @@ ARIZONA_MIXER_ENUMS(AIF2TX2, ARIZONA_AIF2TX2MIX_INPUT_1_SOURCE);
ARIZONA_MIXER_ENUMS(AIF3TX1, ARIZONA_AIF3TX1MIX_INPUT_1_SOURCE);
ARIZONA_MIXER_ENUMS(AIF3TX2, ARIZONA_AIF3TX2MIX_INPUT_1_SOURCE);
-ARIZONA_MIXER_ENUMS(ASRC1L, ARIZONA_ASRC1LMIX_INPUT_1_SOURCE);
-ARIZONA_MIXER_ENUMS(ASRC1R, ARIZONA_ASRC1RMIX_INPUT_1_SOURCE);
-ARIZONA_MIXER_ENUMS(ASRC2L, ARIZONA_ASRC2LMIX_INPUT_1_SOURCE);
-ARIZONA_MIXER_ENUMS(ASRC2R, ARIZONA_ASRC2RMIX_INPUT_1_SOURCE);
+ARIZONA_MUX_ENUMS(ASRC1L, ARIZONA_ASRC1LMIX_INPUT_1_SOURCE);
+ARIZONA_MUX_ENUMS(ASRC1R, ARIZONA_ASRC1RMIX_INPUT_1_SOURCE);
+ARIZONA_MUX_ENUMS(ASRC2L, ARIZONA_ASRC2LMIX_INPUT_1_SOURCE);
+ARIZONA_MUX_ENUMS(ASRC2R, ARIZONA_ASRC2RMIX_INPUT_1_SOURCE);
static const char *wm5110_aec_loopback_texts[] = {
"HPOUT1L", "HPOUT1R", "HPOUT2L", "HPOUT2R", "HPOUT3L", "HPOUT3R",
@@ -352,6 +372,7 @@ SND_SOC_DAPM_REGULATOR_SUPPLY("SPKVDDR", 0, 0),
SND_SOC_DAPM_SIGGEN("TONE"),
SND_SOC_DAPM_SIGGEN("NOISE"),
+SND_SOC_DAPM_SIGGEN("HAPTICS"),
SND_SOC_DAPM_INPUT("IN1L"),
SND_SOC_DAPM_INPUT("IN1R"),
@@ -585,10 +606,10 @@ ARIZONA_MIXER_WIDGETS(AIF2TX2, "AIF2TX2"),
ARIZONA_MIXER_WIDGETS(AIF3TX1, "AIF3TX1"),
ARIZONA_MIXER_WIDGETS(AIF3TX2, "AIF3TX2"),
-ARIZONA_MIXER_WIDGETS(ASRC1L, "ASRC1L"),
-ARIZONA_MIXER_WIDGETS(ASRC1R, "ASRC1R"),
-ARIZONA_MIXER_WIDGETS(ASRC2L, "ASRC2L"),
-ARIZONA_MIXER_WIDGETS(ASRC2R, "ASRC2R"),
+ARIZONA_MUX_WIDGETS(ASRC1L, "ASRC1L"),
+ARIZONA_MUX_WIDGETS(ASRC1R, "ASRC1R"),
+ARIZONA_MUX_WIDGETS(ASRC2L, "ASRC2L"),
+ARIZONA_MUX_WIDGETS(ASRC2R, "ASRC2R"),
SND_SOC_DAPM_OUTPUT("HPOUT1L"),
SND_SOC_DAPM_OUTPUT("HPOUT1R"),
@@ -610,6 +631,7 @@ SND_SOC_DAPM_OUTPUT("SPKDAT2R"),
{ name, "Noise Generator", "Noise Generator" }, \
{ name, "Tone Generator 1", "Tone Generator 1" }, \
{ name, "Tone Generator 2", "Tone Generator 2" }, \
+ { name, "Haptics", "HAPTICS" }, \
{ name, "AEC", "AEC Loopback" }, \
{ name, "IN1L", "IN1L PGA" }, \
{ name, "IN1R", "IN1R PGA" }, \
@@ -786,10 +808,10 @@ static const struct snd_soc_dapm_route wm5110_dapm_routes[] = {
ARIZONA_MIXER_ROUTES("LHPF3", "LHPF3"),
ARIZONA_MIXER_ROUTES("LHPF4", "LHPF4"),
- ARIZONA_MIXER_ROUTES("ASRC1L", "ASRC1L"),
- ARIZONA_MIXER_ROUTES("ASRC1R", "ASRC1R"),
- ARIZONA_MIXER_ROUTES("ASRC2L", "ASRC2L"),
- ARIZONA_MIXER_ROUTES("ASRC2R", "ASRC2R"),
+ ARIZONA_MUX_ROUTES("ASRC1L"),
+ ARIZONA_MUX_ROUTES("ASRC1R"),
+ ARIZONA_MUX_ROUTES("ASRC2L"),
+ ARIZONA_MUX_ROUTES("ASRC2R"),
{ "HPOUT1L", NULL, "OUT1L" },
{ "HPOUT1R", NULL, "OUT1R" },
@@ -902,9 +924,29 @@ static struct snd_soc_dai_driver wm5110_dai[] = {
static int wm5110_codec_probe(struct snd_soc_codec *codec)
{
struct wm5110_priv *priv = snd_soc_codec_get_drvdata(codec);
+ int ret;
codec->control_data = priv->core.arizona->regmap;
- return snd_soc_codec_set_cache_io(codec, 32, 16, SND_SOC_REGMAP);
+ priv->core.arizona->dapm = &codec->dapm;
+
+ ret = snd_soc_codec_set_cache_io(codec, 32, 16, SND_SOC_REGMAP);
+ if (ret != 0)
+ return ret;
+
+ snd_soc_dapm_disable_pin(&codec->dapm, "HAPTICS");
+
+ priv->core.arizona->dapm = &codec->dapm;
+
+ return 0;
+}
+
+static int wm5110_codec_remove(struct snd_soc_codec *codec)
+{
+ struct wm5110_priv *priv = snd_soc_codec_get_drvdata(codec);
+
+ priv->core.arizona->dapm = NULL;
+
+ return 0;
}
#define WM5110_DIG_VU 0x0200
@@ -935,6 +977,7 @@ static unsigned int wm5110_digital_vu[] = {
static struct snd_soc_codec_driver soc_codec_dev_wm5110 = {
.probe = wm5110_codec_probe,
+ .remove = wm5110_codec_remove,
.idle_bias_off = true,
@@ -949,7 +992,7 @@ static struct snd_soc_codec_driver soc_codec_dev_wm5110 = {
.num_dapm_routes = ARRAY_SIZE(wm5110_dapm_routes),
};
-static int __devinit wm5110_probe(struct platform_device *pdev)
+static int wm5110_probe(struct platform_device *pdev)
{
struct arizona *arizona = dev_get_drvdata(pdev->dev.parent);
struct wm5110_priv *wm5110;
@@ -988,7 +1031,7 @@ static int __devinit wm5110_probe(struct platform_device *pdev)
wm5110_dai, ARRAY_SIZE(wm5110_dai));
}
-static int __devexit wm5110_remove(struct platform_device *pdev)
+static int wm5110_remove(struct platform_device *pdev)
{
snd_soc_unregister_codec(&pdev->dev);
pm_runtime_disable(&pdev->dev);
@@ -1002,7 +1045,7 @@ static struct platform_driver wm5110_codec_driver = {
.owner = THIS_MODULE,
},
.probe = wm5110_probe,
- .remove = __devexit_p(wm5110_remove),
+ .remove = wm5110_remove,
};
module_platform_driver(wm5110_codec_driver);
diff --git a/sound/soc/codecs/wm8350.c b/sound/soc/codecs/wm8350.c
index a4cae060bf26..fb92fb47d636 100644
--- a/sound/soc/codecs/wm8350.c
+++ b/sound/soc/codecs/wm8350.c
@@ -1500,7 +1500,7 @@ static int wm8350_codec_probe(struct snd_soc_codec *codec)
for (i = 0; i < ARRAY_SIZE(supply_names); i++)
priv->supplies[i].supply = supply_names[i];
- ret = regulator_bulk_get(wm8350->dev, ARRAY_SIZE(priv->supplies),
+ ret = devm_regulator_bulk_get(wm8350->dev, ARRAY_SIZE(priv->supplies),
priv->supplies);
if (ret != 0)
return ret;
@@ -1607,8 +1607,6 @@ static int wm8350_codec_remove(struct snd_soc_codec *codec)
wm8350_clear_bits(wm8350, WM8350_POWER_MGMT_5, WM8350_CODEC_ENA);
- regulator_bulk_free(ARRAY_SIZE(priv->supplies), priv->supplies);
-
return 0;
}
@@ -1627,13 +1625,13 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8350 = {
.num_dapm_routes = ARRAY_SIZE(wm8350_dapm_routes),
};
-static int __devinit wm8350_probe(struct platform_device *pdev)
+static int wm8350_probe(struct platform_device *pdev)
{
return snd_soc_register_codec(&pdev->dev, &soc_codec_dev_wm8350,
&wm8350_dai, 1);
}
-static int __devexit wm8350_remove(struct platform_device *pdev)
+static int wm8350_remove(struct platform_device *pdev)
{
snd_soc_unregister_codec(&pdev->dev);
return 0;
@@ -1645,7 +1643,7 @@ static struct platform_driver wm8350_codec_driver = {
.owner = THIS_MODULE,
},
.probe = wm8350_probe,
- .remove = __devexit_p(wm8350_remove),
+ .remove = wm8350_remove,
};
module_platform_driver(wm8350_codec_driver);
diff --git a/sound/soc/codecs/wm8400.c b/sound/soc/codecs/wm8400.c
index 5d277a915f81..af6d227e67be 100644
--- a/sound/soc/codecs/wm8400.c
+++ b/sound/soc/codecs/wm8400.c
@@ -1373,7 +1373,7 @@ static int wm8400_codec_probe(struct snd_soc_codec *codec)
codec->control_data = priv->wm8400 = wm8400;
priv->codec = codec;
- ret = regulator_bulk_get(wm8400->dev,
+ ret = devm_regulator_bulk_get(wm8400->dev,
ARRAY_SIZE(power), &power[0]);
if (ret != 0) {
dev_err(codec->dev, "Failed to get regulators: %d\n", ret);
@@ -1398,15 +1398,9 @@ static int wm8400_codec_probe(struct snd_soc_codec *codec)
snd_soc_write(codec, WM8400_LEFT_OUTPUT_VOLUME, 0x50 | (1<<8));
snd_soc_write(codec, WM8400_RIGHT_OUTPUT_VOLUME, 0x50 | (1<<8));
- if (!schedule_work(&priv->work)) {
- ret = -EINVAL;
- goto err_regulator;
- }
+ if (!schedule_work(&priv->work))
+ return -EINVAL;
return 0;
-
-err_regulator:
- regulator_bulk_free(ARRAY_SIZE(power), power);
- return ret;
}
static int wm8400_codec_remove(struct snd_soc_codec *codec)
@@ -1417,8 +1411,6 @@ static int wm8400_codec_remove(struct snd_soc_codec *codec)
snd_soc_write(codec, WM8400_POWER_MANAGEMENT_1,
reg & (~WM8400_CODEC_ENA));
- regulator_bulk_free(ARRAY_SIZE(power), power);
-
return 0;
}
@@ -1439,13 +1431,13 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8400 = {
.num_dapm_routes = ARRAY_SIZE(wm8400_dapm_routes),
};
-static int __devinit wm8400_probe(struct platform_device *pdev)
+static int wm8400_probe(struct platform_device *pdev)
{
return snd_soc_register_codec(&pdev->dev, &soc_codec_dev_wm8400,
&wm8400_dai, 1);
}
-static int __devexit wm8400_remove(struct platform_device *pdev)
+static int wm8400_remove(struct platform_device *pdev)
{
snd_soc_unregister_codec(&pdev->dev);
return 0;
@@ -1457,7 +1449,7 @@ static struct platform_driver wm8400_codec_driver = {
.owner = THIS_MODULE,
},
.probe = wm8400_probe,
- .remove = __devexit_p(wm8400_remove),
+ .remove = wm8400_remove,
};
module_platform_driver(wm8400_codec_driver);
diff --git a/sound/soc/codecs/wm8510.c b/sound/soc/codecs/wm8510.c
index c12a54e72e89..6ed5433943ea 100644
--- a/sound/soc/codecs/wm8510.c
+++ b/sound/soc/codecs/wm8510.c
@@ -608,10 +608,7 @@ static int wm8510_probe(struct snd_soc_codec *codec)
/* power down chip */
static int wm8510_remove(struct snd_soc_codec *codec)
{
- struct wm8510_priv *wm8510 = snd_soc_codec_get_drvdata(codec);
-
wm8510_set_bias_level(codec, SND_SOC_BIAS_OFF);
- kfree(wm8510);
return 0;
}
@@ -648,7 +645,7 @@ static const struct regmap_config wm8510_regmap = {
};
#if defined(CONFIG_SPI_MASTER)
-static int __devinit wm8510_spi_probe(struct spi_device *spi)
+static int wm8510_spi_probe(struct spi_device *spi)
{
struct wm8510_priv *wm8510;
int ret;
@@ -670,7 +667,7 @@ static int __devinit wm8510_spi_probe(struct spi_device *spi)
return ret;
}
-static int __devexit wm8510_spi_remove(struct spi_device *spi)
+static int wm8510_spi_remove(struct spi_device *spi)
{
snd_soc_unregister_codec(&spi->dev);
return 0;
@@ -683,13 +680,13 @@ static struct spi_driver wm8510_spi_driver = {
.of_match_table = wm8510_of_match,
},
.probe = wm8510_spi_probe,
- .remove = __devexit_p(wm8510_spi_remove),
+ .remove = wm8510_spi_remove,
};
#endif /* CONFIG_SPI_MASTER */
#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
-static __devinit int wm8510_i2c_probe(struct i2c_client *i2c,
- const struct i2c_device_id *id)
+static int wm8510_i2c_probe(struct i2c_client *i2c,
+ const struct i2c_device_id *id)
{
struct wm8510_priv *wm8510;
int ret;
@@ -711,7 +708,7 @@ static __devinit int wm8510_i2c_probe(struct i2c_client *i2c,
return ret;
}
-static __devexit int wm8510_i2c_remove(struct i2c_client *client)
+static int wm8510_i2c_remove(struct i2c_client *client)
{
snd_soc_unregister_codec(&client->dev);
return 0;
@@ -730,7 +727,7 @@ static struct i2c_driver wm8510_i2c_driver = {
.of_match_table = wm8510_of_match,
},
.probe = wm8510_i2c_probe,
- .remove = __devexit_p(wm8510_i2c_remove),
+ .remove = wm8510_i2c_remove,
.id_table = wm8510_i2c_id,
};
#endif
diff --git a/sound/soc/codecs/wm8523.c b/sound/soc/codecs/wm8523.c
index 8d5c27673501..139bf9ac9407 100644
--- a/sound/soc/codecs/wm8523.c
+++ b/sound/soc/codecs/wm8523.c
@@ -453,8 +453,8 @@ static const struct regmap_config wm8523_regmap = {
};
#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
-static __devinit int wm8523_i2c_probe(struct i2c_client *i2c,
- const struct i2c_device_id *id)
+static int wm8523_i2c_probe(struct i2c_client *i2c,
+ const struct i2c_device_id *id)
{
struct wm8523_priv *wm8523;
unsigned int val;
@@ -528,7 +528,7 @@ err_enable:
return ret;
}
-static __devexit int wm8523_i2c_remove(struct i2c_client *client)
+static int wm8523_i2c_remove(struct i2c_client *client)
{
snd_soc_unregister_codec(&client->dev);
return 0;
@@ -547,7 +547,7 @@ static struct i2c_driver wm8523_i2c_driver = {
.of_match_table = wm8523_of_match,
},
.probe = wm8523_i2c_probe,
- .remove = __devexit_p(wm8523_i2c_remove),
+ .remove = wm8523_i2c_remove,
.id_table = wm8523_i2c_id,
};
#endif
diff --git a/sound/soc/codecs/wm8711.c b/sound/soc/codecs/wm8711.c
index 8b8bb70f1eb9..5b428b060d41 100644
--- a/sound/soc/codecs/wm8711.c
+++ b/sound/soc/codecs/wm8711.c
@@ -429,7 +429,7 @@ static const struct regmap_config wm8711_regmap = {
};
#if defined(CONFIG_SPI_MASTER)
-static int __devinit wm8711_spi_probe(struct spi_device *spi)
+static int wm8711_spi_probe(struct spi_device *spi)
{
struct wm8711_priv *wm8711;
int ret;
@@ -451,7 +451,7 @@ static int __devinit wm8711_spi_probe(struct spi_device *spi)
return ret;
}
-static int __devexit wm8711_spi_remove(struct spi_device *spi)
+static int wm8711_spi_remove(struct spi_device *spi)
{
snd_soc_unregister_codec(&spi->dev);
@@ -465,13 +465,13 @@ static struct spi_driver wm8711_spi_driver = {
.of_match_table = wm8711_of_match,
},
.probe = wm8711_spi_probe,
- .remove = __devexit_p(wm8711_spi_remove),
+ .remove = wm8711_spi_remove,
};
#endif /* CONFIG_SPI_MASTER */
#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
-static __devinit int wm8711_i2c_probe(struct i2c_client *client,
- const struct i2c_device_id *id)
+static int wm8711_i2c_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
{
struct wm8711_priv *wm8711;
int ret;
@@ -493,7 +493,7 @@ static __devinit int wm8711_i2c_probe(struct i2c_client *client,
return ret;
}
-static __devexit int wm8711_i2c_remove(struct i2c_client *client)
+static int wm8711_i2c_remove(struct i2c_client *client)
{
snd_soc_unregister_codec(&client->dev);
return 0;
@@ -512,7 +512,7 @@ static struct i2c_driver wm8711_i2c_driver = {
.of_match_table = wm8711_of_match,
},
.probe = wm8711_i2c_probe,
- .remove = __devexit_p(wm8711_i2c_remove),
+ .remove = wm8711_i2c_remove,
.id_table = wm8711_i2c_id,
};
#endif
diff --git a/sound/soc/codecs/wm8727.c b/sound/soc/codecs/wm8727.c
index e81705620718..462f5e4d5c05 100644
--- a/sound/soc/codecs/wm8727.c
+++ b/sound/soc/codecs/wm8727.c
@@ -45,13 +45,13 @@ static struct snd_soc_dai_driver wm8727_dai = {
static struct snd_soc_codec_driver soc_codec_dev_wm8727;
-static __devinit int wm8727_probe(struct platform_device *pdev)
+static int wm8727_probe(struct platform_device *pdev)
{
return snd_soc_register_codec(&pdev->dev,
&soc_codec_dev_wm8727, &wm8727_dai, 1);
}
-static int __devexit wm8727_remove(struct platform_device *pdev)
+static int wm8727_remove(struct platform_device *pdev)
{
snd_soc_unregister_codec(&pdev->dev);
return 0;
@@ -64,7 +64,7 @@ static struct platform_driver wm8727_codec_driver = {
},
.probe = wm8727_probe,
- .remove = __devexit_p(wm8727_remove),
+ .remove = wm8727_remove,
};
module_platform_driver(wm8727_codec_driver);
diff --git a/sound/soc/codecs/wm8728.c b/sound/soc/codecs/wm8728.c
index 00a12a0c3919..c6a292dcded0 100644
--- a/sound/soc/codecs/wm8728.c
+++ b/sound/soc/codecs/wm8728.c
@@ -280,7 +280,7 @@ static const struct regmap_config wm8728_regmap = {
};
#if defined(CONFIG_SPI_MASTER)
-static int __devinit wm8728_spi_probe(struct spi_device *spi)
+static int wm8728_spi_probe(struct spi_device *spi)
{
struct wm8728_priv *wm8728;
int ret;
@@ -302,7 +302,7 @@ static int __devinit wm8728_spi_probe(struct spi_device *spi)
return ret;
}
-static int __devexit wm8728_spi_remove(struct spi_device *spi)
+static int wm8728_spi_remove(struct spi_device *spi)
{
snd_soc_unregister_codec(&spi->dev);
@@ -316,13 +316,13 @@ static struct spi_driver wm8728_spi_driver = {
.of_match_table = wm8728_of_match,
},
.probe = wm8728_spi_probe,
- .remove = __devexit_p(wm8728_spi_remove),
+ .remove = wm8728_spi_remove,
};
#endif /* CONFIG_SPI_MASTER */
#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
-static __devinit int wm8728_i2c_probe(struct i2c_client *i2c,
- const struct i2c_device_id *id)
+static int wm8728_i2c_probe(struct i2c_client *i2c,
+ const struct i2c_device_id *id)
{
struct wm8728_priv *wm8728;
int ret;
@@ -344,7 +344,7 @@ static __devinit int wm8728_i2c_probe(struct i2c_client *i2c,
return ret;
}
-static __devexit int wm8728_i2c_remove(struct i2c_client *client)
+static int wm8728_i2c_remove(struct i2c_client *client)
{
snd_soc_unregister_codec(&client->dev);
return 0;
@@ -363,7 +363,7 @@ static struct i2c_driver wm8728_i2c_driver = {
.of_match_table = wm8728_of_match,
},
.probe = wm8728_i2c_probe,
- .remove = __devexit_p(wm8728_i2c_remove),
+ .remove = wm8728_i2c_remove,
.id_table = wm8728_i2c_id,
};
#endif
diff --git a/sound/soc/codecs/wm8731.c b/sound/soc/codecs/wm8731.c
index bb1d26919b10..5276062d6c79 100644
--- a/sound/soc/codecs/wm8731.c
+++ b/sound/soc/codecs/wm8731.c
@@ -631,7 +631,7 @@ static const struct regmap_config wm8731_regmap = {
};
#if defined(CONFIG_SPI_MASTER)
-static int __devinit wm8731_spi_probe(struct spi_device *spi)
+static int wm8731_spi_probe(struct spi_device *spi)
{
struct wm8731_priv *wm8731;
int ret;
@@ -661,7 +661,7 @@ static int __devinit wm8731_spi_probe(struct spi_device *spi)
return 0;
}
-static int __devexit wm8731_spi_remove(struct spi_device *spi)
+static int wm8731_spi_remove(struct spi_device *spi)
{
snd_soc_unregister_codec(&spi->dev);
return 0;
@@ -674,13 +674,13 @@ static struct spi_driver wm8731_spi_driver = {
.of_match_table = wm8731_of_match,
},
.probe = wm8731_spi_probe,
- .remove = __devexit_p(wm8731_spi_remove),
+ .remove = wm8731_spi_remove,
};
#endif /* CONFIG_SPI_MASTER */
#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
-static __devinit int wm8731_i2c_probe(struct i2c_client *i2c,
- const struct i2c_device_id *id)
+static int wm8731_i2c_probe(struct i2c_client *i2c,
+ const struct i2c_device_id *id)
{
struct wm8731_priv *wm8731;
int ret;
@@ -710,7 +710,7 @@ static __devinit int wm8731_i2c_probe(struct i2c_client *i2c,
return 0;
}
-static __devexit int wm8731_i2c_remove(struct i2c_client *client)
+static int wm8731_i2c_remove(struct i2c_client *client)
{
snd_soc_unregister_codec(&client->dev);
return 0;
@@ -729,7 +729,7 @@ static struct i2c_driver wm8731_i2c_driver = {
.of_match_table = wm8731_of_match,
},
.probe = wm8731_i2c_probe,
- .remove = __devexit_p(wm8731_i2c_remove),
+ .remove = wm8731_i2c_remove,
.id_table = wm8731_i2c_id,
};
#endif
diff --git a/sound/soc/codecs/wm8737.c b/sound/soc/codecs/wm8737.c
index 5c9634f4c1f0..2f167a8ca01b 100644
--- a/sound/soc/codecs/wm8737.c
+++ b/sound/soc/codecs/wm8737.c
@@ -645,8 +645,8 @@ static const struct regmap_config wm8737_regmap = {
};
#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
-static __devinit int wm8737_i2c_probe(struct i2c_client *i2c,
- const struct i2c_device_id *id)
+static int wm8737_i2c_probe(struct i2c_client *i2c,
+ const struct i2c_device_id *id)
{
struct wm8737_priv *wm8737;
int ret, i;
@@ -679,7 +679,7 @@ static __devinit int wm8737_i2c_probe(struct i2c_client *i2c,
}
-static __devexit int wm8737_i2c_remove(struct i2c_client *client)
+static int wm8737_i2c_remove(struct i2c_client *client)
{
snd_soc_unregister_codec(&client->dev);
@@ -699,13 +699,13 @@ static struct i2c_driver wm8737_i2c_driver = {
.of_match_table = wm8737_of_match,
},
.probe = wm8737_i2c_probe,
- .remove = __devexit_p(wm8737_i2c_remove),
+ .remove = wm8737_i2c_remove,
.id_table = wm8737_i2c_id,
};
#endif
#if defined(CONFIG_SPI_MASTER)
-static int __devinit wm8737_spi_probe(struct spi_device *spi)
+static int wm8737_spi_probe(struct spi_device *spi)
{
struct wm8737_priv *wm8737;
int ret, i;
@@ -737,7 +737,7 @@ static int __devinit wm8737_spi_probe(struct spi_device *spi)
return ret;
}
-static int __devexit wm8737_spi_remove(struct spi_device *spi)
+static int wm8737_spi_remove(struct spi_device *spi)
{
snd_soc_unregister_codec(&spi->dev);
@@ -751,7 +751,7 @@ static struct spi_driver wm8737_spi_driver = {
.of_match_table = wm8737_of_match,
},
.probe = wm8737_spi_probe,
- .remove = __devexit_p(wm8737_spi_remove),
+ .remove = wm8737_spi_remove,
};
#endif /* CONFIG_SPI_MASTER */
diff --git a/sound/soc/codecs/wm8741.c b/sound/soc/codecs/wm8741.c
index 4281a0802138..b18813cc7ba9 100644
--- a/sound/soc/codecs/wm8741.c
+++ b/sound/soc/codecs/wm8741.c
@@ -522,7 +522,7 @@ static int wm8741_i2c_probe(struct i2c_client *i2c,
return ret;
}
- wm8741->regmap = regmap_init_i2c(i2c, &wm8741_regmap);
+ wm8741->regmap = devm_regmap_init_i2c(i2c, &wm8741_regmap);
if (IS_ERR(wm8741->regmap)) {
ret = PTR_ERR(wm8741->regmap);
dev_err(&i2c->dev, "Failed to init regmap: %d\n", ret);
@@ -562,7 +562,7 @@ static struct i2c_driver wm8741_i2c_driver = {
#endif
#if defined(CONFIG_SPI_MASTER)
-static int __devinit wm8741_spi_probe(struct spi_device *spi)
+static int wm8741_spi_probe(struct spi_device *spi)
{
struct wm8741_priv *wm8741;
int ret, i;
@@ -582,7 +582,7 @@ static int __devinit wm8741_spi_probe(struct spi_device *spi)
return ret;
}
- wm8741->regmap = regmap_init_spi(spi, &wm8741_regmap);
+ wm8741->regmap = devm_regmap_init_spi(spi, &wm8741_regmap);
if (IS_ERR(wm8741->regmap)) {
ret = PTR_ERR(wm8741->regmap);
dev_err(&spi->dev, "Failed to init regmap: %d\n", ret);
@@ -596,7 +596,7 @@ static int __devinit wm8741_spi_probe(struct spi_device *spi)
return ret;
}
-static int __devexit wm8741_spi_remove(struct spi_device *spi)
+static int wm8741_spi_remove(struct spi_device *spi)
{
snd_soc_unregister_codec(&spi->dev);
return 0;
@@ -609,7 +609,7 @@ static struct spi_driver wm8741_spi_driver = {
.of_match_table = wm8741_of_match,
},
.probe = wm8741_spi_probe,
- .remove = __devexit_p(wm8741_spi_remove),
+ .remove = wm8741_spi_remove,
};
#endif /* CONFIG_SPI_MASTER */
diff --git a/sound/soc/codecs/wm8750.c b/sound/soc/codecs/wm8750.c
index 89151ca5e776..50d5ff616232 100644
--- a/sound/soc/codecs/wm8750.c
+++ b/sound/soc/codecs/wm8750.c
@@ -18,6 +18,7 @@
#include <linux/delay.h>
#include <linux/pm.h>
#include <linux/i2c.h>
+#include <linux/regmap.h>
#include <linux/spi/spi.h>
#include <linux/slab.h>
#include <linux/of_device.h>
@@ -34,24 +35,55 @@
* We can't read the WM8750 register space when we
* are using 2 wire for device control, so we cache them instead.
*/
-static const u16 wm8750_reg[] = {
- 0x0097, 0x0097, 0x0079, 0x0079, /* 0 */
- 0x0000, 0x0008, 0x0000, 0x000a, /* 4 */
- 0x0000, 0x0000, 0x00ff, 0x00ff, /* 8 */
- 0x000f, 0x000f, 0x0000, 0x0000, /* 12 */
- 0x0000, 0x007b, 0x0000, 0x0032, /* 16 */
- 0x0000, 0x00c3, 0x00c3, 0x00c0, /* 20 */
- 0x0000, 0x0000, 0x0000, 0x0000, /* 24 */
- 0x0000, 0x0000, 0x0000, 0x0000, /* 28 */
- 0x0000, 0x0000, 0x0050, 0x0050, /* 32 */
- 0x0050, 0x0050, 0x0050, 0x0050, /* 36 */
- 0x0079, 0x0079, 0x0079, /* 40 */
+static const struct reg_default wm8750_reg_defaults[] = {
+ { 0, 0x0097 },
+ { 1, 0x0097 },
+ { 2, 0x0079 },
+ { 3, 0x0079 },
+ { 4, 0x0000 },
+ { 5, 0x0008 },
+ { 6, 0x0000 },
+ { 7, 0x000a },
+ { 8, 0x0000 },
+ { 9, 0x0000 },
+ { 10, 0x00ff },
+ { 11, 0x00ff },
+ { 12, 0x000f },
+ { 13, 0x000f },
+ { 14, 0x0000 },
+ { 15, 0x0000 },
+ { 16, 0x0000 },
+ { 17, 0x007b },
+ { 18, 0x0000 },
+ { 19, 0x0032 },
+ { 20, 0x0000 },
+ { 21, 0x00c3 },
+ { 22, 0x00c3 },
+ { 23, 0x00c0 },
+ { 24, 0x0000 },
+ { 25, 0x0000 },
+ { 26, 0x0000 },
+ { 27, 0x0000 },
+ { 28, 0x0000 },
+ { 29, 0x0000 },
+ { 30, 0x0000 },
+ { 31, 0x0000 },
+ { 32, 0x0000 },
+ { 33, 0x0000 },
+ { 34, 0x0050 },
+ { 35, 0x0050 },
+ { 36, 0x0050 },
+ { 37, 0x0050 },
+ { 38, 0x0050 },
+ { 39, 0x0050 },
+ { 40, 0x0079 },
+ { 41, 0x0079 },
+ { 42, 0x0079 },
};
/* codec private data */
struct wm8750_priv {
unsigned int sysclk;
- enum snd_soc_control_type control_type;
};
#define wm8750_reset(c) snd_soc_write(c, WM8750_RESET, 0)
@@ -668,10 +700,9 @@ static int wm8750_resume(struct snd_soc_codec *codec)
static int wm8750_probe(struct snd_soc_codec *codec)
{
- struct wm8750_priv *wm8750 = snd_soc_codec_get_drvdata(codec);
int ret;
- ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8750->control_type);
+ ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP);
if (ret < 0) {
printk(KERN_ERR "wm8750: failed to set cache I/O: %d\n", ret);
return ret;
@@ -711,9 +742,6 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8750 = {
.suspend = wm8750_suspend,
.resume = wm8750_resume,
.set_bias_level = wm8750_set_bias_level,
- .reg_cache_size = ARRAY_SIZE(wm8750_reg),
- .reg_word_size = sizeof(u16),
- .reg_cache_default = wm8750_reg,
.controls = wm8750_snd_controls,
.num_controls = ARRAY_SIZE(wm8750_snd_controls),
@@ -730,10 +758,21 @@ static const struct of_device_id wm8750_of_match[] = {
};
MODULE_DEVICE_TABLE(of, wm8750_of_match);
+static const struct regmap_config wm8750_regmap = {
+ .reg_bits = 7,
+ .val_bits = 9,
+ .max_register = WM8750_MOUTV,
+
+ .reg_defaults = wm8750_reg_defaults,
+ .num_reg_defaults = ARRAY_SIZE(wm8750_reg_defaults),
+ .cache_type = REGCACHE_RBTREE,
+};
+
#if defined(CONFIG_SPI_MASTER)
-static int __devinit wm8750_spi_probe(struct spi_device *spi)
+static int wm8750_spi_probe(struct spi_device *spi)
{
struct wm8750_priv *wm8750;
+ struct regmap *regmap;
int ret;
wm8750 = devm_kzalloc(&spi->dev, sizeof(struct wm8750_priv),
@@ -741,7 +780,10 @@ static int __devinit wm8750_spi_probe(struct spi_device *spi)
if (wm8750 == NULL)
return -ENOMEM;
- wm8750->control_type = SND_SOC_SPI;
+ regmap = devm_regmap_init_spi(spi, &wm8750_regmap);
+ if (IS_ERR(regmap))
+ return PTR_ERR(regmap);
+
spi_set_drvdata(spi, wm8750);
ret = snd_soc_register_codec(&spi->dev,
@@ -749,7 +791,7 @@ static int __devinit wm8750_spi_probe(struct spi_device *spi)
return ret;
}
-static int __devexit wm8750_spi_remove(struct spi_device *spi)
+static int wm8750_spi_remove(struct spi_device *spi)
{
snd_soc_unregister_codec(&spi->dev);
return 0;
@@ -770,15 +812,16 @@ static struct spi_driver wm8750_spi_driver = {
},
.id_table = wm8750_spi_ids,
.probe = wm8750_spi_probe,
- .remove = __devexit_p(wm8750_spi_remove),
+ .remove = wm8750_spi_remove,
};
#endif /* CONFIG_SPI_MASTER */
#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
-static __devinit int wm8750_i2c_probe(struct i2c_client *i2c,
- const struct i2c_device_id *id)
+static int wm8750_i2c_probe(struct i2c_client *i2c,
+ const struct i2c_device_id *id)
{
struct wm8750_priv *wm8750;
+ struct regmap *regmap;
int ret;
wm8750 = devm_kzalloc(&i2c->dev, sizeof(struct wm8750_priv),
@@ -787,14 +830,17 @@ static __devinit int wm8750_i2c_probe(struct i2c_client *i2c,
return -ENOMEM;
i2c_set_clientdata(i2c, wm8750);
- wm8750->control_type = SND_SOC_I2C;
+
+ regmap = devm_regmap_init_i2c(i2c, &wm8750_regmap);
+ if (IS_ERR(regmap))
+ return PTR_ERR(regmap);
ret = snd_soc_register_codec(&i2c->dev,
&soc_codec_dev_wm8750, &wm8750_dai, 1);
return ret;
}
-static __devexit int wm8750_i2c_remove(struct i2c_client *client)
+static int wm8750_i2c_remove(struct i2c_client *client)
{
snd_soc_unregister_codec(&client->dev);
return 0;
@@ -814,7 +860,7 @@ static struct i2c_driver wm8750_i2c_driver = {
.of_match_table = wm8750_of_match,
},
.probe = wm8750_i2c_probe,
- .remove = __devexit_p(wm8750_i2c_remove),
+ .remove = wm8750_i2c_remove,
.id_table = wm8750_i2c_id,
};
#endif
diff --git a/sound/soc/codecs/wm8753.c b/sound/soc/codecs/wm8753.c
index 2e4a775ae560..0a4ab4c423d1 100644
--- a/sound/soc/codecs/wm8753.c
+++ b/sound/soc/codecs/wm8753.c
@@ -1550,7 +1550,7 @@ static const struct regmap_config wm8753_regmap = {
};
#if defined(CONFIG_SPI_MASTER)
-static int __devinit wm8753_spi_probe(struct spi_device *spi)
+static int wm8753_spi_probe(struct spi_device *spi)
{
struct wm8753_priv *wm8753;
int ret;
@@ -1562,36 +1562,25 @@ static int __devinit wm8753_spi_probe(struct spi_device *spi)
spi_set_drvdata(spi, wm8753);
- wm8753->regmap = regmap_init_spi(spi, &wm8753_regmap);
+ wm8753->regmap = devm_regmap_init_spi(spi, &wm8753_regmap);
if (IS_ERR(wm8753->regmap)) {
ret = PTR_ERR(wm8753->regmap);
dev_err(&spi->dev, "Failed to allocate register map: %d\n",
ret);
- goto err;
+ return ret;
}
ret = snd_soc_register_codec(&spi->dev, &soc_codec_dev_wm8753,
wm8753_dai, ARRAY_SIZE(wm8753_dai));
- if (ret != 0) {
+ if (ret != 0)
dev_err(&spi->dev, "Failed to register CODEC: %d\n", ret);
- goto err_regmap;
- }
- return 0;
-
-err_regmap:
- regmap_exit(wm8753->regmap);
-err:
return ret;
}
-static int __devexit wm8753_spi_remove(struct spi_device *spi)
+static int wm8753_spi_remove(struct spi_device *spi)
{
- struct wm8753_priv *wm8753 = spi_get_drvdata(spi);
-
snd_soc_unregister_codec(&spi->dev);
- regmap_exit(wm8753->regmap);
- kfree(wm8753);
return 0;
}
@@ -1602,13 +1591,13 @@ static struct spi_driver wm8753_spi_driver = {
.of_match_table = wm8753_of_match,
},
.probe = wm8753_spi_probe,
- .remove = __devexit_p(wm8753_spi_remove),
+ .remove = wm8753_spi_remove,
};
#endif /* CONFIG_SPI_MASTER */
#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
-static __devinit int wm8753_i2c_probe(struct i2c_client *i2c,
- const struct i2c_device_id *id)
+static int wm8753_i2c_probe(struct i2c_client *i2c,
+ const struct i2c_device_id *id)
{
struct wm8753_priv *wm8753;
int ret;
@@ -1620,35 +1609,25 @@ static __devinit int wm8753_i2c_probe(struct i2c_client *i2c,
i2c_set_clientdata(i2c, wm8753);
- wm8753->regmap = regmap_init_i2c(i2c, &wm8753_regmap);
+ wm8753->regmap = devm_regmap_init_i2c(i2c, &wm8753_regmap);
if (IS_ERR(wm8753->regmap)) {
ret = PTR_ERR(wm8753->regmap);
dev_err(&i2c->dev, "Failed to allocate register map: %d\n",
ret);
- goto err;
+ return ret;
}
ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_wm8753,
wm8753_dai, ARRAY_SIZE(wm8753_dai));
- if (ret != 0) {
+ if (ret != 0)
dev_err(&i2c->dev, "Failed to register CODEC: %d\n", ret);
- goto err_regmap;
- }
- return 0;
-
-err_regmap:
- regmap_exit(wm8753->regmap);
-err:
return ret;
}
-static __devexit int wm8753_i2c_remove(struct i2c_client *client)
+static int wm8753_i2c_remove(struct i2c_client *client)
{
- struct wm8753_priv *wm8753 = i2c_get_clientdata(client);
-
snd_soc_unregister_codec(&client->dev);
- regmap_exit(wm8753->regmap);
return 0;
}
@@ -1665,7 +1644,7 @@ static struct i2c_driver wm8753_i2c_driver = {
.of_match_table = wm8753_of_match,
},
.probe = wm8753_i2c_probe,
- .remove = __devexit_p(wm8753_i2c_remove),
+ .remove = wm8753_i2c_remove,
.id_table = wm8753_i2c_id,
};
#endif
diff --git a/sound/soc/codecs/wm8770.c b/sound/soc/codecs/wm8770.c
index c7c0034d3966..89a18d82f303 100644
--- a/sound/soc/codecs/wm8770.c
+++ b/sound/soc/codecs/wm8770.c
@@ -17,6 +17,7 @@
#include <linux/of_device.h>
#include <linux/pm.h>
#include <linux/spi/spi.h>
+#include <linux/regmap.h>
#include <linux/regulator/consumer.h>
#include <linux/slab.h>
#include <sound/core.h>
@@ -35,19 +36,52 @@ static const char *wm8770_supply_names[WM8770_NUM_SUPPLIES] = {
"DVDD"
};
-static const u16 wm8770_reg_defs[WM8770_CACHEREGNUM] = {
- 0x7f, 0x7f, 0x7f, 0x7f,
- 0x7f, 0x7f, 0x7f, 0x7f,
- 0x7f, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0, 0x90, 0,
- 0, 0x22, 0x22, 0x3e,
- 0xc, 0xc, 0x100, 0x189,
- 0x189, 0x8770
+static const struct reg_default wm8770_reg_defaults[] = {
+ { 0, 0x7f },
+ { 1, 0x7f },
+ { 2, 0x7f },
+ { 3, 0x7f },
+ { 4, 0x7f },
+ { 5, 0x7f },
+ { 6, 0x7f },
+ { 7, 0x7f },
+ { 8, 0x7f },
+ { 9, 0xff },
+ { 10, 0xff },
+ { 11, 0xff },
+ { 12, 0xff },
+ { 13, 0xff },
+ { 14, 0xff },
+ { 15, 0xff },
+ { 16, 0xff },
+ { 17, 0xff },
+ { 18, 0 },
+ { 19, 0x90 },
+ { 20, 0 },
+ { 21, 0 },
+ { 22, 0x22 },
+ { 23, 0x22 },
+ { 24, 0x3e },
+ { 25, 0xc },
+ { 26, 0xc },
+ { 27, 0x100 },
+ { 28, 0x189 },
+ { 29, 0x189 },
+ { 30, 0x8770 },
};
+static bool wm8770_volatile_reg(struct device *dev, unsigned int reg)
+{
+ switch (reg) {
+ case WM8770_RESET:
+ return true;
+ default:
+ return false;
+ }
+}
+
struct wm8770_priv {
- enum snd_soc_control_type control_type;
+ struct regmap *regmap;
struct regulator_bulk_data supplies[WM8770_NUM_SUPPLIES];
struct notifier_block disable_nb[WM8770_NUM_SUPPLIES];
struct snd_soc_codec *codec;
@@ -71,7 +105,7 @@ static int wm8770_regulator_event_##n(struct notifier_block *nb, \
struct wm8770_priv *wm8770 = container_of(nb, struct wm8770_priv, \
disable_nb[n]); \
if (event & REGULATOR_EVENT_DISABLE) { \
- wm8770->codec->cache_sync = 1; \
+ regcache_mark_dirty(wm8770->regmap); \
} \
return 0; \
}
@@ -466,24 +500,6 @@ static int wm8770_set_sysclk(struct snd_soc_dai *dai,
return 0;
}
-static void wm8770_sync_cache(struct snd_soc_codec *codec)
-{
- int i;
- u16 *cache;
-
- if (!codec->cache_sync)
- return;
-
- codec->cache_only = 0;
- cache = codec->reg_cache;
- for (i = 0; i < codec->driver->reg_cache_size; i++) {
- if (i == WM8770_RESET || cache[i] == wm8770_reg_defs[i])
- continue;
- snd_soc_write(codec, i, cache[i]);
- }
- codec->cache_sync = 0;
-}
-
static int wm8770_set_bias_level(struct snd_soc_codec *codec,
enum snd_soc_bias_level level)
{
@@ -507,7 +523,9 @@ static int wm8770_set_bias_level(struct snd_soc_codec *codec,
ret);
return ret;
}
- wm8770_sync_cache(codec);
+
+ regcache_sync(wm8770->regmap);
+
/* global powerup */
snd_soc_write(codec, WM8770_PWDNCTRL, 0);
}
@@ -554,68 +572,25 @@ static struct snd_soc_dai_driver wm8770_dai = {
.symmetric_rates = 1
};
-#ifdef CONFIG_PM
-static int wm8770_suspend(struct snd_soc_codec *codec)
-{
- wm8770_set_bias_level(codec, SND_SOC_BIAS_OFF);
- return 0;
-}
-
-static int wm8770_resume(struct snd_soc_codec *codec)
-{
- wm8770_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
- return 0;
-}
-#else
-#define wm8770_suspend NULL
-#define wm8770_resume NULL
-#endif
-
static int wm8770_probe(struct snd_soc_codec *codec)
{
struct wm8770_priv *wm8770;
int ret;
- int i;
wm8770 = snd_soc_codec_get_drvdata(codec);
wm8770->codec = codec;
- ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8770->control_type);
+ ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP);
if (ret < 0) {
dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
return ret;
}
- for (i = 0; i < ARRAY_SIZE(wm8770->supplies); i++)
- wm8770->supplies[i].supply = wm8770_supply_names[i];
-
- ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(wm8770->supplies),
- wm8770->supplies);
- if (ret) {
- dev_err(codec->dev, "Failed to request supplies: %d\n", ret);
- return ret;
- }
-
- wm8770->disable_nb[0].notifier_call = wm8770_regulator_event_0;
- wm8770->disable_nb[1].notifier_call = wm8770_regulator_event_1;
- wm8770->disable_nb[2].notifier_call = wm8770_regulator_event_2;
-
- /* This should really be moved into the regulator core */
- for (i = 0; i < ARRAY_SIZE(wm8770->supplies); i++) {
- ret = regulator_register_notifier(wm8770->supplies[i].consumer,
- &wm8770->disable_nb[i]);
- if (ret) {
- dev_err(codec->dev,
- "Failed to register regulator notifier: %d\n",
- ret);
- }
- }
-
ret = regulator_bulk_enable(ARRAY_SIZE(wm8770->supplies),
wm8770->supplies);
if (ret) {
dev_err(codec->dev, "Failed to enable supplies: %d\n", ret);
- goto err_reg_get;
+ return ret;
}
ret = wm8770_reset(codec);
@@ -624,8 +599,6 @@ static int wm8770_probe(struct snd_soc_codec *codec)
goto err_reg_enable;
}
- wm8770_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
-
/* latch the volume update bits */
snd_soc_update_bits(codec, WM8770_MSDIGVOL, 0x100, 0x100);
snd_soc_update_bits(codec, WM8770_MSALGVOL, 0x100, 0x100);
@@ -641,46 +614,22 @@ static int wm8770_probe(struct snd_soc_codec *codec)
/* mute all DACs */
snd_soc_update_bits(codec, WM8770_DACMUTE, 0x10, 0x10);
- snd_soc_add_codec_controls(codec, wm8770_snd_controls,
- ARRAY_SIZE(wm8770_snd_controls));
- snd_soc_dapm_new_controls(&codec->dapm, wm8770_dapm_widgets,
- ARRAY_SIZE(wm8770_dapm_widgets));
- snd_soc_dapm_add_routes(&codec->dapm, wm8770_intercon,
- ARRAY_SIZE(wm8770_intercon));
- return 0;
-
err_reg_enable:
regulator_bulk_disable(ARRAY_SIZE(wm8770->supplies), wm8770->supplies);
-err_reg_get:
- regulator_bulk_free(ARRAY_SIZE(wm8770->supplies), wm8770->supplies);
return ret;
}
-static int wm8770_remove(struct snd_soc_codec *codec)
-{
- struct wm8770_priv *wm8770;
- int i;
-
- wm8770 = snd_soc_codec_get_drvdata(codec);
- wm8770_set_bias_level(codec, SND_SOC_BIAS_OFF);
-
- for (i = 0; i < ARRAY_SIZE(wm8770->supplies); ++i)
- regulator_unregister_notifier(wm8770->supplies[i].consumer,
- &wm8770->disable_nb[i]);
- regulator_bulk_free(ARRAY_SIZE(wm8770->supplies), wm8770->supplies);
- return 0;
-}
-
static struct snd_soc_codec_driver soc_codec_dev_wm8770 = {
.probe = wm8770_probe,
- .remove = wm8770_remove,
- .suspend = wm8770_suspend,
- .resume = wm8770_resume,
.set_bias_level = wm8770_set_bias_level,
.idle_bias_off = true,
- .reg_cache_size = ARRAY_SIZE(wm8770_reg_defs),
- .reg_word_size = sizeof (u16),
- .reg_cache_default = wm8770_reg_defs
+
+ .controls = wm8770_snd_controls,
+ .num_controls = ARRAY_SIZE(wm8770_snd_controls),
+ .dapm_widgets = wm8770_dapm_widgets,
+ .num_dapm_widgets = ARRAY_SIZE(wm8770_dapm_widgets),
+ .dapm_routes = wm8770_intercon,
+ .num_dapm_routes = ARRAY_SIZE(wm8770_intercon),
};
static const struct of_device_id wm8770_of_match[] = {
@@ -689,17 +638,57 @@ static const struct of_device_id wm8770_of_match[] = {
};
MODULE_DEVICE_TABLE(of, wm8770_of_match);
-static int __devinit wm8770_spi_probe(struct spi_device *spi)
+static const struct regmap_config wm8770_regmap = {
+ .reg_bits = 7,
+ .val_bits = 9,
+ .max_register = WM8770_RESET,
+
+ .reg_defaults = wm8770_reg_defaults,
+ .num_reg_defaults = ARRAY_SIZE(wm8770_reg_defaults),
+ .cache_type = REGCACHE_RBTREE,
+
+ .volatile_reg = wm8770_volatile_reg,
+};
+
+static int wm8770_spi_probe(struct spi_device *spi)
{
struct wm8770_priv *wm8770;
- int ret;
+ int ret, i;
wm8770 = devm_kzalloc(&spi->dev, sizeof(struct wm8770_priv),
GFP_KERNEL);
if (!wm8770)
return -ENOMEM;
- wm8770->control_type = SND_SOC_SPI;
+ for (i = 0; i < ARRAY_SIZE(wm8770->supplies); i++)
+ wm8770->supplies[i].supply = wm8770_supply_names[i];
+
+ ret = devm_regulator_bulk_get(&spi->dev, ARRAY_SIZE(wm8770->supplies),
+ wm8770->supplies);
+ if (ret) {
+ dev_err(&spi->dev, "Failed to request supplies: %d\n", ret);
+ return ret;
+ }
+
+ wm8770->disable_nb[0].notifier_call = wm8770_regulator_event_0;
+ wm8770->disable_nb[1].notifier_call = wm8770_regulator_event_1;
+ wm8770->disable_nb[2].notifier_call = wm8770_regulator_event_2;
+
+ /* This should really be moved into the regulator core */
+ for (i = 0; i < ARRAY_SIZE(wm8770->supplies); i++) {
+ ret = regulator_register_notifier(wm8770->supplies[i].consumer,
+ &wm8770->disable_nb[i]);
+ if (ret) {
+ dev_err(&spi->dev,
+ "Failed to register regulator notifier: %d\n",
+ ret);
+ }
+ }
+
+ wm8770->regmap = devm_regmap_init_spi(spi, &wm8770_regmap);
+ if (IS_ERR(wm8770->regmap))
+ return PTR_ERR(wm8770->regmap);
+
spi_set_drvdata(spi, wm8770);
ret = snd_soc_register_codec(&spi->dev,
@@ -708,9 +697,17 @@ static int __devinit wm8770_spi_probe(struct spi_device *spi)
return ret;
}
-static int __devexit wm8770_spi_remove(struct spi_device *spi)
+static int wm8770_spi_remove(struct spi_device *spi)
{
+ struct wm8770_priv *wm8770 = spi_get_drvdata(spi);
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(wm8770->supplies); ++i)
+ regulator_unregister_notifier(wm8770->supplies[i].consumer,
+ &wm8770->disable_nb[i]);
+
snd_soc_unregister_codec(&spi->dev);
+
return 0;
}
@@ -721,7 +718,7 @@ static struct spi_driver wm8770_spi_driver = {
.of_match_table = wm8770_of_match,
},
.probe = wm8770_spi_probe,
- .remove = __devexit_p(wm8770_spi_remove)
+ .remove = wm8770_spi_remove
};
module_spi_driver(wm8770_spi_driver);
diff --git a/sound/soc/codecs/wm8776.c b/sound/soc/codecs/wm8776.c
index c32249ddb2e0..f31017ed1381 100644
--- a/sound/soc/codecs/wm8776.c
+++ b/sound/soc/codecs/wm8776.c
@@ -492,7 +492,7 @@ static const struct regmap_config wm8776_regmap = {
};
#if defined(CONFIG_SPI_MASTER)
-static int __devinit wm8776_spi_probe(struct spi_device *spi)
+static int wm8776_spi_probe(struct spi_device *spi)
{
struct wm8776_priv *wm8776;
int ret;
@@ -514,7 +514,7 @@ static int __devinit wm8776_spi_probe(struct spi_device *spi)
return ret;
}
-static int __devexit wm8776_spi_remove(struct spi_device *spi)
+static int wm8776_spi_remove(struct spi_device *spi)
{
snd_soc_unregister_codec(&spi->dev);
return 0;
@@ -527,13 +527,13 @@ static struct spi_driver wm8776_spi_driver = {
.of_match_table = wm8776_of_match,
},
.probe = wm8776_spi_probe,
- .remove = __devexit_p(wm8776_spi_remove),
+ .remove = wm8776_spi_remove,
};
#endif /* CONFIG_SPI_MASTER */
#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
-static __devinit int wm8776_i2c_probe(struct i2c_client *i2c,
- const struct i2c_device_id *id)
+static int wm8776_i2c_probe(struct i2c_client *i2c,
+ const struct i2c_device_id *id)
{
struct wm8776_priv *wm8776;
int ret;
@@ -555,7 +555,7 @@ static __devinit int wm8776_i2c_probe(struct i2c_client *i2c,
return ret;
}
-static __devexit int wm8776_i2c_remove(struct i2c_client *client)
+static int wm8776_i2c_remove(struct i2c_client *client)
{
snd_soc_unregister_codec(&client->dev);
return 0;
@@ -575,7 +575,7 @@ static struct i2c_driver wm8776_i2c_driver = {
.of_match_table = wm8776_of_match,
},
.probe = wm8776_i2c_probe,
- .remove = __devexit_p(wm8776_i2c_remove),
+ .remove = wm8776_i2c_remove,
.id_table = wm8776_i2c_id,
};
#endif
diff --git a/sound/soc/codecs/wm8782.c b/sound/soc/codecs/wm8782.c
index 3fdea98f732e..f1fdbf63abb4 100644
--- a/sound/soc/codecs/wm8782.c
+++ b/sound/soc/codecs/wm8782.c
@@ -42,13 +42,13 @@ static struct snd_soc_dai_driver wm8782_dai = {
static struct snd_soc_codec_driver soc_codec_dev_wm8782;
-static __devinit int wm8782_probe(struct platform_device *pdev)
+static int wm8782_probe(struct platform_device *pdev)
{
return snd_soc_register_codec(&pdev->dev,
&soc_codec_dev_wm8782, &wm8782_dai, 1);
}
-static int __devexit wm8782_remove(struct platform_device *pdev)
+static int wm8782_remove(struct platform_device *pdev)
{
snd_soc_unregister_codec(&pdev->dev);
return 0;
@@ -60,7 +60,7 @@ static struct platform_driver wm8782_codec_driver = {
.owner = THIS_MODULE,
},
.probe = wm8782_probe,
- .remove = __devexit_p(wm8782_remove),
+ .remove = wm8782_remove,
};
module_platform_driver(wm8782_codec_driver);
diff --git a/sound/soc/codecs/wm8804.c b/sound/soc/codecs/wm8804.c
index c088020172ab..d321a875b029 100644
--- a/sound/soc/codecs/wm8804.c
+++ b/sound/soc/codecs/wm8804.c
@@ -702,7 +702,7 @@ static struct regmap_config wm8804_regmap_config = {
};
#if defined(CONFIG_SPI_MASTER)
-static int __devinit wm8804_spi_probe(struct spi_device *spi)
+static int wm8804_spi_probe(struct spi_device *spi)
{
struct wm8804_priv *wm8804;
int ret;
@@ -711,7 +711,7 @@ static int __devinit wm8804_spi_probe(struct spi_device *spi)
if (!wm8804)
return -ENOMEM;
- wm8804->regmap = regmap_init_spi(spi, &wm8804_regmap_config);
+ wm8804->regmap = devm_regmap_init_spi(spi, &wm8804_regmap_config);
if (IS_ERR(wm8804->regmap)) {
ret = PTR_ERR(wm8804->regmap);
return ret;
@@ -725,11 +725,9 @@ static int __devinit wm8804_spi_probe(struct spi_device *spi)
return ret;
}
-static int __devexit wm8804_spi_remove(struct spi_device *spi)
+static int wm8804_spi_remove(struct spi_device *spi)
{
- struct wm8804_priv *wm8804 = spi_get_drvdata(spi);
snd_soc_unregister_codec(&spi->dev);
- regmap_exit(wm8804->regmap);
return 0;
}
@@ -740,13 +738,13 @@ static struct spi_driver wm8804_spi_driver = {
.of_match_table = wm8804_of_match,
},
.probe = wm8804_spi_probe,
- .remove = __devexit_p(wm8804_spi_remove)
+ .remove = wm8804_spi_remove
};
#endif
#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
-static __devinit int wm8804_i2c_probe(struct i2c_client *i2c,
- const struct i2c_device_id *id)
+static int wm8804_i2c_probe(struct i2c_client *i2c,
+ const struct i2c_device_id *id)
{
struct wm8804_priv *wm8804;
int ret;
@@ -755,7 +753,7 @@ static __devinit int wm8804_i2c_probe(struct i2c_client *i2c,
if (!wm8804)
return -ENOMEM;
- wm8804->regmap = regmap_init_i2c(i2c, &wm8804_regmap_config);
+ wm8804->regmap = devm_regmap_init_i2c(i2c, &wm8804_regmap_config);
if (IS_ERR(wm8804->regmap)) {
ret = PTR_ERR(wm8804->regmap);
return ret;
@@ -765,23 +763,12 @@ static __devinit int wm8804_i2c_probe(struct i2c_client *i2c,
ret = snd_soc_register_codec(&i2c->dev,
&soc_codec_dev_wm8804, &wm8804_dai, 1);
- if (ret != 0)
- goto err;
-
- return 0;
-
-err:
- regmap_exit(wm8804->regmap);
return ret;
}
-static __devexit int wm8804_i2c_remove(struct i2c_client *i2c)
+static int wm8804_i2c_remove(struct i2c_client *i2c)
{
- struct wm8804_priv *wm8804 = i2c_get_clientdata(i2c);
-
snd_soc_unregister_codec(&i2c->dev);
- regmap_exit(wm8804->regmap);
-
return 0;
}
@@ -798,7 +785,7 @@ static struct i2c_driver wm8804_i2c_driver = {
.of_match_table = wm8804_of_match,
},
.probe = wm8804_i2c_probe,
- .remove = __devexit_p(wm8804_i2c_remove),
+ .remove = wm8804_i2c_remove,
.id_table = wm8804_i2c_id
};
#endif
diff --git a/sound/soc/codecs/wm8900.c b/sound/soc/codecs/wm8900.c
index e781f865e5d7..7c8257c5a17b 100644
--- a/sound/soc/codecs/wm8900.c
+++ b/sound/soc/codecs/wm8900.c
@@ -1247,7 +1247,7 @@ static const struct regmap_config wm8900_regmap = {
};
#if defined(CONFIG_SPI_MASTER)
-static int __devinit wm8900_spi_probe(struct spi_device *spi)
+static int wm8900_spi_probe(struct spi_device *spi)
{
struct wm8900_priv *wm8900;
int ret;
@@ -1269,7 +1269,7 @@ static int __devinit wm8900_spi_probe(struct spi_device *spi)
return ret;
}
-static int __devexit wm8900_spi_remove(struct spi_device *spi)
+static int wm8900_spi_remove(struct spi_device *spi)
{
snd_soc_unregister_codec(&spi->dev);
return 0;
@@ -1281,13 +1281,13 @@ static struct spi_driver wm8900_spi_driver = {
.owner = THIS_MODULE,
},
.probe = wm8900_spi_probe,
- .remove = __devexit_p(wm8900_spi_remove),
+ .remove = wm8900_spi_remove,
};
#endif /* CONFIG_SPI_MASTER */
#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
-static __devinit int wm8900_i2c_probe(struct i2c_client *i2c,
- const struct i2c_device_id *id)
+static int wm8900_i2c_probe(struct i2c_client *i2c,
+ const struct i2c_device_id *id)
{
struct wm8900_priv *wm8900;
int ret;
@@ -1309,7 +1309,7 @@ static __devinit int wm8900_i2c_probe(struct i2c_client *i2c,
return ret;
}
-static __devexit int wm8900_i2c_remove(struct i2c_client *client)
+static int wm8900_i2c_remove(struct i2c_client *client)
{
snd_soc_unregister_codec(&client->dev);
return 0;
@@ -1327,7 +1327,7 @@ static struct i2c_driver wm8900_i2c_driver = {
.owner = THIS_MODULE,
},
.probe = wm8900_i2c_probe,
- .remove = __devexit_p(wm8900_i2c_remove),
+ .remove = wm8900_i2c_remove,
.id_table = wm8900_i2c_id,
};
#endif
diff --git a/sound/soc/codecs/wm8903.c b/sound/soc/codecs/wm8903.c
index 839414f9e2ed..134e41c870b9 100644
--- a/sound/soc/codecs/wm8903.c
+++ b/sound/soc/codecs/wm8903.c
@@ -2020,8 +2020,8 @@ static int wm8903_set_pdata_from_of(struct i2c_client *i2c,
return 0;
}
-static __devinit int wm8903_i2c_probe(struct i2c_client *i2c,
- const struct i2c_device_id *id)
+static int wm8903_i2c_probe(struct i2c_client *i2c,
+ const struct i2c_device_id *id)
{
struct wm8903_platform_data *pdata = dev_get_platdata(&i2c->dev);
struct wm8903_priv *wm8903;
@@ -2206,7 +2206,7 @@ err:
return ret;
}
-static __devexit int wm8903_i2c_remove(struct i2c_client *client)
+static int wm8903_i2c_remove(struct i2c_client *client)
{
struct wm8903_priv *wm8903 = i2c_get_clientdata(client);
@@ -2237,7 +2237,7 @@ static struct i2c_driver wm8903_i2c_driver = {
.of_match_table = wm8903_of_match,
},
.probe = wm8903_i2c_probe,
- .remove = __devexit_p(wm8903_i2c_remove),
+ .remove = wm8903_i2c_remove,
.id_table = wm8903_i2c_id,
};
diff --git a/sound/soc/codecs/wm8904.c b/sound/soc/codecs/wm8904.c
index 7c8df52a8d9d..3ff195c541db 100644
--- a/sound/soc/codecs/wm8904.c
+++ b/sound/soc/codecs/wm8904.c
@@ -2111,8 +2111,8 @@ static const struct regmap_config wm8904_regmap = {
.num_reg_defaults = ARRAY_SIZE(wm8904_reg_defaults),
};
-static __devinit int wm8904_i2c_probe(struct i2c_client *i2c,
- const struct i2c_device_id *id)
+static int wm8904_i2c_probe(struct i2c_client *i2c,
+ const struct i2c_device_id *id)
{
struct wm8904_priv *wm8904;
unsigned int val;
@@ -2247,7 +2247,7 @@ err_enable:
return ret;
}
-static __devexit int wm8904_i2c_remove(struct i2c_client *client)
+static int wm8904_i2c_remove(struct i2c_client *client)
{
snd_soc_unregister_codec(&client->dev);
return 0;
@@ -2267,7 +2267,7 @@ static struct i2c_driver wm8904_i2c_driver = {
.owner = THIS_MODULE,
},
.probe = wm8904_i2c_probe,
- .remove = __devexit_p(wm8904_i2c_remove),
+ .remove = wm8904_i2c_remove,
.id_table = wm8904_i2c_id,
};
diff --git a/sound/soc/codecs/wm8940.c b/sound/soc/codecs/wm8940.c
index b20aa4e7c3f9..b1591c61c254 100644
--- a/sound/soc/codecs/wm8940.c
+++ b/sound/soc/codecs/wm8940.c
@@ -742,8 +742,8 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8940 = {
.volatile_register = wm8940_volatile_register,
};
-static __devinit int wm8940_i2c_probe(struct i2c_client *i2c,
- const struct i2c_device_id *id)
+static int wm8940_i2c_probe(struct i2c_client *i2c,
+ const struct i2c_device_id *id)
{
struct wm8940_priv *wm8940;
int ret;
@@ -762,7 +762,7 @@ static __devinit int wm8940_i2c_probe(struct i2c_client *i2c,
return ret;
}
-static __devexit int wm8940_i2c_remove(struct i2c_client *client)
+static int wm8940_i2c_remove(struct i2c_client *client)
{
snd_soc_unregister_codec(&client->dev);
@@ -781,7 +781,7 @@ static struct i2c_driver wm8940_i2c_driver = {
.owner = THIS_MODULE,
},
.probe = wm8940_i2c_probe,
- .remove = __devexit_p(wm8940_i2c_remove),
+ .remove = wm8940_i2c_remove,
.id_table = wm8940_i2c_id,
};
diff --git a/sound/soc/codecs/wm8955.c b/sound/soc/codecs/wm8955.c
index 2f1c075755b1..82c8ba975720 100644
--- a/sound/soc/codecs/wm8955.c
+++ b/sound/soc/codecs/wm8955.c
@@ -1012,8 +1012,8 @@ static const struct regmap_config wm8955_regmap = {
.num_reg_defaults = ARRAY_SIZE(wm8955_reg_defaults),
};
-static __devinit int wm8955_i2c_probe(struct i2c_client *i2c,
- const struct i2c_device_id *id)
+static int wm8955_i2c_probe(struct i2c_client *i2c,
+ const struct i2c_device_id *id)
{
struct wm8955_priv *wm8955;
int ret;
@@ -1023,7 +1023,7 @@ static __devinit int wm8955_i2c_probe(struct i2c_client *i2c,
if (wm8955 == NULL)
return -ENOMEM;
- wm8955->regmap = regmap_init_i2c(i2c, &wm8955_regmap);
+ wm8955->regmap = devm_regmap_init_i2c(i2c, &wm8955_regmap);
if (IS_ERR(wm8955->regmap)) {
ret = PTR_ERR(wm8955->regmap);
dev_err(&i2c->dev, "Failed to allocate register map: %d\n",
@@ -1035,22 +1035,13 @@ static __devinit int wm8955_i2c_probe(struct i2c_client *i2c,
ret = snd_soc_register_codec(&i2c->dev,
&soc_codec_dev_wm8955, &wm8955_dai, 1);
- if (ret != 0)
- goto err;
return ret;
-
-err:
- regmap_exit(wm8955->regmap);
- return ret;
}
-static __devexit int wm8955_i2c_remove(struct i2c_client *client)
+static int wm8955_i2c_remove(struct i2c_client *client)
{
- struct wm8955_priv *wm8955 = i2c_get_clientdata(client);
-
snd_soc_unregister_codec(&client->dev);
- regmap_exit(wm8955->regmap);
return 0;
}
@@ -1067,7 +1058,7 @@ static struct i2c_driver wm8955_i2c_driver = {
.owner = THIS_MODULE,
},
.probe = wm8955_i2c_probe,
- .remove = __devexit_p(wm8955_i2c_remove),
+ .remove = wm8955_i2c_remove,
.id_table = wm8955_i2c_id,
};
diff --git a/sound/soc/codecs/wm8958-dsp2.c b/sound/soc/codecs/wm8958-dsp2.c
index 00121ba36597..b0710d817a65 100644
--- a/sound/soc/codecs/wm8958-dsp2.c
+++ b/sound/soc/codecs/wm8958-dsp2.c
@@ -195,7 +195,7 @@ ok:
static void wm8958_dsp_start_mbc(struct snd_soc_codec *codec, int path)
{
struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
- struct wm8994_pdata *pdata = wm8994->pdata;
+ struct wm8994 *control = wm8994->wm8994;
int i;
/* If the DSP is already running then noop */
@@ -210,9 +210,9 @@ static void wm8958_dsp_start_mbc(struct snd_soc_codec *codec, int path)
WM8958_DSP2_ENA, WM8958_DSP2_ENA);
/* If we've got user supplied MBC settings use them */
- if (pdata && pdata->num_mbc_cfgs) {
+ if (control->pdata.num_mbc_cfgs) {
struct wm8958_mbc_cfg *cfg
- = &pdata->mbc_cfgs[wm8994->mbc_cfg];
+ = &control->pdata.mbc_cfgs[wm8994->mbc_cfg];
for (i = 0; i < ARRAY_SIZE(cfg->coeff_regs); i++)
snd_soc_write(codec, i + WM8958_MBC_BAND_1_K_1,
@@ -239,7 +239,7 @@ static void wm8958_dsp_start_mbc(struct snd_soc_codec *codec, int path)
static void wm8958_dsp_start_vss(struct snd_soc_codec *codec, int path)
{
struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
- struct wm8994_pdata *pdata = wm8994->pdata;
+ struct wm8994 *control = wm8994->wm8994;
int i, ena;
if (wm8994->mbc_vss)
@@ -249,26 +249,26 @@ static void wm8958_dsp_start_vss(struct snd_soc_codec *codec, int path)
WM8958_DSP2_ENA, WM8958_DSP2_ENA);
/* If we've got user supplied settings use them */
- if (pdata && pdata->num_mbc_cfgs) {
+ if (control->pdata.num_mbc_cfgs) {
struct wm8958_mbc_cfg *cfg
- = &pdata->mbc_cfgs[wm8994->mbc_cfg];
+ = &control->pdata.mbc_cfgs[wm8994->mbc_cfg];
for (i = 0; i < ARRAY_SIZE(cfg->combined_regs); i++)
snd_soc_write(codec, i + 0x2800,
cfg->combined_regs[i]);
}
- if (pdata && pdata->num_vss_cfgs) {
+ if (control->pdata.num_vss_cfgs) {
struct wm8958_vss_cfg *cfg
- = &pdata->vss_cfgs[wm8994->vss_cfg];
+ = &control->pdata.vss_cfgs[wm8994->vss_cfg];
for (i = 0; i < ARRAY_SIZE(cfg->regs); i++)
snd_soc_write(codec, i + 0x2600, cfg->regs[i]);
}
- if (pdata && pdata->num_vss_hpf_cfgs) {
+ if (control->pdata.num_vss_hpf_cfgs) {
struct wm8958_vss_hpf_cfg *cfg
- = &pdata->vss_hpf_cfgs[wm8994->vss_hpf_cfg];
+ = &control->pdata.vss_hpf_cfgs[wm8994->vss_hpf_cfg];
for (i = 0; i < ARRAY_SIZE(cfg->regs); i++)
snd_soc_write(codec, i + 0x2400, cfg->regs[i]);
@@ -300,7 +300,7 @@ static void wm8958_dsp_start_vss(struct snd_soc_codec *codec, int path)
static void wm8958_dsp_start_enh_eq(struct snd_soc_codec *codec, int path)
{
struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
- struct wm8994_pdata *pdata = wm8994->pdata;
+ struct wm8994 *control = wm8994->wm8994;
int i;
wm8958_dsp2_fw(codec, "ENH_EQ", wm8994->enh_eq, false);
@@ -309,9 +309,9 @@ static void wm8958_dsp_start_enh_eq(struct snd_soc_codec *codec, int path)
WM8958_DSP2_ENA, WM8958_DSP2_ENA);
/* If we've got user supplied settings use them */
- if (pdata && pdata->num_enh_eq_cfgs) {
+ if (control->pdata.num_enh_eq_cfgs) {
struct wm8958_enh_eq_cfg *cfg
- = &pdata->enh_eq_cfgs[wm8994->enh_eq_cfg];
+ = &control->pdata.enh_eq_cfgs[wm8994->enh_eq_cfg];
for (i = 0; i < ARRAY_SIZE(cfg->regs); i++)
snd_soc_write(codec, i + 0x2200,
@@ -458,7 +458,7 @@ static int wm8958_put_mbc_enum(struct snd_kcontrol *kcontrol,
{
struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
- struct wm8994_pdata *pdata = wm8994->pdata;
+ struct wm8994 *control = wm8994->wm8994;
int value = ucontrol->value.integer.value[0];
int reg;
@@ -467,7 +467,7 @@ static int wm8958_put_mbc_enum(struct snd_kcontrol *kcontrol,
if (reg < 0 || reg & WM8958_DSP2CLK_ENA)
return -EBUSY;
- if (value >= pdata->num_mbc_cfgs)
+ if (value >= control->pdata.num_mbc_cfgs)
return -EINVAL;
wm8994->mbc_cfg = value;
@@ -548,7 +548,7 @@ static int wm8958_put_vss_enum(struct snd_kcontrol *kcontrol,
{
struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
- struct wm8994_pdata *pdata = wm8994->pdata;
+ struct wm8994 *control = wm8994->wm8994;
int value = ucontrol->value.integer.value[0];
int reg;
@@ -557,7 +557,7 @@ static int wm8958_put_vss_enum(struct snd_kcontrol *kcontrol,
if (reg < 0 || reg & WM8958_DSP2CLK_ENA)
return -EBUSY;
- if (value >= pdata->num_vss_cfgs)
+ if (value >= control->pdata.num_vss_cfgs)
return -EINVAL;
wm8994->vss_cfg = value;
@@ -581,7 +581,7 @@ static int wm8958_put_vss_hpf_enum(struct snd_kcontrol *kcontrol,
{
struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
- struct wm8994_pdata *pdata = wm8994->pdata;
+ struct wm8994 *control = wm8994->wm8994;
int value = ucontrol->value.integer.value[0];
int reg;
@@ -590,7 +590,7 @@ static int wm8958_put_vss_hpf_enum(struct snd_kcontrol *kcontrol,
if (reg < 0 || reg & WM8958_DSP2CLK_ENA)
return -EBUSY;
- if (value >= pdata->num_vss_hpf_cfgs)
+ if (value >= control->pdata.num_vss_hpf_cfgs)
return -EINVAL;
wm8994->vss_hpf_cfg = value;
@@ -748,7 +748,7 @@ static int wm8958_put_enh_eq_enum(struct snd_kcontrol *kcontrol,
{
struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
- struct wm8994_pdata *pdata = wm8994->pdata;
+ struct wm8994 *control = wm8994->wm8994;
int value = ucontrol->value.integer.value[0];
int reg;
@@ -757,7 +757,7 @@ static int wm8958_put_enh_eq_enum(struct snd_kcontrol *kcontrol,
if (reg < 0 || reg & WM8958_DSP2CLK_ENA)
return -EBUSY;
- if (value >= pdata->num_enh_eq_cfgs)
+ if (value >= control->pdata.num_enh_eq_cfgs)
return -EINVAL;
wm8994->enh_eq_cfg = value;
@@ -883,13 +883,6 @@ static void wm8958_mbc_vss_loaded(const struct firmware *fw, void *context)
wm8994->mbc_vss = fw;
mutex_unlock(&codec->mutex);
}
-
- /* We can't have more than one request outstanding at once so
- * we daisy chain.
- */
- request_firmware_nowait(THIS_MODULE, FW_ACTION_HOTPLUG,
- "wm8958_enh_eq.wfw", codec->dev, GFP_KERNEL,
- codec, wm8958_enh_eq_loaded);
}
static void wm8958_mbc_loaded(const struct firmware *fw, void *context)
@@ -897,25 +890,18 @@ static void wm8958_mbc_loaded(const struct firmware *fw, void *context)
struct snd_soc_codec *codec = context;
struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
- if (wm8958_dsp2_fw(codec, "MBC", fw, true) != 0)
- return;
-
- mutex_lock(&codec->mutex);
- wm8994->mbc = fw;
- mutex_unlock(&codec->mutex);
-
- /* We can't have more than one request outstanding at once so
- * we daisy chain.
- */
- request_firmware_nowait(THIS_MODULE, FW_ACTION_HOTPLUG,
- "wm8958_mbc_vss.wfw", codec->dev, GFP_KERNEL,
- codec, wm8958_mbc_vss_loaded);
+ if (fw && (wm8958_dsp2_fw(codec, "MBC", fw, true) == 0)) {
+ mutex_lock(&codec->mutex);
+ wm8994->mbc = fw;
+ mutex_unlock(&codec->mutex);
+ }
}
void wm8958_dsp2_init(struct snd_soc_codec *codec)
{
struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
- struct wm8994_pdata *pdata = wm8994->pdata;
+ struct wm8994 *control = wm8994->wm8994;
+ struct wm8994_pdata *pdata = &control->pdata;
int ret, i;
wm8994->dsp_active = -1;
@@ -932,9 +918,12 @@ void wm8958_dsp2_init(struct snd_soc_codec *codec)
request_firmware_nowait(THIS_MODULE, FW_ACTION_HOTPLUG,
"wm8958_mbc.wfw", codec->dev, GFP_KERNEL,
codec, wm8958_mbc_loaded);
-
- if (!pdata)
- return;
+ request_firmware_nowait(THIS_MODULE, FW_ACTION_HOTPLUG,
+ "wm8958_mbc_vss.wfw", codec->dev, GFP_KERNEL,
+ codec, wm8958_mbc_vss_loaded);
+ request_firmware_nowait(THIS_MODULE, FW_ACTION_HOTPLUG,
+ "wm8958_enh_eq.wfw", codec->dev, GFP_KERNEL,
+ codec, wm8958_enh_eq_loaded);
if (pdata->num_mbc_cfgs) {
struct snd_kcontrol_new control[] = {
diff --git a/sound/soc/codecs/wm8960.c b/sound/soc/codecs/wm8960.c
index f0f6f6601785..9bb927325993 100644
--- a/sound/soc/codecs/wm8960.c
+++ b/sound/soc/codecs/wm8960.c
@@ -1028,8 +1028,8 @@ static const struct regmap_config wm8960_regmap = {
.volatile_reg = wm8960_volatile,
};
-static __devinit int wm8960_i2c_probe(struct i2c_client *i2c,
- const struct i2c_device_id *id)
+static int wm8960_i2c_probe(struct i2c_client *i2c,
+ const struct i2c_device_id *id)
{
struct wm8960_data *pdata = dev_get_platdata(&i2c->dev);
struct wm8960_priv *wm8960;
@@ -1040,7 +1040,7 @@ static __devinit int wm8960_i2c_probe(struct i2c_client *i2c,
if (wm8960 == NULL)
return -ENOMEM;
- wm8960->regmap = regmap_init_i2c(i2c, &wm8960_regmap);
+ wm8960->regmap = devm_regmap_init_i2c(i2c, &wm8960_regmap);
if (IS_ERR(wm8960->regmap))
return PTR_ERR(wm8960->regmap);
@@ -1062,7 +1062,7 @@ static __devinit int wm8960_i2c_probe(struct i2c_client *i2c,
return ret;
}
-static __devexit int wm8960_i2c_remove(struct i2c_client *client)
+static int wm8960_i2c_remove(struct i2c_client *client)
{
snd_soc_unregister_codec(&client->dev);
return 0;
@@ -1080,7 +1080,7 @@ static struct i2c_driver wm8960_i2c_driver = {
.owner = THIS_MODULE,
},
.probe = wm8960_i2c_probe,
- .remove = __devexit_p(wm8960_i2c_remove),
+ .remove = wm8960_i2c_remove,
.id_table = wm8960_i2c_id,
};
diff --git a/sound/soc/codecs/wm8961.c b/sound/soc/codecs/wm8961.c
index f387670d0d75..900328e28a15 100644
--- a/sound/soc/codecs/wm8961.c
+++ b/sound/soc/codecs/wm8961.c
@@ -937,8 +937,8 @@ static const struct regmap_config wm8961_regmap = {
.readable_reg = wm8961_readable,
};
-static __devinit int wm8961_i2c_probe(struct i2c_client *i2c,
- const struct i2c_device_id *id)
+static int wm8961_i2c_probe(struct i2c_client *i2c,
+ const struct i2c_device_id *id)
{
struct wm8961_priv *wm8961;
unsigned int val;
@@ -993,7 +993,7 @@ static __devinit int wm8961_i2c_probe(struct i2c_client *i2c,
return ret;
}
-static __devexit int wm8961_i2c_remove(struct i2c_client *client)
+static int wm8961_i2c_remove(struct i2c_client *client)
{
snd_soc_unregister_codec(&client->dev);
@@ -1012,7 +1012,7 @@ static struct i2c_driver wm8961_i2c_driver = {
.owner = THIS_MODULE,
},
.probe = wm8961_i2c_probe,
- .remove = __devexit_p(wm8961_i2c_remove),
+ .remove = wm8961_i2c_remove,
.id_table = wm8961_i2c_id,
};
diff --git a/sound/soc/codecs/wm8962.c b/sound/soc/codecs/wm8962.c
index ce6720073798..bd4b0db4cdaa 100644
--- a/sound/soc/codecs/wm8962.c
+++ b/sound/soc/codecs/wm8962.c
@@ -3588,8 +3588,8 @@ static const struct regmap_config wm8962_regmap = {
.cache_type = REGCACHE_RBTREE,
};
-static __devinit int wm8962_i2c_probe(struct i2c_client *i2c,
- const struct i2c_device_id *id)
+static int wm8962_i2c_probe(struct i2c_client *i2c,
+ const struct i2c_device_id *id)
{
struct wm8962_pdata *pdata = dev_get_platdata(&i2c->dev);
struct wm8962_priv *wm8962;
@@ -3610,7 +3610,7 @@ static __devinit int wm8962_i2c_probe(struct i2c_client *i2c,
for (i = 0; i < ARRAY_SIZE(wm8962->supplies); i++)
wm8962->supplies[i].supply = wm8962_supply_names[i];
- ret = regulator_bulk_get(&i2c->dev, ARRAY_SIZE(wm8962->supplies),
+ ret = devm_regulator_bulk_get(&i2c->dev, ARRAY_SIZE(wm8962->supplies),
wm8962->supplies);
if (ret != 0) {
dev_err(&i2c->dev, "Failed to request supplies: %d\n", ret);
@@ -3621,10 +3621,10 @@ static __devinit int wm8962_i2c_probe(struct i2c_client *i2c,
wm8962->supplies);
if (ret != 0) {
dev_err(&i2c->dev, "Failed to enable supplies: %d\n", ret);
- goto err_get;
+ return ret;
}
- wm8962->regmap = regmap_init_i2c(i2c, &wm8962_regmap);
+ wm8962->regmap = devm_regmap_init_i2c(i2c, &wm8962_regmap);
if (IS_ERR(wm8962->regmap)) {
ret = PTR_ERR(wm8962->regmap);
dev_err(&i2c->dev, "Failed to allocate regmap: %d\n", ret);
@@ -3641,20 +3641,20 @@ static __devinit int wm8962_i2c_probe(struct i2c_client *i2c,
ret = regmap_read(wm8962->regmap, WM8962_SOFTWARE_RESET, &reg);
if (ret < 0) {
dev_err(&i2c->dev, "Failed to read ID register\n");
- goto err_regmap;
+ goto err_enable;
}
if (reg != 0x6243) {
dev_err(&i2c->dev,
"Device is not a WM8962, ID %x != 0x6243\n", reg);
ret = -EINVAL;
- goto err_regmap;
+ goto err_enable;
}
ret = regmap_read(wm8962->regmap, WM8962_RIGHT_INPUT_VOLUME, &reg);
if (ret < 0) {
dev_err(&i2c->dev, "Failed to read device revision: %d\n",
ret);
- goto err_regmap;
+ goto err_enable;
}
dev_info(&i2c->dev, "customer id %x revision %c\n",
@@ -3667,7 +3667,7 @@ static __devinit int wm8962_i2c_probe(struct i2c_client *i2c,
ret = wm8962_reset(wm8962);
if (ret < 0) {
dev_err(&i2c->dev, "Failed to issue reset\n");
- goto err_regmap;
+ goto err_enable;
}
if (pdata && pdata->in4_dc_measure) {
@@ -3686,30 +3686,22 @@ static __devinit int wm8962_i2c_probe(struct i2c_client *i2c,
ret = snd_soc_register_codec(&i2c->dev,
&soc_codec_dev_wm8962, &wm8962_dai, 1);
if (ret < 0)
- goto err_regmap;
+ goto err_enable;
/* The drivers should power up as needed */
regulator_bulk_disable(ARRAY_SIZE(wm8962->supplies), wm8962->supplies);
return 0;
-err_regmap:
- regmap_exit(wm8962->regmap);
err_enable:
regulator_bulk_disable(ARRAY_SIZE(wm8962->supplies), wm8962->supplies);
-err_get:
- regulator_bulk_free(ARRAY_SIZE(wm8962->supplies), wm8962->supplies);
err:
return ret;
}
-static __devexit int wm8962_i2c_remove(struct i2c_client *client)
+static int wm8962_i2c_remove(struct i2c_client *client)
{
- struct wm8962_priv *wm8962 = dev_get_drvdata(&client->dev);
-
snd_soc_unregister_codec(&client->dev);
- regmap_exit(wm8962->regmap);
- regulator_bulk_free(ARRAY_SIZE(wm8962->supplies), wm8962->supplies);
return 0;
}
@@ -3773,7 +3765,7 @@ static struct i2c_driver wm8962_i2c_driver = {
.pm = &wm8962_pm,
},
.probe = wm8962_i2c_probe,
- .remove = __devexit_p(wm8962_i2c_remove),
+ .remove = wm8962_i2c_remove,
.id_table = wm8962_i2c_id,
};
diff --git a/sound/soc/codecs/wm8971.c b/sound/soc/codecs/wm8971.c
index 5ce647758443..67aba78a7ca5 100644
--- a/sound/soc/codecs/wm8971.c
+++ b/sound/soc/codecs/wm8971.c
@@ -19,6 +19,7 @@
#include <linux/delay.h>
#include <linux/pm.h>
#include <linux/i2c.h>
+#include <linux/regmap.h>
#include <linux/slab.h>
#include <sound/core.h>
#include <sound/pcm.h>
@@ -34,7 +35,6 @@ static struct workqueue_struct *wm8971_workq = NULL;
/* codec private data */
struct wm8971_priv {
- enum snd_soc_control_type control_type;
unsigned int sysclk;
};
@@ -43,18 +43,50 @@ struct wm8971_priv {
* We can't read the WM8971 register space when we
* are using 2 wire for device control, so we cache them instead.
*/
-static const u16 wm8971_reg[] = {
- 0x0097, 0x0097, 0x0079, 0x0079, /* 0 */
- 0x0000, 0x0008, 0x0000, 0x000a, /* 4 */
- 0x0000, 0x0000, 0x00ff, 0x00ff, /* 8 */
- 0x000f, 0x000f, 0x0000, 0x0000, /* 12 */
- 0x0000, 0x007b, 0x0000, 0x0032, /* 16 */
- 0x0000, 0x00c3, 0x00c3, 0x00c0, /* 20 */
- 0x0000, 0x0000, 0x0000, 0x0000, /* 24 */
- 0x0000, 0x0000, 0x0000, 0x0000, /* 28 */
- 0x0000, 0x0000, 0x0050, 0x0050, /* 32 */
- 0x0050, 0x0050, 0x0050, 0x0050, /* 36 */
- 0x0079, 0x0079, 0x0079, /* 40 */
+static const struct reg_default wm8971_reg_defaults[] = {
+ { 0, 0x0097 },
+ { 1, 0x0097 },
+ { 2, 0x0079 },
+ { 3, 0x0079 },
+ { 4, 0x0000 },
+ { 5, 0x0008 },
+ { 6, 0x0000 },
+ { 7, 0x000a },
+ { 8, 0x0000 },
+ { 9, 0x0000 },
+ { 10, 0x00ff },
+ { 11, 0x00ff },
+ { 12, 0x000f },
+ { 13, 0x000f },
+ { 14, 0x0000 },
+ { 15, 0x0000 },
+ { 16, 0x0000 },
+ { 17, 0x007b },
+ { 18, 0x0000 },
+ { 19, 0x0032 },
+ { 20, 0x0000 },
+ { 21, 0x00c3 },
+ { 22, 0x00c3 },
+ { 23, 0x00c0 },
+ { 24, 0x0000 },
+ { 25, 0x0000 },
+ { 26, 0x0000 },
+ { 27, 0x0000 },
+ { 28, 0x0000 },
+ { 29, 0x0000 },
+ { 30, 0x0000 },
+ { 31, 0x0000 },
+ { 32, 0x0000 },
+ { 33, 0x0000 },
+ { 34, 0x0050 },
+ { 35, 0x0050 },
+ { 36, 0x0050 },
+ { 37, 0x0050 },
+ { 38, 0x0050 },
+ { 39, 0x0050 },
+ { 40, 0x0079 },
+ { 41, 0x0079 },
+ { 42, 0x0079 },
};
#define wm8971_reset(c) snd_soc_write(c, WM8971_RESET, 0)
@@ -613,11 +645,10 @@ static int wm8971_resume(struct snd_soc_codec *codec)
static int wm8971_probe(struct snd_soc_codec *codec)
{
- struct wm8971_priv *wm8971 = snd_soc_codec_get_drvdata(codec);
int ret = 0;
u16 reg;
- ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8971->control_type);
+ ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP);
if (ret < 0) {
printk(KERN_ERR "wm8971: failed to set cache I/O: %d\n", ret);
return ret;
@@ -667,9 +698,6 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8971 = {
.suspend = wm8971_suspend,
.resume = wm8971_resume,
.set_bias_level = wm8971_set_bias_level,
- .reg_cache_size = ARRAY_SIZE(wm8971_reg),
- .reg_word_size = sizeof(u16),
- .reg_cache_default = wm8971_reg,
.controls = wm8971_snd_controls,
.num_controls = ARRAY_SIZE(wm8971_snd_controls),
@@ -679,10 +707,21 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8971 = {
.num_dapm_routes = ARRAY_SIZE(wm8971_dapm_routes),
};
-static __devinit int wm8971_i2c_probe(struct i2c_client *i2c,
- const struct i2c_device_id *id)
+static const struct regmap_config wm8971_regmap = {
+ .reg_bits = 7,
+ .val_bits = 9,
+ .max_register = WM8971_MOUTV,
+
+ .reg_defaults = wm8971_reg_defaults,
+ .num_reg_defaults = ARRAY_SIZE(wm8971_reg_defaults),
+ .cache_type = REGCACHE_RBTREE,
+};
+
+static int wm8971_i2c_probe(struct i2c_client *i2c,
+ const struct i2c_device_id *id)
{
struct wm8971_priv *wm8971;
+ struct regmap *regmap;
int ret;
wm8971 = devm_kzalloc(&i2c->dev, sizeof(struct wm8971_priv),
@@ -690,7 +729,10 @@ static __devinit int wm8971_i2c_probe(struct i2c_client *i2c,
if (wm8971 == NULL)
return -ENOMEM;
- wm8971->control_type = SND_SOC_I2C;
+ regmap = devm_regmap_init_i2c(i2c, &wm8971_regmap);
+ if (IS_ERR(regmap))
+ return PTR_ERR(regmap);
+
i2c_set_clientdata(i2c, wm8971);
ret = snd_soc_register_codec(&i2c->dev,
@@ -699,7 +741,7 @@ static __devinit int wm8971_i2c_probe(struct i2c_client *i2c,
return ret;
}
-static __devexit int wm8971_i2c_remove(struct i2c_client *client)
+static int wm8971_i2c_remove(struct i2c_client *client)
{
snd_soc_unregister_codec(&client->dev);
return 0;
@@ -717,7 +759,7 @@ static struct i2c_driver wm8971_i2c_driver = {
.owner = THIS_MODULE,
},
.probe = wm8971_i2c_probe,
- .remove = __devexit_p(wm8971_i2c_remove),
+ .remove = wm8971_i2c_remove,
.id_table = wm8971_i2c_id,
};
diff --git a/sound/soc/codecs/wm8974.c b/sound/soc/codecs/wm8974.c
index 9a39511af52a..ea58b73e86b2 100644
--- a/sound/soc/codecs/wm8974.c
+++ b/sound/soc/codecs/wm8974.c
@@ -625,8 +625,8 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8974 = {
.num_dapm_routes = ARRAY_SIZE(wm8974_dapm_routes),
};
-static __devinit int wm8974_i2c_probe(struct i2c_client *i2c,
- const struct i2c_device_id *id)
+static int wm8974_i2c_probe(struct i2c_client *i2c,
+ const struct i2c_device_id *id)
{
int ret;
@@ -636,7 +636,7 @@ static __devinit int wm8974_i2c_probe(struct i2c_client *i2c,
return ret;
}
-static __devexit int wm8974_i2c_remove(struct i2c_client *client)
+static int wm8974_i2c_remove(struct i2c_client *client)
{
snd_soc_unregister_codec(&client->dev);
@@ -655,7 +655,7 @@ static struct i2c_driver wm8974_i2c_driver = {
.owner = THIS_MODULE,
},
.probe = wm8974_i2c_probe,
- .remove = __devexit_p(wm8974_i2c_remove),
+ .remove = wm8974_i2c_remove,
.id_table = wm8974_i2c_id,
};
diff --git a/sound/soc/codecs/wm8978.c b/sound/soc/codecs/wm8978.c
index 4c0a8e496131..f347af3a67c2 100644
--- a/sound/soc/codecs/wm8978.c
+++ b/sound/soc/codecs/wm8978.c
@@ -527,9 +527,6 @@ static int wm8978_configure_pll(struct snd_soc_codec *codec)
return idx;
wm8978->mclk_idx = idx;
-
- /* GPIO1 into default mode as input - before configuring PLL */
- snd_soc_update_bits(codec, WM8978_GPIO_CONTROL, 7, 0);
} else {
return -EINVAL;
}
@@ -1038,8 +1035,8 @@ static const struct regmap_config wm8978_regmap_config = {
.num_reg_defaults = ARRAY_SIZE(wm8978_reg_defaults),
};
-static __devinit int wm8978_i2c_probe(struct i2c_client *i2c,
- const struct i2c_device_id *id)
+static int wm8978_i2c_probe(struct i2c_client *i2c,
+ const struct i2c_device_id *id)
{
struct wm8978_priv *wm8978;
int ret;
@@ -1049,7 +1046,7 @@ static __devinit int wm8978_i2c_probe(struct i2c_client *i2c,
if (wm8978 == NULL)
return -ENOMEM;
- wm8978->regmap = regmap_init_i2c(i2c, &wm8978_regmap_config);
+ wm8978->regmap = devm_regmap_init_i2c(i2c, &wm8978_regmap_config);
if (IS_ERR(wm8978->regmap)) {
ret = PTR_ERR(wm8978->regmap);
dev_err(&i2c->dev, "Failed to allocate regmap: %d\n", ret);
@@ -1062,29 +1059,22 @@ static __devinit int wm8978_i2c_probe(struct i2c_client *i2c,
ret = regmap_write(wm8978->regmap, WM8978_RESET, 0);
if (ret != 0) {
dev_err(&i2c->dev, "Failed to issue reset: %d\n", ret);
- goto err;
+ return ret;
}
ret = snd_soc_register_codec(&i2c->dev,
&soc_codec_dev_wm8978, &wm8978_dai, 1);
if (ret != 0) {
dev_err(&i2c->dev, "Failed to register CODEC: %d\n", ret);
- goto err;
+ return ret;
}
return 0;
-
-err:
- regmap_exit(wm8978->regmap);
- return ret;
}
-static __devexit int wm8978_i2c_remove(struct i2c_client *client)
+static int wm8978_i2c_remove(struct i2c_client *client)
{
- struct wm8978_priv *wm8978 = i2c_get_clientdata(client);
-
snd_soc_unregister_codec(&client->dev);
- regmap_exit(wm8978->regmap);
return 0;
}
@@ -1101,7 +1091,7 @@ static struct i2c_driver wm8978_i2c_driver = {
.owner = THIS_MODULE,
},
.probe = wm8978_i2c_probe,
- .remove = __devexit_p(wm8978_i2c_remove),
+ .remove = wm8978_i2c_remove,
.id_table = wm8978_i2c_id,
};
diff --git a/sound/soc/codecs/wm8983.c b/sound/soc/codecs/wm8983.c
index d8879f262d27..9fe1e041da49 100644
--- a/sound/soc/codecs/wm8983.c
+++ b/sound/soc/codecs/wm8983.c
@@ -1087,7 +1087,7 @@ static const struct regmap_config wm8983_regmap = {
};
#if defined(CONFIG_SPI_MASTER)
-static int __devinit wm8983_spi_probe(struct spi_device *spi)
+static int wm8983_spi_probe(struct spi_device *spi)
{
struct wm8983_priv *wm8983;
int ret;
@@ -1110,7 +1110,7 @@ static int __devinit wm8983_spi_probe(struct spi_device *spi)
return ret;
}
-static int __devexit wm8983_spi_remove(struct spi_device *spi)
+static int wm8983_spi_remove(struct spi_device *spi)
{
snd_soc_unregister_codec(&spi->dev);
return 0;
@@ -1122,13 +1122,13 @@ static struct spi_driver wm8983_spi_driver = {
.owner = THIS_MODULE,
},
.probe = wm8983_spi_probe,
- .remove = __devexit_p(wm8983_spi_remove)
+ .remove = wm8983_spi_remove
};
#endif
#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
-static __devinit int wm8983_i2c_probe(struct i2c_client *i2c,
- const struct i2c_device_id *id)
+static int wm8983_i2c_probe(struct i2c_client *i2c,
+ const struct i2c_device_id *id)
{
struct wm8983_priv *wm8983;
int ret;
@@ -1152,7 +1152,7 @@ static __devinit int wm8983_i2c_probe(struct i2c_client *i2c,
return ret;
}
-static __devexit int wm8983_i2c_remove(struct i2c_client *client)
+static int wm8983_i2c_remove(struct i2c_client *client)
{
snd_soc_unregister_codec(&client->dev);
return 0;
@@ -1170,7 +1170,7 @@ static struct i2c_driver wm8983_i2c_driver = {
.owner = THIS_MODULE,
},
.probe = wm8983_i2c_probe,
- .remove = __devexit_p(wm8983_i2c_remove),
+ .remove = wm8983_i2c_remove,
.id_table = wm8983_i2c_id
};
#endif
diff --git a/sound/soc/codecs/wm8985.c b/sound/soc/codecs/wm8985.c
index 14f666398d0c..ab3782657ac8 100644
--- a/sound/soc/codecs/wm8985.c
+++ b/sound/soc/codecs/wm8985.c
@@ -1111,7 +1111,7 @@ static const struct regmap_config wm8985_regmap = {
};
#if defined(CONFIG_SPI_MASTER)
-static int __devinit wm8985_spi_probe(struct spi_device *spi)
+static int wm8985_spi_probe(struct spi_device *spi)
{
struct wm8985_priv *wm8985;
int ret;
@@ -1122,33 +1122,22 @@ static int __devinit wm8985_spi_probe(struct spi_device *spi)
spi_set_drvdata(spi, wm8985);
- wm8985->regmap = regmap_init_spi(spi, &wm8985_regmap);
+ wm8985->regmap = devm_regmap_init_spi(spi, &wm8985_regmap);
if (IS_ERR(wm8985->regmap)) {
ret = PTR_ERR(wm8985->regmap);
dev_err(&spi->dev, "Failed to allocate register map: %d\n",
ret);
- goto err;
+ return ret;
}
ret = snd_soc_register_codec(&spi->dev,
&soc_codec_dev_wm8985, &wm8985_dai, 1);
- if (ret != 0)
- goto err;
-
- return 0;
-
-err:
- regmap_exit(wm8985->regmap);
return ret;
}
-static int __devexit wm8985_spi_remove(struct spi_device *spi)
+static int wm8985_spi_remove(struct spi_device *spi)
{
- struct wm8985_priv *wm8985 = spi_get_drvdata(spi);
-
snd_soc_unregister_codec(&spi->dev);
- regmap_exit(wm8985->regmap);
-
return 0;
}
@@ -1158,13 +1147,13 @@ static struct spi_driver wm8985_spi_driver = {
.owner = THIS_MODULE,
},
.probe = wm8985_spi_probe,
- .remove = __devexit_p(wm8985_spi_remove)
+ .remove = wm8985_spi_remove
};
#endif
#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
-static __devinit int wm8985_i2c_probe(struct i2c_client *i2c,
- const struct i2c_device_id *id)
+static int wm8985_i2c_probe(struct i2c_client *i2c,
+ const struct i2c_device_id *id)
{
struct wm8985_priv *wm8985;
int ret;
@@ -1175,33 +1164,22 @@ static __devinit int wm8985_i2c_probe(struct i2c_client *i2c,
i2c_set_clientdata(i2c, wm8985);
- wm8985->regmap = regmap_init_i2c(i2c, &wm8985_regmap);
+ wm8985->regmap = devm_regmap_init_i2c(i2c, &wm8985_regmap);
if (IS_ERR(wm8985->regmap)) {
ret = PTR_ERR(wm8985->regmap);
dev_err(&i2c->dev, "Failed to allocate register map: %d\n",
ret);
- goto err;
+ return ret;
}
ret = snd_soc_register_codec(&i2c->dev,
&soc_codec_dev_wm8985, &wm8985_dai, 1);
- if (ret != 0)
- goto err;
-
- return 0;
-
-err:
- regmap_exit(wm8985->regmap);
return ret;
}
-static __devexit int wm8985_i2c_remove(struct i2c_client *i2c)
+static int wm8985_i2c_remove(struct i2c_client *i2c)
{
- struct wm8985_priv *wm8985 = i2c_get_clientdata(i2c);
-
snd_soc_unregister_codec(&i2c->dev);
- regmap_exit(wm8985->regmap);
-
return 0;
}
@@ -1217,7 +1195,7 @@ static struct i2c_driver wm8985_i2c_driver = {
.owner = THIS_MODULE,
},
.probe = wm8985_i2c_probe,
- .remove = __devexit_p(wm8985_i2c_remove),
+ .remove = wm8985_i2c_remove,
.id_table = wm8985_i2c_id
};
#endif
diff --git a/sound/soc/codecs/wm8988.c b/sound/soc/codecs/wm8988.c
index 1d4c5cf47b06..39b9acceb595 100644
--- a/sound/soc/codecs/wm8988.c
+++ b/sound/soc/codecs/wm8988.c
@@ -872,7 +872,7 @@ static struct regmap_config wm8988_regmap = {
};
#if defined(CONFIG_SPI_MASTER)
-static int __devinit wm8988_spi_probe(struct spi_device *spi)
+static int wm8988_spi_probe(struct spi_device *spi)
{
struct wm8988_priv *wm8988;
int ret;
@@ -882,7 +882,7 @@ static int __devinit wm8988_spi_probe(struct spi_device *spi)
if (wm8988 == NULL)
return -ENOMEM;
- wm8988->regmap = regmap_init_spi(spi, &wm8988_regmap);
+ wm8988->regmap = devm_regmap_init_spi(spi, &wm8988_regmap);
if (IS_ERR(wm8988->regmap)) {
ret = PTR_ERR(wm8988->regmap);
dev_err(&spi->dev, "Failed to init regmap: %d\n", ret);
@@ -893,17 +893,12 @@ static int __devinit wm8988_spi_probe(struct spi_device *spi)
ret = snd_soc_register_codec(&spi->dev,
&soc_codec_dev_wm8988, &wm8988_dai, 1);
- if (ret != 0)
- regmap_exit(wm8988->regmap);
-
return ret;
}
-static int __devexit wm8988_spi_remove(struct spi_device *spi)
+static int wm8988_spi_remove(struct spi_device *spi)
{
- struct wm8988_priv *wm8988 = spi_get_drvdata(spi);
snd_soc_unregister_codec(&spi->dev);
- regmap_exit(wm8988->regmap);
return 0;
}
@@ -913,13 +908,13 @@ static struct spi_driver wm8988_spi_driver = {
.owner = THIS_MODULE,
},
.probe = wm8988_spi_probe,
- .remove = __devexit_p(wm8988_spi_remove),
+ .remove = wm8988_spi_remove,
};
#endif /* CONFIG_SPI_MASTER */
#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
-static __devinit int wm8988_i2c_probe(struct i2c_client *i2c,
- const struct i2c_device_id *id)
+static int wm8988_i2c_probe(struct i2c_client *i2c,
+ const struct i2c_device_id *id)
{
struct wm8988_priv *wm8988;
int ret;
@@ -931,7 +926,7 @@ static __devinit int wm8988_i2c_probe(struct i2c_client *i2c,
i2c_set_clientdata(i2c, wm8988);
- wm8988->regmap = regmap_init_i2c(i2c, &wm8988_regmap);
+ wm8988->regmap = devm_regmap_init_i2c(i2c, &wm8988_regmap);
if (IS_ERR(wm8988->regmap)) {
ret = PTR_ERR(wm8988->regmap);
dev_err(&i2c->dev, "Failed to init regmap: %d\n", ret);
@@ -940,17 +935,12 @@ static __devinit int wm8988_i2c_probe(struct i2c_client *i2c,
ret = snd_soc_register_codec(&i2c->dev,
&soc_codec_dev_wm8988, &wm8988_dai, 1);
- if (ret != 0)
- regmap_exit(wm8988->regmap);
-
return ret;
}
-static __devexit int wm8988_i2c_remove(struct i2c_client *client)
+static int wm8988_i2c_remove(struct i2c_client *client)
{
- struct wm8988_priv *wm8988 = i2c_get_clientdata(client);
snd_soc_unregister_codec(&client->dev);
- regmap_exit(wm8988->regmap);
return 0;
}
@@ -966,7 +956,7 @@ static struct i2c_driver wm8988_i2c_driver = {
.owner = THIS_MODULE,
},
.probe = wm8988_i2c_probe,
- .remove = __devexit_p(wm8988_i2c_remove),
+ .remove = wm8988_i2c_remove,
.id_table = wm8988_i2c_id,
};
#endif
diff --git a/sound/soc/codecs/wm8990.c b/sound/soc/codecs/wm8990.c
index c28c83e5395d..837978e16e9d 100644
--- a/sound/soc/codecs/wm8990.c
+++ b/sound/soc/codecs/wm8990.c
@@ -1382,8 +1382,8 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8990 = {
};
#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
-static __devinit int wm8990_i2c_probe(struct i2c_client *i2c,
- const struct i2c_device_id *id)
+static int wm8990_i2c_probe(struct i2c_client *i2c,
+ const struct i2c_device_id *id)
{
struct wm8990_priv *wm8990;
int ret;
@@ -1401,7 +1401,7 @@ static __devinit int wm8990_i2c_probe(struct i2c_client *i2c,
return ret;
}
-static __devexit int wm8990_i2c_remove(struct i2c_client *client)
+static int wm8990_i2c_remove(struct i2c_client *client)
{
snd_soc_unregister_codec(&client->dev);
@@ -1420,7 +1420,7 @@ static struct i2c_driver wm8990_i2c_driver = {
.owner = THIS_MODULE,
},
.probe = wm8990_i2c_probe,
- .remove = __devexit_p(wm8990_i2c_remove),
+ .remove = wm8990_i2c_remove,
.id_table = wm8990_i2c_id,
};
#endif
diff --git a/sound/soc/codecs/wm8991.c b/sound/soc/codecs/wm8991.c
index fe439f027e10..3a39df7a3829 100644
--- a/sound/soc/codecs/wm8991.c
+++ b/sound/soc/codecs/wm8991.c
@@ -1357,8 +1357,8 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8991 = {
.reg_cache_default = wm8991_reg_defs
};
-static __devinit int wm8991_i2c_probe(struct i2c_client *i2c,
- const struct i2c_device_id *id)
+static int wm8991_i2c_probe(struct i2c_client *i2c,
+ const struct i2c_device_id *id)
{
struct wm8991_priv *wm8991;
int ret;
@@ -1376,7 +1376,7 @@ static __devinit int wm8991_i2c_probe(struct i2c_client *i2c,
return ret;
}
-static __devexit int wm8991_i2c_remove(struct i2c_client *client)
+static int wm8991_i2c_remove(struct i2c_client *client)
{
snd_soc_unregister_codec(&client->dev);
@@ -1395,7 +1395,7 @@ static struct i2c_driver wm8991_i2c_driver = {
.owner = THIS_MODULE,
},
.probe = wm8991_i2c_probe,
- .remove = __devexit_p(wm8991_i2c_remove),
+ .remove = wm8991_i2c_remove,
.id_table = wm8991_i2c_id,
};
diff --git a/sound/soc/codecs/wm8993.c b/sound/soc/codecs/wm8993.c
index 94737a30716b..433d59a0f3ef 100644
--- a/sound/soc/codecs/wm8993.c
+++ b/sound/soc/codecs/wm8993.c
@@ -1645,8 +1645,8 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8993 = {
.set_bias_level = wm8993_set_bias_level,
};
-static __devinit int wm8993_i2c_probe(struct i2c_client *i2c,
- const struct i2c_device_id *id)
+static int wm8993_i2c_probe(struct i2c_client *i2c,
+ const struct i2c_device_id *id)
{
struct wm8993_priv *wm8993;
unsigned int reg;
@@ -1660,7 +1660,7 @@ static __devinit int wm8993_i2c_probe(struct i2c_client *i2c,
wm8993->dev = &i2c->dev;
init_completion(&wm8993->fll_lock);
- wm8993->regmap = regmap_init_i2c(i2c, &wm8993_regmap);
+ wm8993->regmap = devm_regmap_init_i2c(i2c, &wm8993_regmap);
if (IS_ERR(wm8993->regmap)) {
ret = PTR_ERR(wm8993->regmap);
dev_err(&i2c->dev, "Failed to allocate regmap: %d\n", ret);
@@ -1672,18 +1672,18 @@ static __devinit int wm8993_i2c_probe(struct i2c_client *i2c,
for (i = 0; i < ARRAY_SIZE(wm8993->supplies); i++)
wm8993->supplies[i].supply = wm8993_supply_names[i];
- ret = regulator_bulk_get(&i2c->dev, ARRAY_SIZE(wm8993->supplies),
+ ret = devm_regulator_bulk_get(&i2c->dev, ARRAY_SIZE(wm8993->supplies),
wm8993->supplies);
if (ret != 0) {
dev_err(&i2c->dev, "Failed to request supplies: %d\n", ret);
- goto err;
+ return ret;
}
ret = regulator_bulk_enable(ARRAY_SIZE(wm8993->supplies),
wm8993->supplies);
if (ret != 0) {
dev_err(&i2c->dev, "Failed to enable supplies: %d\n", ret);
- goto err_get;
+ return ret;
}
ret = regmap_read(wm8993->regmap, WM8993_SOFTWARE_RESET, &reg);
@@ -1742,23 +1742,17 @@ err_irq:
free_irq(i2c->irq, wm8993);
err_enable:
regulator_bulk_disable(ARRAY_SIZE(wm8993->supplies), wm8993->supplies);
-err_get:
- regulator_bulk_free(ARRAY_SIZE(wm8993->supplies), wm8993->supplies);
-err:
- regmap_exit(wm8993->regmap);
return ret;
}
-static __devexit int wm8993_i2c_remove(struct i2c_client *i2c)
+static int wm8993_i2c_remove(struct i2c_client *i2c)
{
struct wm8993_priv *wm8993 = i2c_get_clientdata(i2c);
snd_soc_unregister_codec(&i2c->dev);
if (i2c->irq)
free_irq(i2c->irq, wm8993);
- regmap_exit(wm8993->regmap);
regulator_bulk_disable(ARRAY_SIZE(wm8993->supplies), wm8993->supplies);
- regulator_bulk_free(ARRAY_SIZE(wm8993->supplies), wm8993->supplies);
return 0;
}
@@ -1775,7 +1769,7 @@ static struct i2c_driver wm8993_i2c_driver = {
.owner = THIS_MODULE,
},
.probe = wm8993_i2c_probe,
- .remove = __devexit_p(wm8993_i2c_remove),
+ .remove = wm8993_i2c_remove,
.id_table = wm8993_i2c_id,
};
diff --git a/sound/soc/codecs/wm8994.c b/sound/soc/codecs/wm8994.c
index b2b2b37131bd..3b269fa226bd 100644
--- a/sound/soc/codecs/wm8994.c
+++ b/sound/soc/codecs/wm8994.c
@@ -91,8 +91,6 @@ static int wm8994_retune_mobile_base[] = {
WM8994_AIF2_EQ_GAINS_1,
};
-static void wm8958_default_micdet(u16 status, void *data);
-
static const struct wm8958_micd_rate micdet_rates[] = {
{ 32768, true, 1, 4 },
{ 32768, false, 1, 1 },
@@ -110,15 +108,12 @@ static const struct wm8958_micd_rate jackdet_rates[] = {
static void wm8958_micd_set_rate(struct snd_soc_codec *codec)
{
struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
+ struct wm8994 *control = wm8994->wm8994;
int best, i, sysclk, val;
bool idle;
const struct wm8958_micd_rate *rates;
int num_rates;
- if (!(wm8994->pdata && wm8994->pdata->micd_rates) &&
- wm8994->jack_cb != wm8958_default_micdet)
- return;
-
idle = !wm8994->jack_mic;
sysclk = snd_soc_read(codec, WM8994_CLOCKING_1);
@@ -127,9 +122,9 @@ static void wm8958_micd_set_rate(struct snd_soc_codec *codec)
else
sysclk = wm8994->aifclk[0];
- if (wm8994->pdata && wm8994->pdata->micd_rates) {
- rates = wm8994->pdata->micd_rates;
- num_rates = wm8994->pdata->num_micd_rates;
+ if (control->pdata.micd_rates) {
+ rates = control->pdata.micd_rates;
+ num_rates = control->pdata.num_micd_rates;
} else if (wm8994->jackdet) {
rates = jackdet_rates;
num_rates = ARRAY_SIZE(jackdet_rates);
@@ -326,7 +321,8 @@ static int wm8994_put_drc_sw(struct snd_kcontrol *kcontrol,
static void wm8994_set_drc(struct snd_soc_codec *codec, int drc)
{
struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
- struct wm8994_pdata *pdata = wm8994->pdata;
+ struct wm8994 *control = wm8994->wm8994;
+ struct wm8994_pdata *pdata = &control->pdata;
int base = wm8994_drc_base[drc];
int cfg = wm8994->drc_cfg[drc];
int save, i;
@@ -362,7 +358,8 @@ static int wm8994_put_drc_enum(struct snd_kcontrol *kcontrol,
{
struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
- struct wm8994_pdata *pdata = wm8994->pdata;
+ struct wm8994 *control = wm8994->wm8994;
+ struct wm8994_pdata *pdata = &control->pdata;
int drc = wm8994_get_drc(kcontrol->id.name);
int value = ucontrol->value.integer.value[0];
@@ -394,7 +391,8 @@ static int wm8994_get_drc_enum(struct snd_kcontrol *kcontrol,
static void wm8994_set_retune_mobile(struct snd_soc_codec *codec, int block)
{
struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
- struct wm8994_pdata *pdata = wm8994->pdata;
+ struct wm8994 *control = wm8994->wm8994;
+ struct wm8994_pdata *pdata = &control->pdata;
int base = wm8994_retune_mobile_base[block];
int iface, best, best_val, save, i, cfg;
@@ -465,7 +463,8 @@ static int wm8994_put_retune_mobile_enum(struct snd_kcontrol *kcontrol,
{
struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
- struct wm8994_pdata *pdata = wm8994->pdata;
+ struct wm8994 *control = wm8994->wm8994;
+ struct wm8994_pdata *pdata = &control->pdata;
int block = wm8994_get_retune_mobile_block(kcontrol->id.name);
int value = ucontrol->value.integer.value[0];
@@ -736,7 +735,7 @@ static void wm1811_jackdet_set_mode(struct snd_soc_codec *codec, u16 mode)
{
struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
- if (!wm8994->jackdet || !wm8994->jack_cb)
+ if (!wm8994->jackdet || !wm8994->micdet[0].jack)
return;
if (wm8994->active_refcount)
@@ -862,7 +861,7 @@ static void vmid_reference(struct snd_soc_codec *codec)
WM8994_BIAS_SRC |
WM8994_STARTUP_BIAS_ENA |
WM8994_VMID_BUF_ENA |
- (0x3 << WM8994_VMID_RAMP_SHIFT));
+ (0x2 << WM8994_VMID_RAMP_SHIFT));
/* Main bias enable, VMID=2x40k */
snd_soc_update_bits(codec, WM8994_POWER_MANAGEMENT_1,
@@ -870,7 +869,7 @@ static void vmid_reference(struct snd_soc_codec *codec)
WM8994_VMID_SEL_MASK,
WM8994_BIAS_ENA | 0x2);
- msleep(50);
+ msleep(300);
snd_soc_update_bits(codec, WM8994_ANTIPOP_2,
WM8994_VMID_RAMP_MASK |
@@ -939,16 +938,10 @@ static void vmid_dereference(struct snd_soc_codec *codec)
WM8994_BIAS_SRC |
WM8994_VMID_DISCH);
- switch (wm8994->vmid_mode) {
- case WM8994_VMID_FORCE:
- msleep(350);
- break;
- default:
- break;
- }
+ snd_soc_update_bits(codec, WM8994_POWER_MANAGEMENT_1,
+ WM8994_VMID_SEL_MASK, 0);
- snd_soc_update_bits(codec, WM8994_ADDITIONAL_CONTROL,
- WM8994_VROI, WM8994_VROI);
+ msleep(400);
/* Active discharge */
snd_soc_update_bits(codec, WM8994_ANTIPOP_1,
@@ -957,17 +950,12 @@ static void vmid_dereference(struct snd_soc_codec *codec)
WM8994_LINEOUT1_DISCH |
WM8994_LINEOUT2_DISCH);
- msleep(150);
-
snd_soc_update_bits(codec, WM8994_POWER_MANAGEMENT_3,
WM8994_LINEOUT1N_ENA |
WM8994_LINEOUT1P_ENA |
WM8994_LINEOUT2N_ENA |
WM8994_LINEOUT2P_ENA, 0);
- snd_soc_update_bits(codec, WM8994_ADDITIONAL_CONTROL,
- WM8994_VROI, 0);
-
/* Switch off startup biases */
snd_soc_update_bits(codec, WM8994_ANTIPOP_2,
WM8994_BIAS_SRC |
@@ -976,10 +964,7 @@ static void vmid_dereference(struct snd_soc_codec *codec)
WM8994_VMID_RAMP_MASK, 0);
snd_soc_update_bits(codec, WM8994_POWER_MANAGEMENT_1,
- WM8994_BIAS_ENA | WM8994_VMID_SEL_MASK, 0);
-
- snd_soc_update_bits(codec, WM8994_ANTIPOP_2,
- WM8994_VMID_RAMP_MASK, 0);
+ WM8994_VMID_SEL_MASK, 0);
}
pm_runtime_put(codec->dev);
@@ -2277,6 +2262,18 @@ out:
configure_clock(codec);
+ /*
+ * If SYSCLK will be less than 50kHz adjust AIFnCLK dividers
+ * for detection.
+ */
+ if (max(wm8994->aifclk[0], wm8994->aifclk[1]) < 50000) {
+ dev_dbg(codec->dev, "Configuring AIFs for 128fs\n");
+ snd_soc_update_bits(codec, WM8994_AIF1_RATE,
+ WM8994_AIF1CLK_RATE_MASK, 0x1);
+ snd_soc_update_bits(codec, WM8994_AIF2_RATE,
+ WM8994_AIF2CLK_RATE_MASK, 0x1);
+ }
+
return 0;
}
@@ -2365,6 +2362,18 @@ static int wm8994_set_dai_sysclk(struct snd_soc_dai *dai,
configure_clock(codec);
+ /*
+ * If SYSCLK will be less than 50kHz adjust AIFnCLK dividers
+ * for detection.
+ */
+ if (max(wm8994->aifclk[0], wm8994->aifclk[1]) < 50000) {
+ dev_dbg(codec->dev, "Configuring AIFs for 128fs\n");
+ snd_soc_update_bits(codec, WM8994_AIF1_RATE,
+ WM8994_AIF1CLK_RATE_MASK, 0x1);
+ snd_soc_update_bits(codec, WM8994_AIF2_RATE,
+ WM8994_AIF2CLK_RATE_MASK, 0x1);
+ }
+
return 0;
}
@@ -3082,7 +3091,8 @@ static int wm8994_codec_resume(struct snd_soc_codec *codec)
static void wm8994_handle_retune_mobile_pdata(struct wm8994_priv *wm8994)
{
struct snd_soc_codec *codec = wm8994->hubs.codec;
- struct wm8994_pdata *pdata = wm8994->pdata;
+ struct wm8994 *control = wm8994->wm8994;
+ struct wm8994_pdata *pdata = &control->pdata;
struct snd_kcontrol_new controls[] = {
SOC_ENUM_EXT("AIF1.1 EQ Mode",
wm8994->retune_mobile_enum,
@@ -3149,7 +3159,8 @@ static void wm8994_handle_retune_mobile_pdata(struct wm8994_priv *wm8994)
static void wm8994_handle_pdata(struct wm8994_priv *wm8994)
{
struct snd_soc_codec *codec = wm8994->hubs.codec;
- struct wm8994_pdata *pdata = wm8994->pdata;
+ struct wm8994 *control = wm8994->wm8994;
+ struct wm8994_pdata *pdata = &control->pdata;
int ret, i;
if (!pdata)
@@ -3389,38 +3400,80 @@ static irqreturn_t wm8994_mic_irq(int irq, void *data)
return IRQ_HANDLED;
}
-/* Default microphone detection handler for WM8958 - the user can
- * override this if they wish.
- */
-static void wm8958_default_micdet(u16 status, void *data)
+static void wm1811_micd_stop(struct snd_soc_codec *codec)
+{
+ struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
+
+ if (!wm8994->jackdet)
+ return;
+
+ mutex_lock(&wm8994->accdet_lock);
+
+ snd_soc_update_bits(codec, WM8958_MIC_DETECT_1, WM8958_MICD_ENA, 0);
+
+ wm1811_jackdet_set_mode(codec, WM1811_JACKDET_MODE_JACK);
+
+ mutex_unlock(&wm8994->accdet_lock);
+
+ if (wm8994->wm8994->pdata.jd_ext_cap)
+ snd_soc_dapm_disable_pin(&codec->dapm,
+ "MICBIAS2");
+}
+
+static void wm8958_button_det(struct snd_soc_codec *codec, u16 status)
{
- struct snd_soc_codec *codec = data;
struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
int report;
- dev_dbg(codec->dev, "MICDET %x\n", status);
+ report = 0;
+ if (status & 0x4)
+ report |= SND_JACK_BTN_0;
+
+ if (status & 0x8)
+ report |= SND_JACK_BTN_1;
+
+ if (status & 0x10)
+ report |= SND_JACK_BTN_2;
+
+ if (status & 0x20)
+ report |= SND_JACK_BTN_3;
+
+ if (status & 0x40)
+ report |= SND_JACK_BTN_4;
+
+ if (status & 0x80)
+ report |= SND_JACK_BTN_5;
+
+ snd_soc_jack_report(wm8994->micdet[0].jack, report,
+ wm8994->btn_mask);
+}
+
+static void wm8958_mic_id(void *data, u16 status)
+{
+ struct snd_soc_codec *codec = data;
+ struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
/* Either nothing present or just starting detection */
if (!(status & WM8958_MICD_STS)) {
- if (!wm8994->jackdet) {
- /* If nothing present then clear our statuses */
- dev_dbg(codec->dev, "Detected open circuit\n");
- wm8994->jack_mic = false;
- wm8994->mic_detecting = true;
+ /* If nothing present then clear our statuses */
+ dev_dbg(codec->dev, "Detected open circuit\n");
+ wm8994->jack_mic = false;
+ wm8994->mic_detecting = true;
- wm8958_micd_set_rate(codec);
+ wm1811_micd_stop(codec);
- snd_soc_jack_report(wm8994->micdet[0].jack, 0,
- wm8994->btn_mask |
- SND_JACK_HEADSET);
- }
+ wm8958_micd_set_rate(codec);
+
+ snd_soc_jack_report(wm8994->micdet[0].jack, 0,
+ wm8994->btn_mask |
+ SND_JACK_HEADSET);
return;
}
/* If the measurement is showing a high impedence we've got a
* microphone.
*/
- if (wm8994->mic_detecting && (status & 0x600)) {
+ if (status & 0x600) {
dev_dbg(codec->dev, "Detected microphone\n");
wm8994->mic_detecting = false;
@@ -3433,64 +3486,67 @@ static void wm8958_default_micdet(u16 status, void *data)
}
- if (wm8994->mic_detecting && status & 0xfc) {
+ if (status & 0xfc) {
dev_dbg(codec->dev, "Detected headphone\n");
wm8994->mic_detecting = false;
wm8958_micd_set_rate(codec);
/* If we have jackdet that will detect removal */
- if (wm8994->jackdet) {
- mutex_lock(&wm8994->accdet_lock);
-
- snd_soc_update_bits(codec, WM8958_MIC_DETECT_1,
- WM8958_MICD_ENA, 0);
-
- wm1811_jackdet_set_mode(codec,
- WM1811_JACKDET_MODE_JACK);
-
- mutex_unlock(&wm8994->accdet_lock);
-
- if (wm8994->pdata->jd_ext_cap)
- snd_soc_dapm_disable_pin(&codec->dapm,
- "MICBIAS2");
- }
+ wm1811_micd_stop(codec);
snd_soc_jack_report(wm8994->micdet[0].jack, SND_JACK_HEADPHONE,
SND_JACK_HEADSET);
}
+}
- /* Report short circuit as a button */
- if (wm8994->jack_mic) {
- report = 0;
- if (status & 0x4)
- report |= SND_JACK_BTN_0;
+/* Deferred mic detection to allow for extra settling time */
+static void wm1811_mic_work(struct work_struct *work)
+{
+ struct wm8994_priv *wm8994 = container_of(work, struct wm8994_priv,
+ mic_work.work);
+ struct wm8994 *control = wm8994->wm8994;
+ struct snd_soc_codec *codec = wm8994->hubs.codec;
- if (status & 0x8)
- report |= SND_JACK_BTN_1;
+ pm_runtime_get_sync(codec->dev);
- if (status & 0x10)
- report |= SND_JACK_BTN_2;
+ /* If required for an external cap force MICBIAS on */
+ if (control->pdata.jd_ext_cap) {
+ snd_soc_dapm_force_enable_pin(&codec->dapm,
+ "MICBIAS2");
+ snd_soc_dapm_sync(&codec->dapm);
+ }
- if (status & 0x20)
- report |= SND_JACK_BTN_3;
+ mutex_lock(&wm8994->accdet_lock);
- if (status & 0x40)
- report |= SND_JACK_BTN_4;
+ dev_dbg(codec->dev, "Starting mic detection\n");
- if (status & 0x80)
- report |= SND_JACK_BTN_5;
+ /* Use a user-supplied callback if we have one */
+ if (wm8994->micd_cb) {
+ wm8994->micd_cb(wm8994->micd_cb_data);
+ } else {
+ /*
+ * Start off measument of microphone impedence to find out
+ * what's actually there.
+ */
+ wm8994->mic_detecting = true;
+ wm1811_jackdet_set_mode(codec, WM1811_JACKDET_MODE_MIC);
- snd_soc_jack_report(wm8994->micdet[0].jack, report,
- wm8994->btn_mask);
+ snd_soc_update_bits(codec, WM8958_MIC_DETECT_1,
+ WM8958_MICD_ENA, WM8958_MICD_ENA);
}
+
+ mutex_unlock(&wm8994->accdet_lock);
+
+ pm_runtime_put(codec->dev);
}
static irqreturn_t wm1811_jackdet_irq(int irq, void *data)
{
struct wm8994_priv *wm8994 = data;
+ struct wm8994 *control = wm8994->wm8994;
struct snd_soc_codec *codec = wm8994->hubs.codec;
- int reg;
+ int reg, delay;
bool present;
pm_runtime_get_sync(codec->dev);
@@ -3521,18 +3577,14 @@ static irqreturn_t wm1811_jackdet_irq(int irq, void *data)
snd_soc_update_bits(codec, WM1811_JACKDET_CTRL,
WM1811_JACKDET_DB, 0);
- /*
- * Start off measument of microphone impedence to find
- * out what's actually there.
- */
- wm8994->mic_detecting = true;
- wm1811_jackdet_set_mode(codec, WM1811_JACKDET_MODE_MIC);
-
- snd_soc_update_bits(codec, WM8958_MIC_DETECT_1,
- WM8958_MICD_ENA, WM8958_MICD_ENA);
+ delay = control->pdata.micdet_delay;
+ schedule_delayed_work(&wm8994->mic_work,
+ msecs_to_jiffies(delay));
} else {
dev_dbg(codec->dev, "Jack not detected\n");
+ cancel_delayed_work_sync(&wm8994->mic_work);
+
snd_soc_update_bits(codec, WM8958_MICBIAS2,
WM8958_MICB2_DISCH, WM8958_MICB2_DISCH);
@@ -3549,14 +3601,9 @@ static irqreturn_t wm1811_jackdet_irq(int irq, void *data)
mutex_unlock(&wm8994->accdet_lock);
- /* If required for an external cap force MICBIAS on */
- if (wm8994->pdata->jd_ext_cap) {
- if (present)
- snd_soc_dapm_force_enable_pin(&codec->dapm,
- "MICBIAS2");
- else
- snd_soc_dapm_disable_pin(&codec->dapm, "MICBIAS2");
- }
+ /* Turn off MICBIAS if it was on for an external cap */
+ if (control->pdata.jd_ext_cap && !present)
+ snd_soc_dapm_disable_pin(&codec->dapm, "MICBIAS2");
if (present)
snd_soc_jack_report(wm8994->micdet[0].jack,
@@ -3599,7 +3646,8 @@ static void wm1811_jackdet_bootstrap(struct work_struct *work)
* detection algorithm.
*/
int wm8958_mic_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack,
- wm8958_micdet_cb cb, void *cb_data)
+ wm1811_micdet_cb det_cb, void *det_cb_data,
+ wm1811_mic_id_cb id_cb, void *id_cb_data)
{
struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
struct wm8994 *control = wm8994->wm8994;
@@ -3614,27 +3662,32 @@ int wm8958_mic_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack,
}
if (jack) {
- if (!cb) {
- dev_dbg(codec->dev, "Using default micdet callback\n");
- cb = wm8958_default_micdet;
- cb_data = codec;
- }
-
snd_soc_dapm_force_enable_pin(&codec->dapm, "CLK_SYS");
snd_soc_dapm_sync(&codec->dapm);
wm8994->micdet[0].jack = jack;
- wm8994->jack_cb = cb;
- wm8994->jack_cb_data = cb_data;
- wm8994->mic_detecting = true;
- wm8994->jack_mic = false;
+ if (det_cb) {
+ wm8994->micd_cb = det_cb;
+ wm8994->micd_cb_data = det_cb_data;
+ } else {
+ wm8994->mic_detecting = true;
+ wm8994->jack_mic = false;
+ }
+
+ if (id_cb) {
+ wm8994->mic_id_cb = id_cb;
+ wm8994->mic_id_cb_data = id_cb_data;
+ } else {
+ wm8994->mic_id_cb = wm8958_mic_id;
+ wm8994->mic_id_cb_data = codec;
+ }
wm8958_micd_set_rate(codec);
/* Detect microphones and short circuits by default */
- if (wm8994->pdata->micd_lvl_sel)
- micd_lvl_sel = wm8994->pdata->micd_lvl_sel;
+ if (control->pdata.micd_lvl_sel)
+ micd_lvl_sel = control->pdata.micd_lvl_sel;
else
micd_lvl_sel = 0x41;
@@ -3728,10 +3781,22 @@ static irqreturn_t wm8958_mic_irq(int irq, void *data)
trace_snd_soc_jack_irq(dev_name(codec->dev));
#endif
- if (wm8994->jack_cb)
- wm8994->jack_cb(reg, wm8994->jack_cb_data);
+ /* Avoid a transient report when the accessory is being removed */
+ if (wm8994->jackdet) {
+ reg = snd_soc_read(codec, WM1811_JACKDET_CTRL);
+ if (reg < 0) {
+ dev_err(codec->dev, "Failed to read jack status: %d\n",
+ reg);
+ } else if (!(reg & WM1811_JACKDET_LVL)) {
+ dev_dbg(codec->dev, "Ignoring removed jack\n");
+ return IRQ_HANDLED;
+ }
+ }
+
+ if (wm8994->mic_detecting)
+ wm8994->mic_id_cb(wm8994->mic_id_cb_data, reg);
else
- dev_warn(codec->dev, "Accessory detection with no callback\n");
+ wm8958_button_det(codec, reg);
out:
pm_runtime_put(codec->dev);
@@ -3779,15 +3844,24 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec)
snd_soc_codec_set_cache_io(codec, 16, 16, SND_SOC_REGMAP);
mutex_init(&wm8994->accdet_lock);
- INIT_DELAYED_WORK(&wm8994->mic_work, wm8994_mic_work);
INIT_DELAYED_WORK(&wm8994->jackdet_bootstrap,
wm1811_jackdet_bootstrap);
+ switch (control->type) {
+ case WM8994:
+ INIT_DELAYED_WORK(&wm8994->mic_work, wm8994_mic_work);
+ break;
+ case WM1811:
+ INIT_DELAYED_WORK(&wm8994->mic_work, wm1811_mic_work);
+ break;
+ default:
+ break;
+ }
+
for (i = 0; i < ARRAY_SIZE(wm8994->fll_locked); i++)
init_completion(&wm8994->fll_locked[i]);
- if (wm8994->pdata && wm8994->pdata->micdet_irq)
- wm8994->micdet_irq = wm8994->pdata->micdet_irq;
+ wm8994->micdet_irq = control->pdata.micdet_irq;
pm_runtime_enable(codec->dev);
pm_runtime_idle(codec->dev);
@@ -3800,8 +3874,8 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec)
switch (control->type) {
case WM8994:
/* Single ended line outputs should have VMID on. */
- if (!wm8994->pdata->lineout1_diff ||
- !wm8994->pdata->lineout2_diff)
+ if (!control->pdata.lineout1_diff ||
+ !control->pdata.lineout2_diff)
codec->dapm.idle_bias_off = 0;
switch (wm8994->revision) {
@@ -3839,20 +3913,8 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec)
wm8994->hubs.no_cache_dac_hp_direct = true;
wm8994->fll_byp = true;
- switch (control->cust_id) {
- case 0:
- case 2:
- wm8994->hubs.dcs_codes_l = -9;
- wm8994->hubs.dcs_codes_r = -7;
- break;
- case 1:
- case 3:
- wm8994->hubs.dcs_codes_l = -8;
- wm8994->hubs.dcs_codes_r = -7;
- break;
- default:
- break;
- }
+ wm8994->hubs.dcs_codes_l = -9;
+ wm8994->hubs.dcs_codes_r = -7;
snd_soc_update_bits(codec, WM8994_ANALOGUE_HP_1,
WM1811_HPOUT1_ATTN, WM1811_HPOUT1_ATTN);
@@ -4225,7 +4287,7 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8994 = {
.set_bias_level = wm8994_set_bias_level,
};
-static int __devinit wm8994_probe(struct platform_device *pdev)
+static int wm8994_probe(struct platform_device *pdev)
{
struct wm8994_priv *wm8994;
@@ -4236,13 +4298,12 @@ static int __devinit wm8994_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, wm8994);
wm8994->wm8994 = dev_get_drvdata(pdev->dev.parent);
- wm8994->pdata = dev_get_platdata(pdev->dev.parent);
return snd_soc_register_codec(&pdev->dev, &soc_codec_dev_wm8994,
wm8994_dai, ARRAY_SIZE(wm8994_dai));
}
-static int __devexit wm8994_remove(struct platform_device *pdev)
+static int wm8994_remove(struct platform_device *pdev)
{
snd_soc_unregister_codec(&pdev->dev);
return 0;
@@ -4266,7 +4327,7 @@ static int wm8994_resume(struct device *dev)
{
struct wm8994_priv *wm8994 = dev_get_drvdata(dev);
- if (wm8994->jackdet && wm8994->jack_cb)
+ if (wm8994->jackdet && wm8994->jackdet_mode)
regmap_update_bits(wm8994->wm8994->regmap, WM8994_ANTIPOP_2,
WM1811_JACKDET_MODE_MASK,
WM1811_JACKDET_MODE_AUDIO);
@@ -4286,7 +4347,7 @@ static struct platform_driver wm8994_codec_driver = {
.pm = &wm8994_pm_ops,
},
.probe = wm8994_probe,
- .remove = __devexit_p(wm8994_remove),
+ .remove = wm8994_remove,
};
module_platform_driver(wm8994_codec_driver);
diff --git a/sound/soc/codecs/wm8994.h b/sound/soc/codecs/wm8994.h
index ccbce5791e95..45f192702024 100644
--- a/sound/soc/codecs/wm8994.h
+++ b/sound/soc/codecs/wm8994.h
@@ -39,12 +39,14 @@ enum wm8994_vmid_mode {
WM8994_VMID_FORCE,
};
-typedef void (*wm8958_micdet_cb)(u16 status, void *data);
+typedef void (*wm1811_micdet_cb)(void *data);
+typedef void (*wm1811_mic_id_cb)(void *data, u16 status);
int wm8994_mic_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack,
int micbias);
int wm8958_mic_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack,
- wm8958_micdet_cb cb, void *cb_data);
+ wm1811_micdet_cb cb, void *det_cb_data,
+ wm1811_mic_id_cb id_cb, void *id_cb_data);
int wm8994_vmid_mode(struct snd_soc_codec *codec, enum wm8994_vmid_mode mode);
@@ -138,12 +140,13 @@ struct wm8994_priv {
int jackdet_mode;
struct delayed_work jackdet_bootstrap;
- wm8958_micdet_cb jack_cb;
- void *jack_cb_data;
int micdet_irq;
+ wm1811_micdet_cb micd_cb;
+ void *micd_cb_data;
+ wm1811_mic_id_cb mic_id_cb;
+ void *mic_id_cb_data;
int revision;
- struct wm8994_pdata *pdata;
unsigned int aif1clk_enable:1;
unsigned int aif2clk_enable:1;
diff --git a/sound/soc/codecs/wm8995.c b/sound/soc/codecs/wm8995.c
index 28c89b094c6e..90a65c427541 100644
--- a/sound/soc/codecs/wm8995.c
+++ b/sound/soc/codecs/wm8995.c
@@ -2256,46 +2256,33 @@ static struct regmap_config wm8995_regmap = {
};
#if defined(CONFIG_SPI_MASTER)
-static int __devinit wm8995_spi_probe(struct spi_device *spi)
+static int wm8995_spi_probe(struct spi_device *spi)
{
struct wm8995_priv *wm8995;
int ret;
- wm8995 = kzalloc(sizeof *wm8995, GFP_KERNEL);
+ wm8995 = devm_kzalloc(&spi->dev, sizeof(*wm8995), GFP_KERNEL);
if (!wm8995)
return -ENOMEM;
spi_set_drvdata(spi, wm8995);
- wm8995->regmap = regmap_init_spi(spi, &wm8995_regmap);
+ wm8995->regmap = devm_regmap_init_spi(spi, &wm8995_regmap);
if (IS_ERR(wm8995->regmap)) {
ret = PTR_ERR(wm8995->regmap);
dev_err(&spi->dev, "Failed to register regmap: %d\n", ret);
- goto err_alloc;
+ return ret;
}
ret = snd_soc_register_codec(&spi->dev,
&soc_codec_dev_wm8995, wm8995_dai,
ARRAY_SIZE(wm8995_dai));
- if (ret < 0)
- goto err_regmap;
-
- return ret;
-
-err_regmap:
- regmap_exit(wm8995->regmap);
-err_alloc:
- kfree(wm8995);
-
return ret;
}
-static int __devexit wm8995_spi_remove(struct spi_device *spi)
+static int wm8995_spi_remove(struct spi_device *spi)
{
- struct wm8995_priv *wm8995 = spi_get_drvdata(spi);
snd_soc_unregister_codec(&spi->dev);
- regmap_exit(wm8995->regmap);
- kfree(wm8995);
return 0;
}
@@ -2305,55 +2292,42 @@ static struct spi_driver wm8995_spi_driver = {
.owner = THIS_MODULE,
},
.probe = wm8995_spi_probe,
- .remove = __devexit_p(wm8995_spi_remove)
+ .remove = wm8995_spi_remove
};
#endif
#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
-static __devinit int wm8995_i2c_probe(struct i2c_client *i2c,
- const struct i2c_device_id *id)
+static int wm8995_i2c_probe(struct i2c_client *i2c,
+ const struct i2c_device_id *id)
{
struct wm8995_priv *wm8995;
int ret;
- wm8995 = kzalloc(sizeof *wm8995, GFP_KERNEL);
+ wm8995 = devm_kzalloc(&i2c->dev, sizeof(*wm8995), GFP_KERNEL);
if (!wm8995)
return -ENOMEM;
i2c_set_clientdata(i2c, wm8995);
- wm8995->regmap = regmap_init_i2c(i2c, &wm8995_regmap);
+ wm8995->regmap = devm_regmap_init_i2c(i2c, &wm8995_regmap);
if (IS_ERR(wm8995->regmap)) {
ret = PTR_ERR(wm8995->regmap);
dev_err(&i2c->dev, "Failed to register regmap: %d\n", ret);
- goto err_alloc;
+ return ret;
}
ret = snd_soc_register_codec(&i2c->dev,
&soc_codec_dev_wm8995, wm8995_dai,
ARRAY_SIZE(wm8995_dai));
- if (ret < 0) {
+ if (ret < 0)
dev_err(&i2c->dev, "Failed to register CODEC: %d\n", ret);
- goto err_regmap;
- }
-
- return ret;
-
-err_regmap:
- regmap_exit(wm8995->regmap);
-err_alloc:
- kfree(wm8995);
return ret;
}
-static __devexit int wm8995_i2c_remove(struct i2c_client *client)
+static int wm8995_i2c_remove(struct i2c_client *client)
{
- struct wm8995_priv *wm8995 = i2c_get_clientdata(client);
-
snd_soc_unregister_codec(&client->dev);
- regmap_exit(wm8995->regmap);
- kfree(wm8995);
return 0;
}
@@ -2370,7 +2344,7 @@ static struct i2c_driver wm8995_i2c_driver = {
.owner = THIS_MODULE,
},
.probe = wm8995_i2c_probe,
- .remove = __devexit_p(wm8995_i2c_remove),
+ .remove = wm8995_i2c_remove,
.id_table = wm8995_i2c_id
};
#endif
diff --git a/sound/soc/codecs/wm8996.c b/sound/soc/codecs/wm8996.c
index 6dcb02c3666f..46fe83d2b224 100644
--- a/sound/soc/codecs/wm8996.c
+++ b/sound/soc/codecs/wm8996.c
@@ -2765,8 +2765,8 @@ static struct snd_soc_dai_driver wm8996_dai[] = {
},
};
-static __devinit int wm8996_i2c_probe(struct i2c_client *i2c,
- const struct i2c_device_id *id)
+static int wm8996_i2c_probe(struct i2c_client *i2c,
+ const struct i2c_device_id *id)
{
struct wm8996_priv *wm8996;
int ret, i;
@@ -3077,7 +3077,7 @@ err:
return ret;
}
-static __devexit int wm8996_i2c_remove(struct i2c_client *client)
+static int wm8996_i2c_remove(struct i2c_client *client)
{
struct wm8996_priv *wm8996 = i2c_get_clientdata(client);
int i;
@@ -3107,7 +3107,7 @@ static struct i2c_driver wm8996_i2c_driver = {
.owner = THIS_MODULE,
},
.probe = wm8996_i2c_probe,
- .remove = __devexit_p(wm8996_i2c_remove),
+ .remove = wm8996_i2c_remove,
.id_table = wm8996_i2c_id,
};
diff --git a/sound/soc/codecs/wm9081.c b/sound/soc/codecs/wm9081.c
index 2de74e1ea225..630b3d776ec2 100644
--- a/sound/soc/codecs/wm9081.c
+++ b/sound/soc/codecs/wm9081.c
@@ -1327,8 +1327,8 @@ static const struct regmap_config wm9081_regmap = {
};
#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
-static __devinit int wm9081_i2c_probe(struct i2c_client *i2c,
- const struct i2c_device_id *id)
+static int wm9081_i2c_probe(struct i2c_client *i2c,
+ const struct i2c_device_id *id)
{
struct wm9081_priv *wm9081;
unsigned int reg;
@@ -1341,28 +1341,27 @@ static __devinit int wm9081_i2c_probe(struct i2c_client *i2c,
i2c_set_clientdata(i2c, wm9081);
- wm9081->regmap = regmap_init_i2c(i2c, &wm9081_regmap);
+ wm9081->regmap = devm_regmap_init_i2c(i2c, &wm9081_regmap);
if (IS_ERR(wm9081->regmap)) {
ret = PTR_ERR(wm9081->regmap);
dev_err(&i2c->dev, "regmap_init() failed: %d\n", ret);
- goto err;
+ return ret;
}
ret = regmap_read(wm9081->regmap, WM9081_SOFTWARE_RESET, &reg);
if (ret != 0) {
dev_err(&i2c->dev, "Failed to read chip ID: %d\n", ret);
- goto err_regmap;
+ return ret;
}
if (reg != 0x9081) {
dev_err(&i2c->dev, "Device is not a WM9081: ID=0x%x\n", reg);
- ret = -EINVAL;
- goto err_regmap;
+ return -EINVAL;
}
ret = wm9081_reset(wm9081->regmap);
if (ret < 0) {
dev_err(&i2c->dev, "Failed to issue reset\n");
- goto err_regmap;
+ return ret;
}
if (dev_get_platdata(&i2c->dev))
@@ -1382,23 +1381,14 @@ static __devinit int wm9081_i2c_probe(struct i2c_client *i2c,
ret = snd_soc_register_codec(&i2c->dev,
&soc_codec_dev_wm9081, &wm9081_dai, 1);
if (ret < 0)
- goto err_regmap;
+ return ret;
return 0;
-
-err_regmap:
- regmap_exit(wm9081->regmap);
-err:
-
- return ret;
}
-static __devexit int wm9081_i2c_remove(struct i2c_client *client)
+static int wm9081_i2c_remove(struct i2c_client *client)
{
- struct wm9081_priv *wm9081 = i2c_get_clientdata(client);
-
snd_soc_unregister_codec(&client->dev);
- regmap_exit(wm9081->regmap);
return 0;
}
@@ -1414,7 +1404,7 @@ static struct i2c_driver wm9081_i2c_driver = {
.owner = THIS_MODULE,
},
.probe = wm9081_i2c_probe,
- .remove = __devexit_p(wm9081_i2c_remove),
+ .remove = wm9081_i2c_remove,
.id_table = wm9081_i2c_id,
};
#endif
diff --git a/sound/soc/codecs/wm9090.c b/sound/soc/codecs/wm9090.c
index c7ddc56175d1..a07fe1618eec 100644
--- a/sound/soc/codecs/wm9090.c
+++ b/sound/soc/codecs/wm9090.c
@@ -628,7 +628,7 @@ static int wm9090_i2c_probe(struct i2c_client *i2c,
return -ENOMEM;
}
- wm9090->regmap = regmap_init_i2c(i2c, &wm9090_regmap);
+ wm9090->regmap = devm_regmap_init_i2c(i2c, &wm9090_regmap);
if (IS_ERR(wm9090->regmap)) {
ret = PTR_ERR(wm9090->regmap);
dev_err(&i2c->dev, "Failed to allocate regmap: %d\n", ret);
@@ -637,16 +637,16 @@ static int wm9090_i2c_probe(struct i2c_client *i2c,
ret = regmap_read(wm9090->regmap, WM9090_SOFTWARE_RESET, &reg);
if (ret < 0)
- goto err;
+ return ret;
+
if (reg != 0x9093) {
dev_err(&i2c->dev, "Device is not a WM9090, ID=%x\n", reg);
- ret = -ENODEV;
- goto err;
+ return -ENODEV;
}
ret = regmap_write(wm9090->regmap, WM9090_SOFTWARE_RESET, 0);
if (ret < 0)
- goto err;
+ return ret;
if (i2c->dev.platform_data)
memcpy(&wm9090->pdata, i2c->dev.platform_data,
@@ -658,23 +658,15 @@ static int wm9090_i2c_probe(struct i2c_client *i2c,
&soc_codec_dev_wm9090, NULL, 0);
if (ret != 0) {
dev_err(&i2c->dev, "Failed to register CODEC: %d\n", ret);
- goto err;
+ return ret;
}
return 0;
-
-err:
- regmap_exit(wm9090->regmap);
- return ret;
}
-static int __devexit wm9090_i2c_remove(struct i2c_client *i2c)
+static int wm9090_i2c_remove(struct i2c_client *i2c)
{
- struct wm9090_priv *wm9090 = i2c_get_clientdata(i2c);
-
snd_soc_unregister_codec(&i2c->dev);
- regmap_exit(wm9090->regmap);
-
return 0;
}
@@ -691,7 +683,7 @@ static struct i2c_driver wm9090_i2c_driver = {
.owner = THIS_MODULE,
},
.probe = wm9090_i2c_probe,
- .remove = __devexit_p(wm9090_i2c_remove),
+ .remove = wm9090_i2c_remove,
.id_table = wm9090_id,
};
diff --git a/sound/soc/codecs/wm9705.c b/sound/soc/codecs/wm9705.c
index e8e782a0c78d..05b1f346695b 100644
--- a/sound/soc/codecs/wm9705.c
+++ b/sound/soc/codecs/wm9705.c
@@ -382,13 +382,13 @@ static struct snd_soc_codec_driver soc_codec_dev_wm9705 = {
.num_dapm_routes = ARRAY_SIZE(wm9705_audio_map),
};
-static __devinit int wm9705_probe(struct platform_device *pdev)
+static int wm9705_probe(struct platform_device *pdev)
{
return snd_soc_register_codec(&pdev->dev,
&soc_codec_dev_wm9705, wm9705_dai, ARRAY_SIZE(wm9705_dai));
}
-static int __devexit wm9705_remove(struct platform_device *pdev)
+static int wm9705_remove(struct platform_device *pdev)
{
snd_soc_unregister_codec(&pdev->dev);
return 0;
@@ -401,7 +401,7 @@ static struct platform_driver wm9705_codec_driver = {
},
.probe = wm9705_probe,
- .remove = __devexit_p(wm9705_remove),
+ .remove = wm9705_remove,
};
module_platform_driver(wm9705_codec_driver);
diff --git a/sound/soc/codecs/wm9712.c b/sound/soc/codecs/wm9712.c
index 4dd73ea08d0b..8e9a6a3eeb1a 100644
--- a/sound/soc/codecs/wm9712.c
+++ b/sound/soc/codecs/wm9712.c
@@ -685,13 +685,13 @@ static struct snd_soc_codec_driver soc_codec_dev_wm9712 = {
.num_dapm_routes = ARRAY_SIZE(wm9712_audio_map),
};
-static __devinit int wm9712_probe(struct platform_device *pdev)
+static int wm9712_probe(struct platform_device *pdev)
{
return snd_soc_register_codec(&pdev->dev,
&soc_codec_dev_wm9712, wm9712_dai, ARRAY_SIZE(wm9712_dai));
}
-static int __devexit wm9712_remove(struct platform_device *pdev)
+static int wm9712_remove(struct platform_device *pdev)
{
snd_soc_unregister_codec(&pdev->dev);
return 0;
@@ -704,7 +704,7 @@ static struct platform_driver wm9712_codec_driver = {
},
.probe = wm9712_probe,
- .remove = __devexit_p(wm9712_remove),
+ .remove = wm9712_remove,
};
module_platform_driver(wm9712_codec_driver);
diff --git a/sound/soc/codecs/wm9713.c b/sound/soc/codecs/wm9713.c
index 3eb19fb71d17..f7afa68d8c7f 100644
--- a/sound/soc/codecs/wm9713.c
+++ b/sound/soc/codecs/wm9713.c
@@ -1254,13 +1254,13 @@ static struct snd_soc_codec_driver soc_codec_dev_wm9713 = {
.num_dapm_routes = ARRAY_SIZE(wm9713_audio_map),
};
-static __devinit int wm9713_probe(struct platform_device *pdev)
+static int wm9713_probe(struct platform_device *pdev)
{
return snd_soc_register_codec(&pdev->dev,
&soc_codec_dev_wm9713, wm9713_dai, ARRAY_SIZE(wm9713_dai));
}
-static int __devexit wm9713_remove(struct platform_device *pdev)
+static int wm9713_remove(struct platform_device *pdev)
{
snd_soc_unregister_codec(&pdev->dev);
return 0;
@@ -1273,7 +1273,7 @@ static struct platform_driver wm9713_codec_driver = {
},
.probe = wm9713_probe,
- .remove = __devexit_p(wm9713_remove),
+ .remove = wm9713_remove,
};
module_platform_driver(wm9713_codec_driver);
diff --git a/sound/soc/codecs/wm_adsp.c b/sound/soc/codecs/wm_adsp.c
new file mode 100644
index 000000000000..ffc89fab96fb
--- /dev/null
+++ b/sound/soc/codecs/wm_adsp.c
@@ -0,0 +1,699 @@
+/*
+ * wm_adsp.c -- Wolfson ADSP support
+ *
+ * Copyright 2012 Wolfson Microelectronics plc
+ *
+ * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/firmware.h>
+#include <linux/pm.h>
+#include <linux/pm_runtime.h>
+#include <linux/regmap.h>
+#include <linux/regulator/consumer.h>
+#include <linux/slab.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/jack.h>
+#include <sound/initval.h>
+#include <sound/tlv.h>
+
+#include <linux/mfd/arizona/registers.h>
+
+#include "wm_adsp.h"
+
+#define adsp_crit(_dsp, fmt, ...) \
+ dev_crit(_dsp->dev, "DSP%d: " fmt, _dsp->num, ##__VA_ARGS__)
+#define adsp_err(_dsp, fmt, ...) \
+ dev_err(_dsp->dev, "DSP%d: " fmt, _dsp->num, ##__VA_ARGS__)
+#define adsp_warn(_dsp, fmt, ...) \
+ dev_warn(_dsp->dev, "DSP%d: " fmt, _dsp->num, ##__VA_ARGS__)
+#define adsp_info(_dsp, fmt, ...) \
+ dev_info(_dsp->dev, "DSP%d: " fmt, _dsp->num, ##__VA_ARGS__)
+#define adsp_dbg(_dsp, fmt, ...) \
+ dev_dbg(_dsp->dev, "DSP%d: " fmt, _dsp->num, ##__VA_ARGS__)
+
+#define ADSP1_CONTROL_1 0x00
+#define ADSP1_CONTROL_2 0x02
+#define ADSP1_CONTROL_3 0x03
+#define ADSP1_CONTROL_4 0x04
+#define ADSP1_CONTROL_5 0x06
+#define ADSP1_CONTROL_6 0x07
+#define ADSP1_CONTROL_7 0x08
+#define ADSP1_CONTROL_8 0x09
+#define ADSP1_CONTROL_9 0x0A
+#define ADSP1_CONTROL_10 0x0B
+#define ADSP1_CONTROL_11 0x0C
+#define ADSP1_CONTROL_12 0x0D
+#define ADSP1_CONTROL_13 0x0F
+#define ADSP1_CONTROL_14 0x10
+#define ADSP1_CONTROL_15 0x11
+#define ADSP1_CONTROL_16 0x12
+#define ADSP1_CONTROL_17 0x13
+#define ADSP1_CONTROL_18 0x14
+#define ADSP1_CONTROL_19 0x16
+#define ADSP1_CONTROL_20 0x17
+#define ADSP1_CONTROL_21 0x18
+#define ADSP1_CONTROL_22 0x1A
+#define ADSP1_CONTROL_23 0x1B
+#define ADSP1_CONTROL_24 0x1C
+#define ADSP1_CONTROL_25 0x1E
+#define ADSP1_CONTROL_26 0x20
+#define ADSP1_CONTROL_27 0x21
+#define ADSP1_CONTROL_28 0x22
+#define ADSP1_CONTROL_29 0x23
+#define ADSP1_CONTROL_30 0x24
+#define ADSP1_CONTROL_31 0x26
+
+/*
+ * ADSP1 Control 19
+ */
+#define ADSP1_WDMA_BUFFER_LENGTH_MASK 0x00FF /* DSP1_WDMA_BUFFER_LENGTH - [7:0] */
+#define ADSP1_WDMA_BUFFER_LENGTH_SHIFT 0 /* DSP1_WDMA_BUFFER_LENGTH - [7:0] */
+#define ADSP1_WDMA_BUFFER_LENGTH_WIDTH 8 /* DSP1_WDMA_BUFFER_LENGTH - [7:0] */
+
+
+/*
+ * ADSP1 Control 30
+ */
+#define ADSP1_DBG_CLK_ENA 0x0008 /* DSP1_DBG_CLK_ENA */
+#define ADSP1_DBG_CLK_ENA_MASK 0x0008 /* DSP1_DBG_CLK_ENA */
+#define ADSP1_DBG_CLK_ENA_SHIFT 3 /* DSP1_DBG_CLK_ENA */
+#define ADSP1_DBG_CLK_ENA_WIDTH 1 /* DSP1_DBG_CLK_ENA */
+#define ADSP1_SYS_ENA 0x0004 /* DSP1_SYS_ENA */
+#define ADSP1_SYS_ENA_MASK 0x0004 /* DSP1_SYS_ENA */
+#define ADSP1_SYS_ENA_SHIFT 2 /* DSP1_SYS_ENA */
+#define ADSP1_SYS_ENA_WIDTH 1 /* DSP1_SYS_ENA */
+#define ADSP1_CORE_ENA 0x0002 /* DSP1_CORE_ENA */
+#define ADSP1_CORE_ENA_MASK 0x0002 /* DSP1_CORE_ENA */
+#define ADSP1_CORE_ENA_SHIFT 1 /* DSP1_CORE_ENA */
+#define ADSP1_CORE_ENA_WIDTH 1 /* DSP1_CORE_ENA */
+#define ADSP1_START 0x0001 /* DSP1_START */
+#define ADSP1_START_MASK 0x0001 /* DSP1_START */
+#define ADSP1_START_SHIFT 0 /* DSP1_START */
+#define ADSP1_START_WIDTH 1 /* DSP1_START */
+
+#define ADSP2_CONTROL 0
+#define ADSP2_CLOCKING 1
+#define ADSP2_STATUS1 4
+
+/*
+ * ADSP2 Control
+ */
+
+#define ADSP2_MEM_ENA 0x0010 /* DSP1_MEM_ENA */
+#define ADSP2_MEM_ENA_MASK 0x0010 /* DSP1_MEM_ENA */
+#define ADSP2_MEM_ENA_SHIFT 4 /* DSP1_MEM_ENA */
+#define ADSP2_MEM_ENA_WIDTH 1 /* DSP1_MEM_ENA */
+#define ADSP2_SYS_ENA 0x0004 /* DSP1_SYS_ENA */
+#define ADSP2_SYS_ENA_MASK 0x0004 /* DSP1_SYS_ENA */
+#define ADSP2_SYS_ENA_SHIFT 2 /* DSP1_SYS_ENA */
+#define ADSP2_SYS_ENA_WIDTH 1 /* DSP1_SYS_ENA */
+#define ADSP2_CORE_ENA 0x0002 /* DSP1_CORE_ENA */
+#define ADSP2_CORE_ENA_MASK 0x0002 /* DSP1_CORE_ENA */
+#define ADSP2_CORE_ENA_SHIFT 1 /* DSP1_CORE_ENA */
+#define ADSP2_CORE_ENA_WIDTH 1 /* DSP1_CORE_ENA */
+#define ADSP2_START 0x0001 /* DSP1_START */
+#define ADSP2_START_MASK 0x0001 /* DSP1_START */
+#define ADSP2_START_SHIFT 0 /* DSP1_START */
+#define ADSP2_START_WIDTH 1 /* DSP1_START */
+
+/*
+ * ADSP2 clocking
+ */
+#define ADSP2_CLK_SEL_MASK 0x0007 /* CLK_SEL_ENA */
+#define ADSP2_CLK_SEL_SHIFT 0 /* CLK_SEL_ENA */
+#define ADSP2_CLK_SEL_WIDTH 3 /* CLK_SEL_ENA */
+
+/*
+ * ADSP2 Status 1
+ */
+#define ADSP2_RAM_RDY 0x0001
+#define ADSP2_RAM_RDY_MASK 0x0001
+#define ADSP2_RAM_RDY_SHIFT 0
+#define ADSP2_RAM_RDY_WIDTH 1
+
+
+static struct wm_adsp_region const *wm_adsp_find_region(struct wm_adsp *dsp,
+ int type)
+{
+ int i;
+
+ for (i = 0; i < dsp->num_mems; i++)
+ if (dsp->mem[i].type == type)
+ return &dsp->mem[i];
+
+ return NULL;
+}
+
+static int wm_adsp_load(struct wm_adsp *dsp)
+{
+ const struct firmware *firmware;
+ struct regmap *regmap = dsp->regmap;
+ unsigned int pos = 0;
+ const struct wmfw_header *header;
+ const struct wmfw_adsp1_sizes *adsp1_sizes;
+ const struct wmfw_adsp2_sizes *adsp2_sizes;
+ const struct wmfw_footer *footer;
+ const struct wmfw_region *region;
+ const struct wm_adsp_region *mem;
+ const char *region_name;
+ char *file, *text;
+ unsigned int reg;
+ int regions = 0;
+ int ret, offset, type, sizes;
+
+ file = kzalloc(PAGE_SIZE, GFP_KERNEL);
+ if (file == NULL)
+ return -ENOMEM;
+
+ snprintf(file, PAGE_SIZE, "%s-dsp%d.wmfw", dsp->part, dsp->num);
+ file[PAGE_SIZE - 1] = '\0';
+
+ ret = request_firmware(&firmware, file, dsp->dev);
+ if (ret != 0) {
+ adsp_err(dsp, "Failed to request '%s'\n", file);
+ goto out;
+ }
+ ret = -EINVAL;
+
+ pos = sizeof(*header) + sizeof(*adsp1_sizes) + sizeof(*footer);
+ if (pos >= firmware->size) {
+ adsp_err(dsp, "%s: file too short, %zu bytes\n",
+ file, firmware->size);
+ goto out_fw;
+ }
+
+ header = (void*)&firmware->data[0];
+
+ if (memcmp(&header->magic[0], "WMFW", 4) != 0) {
+ adsp_err(dsp, "%s: invalid magic\n", file);
+ goto out_fw;
+ }
+
+ if (header->ver != 0) {
+ adsp_err(dsp, "%s: unknown file format %d\n",
+ file, header->ver);
+ goto out_fw;
+ }
+
+ if (header->core != dsp->type) {
+ adsp_err(dsp, "%s: invalid core %d != %d\n",
+ file, header->core, dsp->type);
+ goto out_fw;
+ }
+
+ switch (dsp->type) {
+ case WMFW_ADSP1:
+ pos = sizeof(*header) + sizeof(*adsp1_sizes) + sizeof(*footer);
+ adsp1_sizes = (void *)&(header[1]);
+ footer = (void *)&(adsp1_sizes[1]);
+ sizes = sizeof(*adsp1_sizes);
+
+ adsp_dbg(dsp, "%s: %d DM, %d PM, %d ZM\n",
+ file, le32_to_cpu(adsp1_sizes->dm),
+ le32_to_cpu(adsp1_sizes->pm),
+ le32_to_cpu(adsp1_sizes->zm));
+ break;
+
+ case WMFW_ADSP2:
+ pos = sizeof(*header) + sizeof(*adsp2_sizes) + sizeof(*footer);
+ adsp2_sizes = (void *)&(header[1]);
+ footer = (void *)&(adsp2_sizes[1]);
+ sizes = sizeof(*adsp2_sizes);
+
+ adsp_dbg(dsp, "%s: %d XM, %d YM %d PM, %d ZM\n",
+ file, le32_to_cpu(adsp2_sizes->xm),
+ le32_to_cpu(adsp2_sizes->ym),
+ le32_to_cpu(adsp2_sizes->pm),
+ le32_to_cpu(adsp2_sizes->zm));
+ break;
+
+ default:
+ BUG_ON(NULL == "Unknown DSP type");
+ goto out_fw;
+ }
+
+ if (le32_to_cpu(header->len) != sizeof(*header) +
+ sizes + sizeof(*footer)) {
+ adsp_err(dsp, "%s: unexpected header length %d\n",
+ file, le32_to_cpu(header->len));
+ goto out_fw;
+ }
+
+ adsp_dbg(dsp, "%s: timestamp %llu\n", file,
+ le64_to_cpu(footer->timestamp));
+
+ while (pos < firmware->size &&
+ pos - firmware->size > sizeof(*region)) {
+ region = (void *)&(firmware->data[pos]);
+ region_name = "Unknown";
+ reg = 0;
+ text = NULL;
+ offset = le32_to_cpu(region->offset) & 0xffffff;
+ type = be32_to_cpu(region->type) & 0xff;
+ mem = wm_adsp_find_region(dsp, type);
+
+ switch (type) {
+ case WMFW_NAME_TEXT:
+ region_name = "Firmware name";
+ text = kzalloc(le32_to_cpu(region->len) + 1,
+ GFP_KERNEL);
+ break;
+ case WMFW_INFO_TEXT:
+ region_name = "Information";
+ text = kzalloc(le32_to_cpu(region->len) + 1,
+ GFP_KERNEL);
+ break;
+ case WMFW_ABSOLUTE:
+ region_name = "Absolute";
+ reg = offset;
+ break;
+ case WMFW_ADSP1_PM:
+ BUG_ON(!mem);
+ region_name = "PM";
+ reg = mem->base + (offset * 3);
+ break;
+ case WMFW_ADSP1_DM:
+ BUG_ON(!mem);
+ region_name = "DM";
+ reg = mem->base + (offset * 2);
+ break;
+ case WMFW_ADSP2_XM:
+ BUG_ON(!mem);
+ region_name = "XM";
+ reg = mem->base + (offset * 2);
+ break;
+ case WMFW_ADSP2_YM:
+ BUG_ON(!mem);
+ region_name = "YM";
+ reg = mem->base + (offset * 2);
+ break;
+ case WMFW_ADSP1_ZM:
+ BUG_ON(!mem);
+ region_name = "ZM";
+ reg = mem->base + (offset * 2);
+ break;
+ default:
+ adsp_warn(dsp,
+ "%s.%d: Unknown region type %x at %d(%x)\n",
+ file, regions, type, pos, pos);
+ break;
+ }
+
+ adsp_dbg(dsp, "%s.%d: %d bytes at %d in %s\n", file,
+ regions, le32_to_cpu(region->len), offset,
+ region_name);
+
+ if (text) {
+ memcpy(text, region->data, le32_to_cpu(region->len));
+ adsp_info(dsp, "%s: %s\n", file, text);
+ kfree(text);
+ }
+
+ if (reg) {
+ ret = regmap_raw_write(regmap, reg, region->data,
+ le32_to_cpu(region->len));
+ if (ret != 0) {
+ adsp_err(dsp,
+ "%s.%d: Failed to write %d bytes at %d in %s: %d\n",
+ file, regions,
+ le32_to_cpu(region->len), offset,
+ region_name, ret);
+ goto out_fw;
+ }
+ }
+
+ pos += le32_to_cpu(region->len) + sizeof(*region);
+ regions++;
+ }
+
+ if (pos > firmware->size)
+ adsp_warn(dsp, "%s.%d: %zu bytes at end of file\n",
+ file, regions, pos - firmware->size);
+
+out_fw:
+ release_firmware(firmware);
+out:
+ kfree(file);
+
+ return ret;
+}
+
+static int wm_adsp_load_coeff(struct wm_adsp *dsp)
+{
+ struct regmap *regmap = dsp->regmap;
+ struct wmfw_coeff_hdr *hdr;
+ struct wmfw_coeff_item *blk;
+ const struct firmware *firmware;
+ const char *region_name;
+ int ret, pos, blocks, type, offset, reg;
+ char *file;
+
+ file = kzalloc(PAGE_SIZE, GFP_KERNEL);
+ if (file == NULL)
+ return -ENOMEM;
+
+ snprintf(file, PAGE_SIZE, "%s-dsp%d.bin", dsp->part, dsp->num);
+ file[PAGE_SIZE - 1] = '\0';
+
+ ret = request_firmware(&firmware, file, dsp->dev);
+ if (ret != 0) {
+ adsp_warn(dsp, "Failed to request '%s'\n", file);
+ ret = 0;
+ goto out;
+ }
+ ret = -EINVAL;
+
+ if (sizeof(*hdr) >= firmware->size) {
+ adsp_err(dsp, "%s: file too short, %zu bytes\n",
+ file, firmware->size);
+ goto out_fw;
+ }
+
+ hdr = (void*)&firmware->data[0];
+ if (memcmp(hdr->magic, "WMDR", 4) != 0) {
+ adsp_err(dsp, "%s: invalid magic\n", file);
+ return -EINVAL;
+ }
+
+ adsp_dbg(dsp, "%s: v%d.%d.%d\n", file,
+ (le32_to_cpu(hdr->ver) >> 16) & 0xff,
+ (le32_to_cpu(hdr->ver) >> 8) & 0xff,
+ le32_to_cpu(hdr->ver) & 0xff);
+
+ pos = le32_to_cpu(hdr->len);
+
+ blocks = 0;
+ while (pos < firmware->size &&
+ pos - firmware->size > sizeof(*blk)) {
+ blk = (void*)(&firmware->data[pos]);
+
+ type = be32_to_cpu(blk->type) & 0xff;
+ offset = le32_to_cpu(blk->offset) & 0xffffff;
+
+ adsp_dbg(dsp, "%s.%d: %x v%d.%d.%d\n",
+ file, blocks, le32_to_cpu(blk->id),
+ (le32_to_cpu(blk->ver) >> 16) & 0xff,
+ (le32_to_cpu(blk->ver) >> 8) & 0xff,
+ le32_to_cpu(blk->ver) & 0xff);
+ adsp_dbg(dsp, "%s.%d: %d bytes at 0x%x in %x\n",
+ file, blocks, le32_to_cpu(blk->len), offset, type);
+
+ reg = 0;
+ region_name = "Unknown";
+ switch (type) {
+ case WMFW_NAME_TEXT:
+ case WMFW_INFO_TEXT:
+ break;
+ case WMFW_ABSOLUTE:
+ region_name = "register";
+ reg = offset;
+ break;
+ default:
+ adsp_err(dsp, "Unknown region type %x\n", type);
+ break;
+ }
+
+ if (reg) {
+ ret = regmap_raw_write(regmap, reg, blk->data,
+ le32_to_cpu(blk->len));
+ if (ret != 0) {
+ adsp_err(dsp,
+ "%s.%d: Failed to write to %x in %s\n",
+ file, blocks, reg, region_name);
+ }
+ }
+
+ pos += le32_to_cpu(blk->len) + sizeof(*blk);
+ blocks++;
+ }
+
+ if (pos > firmware->size)
+ adsp_warn(dsp, "%s.%d: %zu bytes at end of file\n",
+ file, blocks, pos - firmware->size);
+
+out_fw:
+ release_firmware(firmware);
+out:
+ kfree(file);
+ return 0;
+}
+
+int wm_adsp1_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol,
+ int event)
+{
+ struct snd_soc_codec *codec = w->codec;
+ struct wm_adsp *dsps = snd_soc_codec_get_drvdata(codec);
+ struct wm_adsp *dsp = &dsps[w->shift];
+ int ret;
+
+ switch (event) {
+ case SND_SOC_DAPM_POST_PMU:
+ regmap_update_bits(dsp->regmap, dsp->base + ADSP1_CONTROL_30,
+ ADSP1_SYS_ENA, ADSP1_SYS_ENA);
+
+ ret = wm_adsp_load(dsp);
+ if (ret != 0)
+ goto err;
+
+ ret = wm_adsp_load_coeff(dsp);
+ if (ret != 0)
+ goto err;
+
+ /* Start the core running */
+ regmap_update_bits(dsp->regmap, dsp->base + ADSP1_CONTROL_30,
+ ADSP1_CORE_ENA | ADSP1_START,
+ ADSP1_CORE_ENA | ADSP1_START);
+ break;
+
+ case SND_SOC_DAPM_PRE_PMD:
+ /* Halt the core */
+ regmap_update_bits(dsp->regmap, dsp->base + ADSP1_CONTROL_30,
+ ADSP1_CORE_ENA | ADSP1_START, 0);
+
+ regmap_update_bits(dsp->regmap, dsp->base + ADSP1_CONTROL_19,
+ ADSP1_WDMA_BUFFER_LENGTH_MASK, 0);
+
+ regmap_update_bits(dsp->regmap, dsp->base + ADSP1_CONTROL_30,
+ ADSP1_SYS_ENA, 0);
+ break;
+
+ default:
+ break;
+ }
+
+ return 0;
+
+err:
+ regmap_update_bits(dsp->regmap, dsp->base + ADSP1_CONTROL_30,
+ ADSP1_SYS_ENA, 0);
+ return ret;
+}
+EXPORT_SYMBOL_GPL(wm_adsp1_event);
+
+static int wm_adsp2_ena(struct wm_adsp *dsp)
+{
+ unsigned int val;
+ int ret, count;
+
+ ret = regmap_update_bits(dsp->regmap, dsp->base + ADSP2_CONTROL,
+ ADSP2_SYS_ENA, ADSP2_SYS_ENA);
+ if (ret != 0)
+ return ret;
+
+ /* Wait for the RAM to start, should be near instantaneous */
+ count = 0;
+ do {
+ ret = regmap_read(dsp->regmap, dsp->base + ADSP2_STATUS1,
+ &val);
+ if (ret != 0)
+ return ret;
+ } while (!(val & ADSP2_RAM_RDY) && ++count < 10);
+
+ if (!(val & ADSP2_RAM_RDY)) {
+ adsp_err(dsp, "Failed to start DSP RAM\n");
+ return -EBUSY;
+ }
+
+ adsp_dbg(dsp, "RAM ready after %d polls\n", count);
+ adsp_info(dsp, "RAM ready after %d polls\n", count);
+
+ return 0;
+}
+
+int wm_adsp2_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_codec *codec = w->codec;
+ struct wm_adsp *dsps = snd_soc_codec_get_drvdata(codec);
+ struct wm_adsp *dsp = &dsps[w->shift];
+ unsigned int val;
+ int ret;
+
+ switch (event) {
+ case SND_SOC_DAPM_POST_PMU:
+ /*
+ * For simplicity set the DSP clock rate to be the
+ * SYSCLK rate rather than making it configurable.
+ */
+ ret = regmap_read(dsp->regmap, ARIZONA_SYSTEM_CLOCK_1, &val);
+ if (ret != 0) {
+ adsp_err(dsp, "Failed to read SYSCLK state: %d\n",
+ ret);
+ return ret;
+ }
+ val = (val & ARIZONA_SYSCLK_FREQ_MASK)
+ >> ARIZONA_SYSCLK_FREQ_SHIFT;
+
+ ret = regmap_update_bits(dsp->regmap,
+ dsp->base + ADSP2_CLOCKING,
+ ADSP2_CLK_SEL_MASK, val);
+ if (ret != 0) {
+ adsp_err(dsp, "Failed to set clock rate: %d\n",
+ ret);
+ return ret;
+ }
+
+ if (dsp->dvfs) {
+ ret = regmap_read(dsp->regmap,
+ dsp->base + ADSP2_CLOCKING, &val);
+ if (ret != 0) {
+ dev_err(dsp->dev,
+ "Failed to read clocking: %d\n", ret);
+ return ret;
+ }
+
+ if ((val & ADSP2_CLK_SEL_MASK) >= 3) {
+ ret = regulator_enable(dsp->dvfs);
+ if (ret != 0) {
+ dev_err(dsp->dev,
+ "Failed to enable supply: %d\n",
+ ret);
+ return ret;
+ }
+
+ ret = regulator_set_voltage(dsp->dvfs,
+ 1800000,
+ 1800000);
+ if (ret != 0) {
+ dev_err(dsp->dev,
+ "Failed to raise supply: %d\n",
+ ret);
+ return ret;
+ }
+ }
+ }
+
+ ret = wm_adsp2_ena(dsp);
+ if (ret != 0)
+ return ret;
+
+ ret = wm_adsp_load(dsp);
+ if (ret != 0)
+ goto err;
+
+ ret = wm_adsp_load_coeff(dsp);
+ if (ret != 0)
+ goto err;
+
+ ret = regmap_update_bits(dsp->regmap,
+ dsp->base + ADSP2_CONTROL,
+ ADSP2_CORE_ENA | ADSP2_START,
+ ADSP2_CORE_ENA | ADSP2_START);
+ if (ret != 0)
+ goto err;
+ break;
+
+ case SND_SOC_DAPM_PRE_PMD:
+ regmap_update_bits(dsp->regmap, dsp->base + ADSP2_CONTROL,
+ ADSP2_SYS_ENA | ADSP2_CORE_ENA |
+ ADSP2_START, 0);
+
+ if (dsp->dvfs) {
+ ret = regulator_set_voltage(dsp->dvfs, 1200000,
+ 1800000);
+ if (ret != 0)
+ dev_warn(dsp->dev,
+ "Failed to lower supply: %d\n",
+ ret);
+
+ ret = regulator_disable(dsp->dvfs);
+ if (ret != 0)
+ dev_err(dsp->dev,
+ "Failed to enable supply: %d\n",
+ ret);
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ return 0;
+err:
+ regmap_update_bits(dsp->regmap, dsp->base + ADSP2_CONTROL,
+ ADSP2_SYS_ENA | ADSP2_CORE_ENA | ADSP2_START, 0);
+ return ret;
+}
+EXPORT_SYMBOL_GPL(wm_adsp2_event);
+
+int wm_adsp2_init(struct wm_adsp *adsp, bool dvfs)
+{
+ int ret;
+
+ /*
+ * Disable the DSP memory by default when in reset for a small
+ * power saving.
+ */
+ ret = regmap_update_bits(adsp->regmap, adsp->base + ADSP2_CONTROL,
+ ADSP2_MEM_ENA, 0);
+ if (ret != 0) {
+ adsp_err(adsp, "Failed to clear memory retention: %d\n", ret);
+ return ret;
+ }
+
+ if (dvfs) {
+ adsp->dvfs = devm_regulator_get(adsp->dev, "DCVDD");
+ if (IS_ERR(adsp->dvfs)) {
+ ret = PTR_ERR(adsp->dvfs);
+ dev_err(adsp->dev, "Failed to get DCVDD: %d\n", ret);
+ return ret;
+ }
+
+ ret = regulator_enable(adsp->dvfs);
+ if (ret != 0) {
+ dev_err(adsp->dev, "Failed to enable DCVDD: %d\n",
+ ret);
+ return ret;
+ }
+
+ ret = regulator_set_voltage(adsp->dvfs, 1200000, 1800000);
+ if (ret != 0) {
+ dev_err(adsp->dev, "Failed to initialise DVFS: %d\n",
+ ret);
+ return ret;
+ }
+
+ ret = regulator_disable(adsp->dvfs);
+ if (ret != 0) {
+ dev_err(adsp->dev, "Failed to disable DCVDD: %d\n",
+ ret);
+ return ret;
+ }
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(wm_adsp2_init);
diff --git a/sound/soc/codecs/wm_adsp.h b/sound/soc/codecs/wm_adsp.h
new file mode 100644
index 000000000000..ffd29a4609e2
--- /dev/null
+++ b/sound/soc/codecs/wm_adsp.h
@@ -0,0 +1,59 @@
+/*
+ * wm_adsp.h -- Wolfson ADSP support
+ *
+ * Copyright 2012 Wolfson Microelectronics plc
+ *
+ * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __WM_ADSP_H
+#define __WM_ADSP_H
+
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+
+#include "wmfw.h"
+
+struct regulator;
+
+struct wm_adsp_region {
+ int type;
+ unsigned int base;
+};
+
+struct wm_adsp {
+ const char *part;
+ int num;
+ int type;
+ struct device *dev;
+ struct regmap *regmap;
+
+ int base;
+
+ const struct wm_adsp_region *mem;
+ int num_mems;
+
+ struct regulator *dvfs;
+};
+
+#define WM_ADSP1(wname, num) \
+ { .id = snd_soc_dapm_pga, .name = wname, .reg = SND_SOC_NOPM, \
+ .shift = num, .event = wm_adsp1_event, \
+ .event_flags = SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD }
+
+#define WM_ADSP2(wname, num) \
+{ .id = snd_soc_dapm_pga, .name = wname, .reg = SND_SOC_NOPM, \
+ .shift = num, .event = wm_adsp2_event, \
+ .event_flags = SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD }
+
+int wm_adsp2_init(struct wm_adsp *adsp, bool dvfs);
+int wm_adsp1_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event);
+int wm_adsp2_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event);
+
+#endif
diff --git a/sound/soc/codecs/wmfw.h b/sound/soc/codecs/wmfw.h
new file mode 100644
index 000000000000..5632ded67fdd
--- /dev/null
+++ b/sound/soc/codecs/wmfw.h
@@ -0,0 +1,128 @@
+/*
+ * wmfw.h - Wolfson firmware format information
+ *
+ * Copyright 2012 Wolfson Microelectronics plc
+ *
+ * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __WMFW_H
+#define __WMFW_H
+
+#include <linux/types.h>
+
+struct wmfw_header {
+ char magic[4];
+ __le32 len;
+ __le16 rev;
+ u8 core;
+ u8 ver;
+} __packed;
+
+struct wmfw_footer {
+ __le64 timestamp;
+ __le32 checksum;
+} __packed;
+
+struct wmfw_adsp1_sizes {
+ __le32 dm;
+ __le32 pm;
+ __le32 zm;
+} __packed;
+
+struct wmfw_adsp2_sizes {
+ __le32 xm;
+ __le32 ym;
+ __le32 pm;
+ __le32 zm;
+} __packed;
+
+struct wmfw_region {
+ union {
+ __be32 type;
+ __le32 offset;
+ };
+ __le32 len;
+ u8 data[];
+} __packed;
+
+struct wmfw_id_hdr {
+ __be32 core_id;
+ __be32 core_rev;
+ __be32 id;
+ __be32 ver;
+} __packed;
+
+struct wmfw_adsp1_id_hdr {
+ struct wmfw_id_hdr fw;
+ __be32 zm;
+ __be32 dm;
+ __be32 algs;
+} __packed;
+
+struct wmfw_adsp2_id_hdr {
+ struct wmfw_id_hdr fw;
+ __be32 zm;
+ __be32 xm;
+ __be32 ym;
+ __be32 algs;
+} __packed;
+
+struct wmfw_alg_hdr {
+ __be32 id;
+ __be32 ver;
+} __packed;
+
+struct wmfw_adsp1_alg_hdr {
+ struct wmfw_alg_hdr alg;
+ __be32 zm;
+ __be32 dm;
+} __packed;
+
+struct wmfw_adsp2_alg_hdr {
+ struct wmfw_alg_hdr alg;
+ __be32 zm;
+ __be32 xm;
+ __be32 ym;
+} __packed;
+
+struct wmfw_coeff_hdr {
+ u8 magic[4];
+ __le32 len;
+ __le32 ver;
+ u8 data[];
+} __packed;
+
+struct wmfw_coeff_item {
+ union {
+ __be32 type;
+ __le32 offset;
+ };
+ __le32 id;
+ __le32 ver;
+ __le32 sr;
+ __le32 len;
+ u8 data[];
+} __packed;
+
+#define WMFW_ADSP1 1
+#define WMFW_ADSP2 2
+
+#define WMFW_ABSOLUTE 0xf0
+#define WMFW_NAME_TEXT 0xfe
+#define WMFW_INFO_TEXT 0xff
+
+#define WMFW_ADSP1_PM 2
+#define WMFW_ADSP1_DM 3
+#define WMFW_ADSP1_ZM 4
+
+#define WMFW_ADSP2_PM 2
+#define WMFW_ADSP2_ZM 4
+#define WMFW_ADSP2_XM 5
+#define WMFW_ADSP2_YM 6
+
+#endif