|
@@ -28,6 +28,7 @@
|
|
|
#include <linux/slab.h>
|
|
|
#include <linux/of_device.h>
|
|
|
#include <linux/module.h>
|
|
|
+#include <linux/regmap.h>
|
|
|
#include <sound/soc.h>
|
|
|
#include <sound/initval.h>
|
|
|
#include <sound/tlv.h>
|
|
@@ -198,30 +199,30 @@ static const struct snd_soc_dapm_route ak4642_intercon[] = {
|
|
|
/*
|
|
|
* ak4642 register cache
|
|
|
*/
|
|
|
-static const u8 ak4642_reg[] = {
|
|
|
- 0x00, 0x00, 0x01, 0x00,
|
|
|
- 0x02, 0x00, 0x00, 0x00,
|
|
|
- 0xe1, 0xe1, 0x18, 0x00,
|
|
|
- 0xe1, 0x18, 0x11, 0x08,
|
|
|
- 0x00, 0x00, 0x00, 0x00,
|
|
|
- 0x00, 0x00, 0x00, 0x00,
|
|
|
- 0x00, 0x00, 0x00, 0x00,
|
|
|
- 0x00, 0x00, 0x00, 0x00,
|
|
|
- 0x00, 0x00, 0x00, 0x00,
|
|
|
- 0x00,
|
|
|
+static const struct reg_default ak4642_reg[] = {
|
|
|
+ { 0, 0x00 }, { 1, 0x00 }, { 2, 0x01 }, { 3, 0x00 },
|
|
|
+ { 4, 0x02 }, { 5, 0x00 }, { 6, 0x00 }, { 7, 0x00 },
|
|
|
+ { 8, 0xe1 }, { 9, 0xe1 }, { 10, 0x18 }, { 11, 0x00 },
|
|
|
+ { 12, 0xe1 }, { 13, 0x18 }, { 14, 0x11 }, { 15, 0x08 },
|
|
|
+ { 16, 0x00 }, { 17, 0x00 }, { 18, 0x00 }, { 19, 0x00 },
|
|
|
+ { 20, 0x00 }, { 21, 0x00 }, { 22, 0x00 }, { 23, 0x00 },
|
|
|
+ { 24, 0x00 }, { 25, 0x00 }, { 26, 0x00 }, { 27, 0x00 },
|
|
|
+ { 28, 0x00 }, { 29, 0x00 }, { 30, 0x00 }, { 31, 0x00 },
|
|
|
+ { 32, 0x00 }, { 33, 0x00 }, { 34, 0x00 }, { 35, 0x00 },
|
|
|
+ { 36, 0x00 },
|
|
|
};
|
|
|
|
|
|
-static const u8 ak4648_reg[] = {
|
|
|
- 0x00, 0x00, 0x01, 0x00,
|
|
|
- 0x02, 0x00, 0x00, 0x00,
|
|
|
- 0xe1, 0xe1, 0x18, 0x00,
|
|
|
- 0xe1, 0x18, 0x11, 0xb8,
|
|
|
- 0x00, 0x00, 0x00, 0x00,
|
|
|
- 0x00, 0x00, 0x00, 0x00,
|
|
|
- 0x00, 0x00, 0x00, 0x00,
|
|
|
- 0x00, 0x00, 0x00, 0x00,
|
|
|
- 0x00, 0x00, 0x00, 0x00,
|
|
|
- 0x00, 0x88, 0x88, 0x08,
|
|
|
+static const struct reg_default ak4648_reg[] = {
|
|
|
+ { 0, 0x00 }, { 1, 0x00 }, { 2, 0x01 }, { 3, 0x00 },
|
|
|
+ { 4, 0x02 }, { 5, 0x00 }, { 6, 0x00 }, { 7, 0x00 },
|
|
|
+ { 8, 0xe1 }, { 9, 0xe1 }, { 10, 0x18 }, { 11, 0x00 },
|
|
|
+ { 12, 0xe1 }, { 13, 0x18 }, { 14, 0x11 }, { 15, 0xb8 },
|
|
|
+ { 16, 0x00 }, { 17, 0x00 }, { 18, 0x00 }, { 19, 0x00 },
|
|
|
+ { 20, 0x00 }, { 21, 0x00 }, { 22, 0x00 }, { 23, 0x00 },
|
|
|
+ { 24, 0x00 }, { 25, 0x00 }, { 26, 0x00 }, { 27, 0x00 },
|
|
|
+ { 28, 0x00 }, { 29, 0x00 }, { 30, 0x00 }, { 31, 0x00 },
|
|
|
+ { 32, 0x00 }, { 33, 0x00 }, { 34, 0x00 }, { 35, 0x00 },
|
|
|
+ { 36, 0x00 }, { 37, 0x88 }, { 38, 0x88 }, { 39, 0x08 },
|
|
|
};
|
|
|
|
|
|
static int ak4642_dai_startup(struct snd_pcm_substream *substream,
|
|
@@ -454,7 +455,10 @@ static struct snd_soc_dai_driver ak4642_dai = {
|
|
|
|
|
|
static int ak4642_resume(struct snd_soc_codec *codec)
|
|
|
{
|
|
|
- snd_soc_cache_sync(codec);
|
|
|
+ struct regmap *regmap = dev_get_regmap(codec->dev, NULL);
|
|
|
+
|
|
|
+ regcache_mark_dirty(regmap);
|
|
|
+ regcache_sync(regmap);
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
@@ -463,7 +467,7 @@ static int ak4642_probe(struct snd_soc_codec *codec)
|
|
|
{
|
|
|
int ret;
|
|
|
|
|
|
- ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_I2C);
|
|
|
+ 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;
|
|
@@ -485,9 +489,6 @@ static struct snd_soc_codec_driver soc_codec_dev_ak4642 = {
|
|
|
.remove = ak4642_remove,
|
|
|
.resume = ak4642_resume,
|
|
|
.set_bias_level = ak4642_set_bias_level,
|
|
|
- .reg_cache_default = ak4642_reg, /* ak4642 reg */
|
|
|
- .reg_cache_size = ARRAY_SIZE(ak4642_reg), /* ak4642 reg */
|
|
|
- .reg_word_size = sizeof(u8),
|
|
|
.controls = ak4642_snd_controls,
|
|
|
.num_controls = ARRAY_SIZE(ak4642_snd_controls),
|
|
|
.dapm_widgets = ak4642_dapm_widgets,
|
|
@@ -496,20 +497,20 @@ static struct snd_soc_codec_driver soc_codec_dev_ak4642 = {
|
|
|
.num_dapm_routes = ARRAY_SIZE(ak4642_intercon),
|
|
|
};
|
|
|
|
|
|
-static struct snd_soc_codec_driver soc_codec_dev_ak4648 = {
|
|
|
- .probe = ak4642_probe,
|
|
|
- .remove = ak4642_remove,
|
|
|
- .resume = ak4642_resume,
|
|
|
- .set_bias_level = ak4642_set_bias_level,
|
|
|
- .reg_cache_default = ak4648_reg, /* ak4648 reg */
|
|
|
- .reg_cache_size = ARRAY_SIZE(ak4648_reg), /* ak4648 reg */
|
|
|
- .reg_word_size = sizeof(u8),
|
|
|
- .controls = ak4642_snd_controls,
|
|
|
- .num_controls = ARRAY_SIZE(ak4642_snd_controls),
|
|
|
- .dapm_widgets = ak4642_dapm_widgets,
|
|
|
- .num_dapm_widgets = ARRAY_SIZE(ak4642_dapm_widgets),
|
|
|
- .dapm_routes = ak4642_intercon,
|
|
|
- .num_dapm_routes = ARRAY_SIZE(ak4642_intercon),
|
|
|
+static const struct regmap_config ak4642_regmap = {
|
|
|
+ .reg_bits = 8,
|
|
|
+ .val_bits = 8,
|
|
|
+ .max_register = ARRAY_SIZE(ak4642_reg) + 1,
|
|
|
+ .reg_defaults = ak4642_reg,
|
|
|
+ .num_reg_defaults = ARRAY_SIZE(ak4642_reg),
|
|
|
+};
|
|
|
+
|
|
|
+static const struct regmap_config ak4648_regmap = {
|
|
|
+ .reg_bits = 8,
|
|
|
+ .val_bits = 8,
|
|
|
+ .max_register = ARRAY_SIZE(ak4648_reg) + 1,
|
|
|
+ .reg_defaults = ak4648_reg,
|
|
|
+ .num_reg_defaults = ARRAY_SIZE(ak4648_reg),
|
|
|
};
|
|
|
|
|
|
#if IS_ENABLED(CONFIG_I2C)
|
|
@@ -518,26 +519,30 @@ static int ak4642_i2c_probe(struct i2c_client *i2c,
|
|
|
const struct i2c_device_id *id)
|
|
|
{
|
|
|
struct device_node *np = i2c->dev.of_node;
|
|
|
- const struct snd_soc_codec_driver *driver;
|
|
|
+ const struct regmap_config *regmap_config = NULL;
|
|
|
+ struct regmap *regmap;
|
|
|
|
|
|
- driver = NULL;
|
|
|
if (np) {
|
|
|
const struct of_device_id *of_id;
|
|
|
|
|
|
of_id = of_match_device(ak4642_of_match, &i2c->dev);
|
|
|
if (of_id)
|
|
|
- driver = of_id->data;
|
|
|
+ regmap_config = of_id->data;
|
|
|
} else {
|
|
|
- driver = (struct snd_soc_codec_driver *)id->driver_data;
|
|
|
+ regmap_config = (const struct regmap_config *)id->driver_data;
|
|
|
}
|
|
|
|
|
|
- if (!driver) {
|
|
|
- dev_err(&i2c->dev, "no driver\n");
|
|
|
+ if (!regmap_config) {
|
|
|
+ dev_err(&i2c->dev, "Unknown device type\n");
|
|
|
return -EINVAL;
|
|
|
}
|
|
|
|
|
|
+ regmap = devm_regmap_init_i2c(i2c, regmap_config);
|
|
|
+ if (IS_ERR(regmap))
|
|
|
+ return PTR_ERR(regmap);
|
|
|
+
|
|
|
return snd_soc_register_codec(&i2c->dev,
|
|
|
- driver, &ak4642_dai, 1);
|
|
|
+ &soc_codec_dev_ak4642, &ak4642_dai, 1);
|
|
|
}
|
|
|
|
|
|
static int ak4642_i2c_remove(struct i2c_client *client)
|
|
@@ -547,17 +552,17 @@ static int ak4642_i2c_remove(struct i2c_client *client)
|
|
|
}
|
|
|
|
|
|
static struct of_device_id ak4642_of_match[] = {
|
|
|
- { .compatible = "asahi-kasei,ak4642", .data = &soc_codec_dev_ak4642},
|
|
|
- { .compatible = "asahi-kasei,ak4643", .data = &soc_codec_dev_ak4642},
|
|
|
- { .compatible = "asahi-kasei,ak4648", .data = &soc_codec_dev_ak4648},
|
|
|
+ { .compatible = "asahi-kasei,ak4642", .data = &ak4642_regmap},
|
|
|
+ { .compatible = "asahi-kasei,ak4643", .data = &ak4642_regmap},
|
|
|
+ { .compatible = "asahi-kasei,ak4648", .data = &ak4648_regmap},
|
|
|
{},
|
|
|
};
|
|
|
MODULE_DEVICE_TABLE(of, ak4642_of_match);
|
|
|
|
|
|
static const struct i2c_device_id ak4642_i2c_id[] = {
|
|
|
- { "ak4642", (kernel_ulong_t)&soc_codec_dev_ak4642 },
|
|
|
- { "ak4643", (kernel_ulong_t)&soc_codec_dev_ak4642 },
|
|
|
- { "ak4648", (kernel_ulong_t)&soc_codec_dev_ak4648 },
|
|
|
+ { "ak4642", (kernel_ulong_t)&ak4642_regmap },
|
|
|
+ { "ak4643", (kernel_ulong_t)&ak4642_regmap },
|
|
|
+ { "ak4648", (kernel_ulong_t)&ak4648_regmap },
|
|
|
{ }
|
|
|
};
|
|
|
MODULE_DEVICE_TABLE(i2c, ak4642_i2c_id);
|