aqt1000-utils.c 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /* Copyright (c) 2016-2018, The Linux Foundation. All rights reserved.
  3. */
  4. #include <linux/kernel.h>
  5. #include <linux/module.h>
  6. #include <linux/slab.h>
  7. #include <linux/regmap.h>
  8. #include <linux/delay.h>
  9. #include <linux/sched.h>
  10. #include "aqt1000.h"
  11. #include "aqt1000-utils.h"
  12. #define REG_BYTES 2
  13. #define VAL_BYTES 1
  14. /*
  15. * Page Register Address that APP Proc uses to
  16. * access codec registers is identified as 0x00
  17. */
  18. #define PAGE_REG_ADDR 0x00
  19. static int aqt_page_write(struct aqt1000 *aqt, unsigned short *reg)
  20. {
  21. int ret = 0;
  22. unsigned short c_reg, reg_addr;
  23. u8 pg_num, prev_pg_num;
  24. c_reg = *reg;
  25. pg_num = c_reg >> 8;
  26. reg_addr = c_reg & 0xff;
  27. if (aqt->prev_pg_valid) {
  28. prev_pg_num = aqt->prev_pg;
  29. if (prev_pg_num != pg_num) {
  30. ret = aqt->write_dev(
  31. aqt, PAGE_REG_ADDR,
  32. (void *) &pg_num, 1);
  33. if (ret < 0)
  34. dev_err(aqt->dev,
  35. "%s: page write error, pg_num: 0x%x\n",
  36. __func__, pg_num);
  37. else {
  38. aqt->prev_pg = pg_num;
  39. dev_dbg(aqt->dev, "%s: Page 0x%x Write to 0x00\n",
  40. __func__, pg_num);
  41. }
  42. }
  43. } else {
  44. ret = aqt->write_dev(
  45. aqt, PAGE_REG_ADDR, (void *) &pg_num, 1);
  46. if (ret < 0)
  47. dev_err(aqt->dev,
  48. "%s: page write error, pg_num: 0x%x\n",
  49. __func__, pg_num);
  50. else {
  51. aqt->prev_pg = pg_num;
  52. aqt->prev_pg_valid = true;
  53. dev_dbg(aqt->dev, "%s: Page 0x%x Write to 0x00\n",
  54. __func__, pg_num);
  55. }
  56. }
  57. *reg = reg_addr;
  58. return ret;
  59. }
  60. static int regmap_bus_read(void *context, const void *reg, size_t reg_size,
  61. void *val, size_t val_size)
  62. {
  63. struct device *dev = context;
  64. struct aqt1000 *aqt = dev_get_drvdata(dev);
  65. unsigned short c_reg, rreg;
  66. int ret, i;
  67. if (!aqt) {
  68. dev_err(dev, "%s: aqt is NULL\n", __func__);
  69. return -EINVAL;
  70. }
  71. if (!reg || !val) {
  72. dev_err(dev, "%s: reg or val is NULL\n", __func__);
  73. return -EINVAL;
  74. }
  75. if (reg_size != REG_BYTES) {
  76. dev_err(dev, "%s: register size %zd bytes, not supported\n",
  77. __func__, reg_size);
  78. return -EINVAL;
  79. }
  80. mutex_lock(&aqt->io_lock);
  81. c_reg = *(u16 *)reg;
  82. rreg = c_reg;
  83. ret = aqt_page_write(aqt, &c_reg);
  84. if (ret)
  85. goto err;
  86. ret = aqt->read_dev(aqt, c_reg, val, val_size);
  87. if (ret < 0)
  88. dev_err(dev, "%s: Codec read failed (%d), reg: 0x%x, size:%zd\n",
  89. __func__, ret, rreg, val_size);
  90. else {
  91. for (i = 0; i < val_size; i++)
  92. dev_dbg(dev, "%s: Read 0x%02x from 0x%x\n",
  93. __func__, ((u8 *)val)[i], rreg + i);
  94. }
  95. err:
  96. mutex_unlock(&aqt->io_lock);
  97. return ret;
  98. }
  99. static int regmap_bus_gather_write(void *context,
  100. const void *reg, size_t reg_size,
  101. const void *val, size_t val_size)
  102. {
  103. struct device *dev = context;
  104. struct aqt1000 *aqt = dev_get_drvdata(dev);
  105. unsigned short c_reg, rreg;
  106. int ret, i;
  107. if (!aqt) {
  108. dev_err(dev, "%s: aqt is NULL\n", __func__);
  109. return -EINVAL;
  110. }
  111. if (!reg || !val) {
  112. dev_err(dev, "%s: reg or val is NULL\n", __func__);
  113. return -EINVAL;
  114. }
  115. if (reg_size != REG_BYTES) {
  116. dev_err(dev, "%s: register size %zd bytes, not supported\n",
  117. __func__, reg_size);
  118. return -EINVAL;
  119. }
  120. mutex_lock(&aqt->io_lock);
  121. c_reg = *(u16 *)reg;
  122. rreg = c_reg;
  123. ret = aqt_page_write(aqt, &c_reg);
  124. if (ret)
  125. goto err;
  126. for (i = 0; i < val_size; i++)
  127. dev_dbg(dev, "Write %02x to 0x%x\n", ((u8 *)val)[i],
  128. rreg + i);
  129. ret = aqt->write_dev(aqt, c_reg, (void *) val, val_size);
  130. if (ret < 0)
  131. dev_err(dev, "%s: Codec write failed (%d), reg:0x%x, size:%zd\n",
  132. __func__, ret, rreg, val_size);
  133. err:
  134. mutex_unlock(&aqt->io_lock);
  135. return ret;
  136. }
  137. static int regmap_bus_write(void *context, const void *data, size_t count)
  138. {
  139. struct device *dev = context;
  140. struct aqt1000 *aqt = dev_get_drvdata(dev);
  141. if (!aqt)
  142. return -EINVAL;
  143. WARN_ON(count < REG_BYTES);
  144. return regmap_bus_gather_write(context, data, REG_BYTES,
  145. data + REG_BYTES,
  146. count - REG_BYTES);
  147. }
  148. static struct regmap_bus regmap_bus_config = {
  149. .write = regmap_bus_write,
  150. .gather_write = regmap_bus_gather_write,
  151. .read = regmap_bus_read,
  152. .reg_format_endian_default = REGMAP_ENDIAN_NATIVE,
  153. .val_format_endian_default = REGMAP_ENDIAN_NATIVE,
  154. };
  155. /*
  156. * aqt1000_regmap_init:
  157. * Initialize aqt1000 register map
  158. *
  159. * @dev: pointer to wcd device
  160. * @config: pointer to register map config
  161. *
  162. * Returns pointer to regmap structure for success
  163. * or NULL in case of failure.
  164. */
  165. struct regmap *aqt1000_regmap_init(struct device *dev,
  166. const struct regmap_config *config)
  167. {
  168. return devm_regmap_init(dev, &regmap_bus_config, dev, config);
  169. }
  170. EXPORT_SYMBOL(aqt1000_regmap_init);