From 68a9d45bacb6259cabedb95a8fbcfd20b8e39370 Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Wed, 12 Jun 2024 15:17:19 +0100 Subject: [PATCH 1/6] soundwire: SDCA: Add additional SDCA address macros Compliment the existing macro to construct an SDCA control address with macros to extract the constituent parts, and validation of such an address. Also update the masks for the original macro to use GENMASK to make mental comparisons with the included comment on the address format easier. Acked-by: Vinod Koul Signed-off-by: Charles Keepax --- include/linux/soundwire/sdw_registers.h | 30 ++++++++++++++++++------- 1 file changed, 22 insertions(+), 8 deletions(-) diff --git a/include/linux/soundwire/sdw_registers.h b/include/linux/soundwire/sdw_registers.h index 658b10fa5b20ad..0a5939285583b6 100644 --- a/include/linux/soundwire/sdw_registers.h +++ b/include/linux/soundwire/sdw_registers.h @@ -4,6 +4,9 @@ #ifndef __SDW_REGISTERS_H #define __SDW_REGISTERS_H +#include +#include + /* * SDW registers as defined by MIPI 1.2 Spec */ @@ -329,16 +332,27 @@ * 2:0 Control Number[2:0] */ -#define SDW_SDCA_CTL(fun, ent, ctl, ch) (BIT(30) | \ - (((fun) & 0x7) << 22) | \ - (((ent) & 0x40) << 15) | \ - (((ent) & 0x3f) << 7) | \ - (((ctl) & 0x30) << 15) | \ - (((ctl) & 0x0f) << 3) | \ - (((ch) & 0x38) << 12) | \ - ((ch) & 0x07)) +#define SDW_SDCA_CTL(fun, ent, ctl, ch) (BIT(30) | \ + (((fun) & GENMASK(2, 0)) << 22) | \ + (((ent) & BIT(6)) << 15) | \ + (((ent) & GENMASK(5, 0)) << 7) | \ + (((ctl) & GENMASK(5, 4)) << 15) | \ + (((ctl) & GENMASK(3, 0)) << 3) | \ + (((ch) & GENMASK(5, 3)) << 12) | \ + ((ch) & GENMASK(2, 0))) + +#define SDW_SDCA_CTL_FUNC(reg) FIELD_GET(GENMASK(24, 22), (reg)) +#define SDW_SDCA_CTL_ENT(reg) ((FIELD_GET(BIT(21), (reg)) << 6) | \ + FIELD_GET(GENMASK(12, 7), (reg))) +#define SDW_SDCA_CTL_CSEL(reg) ((FIELD_GET(GENMASK(20, 19), (reg)) << 4) | \ + FIELD_GET(GENMASK(6, 3), (reg))) +#define SDW_SDCA_CTL_CNUM(reg) ((FIELD_GET(GENMASK(17, 15), (reg)) << 3) | \ + FIELD_GET(GENMASK(2, 0), (reg))) #define SDW_SDCA_MBQ_CTL(reg) ((reg) | BIT(13)) #define SDW_SDCA_NEXT_CTL(reg) ((reg) | BIT(14)) +/* Check the reserved and fixed bits in address */ +#define SDW_SDCA_VALID_CTL(reg) (((reg) & (GENMASK(31, 25) | BIT(18) | BIT(13))) == BIT(30)) + #endif /* __SDW_REGISTERS_H */ From 937d8c1c639686e8d110c845d29b8374cfd23590 Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Thu, 21 Nov 2024 15:28:51 +0000 Subject: [PATCH 2/6] ASoC: SDCA: Update list of entity_0 controls Update the list of entity_0 controls to better match version v1.0 of the SDCA specification. Remove both INTSTAT_CLEAR and INT_ENABLE as these are no longer used, and add some missing controls and bits into the enum. Also rename the SDCA_CONTROL prefix to SDCA_CTL because this better matches the macros in the sdw_registers.h header, and the names can get quite long so saving a few characters is definitely a plus. Signed-off-by: Charles Keepax --- include/sound/sdca_function.h | 33 +++++++++++++++++++++++++-------- 1 file changed, 25 insertions(+), 8 deletions(-) diff --git a/include/sound/sdca_function.h b/include/sound/sdca_function.h index 89e42db6d59191..c051c17903e836 100644 --- a/include/sound/sdca_function.h +++ b/include/sound/sdca_function.h @@ -45,14 +45,31 @@ enum sdca_function_type { #define SDCA_FUNCTION_TYPE_IMP_DEF_NAME "ImplementationDefined" enum sdca_entity0_controls { - SDCA_CONTROL_ENTITY_0_COMMIT_GROUP_MASK = 0x01, - SDCA_CONTROL_ENTITY_0_INTSTAT_CLEAR = 0x02, - SDCA_CONTROL_ENTITY_0_INT_ENABLE = 0x03, - SDCA_CONTROL_ENTITY_0_FUNCTION_SDCA_VERSION = 0x04, - SDCA_CONTROL_ENTITY_0_FUNCTION_TOPOLOGY = 0x05, - SDCA_CONTROL_ENTITY_0_FUNCTION_MANUFACTURER_ID = 0x06, - SDCA_CONTROL_ENTITY_0_FUNCTION_ID = 0x07, - SDCA_CONTROL_ENTITY_0_FUNCTION_VERSION = 0x08 + SDCA_CTL_ENTITY_0_COMMIT_GROUP_MASK = 0x01, + SDCA_CTL_ENTITY_0_FUNCTION_SDCA_VERSION = 0x04, + SDCA_CTL_ENTITY_0_FUNCTION_TYPE = 0x05, + SDCA_CTL_ENTITY_0_FUNCTION_MANUFACTURER_ID = 0x06, + SDCA_CTL_ENTITY_0_FUNCTION_ID = 0x07, + SDCA_CTL_ENTITY_0_FUNCTION_VERSION = 0x08, + SDCA_CTL_ENTITY_0_FUNCTION_EXTENSION_ID = 0x09, + SDCA_CTL_ENTITY_0_FUNCTION_EXTENSION_VERSION = 0x0A, + SDCA_CTL_ENTITY_0_FUNCTION_STATUS = 0x10, + SDCA_CTL_ENTITY_0_FUNCTION_ACTION = 0x11, + SDCA_CTL_ENTITY_0_MATCHING_GUID = 0x12, + SDCA_CTL_ENTITY_0_DEVICE_MANUFACTURER_ID = 0x2C, + SDCA_CTL_ENTITY_0_DEVICE_PART_ID = 0x2D, + SDCA_CTL_ENTITY_0_DEVICE_VERSION = 0x2E, + SDCA_CTL_ENTITY_0_DEVICE_SDCA_VERSION = 0x2F, + + /* Function Status Bits */ + SDCA_CTL_ENTITY_0_DEVICE_NEWLY_ATTACHED = BIT(0), + SDCA_CTL_ENTITY_0_INTS_DISABLED_ABNORMALLY = BIT(1), + SDCA_CTL_ENTITY_0_STREAMING_STOPPED_ABNORMALLY = BIT(2), + SDCA_CTL_ENTITY_0_FUNCTION_FAULT = BIT(3), + SDCA_CTL_ENTITY_0_UMP_SEQUENCE_FAULT = BIT(4), + SDCA_CTL_ENTITY_0_FUNCTION_NEEDS_INITIALIZATION = BIT(5), + SDCA_CTL_ENTITY_0_FUNCTION_HAS_BEEN_RESET = BIT(6), + SDCA_CTL_ENTITY_0_FUNCTION_BUSY = BIT(7), }; #endif From f540b3cd839a0a07c66164853738826e893b5c0c Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Fri, 10 May 2024 13:09:55 +0100 Subject: [PATCH 3/6] regmap: sdw-mbq: Add support for further MBQ register sizes SoundWire MBQ register maps typically contain a variety of register sizes, which doesn't map ideally to the regmap abstraction which expects register maps to have a consistent size. Currently the MBQ register map only allows 16-bit registers to be defined, however this leads to complex CODEC driver implementations with an 8-bit register map and a 16-bit MBQ, every control will then have a custom get and put handler that allows them to access different register maps. Further more 32-bit MBQ quantities are not currently supported. Add support for additional MBQ sizes and to avoid the complexity of multiple register maps treat the val_size as a maximum size for the register map. Within the regmap use an ancillary callback to determine how many bytes to actually read/write to the hardware for a specific register. In the case that no callback is defined the behaviour defaults back to the existing behaviour of a fixed size register map. Signed-off-by: Charles Keepax --- drivers/base/regmap/regmap-sdw-mbq.c | 114 ++++++++++++++++++++++----- include/linux/regmap.h | 47 ++++++++++- 2 files changed, 139 insertions(+), 22 deletions(-) diff --git a/drivers/base/regmap/regmap-sdw-mbq.c b/drivers/base/regmap/regmap-sdw-mbq.c index c99eada83780c9..1bd2773b11a457 100644 --- a/drivers/base/regmap/regmap-sdw-mbq.c +++ b/drivers/base/regmap/regmap-sdw-mbq.c @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 // Copyright(c) 2020 Intel Corporation. +#include #include #include #include @@ -9,35 +10,77 @@ #include #include "internal.h" +struct regmap_mbq_context { + struct device *dev; + + struct regmap_sdw_mbq_cfg cfg; + + int val_size; +}; + +static int regmap_sdw_mbq_size(struct regmap_mbq_context *ctx, unsigned int reg) +{ + int size = ctx->val_size; + + if (ctx->cfg.mbq_size) { + size = ctx->cfg.mbq_size(ctx->dev, reg); + if (!size || size > ctx->val_size) + return -EINVAL; + } + + return size; +} + static int regmap_sdw_mbq_write(void *context, unsigned int reg, unsigned int val) { - struct device *dev = context; + struct regmap_mbq_context *ctx = context; + struct device *dev = ctx->dev; struct sdw_slave *slave = dev_to_sdw_dev(dev); + int mbq_size = regmap_sdw_mbq_size(ctx, reg); + int shift = mbq_size * BITS_PER_BYTE; int ret; - ret = sdw_write_no_pm(slave, SDW_SDCA_MBQ_CTL(reg), (val >> 8) & 0xff); - if (ret < 0) - return ret; + if (mbq_size < 0) + return mbq_size; + + while (--mbq_size > 0) { + shift -= BITS_PER_BYTE; + + ret = sdw_write_no_pm(slave, SDW_SDCA_MBQ_CTL(reg), + (val >> shift) & 0xff); + if (ret < 0) + return ret; + } return sdw_write_no_pm(slave, reg, val & 0xff); } static int regmap_sdw_mbq_read(void *context, unsigned int reg, unsigned int *val) { - struct device *dev = context; + struct regmap_mbq_context *ctx = context; + struct device *dev = ctx->dev; struct sdw_slave *slave = dev_to_sdw_dev(dev); - int read0; - int read1; + int mbq_size = regmap_sdw_mbq_size(ctx, reg); + int shift = BITS_PER_BYTE; + int read; - read0 = sdw_read_no_pm(slave, reg); - if (read0 < 0) - return read0; + if (mbq_size < 0) + return mbq_size; - read1 = sdw_read_no_pm(slave, SDW_SDCA_MBQ_CTL(reg)); - if (read1 < 0) - return read1; + read = sdw_read_no_pm(slave, reg); + if (read < 0) + return read; - *val = (read1 << 8) | read0; + *val = read; + + while (--mbq_size > 0) { + read = sdw_read_no_pm(slave, SDW_SDCA_MBQ_CTL(reg)); + if (read < 0) + return read; + + *val |= read << shift; + shift += BITS_PER_BYTE; + } return 0; } @@ -51,8 +94,7 @@ static const struct regmap_bus regmap_sdw_mbq = { static int regmap_sdw_mbq_config_check(const struct regmap_config *config) { - /* MBQ-based controls are only 16-bits for now */ - if (config->val_bits != 16) + if (config->val_bits > (sizeof(unsigned int) * BITS_PER_BYTE)) return -ENOTSUPP; /* Registers are 32 bits wide */ @@ -65,35 +107,67 @@ static int regmap_sdw_mbq_config_check(const struct regmap_config *config) return 0; } +static struct regmap_mbq_context * +regmap_sdw_mbq_gen_context(struct device *dev, + const struct regmap_config *config, + const struct regmap_sdw_mbq_cfg *mbq_config) +{ + struct regmap_mbq_context *ctx; + + ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL); + if (!ctx) + return ERR_PTR(-ENOMEM); + + ctx->dev = dev; + ctx->val_size = config->val_bits / BITS_PER_BYTE; + + if (mbq_config) + ctx->cfg = *mbq_config; + + return ctx; +} + struct regmap *__regmap_init_sdw_mbq(struct sdw_slave *sdw, const struct regmap_config *config, + const struct regmap_sdw_mbq_cfg *mbq_config, struct lock_class_key *lock_key, const char *lock_name) { + struct regmap_mbq_context *ctx; int ret; ret = regmap_sdw_mbq_config_check(config); if (ret) return ERR_PTR(ret); - return __regmap_init(&sdw->dev, ®map_sdw_mbq, - &sdw->dev, config, lock_key, lock_name); + ctx = regmap_sdw_mbq_gen_context(&sdw->dev, config, mbq_config); + if (IS_ERR(ctx)) + return ERR_CAST(ctx); + + return __regmap_init(&sdw->dev, ®map_sdw_mbq, ctx, + config, lock_key, lock_name); } EXPORT_SYMBOL_GPL(__regmap_init_sdw_mbq); struct regmap *__devm_regmap_init_sdw_mbq(struct sdw_slave *sdw, const struct regmap_config *config, + const struct regmap_sdw_mbq_cfg *mbq_config, struct lock_class_key *lock_key, const char *lock_name) { + struct regmap_mbq_context *ctx; int ret; ret = regmap_sdw_mbq_config_check(config); if (ret) return ERR_PTR(ret); - return __devm_regmap_init(&sdw->dev, ®map_sdw_mbq, - &sdw->dev, config, lock_key, lock_name); + ctx = regmap_sdw_mbq_gen_context(&sdw->dev, config, mbq_config); + if (IS_ERR(ctx)) + return ERR_CAST(ctx); + + return __devm_regmap_init(&sdw->dev, ®map_sdw_mbq, ctx, + config, lock_key, lock_name); } EXPORT_SYMBOL_GPL(__devm_regmap_init_sdw_mbq); diff --git a/include/linux/regmap.h b/include/linux/regmap.h index 3871c74f767706..36d2934d8b42ce 100644 --- a/include/linux/regmap.h +++ b/include/linux/regmap.h @@ -506,6 +506,17 @@ struct regmap_range_cfg { unsigned int window_len; }; +/** + * struct regmap_sdw_mbq_cfg - Configuration for Multi-Byte Quantities + * + * @mbq_size: Callback returning the actual size of the given register. + * + * Provides additional configuration required for SoundWire MBQ register maps. + */ +struct regmap_sdw_mbq_cfg { + int (*mbq_size)(struct device *dev, unsigned int reg); +}; + struct regmap_async; typedef int (*regmap_hw_write)(void *context, const void *data, @@ -652,6 +663,7 @@ struct regmap *__regmap_init_sdw(struct sdw_slave *sdw, const char *lock_name); struct regmap *__regmap_init_sdw_mbq(struct sdw_slave *sdw, const struct regmap_config *config, + const struct regmap_sdw_mbq_cfg *mbq_config, struct lock_class_key *lock_key, const char *lock_name); struct regmap *__regmap_init_spi_avmm(struct spi_device *spi, @@ -713,6 +725,7 @@ struct regmap *__devm_regmap_init_sdw(struct sdw_slave *sdw, const char *lock_name); struct regmap *__devm_regmap_init_sdw_mbq(struct sdw_slave *sdw, const struct regmap_config *config, + const struct regmap_sdw_mbq_cfg *mbq_config, struct lock_class_key *lock_key, const char *lock_name); struct regmap *__devm_regmap_init_slimbus(struct slim_device *slimbus, @@ -942,7 +955,22 @@ bool regmap_ac97_default_volatile(struct device *dev, unsigned int reg); */ #define regmap_init_sdw_mbq(sdw, config) \ __regmap_lockdep_wrapper(__regmap_init_sdw_mbq, #config, \ - sdw, config) + sdw, config, NULL) + +/** + * regmap_init_sdw_mbq_cfg() - Initialise MBQ SDW register map with config + * + * @sdw: Device that will be interacted with + * @config: Configuration for register map + * @mbq_config: Properties for the MBQ registers + * + * The return value will be an ERR_PTR() on error or a valid pointer + * to a struct regmap. The regmap will be automatically freed by the + * device management code. + */ +#define regmap_init_sdw_mbq_cfg(sdw, config, mbq_config) \ + __regmap_lockdep_wrapper(__regmap_init_sdw_mbq, #config, \ + sdw, config, mbq_config) /** * regmap_init_spi_avmm() - Initialize register map for Intel SPI Slave @@ -1155,7 +1183,22 @@ bool regmap_ac97_default_volatile(struct device *dev, unsigned int reg); */ #define devm_regmap_init_sdw_mbq(sdw, config) \ __regmap_lockdep_wrapper(__devm_regmap_init_sdw_mbq, #config, \ - sdw, config) + sdw, config, NULL) + +/** + * devm_regmap_init_sdw_mbq_cfg() - Initialise managed MBQ SDW register map with config + * + * @sdw: Device that will be interacted with + * @config: Configuration for register map + * @mbq_config: Properties for the MBQ registers + * + * The return value will be an ERR_PTR() on error or a valid pointer + * to a struct regmap. The regmap will be automatically freed by the + * device management code. + */ +#define devm_regmap_init_sdw_mbq_cfg(sdw, config, mbq_config) \ + __regmap_lockdep_wrapper(__devm_regmap_init_sdw_mbq, \ + #config, sdw, config, mbq_config) /** * devm_regmap_init_slimbus() - Initialise managed register map From 0be106fd3832aa8363d3e0e94d4b7820eda4eeb1 Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Thu, 20 Jun 2024 17:47:24 +0100 Subject: [PATCH 4/6] regmap: sdw-mbq: Add support for SDCA deferred controls The SDCA specification allows for controls to be deferred. In the case of a deferred control the device will return COMMAND_IGNORED to the 8-bit operation that would cause the value to commit. Which is the final 8-bits on a write, or the first 8-bits on a read. In the case of receiving a defer, the regmap will poll the SDCA function busy bit, after which the transaction will be retried, returning an error if the function busy does not clear within a chip specific timeout. Since this is common SDCA functionality which is the 99% use-case for MBQs it makes sense to incorporate this functionality into the register map. If no MBQ configuration is specified, the behaviour will default to the existing behaviour. Signed-off-by: Charles Keepax --- drivers/base/regmap/regmap-sdw-mbq.c | 129 ++++++++++++++++++++++++--- include/linux/regmap.h | 15 ++++ 2 files changed, 130 insertions(+), 14 deletions(-) diff --git a/drivers/base/regmap/regmap-sdw-mbq.c b/drivers/base/regmap/regmap-sdw-mbq.c index 1bd2773b11a457..86644bbd071009 100644 --- a/drivers/base/regmap/regmap-sdw-mbq.c +++ b/drivers/base/regmap/regmap-sdw-mbq.c @@ -2,12 +2,15 @@ // Copyright(c) 2020 Intel Corporation. #include +#include #include #include +#include #include #include #include #include +#include #include "internal.h" struct regmap_mbq_context { @@ -16,6 +19,7 @@ struct regmap_mbq_context { struct regmap_sdw_mbq_cfg cfg; int val_size; + bool (*readable_reg)(struct device *dev, unsigned int reg); }; static int regmap_sdw_mbq_size(struct regmap_mbq_context *ctx, unsigned int reg) @@ -31,18 +35,48 @@ static int regmap_sdw_mbq_size(struct regmap_mbq_context *ctx, unsigned int reg) return size; } -static int regmap_sdw_mbq_write(void *context, unsigned int reg, unsigned int val) +static bool regmap_sdw_mbq_deferrable(struct regmap_mbq_context *ctx, unsigned int reg) +{ + if (ctx->cfg.deferrable) + return ctx->cfg.deferrable(ctx->dev, reg); + + return false; +} + +static int regmap_sdw_mbq_poll_busy(struct sdw_slave *slave, unsigned int reg, + struct regmap_mbq_context *ctx) +{ + struct device *dev = &slave->dev; + int val, ret = 0; + + dev_dbg(dev, "Deferring transaction for 0x%x\n", reg); + + reg = SDW_SDCA_CTL(SDW_SDCA_CTL_FUNC(reg), 0, + SDCA_CTL_ENTITY_0_FUNCTION_STATUS, 0); + + if (ctx->readable_reg(dev, reg)) { + ret = read_poll_timeout(sdw_read_no_pm, val, + val < 0 || !(val & SDCA_CTL_ENTITY_0_FUNCTION_BUSY), + ctx->cfg.timeout_us, ctx->cfg.retry_us, + false, slave, reg); + if (val < 0) + return val; + if (ret) + dev_err(dev, "Function busy timed out 0x%x: %d\n", reg, val); + } else { + fsleep(ctx->cfg.timeout_us); + } + + return ret; +} + +static int regmap_sdw_mbq_write_impl(struct sdw_slave *slave, + unsigned int reg, unsigned int val, + int mbq_size, bool deferrable) { - struct regmap_mbq_context *ctx = context; - struct device *dev = ctx->dev; - struct sdw_slave *slave = dev_to_sdw_dev(dev); - int mbq_size = regmap_sdw_mbq_size(ctx, reg); int shift = mbq_size * BITS_PER_BYTE; int ret; - if (mbq_size < 0) - return mbq_size; - while (--mbq_size > 0) { shift -= BITS_PER_BYTE; @@ -52,24 +86,58 @@ static int regmap_sdw_mbq_write(void *context, unsigned int reg, unsigned int va return ret; } - return sdw_write_no_pm(slave, reg, val & 0xff); + ret = sdw_write_no_pm(slave, reg, val & 0xff); + if (deferrable && ret == -ENODATA) + return -EAGAIN; + + return ret; } -static int regmap_sdw_mbq_read(void *context, unsigned int reg, unsigned int *val) +static int regmap_sdw_mbq_write(void *context, unsigned int reg, unsigned int val) { struct regmap_mbq_context *ctx = context; struct device *dev = ctx->dev; struct sdw_slave *slave = dev_to_sdw_dev(dev); + bool deferrable = regmap_sdw_mbq_deferrable(ctx, reg); int mbq_size = regmap_sdw_mbq_size(ctx, reg); - int shift = BITS_PER_BYTE; - int read; + int ret; if (mbq_size < 0) return mbq_size; + /* + * Technically the spec does allow a device to set itself to busy for + * internal reasons, but since it doesn't provide any information on + * how to handle timeouts in that case, for now the code will only + * process a single wait/timeout on function busy and a single retry + * of the transaction. + */ + ret = regmap_sdw_mbq_write_impl(slave, reg, val, mbq_size, deferrable); + if (ret == -EAGAIN) { + ret = regmap_sdw_mbq_poll_busy(slave, reg, ctx); + if (ret) + return ret; + + ret = regmap_sdw_mbq_write_impl(slave, reg, val, mbq_size, false); + } + + return ret; +} + +static int regmap_sdw_mbq_read_impl(struct sdw_slave *slave, + unsigned int reg, unsigned int *val, + int mbq_size, bool deferrable) +{ + int shift = BITS_PER_BYTE; + int read; + read = sdw_read_no_pm(slave, reg); - if (read < 0) + if (read < 0) { + if (deferrable && read == -ENODATA) + return -EAGAIN; + return read; + } *val = read; @@ -85,6 +153,37 @@ static int regmap_sdw_mbq_read(void *context, unsigned int reg, unsigned int *va return 0; } +static int regmap_sdw_mbq_read(void *context, unsigned int reg, unsigned int *val) +{ + struct regmap_mbq_context *ctx = context; + struct device *dev = ctx->dev; + struct sdw_slave *slave = dev_to_sdw_dev(dev); + bool deferrable = regmap_sdw_mbq_deferrable(ctx, reg); + int mbq_size = regmap_sdw_mbq_size(ctx, reg); + int ret; + + if (mbq_size < 0) + return mbq_size; + + /* + * Technically the spec does allow a device to set itself to busy for + * internal reasons, but since it doesn't provide any information on + * how to handle timeouts in that case, for now the code will only + * process a single wait/timeout on function busy and a single retry + * of the transaction. + */ + ret = regmap_sdw_mbq_read_impl(slave, reg, val, mbq_size, deferrable); + if (ret == -EAGAIN) { + ret = regmap_sdw_mbq_poll_busy(slave, reg, ctx); + if (ret) + return ret; + + ret = regmap_sdw_mbq_read_impl(slave, reg, val, mbq_size, false); + } + + return ret; +} + static const struct regmap_bus regmap_sdw_mbq = { .reg_read = regmap_sdw_mbq_read, .reg_write = regmap_sdw_mbq_write, @@ -119,11 +218,13 @@ regmap_sdw_mbq_gen_context(struct device *dev, return ERR_PTR(-ENOMEM); ctx->dev = dev; - ctx->val_size = config->val_bits / BITS_PER_BYTE; if (mbq_config) ctx->cfg = *mbq_config; + ctx->val_size = config->val_bits / BITS_PER_BYTE; + ctx->readable_reg = config->readable_reg; + return ctx; } diff --git a/include/linux/regmap.h b/include/linux/regmap.h index 36d2934d8b42ce..3a96d068915f3f 100644 --- a/include/linux/regmap.h +++ b/include/linux/regmap.h @@ -510,11 +510,26 @@ struct regmap_range_cfg { * struct regmap_sdw_mbq_cfg - Configuration for Multi-Byte Quantities * * @mbq_size: Callback returning the actual size of the given register. + * @deferrable: Callback returning true if the hardware can defer + * transactions to the given register. Deferral should + * only be used by SDCA parts and typically which controls + * are deferrable will be specified in either as a hard + * coded list or from the DisCo tables in the platform + * firmware. + * + * @timeout_us: The time in microseconds after which waiting for a deferred + * transaction should time out. + * @retry_us: The time in microseconds between polls of the function busy + * status whilst waiting for an opportunity to retry a deferred + * transaction. * * Provides additional configuration required for SoundWire MBQ register maps. */ struct regmap_sdw_mbq_cfg { int (*mbq_size)(struct device *dev, unsigned int reg); + bool (*deferrable)(struct device *dev, unsigned int reg); + unsigned long timeout_us; + unsigned long retry_us; }; struct regmap_async; From 2a9c06e27304e791f04f3230b03d905089bb517f Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Tue, 7 Jan 2025 14:45:45 +0000 Subject: [PATCH 5/6] ASoC: rt722-sdca: Add some missing readable registers Add a few missing registers from the readable register callback. Suggested-by: Shuming Fan Signed-off-by: Charles Keepax --- sound/soc/codecs/rt722-sdca-sdw.c | 49 +++++++++++++++++++++++++++++-- 1 file changed, 46 insertions(+), 3 deletions(-) diff --git a/sound/soc/codecs/rt722-sdca-sdw.c b/sound/soc/codecs/rt722-sdca-sdw.c index e512217b64a2af..0b38474d5d3fbd 100644 --- a/sound/soc/codecs/rt722-sdca-sdw.c +++ b/sound/soc/codecs/rt722-sdca-sdw.c @@ -28,9 +28,50 @@ static bool rt722_sdca_readable_register(struct device *dev, unsigned int reg) 0): case SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT722_SDCA_ENT_GE49, RT722_SDCA_CTL_DETECTED_MODE, 0): - case SDW_SDCA_CTL(FUNC_NUM_HID, RT722_SDCA_ENT_HID01, RT722_SDCA_CTL_HIDTX_CURRENT_OWNER, - 0) ... SDW_SDCA_CTL(FUNC_NUM_HID, RT722_SDCA_ENT_HID01, - RT722_SDCA_CTL_HIDTX_MESSAGE_LENGTH, 0): + case SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT722_SDCA_ENT_XU03, RT722_SDCA_CTL_SELECTED_MODE, + 0): + case SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT722_SDCA_ENT_USER_FU05, + RT722_SDCA_CTL_FU_MUTE, CH_L) ... + SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT722_SDCA_ENT_USER_FU05, + RT722_SDCA_CTL_FU_MUTE, CH_R): + case SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT722_SDCA_ENT_XU0D, + RT722_SDCA_CTL_SELECTED_MODE, 0): + case SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT722_SDCA_ENT_USER_FU0F, + RT722_SDCA_CTL_FU_MUTE, CH_L) ... + SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT722_SDCA_ENT_USER_FU0F, + RT722_SDCA_CTL_FU_MUTE, CH_R): + case SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT722_SDCA_ENT_PDE40, + RT722_SDCA_CTL_REQ_POWER_STATE, 0): + case SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT722_SDCA_ENT_PDE12, + RT722_SDCA_CTL_REQ_POWER_STATE, 0): + case SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT722_SDCA_ENT_CS01, + RT722_SDCA_CTL_SAMPLE_FREQ_INDEX, 0): + case SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT722_SDCA_ENT_CS11, + RT722_SDCA_CTL_SAMPLE_FREQ_INDEX, 0): + case SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT722_SDCA_ENT_USER_FU1E, + RT722_SDCA_CTL_FU_MUTE, CH_01) ... + SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT722_SDCA_ENT_USER_FU1E, + RT722_SDCA_CTL_FU_MUTE, CH_04): + case SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT722_SDCA_ENT_IT26, + RT722_SDCA_CTL_VENDOR_DEF, 0): + case SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT722_SDCA_ENT_PDE2A, + RT722_SDCA_CTL_REQ_POWER_STATE, 0): + case SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT722_SDCA_ENT_CS1F, + RT722_SDCA_CTL_SAMPLE_FREQ_INDEX, 0): + case SDW_SDCA_CTL(FUNC_NUM_HID, RT722_SDCA_ENT_HID01, + RT722_SDCA_CTL_HIDTX_CURRENT_OWNER, 0) ... + SDW_SDCA_CTL(FUNC_NUM_HID, RT722_SDCA_ENT_HID01, + RT722_SDCA_CTL_HIDTX_MESSAGE_LENGTH, 0): + case SDW_SDCA_CTL(FUNC_NUM_AMP, RT722_SDCA_ENT_USER_FU06, + RT722_SDCA_CTL_FU_MUTE, CH_L) ... + SDW_SDCA_CTL(FUNC_NUM_AMP, RT722_SDCA_ENT_USER_FU06, + RT722_SDCA_CTL_FU_MUTE, CH_R): + case SDW_SDCA_CTL(FUNC_NUM_AMP, RT722_SDCA_ENT_OT23, + RT722_SDCA_CTL_VENDOR_DEF, CH_08): + case SDW_SDCA_CTL(FUNC_NUM_AMP, RT722_SDCA_ENT_PDE23, + RT722_SDCA_CTL_REQ_POWER_STATE, 0): + case SDW_SDCA_CTL(FUNC_NUM_AMP, RT722_SDCA_ENT_CS31, + RT722_SDCA_CTL_SAMPLE_FREQ_INDEX, 0): case RT722_BUF_ADDR_HID1 ... RT722_BUF_ADDR_HID2: return true; default: @@ -74,6 +115,7 @@ static bool rt722_sdca_mbq_readable_register(struct device *dev, unsigned int re case 0x5600000 ... 0x5600007: case 0x5700000 ... 0x5700004: case 0x5800000 ... 0x5800004: + case 0x5810000: case 0x5b00003: case 0x5c00011: case 0x5d00006: @@ -81,6 +123,7 @@ static bool rt722_sdca_mbq_readable_register(struct device *dev, unsigned int re case 0x5f00030: case 0x6100000 ... 0x6100051: case 0x6100055 ... 0x6100057: + case 0x6100060: case 0x6100062: case 0x6100064 ... 0x6100065: case 0x6100067: From e4d66743666185b9becd21cd7b01e6da3b26eddd Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Fri, 6 Dec 2024 17:43:33 +0000 Subject: [PATCH 6/6] ASoC: rt722-sdca: Make use of new expanded MBQ regmap Now the MBQ regmap implementation handles multiple sizes, this driver can combine its two register maps into one. So remove mbq_regmap and combine all the registers into regmap. Also as rt722_sdca_adc_mux_get/put() only exist to access mbq_regmap, rather than doing any processing, these can now be dropped and the normal DAPM helpers used. Signed-off-by: Charles Keepax --- sound/soc/codecs/rt722-sdca-sdw.c | 81 ++++++------------ sound/soc/codecs/rt722-sdca-sdw.h | 99 +++++++++++----------- sound/soc/codecs/rt722-sdca.c | 135 +++++++----------------------- sound/soc/codecs/rt722-sdca.h | 4 +- 4 files changed, 105 insertions(+), 214 deletions(-) diff --git a/sound/soc/codecs/rt722-sdca-sdw.c b/sound/soc/codecs/rt722-sdca-sdw.c index 0b38474d5d3fbd..7a38fcf6314310 100644 --- a/sound/soc/codecs/rt722-sdca-sdw.c +++ b/sound/soc/codecs/rt722-sdca-sdw.c @@ -16,7 +16,7 @@ #include "rt722-sdca.h" #include "rt722-sdca-sdw.h" -static bool rt722_sdca_readable_register(struct device *dev, unsigned int reg) +static int rt722_sdca_mbq_size(struct device *dev, unsigned int reg) { switch (reg) { case 0x2f01 ... 0x2f0a: @@ -73,32 +73,7 @@ static bool rt722_sdca_readable_register(struct device *dev, unsigned int reg) case SDW_SDCA_CTL(FUNC_NUM_AMP, RT722_SDCA_ENT_CS31, RT722_SDCA_CTL_SAMPLE_FREQ_INDEX, 0): case RT722_BUF_ADDR_HID1 ... RT722_BUF_ADDR_HID2: - return true; - default: - return false; - } -} - -static bool rt722_sdca_volatile_register(struct device *dev, unsigned int reg) -{ - switch (reg) { - case 0x2f01: - case 0x2f54: - case SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT722_SDCA_ENT_GE49, RT722_SDCA_CTL_DETECTED_MODE, - 0): - case SDW_SDCA_CTL(FUNC_NUM_HID, RT722_SDCA_ENT_HID01, RT722_SDCA_CTL_HIDTX_CURRENT_OWNER, - 0) ... SDW_SDCA_CTL(FUNC_NUM_HID, RT722_SDCA_ENT_HID01, - RT722_SDCA_CTL_HIDTX_MESSAGE_LENGTH, 0): - case RT722_BUF_ADDR_HID1 ... RT722_BUF_ADDR_HID2: - return true; - default: - return false; - } -} - -static bool rt722_sdca_mbq_readable_register(struct device *dev, unsigned int reg) -{ - switch (reg) { + return 1; case 0x2000000 ... 0x2000024: case 0x2000029 ... 0x200004a: case 0x2000051 ... 0x2000052: @@ -151,15 +126,32 @@ static bool rt722_sdca_mbq_readable_register(struct device *dev, unsigned int re RT722_SDCA_CTL_FU_CH_GAIN, CH_L): case SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT722_SDCA_ENT_PLATFORM_FU44, RT722_SDCA_CTL_FU_CH_GAIN, CH_R): - return true; + return 2; default: - return false; + return 0; } } -static bool rt722_sdca_mbq_volatile_register(struct device *dev, unsigned int reg) +static struct regmap_sdw_mbq_cfg rt722_mbq_config = { + .mbq_size = rt722_sdca_mbq_size, +}; + +static bool rt722_sdca_readable_register(struct device *dev, unsigned int reg) +{ + return rt722_sdca_mbq_size(dev, reg) > 0; +} + +static bool rt722_sdca_volatile_register(struct device *dev, unsigned int reg) { switch (reg) { + case 0x2f01: + case 0x2f54: + case SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT722_SDCA_ENT_GE49, RT722_SDCA_CTL_DETECTED_MODE, + 0): + case SDW_SDCA_CTL(FUNC_NUM_HID, RT722_SDCA_ENT_HID01, RT722_SDCA_CTL_HIDTX_CURRENT_OWNER, + 0) ... SDW_SDCA_CTL(FUNC_NUM_HID, RT722_SDCA_ENT_HID01, + RT722_SDCA_CTL_HIDTX_MESSAGE_LENGTH, 0): + case RT722_BUF_ADDR_HID1 ... RT722_BUF_ADDR_HID2: case 0x2000000: case 0x200000d: case 0x2000019: @@ -178,7 +170,7 @@ static bool rt722_sdca_mbq_volatile_register(struct device *dev, unsigned int re static const struct regmap_config rt722_sdca_regmap = { .reg_bits = 32, - .val_bits = 8, + .val_bits = 16, .readable_reg = rt722_sdca_readable_register, .volatile_reg = rt722_sdca_volatile_register, .max_register = 0x44ffffff, @@ -189,20 +181,6 @@ static const struct regmap_config rt722_sdca_regmap = { .use_single_write = true, }; -static const struct regmap_config rt722_sdca_mbq_regmap = { - .name = "sdw-mbq", - .reg_bits = 32, - .val_bits = 16, - .readable_reg = rt722_sdca_mbq_readable_register, - .volatile_reg = rt722_sdca_mbq_volatile_register, - .max_register = 0x41000312, - .reg_defaults = rt722_sdca_mbq_defaults, - .num_reg_defaults = ARRAY_SIZE(rt722_sdca_mbq_defaults), - .cache_type = REGCACHE_MAPLE, - .use_single_read = true, - .use_single_write = true, -}; - static int rt722_sdca_update_status(struct sdw_slave *slave, enum sdw_slave_status status) { @@ -414,18 +392,14 @@ static const struct sdw_slave_ops rt722_sdca_slave_ops = { static int rt722_sdca_sdw_probe(struct sdw_slave *slave, const struct sdw_device_id *id) { - struct regmap *regmap, *mbq_regmap; + struct regmap *regmap; /* Regmap Initialization */ - mbq_regmap = devm_regmap_init_sdw_mbq(slave, &rt722_sdca_mbq_regmap); - if (IS_ERR(mbq_regmap)) - return PTR_ERR(mbq_regmap); - - regmap = devm_regmap_init_sdw(slave, &rt722_sdca_regmap); + regmap = devm_regmap_init_sdw_mbq_cfg(slave, &rt722_sdca_regmap, &rt722_mbq_config); if (IS_ERR(regmap)) return PTR_ERR(regmap); - return rt722_sdca_init(&slave->dev, regmap, mbq_regmap, slave); + return rt722_sdca_init(&slave->dev, regmap, slave); } static int rt722_sdca_sdw_remove(struct sdw_slave *slave) @@ -463,7 +437,6 @@ static int __maybe_unused rt722_sdca_dev_suspend(struct device *dev) cancel_delayed_work_sync(&rt722->jack_btn_check_work); regcache_cache_only(rt722->regmap, true); - regcache_cache_only(rt722->mbq_regmap, true); return 0; } @@ -533,8 +506,6 @@ static int __maybe_unused rt722_sdca_dev_resume(struct device *dev) slave->unattach_request = 0; regcache_cache_only(rt722->regmap, false); regcache_sync(rt722->regmap); - regcache_cache_only(rt722->mbq_regmap, false); - regcache_sync(rt722->mbq_regmap); return 0; } diff --git a/sound/soc/codecs/rt722-sdca-sdw.h b/sound/soc/codecs/rt722-sdca-sdw.h index 5b43e86f75d193..80b01445694069 100644 --- a/sound/soc/codecs/rt722-sdca-sdw.h +++ b/sound/soc/codecs/rt722-sdca-sdw.h @@ -31,50 +31,9 @@ static const struct reg_default rt722_sdca_reg_defaults[] = { { 0x2f5b, 0x07 }, { 0x2f5c, 0x27 }, { 0x2f5d, 0x07 }, - { SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT722_SDCA_ENT_CS01, RT722_SDCA_CTL_SAMPLE_FREQ_INDEX, - 0), 0x09 }, - { SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT722_SDCA_ENT_CS11, RT722_SDCA_CTL_SAMPLE_FREQ_INDEX, - 0), 0x09 }, - { SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT722_SDCA_ENT_PDE12, RT722_SDCA_CTL_REQ_POWER_STATE, - 0), 0x03 }, - { SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT722_SDCA_ENT_PDE40, RT722_SDCA_CTL_REQ_POWER_STATE, - 0), 0x03 }, - { SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT722_SDCA_ENT_USER_FU05, RT722_SDCA_CTL_FU_MUTE, CH_L), - 0x01 }, - { SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT722_SDCA_ENT_USER_FU05, RT722_SDCA_CTL_FU_MUTE, CH_R), - 0x01 }, - { SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT722_SDCA_ENT_USER_FU0F, RT722_SDCA_CTL_FU_MUTE, CH_L), - 0x01 }, - { SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT722_SDCA_ENT_USER_FU0F, RT722_SDCA_CTL_FU_MUTE, CH_R), - 0x01 }, - { SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT722_SDCA_ENT_CS1F, RT722_SDCA_CTL_SAMPLE_FREQ_INDEX, - 0), 0x09 }, - { SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT722_SDCA_ENT_USER_FU1E, RT722_SDCA_CTL_FU_MUTE, CH_01), - 0x01 }, - { SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT722_SDCA_ENT_USER_FU1E, RT722_SDCA_CTL_FU_MUTE, CH_02), - 0x01 }, - { SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT722_SDCA_ENT_USER_FU1E, RT722_SDCA_CTL_FU_MUTE, CH_03), - 0x01 }, - { SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT722_SDCA_ENT_USER_FU1E, RT722_SDCA_CTL_FU_MUTE, CH_04), - 0x01 }, - { SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT722_SDCA_ENT_PDE2A, RT722_SDCA_CTL_REQ_POWER_STATE, 0), - 0x03 }, - { SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT722_SDCA_ENT_IT26, RT722_SDCA_CTL_VENDOR_DEF, 0), - 0x00 }, - { SDW_SDCA_CTL(FUNC_NUM_AMP, RT722_SDCA_ENT_CS31, RT722_SDCA_CTL_SAMPLE_FREQ_INDEX, 0), - 0x09 }, - { SDW_SDCA_CTL(FUNC_NUM_AMP, RT722_SDCA_ENT_USER_FU06, RT722_SDCA_CTL_FU_MUTE, CH_L), - 0x01 }, - { SDW_SDCA_CTL(FUNC_NUM_AMP, RT722_SDCA_ENT_USER_FU06, RT722_SDCA_CTL_FU_MUTE, CH_R), - 0x01 }, - { SDW_SDCA_CTL(FUNC_NUM_AMP, RT722_SDCA_ENT_PDE23, RT722_SDCA_CTL_REQ_POWER_STATE, 0), - 0x03 }, - { SDW_SDCA_CTL(FUNC_NUM_AMP, RT722_SDCA_ENT_OT23, RT722_SDCA_CTL_VENDOR_DEF, 0), 0x00 }, -}; - -static const struct reg_default rt722_sdca_mbq_defaults[] = { { 0x200003c, 0xc214 }, { 0x2000046, 0x8004 }, + { 0x5810000, 0x702d }, { 0x6100006, 0x0005 }, { 0x6100010, 0x2630 }, { 0x6100011, 0x152f }, @@ -86,27 +45,34 @@ static const struct reg_default rt722_sdca_mbq_defaults[] = { { 0x6100028, 0x2a2a }, { 0x6100029, 0x4141 }, { 0x6100055, 0x0000 }, - { 0x5810000, 0x702d }, + { SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT722_SDCA_ENT_USER_FU05, RT722_SDCA_CTL_FU_MUTE, CH_L), + 0x01 }, + { SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT722_SDCA_ENT_USER_FU05, RT722_SDCA_CTL_FU_MUTE, CH_R), + 0x01 }, { SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT722_SDCA_ENT_USER_FU05, RT722_SDCA_CTL_FU_VOLUME, CH_L), 0x0000 }, { SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT722_SDCA_ENT_USER_FU05, RT722_SDCA_CTL_FU_VOLUME, CH_R), 0x0000 }, + { SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT722_SDCA_ENT_USER_FU0F, RT722_SDCA_CTL_FU_MUTE, CH_L), + 0x01 }, + { SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT722_SDCA_ENT_USER_FU0F, RT722_SDCA_CTL_FU_MUTE, CH_R), + 0x01 }, { SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT722_SDCA_ENT_USER_FU0F, RT722_SDCA_CTL_FU_VOLUME, CH_L), 0x0000 }, { SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT722_SDCA_ENT_USER_FU0F, RT722_SDCA_CTL_FU_VOLUME, CH_R), 0x0000 }, + { SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT722_SDCA_ENT_PDE12, RT722_SDCA_CTL_REQ_POWER_STATE, + 0), 0x03 }, + { SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT722_SDCA_ENT_CS01, RT722_SDCA_CTL_SAMPLE_FREQ_INDEX, + 0), 0x09 }, + { SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT722_SDCA_ENT_CS11, RT722_SDCA_CTL_SAMPLE_FREQ_INDEX, + 0), 0x09 }, + { SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT722_SDCA_ENT_PDE40, RT722_SDCA_CTL_REQ_POWER_STATE, + 0), 0x03 }, { SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT722_SDCA_ENT_PLATFORM_FU44, RT722_SDCA_CTL_FU_CH_GAIN, CH_L), 0x0000 }, { SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT722_SDCA_ENT_PLATFORM_FU44, RT722_SDCA_CTL_FU_CH_GAIN, CH_R), 0x0000 }, - { SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT722_SDCA_ENT_USER_FU1E, RT722_SDCA_CTL_FU_VOLUME, - CH_01), 0x0000 }, - { SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT722_SDCA_ENT_USER_FU1E, RT722_SDCA_CTL_FU_VOLUME, - CH_02), 0x0000 }, - { SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT722_SDCA_ENT_USER_FU1E, RT722_SDCA_CTL_FU_VOLUME, - CH_03), 0x0000 }, - { SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT722_SDCA_ENT_USER_FU1E, RT722_SDCA_CTL_FU_VOLUME, - CH_04), 0x0000 }, { SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT722_SDCA_ENT_FU15, RT722_SDCA_CTL_FU_CH_GAIN, CH_01), 0x0000 }, { SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT722_SDCA_ENT_FU15, RT722_SDCA_CTL_FU_CH_GAIN, CH_02), @@ -115,10 +81,41 @@ static const struct reg_default rt722_sdca_mbq_defaults[] = { 0x0000 }, { SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT722_SDCA_ENT_FU15, RT722_SDCA_CTL_FU_CH_GAIN, CH_04), 0x0000 }, + { SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT722_SDCA_ENT_USER_FU1E, RT722_SDCA_CTL_FU_MUTE, CH_01), + 0x01 }, + { SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT722_SDCA_ENT_USER_FU1E, RT722_SDCA_CTL_FU_MUTE, CH_02), + 0x01 }, + { SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT722_SDCA_ENT_USER_FU1E, RT722_SDCA_CTL_FU_MUTE, CH_03), + 0x01 }, + { SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT722_SDCA_ENT_USER_FU1E, RT722_SDCA_CTL_FU_MUTE, CH_04), + 0x01 }, + { SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT722_SDCA_ENT_USER_FU1E, RT722_SDCA_CTL_FU_VOLUME, + CH_01), 0x0000 }, + { SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT722_SDCA_ENT_USER_FU1E, RT722_SDCA_CTL_FU_VOLUME, + CH_02), 0x0000 }, + { SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT722_SDCA_ENT_USER_FU1E, RT722_SDCA_CTL_FU_VOLUME, + CH_03), 0x0000 }, + { SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT722_SDCA_ENT_USER_FU1E, RT722_SDCA_CTL_FU_VOLUME, + CH_04), 0x0000 }, + { SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT722_SDCA_ENT_PDE2A, RT722_SDCA_CTL_REQ_POWER_STATE, 0), + 0x03 }, + { SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT722_SDCA_ENT_CS1F, RT722_SDCA_CTL_SAMPLE_FREQ_INDEX, + 0), 0x09 }, + { SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT722_SDCA_ENT_IT26, RT722_SDCA_CTL_VENDOR_DEF, 0), + 0x00 }, + { SDW_SDCA_CTL(FUNC_NUM_AMP, RT722_SDCA_ENT_USER_FU06, RT722_SDCA_CTL_FU_MUTE, CH_L), + 0x01 }, + { SDW_SDCA_CTL(FUNC_NUM_AMP, RT722_SDCA_ENT_USER_FU06, RT722_SDCA_CTL_FU_MUTE, CH_R), + 0x01 }, { SDW_SDCA_CTL(FUNC_NUM_AMP, RT722_SDCA_ENT_USER_FU06, RT722_SDCA_CTL_FU_VOLUME, CH_L), 0x0000 }, { SDW_SDCA_CTL(FUNC_NUM_AMP, RT722_SDCA_ENT_USER_FU06, RT722_SDCA_CTL_FU_VOLUME, CH_R), 0x0000 }, + { SDW_SDCA_CTL(FUNC_NUM_AMP, RT722_SDCA_ENT_PDE23, RT722_SDCA_CTL_REQ_POWER_STATE, 0), + 0x03 }, + { SDW_SDCA_CTL(FUNC_NUM_AMP, RT722_SDCA_ENT_CS31, RT722_SDCA_CTL_SAMPLE_FREQ_INDEX, 0), + 0x09 }, + { SDW_SDCA_CTL(FUNC_NUM_AMP, RT722_SDCA_ENT_OT23, RT722_SDCA_CTL_VENDOR_DEF, 0), 0x00 }, }; #endif /* __RT722_SDW_H__ */ diff --git a/sound/soc/codecs/rt722-sdca.c b/sound/soc/codecs/rt722-sdca.c index e17a142d03b999..f093ce841b3fb0 100644 --- a/sound/soc/codecs/rt722-sdca.c +++ b/sound/soc/codecs/rt722-sdca.c @@ -25,11 +25,13 @@ #include "rt722-sdca.h" +#define RT722_NID_ADDR(nid, reg) ((nid) << 20 | (reg)) + int rt722_sdca_index_write(struct rt722_sdca_priv *rt722, unsigned int nid, unsigned int reg, unsigned int value) { - struct regmap *regmap = rt722->mbq_regmap; - unsigned int addr = (nid << 20) | reg; + struct regmap *regmap = rt722->regmap; + unsigned int addr = RT722_NID_ADDR(nid, reg); int ret; ret = regmap_write(regmap, addr, value); @@ -45,8 +47,8 @@ int rt722_sdca_index_read(struct rt722_sdca_priv *rt722, unsigned int nid, unsigned int reg, unsigned int *value) { int ret; - struct regmap *regmap = rt722->mbq_regmap; - unsigned int addr = (nid << 20) | reg; + struct regmap *regmap = rt722->regmap; + unsigned int addr = RT722_NID_ADDR(nid, reg); ret = regmap_read(regmap, addr, value); if (ret < 0) @@ -361,8 +363,8 @@ static int rt722_sdca_set_gain_put(struct snd_kcontrol *kcontrol, strstr(ucontrol->id.name, "FU0F Capture Volume")) adc_vol_flag = 1; - regmap_read(rt722->mbq_regmap, mc->reg, &lvalue); - regmap_read(rt722->mbq_regmap, mc->rreg, &rvalue); + regmap_read(rt722->regmap, mc->reg, &lvalue); + regmap_read(rt722->regmap, mc->rreg, &rvalue); /* L Channel */ gain_l_val = ucontrol->value.integer.value[0]; @@ -402,13 +404,13 @@ static int rt722_sdca_set_gain_put(struct snd_kcontrol *kcontrol, return 0; /* Lch*/ - regmap_write(rt722->mbq_regmap, mc->reg, gain_l_val); + regmap_write(rt722->regmap, mc->reg, gain_l_val); /* Rch */ - regmap_write(rt722->mbq_regmap, mc->rreg, gain_r_val); + regmap_write(rt722->regmap, mc->rreg, gain_r_val); - regmap_read(rt722->mbq_regmap, mc->reg, &read_l); - regmap_read(rt722->mbq_regmap, mc->rreg, &read_r); + regmap_read(rt722->regmap, mc->reg, &read_l); + regmap_read(rt722->regmap, mc->rreg, &read_r); if (read_r == gain_r_val && read_l == gain_l_val) return changed; @@ -431,8 +433,8 @@ static int rt722_sdca_set_gain_get(struct snd_kcontrol *kcontrol, strstr(ucontrol->id.name, "FU0F Capture Volume")) adc_vol_flag = 1; - regmap_read(rt722->mbq_regmap, mc->reg, &read_l); - regmap_read(rt722->mbq_regmap, mc->rreg, &read_r); + regmap_read(rt722->regmap, mc->reg, &read_l); + regmap_read(rt722->regmap, mc->rreg, &read_r); if (mc->shift == 8) /* boost gain */ ctl_l = read_l / tendB; @@ -604,7 +606,7 @@ static int rt722_sdca_dmic_set_gain_get(struct snd_kcontrol *kcontrol, /* check all channels */ for (i = 0; i < p->count; i++) { - regmap_read(rt722->mbq_regmap, p->reg_base + i, ®value); + regmap_read(rt722->regmap, p->reg_base + i, ®value); if (!adc_vol_flag) /* boost gain */ ctl = regvalue / boost_step; @@ -637,7 +639,7 @@ static int rt722_sdca_dmic_set_gain_put(struct snd_kcontrol *kcontrol, /* check all channels */ for (i = 0; i < p->count; i++) { - regmap_read(rt722->mbq_regmap, p->reg_base + i, ®value[i]); + regmap_read(rt722->regmap, p->reg_base + i, ®value[i]); gain_val[i] = ucontrol->value.integer.value[i]; if (gain_val[i] > p->max) @@ -658,7 +660,7 @@ static int rt722_sdca_dmic_set_gain_put(struct snd_kcontrol *kcontrol, return 0; for (i = 0; i < p->count; i++) { - err = regmap_write(rt722->mbq_regmap, p->reg_base + i, gain_val[i]); + err = regmap_write(rt722->regmap, p->reg_base + i, gain_val[i]); if (err < 0) dev_err(&rt722->slave->dev, "%s: %#08x can't be set\n", __func__, p->reg_base + i); @@ -739,77 +741,6 @@ static const struct snd_kcontrol_new rt722_sdca_controls[] = { 4, 3, boost_vol_tlv), }; -static int rt722_sdca_adc_mux_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_soc_component *component = - snd_soc_dapm_kcontrol_component(kcontrol); - struct rt722_sdca_priv *rt722 = snd_soc_component_get_drvdata(component); - unsigned int val = 0, mask_sft; - - if (strstr(ucontrol->id.name, "ADC 22 Mux")) - mask_sft = 12; - else if (strstr(ucontrol->id.name, "ADC 24 Mux")) - mask_sft = 4; - else if (strstr(ucontrol->id.name, "ADC 25 Mux")) - mask_sft = 0; - else - return -EINVAL; - - rt722_sdca_index_read(rt722, RT722_VENDOR_HDA_CTL, - RT722_HDA_LEGACY_MUX_CTL0, &val); - - ucontrol->value.enumerated.item[0] = (val >> mask_sft) & 0x7; - - return 0; -} - -static int rt722_sdca_adc_mux_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_soc_component *component = - snd_soc_dapm_kcontrol_component(kcontrol); - struct snd_soc_dapm_context *dapm = - snd_soc_dapm_kcontrol_dapm(kcontrol); - struct rt722_sdca_priv *rt722 = snd_soc_component_get_drvdata(component); - struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; - unsigned int *item = ucontrol->value.enumerated.item; - unsigned int val, val2 = 0, change, mask_sft; - - if (item[0] >= e->items) - return -EINVAL; - - if (strstr(ucontrol->id.name, "ADC 22 Mux")) - mask_sft = 12; - else if (strstr(ucontrol->id.name, "ADC 24 Mux")) - mask_sft = 4; - else if (strstr(ucontrol->id.name, "ADC 25 Mux")) - mask_sft = 0; - else - return -EINVAL; - - val = snd_soc_enum_item_to_val(e, item[0]) << e->shift_l; - - rt722_sdca_index_read(rt722, RT722_VENDOR_HDA_CTL, - RT722_HDA_LEGACY_MUX_CTL0, &val2); - val2 = (0x7 << mask_sft) & val2; - - if (val == val2) - change = 0; - else - change = 1; - - if (change) - rt722_sdca_index_update_bits(rt722, RT722_VENDOR_HDA_CTL, - RT722_HDA_LEGACY_MUX_CTL0, 0x7 << mask_sft, - val << mask_sft); - - snd_soc_dapm_mux_update_power(dapm, kcontrol, - item[0], e, NULL); - - return change; -} - static const char * const adc22_mux_text[] = { "MIC2", "LINE1", @@ -821,26 +752,26 @@ static const char * const adc07_10_mux_text[] = { "DMIC2", }; -static SOC_ENUM_SINGLE_DECL( - rt722_adc22_enum, SND_SOC_NOPM, 0, adc22_mux_text); +static SOC_ENUM_SINGLE_DECL(rt722_adc22_enum, + RT722_NID_ADDR(RT722_VENDOR_HDA_CTL, RT722_HDA_LEGACY_MUX_CTL0), + 12, adc22_mux_text); -static SOC_ENUM_SINGLE_DECL( - rt722_adc24_enum, SND_SOC_NOPM, 0, adc07_10_mux_text); +static SOC_ENUM_SINGLE_DECL(rt722_adc24_enum, + RT722_NID_ADDR(RT722_VENDOR_HDA_CTL, RT722_HDA_LEGACY_MUX_CTL0), + 4, adc07_10_mux_text); -static SOC_ENUM_SINGLE_DECL( - rt722_adc25_enum, SND_SOC_NOPM, 0, adc07_10_mux_text); +static SOC_ENUM_SINGLE_DECL(rt722_adc25_enum, + RT722_NID_ADDR(RT722_VENDOR_HDA_CTL, RT722_HDA_LEGACY_MUX_CTL0), + 0, adc07_10_mux_text); static const struct snd_kcontrol_new rt722_sdca_adc22_mux = - SOC_DAPM_ENUM_EXT("ADC 22 Mux", rt722_adc22_enum, - rt722_sdca_adc_mux_get, rt722_sdca_adc_mux_put); + SOC_DAPM_ENUM("ADC 22 Mux", rt722_adc22_enum); static const struct snd_kcontrol_new rt722_sdca_adc24_mux = - SOC_DAPM_ENUM_EXT("ADC 24 Mux", rt722_adc24_enum, - rt722_sdca_adc_mux_get, rt722_sdca_adc_mux_put); + SOC_DAPM_ENUM("ADC 24 Mux", rt722_adc24_enum); static const struct snd_kcontrol_new rt722_sdca_adc25_mux = - SOC_DAPM_ENUM_EXT("ADC 25 Mux", rt722_adc25_enum, - rt722_sdca_adc_mux_get, rt722_sdca_adc_mux_put); + SOC_DAPM_ENUM("ADC 25 Mux", rt722_adc25_enum); static int rt722_sdca_fu42_event(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol, int event) @@ -1335,8 +1266,7 @@ static struct snd_soc_dai_driver rt722_sdca_dai[] = { } }; -int rt722_sdca_init(struct device *dev, struct regmap *regmap, - struct regmap *mbq_regmap, struct sdw_slave *slave) +int rt722_sdca_init(struct device *dev, struct regmap *regmap, struct sdw_slave *slave) { struct rt722_sdca_priv *rt722; @@ -1347,7 +1277,6 @@ int rt722_sdca_init(struct device *dev, struct regmap *regmap, dev_set_drvdata(dev, rt722); rt722->slave = slave; rt722->regmap = regmap; - rt722->mbq_regmap = mbq_regmap; mutex_init(&rt722->calibrate_mutex); mutex_init(&rt722->disable_irq_lock); @@ -1521,8 +1450,6 @@ int rt722_sdca_io_init(struct device *dev, struct sdw_slave *slave) if (rt722->first_hw_init) { regcache_cache_only(rt722->regmap, false); regcache_cache_bypass(rt722->regmap, true); - regcache_cache_only(rt722->mbq_regmap, false); - regcache_cache_bypass(rt722->mbq_regmap, true); } else { /* * PM runtime is only enabled when a Slave reports as Attached @@ -1550,8 +1477,6 @@ int rt722_sdca_io_init(struct device *dev, struct sdw_slave *slave) if (rt722->first_hw_init) { regcache_cache_bypass(rt722->regmap, false); regcache_mark_dirty(rt722->regmap); - regcache_cache_bypass(rt722->mbq_regmap, false); - regcache_mark_dirty(rt722->mbq_regmap); } else rt722->first_hw_init = true; diff --git a/sound/soc/codecs/rt722-sdca.h b/sound/soc/codecs/rt722-sdca.h index 2464361a7958c6..04c3b4232ef333 100644 --- a/sound/soc/codecs/rt722-sdca.h +++ b/sound/soc/codecs/rt722-sdca.h @@ -17,7 +17,6 @@ struct rt722_sdca_priv { struct regmap *regmap; - struct regmap *mbq_regmap; struct snd_soc_component *component; struct sdw_slave *slave; struct sdw_bus_params params; @@ -229,8 +228,7 @@ enum rt722_sdca_jd_src { }; int rt722_sdca_io_init(struct device *dev, struct sdw_slave *slave); -int rt722_sdca_init(struct device *dev, struct regmap *regmap, - struct regmap *mbq_regmap, struct sdw_slave *slave); +int rt722_sdca_init(struct device *dev, struct regmap *regmap, struct sdw_slave *slave); int rt722_sdca_index_write(struct rt722_sdca_priv *rt722, unsigned int nid, unsigned int reg, unsigned int value); int rt722_sdca_index_read(struct rt722_sdca_priv *rt722,