|
@@ -17,6 +17,7 @@
|
|
|
|
|
|
#include <linux/delay.h>
|
|
|
#include <linux/i2c.h>
|
|
|
+#include <linux/spi/spi.h>
|
|
|
#include <linux/regmap.h>
|
|
|
#include <linux/slab.h>
|
|
|
#include <linux/module.h>
|
|
@@ -27,6 +28,7 @@
|
|
|
#include <sound/tlv.h>
|
|
|
|
|
|
/* DA7210 register space */
|
|
|
+#define DA7210_PAGE_CONTROL 0x00
|
|
|
#define DA7210_CONTROL 0x01
|
|
|
#define DA7210_STATUS 0x02
|
|
|
#define DA7210_STARTUP1 0x03
|
|
@@ -631,6 +633,7 @@ struct da7210_priv {
|
|
|
};
|
|
|
|
|
|
static struct reg_default da7210_reg_defaults[] = {
|
|
|
+ { 0x00, 0x00 },
|
|
|
{ 0x01, 0x11 },
|
|
|
{ 0x03, 0x00 },
|
|
|
{ 0x04, 0x00 },
|
|
@@ -927,13 +930,6 @@ static int da7210_probe(struct snd_soc_codec *codec)
|
|
|
* DA7210_PLL_DIV3 :: DA7210_MCLK_RANGExxx
|
|
|
*/
|
|
|
|
|
|
- /*
|
|
|
- * make sure that DA7210 use bypass mode before start up
|
|
|
- */
|
|
|
- snd_soc_write(codec, DA7210_STARTUP1, 0);
|
|
|
- snd_soc_write(codec, DA7210_PLL_DIV3,
|
|
|
- DA7210_MCLK_RANGE_10_20_MHZ | DA7210_PLL_BYP);
|
|
|
-
|
|
|
/*
|
|
|
* ADC settings
|
|
|
*/
|
|
@@ -1025,16 +1021,6 @@ static int da7210_probe(struct snd_soc_codec *codec)
|
|
|
DA7210_MCLK_RANGE_10_20_MHZ | DA7210_PLL_BYP);
|
|
|
snd_soc_update_bits(codec, DA7210_PLL, DA7210_PLL_EN, DA7210_PLL_EN);
|
|
|
|
|
|
- /* As suggested by Dialog */
|
|
|
- /* unlock */
|
|
|
- regmap_write(da7210->regmap, DA7210_A_HID_UNLOCK, 0x8B);
|
|
|
- regmap_write(da7210->regmap, DA7210_A_TEST_UNLOCK, 0xB4);
|
|
|
- regmap_write(da7210->regmap, DA7210_A_PLL1, 0x01);
|
|
|
- regmap_write(da7210->regmap, DA7210_A_CP_MODE, 0x7C);
|
|
|
- /* re-lock */
|
|
|
- regmap_write(da7210->regmap, DA7210_A_HID_UNLOCK, 0x00);
|
|
|
- regmap_write(da7210->regmap, DA7210_A_TEST_UNLOCK, 0x00);
|
|
|
-
|
|
|
/* Activate all enabled subsystem */
|
|
|
snd_soc_write(codec, DA7210_STARTUP1, DA7210_SC_MST_EN);
|
|
|
|
|
@@ -1055,7 +1041,26 @@ static struct snd_soc_codec_driver soc_codec_dev_da7210 = {
|
|
|
.num_dapm_routes = ARRAY_SIZE(da7210_audio_map),
|
|
|
};
|
|
|
|
|
|
-static struct regmap_config da7210_regmap = {
|
|
|
+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
|
|
|
+
|
|
|
+static struct reg_default da7210_regmap_i2c_patch[] = {
|
|
|
+
|
|
|
+ /* System controller master disable */
|
|
|
+ { DA7210_STARTUP1, 0x00 },
|
|
|
+ /* make sure that DA7210 use bypass mode before start up */
|
|
|
+ { DA7210_PLL_DIV3, DA7210_MCLK_RANGE_10_20_MHZ | DA7210_PLL_BYP },
|
|
|
+
|
|
|
+ /* to unlock */
|
|
|
+ { DA7210_A_HID_UNLOCK, 0x8B},
|
|
|
+ { DA7210_A_TEST_UNLOCK, 0xB4},
|
|
|
+ { DA7210_A_PLL1, 0x01},
|
|
|
+ { DA7210_A_CP_MODE, 0x7C},
|
|
|
+ /* to re-lock */
|
|
|
+ { DA7210_A_HID_UNLOCK, 0x00},
|
|
|
+ { DA7210_A_TEST_UNLOCK, 0x00},
|
|
|
+};
|
|
|
+
|
|
|
+static const struct regmap_config da7210_regmap_config_i2c = {
|
|
|
.reg_bits = 8,
|
|
|
.val_bits = 8,
|
|
|
|
|
@@ -1066,7 +1071,6 @@ static struct regmap_config da7210_regmap = {
|
|
|
.cache_type = REGCACHE_RBTREE,
|
|
|
};
|
|
|
|
|
|
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
|
|
|
static int __devinit da7210_i2c_probe(struct i2c_client *i2c,
|
|
|
const struct i2c_device_id *id)
|
|
|
{
|
|
@@ -1080,13 +1084,18 @@ static int __devinit da7210_i2c_probe(struct i2c_client *i2c,
|
|
|
|
|
|
i2c_set_clientdata(i2c, da7210);
|
|
|
|
|
|
- da7210->regmap = regmap_init_i2c(i2c, &da7210_regmap);
|
|
|
+ da7210->regmap = 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);
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
|
+ ret = regmap_register_patch(da7210->regmap, da7210_regmap_i2c_patch,
|
|
|
+ ARRAY_SIZE(da7210_regmap_i2c_patch));
|
|
|
+ if (ret != 0)
|
|
|
+ dev_warn(&i2c->dev, "Failed to apply regmap patch: %d\n", ret);
|
|
|
+
|
|
|
ret = snd_soc_register_codec(&i2c->dev,
|
|
|
&soc_codec_dev_da7210, &da7210_dai, 1);
|
|
|
if (ret < 0) {
|
|
@@ -1119,7 +1128,7 @@ MODULE_DEVICE_TABLE(i2c, da7210_i2c_id);
|
|
|
/* I2C codec control layer */
|
|
|
static struct i2c_driver da7210_i2c_driver = {
|
|
|
.driver = {
|
|
|
- .name = "da7210-codec",
|
|
|
+ .name = "da7210",
|
|
|
.owner = THIS_MODULE,
|
|
|
},
|
|
|
.probe = da7210_i2c_probe,
|
|
@@ -1128,11 +1137,111 @@ static struct i2c_driver da7210_i2c_driver = {
|
|
|
};
|
|
|
#endif
|
|
|
|
|
|
+#if defined(CONFIG_SPI_MASTER)
|
|
|
+
|
|
|
+static struct reg_default da7210_regmap_spi_patch[] = {
|
|
|
+ /* Dummy read to give two pulses over nCS for SPI */
|
|
|
+ { DA7210_AUX2, 0x00 },
|
|
|
+ { DA7210_AUX2, 0x00 },
|
|
|
+
|
|
|
+ /* System controller master disable */
|
|
|
+ { DA7210_STARTUP1, 0x00 },
|
|
|
+ /* make sure that DA7210 use bypass mode before start up */
|
|
|
+ { DA7210_PLL_DIV3, DA7210_MCLK_RANGE_10_20_MHZ | DA7210_PLL_BYP },
|
|
|
+
|
|
|
+ /* to set PAGE1 of SPI register space */
|
|
|
+ { DA7210_PAGE_CONTROL, 0x80 },
|
|
|
+ /* to unlock */
|
|
|
+ { DA7210_A_HID_UNLOCK, 0x8B},
|
|
|
+ { DA7210_A_TEST_UNLOCK, 0xB4},
|
|
|
+ { DA7210_A_PLL1, 0x01},
|
|
|
+ { DA7210_A_CP_MODE, 0x7C},
|
|
|
+ /* to re-lock */
|
|
|
+ { DA7210_A_HID_UNLOCK, 0x00},
|
|
|
+ { DA7210_A_TEST_UNLOCK, 0x00},
|
|
|
+ /* to set back PAGE0 of SPI register space */
|
|
|
+ { DA7210_PAGE_CONTROL, 0x00 },
|
|
|
+};
|
|
|
+
|
|
|
+static const struct regmap_config da7210_regmap_config_spi = {
|
|
|
+ .reg_bits = 8,
|
|
|
+ .val_bits = 8,
|
|
|
+ .read_flag_mask = 0x01,
|
|
|
+ .write_flag_mask = 0x00,
|
|
|
+
|
|
|
+ .reg_defaults = da7210_reg_defaults,
|
|
|
+ .num_reg_defaults = ARRAY_SIZE(da7210_reg_defaults),
|
|
|
+ .volatile_reg = da7210_volatile_register,
|
|
|
+ .readable_reg = da7210_readable_register,
|
|
|
+ .cache_type = REGCACHE_RBTREE,
|
|
|
+};
|
|
|
+
|
|
|
+static int __devinit da7210_spi_probe(struct spi_device *spi)
|
|
|
+{
|
|
|
+ struct da7210_priv *da7210;
|
|
|
+ int ret;
|
|
|
+
|
|
|
+ da7210 = devm_kzalloc(&spi->dev, sizeof(struct da7210_priv),
|
|
|
+ GFP_KERNEL);
|
|
|
+ if (!da7210)
|
|
|
+ return -ENOMEM;
|
|
|
+
|
|
|
+ spi_set_drvdata(spi, da7210);
|
|
|
+ da7210->regmap = devm_regmap_init_spi(spi, &da7210_regmap_config_spi);
|
|
|
+ if (IS_ERR(da7210->regmap)) {
|
|
|
+ ret = PTR_ERR(da7210->regmap);
|
|
|
+ dev_err(&spi->dev, "Failed to register regmap: %d\n", ret);
|
|
|
+ return ret;
|
|
|
+ }
|
|
|
+
|
|
|
+ ret = regmap_register_patch(da7210->regmap, da7210_regmap_spi_patch,
|
|
|
+ ARRAY_SIZE(da7210_regmap_spi_patch));
|
|
|
+ if (ret != 0)
|
|
|
+ dev_warn(&spi->dev, "Failed to apply regmap patch: %d\n", ret);
|
|
|
+
|
|
|
+ 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)
|
|
|
+{
|
|
|
+ struct da7210_priv *da7210 = spi_get_drvdata(spi);
|
|
|
+ snd_soc_unregister_codec(&spi->dev);
|
|
|
+ regmap_exit(da7210->regmap);
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+static struct spi_driver da7210_spi_driver = {
|
|
|
+ .driver = {
|
|
|
+ .name = "da7210",
|
|
|
+ .owner = THIS_MODULE,
|
|
|
+ },
|
|
|
+ .probe = da7210_spi_probe,
|
|
|
+ .remove = __devexit_p(da7210_spi_remove)
|
|
|
+};
|
|
|
+#endif
|
|
|
+
|
|
|
static int __init da7210_modinit(void)
|
|
|
{
|
|
|
int ret = 0;
|
|
|
#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
|
|
|
ret = i2c_add_driver(&da7210_i2c_driver);
|
|
|
+#endif
|
|
|
+#if defined(CONFIG_SPI_MASTER)
|
|
|
+ ret = spi_register_driver(&da7210_spi_driver);
|
|
|
+ if (ret) {
|
|
|
+ printk(KERN_ERR "Failed to register da7210 SPI driver: %d\n",
|
|
|
+ ret);
|
|
|
+ }
|
|
|
#endif
|
|
|
return ret;
|
|
|
}
|
|
@@ -1143,6 +1252,9 @@ static void __exit da7210_exit(void)
|
|
|
#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
|
|
|
i2c_del_driver(&da7210_i2c_driver);
|
|
|
#endif
|
|
|
+#if defined(CONFIG_SPI_MASTER)
|
|
|
+ spi_unregister_driver(&da7210_spi_driver);
|
|
|
+#endif
|
|
|
}
|
|
|
module_exit(da7210_exit);
|
|
|
|