Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>
Link: https://patch.msgid.link/959e8dcb075948459be4463f6a4ca6ee@realtek.com
Signed-off-by: Mark Brown <broonie@kernel.org>

authored by

Jack Yu and committed by
Mark Brown
bbca8e70 344190e0

+311
+5
sound/soc/codecs/Kconfig
··· 1545 1545 default m if SND_SOC_RT1305=m 1546 1546 default m if SND_SOC_RT1308=m 1547 1547 1548 + config SND_SOC_RT_SDW_COMMON 1549 + tristate 1550 + default y if SND_SOC_RT721_SDCA_SDW=y 1551 + default m if SND_SOC_RT721_SDCA_SDW=m 1552 + 1548 1553 config SND_SOC_RL6347A 1549 1554 tristate 1550 1555 default y if SND_SOC_RT274=y
+2
sound/soc/codecs/Makefile
··· 219 219 snd-soc-rk3328-y := rk3328_codec.o 220 220 snd-soc-rk817-y := rk817_codec.o 221 221 snd-soc-rl6231-y := rl6231.o 222 + snd-soc-rt-sdw-common-y := rt-sdw-common.o 222 223 snd-soc-rl6347a-y := rl6347a.o 223 224 snd-soc-rt1011-y := rt1011.o 224 225 snd-soc-rt1015-y := rt1015.o ··· 625 624 obj-$(CONFIG_SND_SOC_RK3328) += snd-soc-rk3328.o 626 625 obj-$(CONFIG_SND_SOC_RK817) += snd-soc-rk817.o 627 626 obj-$(CONFIG_SND_SOC_RL6231) += snd-soc-rl6231.o 627 + obj-$(CONFIG_SND_SOC_RT_SDW_COMMON) += snd-soc-rt-sdw-common.o 628 628 obj-$(CONFIG_SND_SOC_RL6347A) += snd-soc-rl6347a.o 629 629 obj-$(CONFIG_SND_SOC_RT1011) += snd-soc-rt1011.o 630 630 obj-$(CONFIG_SND_SOC_RT1015) += snd-soc-rt1015.o
+238
sound/soc/codecs/rt-sdw-common.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + // 3 + // rt-sdw-common.c 4 + // 5 + // Copyright(c) 2024 Realtek Semiconductor Corp. 6 + // 7 + 8 + /* 9 + * This file defines common functions used with Realtek soundwire codecs. 10 + */ 11 + 12 + #include <linux/module.h> 13 + #include <linux/regmap.h> 14 + #include <linux/bitops.h> 15 + #include <linux/soundwire/sdw_registers.h> 16 + #include <sound/jack.h> 17 + 18 + #include "rt-sdw-common.h" 19 + 20 + /** 21 + * rt_sdca_index_write - Write a value to Realtek defined register. 22 + * 23 + * @map: map for setting. 24 + * @nid: Realtek-defined ID. 25 + * @reg: register. 26 + * @value: value. 27 + * 28 + * A value of zero will be returned on success, a negative errno will 29 + * be returned in error cases. 30 + */ 31 + int rt_sdca_index_write(struct regmap *map, unsigned int nid, 32 + unsigned int reg, unsigned int value) 33 + { 34 + unsigned int addr = (nid << 20) | reg; 35 + int ret; 36 + 37 + ret = regmap_write(map, addr, value); 38 + if (ret < 0) 39 + pr_err("Failed to set value: %06x <= %04x ret=%d\n", 40 + addr, value, ret); 41 + 42 + return ret; 43 + } 44 + EXPORT_SYMBOL_GPL(rt_sdca_index_write); 45 + 46 + /** 47 + * rt_sdca_index_read - Read value from Realtek defined register. 48 + * 49 + * @map: map for setting. 50 + * @nid: Realtek-defined ID. 51 + * @reg: register. 52 + * @value: value. 53 + * 54 + * A value of zero will be returned on success, a negative errno will 55 + * be returned in error cases. 56 + */ 57 + int rt_sdca_index_read(struct regmap *map, unsigned int nid, 58 + unsigned int reg, unsigned int *value) 59 + { 60 + unsigned int addr = (nid << 20) | reg; 61 + int ret; 62 + 63 + ret = regmap_read(map, addr, value); 64 + if (ret < 0) 65 + pr_err("Failed to get value: %06x => %04x ret=%d\n", 66 + addr, *value, ret); 67 + 68 + return ret; 69 + } 70 + EXPORT_SYMBOL_GPL(rt_sdca_index_read); 71 + 72 + /** 73 + * rt_sdca_index_update_bits - Update value on Realtek defined register. 74 + * 75 + * @map: map for setting. 76 + * @nid: Realtek-defined ID. 77 + * @reg: register. 78 + * @mask: Bitmask to change 79 + * @value: New value for bitmask 80 + * 81 + * A value of zero will be returned on success, a negative errno will 82 + * be returned in error cases. 83 + */ 84 + 85 + int rt_sdca_index_update_bits(struct regmap *map, 86 + unsigned int nid, unsigned int reg, unsigned int mask, unsigned int val) 87 + { 88 + unsigned int tmp; 89 + int ret; 90 + 91 + ret = rt_sdca_index_read(map, nid, reg, &tmp); 92 + if (ret < 0) 93 + return ret; 94 + 95 + set_mask_bits(&tmp, mask, val); 96 + return rt_sdca_index_write(map, nid, reg, tmp); 97 + } 98 + EXPORT_SYMBOL_GPL(rt_sdca_index_update_bits); 99 + 100 + /** 101 + * rt_sdca_btn_type - Decision of button type. 102 + * 103 + * @buffer: UMP message buffer. 104 + * 105 + * A button type will be returned regarding to buffer, 106 + * it returns zero if buffer cannot be recognized. 107 + */ 108 + int rt_sdca_btn_type(unsigned char *buffer) 109 + { 110 + u8 btn_type = 0; 111 + int ret; 112 + 113 + btn_type |= buffer[0] & 0xf; 114 + btn_type |= (buffer[0] >> 4) & 0xf; 115 + btn_type |= buffer[1] & 0xf; 116 + btn_type |= (buffer[1] >> 4) & 0xf; 117 + 118 + if (btn_type & BIT(0)) 119 + ret |= SND_JACK_BTN_2; 120 + if (btn_type & BIT(1)) 121 + ret |= SND_JACK_BTN_3; 122 + if (btn_type & BIT(2)) 123 + ret |= SND_JACK_BTN_0; 124 + if (btn_type & BIT(3)) 125 + ret |= SND_JACK_BTN_1; 126 + 127 + return ret; 128 + } 129 + EXPORT_SYMBOL_GPL(rt_sdca_btn_type); 130 + 131 + /** 132 + * rt_sdca_headset_detect - Headset jack type detection. 133 + * 134 + * @map: map for setting. 135 + * @entity_id: SDCA entity ID. 136 + * 137 + * A headset jack type will be returned, a negative errno will 138 + * be returned in error cases. 139 + */ 140 + int rt_sdca_headset_detect(struct regmap *map, unsigned int entity_id) 141 + { 142 + unsigned int det_mode, jack_type; 143 + int ret; 144 + 145 + /* get detected_mode */ 146 + ret = regmap_read(map, SDW_SDCA_CTL(SDCA_NUM_JACK_CODEC, entity_id, 147 + RT_SDCA_CTL_DETECTED_MODE, 0), &det_mode); 148 + 149 + if (ret < 0) 150 + goto io_error; 151 + 152 + switch (det_mode) { 153 + case 0x00: 154 + jack_type = 0; 155 + break; 156 + case 0x03: 157 + jack_type = SND_JACK_HEADPHONE; 158 + break; 159 + case 0x05: 160 + jack_type = SND_JACK_HEADSET; 161 + break; 162 + } 163 + 164 + /* write selected_mode */ 165 + if (det_mode) { 166 + ret = regmap_write(map, SDW_SDCA_CTL(SDCA_NUM_JACK_CODEC, entity_id, 167 + RT_SDCA_CTL_SELECTED_MODE, 0), det_mode); 168 + if (ret < 0) 169 + goto io_error; 170 + } 171 + 172 + return jack_type; 173 + 174 + io_error: 175 + pr_err_ratelimited("IO error in %s, ret %d\n", __func__, ret); 176 + return ret; 177 + } 178 + EXPORT_SYMBOL_GPL(rt_sdca_headset_detect); 179 + 180 + /** 181 + * rt_sdca_button_detect - Read UMP message and decide button type. 182 + * 183 + * @map: map for setting. 184 + * @entity_id: SDCA entity ID. 185 + * @hid_buf_addr: HID buffer address. 186 + * @hid_id: Report ID for HID. 187 + * 188 + * A button type will be returned regarding to buffer, 189 + * it returns zero if buffer cannot be recognized. 190 + */ 191 + int rt_sdca_button_detect(struct regmap *map, unsigned int entity_id, 192 + unsigned int hid_buf_addr, unsigned int hid_id) 193 + { 194 + unsigned int btn_type = 0, offset, idx, val, owner; 195 + unsigned char buf[3]; 196 + int ret; 197 + 198 + /* get current UMP message owner */ 199 + ret = regmap_read(map, SDW_SDCA_CTL(SDCA_NUM_HID, entity_id, 200 + RT_SDCA_CTL_HIDTX_CURRENT_OWNER, 0), &owner); 201 + if (ret < 0) 202 + return 0; 203 + 204 + /* if owner is device then there is no button event from device */ 205 + if (owner == 1) 206 + return 0; 207 + 208 + /* read UMP message offset */ 209 + ret = regmap_read(map, SDW_SDCA_CTL(SDCA_NUM_HID, entity_id, 210 + RT_SDCA_CTL_HIDTX_MESSAGE_OFFSET, 0), &offset); 211 + if (ret < 0) 212 + goto _end_btn_det_; 213 + 214 + for (idx = 0; idx < sizeof(buf); idx++) { 215 + ret = regmap_read(map, hid_buf_addr + offset + idx, &val); 216 + if (ret < 0) 217 + goto _end_btn_det_; 218 + buf[idx] = val & 0xff; 219 + } 220 + /* Report ID for HID */ 221 + if (buf[0] == hid_id) 222 + btn_type = rt_sdca_btn_type(&buf[1]); 223 + 224 + _end_btn_det_: 225 + /* Host is owner, so set back to device */ 226 + if (owner == 0) 227 + /* set owner to device */ 228 + regmap_write(map, 229 + SDW_SDCA_CTL(SDCA_NUM_HID, entity_id, 230 + RT_SDCA_CTL_HIDTX_CURRENT_OWNER, 0), 0x01); 231 + 232 + return btn_type; 233 + } 234 + EXPORT_SYMBOL_GPL(rt_sdca_button_detect); 235 + 236 + MODULE_DESCRIPTION("Realtek soundwire common functions"); 237 + MODULE_AUTHOR("jack yu <jack.yu@realtek.com>"); 238 + MODULE_LICENSE("GPL");
+66
sound/soc/codecs/rt-sdw-common.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0-only */ 2 + // 3 + // rt-sdw-common.h 4 + // 5 + // Copyright(c) 2024 Realtek Semiconductor Corp. 6 + // 7 + 8 + /* 9 + * This file defines common functions used with Realtek soundwire codecs. 10 + */ 11 + 12 + #ifndef __RT_SDW_COMMON_H__ 13 + #define __RT_SDW_COMMON_H__ 14 + 15 + #define SDCA_NUM_JACK_CODEC 0x01 16 + #define SDCA_NUM_MIC_ARRAY 0x02 17 + #define SDCA_NUM_HID 0x03 18 + #define SDCA_NUM_AMP 0x04 19 + #define RT_SDCA_CTL_SELECTED_MODE 0x01 20 + #define RT_SDCA_CTL_DETECTED_MODE 0x02 21 + #define RT_SDCA_CTL_HIDTX_CURRENT_OWNER 0x10 22 + #define RT_SDCA_CTL_HIDTX_MESSAGE_OFFSET 0x12 23 + 24 + struct rt_sdca_dmic_kctrl_priv { 25 + unsigned int reg_base; 26 + unsigned int count; 27 + unsigned int max; 28 + unsigned int invert; 29 + }; 30 + 31 + #define RT_SDCA_PR_VALUE(xreg_base, xcount, xmax, xinvert) \ 32 + ((unsigned long)&(struct rt_sdca_dmic_kctrl_priv) \ 33 + {.reg_base = xreg_base, .count = xcount, .max = xmax, \ 34 + .invert = xinvert}) 35 + 36 + #define RT_SDCA_FU_CTRL(xname, reg_base, xmax, xinvert, xcount, \ 37 + xinfo, xget, xput) \ 38 + { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \ 39 + .info = xinfo, \ 40 + .get = xget, \ 41 + .put = xput, \ 42 + .private_value = RT_SDCA_PR_VALUE(reg_base, xcount, xmax, xinvert)} 43 + 44 + #define RT_SDCA_EXT_TLV(xname, reg_base, xhandler_get,\ 45 + xhandler_put, xcount, xmax, tlv_array, xinfo) \ 46 + { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \ 47 + .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ | \ 48 + SNDRV_CTL_ELEM_ACCESS_READWRITE, \ 49 + .tlv.p = (tlv_array), \ 50 + .info = xinfo, \ 51 + .get = xhandler_get, .put = xhandler_put, \ 52 + .private_value = RT_SDCA_PR_VALUE(reg_base, xcount, xmax, 0) } 53 + 54 + 55 + int rt_sdca_index_write(struct regmap *map, unsigned int nid, 56 + unsigned int reg, unsigned int value); 57 + int rt_sdca_index_read(struct regmap *map, unsigned int nid, 58 + unsigned int reg, unsigned int *value); 59 + int rt_sdca_index_update_bits(struct regmap *map, 60 + unsigned int nid, unsigned int reg, unsigned int mask, unsigned int val); 61 + int rt_sdca_btn_type(unsigned char *buffer); 62 + int rt_sdca_headset_detect(struct regmap *map, unsigned int entity_id); 63 + int rt_sdca_button_detect(struct regmap *map, unsigned int entity_id, 64 + unsigned int hid_buf_addr, unsigned int hid_id); 65 + 66 + #endif /* __RT_SDW_COMMON_H__ */