Merge branches 'topic/ad193x', 'topic/tlv320aic23', 'topic/tlv320aic32x4', 'topic/wm8991', 'fix/si476x' and 'fix/88pm860' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound into asoc-io
diff --git a/Documentation/devicetree/bindings/i2c/trivial-devices.txt b/Documentation/devicetree/bindings/i2c/trivial-devices.txt
index 1a1ac2e..f47e56b 100644
--- a/Documentation/devicetree/bindings/i2c/trivial-devices.txt
+++ b/Documentation/devicetree/bindings/i2c/trivial-devices.txt
@@ -18,6 +18,7 @@
atmel,at97sc3204t i2c trusted platform module (TPM)
capella,cm32181 CM32181: Ambient Light Sensor
catalyst,24c32 i2c serial eeprom
+cirrus,cs42l51 Cirrus Logic CS42L51 audio codec
dallas,ds1307 64 x 8, Serial, I2C Real-Time Clock
dallas,ds1338 I2C RTC with 56-Byte NV RAM
dallas,ds1339 I2C Serial Real-Time Clock
diff --git a/include/sound/soc.h b/include/sound/soc.h
index c4be7ab..2d8982d 100644
--- a/include/sound/soc.h
+++ b/include/sound/soc.h
@@ -355,8 +355,6 @@
extern struct snd_ac97_bus_ops *soc_ac97_ops;
enum snd_soc_control_type {
- SND_SOC_I2C = 1,
- SND_SOC_SPI,
SND_SOC_REGMAP,
};
@@ -711,7 +709,6 @@
/* codec IO */
void *control_data; /* codec control (i2c/3wire) data */
hw_write_t hw_write;
- unsigned int (*hw_read)(struct snd_soc_codec *, unsigned int);
unsigned int (*read)(struct snd_soc_codec *, unsigned int);
int (*write)(struct snd_soc_codec *, unsigned int, unsigned int);
void *reg_cache;
diff --git a/sound/soc/atmel/Kconfig b/sound/soc/atmel/Kconfig
index e634eb7..4789619 100644
--- a/sound/soc/atmel/Kconfig
+++ b/sound/soc/atmel/Kconfig
@@ -58,6 +58,6 @@
depends on ARCH_AT91 && ATMEL_SSC && ARCH_AT91 && MACH_AFEB9260 && SND_ATMEL_SOC
select SND_ATMEL_SOC_PDC
select SND_ATMEL_SOC_SSC
- select SND_SOC_TLV320AIC23
+ select SND_SOC_TLV320AIC23_I2C
help
Say Y here to support sound on AFEB9260 board.
diff --git a/sound/soc/blackfin/Kconfig b/sound/soc/blackfin/Kconfig
index 54f74f8..3591367 100644
--- a/sound/soc/blackfin/Kconfig
+++ b/sound/soc/blackfin/Kconfig
@@ -68,7 +68,8 @@
tristate "SoC AD193X Audio support for Blackfin"
depends on SND_BF5XX_I2S
select SND_BF5XX_SOC_I2S
- select SND_SOC_AD193X
+ select SND_SOC_AD193X_I2C if I2C
+ select SND_SOC_AD193X_SPI if SPI_MASTER
help
Say Y if you want to add support for AD193X codec on Blackfin.
This driver supports AD1936, AD1937, AD1938 and AD1939.
diff --git a/sound/soc/cirrus/Kconfig b/sound/soc/cirrus/Kconfig
index 06f938d..a0bf4a6 100644
--- a/sound/soc/cirrus/Kconfig
+++ b/sound/soc/cirrus/Kconfig
@@ -18,7 +18,7 @@
tristate "SoC Audio support for Bluewater Systems Snapper CL15 module"
depends on SND_EP93XX_SOC && MACH_SNAPPER_CL15
select SND_EP93XX_SOC_I2S
- select SND_SOC_TLV320AIC23
+ select SND_SOC_TLV320AIC23_I2C
help
Say Y or M here if you want to add support for I2S audio on the
Bluewater Systems Snapper CL15 module.
diff --git a/sound/soc/codecs/88pm860x-codec.c b/sound/soc/codecs/88pm860x-codec.c
index 75d0ad5..647a72c 100644
--- a/sound/soc/codecs/88pm860x-codec.c
+++ b/sound/soc/codecs/88pm860x-codec.c
@@ -1328,6 +1328,9 @@
pm860x->codec = codec;
codec->control_data = pm860x->regmap;
+ ret = snd_soc_codec_set_cache_io(codec, 0, 0, SND_SOC_REGMAP);
+ if (ret)
+ return ret;
for (i = 0; i < 4; i++) {
ret = request_threaded_irq(pm860x->irq[i], NULL,
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
index 983d087a..555f32f 100644
--- a/sound/soc/codecs/Kconfig
+++ b/sound/soc/codecs/Kconfig
@@ -16,7 +16,8 @@
select SND_SOC_AB8500_CODEC if ABX500_CORE
select SND_SOC_AC97_CODEC if SND_SOC_AC97_BUS
select SND_SOC_AD1836 if SPI_MASTER
- select SND_SOC_AD193X if SND_SOC_I2C_AND_SPI
+ select SND_SOC_AD193X_SPI if SPI_MASTER
+ select SND_SOC_AD193X_I2C if I2C
select SND_SOC_AD1980 if SND_SOC_AC97_BUS
select SND_SOC_AD73311
select SND_SOC_ADAU1373 if I2C
@@ -71,7 +72,8 @@
select SND_SOC_STA529 if I2C
select SND_SOC_STAC9766 if SND_SOC_AC97_BUS
select SND_SOC_TAS5086 if I2C
- select SND_SOC_TLV320AIC23 if I2C
+ select SND_SOC_TLV320AIC23_I2C if I2C
+ select SND_SOC_TLV320AIC23_SPI if SPI_MASTER
select SND_SOC_TLV320AIC26 if SPI_MASTER
select SND_SOC_TLV320AIC32X4 if I2C
select SND_SOC_TLV320AIC3X if I2C
@@ -182,6 +184,14 @@
config SND_SOC_AD193X
tristate
+config SND_SOC_AD193X_SPI
+ tristate
+ select SND_SOC_AD193X
+
+config SND_SOC_AD193X_I2C
+ tristate
+ select SND_SOC_AD193X
+
config SND_SOC_AD1980
tristate
@@ -357,6 +367,14 @@
config SND_SOC_TLV320AIC23
tristate
+config SND_SOC_TLV320AIC23_I2C
+ tristate
+ select SND_SOC_TLV320AIC23
+
+config SND_SOC_TLV320AIC23_SPI
+ tristate
+ select SND_SOC_TLV320AIC23
+
config SND_SOC_TLV320AIC26
tristate
depends on SPI
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile
index 1deeb20..bfda5c6 100644
--- a/sound/soc/codecs/Makefile
+++ b/sound/soc/codecs/Makefile
@@ -3,6 +3,8 @@
snd-soc-ac97-objs := ac97.o
snd-soc-ad1836-objs := ad1836.o
snd-soc-ad193x-objs := ad193x.o
+snd-soc-ad193x-spi-objs := ad193x-spi.o
+snd-soc-ad193x-i2c-objs := ad193x-i2c.o
snd-soc-ad1980-objs := ad1980.o
snd-soc-ad73311-objs := ad73311.o
snd-soc-adau1701-objs := adau1701.o
@@ -63,6 +65,8 @@
snd-soc-stac9766-objs := stac9766.o
snd-soc-tas5086-objs := tas5086.o
snd-soc-tlv320aic23-objs := tlv320aic23.o
+snd-soc-tlv320aic23-i2c-objs := tlv320aic23-i2c.o
+snd-soc-tlv320aic23-spi-objs := tlv320aic23-spi.o
snd-soc-tlv320aic26-objs := tlv320aic26.o
snd-soc-tlv320aic32x4-objs := tlv320aic32x4.o
snd-soc-tlv320aic3x-objs := tlv320aic3x.o
@@ -134,6 +138,8 @@
obj-$(CONFIG_SND_SOC_AC97_CODEC) += snd-soc-ac97.o
obj-$(CONFIG_SND_SOC_AD1836) += snd-soc-ad1836.o
obj-$(CONFIG_SND_SOC_AD193X) += snd-soc-ad193x.o
+obj-$(CONFIG_SND_SOC_AD193X_SPI) += snd-soc-ad193x-spi.o
+obj-$(CONFIG_SND_SOC_AD193X_I2C) += snd-soc-ad193x-i2c.o
obj-$(CONFIG_SND_SOC_AD1980) += snd-soc-ad1980.o
obj-$(CONFIG_SND_SOC_AD73311) += snd-soc-ad73311.o
obj-$(CONFIG_SND_SOC_ADAU1373) += snd-soc-adau1373.o
@@ -193,6 +199,8 @@
obj-$(CONFIG_SND_SOC_STAC9766) += snd-soc-stac9766.o
obj-$(CONFIG_SND_SOC_TAS5086) += snd-soc-tas5086.o
obj-$(CONFIG_SND_SOC_TLV320AIC23) += snd-soc-tlv320aic23.o
+obj-$(CONFIG_SND_SOC_TLV320AIC23_I2C) += snd-soc-tlv320aic23-i2c.o
+obj-$(CONFIG_SND_SOC_TLV320AIC23_SPI) += snd-soc-tlv320aic23-spi.o
obj-$(CONFIG_SND_SOC_TLV320AIC26) += snd-soc-tlv320aic26.o
obj-$(CONFIG_SND_SOC_TLV320AIC32X4) += snd-soc-tlv320aic32x4.o
obj-$(CONFIG_SND_SOC_TLV320AIC3X) += snd-soc-tlv320aic3x.o
diff --git a/sound/soc/codecs/ad193x-i2c.c b/sound/soc/codecs/ad193x-i2c.c
new file mode 100644
index 0000000..df3a1a4
--- /dev/null
+++ b/sound/soc/codecs/ad193x-i2c.c
@@ -0,0 +1,54 @@
+/*
+ * AD1936/AD1937 audio driver
+ *
+ * Copyright 2014 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2.
+ */
+
+#include <linux/module.h>
+#include <linux/i2c.h>
+#include <linux/regmap.h>
+
+#include <sound/soc.h>
+
+#include "ad193x.h"
+
+static const struct i2c_device_id ad193x_id[] = {
+ { "ad1936", 0 },
+ { "ad1937", 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, ad193x_id);
+
+static int ad193x_i2c_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct regmap_config config;
+
+ config = ad193x_regmap_config;
+ config.val_bits = 8;
+ config.reg_bits = 8;
+
+ return ad193x_probe(&client->dev, devm_regmap_init_i2c(client, &config));
+}
+
+static int ad193x_i2c_remove(struct i2c_client *client)
+{
+ snd_soc_unregister_codec(&client->dev);
+ return 0;
+}
+
+static struct i2c_driver ad193x_i2c_driver = {
+ .driver = {
+ .name = "ad193x",
+ },
+ .probe = ad193x_i2c_probe,
+ .remove = ad193x_i2c_remove,
+ .id_table = ad193x_id,
+};
+module_i2c_driver(ad193x_i2c_driver);
+
+MODULE_DESCRIPTION("ASoC AD1936/AD1937 audio CODEC driver");
+MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/ad193x-spi.c b/sound/soc/codecs/ad193x-spi.c
new file mode 100644
index 0000000..390cef9
--- /dev/null
+++ b/sound/soc/codecs/ad193x-spi.c
@@ -0,0 +1,48 @@
+/*
+ * AD1938/AD1939 audio driver
+ *
+ * Copyright 2014 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2.
+ */
+
+#include <linux/module.h>
+#include <linux/spi/spi.h>
+#include <linux/regmap.h>
+
+#include <sound/soc.h>
+
+#include "ad193x.h"
+
+static int ad193x_spi_probe(struct spi_device *spi)
+{
+ struct regmap_config config;
+
+ config = ad193x_regmap_config;
+ config.val_bits = 8;
+ config.reg_bits = 16;
+ config.read_flag_mask = 0x09;
+ config.write_flag_mask = 0x08;
+
+ return ad193x_probe(&spi->dev, devm_regmap_init_spi(spi, &config));
+}
+
+static int ad193x_spi_remove(struct spi_device *spi)
+{
+ snd_soc_unregister_codec(&spi->dev);
+ return 0;
+}
+
+static struct spi_driver ad193x_spi_driver = {
+ .driver = {
+ .name = "ad193x",
+ .owner = THIS_MODULE,
+ },
+ .probe = ad193x_spi_probe,
+ .remove = ad193x_spi_remove,
+};
+module_spi_driver(ad193x_spi_driver);
+
+MODULE_DESCRIPTION("ASoC AD1938/AD1939 audio CODEC driver");
+MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/ad193x.c b/sound/soc/codecs/ad193x.c
index 5a42dca..9381a76 100644
--- a/sound/soc/codecs/ad193x.c
+++ b/sound/soc/codecs/ad193x.c
@@ -6,12 +6,10 @@
* Licensed under the GPL-2 or later.
*/
-#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/device.h>
-#include <linux/i2c.h>
-#include <linux/spi/spi.h>
+#include <linux/regmap.h>
#include <linux/slab.h>
#include <sound/core.h>
#include <sound/pcm.h>
@@ -19,6 +17,7 @@
#include <sound/initval.h>
#include <sound/soc.h>
#include <sound/tlv.h>
+
#include "ad193x.h"
/* codec private data */
@@ -32,8 +31,8 @@
*/
static const char * const ad193x_deemp[] = {"None", "48kHz", "44.1kHz", "32kHz"};
-static const struct soc_enum ad193x_deemp_enum =
- SOC_ENUM_SINGLE(AD193X_DAC_CTRL2, 1, 4, ad193x_deemp);
+static SOC_ENUM_SINGLE_DECL(ad193x_deemp_enum, AD193X_DAC_CTRL2, 1,
+ ad193x_deemp);
static const DECLARE_TLV_DB_MINMAX(adau193x_tlv, -9563, 0);
@@ -320,7 +319,7 @@
.ops = &ad193x_dai_ops,
};
-static int ad193x_probe(struct snd_soc_codec *codec)
+static int ad193x_codec_probe(struct snd_soc_codec *codec)
{
struct ad193x_priv *ad193x = snd_soc_codec_get_drvdata(codec);
int ret;
@@ -352,7 +351,7 @@
}
static struct snd_soc_codec_driver soc_codec_dev_ad193x = {
- .probe = ad193x_probe,
+ .probe = ad193x_codec_probe,
.controls = ad193x_snd_controls,
.num_controls = ARRAY_SIZE(ad193x_snd_controls),
.dapm_widgets = ad193x_dapm_widgets,
@@ -366,140 +365,31 @@
return false;
}
-#if defined(CONFIG_SPI_MASTER)
-
-static const struct regmap_config ad193x_spi_regmap_config = {
- .val_bits = 8,
- .reg_bits = 16,
- .read_flag_mask = 0x09,
- .write_flag_mask = 0x08,
-
+const struct regmap_config ad193x_regmap_config = {
.max_register = AD193X_NUM_REGS - 1,
.volatile_reg = adau193x_reg_volatile,
};
+EXPORT_SYMBOL_GPL(ad193x_regmap_config);
-static int ad193x_spi_probe(struct spi_device *spi)
+int ad193x_probe(struct device *dev, struct regmap *regmap)
{
struct ad193x_priv *ad193x;
- ad193x = devm_kzalloc(&spi->dev, sizeof(struct ad193x_priv),
- GFP_KERNEL);
+ if (IS_ERR(regmap))
+ return PTR_ERR(regmap);
+
+ ad193x = devm_kzalloc(dev, sizeof(*ad193x), GFP_KERNEL);
if (ad193x == NULL)
return -ENOMEM;
- ad193x->regmap = devm_regmap_init_spi(spi, &ad193x_spi_regmap_config);
- if (IS_ERR(ad193x->regmap))
- return PTR_ERR(ad193x->regmap);
+ ad193x->regmap = regmap;
- spi_set_drvdata(spi, ad193x);
+ dev_set_drvdata(dev, ad193x);
- return snd_soc_register_codec(&spi->dev, &soc_codec_dev_ad193x,
- &ad193x_dai, 1);
+ return snd_soc_register_codec(dev, &soc_codec_dev_ad193x,
+ &ad193x_dai, 1);
}
-
-static int ad193x_spi_remove(struct spi_device *spi)
-{
- snd_soc_unregister_codec(&spi->dev);
- return 0;
-}
-
-static struct spi_driver ad193x_spi_driver = {
- .driver = {
- .name = "ad193x",
- .owner = THIS_MODULE,
- },
- .probe = ad193x_spi_probe,
- .remove = ad193x_spi_remove,
-};
-#endif
-
-#if IS_ENABLED(CONFIG_I2C)
-
-static const struct regmap_config ad193x_i2c_regmap_config = {
- .val_bits = 8,
- .reg_bits = 8,
-
- .max_register = AD193X_NUM_REGS - 1,
- .volatile_reg = adau193x_reg_volatile,
-};
-
-static const struct i2c_device_id ad193x_id[] = {
- { "ad1936", 0 },
- { "ad1937", 0 },
- { }
-};
-MODULE_DEVICE_TABLE(i2c, ad193x_id);
-
-static int ad193x_i2c_probe(struct i2c_client *client,
- const struct i2c_device_id *id)
-{
- struct ad193x_priv *ad193x;
-
- ad193x = devm_kzalloc(&client->dev, sizeof(struct ad193x_priv),
- GFP_KERNEL);
- if (ad193x == NULL)
- return -ENOMEM;
-
- ad193x->regmap = devm_regmap_init_i2c(client, &ad193x_i2c_regmap_config);
- if (IS_ERR(ad193x->regmap))
- return PTR_ERR(ad193x->regmap);
-
- i2c_set_clientdata(client, ad193x);
-
- return snd_soc_register_codec(&client->dev, &soc_codec_dev_ad193x,
- &ad193x_dai, 1);
-}
-
-static int ad193x_i2c_remove(struct i2c_client *client)
-{
- snd_soc_unregister_codec(&client->dev);
- return 0;
-}
-
-static struct i2c_driver ad193x_i2c_driver = {
- .driver = {
- .name = "ad193x",
- },
- .probe = ad193x_i2c_probe,
- .remove = ad193x_i2c_remove,
- .id_table = ad193x_id,
-};
-#endif
-
-static int __init ad193x_modinit(void)
-{
- int ret;
-
-#if IS_ENABLED(CONFIG_I2C)
- ret = i2c_add_driver(&ad193x_i2c_driver);
- if (ret != 0) {
- printk(KERN_ERR "Failed to register AD193X I2C driver: %d\n",
- ret);
- }
-#endif
-
-#if defined(CONFIG_SPI_MASTER)
- ret = spi_register_driver(&ad193x_spi_driver);
- if (ret != 0) {
- printk(KERN_ERR "Failed to register AD193X SPI driver: %d\n",
- ret);
- }
-#endif
- return ret;
-}
-module_init(ad193x_modinit);
-
-static void __exit ad193x_modexit(void)
-{
-#if defined(CONFIG_SPI_MASTER)
- spi_unregister_driver(&ad193x_spi_driver);
-#endif
-
-#if IS_ENABLED(CONFIG_I2C)
- i2c_del_driver(&ad193x_i2c_driver);
-#endif
-}
-module_exit(ad193x_modexit);
+EXPORT_SYMBOL_GPL(ad193x_probe);
MODULE_DESCRIPTION("ASoC ad193x driver");
MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>");
diff --git a/sound/soc/codecs/ad193x.h b/sound/soc/codecs/ad193x.h
index 4733880..ab9a998 100644
--- a/sound/soc/codecs/ad193x.h
+++ b/sound/soc/codecs/ad193x.h
@@ -9,6 +9,13 @@
#ifndef __AD193X_H__
#define __AD193X_H__
+#include <linux/regmap.h>
+
+struct device;
+
+extern const struct regmap_config ad193x_regmap_config;
+int ad193x_probe(struct device *dev, struct regmap *regmap);
+
#define AD193X_PLL_CLK_CTRL0 0x00
#define AD193X_PLL_POWERDOWN 0x01
#define AD193X_PLL_INPUT_MASK 0x6
diff --git a/sound/soc/codecs/ak4671.c b/sound/soc/codecs/ak4671.c
index 25bdf6a..deb2b44 100644
--- a/sound/soc/codecs/ak4671.c
+++ b/sound/soc/codecs/ak4671.c
@@ -15,6 +15,7 @@
#include <linux/init.h>
#include <linux/i2c.h>
#include <linux/delay.h>
+#include <linux/regmap.h>
#include <linux/slab.h>
#include <sound/soc.h>
#include <sound/initval.h>
@@ -23,104 +24,99 @@
#include "ak4671.h"
-/* codec private data */
-struct ak4671_priv {
- enum snd_soc_control_type control_type;
-};
-
/* ak4671 register cache & default register settings */
-static const u8 ak4671_reg[AK4671_CACHEREGNUM] = {
- 0x00, /* AK4671_AD_DA_POWER_MANAGEMENT (0x00) */
- 0xf6, /* AK4671_PLL_MODE_SELECT0 (0x01) */
- 0x00, /* AK4671_PLL_MODE_SELECT1 (0x02) */
- 0x02, /* AK4671_FORMAT_SELECT (0x03) */
- 0x00, /* AK4671_MIC_SIGNAL_SELECT (0x04) */
- 0x55, /* AK4671_MIC_AMP_GAIN (0x05) */
- 0x00, /* AK4671_MIXING_POWER_MANAGEMENT0 (0x06) */
- 0x00, /* AK4671_MIXING_POWER_MANAGEMENT1 (0x07) */
- 0xb5, /* AK4671_OUTPUT_VOLUME_CONTROL (0x08) */
- 0x00, /* AK4671_LOUT1_SIGNAL_SELECT (0x09) */
- 0x00, /* AK4671_ROUT1_SIGNAL_SELECT (0x0a) */
- 0x00, /* AK4671_LOUT2_SIGNAL_SELECT (0x0b) */
- 0x00, /* AK4671_ROUT2_SIGNAL_SELECT (0x0c) */
- 0x00, /* AK4671_LOUT3_SIGNAL_SELECT (0x0d) */
- 0x00, /* AK4671_ROUT3_SIGNAL_SELECT (0x0e) */
- 0x00, /* AK4671_LOUT1_POWER_MANAGERMENT (0x0f) */
- 0x00, /* AK4671_LOUT2_POWER_MANAGERMENT (0x10) */
- 0x80, /* AK4671_LOUT3_POWER_MANAGERMENT (0x11) */
- 0x91, /* AK4671_LCH_INPUT_VOLUME_CONTROL (0x12) */
- 0x91, /* AK4671_RCH_INPUT_VOLUME_CONTROL (0x13) */
- 0xe1, /* AK4671_ALC_REFERENCE_SELECT (0x14) */
- 0x00, /* AK4671_DIGITAL_MIXING_CONTROL (0x15) */
- 0x00, /* AK4671_ALC_TIMER_SELECT (0x16) */
- 0x00, /* AK4671_ALC_MODE_CONTROL (0x17) */
- 0x02, /* AK4671_MODE_CONTROL1 (0x18) */
- 0x01, /* AK4671_MODE_CONTROL2 (0x19) */
- 0x18, /* AK4671_LCH_OUTPUT_VOLUME_CONTROL (0x1a) */
- 0x18, /* AK4671_RCH_OUTPUT_VOLUME_CONTROL (0x1b) */
- 0x00, /* AK4671_SIDETONE_A_CONTROL (0x1c) */
- 0x02, /* AK4671_DIGITAL_FILTER_SELECT (0x1d) */
- 0x00, /* AK4671_FIL3_COEFFICIENT0 (0x1e) */
- 0x00, /* AK4671_FIL3_COEFFICIENT1 (0x1f) */
- 0x00, /* AK4671_FIL3_COEFFICIENT2 (0x20) */
- 0x00, /* AK4671_FIL3_COEFFICIENT3 (0x21) */
- 0x00, /* AK4671_EQ_COEFFICIENT0 (0x22) */
- 0x00, /* AK4671_EQ_COEFFICIENT1 (0x23) */
- 0x00, /* AK4671_EQ_COEFFICIENT2 (0x24) */
- 0x00, /* AK4671_EQ_COEFFICIENT3 (0x25) */
- 0x00, /* AK4671_EQ_COEFFICIENT4 (0x26) */
- 0x00, /* AK4671_EQ_COEFFICIENT5 (0x27) */
- 0xa9, /* AK4671_FIL1_COEFFICIENT0 (0x28) */
- 0x1f, /* AK4671_FIL1_COEFFICIENT1 (0x29) */
- 0xad, /* AK4671_FIL1_COEFFICIENT2 (0x2a) */
- 0x20, /* AK4671_FIL1_COEFFICIENT3 (0x2b) */
- 0x00, /* AK4671_FIL2_COEFFICIENT0 (0x2c) */
- 0x00, /* AK4671_FIL2_COEFFICIENT1 (0x2d) */
- 0x00, /* AK4671_FIL2_COEFFICIENT2 (0x2e) */
- 0x00, /* AK4671_FIL2_COEFFICIENT3 (0x2f) */
- 0x00, /* AK4671_DIGITAL_FILTER_SELECT2 (0x30) */
- 0x00, /* this register not used */
- 0x00, /* AK4671_E1_COEFFICIENT0 (0x32) */
- 0x00, /* AK4671_E1_COEFFICIENT1 (0x33) */
- 0x00, /* AK4671_E1_COEFFICIENT2 (0x34) */
- 0x00, /* AK4671_E1_COEFFICIENT3 (0x35) */
- 0x00, /* AK4671_E1_COEFFICIENT4 (0x36) */
- 0x00, /* AK4671_E1_COEFFICIENT5 (0x37) */
- 0x00, /* AK4671_E2_COEFFICIENT0 (0x38) */
- 0x00, /* AK4671_E2_COEFFICIENT1 (0x39) */
- 0x00, /* AK4671_E2_COEFFICIENT2 (0x3a) */
- 0x00, /* AK4671_E2_COEFFICIENT3 (0x3b) */
- 0x00, /* AK4671_E2_COEFFICIENT4 (0x3c) */
- 0x00, /* AK4671_E2_COEFFICIENT5 (0x3d) */
- 0x00, /* AK4671_E3_COEFFICIENT0 (0x3e) */
- 0x00, /* AK4671_E3_COEFFICIENT1 (0x3f) */
- 0x00, /* AK4671_E3_COEFFICIENT2 (0x40) */
- 0x00, /* AK4671_E3_COEFFICIENT3 (0x41) */
- 0x00, /* AK4671_E3_COEFFICIENT4 (0x42) */
- 0x00, /* AK4671_E3_COEFFICIENT5 (0x43) */
- 0x00, /* AK4671_E4_COEFFICIENT0 (0x44) */
- 0x00, /* AK4671_E4_COEFFICIENT1 (0x45) */
- 0x00, /* AK4671_E4_COEFFICIENT2 (0x46) */
- 0x00, /* AK4671_E4_COEFFICIENT3 (0x47) */
- 0x00, /* AK4671_E4_COEFFICIENT4 (0x48) */
- 0x00, /* AK4671_E4_COEFFICIENT5 (0x49) */
- 0x00, /* AK4671_E5_COEFFICIENT0 (0x4a) */
- 0x00, /* AK4671_E5_COEFFICIENT1 (0x4b) */
- 0x00, /* AK4671_E5_COEFFICIENT2 (0x4c) */
- 0x00, /* AK4671_E5_COEFFICIENT3 (0x4d) */
- 0x00, /* AK4671_E5_COEFFICIENT4 (0x4e) */
- 0x00, /* AK4671_E5_COEFFICIENT5 (0x4f) */
- 0x88, /* AK4671_EQ_CONTROL_250HZ_100HZ (0x50) */
- 0x88, /* AK4671_EQ_CONTROL_3500HZ_1KHZ (0x51) */
- 0x08, /* AK4671_EQ_CONTRO_10KHZ (0x52) */
- 0x00, /* AK4671_PCM_IF_CONTROL0 (0x53) */
- 0x00, /* AK4671_PCM_IF_CONTROL1 (0x54) */
- 0x00, /* AK4671_PCM_IF_CONTROL2 (0x55) */
- 0x18, /* AK4671_DIGITAL_VOLUME_B_CONTROL (0x56) */
- 0x18, /* AK4671_DIGITAL_VOLUME_C_CONTROL (0x57) */
- 0x00, /* AK4671_SIDETONE_VOLUME_CONTROL (0x58) */
- 0x00, /* AK4671_DIGITAL_MIXING_CONTROL2 (0x59) */
- 0x00, /* AK4671_SAR_ADC_CONTROL (0x5a) */
+static const struct reg_default ak4671_reg_defaults[] = {
+ { 0x00, 0x00 }, /* AK4671_AD_DA_POWER_MANAGEMENT (0x00) */
+ { 0x01, 0xf6 }, /* AK4671_PLL_MODE_SELECT0 (0x01) */
+ { 0x02, 0x00 }, /* AK4671_PLL_MODE_SELECT1 (0x02) */
+ { 0x03, 0x02 }, /* AK4671_FORMAT_SELECT (0x03) */
+ { 0x04, 0x00 }, /* AK4671_MIC_SIGNAL_SELECT (0x04) */
+ { 0x05, 0x55 }, /* AK4671_MIC_AMP_GAIN (0x05) */
+ { 0x06, 0x00 }, /* AK4671_MIXING_POWER_MANAGEMENT0 (0x06) */
+ { 0x07, 0x00 }, /* AK4671_MIXING_POWER_MANAGEMENT1 (0x07) */
+ { 0x08, 0xb5 }, /* AK4671_OUTPUT_VOLUME_CONTROL (0x08) */
+ { 0x09, 0x00 }, /* AK4671_LOUT1_SIGNAL_SELECT (0x09) */
+ { 0x0a, 0x00 }, /* AK4671_ROUT1_SIGNAL_SELECT (0x0a) */
+ { 0x0b, 0x00 }, /* AK4671_LOUT2_SIGNAL_SELECT (0x0b) */
+ { 0x0c, 0x00 }, /* AK4671_ROUT2_SIGNAL_SELECT (0x0c) */
+ { 0x0d, 0x00 }, /* AK4671_LOUT3_SIGNAL_SELECT (0x0d) */
+ { 0x0e, 0x00 }, /* AK4671_ROUT3_SIGNAL_SELECT (0x0e) */
+ { 0x0f, 0x00 }, /* AK4671_LOUT1_POWER_MANAGERMENT (0x0f) */
+ { 0x10, 0x00 }, /* AK4671_LOUT2_POWER_MANAGERMENT (0x10) */
+ { 0x11, 0x80 }, /* AK4671_LOUT3_POWER_MANAGERMENT (0x11) */
+ { 0x12, 0x91 }, /* AK4671_LCH_INPUT_VOLUME_CONTROL (0x12) */
+ { 0x13, 0x91 }, /* AK4671_RCH_INPUT_VOLUME_CONTROL (0x13) */
+ { 0x14, 0xe1 }, /* AK4671_ALC_REFERENCE_SELECT (0x14) */
+ { 0x15, 0x00 }, /* AK4671_DIGITAL_MIXING_CONTROL (0x15) */
+ { 0x16, 0x00 }, /* AK4671_ALC_TIMER_SELECT (0x16) */
+ { 0x17, 0x00 }, /* AK4671_ALC_MODE_CONTROL (0x17) */
+ { 0x18, 0x02 }, /* AK4671_MODE_CONTROL1 (0x18) */
+ { 0x19, 0x01 }, /* AK4671_MODE_CONTROL2 (0x19) */
+ { 0x1a, 0x18 }, /* AK4671_LCH_OUTPUT_VOLUME_CONTROL (0x1a) */
+ { 0x1b, 0x18 }, /* AK4671_RCH_OUTPUT_VOLUME_CONTROL (0x1b) */
+ { 0x1c, 0x00 }, /* AK4671_SIDETONE_A_CONTROL (0x1c) */
+ { 0x1d, 0x02 }, /* AK4671_DIGITAL_FILTER_SELECT (0x1d) */
+ { 0x1e, 0x00 }, /* AK4671_FIL3_COEFFICIENT0 (0x1e) */
+ { 0x1f, 0x00 }, /* AK4671_FIL3_COEFFICIENT1 (0x1f) */
+ { 0x20, 0x00 }, /* AK4671_FIL3_COEFFICIENT2 (0x20) */
+ { 0x21, 0x00 }, /* AK4671_FIL3_COEFFICIENT3 (0x21) */
+ { 0x22, 0x00 }, /* AK4671_EQ_COEFFICIENT0 (0x22) */
+ { 0x23, 0x00 }, /* AK4671_EQ_COEFFICIENT1 (0x23) */
+ { 0x24, 0x00 }, /* AK4671_EQ_COEFFICIENT2 (0x24) */
+ { 0x25, 0x00 }, /* AK4671_EQ_COEFFICIENT3 (0x25) */
+ { 0x26, 0x00 }, /* AK4671_EQ_COEFFICIENT4 (0x26) */
+ { 0x27, 0x00 }, /* AK4671_EQ_COEFFICIENT5 (0x27) */
+ { 0x28, 0xa9 }, /* AK4671_FIL1_COEFFICIENT0 (0x28) */
+ { 0x29, 0x1f }, /* AK4671_FIL1_COEFFICIENT1 (0x29) */
+ { 0x2a, 0xad }, /* AK4671_FIL1_COEFFICIENT2 (0x2a) */
+ { 0x2b, 0x20 }, /* AK4671_FIL1_COEFFICIENT3 (0x2b) */
+ { 0x2c, 0x00 }, /* AK4671_FIL2_COEFFICIENT0 (0x2c) */
+ { 0x2d, 0x00 }, /* AK4671_FIL2_COEFFICIENT1 (0x2d) */
+ { 0x2e, 0x00 }, /* AK4671_FIL2_COEFFICIENT2 (0x2e) */
+ { 0x2f, 0x00 }, /* AK4671_FIL2_COEFFICIENT3 (0x2f) */
+ { 0x30, 0x00 }, /* AK4671_DIGITAL_FILTER_SELECT2 (0x30) */
+
+ { 0x32, 0x00 }, /* AK4671_E1_COEFFICIENT0 (0x32) */
+ { 0x33, 0x00 }, /* AK4671_E1_COEFFICIENT1 (0x33) */
+ { 0x34, 0x00 }, /* AK4671_E1_COEFFICIENT2 (0x34) */
+ { 0x35, 0x00 }, /* AK4671_E1_COEFFICIENT3 (0x35) */
+ { 0x36, 0x00 }, /* AK4671_E1_COEFFICIENT4 (0x36) */
+ { 0x37, 0x00 }, /* AK4671_E1_COEFFICIENT5 (0x37) */
+ { 0x38, 0x00 }, /* AK4671_E2_COEFFICIENT0 (0x38) */
+ { 0x39, 0x00 }, /* AK4671_E2_COEFFICIENT1 (0x39) */
+ { 0x3a, 0x00 }, /* AK4671_E2_COEFFICIENT2 (0x3a) */
+ { 0x3b, 0x00 }, /* AK4671_E2_COEFFICIENT3 (0x3b) */
+ { 0x3c, 0x00 }, /* AK4671_E2_COEFFICIENT4 (0x3c) */
+ { 0x3d, 0x00 }, /* AK4671_E2_COEFFICIENT5 (0x3d) */
+ { 0x3e, 0x00 }, /* AK4671_E3_COEFFICIENT0 (0x3e) */
+ { 0x3f, 0x00 }, /* AK4671_E3_COEFFICIENT1 (0x3f) */
+ { 0x40, 0x00 }, /* AK4671_E3_COEFFICIENT2 (0x40) */
+ { 0x41, 0x00 }, /* AK4671_E3_COEFFICIENT3 (0x41) */
+ { 0x42, 0x00 }, /* AK4671_E3_COEFFICIENT4 (0x42) */
+ { 0x43, 0x00 }, /* AK4671_E3_COEFFICIENT5 (0x43) */
+ { 0x44, 0x00 }, /* AK4671_E4_COEFFICIENT0 (0x44) */
+ { 0x45, 0x00 }, /* AK4671_E4_COEFFICIENT1 (0x45) */
+ { 0x46, 0x00 }, /* AK4671_E4_COEFFICIENT2 (0x46) */
+ { 0x47, 0x00 }, /* AK4671_E4_COEFFICIENT3 (0x47) */
+ { 0x48, 0x00 }, /* AK4671_E4_COEFFICIENT4 (0x48) */
+ { 0x49, 0x00 }, /* AK4671_E4_COEFFICIENT5 (0x49) */
+ { 0x4a, 0x00 }, /* AK4671_E5_COEFFICIENT0 (0x4a) */
+ { 0x4b, 0x00 }, /* AK4671_E5_COEFFICIENT1 (0x4b) */
+ { 0x4c, 0x00 }, /* AK4671_E5_COEFFICIENT2 (0x4c) */
+ { 0x4d, 0x00 }, /* AK4671_E5_COEFFICIENT3 (0x4d) */
+ { 0x4e, 0x00 }, /* AK4671_E5_COEFFICIENT4 (0x4e) */
+ { 0x4f, 0x00 }, /* AK4671_E5_COEFFICIENT5 (0x4f) */
+ { 0x50, 0x88 }, /* AK4671_EQ_CONTROL_250HZ_100HZ (0x50) */
+ { 0x51, 0x88 }, /* AK4671_EQ_CONTROL_3500HZ_1KHZ (0x51) */
+ { 0x52, 0x08 }, /* AK4671_EQ_CONTRO_10KHZ (0x52) */
+ { 0x53, 0x00 }, /* AK4671_PCM_IF_CONTROL0 (0x53) */
+ { 0x54, 0x00 }, /* AK4671_PCM_IF_CONTROL1 (0x54) */
+ { 0x55, 0x00 }, /* AK4671_PCM_IF_CONTROL2 (0x55) */
+ { 0x56, 0x18 }, /* AK4671_DIGITAL_VOLUME_B_CONTROL (0x56) */
+ { 0x57, 0x18 }, /* AK4671_DIGITAL_VOLUME_C_CONTROL (0x57) */
+ { 0x58, 0x00 }, /* AK4671_SIDETONE_VOLUME_CONTROL (0x58) */
+ { 0x59, 0x00 }, /* AK4671_DIGITAL_MIXING_CONTROL2 (0x59) */
+ { 0x5a, 0x00 }, /* AK4671_SAR_ADC_CONTROL (0x5a) */
};
/*
@@ -241,19 +237,17 @@
/* Input MUXs */
static const char *ak4671_lin_mux_texts[] =
{"LIN1", "LIN2", "LIN3", "LIN4"};
-static const struct soc_enum ak4671_lin_mux_enum =
- SOC_ENUM_SINGLE(AK4671_MIC_SIGNAL_SELECT, 0,
- ARRAY_SIZE(ak4671_lin_mux_texts),
- ak4671_lin_mux_texts);
+static SOC_ENUM_SINGLE_DECL(ak4671_lin_mux_enum,
+ AK4671_MIC_SIGNAL_SELECT, 0,
+ ak4671_lin_mux_texts);
static const struct snd_kcontrol_new ak4671_lin_mux_control =
SOC_DAPM_ENUM("Route", ak4671_lin_mux_enum);
static const char *ak4671_rin_mux_texts[] =
{"RIN1", "RIN2", "RIN3", "RIN4"};
-static const struct soc_enum ak4671_rin_mux_enum =
- SOC_ENUM_SINGLE(AK4671_MIC_SIGNAL_SELECT, 2,
- ARRAY_SIZE(ak4671_rin_mux_texts),
- ak4671_rin_mux_texts);
+static SOC_ENUM_SINGLE_DECL(ak4671_rin_mux_enum,
+ AK4671_MIC_SIGNAL_SELECT, 2,
+ ak4671_rin_mux_texts);
static const struct snd_kcontrol_new ak4671_rin_mux_control =
SOC_DAPM_ENUM("Route", ak4671_rin_mux_enum);
@@ -619,18 +613,14 @@
static int ak4671_probe(struct snd_soc_codec *codec)
{
- struct ak4671_priv *ak4671 = snd_soc_codec_get_drvdata(codec);
int ret;
- ret = snd_soc_codec_set_cache_io(codec, 8, 8, ak4671->control_type);
+ ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP);
if (ret < 0) {
dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
return ret;
}
- snd_soc_add_codec_controls(codec, ak4671_snd_controls,
- ARRAY_SIZE(ak4671_snd_controls));
-
ak4671_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
return ret;
@@ -646,28 +636,36 @@
.probe = ak4671_probe,
.remove = ak4671_remove,
.set_bias_level = ak4671_set_bias_level,
- .reg_cache_size = AK4671_CACHEREGNUM,
- .reg_word_size = sizeof(u8),
- .reg_cache_default = ak4671_reg,
+ .controls = ak4671_snd_controls,
+ .num_controls = ARRAY_SIZE(ak4671_snd_controls),
.dapm_widgets = ak4671_dapm_widgets,
.num_dapm_widgets = ARRAY_SIZE(ak4671_dapm_widgets),
.dapm_routes = ak4671_intercon,
.num_dapm_routes = ARRAY_SIZE(ak4671_intercon),
};
+static const struct regmap_config ak4671_regmap = {
+ .reg_bits = 8,
+ .val_bits = 8,
+
+ .max_register = AK4671_SAR_ADC_CONTROL,
+ .reg_defaults = ak4671_reg_defaults,
+ .num_reg_defaults = ARRAY_SIZE(ak4671_reg_defaults),
+ .cache_type = REGCACHE_RBTREE,
+};
+
static int ak4671_i2c_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
- struct ak4671_priv *ak4671;
+ struct regmap *regmap;
int ret;
- ak4671 = devm_kzalloc(&client->dev, sizeof(struct ak4671_priv),
- GFP_KERNEL);
- if (ak4671 == NULL)
- return -ENOMEM;
-
- i2c_set_clientdata(client, ak4671);
- ak4671->control_type = SND_SOC_I2C;
+ regmap = devm_regmap_init_i2c(client, &ak4671_regmap);
+ if (IS_ERR(regmap)) {
+ ret = PTR_ERR(regmap);
+ dev_err(&client->dev, "Failed to create regmap: %d\n", ret);
+ return ret;
+ }
ret = snd_soc_register_codec(&client->dev,
&soc_codec_dev_ak4671, &ak4671_dai, 1);
diff --git a/sound/soc/codecs/ak4671.h b/sound/soc/codecs/ak4671.h
index 61cb7ab..394a34d 100644
--- a/sound/soc/codecs/ak4671.h
+++ b/sound/soc/codecs/ak4671.h
@@ -105,8 +105,6 @@
#define AK4671_DIGITAL_MIXING_CONTROL2 0x59
#define AK4671_SAR_ADC_CONTROL 0x5a
-#define AK4671_CACHEREGNUM (AK4671_SAR_ADC_CONTROL + 1)
-
/* Bitfield Definitions */
/* AK4671_AD_DA_POWER_MANAGEMENT (0x00) Fields */
diff --git a/sound/soc/codecs/alc5623.c b/sound/soc/codecs/alc5623.c
index d303628..ed50625 100644
--- a/sound/soc/codecs/alc5623.c
+++ b/sound/soc/codecs/alc5623.c
@@ -21,6 +21,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>
@@ -38,26 +39,13 @@
/* codec private data */
struct alc5623_priv {
- enum snd_soc_control_type control_type;
+ struct regmap *regmap;
u8 id;
unsigned int sysclk;
- u16 reg_cache[ALC5623_VENDOR_ID2+2];
unsigned int add_ctrl;
unsigned int jack_det_ctrl;
};
-static void alc5623_fill_cache(struct snd_soc_codec *codec)
-{
- int i, step = codec->driver->reg_cache_step;
- u16 *cache = codec->reg_cache;
-
- /* not really efficient ... */
- codec->cache_bypass = 1;
- for (i = 0 ; i < codec->driver->reg_cache_size ; i += step)
- cache[i] = snd_soc_read(codec, i);
- codec->cache_bypass = 0;
-}
-
static inline int alc5623_reset(struct snd_soc_codec *codec)
{
return snd_soc_write(codec, ALC5623_RESET, 0);
@@ -228,32 +216,37 @@
"Vmid", "HPOut Mix", "Speaker Mix", "Mono Mix"};
/* auxout output mux */
-static const struct soc_enum alc5623_aux_out_input_enum =
-SOC_ENUM_SINGLE(ALC5623_OUTPUT_MIXER_CTRL, 6, 4, alc5623_aux_out_input_sel);
+static SOC_ENUM_SINGLE_DECL(alc5623_aux_out_input_enum,
+ ALC5623_OUTPUT_MIXER_CTRL, 6,
+ alc5623_aux_out_input_sel);
static const struct snd_kcontrol_new alc5623_auxout_mux_controls =
SOC_DAPM_ENUM("Route", alc5623_aux_out_input_enum);
/* speaker output mux */
-static const struct soc_enum alc5623_spkout_input_enum =
-SOC_ENUM_SINGLE(ALC5623_OUTPUT_MIXER_CTRL, 10, 4, alc5623_spkout_input_sel);
+static SOC_ENUM_SINGLE_DECL(alc5623_spkout_input_enum,
+ ALC5623_OUTPUT_MIXER_CTRL, 10,
+ alc5623_spkout_input_sel);
static const struct snd_kcontrol_new alc5623_spkout_mux_controls =
SOC_DAPM_ENUM("Route", alc5623_spkout_input_enum);
/* headphone left output mux */
-static const struct soc_enum alc5623_hpl_out_input_enum =
-SOC_ENUM_SINGLE(ALC5623_OUTPUT_MIXER_CTRL, 9, 2, alc5623_hpl_out_input_sel);
+static SOC_ENUM_SINGLE_DECL(alc5623_hpl_out_input_enum,
+ ALC5623_OUTPUT_MIXER_CTRL, 9,
+ alc5623_hpl_out_input_sel);
static const struct snd_kcontrol_new alc5623_hpl_out_mux_controls =
SOC_DAPM_ENUM("Route", alc5623_hpl_out_input_enum);
/* headphone right output mux */
-static const struct soc_enum alc5623_hpr_out_input_enum =
-SOC_ENUM_SINGLE(ALC5623_OUTPUT_MIXER_CTRL, 8, 2, alc5623_hpr_out_input_sel);
+static SOC_ENUM_SINGLE_DECL(alc5623_hpr_out_input_enum,
+ ALC5623_OUTPUT_MIXER_CTRL, 8,
+ alc5623_hpr_out_input_sel);
static const struct snd_kcontrol_new alc5623_hpr_out_mux_controls =
SOC_DAPM_ENUM("Route", alc5623_hpr_out_input_enum);
/* speaker output N select */
-static const struct soc_enum alc5623_spk_n_sour_enum =
-SOC_ENUM_SINGLE(ALC5623_OUTPUT_MIXER_CTRL, 14, 4, alc5623_spk_n_sour_sel);
+static SOC_ENUM_SINGLE_DECL(alc5623_spk_n_sour_enum,
+ ALC5623_OUTPUT_MIXER_CTRL, 14,
+ alc5623_spk_n_sour_sel);
static const struct snd_kcontrol_new alc5623_spkoutn_mux_controls =
SOC_DAPM_ENUM("Route", alc5623_spk_n_sour_enum);
@@ -338,8 +331,9 @@
};
static const char *alc5623_amp_names[] = {"AB Amp", "D Amp"};
-static const struct soc_enum alc5623_amp_enum =
- SOC_ENUM_SINGLE(ALC5623_OUTPUT_MIXER_CTRL, 13, 2, alc5623_amp_names);
+static SOC_ENUM_SINGLE_DECL(alc5623_amp_enum,
+ ALC5623_OUTPUT_MIXER_CTRL, 13,
+ alc5623_amp_names);
static const struct snd_kcontrol_new alc5623_amp_mux_controls =
SOC_DAPM_ENUM("Route", alc5623_amp_enum);
@@ -869,18 +863,28 @@
static int alc5623_suspend(struct snd_soc_codec *codec)
{
+ struct alc5623_priv *alc5623 = snd_soc_codec_get_drvdata(codec);
+
alc5623_set_bias_level(codec, SND_SOC_BIAS_OFF);
+ regcache_cache_only(alc5623->regmap, true);
+
return 0;
}
static int alc5623_resume(struct snd_soc_codec *codec)
{
- int i, step = codec->driver->reg_cache_step;
- u16 *cache = codec->reg_cache;
+ struct alc5623_priv *alc5623 = snd_soc_codec_get_drvdata(codec);
+ int ret;
/* Sync reg_cache with the hardware */
- for (i = 2 ; i < codec->driver->reg_cache_size ; i += step)
- snd_soc_write(codec, i, cache[i]);
+ regcache_cache_only(alc5623->regmap, false);
+ ret = regcache_sync(alc5623->regmap);
+ if (ret != 0) {
+ dev_err(codec->dev, "Failed to sync register cache: %d\n",
+ ret);
+ regcache_cache_only(alc5623->regmap, true);
+ return ret;
+ }
alc5623_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
@@ -900,14 +904,14 @@
struct snd_soc_dapm_context *dapm = &codec->dapm;
int ret;
- ret = snd_soc_codec_set_cache_io(codec, 8, 16, alc5623->control_type);
+ codec->control_data = alc5623->regmap;
+ ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_REGMAP);
if (ret < 0) {
dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
return ret;
}
alc5623_reset(codec);
- alc5623_fill_cache(codec);
/* power on device */
alc5623_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
@@ -980,9 +984,15 @@
.suspend = alc5623_suspend,
.resume = alc5623_resume,
.set_bias_level = alc5623_set_bias_level,
- .reg_cache_size = ALC5623_VENDOR_ID2+2,
- .reg_word_size = sizeof(u16),
- .reg_cache_step = 2,
+};
+
+static const struct regmap_config alc5623_regmap = {
+ .reg_bits = 8,
+ .val_bits = 16,
+ .reg_stride = 2,
+
+ .max_register = ALC5623_VENDOR_ID2,
+ .cache_type = REGCACHE_RBTREE,
};
/*
@@ -996,19 +1006,32 @@
{
struct alc5623_platform_data *pdata;
struct alc5623_priv *alc5623;
- int ret, vid1, vid2;
+ unsigned int vid1, vid2;
+ int ret;
- vid1 = i2c_smbus_read_word_data(client, ALC5623_VENDOR_ID1);
- if (vid1 < 0) {
- dev_err(&client->dev, "failed to read I2C\n");
- return -EIO;
+ alc5623 = devm_kzalloc(&client->dev, sizeof(struct alc5623_priv),
+ GFP_KERNEL);
+ if (alc5623 == NULL)
+ return -ENOMEM;
+
+ alc5623->regmap = devm_regmap_init_i2c(client, &alc5623_regmap);
+ if (IS_ERR(alc5623->regmap)) {
+ ret = PTR_ERR(alc5623->regmap);
+ dev_err(&client->dev, "Failed to initialise I/O: %d\n", ret);
+ return ret;
+ }
+
+ ret = regmap_read(alc5623->regmap, ALC5623_VENDOR_ID1, &vid1);
+ if (ret < 0) {
+ dev_err(&client->dev, "failed to read vendor ID1: %d\n", ret);
+ return ret;
}
vid1 = ((vid1 & 0xff) << 8) | (vid1 >> 8);
- vid2 = i2c_smbus_read_byte_data(client, ALC5623_VENDOR_ID2);
- if (vid2 < 0) {
- dev_err(&client->dev, "failed to read I2C\n");
- return -EIO;
+ ret = regmap_read(alc5623->regmap, ALC5623_VENDOR_ID2, &vid2);
+ if (ret < 0) {
+ dev_err(&client->dev, "failed to read vendor ID2: %d\n", ret);
+ return ret;
}
if ((vid1 != 0x10ec) || (vid2 != id->driver_data)) {
@@ -1021,11 +1044,6 @@
dev_dbg(&client->dev, "Found codec id : alc56%02x\n", vid2);
- alc5623 = devm_kzalloc(&client->dev, sizeof(struct alc5623_priv),
- GFP_KERNEL);
- if (alc5623 == NULL)
- return -ENOMEM;
-
pdata = client->dev.platform_data;
if (pdata) {
alc5623->add_ctrl = pdata->add_ctrl;
@@ -1048,7 +1066,6 @@
}
i2c_set_clientdata(client, alc5623);
- alc5623->control_type = SND_SOC_I2C;
ret = snd_soc_register_codec(&client->dev,
&soc_codec_device_alc5623, &alc5623_dai, 1);
diff --git a/sound/soc/codecs/alc5632.c b/sound/soc/codecs/alc5632.c
index fb001c5..d885056 100644
--- a/sound/soc/codecs/alc5632.c
+++ b/sound/soc/codecs/alc5632.c
@@ -293,51 +293,59 @@
"ADC LR", "Voice Stereo Digital"};
/* auxout output mux */
-static const struct soc_enum alc5632_aux_out_input_enum =
-SOC_ENUM_SINGLE(ALC5632_OUTPUT_MIXER_CTRL, 6, 4, alc5632_aux_out_input_sel);
+static SOC_ENUM_SINGLE_DECL(alc5632_aux_out_input_enum,
+ ALC5632_OUTPUT_MIXER_CTRL, 6,
+ alc5632_aux_out_input_sel);
static const struct snd_kcontrol_new alc5632_auxout_mux_controls =
SOC_DAPM_ENUM("AuxOut Mux", alc5632_aux_out_input_enum);
/* speaker output mux */
-static const struct soc_enum alc5632_spkout_input_enum =
-SOC_ENUM_SINGLE(ALC5632_OUTPUT_MIXER_CTRL, 10, 4, alc5632_spkout_input_sel);
+static SOC_ENUM_SINGLE_DECL(alc5632_spkout_input_enum,
+ ALC5632_OUTPUT_MIXER_CTRL, 10,
+ alc5632_spkout_input_sel);
static const struct snd_kcontrol_new alc5632_spkout_mux_controls =
SOC_DAPM_ENUM("SpeakerOut Mux", alc5632_spkout_input_enum);
/* headphone left output mux */
-static const struct soc_enum alc5632_hpl_out_input_enum =
-SOC_ENUM_SINGLE(ALC5632_OUTPUT_MIXER_CTRL, 9, 2, alc5632_hpl_out_input_sel);
+static SOC_ENUM_SINGLE_DECL(alc5632_hpl_out_input_enum,
+ ALC5632_OUTPUT_MIXER_CTRL, 9,
+ alc5632_hpl_out_input_sel);
static const struct snd_kcontrol_new alc5632_hpl_out_mux_controls =
SOC_DAPM_ENUM("Left Headphone Mux", alc5632_hpl_out_input_enum);
/* headphone right output mux */
-static const struct soc_enum alc5632_hpr_out_input_enum =
-SOC_ENUM_SINGLE(ALC5632_OUTPUT_MIXER_CTRL, 8, 2, alc5632_hpr_out_input_sel);
+static SOC_ENUM_SINGLE_DECL(alc5632_hpr_out_input_enum,
+ ALC5632_OUTPUT_MIXER_CTRL, 8,
+ alc5632_hpr_out_input_sel);
static const struct snd_kcontrol_new alc5632_hpr_out_mux_controls =
SOC_DAPM_ENUM("Right Headphone Mux", alc5632_hpr_out_input_enum);
/* speaker output N select */
-static const struct soc_enum alc5632_spk_n_sour_enum =
-SOC_ENUM_SINGLE(ALC5632_OUTPUT_MIXER_CTRL, 14, 4, alc5632_spk_n_sour_sel);
+static SOC_ENUM_SINGLE_DECL(alc5632_spk_n_sour_enum,
+ ALC5632_OUTPUT_MIXER_CTRL, 14,
+ alc5632_spk_n_sour_sel);
static const struct snd_kcontrol_new alc5632_spkoutn_mux_controls =
SOC_DAPM_ENUM("SpeakerOut N Mux", alc5632_spk_n_sour_enum);
/* speaker amplifier */
static const char *alc5632_amp_names[] = {"AB Amp", "D Amp"};
-static const struct soc_enum alc5632_amp_enum =
- SOC_ENUM_SINGLE(ALC5632_OUTPUT_MIXER_CTRL, 13, 2, alc5632_amp_names);
+static SOC_ENUM_SINGLE_DECL(alc5632_amp_enum,
+ ALC5632_OUTPUT_MIXER_CTRL, 13,
+ alc5632_amp_names);
static const struct snd_kcontrol_new alc5632_amp_mux_controls =
SOC_DAPM_ENUM("AB-D Amp Mux", alc5632_amp_enum);
/* ADC output select */
-static const struct soc_enum alc5632_adcr_func_enum =
- SOC_ENUM_SINGLE(ALC5632_DAC_FUNC_SELECT, 5, 2, alc5632_adcr_func_sel);
+static SOC_ENUM_SINGLE_DECL(alc5632_adcr_func_enum,
+ ALC5632_DAC_FUNC_SELECT, 5,
+ alc5632_adcr_func_sel);
static const struct snd_kcontrol_new alc5632_adcr_func_controls =
SOC_DAPM_ENUM("ADCR Mux", alc5632_adcr_func_enum);
/* I2S out select */
-static const struct soc_enum alc5632_i2s_out_enum =
- SOC_ENUM_SINGLE(ALC5632_I2S_OUT_CTL, 5, 2, alc5632_i2s_out_sel);
+static SOC_ENUM_SINGLE_DECL(alc5632_i2s_out_enum,
+ ALC5632_I2S_OUT_CTL, 5,
+ alc5632_i2s_out_sel);
static const struct snd_kcontrol_new alc5632_i2s_out_controls =
SOC_DAPM_ENUM("I2SOut Mux", alc5632_i2s_out_enum);
diff --git a/sound/soc/codecs/cs42l51.c b/sound/soc/codecs/cs42l51.c
index 6e9ea83..3eab460 100644
--- a/sound/soc/codecs/cs42l51.c
+++ b/sound/soc/codecs/cs42l51.c
@@ -30,6 +30,7 @@
#include <sound/pcm_params.h>
#include <sound/pcm.h>
#include <linux/i2c.h>
+#include <linux/regmap.h>
#include "cs42l51.h"
@@ -40,7 +41,6 @@
};
struct cs42l51_private {
- enum snd_soc_control_type control_type;
unsigned int mclk;
unsigned int audio_mode; /* The mode (I2S or left-justified) */
enum master_slave_mode func;
@@ -52,24 +52,6 @@
SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S20_3BE | \
SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S24_BE)
-static int cs42l51_fill_cache(struct snd_soc_codec *codec)
-{
- u8 *cache = codec->reg_cache + 1;
- struct i2c_client *i2c_client = to_i2c_client(codec->dev);
- s32 length;
-
- length = i2c_smbus_read_i2c_block_data(i2c_client,
- CS42L51_FIRSTREG | 0x80, CS42L51_NUMREGS, cache);
- if (length != CS42L51_NUMREGS) {
- dev_err(&i2c_client->dev,
- "I2C read failure, addr=0x%x (ret=%d vs %d)\n",
- i2c_client->addr, length, CS42L51_NUMREGS);
- return -EIO;
- }
-
- return 0;
-}
-
static int cs42l51_get_chan_mix(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
@@ -505,16 +487,9 @@
static int cs42l51_probe(struct snd_soc_codec *codec)
{
- struct cs42l51_private *cs42l51 = snd_soc_codec_get_drvdata(codec);
int ret, reg;
- ret = cs42l51_fill_cache(codec);
- if (ret < 0) {
- dev_err(codec->dev, "failed to fill register cache\n");
- return ret;
- }
-
- ret = snd_soc_codec_set_cache_io(codec, 8, 8, cs42l51->control_type);
+ ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP);
if (ret < 0) {
dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
return ret;
@@ -538,8 +513,6 @@
static struct snd_soc_codec_driver soc_codec_device_cs42l51 = {
.probe = cs42l51_probe,
- .reg_cache_size = CS42L51_NUMREGS + 1,
- .reg_word_size = sizeof(u8),
.controls = cs42l51_snd_controls,
.num_controls = ARRAY_SIZE(cs42l51_snd_controls),
@@ -549,38 +522,53 @@
.num_dapm_routes = ARRAY_SIZE(cs42l51_routes),
};
+static const struct regmap_config cs42l51_regmap = {
+ .reg_bits = 8,
+ .val_bits = 8,
+
+ .max_register = CS42L51_CHARGE_FREQ,
+ .cache_type = REGCACHE_RBTREE,
+};
+
static int cs42l51_i2c_probe(struct i2c_client *i2c_client,
const struct i2c_device_id *id)
{
struct cs42l51_private *cs42l51;
+ struct regmap *regmap;
+ unsigned int val;
int ret;
+ regmap = devm_regmap_init_i2c(i2c_client, &cs42l51_regmap);
+ if (IS_ERR(regmap)) {
+ ret = PTR_ERR(regmap);
+ dev_err(&i2c_client->dev, "Failed to create regmap: %d\n",
+ ret);
+ return ret;
+ }
+
/* Verify that we have a CS42L51 */
- ret = i2c_smbus_read_byte_data(i2c_client, CS42L51_CHIP_REV_ID);
+ ret = regmap_read(regmap, CS42L51_CHIP_REV_ID, &val);
if (ret < 0) {
dev_err(&i2c_client->dev, "failed to read I2C\n");
goto error;
}
- if ((ret != CS42L51_MK_CHIP_REV(CS42L51_CHIP_ID, CS42L51_CHIP_REV_A)) &&
- (ret != CS42L51_MK_CHIP_REV(CS42L51_CHIP_ID, CS42L51_CHIP_REV_B))) {
- dev_err(&i2c_client->dev, "Invalid chip id\n");
+ if ((val != CS42L51_MK_CHIP_REV(CS42L51_CHIP_ID, CS42L51_CHIP_REV_A)) &&
+ (val != CS42L51_MK_CHIP_REV(CS42L51_CHIP_ID, CS42L51_CHIP_REV_B))) {
+ dev_err(&i2c_client->dev, "Invalid chip id: %x\n", val);
ret = -ENODEV;
goto error;
}
dev_info(&i2c_client->dev, "found device cs42l51 rev %d\n",
- ret & 7);
+ val & 7);
cs42l51 = devm_kzalloc(&i2c_client->dev, sizeof(struct cs42l51_private),
GFP_KERNEL);
- if (!cs42l51) {
- dev_err(&i2c_client->dev, "could not allocate codec\n");
+ if (!cs42l51)
return -ENOMEM;
- }
i2c_set_clientdata(i2c_client, cs42l51);
- cs42l51->control_type = SND_SOC_I2C;
ret = snd_soc_register_codec(&i2c_client->dev,
&soc_codec_device_cs42l51, &cs42l51_dai, 1);
@@ -600,10 +588,17 @@
};
MODULE_DEVICE_TABLE(i2c, cs42l51_id);
+static const struct of_device_id cs42l51_of_match[] = {
+ { .compatible = "cirrus,cs42l51", },
+ { }
+};
+MODULE_DEVICE_TABLE(of, cs42l51_of_match);
+
static struct i2c_driver cs42l51_i2c_driver = {
.driver = {
.name = "cs42l51-codec",
.owner = THIS_MODULE,
+ .of_match_table = cs42l51_of_match,
},
.id_table = cs42l51_id,
.probe = cs42l51_i2c_probe,
diff --git a/sound/soc/codecs/da732x.c b/sound/soc/codecs/da732x.c
index f295b65..8053e0e 100644
--- a/sound/soc/codecs/da732x.c
+++ b/sound/soc/codecs/da732x.c
@@ -1301,9 +1301,9 @@
msleep(DA732X_WAIT_FOR_STABILIZATION);
/* Check DAC offset sign */
- sign[DA732X_HPL_DAC] = (codec->hw_read(codec, DA732X_REG_HPL_DAC_OFF_CNTL) &
+ sign[DA732X_HPL_DAC] = (snd_soc_read(codec, DA732X_REG_HPL_DAC_OFF_CNTL) &
DA732X_HP_DAC_OFF_CNTL_COMPO);
- sign[DA732X_HPR_DAC] = (codec->hw_read(codec, DA732X_REG_HPR_DAC_OFF_CNTL) &
+ sign[DA732X_HPR_DAC] = (snd_soc_read(codec, DA732X_REG_HPR_DAC_OFF_CNTL) &
DA732X_HP_DAC_OFF_CNTL_COMPO);
/* Binary search DAC offset values (both channels at once) */
@@ -1320,10 +1320,10 @@
msleep(DA732X_WAIT_FOR_STABILIZATION);
- if ((codec->hw_read(codec, DA732X_REG_HPL_DAC_OFF_CNTL) &
+ if ((snd_soc_read(codec, DA732X_REG_HPL_DAC_OFF_CNTL) &
DA732X_HP_DAC_OFF_CNTL_COMPO) ^ sign[DA732X_HPL_DAC])
offset[DA732X_HPL_DAC] &= ~step;
- if ((codec->hw_read(codec, DA732X_REG_HPR_DAC_OFF_CNTL) &
+ if ((snd_soc_read(codec, DA732X_REG_HPR_DAC_OFF_CNTL) &
DA732X_HP_DAC_OFF_CNTL_COMPO) ^ sign[DA732X_HPR_DAC])
offset[DA732X_HPR_DAC] &= ~step;
@@ -1364,9 +1364,9 @@
msleep(DA732X_WAIT_FOR_STABILIZATION);
/* Check output offset sign */
- sign[DA732X_HPL_AMP] = codec->hw_read(codec, DA732X_REG_HPL) &
+ sign[DA732X_HPL_AMP] = snd_soc_read(codec, DA732X_REG_HPL) &
DA732X_HP_OUT_COMPO;
- sign[DA732X_HPR_AMP] = codec->hw_read(codec, DA732X_REG_HPR) &
+ sign[DA732X_HPR_AMP] = snd_soc_read(codec, DA732X_REG_HPR) &
DA732X_HP_OUT_COMPO;
snd_soc_write(codec, DA732X_REG_HPL, DA732X_HP_OUT_COMP |
@@ -1387,10 +1387,10 @@
msleep(DA732X_WAIT_FOR_STABILIZATION);
- if ((codec->hw_read(codec, DA732X_REG_HPL) &
+ if ((snd_soc_read(codec, DA732X_REG_HPL) &
DA732X_HP_OUT_COMPO) ^ sign[DA732X_HPL_AMP])
offset[DA732X_HPL_AMP] &= ~step;
- if ((codec->hw_read(codec, DA732X_REG_HPR) &
+ if ((snd_soc_read(codec, DA732X_REG_HPR) &
DA732X_HP_OUT_COMPO) ^ sign[DA732X_HPR_AMP])
offset[DA732X_HPR_AMP] &= ~step;
diff --git a/sound/soc/codecs/sgtl5000.c b/sound/soc/codecs/sgtl5000.c
index 0fcbe90..c8c37e4 100644
--- a/sound/soc/codecs/sgtl5000.c
+++ b/sound/soc/codecs/sgtl5000.c
@@ -1350,14 +1350,6 @@
int ret;
struct sgtl5000_priv *sgtl5000 = snd_soc_codec_get_drvdata(codec);
- /* setup i2c data ops */
- codec->control_data = sgtl5000->regmap;
- ret = snd_soc_codec_set_cache_io(codec, 16, 16, SND_SOC_REGMAP);
- if (ret < 0) {
- dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
- return ret;
- }
-
ret = sgtl5000_enable_regulators(codec);
if (ret)
return ret;
diff --git a/sound/soc/codecs/si476x.c b/sound/soc/codecs/si476x.c
index 52e7cb0..fa2b8e0 100644
--- a/sound/soc/codecs/si476x.c
+++ b/sound/soc/codecs/si476x.c
@@ -210,7 +210,7 @@
static int si476x_codec_probe(struct snd_soc_codec *codec)
{
codec->control_data = dev_get_regmap(codec->dev->parent, NULL);
- return 0;
+ return snd_soc_codec_set_cache_io(codec, 0, 0, SND_SOC_REGMAP);
}
static struct snd_soc_dai_ops si476x_dai_ops = {
diff --git a/sound/soc/codecs/tlv320aic23-i2c.c b/sound/soc/codecs/tlv320aic23-i2c.c
new file mode 100644
index 0000000..20fc460
--- /dev/null
+++ b/sound/soc/codecs/tlv320aic23-i2c.c
@@ -0,0 +1,59 @@
+/*
+ * ALSA SoC TLV320AIC23 codec driver I2C interface
+ *
+ * Author: Arun KS, <arunks@mistralsolutions.com>
+ * Copyright: (C) 2008 Mistral Solutions Pvt Ltd.,
+ *
+ * Based on sound/soc/codecs/wm8731.c by Richard Purdie
+ *
+ * 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 "tlv320aic23.h"
+
+static int tlv320aic23_i2c_probe(struct i2c_client *i2c,
+ const struct i2c_device_id *i2c_id)
+{
+ struct regmap *regmap;
+
+ if (!i2c_check_functionality(i2c->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
+ return -EINVAL;
+
+ regmap = devm_regmap_init_i2c(i2c, &tlv320aic23_regmap);
+ return tlv320aic23_probe(&i2c->dev, regmap);
+}
+
+static int __exit tlv320aic23_i2c_remove(struct i2c_client *i2c)
+{
+ snd_soc_unregister_codec(&i2c->dev);
+ return 0;
+}
+
+static const struct i2c_device_id tlv320aic23_id[] = {
+ {"tlv320aic23", 0},
+ {}
+};
+
+MODULE_DEVICE_TABLE(i2c, tlv320aic23_id);
+
+static struct i2c_driver tlv320aic23_i2c_driver = {
+ .driver = {
+ .name = "tlv320aic23-codec",
+ },
+ .probe = tlv320aic23_i2c_probe,
+ .remove = __exit_p(tlv320aic23_i2c_remove),
+ .id_table = tlv320aic23_id,
+};
+
+module_i2c_driver(tlv320aic23_i2c_driver);
+
+MODULE_DESCRIPTION("ASoC TLV320AIC23 codec driver I2C");
+MODULE_AUTHOR("Arun KS <arunks@mistralsolutions.com>");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/tlv320aic23-spi.c b/sound/soc/codecs/tlv320aic23-spi.c
new file mode 100644
index 0000000..585aea4
--- /dev/null
+++ b/sound/soc/codecs/tlv320aic23-spi.c
@@ -0,0 +1,57 @@
+/*
+ * ALSA SoC TLV320AIC23 codec driver SPI interface
+ *
+ * Author: Arun KS, <arunks@mistralsolutions.com>
+ * Copyright: (C) 2008 Mistral Solutions Pvt Ltd.,
+ *
+ * Based on sound/soc/codecs/wm8731.c by Richard Purdie
+ *
+ * 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/regmap.h>
+#include <linux/spi/spi.h>
+#include <sound/soc.h>
+
+#include "tlv320aic23.h"
+
+static int aic23_spi_probe(struct spi_device *spi)
+{
+ int ret;
+ struct regmap *regmap;
+
+ dev_dbg(&spi->dev, "probing tlv320aic23 spi device\n");
+
+ spi->bits_per_word = 16;
+ spi->mode = SPI_MODE_0;
+ ret = spi_setup(spi);
+ if (ret < 0)
+ return ret;
+
+ regmap = devm_regmap_init_spi(spi, &tlv320aic23_regmap);
+ return tlv320aic23_probe(&spi->dev, regmap);
+}
+
+static int aic23_spi_remove(struct spi_device *spi)
+{
+ snd_soc_unregister_codec(&spi->dev);
+ return 0;
+}
+
+static struct spi_driver aic23_spi = {
+ .driver = {
+ .name = "tlv320aic23",
+ .owner = THIS_MODULE,
+ },
+ .probe = aic23_spi_probe,
+ .remove = aic23_spi_remove,
+};
+
+module_spi_driver(aic23_spi);
+
+MODULE_DESCRIPTION("ASoC TLV320AIC23 codec driver SPI");
+MODULE_AUTHOR("Arun KS <arunks@mistralsolutions.com>");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/tlv320aic23.c b/sound/soc/codecs/tlv320aic23.c
index 5d430cc..7b4cfef 100644
--- a/sound/soc/codecs/tlv320aic23.c
+++ b/sound/soc/codecs/tlv320aic23.c
@@ -23,7 +23,6 @@
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/pm.h>
-#include <linux/i2c.h>
#include <linux/regmap.h>
#include <linux/slab.h>
#include <sound/core.h>
@@ -51,7 +50,7 @@
{ 9, 0x0000 },
};
-static const struct regmap_config tlv320aic23_regmap = {
+const struct regmap_config tlv320aic23_regmap = {
.reg_bits = 7,
.val_bits = 9,
@@ -60,20 +59,21 @@
.num_reg_defaults = ARRAY_SIZE(tlv320aic23_reg),
.cache_type = REGCACHE_RBTREE,
};
+EXPORT_SYMBOL(tlv320aic23_regmap);
static const char *rec_src_text[] = { "Line", "Mic" };
static const char *deemph_text[] = {"None", "32Khz", "44.1Khz", "48Khz"};
-static const struct soc_enum rec_src_enum =
- SOC_ENUM_SINGLE(TLV320AIC23_ANLG, 2, 2, rec_src_text);
+static SOC_ENUM_SINGLE_DECL(rec_src_enum,
+ TLV320AIC23_ANLG, 2, rec_src_text);
static const struct snd_kcontrol_new tlv320aic23_rec_src_mux_controls =
SOC_DAPM_ENUM("Input Select", rec_src_enum);
-static const struct soc_enum tlv320aic23_rec_src =
- SOC_ENUM_SINGLE(TLV320AIC23_ANLG, 2, 2, rec_src_text);
-static const struct soc_enum tlv320aic23_deemph =
- SOC_ENUM_SINGLE(TLV320AIC23_DIGT, 1, 4, deemph_text);
+static SOC_ENUM_SINGLE_DECL(tlv320aic23_rec_src,
+ TLV320AIC23_ANLG, 2, rec_src_text);
+static SOC_ENUM_SINGLE_DECL(tlv320aic23_deemph,
+ TLV320AIC23_DIGT, 1, deemph_text);
static const DECLARE_TLV_DB_SCALE(out_gain_tlv, -12100, 100, 0);
static const DECLARE_TLV_DB_SCALE(input_gain_tlv, -1725, 75, 0);
@@ -557,7 +557,7 @@
return 0;
}
-static int tlv320aic23_probe(struct snd_soc_codec *codec)
+static int tlv320aic23_codec_probe(struct snd_soc_codec *codec)
{
int ret;
@@ -604,7 +604,7 @@
}
static struct snd_soc_codec_driver soc_codec_dev_tlv320aic23 = {
- .probe = tlv320aic23_probe,
+ .probe = tlv320aic23_codec_probe,
.remove = tlv320aic23_remove,
.suspend = tlv320aic23_suspend,
.resume = tlv320aic23_resume,
@@ -617,56 +617,25 @@
.num_dapm_routes = ARRAY_SIZE(tlv320aic23_intercon),
};
-/*
- * If the i2c layer weren't so broken, we could pass this kind of data
- * around
- */
-static int tlv320aic23_codec_probe(struct i2c_client *i2c,
- const struct i2c_device_id *i2c_id)
+int tlv320aic23_probe(struct device *dev, struct regmap *regmap)
{
struct aic23 *aic23;
- int ret;
- if (!i2c_check_functionality(i2c->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
- return -EINVAL;
+ if (IS_ERR(regmap))
+ return PTR_ERR(regmap);
- aic23 = devm_kzalloc(&i2c->dev, sizeof(struct aic23), GFP_KERNEL);
+ aic23 = devm_kzalloc(dev, sizeof(struct aic23), GFP_KERNEL);
if (aic23 == NULL)
return -ENOMEM;
- aic23->regmap = devm_regmap_init_i2c(i2c, &tlv320aic23_regmap);
- if (IS_ERR(aic23->regmap))
- return PTR_ERR(aic23->regmap);
+ aic23->regmap = regmap;
- i2c_set_clientdata(i2c, aic23);
+ dev_set_drvdata(dev, aic23);
- ret = snd_soc_register_codec(&i2c->dev,
- &soc_codec_dev_tlv320aic23, &tlv320aic23_dai, 1);
- return ret;
+ return snd_soc_register_codec(dev, &soc_codec_dev_tlv320aic23,
+ &tlv320aic23_dai, 1);
}
-static int __exit tlv320aic23_i2c_remove(struct i2c_client *i2c)
-{
- snd_soc_unregister_codec(&i2c->dev);
- return 0;
-}
-
-static const struct i2c_device_id tlv320aic23_id[] = {
- {"tlv320aic23", 0},
- {}
-};
-
-MODULE_DEVICE_TABLE(i2c, tlv320aic23_id);
-
-static struct i2c_driver tlv320aic23_i2c_driver = {
- .driver = {
- .name = "tlv320aic23-codec",
- },
- .probe = tlv320aic23_codec_probe,
- .remove = __exit_p(tlv320aic23_i2c_remove),
- .id_table = tlv320aic23_id,
-};
-
-module_i2c_driver(tlv320aic23_i2c_driver);
+EXPORT_SYMBOL(tlv320aic23_probe);
MODULE_DESCRIPTION("ASoC TLV320AIC23 codec driver");
MODULE_AUTHOR("Arun KS <arunks@mistralsolutions.com>");
diff --git a/sound/soc/codecs/tlv320aic23.h b/sound/soc/codecs/tlv320aic23.h
index e804120..3a7235a 100644
--- a/sound/soc/codecs/tlv320aic23.h
+++ b/sound/soc/codecs/tlv320aic23.h
@@ -12,6 +12,12 @@
#ifndef _TLV320AIC23_H
#define _TLV320AIC23_H
+struct device;
+struct regmap_config;
+
+extern const struct regmap_config tlv320aic23_regmap;
+int tlv320aic23_probe(struct device *dev, struct regmap *regmap);
+
/* Codec TLV320AIC23 */
#define TLV320AIC23_LINVOL 0x00
#define TLV320AIC23_RINVOL 0x01
diff --git a/sound/soc/codecs/wm8991.c b/sound/soc/codecs/wm8991.c
index dba0306..32d2195 100644
--- a/sound/soc/codecs/wm8991.c
+++ b/sound/soc/codecs/wm8991.c
@@ -171,26 +171,23 @@
static const char *wm8991_digital_sidetone[] =
{"None", "Left ADC", "Right ADC", "Reserved"};
-static const struct soc_enum wm8991_left_digital_sidetone_enum =
- SOC_ENUM_SINGLE(WM8991_DIGITAL_SIDE_TONE,
- WM8991_ADC_TO_DACL_SHIFT,
- WM8991_ADC_TO_DACL_MASK,
- wm8991_digital_sidetone);
+static SOC_ENUM_SINGLE_DECL(wm8991_left_digital_sidetone_enum,
+ WM8991_DIGITAL_SIDE_TONE,
+ WM8991_ADC_TO_DACL_SHIFT,
+ wm8991_digital_sidetone);
-static const struct soc_enum wm8991_right_digital_sidetone_enum =
- SOC_ENUM_SINGLE(WM8991_DIGITAL_SIDE_TONE,
- WM8991_ADC_TO_DACR_SHIFT,
- WM8991_ADC_TO_DACR_MASK,
- wm8991_digital_sidetone);
+static SOC_ENUM_SINGLE_DECL(wm8991_right_digital_sidetone_enum,
+ WM8991_DIGITAL_SIDE_TONE,
+ WM8991_ADC_TO_DACR_SHIFT,
+ wm8991_digital_sidetone);
static const char *wm8991_adcmode[] =
{"Hi-fi mode", "Voice mode 1", "Voice mode 2", "Voice mode 3"};
-static const struct soc_enum wm8991_right_adcmode_enum =
- SOC_ENUM_SINGLE(WM8991_ADC_CTRL,
- WM8991_ADC_HPF_CUT_SHIFT,
- WM8991_ADC_HPF_CUT_MASK,
- wm8991_adcmode);
+static SOC_ENUM_SINGLE_DECL(wm8991_right_adcmode_enum,
+ WM8991_ADC_CTRL,
+ WM8991_ADC_HPF_CUT_SHIFT,
+ wm8991_adcmode);
static const struct snd_kcontrol_new wm8991_snd_controls[] = {
/* INMIXL */
@@ -486,9 +483,9 @@
static const char *wm8991_ainlmux[] =
{"INMIXL Mix", "RXVOICE Mix", "DIFFINL Mix"};
-static const struct soc_enum wm8991_ainlmux_enum =
- SOC_ENUM_SINGLE(WM8991_INPUT_MIXER1, WM8991_AINLMODE_SHIFT,
- ARRAY_SIZE(wm8991_ainlmux), wm8991_ainlmux);
+static SOC_ENUM_SINGLE_DECL(wm8991_ainlmux_enum,
+ WM8991_INPUT_MIXER1, WM8991_AINLMODE_SHIFT,
+ wm8991_ainlmux);
static const struct snd_kcontrol_new wm8991_dapm_ainlmux_controls =
SOC_DAPM_ENUM("Route", wm8991_ainlmux_enum);
@@ -499,9 +496,9 @@
static const char *wm8991_ainrmux[] =
{"INMIXR Mix", "RXVOICE Mix", "DIFFINR Mix"};
-static const struct soc_enum wm8991_ainrmux_enum =
- SOC_ENUM_SINGLE(WM8991_INPUT_MIXER1, WM8991_AINRMODE_SHIFT,
- ARRAY_SIZE(wm8991_ainrmux), wm8991_ainrmux);
+static SOC_ENUM_SINGLE_DECL(wm8991_ainrmux_enum,
+ WM8991_INPUT_MIXER1, WM8991_AINRMODE_SHIFT,
+ wm8991_ainrmux);
static const struct snd_kcontrol_new wm8991_dapm_ainrmux_controls =
SOC_DAPM_ENUM("Route", wm8991_ainrmux_enum);
@@ -1251,11 +1248,8 @@
static int wm8991_probe(struct snd_soc_codec *codec)
{
- struct wm8991_priv *wm8991;
int ret;
- wm8991 = snd_soc_codec_get_drvdata(codec);
-
ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_REGMAP);
if (ret < 0) {
dev_err(codec->dev, "Failed to set cache i/o: %d\n", ret);
diff --git a/sound/soc/fsl/Kconfig b/sound/soc/fsl/Kconfig
index 07f8f14..19a18a4 100644
--- a/sound/soc/fsl/Kconfig
+++ b/sound/soc/fsl/Kconfig
@@ -170,7 +170,7 @@
|| MACH_EUKREA_MBIMXSD35_BASEBOARD \
|| MACH_EUKREA_MBIMXSD51_BASEBOARD
depends on I2C
- select SND_SOC_TLV320AIC23
+ select SND_SOC_TLV320AIC23_I2C
select SND_SOC_IMX_PCM_FIQ
select SND_SOC_IMX_AUDMUX
select SND_SOC_IMX_SSI
diff --git a/sound/soc/omap/Kconfig b/sound/soc/omap/Kconfig
index 22ad9c5..e006593 100644
--- a/sound/soc/omap/Kconfig
+++ b/sound/soc/omap/Kconfig
@@ -58,7 +58,7 @@
tristate "SoC Audio support for omap osk5912"
depends on SND_OMAP_SOC && MACH_OMAP_OSK && I2C
select SND_OMAP_SOC_MCBSP
- select SND_SOC_TLV320AIC23
+ select SND_SOC_TLV320AIC23_I2C
help
Say Y if you want to add support for SoC audio on osk5912.
@@ -66,7 +66,7 @@
tristate "SoC Audio support for OMAP3517 / AM3517 EVM"
depends on SND_OMAP_SOC && MACH_OMAP3517EVM && I2C
select SND_OMAP_SOC_MCBSP
- select SND_SOC_TLV320AIC23
+ select SND_SOC_TLV320AIC23_I2C
help
Say Y if you want to add support for SoC audio on the OMAP3517 / AM3517
EVM.
diff --git a/sound/soc/samsung/Kconfig b/sound/soc/samsung/Kconfig
index 454f41c..47a7a1b 100644
--- a/sound/soc/samsung/Kconfig
+++ b/sound/soc/samsung/Kconfig
@@ -117,7 +117,7 @@
tristate "SoC I2S Audio support for TLV320AIC23 on Simtec boards"
depends on SND_SOC_SAMSUNG && ARCH_S3C24XX
select SND_S3C24XX_I2S
- select SND_SOC_TLV320AIC23
+ select SND_SOC_TLV320AIC23_I2C
select SND_SOC_SAMSUNG_SIMTEC
config SND_SOC_SAMSUNG_SIMTEC_HERMES
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c
index c1d9d85..ad2dd14 100644
--- a/sound/soc/soc-core.c
+++ b/sound/soc/soc-core.c
@@ -1137,6 +1137,10 @@
codec->dapm.idle_bias_off = driver->idle_bias_off;
+ /* Set the default I/O up try regmap */
+ if (dev_get_regmap(codec->dev, NULL))
+ snd_soc_codec_set_cache_io(codec, 0, 0, SND_SOC_REGMAP);
+
if (driver->probe) {
ret = driver->probe(codec);
if (ret < 0) {
@@ -1150,10 +1154,6 @@
codec->name);
}
- /* If the driver didn't set I/O up try regmap */
- if (!codec->write && dev_get_regmap(codec->dev, NULL))
- snd_soc_codec_set_cache_io(codec, 0, 0, SND_SOC_REGMAP);
-
if (driver->controls)
snd_soc_add_codec_controls(codec, driver->controls,
driver->num_controls);
diff --git a/sound/soc/soc-io.c b/sound/soc/soc-io.c
index aa886cc..18353f1 100644
--- a/sound/soc/soc-io.c
+++ b/sound/soc/soc-io.c
@@ -88,31 +88,12 @@
int addr_bits, int data_bits,
enum snd_soc_control_type control)
{
- struct regmap_config config;
int ret;
- memset(&config, 0, sizeof(config));
codec->write = hw_write;
codec->read = hw_read;
- config.reg_bits = addr_bits;
- config.val_bits = data_bits;
-
switch (control) {
-#if IS_ENABLED(CONFIG_REGMAP_I2C)
- case SND_SOC_I2C:
- codec->control_data = regmap_init_i2c(to_i2c_client(codec->dev),
- &config);
- break;
-#endif
-
-#if IS_ENABLED(CONFIG_REGMAP_SPI)
- case SND_SOC_SPI:
- codec->control_data = regmap_init_spi(to_spi_device(codec->dev),
- &config);
- break;
-#endif
-
case SND_SOC_REGMAP:
/* Device has made its own regmap arrangements */
codec->using_regmap = true;
diff --git a/sound/soc/tegra/Kconfig b/sound/soc/tegra/Kconfig
index 9f9c185..31198cf7 100644
--- a/sound/soc/tegra/Kconfig
+++ b/sound/soc/tegra/Kconfig
@@ -105,7 +105,7 @@
tristate "SoC Audio support for TrimSlice board"
depends on SND_SOC_TEGRA && I2C
select SND_SOC_TEGRA20_I2S if ARCH_TEGRA_2x_SOC
- select SND_SOC_TLV320AIC23
+ select SND_SOC_TLV320AIC23_I2C
help
Say Y or M here if you want to add support for SoC audio on the
TrimSlice platform.