regmap-sdw-mbq.c 2.4 KB

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