1 // SPDX-License-Identifier: GPL-2.0 2 // Copyright(c) 2020 Intel Corporation. 3 4 #include <linux/device.h> 5 #include <linux/errno.h> 6 #include <linux/module.h> 7 #include <linux/regmap.h> 8 #include <linux/soundwire/sdw.h> 9 #include <linux/soundwire/sdw_registers.h> 10 #include "internal.h" 11 12 static int regmap_sdw_mbq_write(void *context, unsigned int reg, unsigned int val) 13 { 14 struct device *dev = context; 15 struct sdw_slave *slave = dev_to_sdw_dev(dev); 16 int ret; 17 18 ret = sdw_write(slave, SDW_SDCA_MBQ_CTL(reg), (val >> 8) & 0xff); 19 if (ret < 0) 20 return ret; 21 22 return sdw_write(slave, reg, val & 0xff); 23 } 24 25 static int regmap_sdw_mbq_read(void *context, unsigned int reg, unsigned int *val) 26 { 27 struct device *dev = context; 28 struct sdw_slave *slave = dev_to_sdw_dev(dev); 29 int read0; 30 int read1; 31 32 read0 = sdw_read(slave, reg); 33 if (read0 < 0) 34 return read0; 35 36 read1 = sdw_read(slave, SDW_SDCA_MBQ_CTL(reg)); 37 if (read1 < 0) 38 return read1; 39 40 *val = (read1 << 8) | read0; 41 42 return 0; 43 } 44 45 static struct regmap_bus regmap_sdw_mbq = { 46 .reg_read = regmap_sdw_mbq_read, 47 .reg_write = regmap_sdw_mbq_write, 48 .reg_format_endian_default = REGMAP_ENDIAN_LITTLE, 49 .val_format_endian_default = REGMAP_ENDIAN_LITTLE, 50 }; 51 52 static int regmap_sdw_mbq_config_check(const struct regmap_config *config) 53 { 54 /* MBQ-based controls are only 16-bits for now */ 55 if (config->val_bits != 16) 56 return -ENOTSUPP; 57 58 /* Registers are 32 bits wide */ 59 if (config->reg_bits != 32) 60 return -ENOTSUPP; 61 62 if (config->pad_bits != 0) 63 return -ENOTSUPP; 64 65 return 0; 66 } 67 68 struct regmap *__regmap_init_sdw_mbq(struct sdw_slave *sdw, 69 const struct regmap_config *config, 70 struct lock_class_key *lock_key, 71 const char *lock_name) 72 { 73 int ret; 74 75 ret = regmap_sdw_mbq_config_check(config); 76 if (ret) 77 return ERR_PTR(ret); 78 79 return __regmap_init(&sdw->dev, ®map_sdw_mbq, 80 &sdw->dev, config, lock_key, lock_name); 81 } 82 EXPORT_SYMBOL_GPL(__regmap_init_sdw_mbq); 83 84 struct regmap *__devm_regmap_init_sdw_mbq(struct sdw_slave *sdw, 85 const struct regmap_config *config, 86 struct lock_class_key *lock_key, 87 const char *lock_name) 88 { 89 int ret; 90 91 ret = regmap_sdw_mbq_config_check(config); 92 if (ret) 93 return ERR_PTR(ret); 94 95 return __devm_regmap_init(&sdw->dev, ®map_sdw_mbq, 96 &sdw->dev, config, lock_key, lock_name); 97 } 98 EXPORT_SYMBOL_GPL(__devm_regmap_init_sdw_mbq); 99 100 MODULE_DESCRIPTION("Regmap SoundWire MBQ Module"); 101 MODULE_LICENSE("GPL v2"); 102