|
@@ -22,6 +22,7 @@
|
|
|
#include <linux/pm.h>
|
|
|
#include <linux/i2c.h>
|
|
|
#include <linux/slab.h>
|
|
|
+#include <linux/regmap.h>
|
|
|
#include <sound/core.h>
|
|
|
#include <sound/pcm.h>
|
|
|
#include <sound/pcm_params.h>
|
|
@@ -34,45 +35,129 @@
|
|
|
/*
|
|
|
* ALC5632 register cache
|
|
|
*/
|
|
|
-static const u16 alc5632_reg_defaults[] = {
|
|
|
- 0x59B4, 0x0000, 0x8080, 0x0000, /* 0 */
|
|
|
- 0x8080, 0x0000, 0x8080, 0x0000, /* 4 */
|
|
|
- 0xC800, 0x0000, 0xE808, 0x0000, /* 8 */
|
|
|
- 0x1010, 0x0000, 0x0808, 0x0000, /* 12 */
|
|
|
- 0xEE0F, 0x0000, 0xCBCB, 0x0000, /* 16 */
|
|
|
- 0x7F7F, 0x0000, 0x0000, 0x0000, /* 20 */
|
|
|
- 0xE010, 0x0000, 0x0000, 0x0000, /* 24 */
|
|
|
- 0x8008, 0x0000, 0x0000, 0x0000, /* 28 */
|
|
|
- 0x0000, 0x0000, 0x0000, 0x0000, /* 32 */
|
|
|
- 0x00C0, 0x0000, 0xEF00, 0x0000, /* 36 */
|
|
|
- 0x0000, 0x0000, 0x0000, 0x0000, /* 40 */
|
|
|
- 0x0000, 0x0000, 0x0000, 0x0000, /* 44 */
|
|
|
- 0x0000, 0x0000, 0x0000, 0x0000, /* 48 */
|
|
|
- 0x8000, 0x0000, 0x0000, 0x0000, /* 52 */
|
|
|
- 0x0000, 0x0000, 0x0000, 0x0000, /* 56 */
|
|
|
- 0x0000, 0x0000, 0x8000, 0x0000, /* 60 */
|
|
|
- 0x0C0A, 0x0000, 0x0000, 0x0000, /* 64 */
|
|
|
- 0x0000, 0x0000, 0x0000, 0x0000, /* 68 */
|
|
|
- 0x0000, 0x0000, 0x0000, 0x0000, /* 72 */
|
|
|
- 0xBE3E, 0x0000, 0xBE3E, 0x0000, /* 76 */
|
|
|
- 0x0000, 0x0000, 0x0000, 0x0000, /* 80 */
|
|
|
- 0x803A, 0x0000, 0x0000, 0x0000, /* 84 */
|
|
|
- 0x0000, 0x0000, 0x0009, 0x0000, /* 88 */
|
|
|
- 0x0000, 0x0000, 0x3000, 0x0000, /* 92 */
|
|
|
- 0x3075, 0x0000, 0x1010, 0x0000, /* 96 */
|
|
|
- 0x3110, 0x0000, 0x0000, 0x0000, /* 100 */
|
|
|
- 0x0553, 0x0000, 0x0000, 0x0000, /* 104 */
|
|
|
- 0x0000, 0x0000, 0x0000, 0x0000, /* 108 */
|
|
|
+static struct reg_default alc5632_reg_defaults[] = {
|
|
|
+ { 0, 0x59B4 },
|
|
|
+ { 1, 0x0000 },
|
|
|
+ { 2, 0x8080 },
|
|
|
+ { 3, 0x0000 },
|
|
|
+ { 4, 0x8080 },
|
|
|
+ { 5, 0x0000 },
|
|
|
+ { 6, 0x8080 },
|
|
|
+ { 7, 0x0000 },
|
|
|
+ { 8, 0xC800 },
|
|
|
+ { 9, 0x0000 },
|
|
|
+ { 10, 0xE808 },
|
|
|
+ { 11, 0x0000 },
|
|
|
+ { 12, 0x1010 },
|
|
|
+ { 13, 0x0000 },
|
|
|
+ { 14, 0x0808 },
|
|
|
+ { 15, 0x0000 },
|
|
|
+ { 16, 0xEE0F },
|
|
|
+ { 17, 0x0000 },
|
|
|
+ { 18, 0xCBCB },
|
|
|
+ { 19, 0x0000 },
|
|
|
+ { 20, 0x7F7F },
|
|
|
+ { 21, 0x0000 },
|
|
|
+ { 22, 0x0000 },
|
|
|
+ { 23, 0x0000 },
|
|
|
+ { 24, 0xE010 },
|
|
|
+ { 25, 0x0000 },
|
|
|
+ { 26, 0x0000 },
|
|
|
+ { 27, 0x0000 },
|
|
|
+ { 28, 0x8008 },
|
|
|
+ { 29, 0x0000 },
|
|
|
+ { 30, 0x0000 },
|
|
|
+ { 31, 0x0000 },
|
|
|
+ { 32, 0x0000 },
|
|
|
+ { 33, 0x0000 },
|
|
|
+ { 34, 0x0000 },
|
|
|
+ { 35, 0x0000 },
|
|
|
+ { 36, 0x00C0 },
|
|
|
+ { 37, 0x0000 },
|
|
|
+ { 38, 0xEF00 },
|
|
|
+ { 39, 0x0000 },
|
|
|
+ { 40, 0x0000 },
|
|
|
+ { 41, 0x0000 },
|
|
|
+ { 42, 0x0000 },
|
|
|
+ { 43, 0x0000 },
|
|
|
+ { 44, 0x0000 },
|
|
|
+ { 45, 0x0000 },
|
|
|
+ { 46, 0x0000 },
|
|
|
+ { 47, 0x0000 },
|
|
|
+ { 48, 0x0000 },
|
|
|
+ { 49, 0x0000 },
|
|
|
+ { 50, 0x0000 },
|
|
|
+ { 51, 0x0000 },
|
|
|
+ { 52, 0x8000 },
|
|
|
+ { 53, 0x0000 },
|
|
|
+ { 54, 0x0000 },
|
|
|
+ { 55, 0x0000 },
|
|
|
+ { 56, 0x0000 },
|
|
|
+ { 57, 0x0000 },
|
|
|
+ { 58, 0x0000 },
|
|
|
+ { 59, 0x0000 },
|
|
|
+ { 60, 0x0000 },
|
|
|
+ { 61, 0x0000 },
|
|
|
+ { 62, 0x8000 },
|
|
|
+ { 63, 0x0000 },
|
|
|
+ { 64, 0x0C0A },
|
|
|
+ { 65, 0x0000 },
|
|
|
+ { 66, 0x0000 },
|
|
|
+ { 67, 0x0000 },
|
|
|
+ { 68, 0x0000 },
|
|
|
+ { 69, 0x0000 },
|
|
|
+ { 70, 0x0000 },
|
|
|
+ { 71, 0x0000 },
|
|
|
+ { 72, 0x0000 },
|
|
|
+ { 73, 0x0000 },
|
|
|
+ { 74, 0x0000 },
|
|
|
+ { 75, 0x0000 },
|
|
|
+ { 76, 0xBE3E },
|
|
|
+ { 77, 0x0000 },
|
|
|
+ { 78, 0xBE3E },
|
|
|
+ { 79, 0x0000 },
|
|
|
+ { 80, 0x0000 },
|
|
|
+ { 81, 0x0000 },
|
|
|
+ { 82, 0x0000 },
|
|
|
+ { 83, 0x0000 },
|
|
|
+ { 84, 0x803A },
|
|
|
+ { 85, 0x0000 },
|
|
|
+ { 86, 0x0000 },
|
|
|
+ { 87, 0x0000 },
|
|
|
+ { 88, 0x0000 },
|
|
|
+ { 89, 0x0000 },
|
|
|
+ { 90, 0x0009 },
|
|
|
+ { 91, 0x0000 },
|
|
|
+ { 92, 0x0000 },
|
|
|
+ { 93, 0x0000 },
|
|
|
+ { 94, 0x3000 },
|
|
|
+ { 95, 0x0000 },
|
|
|
+ { 96, 0x3075 },
|
|
|
+ { 97, 0x0000 },
|
|
|
+ { 98, 0x1010 },
|
|
|
+ { 99, 0x0000 },
|
|
|
+ { 100, 0x3110 },
|
|
|
+ { 101, 0x0000 },
|
|
|
+ { 102, 0x0000 },
|
|
|
+ { 103, 0x0000 },
|
|
|
+ { 104, 0x0553 },
|
|
|
+ { 105, 0x0000 },
|
|
|
+ { 106, 0x0000 },
|
|
|
+ { 107, 0x0000 },
|
|
|
+ { 108, 0x0000 },
|
|
|
+ { 109, 0x0000 },
|
|
|
+ { 110, 0x0000 },
|
|
|
+ { 111, 0x0000 },
|
|
|
};
|
|
|
|
|
|
/* codec private data */
|
|
|
struct alc5632_priv {
|
|
|
- enum snd_soc_control_type control_type;
|
|
|
+ struct regmap *regmap;
|
|
|
u8 id;
|
|
|
unsigned int sysclk;
|
|
|
};
|
|
|
|
|
|
-static int alc5632_volatile_register(struct snd_soc_codec *codec,
|
|
|
+static bool alc5632_volatile_register(struct device *dev,
|
|
|
unsigned int reg)
|
|
|
{
|
|
|
switch (reg) {
|
|
@@ -82,19 +167,18 @@ static int alc5632_volatile_register(struct snd_soc_codec *codec,
|
|
|
case ALC5632_OVER_CURR_STATUS:
|
|
|
case ALC5632_HID_CTRL_DATA:
|
|
|
case ALC5632_EQ_CTRL:
|
|
|
- return 1;
|
|
|
+ return true;
|
|
|
|
|
|
default:
|
|
|
break;
|
|
|
}
|
|
|
|
|
|
- return 0;
|
|
|
+ return false;
|
|
|
}
|
|
|
|
|
|
-static inline int alc5632_reset(struct snd_soc_codec *codec)
|
|
|
+static inline int alc5632_reset(struct regmap *map)
|
|
|
{
|
|
|
- snd_soc_write(codec, ALC5632_RESET, 0);
|
|
|
- return snd_soc_read(codec, ALC5632_RESET);
|
|
|
+ return regmap_write(map, ALC5632_RESET, 0x59B4);
|
|
|
}
|
|
|
|
|
|
static int amp_mixer_event(struct snd_soc_dapm_widget *w,
|
|
@@ -948,16 +1032,9 @@ static int alc5632_suspend(struct snd_soc_codec *codec, pm_message_t mesg)
|
|
|
|
|
|
static int alc5632_resume(struct snd_soc_codec *codec)
|
|
|
{
|
|
|
- int ret;
|
|
|
-
|
|
|
- /* mark cache as needed to sync */
|
|
|
- codec->cache_sync = 1;
|
|
|
+ struct alc5632_priv *alc5632 = snd_soc_codec_get_drvdata(codec);
|
|
|
|
|
|
- ret = snd_soc_cache_sync(codec);
|
|
|
- if (ret != 0) {
|
|
|
- dev_err(codec->dev, "Failed to sync cache: %d\n", ret);
|
|
|
- return ret;
|
|
|
- }
|
|
|
+ regcache_sync(alc5632->regmap);
|
|
|
|
|
|
alc5632_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
|
|
|
return 0;
|
|
@@ -972,14 +1049,14 @@ static int alc5632_probe(struct snd_soc_codec *codec)
|
|
|
struct alc5632_priv *alc5632 = snd_soc_codec_get_drvdata(codec);
|
|
|
int ret;
|
|
|
|
|
|
- ret = snd_soc_codec_set_cache_io(codec, 8, 16, alc5632->control_type);
|
|
|
- if (ret < 0) {
|
|
|
+ codec->control_data = alc5632->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;
|
|
|
}
|
|
|
|
|
|
- alc5632_reset(codec);
|
|
|
-
|
|
|
/* power on device */
|
|
|
alc5632_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
|
|
|
|
|
@@ -1008,11 +1085,6 @@ static struct snd_soc_codec_driver soc_codec_device_alc5632 = {
|
|
|
.suspend = alc5632_suspend,
|
|
|
.resume = alc5632_resume,
|
|
|
.set_bias_level = alc5632_set_bias_level,
|
|
|
- .reg_word_size = sizeof(u16),
|
|
|
- .reg_cache_step = 2,
|
|
|
- .reg_cache_default = alc5632_reg_defaults,
|
|
|
- .reg_cache_size = ARRAY_SIZE(alc5632_reg_defaults),
|
|
|
- .volatile_register = alc5632_volatile_register,
|
|
|
.controls = alc5632_snd_controls,
|
|
|
.num_controls = ARRAY_SIZE(alc5632_snd_controls),
|
|
|
.dapm_widgets = alc5632_dapm_widgets,
|
|
@@ -1021,13 +1093,24 @@ static struct snd_soc_codec_driver soc_codec_device_alc5632 = {
|
|
|
.num_dapm_routes = ARRAY_SIZE(alc5632_dapm_routes),
|
|
|
};
|
|
|
|
|
|
+static struct regmap_config alc5632_regmap = {
|
|
|
+ .reg_bits = 8,
|
|
|
+ .val_bits = 16,
|
|
|
+
|
|
|
+ .max_register = ALC5632_MAX_REGISTER,
|
|
|
+ .reg_defaults = alc5632_reg_defaults,
|
|
|
+ .num_reg_defaults = ARRAY_SIZE(alc5632_reg_defaults),
|
|
|
+ .volatile_reg = alc5632_volatile_register,
|
|
|
+ .cache_type = REGCACHE_RBTREE,
|
|
|
+};
|
|
|
+
|
|
|
/*
|
|
|
* alc5632 2 wire address is determined by A1 pin
|
|
|
* state during powerup.
|
|
|
* low = 0x1a
|
|
|
* high = 0x1b
|
|
|
*/
|
|
|
-static int alc5632_i2c_probe(struct i2c_client *client,
|
|
|
+static __devinit int alc5632_i2c_probe(struct i2c_client *client,
|
|
|
const struct i2c_device_id *id)
|
|
|
{
|
|
|
struct alc5632_priv *alc5632;
|
|
@@ -1074,20 +1157,38 @@ static int alc5632_i2c_probe(struct i2c_client *client,
|
|
|
}
|
|
|
|
|
|
i2c_set_clientdata(client, alc5632);
|
|
|
- alc5632->control_type = SND_SOC_I2C;
|
|
|
+
|
|
|
+ alc5632->regmap = regmap_init_i2c(client, &alc5632_regmap);
|
|
|
+ if (IS_ERR(alc5632->regmap)) {
|
|
|
+ ret = PTR_ERR(alc5632->regmap);
|
|
|
+ dev_err(&client->dev, "regmap_init() failed: %d\n", ret);
|
|
|
+ return ret;
|
|
|
+ }
|
|
|
+
|
|
|
+ ret = alc5632_reset(alc5632->regmap);
|
|
|
+ if (ret < 0) {
|
|
|
+ dev_err(&client->dev, "Failed to issue reset\n");
|
|
|
+ regmap_exit(alc5632->regmap);
|
|
|
+ return ret;
|
|
|
+ }
|
|
|
|
|
|
ret = snd_soc_register_codec(&client->dev,
|
|
|
&soc_codec_device_alc5632, &alc5632_dai, 1);
|
|
|
- if (ret != 0)
|
|
|
+
|
|
|
+ if (ret < 0) {
|
|
|
dev_err(&client->dev, "Failed to register codec: %d\n", ret);
|
|
|
+ regmap_exit(alc5632->regmap);
|
|
|
+ return ret;
|
|
|
+ }
|
|
|
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
|
static int alc5632_i2c_remove(struct i2c_client *client)
|
|
|
{
|
|
|
+ struct alc5632_priv *alc5632 = i2c_get_clientdata(client);
|
|
|
snd_soc_unregister_codec(&client->dev);
|
|
|
-
|
|
|
+ regmap_exit(alc5632->regmap);
|
|
|
return 0;
|
|
|
}
|
|
|
|