This patch adds ak4648 support. ak4642/ak4643/ak4648 are register compatible, but these have a slightly different register default value. struct ak4642_chip is added in order to absorb this difference.
Signed-off-by: Kuninori Morimoto kuninori.morimoto.gx@renesas.com --- sound/soc/codecs/ak4642.c | 74 +++++++++++++++++++++++++++++++++++++++----- 1 files changed, 65 insertions(+), 9 deletions(-)
diff --git a/sound/soc/codecs/ak4642.c b/sound/soc/codecs/ak4642.c index f30e434..1b768ad 100644 --- a/sound/soc/codecs/ak4642.c +++ b/sound/soc/codecs/ak4642.c @@ -20,6 +20,7 @@ * * AK4642 is tested. * AK4643 is tested. + * AK4648 is tested. */
#include <linux/delay.h> @@ -70,8 +71,6 @@ #define HP_MS 0x23 #define SPK_MS 0x24
-#define AK4642_CACHEREGNUM 0x25 - /* PW_MGMT1*/ #define PMVCM (1 << 6) /* VCOM Power Management */ #define PMMIN (1 << 5) /* MIN Input Power Management */ @@ -158,28 +157,58 @@ static const struct snd_kcontrol_new ak4642_snd_controls[] = { 0, 0xFF, 1, out_tlv), };
+/* + * ak464x list + */ + +#define AK4642_CACHEREGNUM (0x24 + 1) +#define AK4648_CACHEREGNUM (0x27 + 1) +#define AK464x_CACHEREGNUM_MAX AK4648_CACHEREGNUM /* max size */
/* codec private data */ +struct ak4642_reg_fix { + unsigned int reg; + unsigned int val; +}; + +struct ak4642_chip { + int reg_max; + struct ak4642_reg_fix *reg_fix; + int reg_fix_size; +}; + struct ak4642_priv { unsigned int sysclk; enum snd_soc_control_type control_type; void *control_data; + struct ak4642_chip *chip; };
/* * ak4642 register cache */ -static const u8 ak4642_reg[AK4642_CACHEREGNUM] = { +static const u8 ak4642_reg[AK464x_CACHEREGNUM_MAX] = { 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0xe1, 0xe1, 0x18, 0x00, - 0xe1, 0x18, 0x11, 0x08, + 0xe1, 0x18, 0x11, 0xff, /* 0xF will be fixed */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, + 0x00, 0xff, 0xff, 0xff, /* 0x25 - 0x27 will be fixed */ +}; + +static struct ak4642_reg_fix ak4642_reg_fix[] = { + { 0xF, 0x08 } +}; + +static struct ak4642_reg_fix ak4648_reg_fix[] = { + { 0xF, 0xb8 }, + { 0x25, 0x88 }, + { 0x26, 0x88 }, + { 0x27, 0x08 }, };
/* @@ -496,6 +525,8 @@ 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); + struct ak4642_chip *chip = ak4642->chip; + int i;
dev_info(codec->dev, "AK4642 Audio Codec %s", AK4642_VERSION);
@@ -505,6 +536,15 @@ static int ak4642_probe(struct snd_soc_codec *codec) snd_soc_add_controls(codec, ak4642_snd_controls, ARRAY_SIZE(ak4642_snd_controls));
+ /* + * fixup register cache + * each ak464x have a slightly different value + */ + for (i = 0; i < chip->reg_fix_size; i++) + ak4642_write_reg_cache(codec, + chip->reg_fix[i].reg, + chip->reg_fix[i].val); + return 0; }
@@ -530,8 +570,9 @@ static __devinit int ak4642_i2c_probe(struct i2c_client *i2c, return -ENOMEM;
i2c_set_clientdata(i2c, ak4642); - ak4642->control_data = i2c; - ak4642->control_type = SND_SOC_I2C; + ak4642->control_data = i2c; + ak4642->control_type = SND_SOC_I2C; + ak4642->chip = (struct ak4642_chip *)id->driver_data;
ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_ak4642, &ak4642_dai, 1); @@ -547,9 +588,24 @@ static __devexit int ak4642_i2c_remove(struct i2c_client *client) return 0; }
+/* ak4642 / ak4643 */ +static const struct ak4642_chip ak4642_chip = { + .reg_max = AK4642_CACHEREGNUM, + .reg_fix = ak4642_reg_fix, + .reg_fix_size = ARRAY_SIZE(ak4642_reg_fix), +}; + +/* ak4648 */ +static const struct ak4642_chip ak4648_chip = { + .reg_max = AK4648_CACHEREGNUM, + .reg_fix = ak4648_reg_fix, + .reg_fix_size = ARRAY_SIZE(ak4648_reg_fix), +}; + static const struct i2c_device_id ak4642_i2c_id[] = { - { "ak4642", 0 }, - { "ak4643", 0 }, + { "ak4642", (kernel_ulong_t)&ak4642_chip }, + { "ak4643", (kernel_ulong_t)&ak4642_chip }, /* same as ak4642 */ + { "ak4648", (kernel_ulong_t)&ak4648_chip }, { } }; MODULE_DEVICE_TABLE(i2c, ak4642_i2c_id);