[alsa-devel] [PATCH] ASoC: rt286: Add RL6347A class device shared support for RT286

Oder Chiou oder_chiou at realtek.com
Fri Jun 12 11:06:29 CEST 2015


The patch separates the IO function from the rt286. It is prepared to share
for new chips that support the same IO function.

Signed-off-by: Oder Chiou <oder_chiou at realtek.com>
---
 sound/soc/codecs/Kconfig   |   5 ++
 sound/soc/codecs/Makefile  |   2 +
 sound/soc/codecs/rl6347a.c | 128 +++++++++++++++++++++++++++++++++++++++++++++
 sound/soc/codecs/rl6347a.h |  32 ++++++++++++
 sound/soc/codecs/rt286.c   |  97 +++-------------------------------
 5 files changed, 173 insertions(+), 91 deletions(-)
 create mode 100644 sound/soc/codecs/rl6347a.c
 create mode 100644 sound/soc/codecs/rl6347a.h

diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
index 9b36011..efaafce 100644
--- a/sound/soc/codecs/Kconfig
+++ b/sound/soc/codecs/Kconfig
@@ -509,6 +509,11 @@ config SND_SOC_RL6231
 	default m if SND_SOC_RT5670=m
 	default m if SND_SOC_RT5677=m
 
+config SND_SOC_RL6347A
+	tristate
+	default y if SND_SOC_RT286=y
+	default m if SND_SOC_RT286=m
+
 config SND_SOC_RT286
 	tristate
 	depends on I2C
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile
index 3dcf5ac..cf160d9 100644
--- a/sound/soc/codecs/Makefile
+++ b/sound/soc/codecs/Makefile
@@ -77,6 +77,7 @@ snd-soc-pcm512x-objs := pcm512x.o
 snd-soc-pcm512x-i2c-objs := pcm512x-i2c.o
 snd-soc-pcm512x-spi-objs := pcm512x-spi.o
 snd-soc-rl6231-objs := rl6231.o
+snd-soc-rl6347a-objs := rl6347a.o
 snd-soc-rt286-objs := rt286.o
 snd-soc-rt5631-objs := rt5631.o
 snd-soc-rt5640-objs := rt5640.o
@@ -263,6 +264,7 @@ obj-$(CONFIG_SND_SOC_PCM512x)	+= snd-soc-pcm512x.o
 obj-$(CONFIG_SND_SOC_PCM512x_I2C)	+= snd-soc-pcm512x-i2c.o
 obj-$(CONFIG_SND_SOC_PCM512x_SPI)	+= snd-soc-pcm512x-spi.o
 obj-$(CONFIG_SND_SOC_RL6231)	+= snd-soc-rl6231.o
+obj-$(CONFIG_SND_SOC_RL6347A)	+= snd-soc-rl6347a.o
 obj-$(CONFIG_SND_SOC_RT286)	+= snd-soc-rt286.o
 obj-$(CONFIG_SND_SOC_RT5631)	+= snd-soc-rt5631.o
 obj-$(CONFIG_SND_SOC_RT5640)	+= snd-soc-rt5640.o
diff --git a/sound/soc/codecs/rl6347a.c b/sound/soc/codecs/rl6347a.c
new file mode 100644
index 0000000..91d5166
--- /dev/null
+++ b/sound/soc/codecs/rl6347a.c
@@ -0,0 +1,128 @@
+/*
+ * rl6347a.c - RL6347A class device shared support
+ *
+ * Copyright 2015 Realtek Semiconductor Corp.
+ *
+ * Author: Oder Chiou <oder_chiou at realtek.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/pm.h>
+#include <linux/i2c.h>
+#include <linux/platform_device.h>
+#include <linux/spi/spi.h>
+#include <linux/dmi.h>
+#include <linux/acpi.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+#include <sound/initval.h>
+#include <sound/tlv.h>
+#include <sound/jack.h>
+#include <linux/workqueue.h>
+#include <sound/hda_verbs.h>
+
+#include "rl6347a.h"
+
+int rl6347a_hw_write(void *context, unsigned int reg, unsigned int value)
+{
+	struct i2c_client *client = context;
+	struct rl6347a_priv *rl6347a = i2c_get_clientdata(client);
+	u8 data[4];
+	int ret, i;
+
+	/* handle index registers */
+	if (reg <= 0xff) {
+		rl6347a_hw_write(client, RL6347A_COEF_INDEX, reg);
+		for (i = 0; i < rl6347a->index_cache_size; i++) {
+			if (reg == rl6347a->index_cache[i].reg) {
+				rl6347a->index_cache[i].def = value;
+				break;
+			}
+
+		}
+		reg = RL6347A_PROC_COEF;
+	}
+
+	data[0] = (reg >> 24) & 0xff;
+	data[1] = (reg >> 16) & 0xff;
+	/*
+	 * 4 bit VID: reg should be 0
+	 * 12 bit VID: value should be 0
+	 * So we use an OR operator to handle it rather than use if condition.
+	 */
+	data[2] = ((reg >> 8) & 0xff) | ((value >> 8) & 0xff);
+	data[3] = value & 0xff;
+
+	ret = i2c_master_send(client, data, 4);
+
+	if (ret == 4)
+		return 0;
+	else
+		pr_err("ret=%d\n", ret);
+	if (ret < 0)
+		return ret;
+	else
+		return -EIO;
+}
+EXPORT_SYMBOL_GPL(rl6347a_hw_write);
+
+int rl6347a_hw_read(void *context, unsigned int reg, unsigned int *value)
+{
+	struct i2c_client *client = context;
+	struct i2c_msg xfer[2];
+	int ret;
+	__be32 be_reg;
+	unsigned int index, vid, buf = 0x0;
+
+	/* handle index registers */
+	if (reg <= 0xff) {
+		rl6347a_hw_write(client, RL6347A_COEF_INDEX, reg);
+		reg = RL6347A_PROC_COEF;
+	}
+
+	reg = reg | 0x80000;
+	vid = (reg >> 8) & 0xfff;
+
+	if (AC_VERB_GET_AMP_GAIN_MUTE == (vid & 0xf00)) {
+		index = (reg >> 8) & 0xf;
+		reg = (reg & ~0xf0f) | index;
+	}
+	be_reg = cpu_to_be32(reg);
+
+	/* Write register */
+	xfer[0].addr = client->addr;
+	xfer[0].flags = 0;
+	xfer[0].len = 4;
+	xfer[0].buf = (u8 *)&be_reg;
+
+	/* Read data */
+	xfer[1].addr = client->addr;
+	xfer[1].flags = I2C_M_RD;
+	xfer[1].len = 4;
+	xfer[1].buf = (u8 *)&buf;
+
+	ret = i2c_transfer(client->adapter, xfer, 2);
+	if (ret < 0)
+		return ret;
+	else if (ret != 2)
+		return -EIO;
+
+	*value = be32_to_cpu(buf);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(rl6347a_hw_read);
+
+MODULE_DESCRIPTION("RL6347A class device shared support");
+MODULE_AUTHOR("Oder Chiou <oder_chiou at realtek.com>");
+MODULE_LICENSE("GPL v2");
diff --git a/sound/soc/codecs/rl6347a.h b/sound/soc/codecs/rl6347a.h
new file mode 100644
index 0000000..1cb56e5
--- /dev/null
+++ b/sound/soc/codecs/rl6347a.h
@@ -0,0 +1,32 @@
+/*
+ * rl6347a.h - RL6347A class device shared support
+ *
+ * Copyright 2015 Realtek Semiconductor Corp.
+ *
+ * Author: Oder Chiou <oder_chiou at realtek.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#ifndef __RL6347A_H__
+#define __RL6347A_H__
+
+#define VERB_CMD(V, N, D) ((N << 20) | (V << 8) | D)
+
+#define RL6347A_VENDOR_REGISTERS	0x20
+
+#define RL6347A_COEF_INDEX\
+	VERB_CMD(AC_VERB_SET_COEF_INDEX, RL6347A_VENDOR_REGISTERS, 0)
+#define RL6347A_PROC_COEF\
+	VERB_CMD(AC_VERB_SET_PROC_COEF, RL6347A_VENDOR_REGISTERS, 0)
+
+struct rl6347a_priv {
+	struct reg_default *index_cache;
+	int index_cache_size;
+};
+
+int rl6347a_hw_write(void *context, unsigned int reg, unsigned int value);
+int rl6347a_hw_read(void *context, unsigned int reg, unsigned int *value);
+
+#endif /* __RL6347A_H__ */
diff --git a/sound/soc/codecs/rt286.c b/sound/soc/codecs/rt286.c
index c6cca06..5c43e26 100644
--- a/sound/soc/codecs/rt286.c
+++ b/sound/soc/codecs/rt286.c
@@ -31,12 +31,15 @@
 #include <sound/rt286.h>
 #include <sound/hda_verbs.h>
 
+#include "rl6347a.h"
 #include "rt286.h"
 
 #define RT286_VENDOR_ID 0x10ec0286
 #define RT288_VENDOR_ID 0x10ec0288
 
 struct rt286_priv {
+	struct reg_default *index_cache;
+	int index_cache_size;
 	struct regmap *regmap;
 	struct snd_soc_codec *codec;
 	struct rt286_platform_data pdata;
@@ -45,7 +48,6 @@ struct rt286_priv {
 	struct delayed_work jack_detect_work;
 	int sys_clk;
 	int clk_id;
-	struct reg_default *index_cache;
 };
 
 static struct reg_default rt286_index_def[] = {
@@ -185,94 +187,6 @@ static bool rt286_readable_register(struct device *dev, unsigned int reg)
 	}
 }
 
-static int rt286_hw_write(void *context, unsigned int reg, unsigned int value)
-{
-	struct i2c_client *client = context;
-	struct rt286_priv *rt286 = i2c_get_clientdata(client);
-	u8 data[4];
-	int ret, i;
-
-	/* handle index registers */
-	if (reg <= 0xff) {
-		rt286_hw_write(client, RT286_COEF_INDEX, reg);
-		for (i = 0; i < INDEX_CACHE_SIZE; i++) {
-			if (reg == rt286->index_cache[i].reg) {
-				rt286->index_cache[i].def = value;
-				break;
-			}
-
-		}
-		reg = RT286_PROC_COEF;
-	}
-
-	data[0] = (reg >> 24) & 0xff;
-	data[1] = (reg >> 16) & 0xff;
-	/*
-	 * 4 bit VID: reg should be 0
-	 * 12 bit VID: value should be 0
-	 * So we use an OR operator to handle it rather than use if condition.
-	 */
-	data[2] = ((reg >> 8) & 0xff) | ((value >> 8) & 0xff);
-	data[3] = value & 0xff;
-
-	ret = i2c_master_send(client, data, 4);
-
-	if (ret == 4)
-		return 0;
-	else
-		pr_err("ret=%d\n", ret);
-	if (ret < 0)
-		return ret;
-	else
-		return -EIO;
-}
-
-static int rt286_hw_read(void *context, unsigned int reg, unsigned int *value)
-{
-	struct i2c_client *client = context;
-	struct i2c_msg xfer[2];
-	int ret;
-	__be32 be_reg;
-	unsigned int index, vid, buf = 0x0;
-
-	/* handle index registers */
-	if (reg <= 0xff) {
-		rt286_hw_write(client, RT286_COEF_INDEX, reg);
-		reg = RT286_PROC_COEF;
-	}
-
-	reg = reg | 0x80000;
-	vid = (reg >> 8) & 0xfff;
-
-	if (AC_VERB_GET_AMP_GAIN_MUTE == (vid & 0xf00)) {
-		index = (reg >> 8) & 0xf;
-		reg = (reg & ~0xf0f) | index;
-	}
-	be_reg = cpu_to_be32(reg);
-
-	/* Write register */
-	xfer[0].addr = client->addr;
-	xfer[0].flags = 0;
-	xfer[0].len = 4;
-	xfer[0].buf = (u8 *)&be_reg;
-
-	/* Read data */
-	xfer[1].addr = client->addr;
-	xfer[1].flags = I2C_M_RD;
-	xfer[1].len = 4;
-	xfer[1].buf = (u8 *)&buf;
-
-	ret = i2c_transfer(client->adapter, xfer, 2);
-	if (ret < 0)
-		return ret;
-	else if (ret != 2)
-		return -EIO;
-
-	*value = be32_to_cpu(buf);
-
-	return 0;
-}
-
 #ifdef CONFIG_PM
 static void rt286_index_sync(struct snd_soc_codec *codec)
 {
@@ -1174,8 +1088,8 @@ static const struct regmap_config rt286_regmap = {
 	.max_register = 0x02370100,
 	.volatile_reg = rt286_volatile_register,
 	.readable_reg = rt286_readable_register,
-	.reg_write = rt286_hw_write,
-	.reg_read = rt286_hw_read,
+	.reg_write = rl6347a_hw_write,
+	.reg_read = rl6347a_hw_read,
 	.cache_type = REGCACHE_RBTREE,
 	.reg_defaults = rt286_reg,
 	.num_reg_defaults = ARRAY_SIZE(rt286_reg),
@@ -1248,6 +1162,7 @@ static int rt286_i2c_probe(struct i2c_client *i2c,
 	}
 
 	rt286->index_cache = rt286_index_def;
+	rt286->index_cache_size = INDEX_CACHE_SIZE;
 	rt286->i2c = i2c;
 	i2c_set_clientdata(i2c, rt286);
 
-- 
1.8.1.1.439.g50a6b54



More information about the Alsa-devel mailing list