All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] ASoC: rt-sdw-common: Common functions for Realtek soundwire driver
@ 2024-10-01  7:00 Jack Yu
  0 siblings, 0 replies; only message in thread
From: Jack Yu @ 2024-10-01  7:00 UTC (permalink / raw)
  To: broonie@kernel.org, lgirdwood@gmail.com
  Cc: alsa-devel@alsa-project.org, lars@metafoo.de, Flove(HsinFu),
	Oder Chiou, Shuming [范書銘],
	Derek [方德義], Jack Yu

[-- Attachment #1: Type: text/plain, Size: 10875 bytes --]

This is the first version of common functions for Realtek
soundwire codec driver.

Signed-off-by: Jack Yu <jack.yu@realtek.com>
---
 sound/soc/codecs/Kconfig         |   5 +
 sound/soc/codecs/Makefile        |   2 +
 sound/soc/codecs/rt-sdw-common.c | 241 +++++++++++++++++++++++++++++++
 sound/soc/codecs/rt-sdw-common.h |  67 +++++++++
 4 files changed, 315 insertions(+)
 create mode 100644 sound/soc/codecs/rt-sdw-common.c
 create mode 100644 sound/soc/codecs/rt-sdw-common.h

diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
index 7092842480ef..b095eba9d634 100644
--- a/sound/soc/codecs/Kconfig
+++ b/sound/soc/codecs/Kconfig
@@ -1545,6 +1545,11 @@ config SND_SOC_RL6231
 	default m if SND_SOC_RT1305=m
 	default m if SND_SOC_RT1308=m
 
+config SND_SOC_RT_SDW_COMMON
+	tristate
+	default y if SND_SOC_RT721_SDCA_SDW=y
+	default m if SND_SOC_RT721_SDCA_SDW=m
+
 config SND_SOC_RL6347A
 	tristate
 	default y if SND_SOC_RT274=y
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile
index 54cbc3feae32..4497b2e30cd3 100644
--- a/sound/soc/codecs/Makefile
+++ b/sound/soc/codecs/Makefile
@@ -216,6 +216,7 @@ snd-soc-rk3308-y := rk3308_codec.o
 snd-soc-rk3328-y := rk3328_codec.o
 snd-soc-rk817-y := rk817_codec.o
 snd-soc-rl6231-y := rl6231.o
+snd-soc-rt-sdw-common-y := rt-sdw-common.o
 snd-soc-rl6347a-y := rl6347a.o
 snd-soc-rt1011-y := rt1011.o
 snd-soc-rt1015-y := rt1015.o
@@ -618,6 +619,7 @@ obj-$(CONFIG_SND_SOC_RK3308)	+= snd-soc-rk3308.o
 obj-$(CONFIG_SND_SOC_RK3328)	+= snd-soc-rk3328.o
 obj-$(CONFIG_SND_SOC_RK817)	+= snd-soc-rk817.o
 obj-$(CONFIG_SND_SOC_RL6231)	+= snd-soc-rl6231.o
+obj-$(CONFIG_SND_SOC_RT_SDW_COMMON)	+= snd-soc-rt-sdw-common.o
 obj-$(CONFIG_SND_SOC_RL6347A)	+= snd-soc-rl6347a.o
 obj-$(CONFIG_SND_SOC_RT1011)	+= snd-soc-rt1011.o
 obj-$(CONFIG_SND_SOC_RT1015)	+= snd-soc-rt1015.o
diff --git a/sound/soc/codecs/rt-sdw-common.c b/sound/soc/codecs/rt-sdw-common.c
new file mode 100644
index 000000000000..e758567e9c58
--- /dev/null
+++ b/sound/soc/codecs/rt-sdw-common.c
@@ -0,0 +1,241 @@
+// SPDX-License-Identifier: GPL-2.0-only
+//
+// rt-sdw-common.c
+//
+// Copyright(c) 2024 Realtek Semiconductor Corp.
+//
+
+/*
+ * This file defines common functions used with Realtek soundwire codecs.
+ */
+
+#include <linux/module.h>
+#include <linux/regmap.h>
+#include <linux/bitops.h>
+#include <linux/soundwire/sdw_registers.h>
+#include <sound/jack.h>
+
+#include "rt-sdw-common.h"
+
+/**
+ * rt_sdca_index_write - Write a value to Realtek defined register.
+ *
+ * @map: map for setting.
+ * @nid: Realtek-defined ID.
+ * @reg: register.
+ * @value: value.
+ *
+ * A value of zero will be returned on success, a negative errno will
+ * be returned in error cases.
+ */
+int rt_sdca_index_write(struct regmap *map, unsigned int nid,
+	unsigned int reg, unsigned int value)
+{
+	unsigned int addr = (nid << 20) | reg;
+	int ret;
+
+	ret = regmap_write(map, addr, value);
+	if (ret < 0)
+		pr_err("Failed to set value: %06x <= %04x ret=%d\n",
+			addr, value, ret);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(rt_sdca_index_write);
+
+/**
+ * rt_sdca_index_read - Read value from Realtek defined register.
+ *
+ * @map: map for setting.
+ * @nid: Realtek-defined ID.
+ * @reg: register.
+ * @value: value.
+ *
+ * A value of zero will be returned on success, a negative errno will
+ * be returned in error cases.
+ */
+int rt_sdca_index_read(struct regmap *map, unsigned int nid,
+	unsigned int reg, unsigned int *value)
+{
+	unsigned int addr = (nid << 20) | reg;
+	int ret;
+
+	ret = regmap_read(map, addr, value);
+	if (ret < 0)
+		pr_err("Failed to get value: %06x => %04x ret=%d\n",
+			addr, *value, ret);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(rt_sdca_index_read);
+
+/**
+ * rt_sdca_index_update_bits - Update value on Realtek defined register.
+ *
+ * @map: map for setting.
+ * @nid: Realtek-defined ID.
+ * @reg: register.
+ * @mask: Bitmask to change
+ * @value: New value for bitmask
+ *
+ * A value of zero will be returned on success, a negative errno will
+ * be returned in error cases.
+ */
+
+int rt_sdca_index_update_bits(struct regmap *map,
+	unsigned int nid, unsigned int reg, unsigned int mask, unsigned int val)
+{
+	unsigned int tmp;
+	int ret;
+
+	ret = rt_sdca_index_read(map, nid, reg, &tmp);
+	if (ret < 0)
+		return ret;
+
+	set_mask_bits(&tmp, mask, val);
+	return rt_sdca_index_write(map, nid, reg, tmp);
+}
+EXPORT_SYMBOL_GPL(rt_sdca_index_update_bits);
+
+/**
+ * rt_sdca_btn_type - Decision of button type.
+ *
+ * @buffer: UMP message buffer.
+ *
+ * A button type will be returned regarding to buffer,
+ * it returns zero if buffer cannot be recognized.
+ */
+int rt_sdca_btn_type(unsigned char *buffer)
+{
+	u8 btn_type = 0;
+	int ret;
+
+	btn_type |= buffer[0] & 0xf;
+	btn_type |= (buffer[0] >> 4) & 0xf;
+	btn_type |= buffer[1] & 0xf;
+	btn_type |= (buffer[1] >> 4) & 0xf;
+
+	if (btn_type & BIT(0))
+		ret |= SND_JACK_BTN_2;
+	if (btn_type & BIT(1))
+		ret |= SND_JACK_BTN_3;
+	if (btn_type & BIT(2))
+		ret |= SND_JACK_BTN_0;
+	if (btn_type & BIT(3))
+		ret |= SND_JACK_BTN_1;
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(rt_sdca_btn_type);
+
+/**
+ * rt_sdca_headset_detect - Headset jack type detection.
+ *
+ * @map: map for setting.
+ * @entity_id: SDCA entity ID.
+ *
+ * A headset jack type will be returned, a negative errno will
+ * be returned in error cases.
+ */
+int rt_sdca_headset_detect(struct regmap *map, unsigned int entity_id)
+{
+	unsigned int det_mode, jack_type;
+	int ret;
+
+	/* get detected_mode */
+	ret = regmap_read(map, SDW_SDCA_CTL(SDCA_NUM_JACK_CODEC, entity_id,
+			RT_SDCA_CTL_DETECTED_MODE, 0), &det_mode);
+
+	if (ret < 0)
+		goto io_error;
+
+	switch (det_mode) {
+	case 0x00:
+		jack_type = 0;
+		break;
+	case 0x03:
+		jack_type = SND_JACK_HEADPHONE;
+		break;
+	case 0x05:
+		jack_type = SND_JACK_HEADSET;
+		break;
+	}
+
+	/* write selected_mode */
+	if (det_mode) {
+		ret = regmap_write(map, SDW_SDCA_CTL(SDCA_NUM_JACK_CODEC, entity_id,
+				RT_SDCA_CTL_SELECTED_MODE, 0), det_mode);
+		if (ret < 0)
+			goto io_error;
+	}
+
+	return jack_type;
+
+io_error:
+	pr_err_ratelimited("IO error in %s, ret %d\n", __func__, ret);
+	return ret;
+}
+EXPORT_SYMBOL_GPL(rt_sdca_headset_detect);
+
+/**
+ * rt_sdca_button_detect - Read UMP message and decide button type.
+ *
+ * @map: map for setting.
+ * @entity_id: SDCA entity ID.
+ * @hid_buf_addr: HID buffer address.
+ * @hid_id: Report ID for HID.
+ * @mask1: Mask for button message.
+ * @mask2: Mask for button message.
+ *
+ * A button type will be returned regarding to buffer,
+ * it returns zero if buffer cannot be recognized.
+ */
+int rt_sdca_button_detect(struct regmap *map, unsigned int entity_id,
+	unsigned int hid_buf_addr, unsigned int hid_id,
+	unsigned int mask1, unsigned int mask2)
+{
+	unsigned int btn_type = 0, offset, idx, val, owner;
+	unsigned char buf[3];
+	int ret;
+
+	/* get current UMP message owner */
+	ret = regmap_read(map, SDW_SDCA_CTL(SDCA_NUM_HID, entity_id,
+			RT_SDCA_CTL_HIDTX_CURRENT_OWNER, 0), &owner);
+	if (ret < 0)
+		return 0;
+
+	/* if owner is device then there is no button event from device */
+	if (owner == 1)
+		return 0;
+
+	/* read UMP message offset */
+	ret = regmap_read(map, SDW_SDCA_CTL(SDCA_NUM_HID, entity_id,
+			RT_SDCA_CTL_HIDTX_MESSAGE_OFFSET, 0), &offset);
+	if (ret < 0)
+		goto _end_btn_det_;
+
+	for (idx = 0; idx < sizeof(buf); idx++) {
+		ret = regmap_read(map, hid_buf_addr + offset + idx, &val);
+		if (ret < 0)
+			goto _end_btn_det_;
+		buf[idx] = val & 0xff;
+	}
+	/* Report ID for HID */
+	if (buf[0] == hid_id)
+		btn_type = rt_sdca_btn_type(&buf[1]);
+
+_end_btn_det_:
+	/* Host is owner, so set back to device */
+	if (owner == 0)
+		/* set owner to device */
+		regmap_write(map,
+			SDW_SDCA_CTL(SDCA_NUM_HID, entity_id,
+				RT_SDCA_CTL_HIDTX_CURRENT_OWNER, 0), 0x01);
+
+	return btn_type;
+}
+EXPORT_SYMBOL_GPL(rt_sdca_button_detect);
+
+MODULE_DESCRIPTION("Realtek soundwire common functions");
+MODULE_AUTHOR("jack yu <jack.yu@realtek.com>");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/rt-sdw-common.h b/sound/soc/codecs/rt-sdw-common.h
new file mode 100644
index 000000000000..09e5ffd4fb9e
--- /dev/null
+++ b/sound/soc/codecs/rt-sdw-common.h
@@ -0,0 +1,67 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+//
+// rt-sdw-common.h
+//
+// Copyright(c) 2024 Realtek Semiconductor Corp.
+//
+
+/*
+ * This file defines common functions used with Realtek soundwire codecs.
+ */
+
+#ifndef __RT_SDW_COMMON_H__
+#define __RT_SDW_COMMON_H__
+
+#define SDCA_NUM_JACK_CODEC			0x01
+#define SDCA_NUM_MIC_ARRAY			0x02
+#define SDCA_NUM_HID				0x03
+#define SDCA_NUM_AMP				0x04
+#define RT_SDCA_CTL_SELECTED_MODE		0x01
+#define RT_SDCA_CTL_DETECTED_MODE		0x02
+#define RT_SDCA_CTL_HIDTX_CURRENT_OWNER		0x10
+#define RT_SDCA_CTL_HIDTX_MESSAGE_OFFSET	0x12
+
+struct rt_sdca_dmic_kctrl_priv {
+	unsigned int reg_base;
+	unsigned int count;
+	unsigned int max;
+	unsigned int invert;
+};
+
+#define RT_SDCA_PR_VALUE(xreg_base, xcount, xmax, xinvert) \
+	((unsigned long)&(struct rt_sdca_dmic_kctrl_priv) \
+		{.reg_base = xreg_base, .count = xcount, .max = xmax, \
+		.invert = xinvert})
+
+#define RT_SDCA_FU_CTRL(xname, reg_base, xmax, xinvert, xcount, \
+	xinfo, xget, xput) \
+{	.iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \
+	.info = xinfo, \
+	.get = xget, \
+	.put = xput, \
+	.private_value = RT_SDCA_PR_VALUE(reg_base, xcount, xmax, xinvert)}
+
+#define RT_SDCA_EXT_TLV(xname, reg_base, xhandler_get,\
+	 xhandler_put, xcount, xmax, tlv_array, xinfo) \
+{	.iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \
+	.access = SNDRV_CTL_ELEM_ACCESS_TLV_READ | \
+		 SNDRV_CTL_ELEM_ACCESS_READWRITE, \
+	.tlv.p = (tlv_array), \
+	.info = xinfo, \
+	.get = xhandler_get, .put = xhandler_put, \
+	.private_value = RT_SDCA_PR_VALUE(reg_base, xcount, xmax, 0) }
+
+
+int rt_sdca_index_write(struct regmap *map, unsigned int nid,
+	unsigned int reg, unsigned int value);
+int rt_sdca_index_read(struct regmap *map, unsigned int nid,
+	unsigned int reg, unsigned int *value);
+int rt_sdca_index_update_bits(struct regmap *map,
+	unsigned int nid, unsigned int reg, unsigned int mask, unsigned int val);
+int rt_sdca_btn_type(unsigned char *buffer);
+int rt_sdca_headset_detect(struct regmap *map, unsigned int entity_id);
+int rt_sdca_button_detect(struct regmap *map, unsigned int entity_id,
+	unsigned int hid_buf_addr, unsigned int hid_id,
+	unsigned int mask1, unsigned int mask2);
+
+#endif /* __RT_SDW_COMMON_H__ */
-- 
2.34.1


[-- Attachment #2: winmail.dat --]
[-- Type: application/ms-tnef, Size: 8603 bytes --]

^ permalink raw reply related	[flat|nested] only message in thread

only message in thread, other threads:[~2024-10-01  7:01 UTC | newest]

Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-10-01  7:00 [PATCH] ASoC: rt-sdw-common: Common functions for Realtek soundwire driver Jack Yu

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.