[alsa-devel] [PATCH 4/5] ASoC: ak4642: add ak4648 support

Kuninori Morimoto kuninori.morimoto.gx at renesas.com
Mon Nov 7 07:05:15 CET 2011


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 at 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);
-- 
1.7.5.4



More information about the Alsa-devel mailing list