[PATCH v2] ASoC: rt-sdw-common: Common functions for Realtek soundwire driver
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 | 238 +++++++++++++++++++++++++++++++ sound/soc/codecs/rt-sdw-common.h | 66 +++++++++ 4 files changed, 311 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..9ed0e9855699 --- /dev/null +++ b/sound/soc/codecs/rt-sdw-common.c @@ -0,0 +1,238 @@ +// 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. + * + * 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 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..4759516feb38 --- /dev/null +++ b/sound/soc/codecs/rt-sdw-common.h @@ -0,0 +1,66 @@ +/* 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); + +#endif /* __RT_SDW_COMMON_H__ */
On Tue, Oct 01, 2024 at 09:16:27AM +0000, Jack Yu wrote:
+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
This should really be posted in a series with the patch adding the driver, I guess the driver won't build without this.
On Tue, 01 Oct 2024 09:16:27 +0000, Jack Yu wrote:
This is the first version of common functions for Realtek soundwire codec driver.
Applied to
https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git for-next
Thanks!
[1/1] ASoC: rt-sdw-common: Common functions for Realtek soundwire driver commit: bbca8e7050e0769d46eb775082d1926db05e7dac
All being well this means that it will be integrated into the linux-next tree (usually sometime in the next 24 hours) and sent to Linus during the next merge window (or sooner if it is a bug fix), however if problems are discovered then the patch may be dropped or reverted.
You may get further e-mails resulting from automated or manual testing and review of the tree, please engage with people reporting problems and send followup patches addressing any issues that are reported if needed.
If any updates are required or you are submitting further changes they should be sent as incremental updates against current git, existing patches will not be replaced.
Please add any relevant lists and maintainers to the CCs when replying to this mail.
Thanks, Mark
Op 01-10-2024 om 11:16 schreef Jack Yu:
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 | 238 +++++++++++++++++++++++++++++++ sound/soc/codecs/rt-sdw-common.h | 66 +++++++++ 4 files changed, 311 insertions(+) create mode 100644 sound/soc/codecs/rt-sdw-common.c create mode 100644 sound/soc/codecs/rt-sdw-common.h
[...] +/**
- 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;
No initializer ?? You probably want to set it to zero here.
- 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))
Variable "ret" is not initialized yet.
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);
Op 01-10-2024 om 11:16 schreef Jack Yu:
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 | 238 +++++++++++++++++++++++++++++++ sound/soc/codecs/rt-sdw-common.h | 66 +++++++++ 4 files changed, 311 insertions(+) create mode 100644 sound/soc/codecs/rt-sdw-common.c create mode 100644 sound/soc/codecs/rt-sdw-common.h
[...] +/**
- 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;
There is no default case. So, variable jack_type can remain uninitialized and then used for the return value. Perhaps you can combine "case 0x00" with "default".
- }
- /* 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;
Op 08-10-2024 om 22:59 schreef Kees Bakker:
Op 01-10-2024 om 11:16 schreef Jack Yu:
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 | 238 +++++++++++++++++++++++++++++++ sound/soc/codecs/rt-sdw-common.h | 66 +++++++++ 4 files changed, 311 insertions(+) create mode 100644 sound/soc/codecs/rt-sdw-common.c create mode 100644 sound/soc/codecs/rt-sdw-common.h
[...] +/**
- 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;
There is no default case. So, variable jack_type can remain uninitialized and then used for the return value. Perhaps you can combine "case 0x00" with "default".
+ }
+ /* 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;
Please have a look at my comment again. If regmap_read returns a `det_mode` not 0, 3 or 5 then the function will return jack_type with an uninitialzed value.
participants (3)
-
Jack Yu
-
Kees Bakker
-
Mark Brown