cs42l83-i2c.c 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * cs42l83-i2c.c -- CS42L83 ALSA SoC audio driver for I2C
  4. *
  5. * Based on cs42l42-i2c.c:
  6. * Copyright 2016, 2022 Cirrus Logic, Inc.
  7. */
  8. #include <linux/i2c.h>
  9. #include <linux/module.h>
  10. #include <linux/regmap.h>
  11. #include <linux/slab.h>
  12. #include <linux/types.h>
  13. #include "cs42l42.h"
  14. static const struct reg_default cs42l83_reg_defaults[] = {
  15. { CS42L42_FRZ_CTL, 0x00 },
  16. { CS42L42_SRC_CTL, 0x10 },
  17. { CS42L42_MCLK_CTL, 0x00 }, /* <- only deviation from CS42L42 */
  18. { CS42L42_SFTRAMP_RATE, 0xA4 },
  19. { CS42L42_SLOW_START_ENABLE, 0x70 },
  20. { CS42L42_I2C_DEBOUNCE, 0x88 },
  21. { CS42L42_I2C_STRETCH, 0x03 },
  22. { CS42L42_I2C_TIMEOUT, 0xB7 },
  23. { CS42L42_PWR_CTL1, 0xFF },
  24. { CS42L42_PWR_CTL2, 0x84 },
  25. { CS42L42_PWR_CTL3, 0x20 },
  26. { CS42L42_RSENSE_CTL1, 0x40 },
  27. { CS42L42_RSENSE_CTL2, 0x00 },
  28. { CS42L42_OSC_SWITCH, 0x00 },
  29. { CS42L42_RSENSE_CTL3, 0x1B },
  30. { CS42L42_TSENSE_CTL, 0x1B },
  31. { CS42L42_TSRS_INT_DISABLE, 0x00 },
  32. { CS42L42_HSDET_CTL1, 0x77 },
  33. { CS42L42_HSDET_CTL2, 0x00 },
  34. { CS42L42_HS_SWITCH_CTL, 0xF3 },
  35. { CS42L42_HS_CLAMP_DISABLE, 0x00 },
  36. { CS42L42_MCLK_SRC_SEL, 0x00 },
  37. { CS42L42_SPDIF_CLK_CFG, 0x00 },
  38. { CS42L42_FSYNC_PW_LOWER, 0x00 },
  39. { CS42L42_FSYNC_PW_UPPER, 0x00 },
  40. { CS42L42_FSYNC_P_LOWER, 0xF9 },
  41. { CS42L42_FSYNC_P_UPPER, 0x00 },
  42. { CS42L42_ASP_CLK_CFG, 0x00 },
  43. { CS42L42_ASP_FRM_CFG, 0x10 },
  44. { CS42L42_FS_RATE_EN, 0x00 },
  45. { CS42L42_IN_ASRC_CLK, 0x00 },
  46. { CS42L42_OUT_ASRC_CLK, 0x00 },
  47. { CS42L42_PLL_DIV_CFG1, 0x00 },
  48. { CS42L42_ADC_OVFL_INT_MASK, 0x01 },
  49. { CS42L42_MIXER_INT_MASK, 0x0F },
  50. { CS42L42_SRC_INT_MASK, 0x0F },
  51. { CS42L42_ASP_RX_INT_MASK, 0x1F },
  52. { CS42L42_ASP_TX_INT_MASK, 0x0F },
  53. { CS42L42_CODEC_INT_MASK, 0x03 },
  54. { CS42L42_SRCPL_INT_MASK, 0x7F },
  55. { CS42L42_VPMON_INT_MASK, 0x01 },
  56. { CS42L42_PLL_LOCK_INT_MASK, 0x01 },
  57. { CS42L42_TSRS_PLUG_INT_MASK, 0x0F },
  58. { CS42L42_PLL_CTL1, 0x00 },
  59. { CS42L42_PLL_DIV_FRAC0, 0x00 },
  60. { CS42L42_PLL_DIV_FRAC1, 0x00 },
  61. { CS42L42_PLL_DIV_FRAC2, 0x00 },
  62. { CS42L42_PLL_DIV_INT, 0x40 },
  63. { CS42L42_PLL_CTL3, 0x10 },
  64. { CS42L42_PLL_CAL_RATIO, 0x80 },
  65. { CS42L42_PLL_CTL4, 0x03 },
  66. { CS42L42_LOAD_DET_EN, 0x00 },
  67. { CS42L42_HSBIAS_SC_AUTOCTL, 0x03 },
  68. { CS42L42_WAKE_CTL, 0xC0 },
  69. { CS42L42_ADC_DISABLE_MUTE, 0x00 },
  70. { CS42L42_TIPSENSE_CTL, 0x02 },
  71. { CS42L42_MISC_DET_CTL, 0x03 },
  72. { CS42L42_MIC_DET_CTL1, 0x1F },
  73. { CS42L42_MIC_DET_CTL2, 0x2F },
  74. { CS42L42_DET_INT1_MASK, 0xE0 },
  75. { CS42L42_DET_INT2_MASK, 0xFF },
  76. { CS42L42_HS_BIAS_CTL, 0xC2 },
  77. { CS42L42_ADC_CTL, 0x00 },
  78. { CS42L42_ADC_VOLUME, 0x00 },
  79. { CS42L42_ADC_WNF_HPF_CTL, 0x71 },
  80. { CS42L42_DAC_CTL1, 0x00 },
  81. { CS42L42_DAC_CTL2, 0x02 },
  82. { CS42L42_HP_CTL, 0x0D },
  83. { CS42L42_CLASSH_CTL, 0x07 },
  84. { CS42L42_MIXER_CHA_VOL, 0x3F },
  85. { CS42L42_MIXER_ADC_VOL, 0x3F },
  86. { CS42L42_MIXER_CHB_VOL, 0x3F },
  87. { CS42L42_EQ_COEF_IN0, 0x00 },
  88. { CS42L42_EQ_COEF_IN1, 0x00 },
  89. { CS42L42_EQ_COEF_IN2, 0x00 },
  90. { CS42L42_EQ_COEF_IN3, 0x00 },
  91. { CS42L42_EQ_COEF_RW, 0x00 },
  92. { CS42L42_EQ_COEF_OUT0, 0x00 },
  93. { CS42L42_EQ_COEF_OUT1, 0x00 },
  94. { CS42L42_EQ_COEF_OUT2, 0x00 },
  95. { CS42L42_EQ_COEF_OUT3, 0x00 },
  96. { CS42L42_EQ_INIT_STAT, 0x00 },
  97. { CS42L42_EQ_START_FILT, 0x00 },
  98. { CS42L42_EQ_MUTE_CTL, 0x00 },
  99. { CS42L42_SP_RX_CH_SEL, 0x04 },
  100. { CS42L42_SP_RX_ISOC_CTL, 0x04 },
  101. { CS42L42_SP_RX_FS, 0x8C },
  102. { CS42l42_SPDIF_CH_SEL, 0x0E },
  103. { CS42L42_SP_TX_ISOC_CTL, 0x04 },
  104. { CS42L42_SP_TX_FS, 0xCC },
  105. { CS42L42_SPDIF_SW_CTL1, 0x3F },
  106. { CS42L42_SRC_SDIN_FS, 0x40 },
  107. { CS42L42_SRC_SDOUT_FS, 0x40 },
  108. { CS42L42_SPDIF_CTL1, 0x01 },
  109. { CS42L42_SPDIF_CTL2, 0x00 },
  110. { CS42L42_SPDIF_CTL3, 0x00 },
  111. { CS42L42_SPDIF_CTL4, 0x42 },
  112. { CS42L42_ASP_TX_SZ_EN, 0x00 },
  113. { CS42L42_ASP_TX_CH_EN, 0x00 },
  114. { CS42L42_ASP_TX_CH_AP_RES, 0x0F },
  115. { CS42L42_ASP_TX_CH1_BIT_MSB, 0x00 },
  116. { CS42L42_ASP_TX_CH1_BIT_LSB, 0x00 },
  117. { CS42L42_ASP_TX_HIZ_DLY_CFG, 0x00 },
  118. { CS42L42_ASP_TX_CH2_BIT_MSB, 0x00 },
  119. { CS42L42_ASP_TX_CH2_BIT_LSB, 0x00 },
  120. { CS42L42_ASP_RX_DAI0_EN, 0x00 },
  121. { CS42L42_ASP_RX_DAI0_CH1_AP_RES, 0x03 },
  122. { CS42L42_ASP_RX_DAI0_CH1_BIT_MSB, 0x00 },
  123. { CS42L42_ASP_RX_DAI0_CH1_BIT_LSB, 0x00 },
  124. { CS42L42_ASP_RX_DAI0_CH2_AP_RES, 0x03 },
  125. { CS42L42_ASP_RX_DAI0_CH2_BIT_MSB, 0x00 },
  126. { CS42L42_ASP_RX_DAI0_CH2_BIT_LSB, 0x00 },
  127. { CS42L42_ASP_RX_DAI0_CH3_AP_RES, 0x03 },
  128. { CS42L42_ASP_RX_DAI0_CH3_BIT_MSB, 0x00 },
  129. { CS42L42_ASP_RX_DAI0_CH3_BIT_LSB, 0x00 },
  130. { CS42L42_ASP_RX_DAI0_CH4_AP_RES, 0x03 },
  131. { CS42L42_ASP_RX_DAI0_CH4_BIT_MSB, 0x00 },
  132. { CS42L42_ASP_RX_DAI0_CH4_BIT_LSB, 0x00 },
  133. { CS42L42_ASP_RX_DAI1_CH1_AP_RES, 0x03 },
  134. { CS42L42_ASP_RX_DAI1_CH1_BIT_MSB, 0x00 },
  135. { CS42L42_ASP_RX_DAI1_CH1_BIT_LSB, 0x00 },
  136. { CS42L42_ASP_RX_DAI1_CH2_AP_RES, 0x03 },
  137. { CS42L42_ASP_RX_DAI1_CH2_BIT_MSB, 0x00 },
  138. { CS42L42_ASP_RX_DAI1_CH2_BIT_LSB, 0x00 },
  139. };
  140. /*
  141. * This is all the same as for CS42L42 but we
  142. * replace the on-reset register defaults.
  143. */
  144. const struct regmap_config cs42l83_regmap = {
  145. .reg_bits = 8,
  146. .val_bits = 8,
  147. .readable_reg = cs42l42_readable_register,
  148. .volatile_reg = cs42l42_volatile_register,
  149. .ranges = &cs42l42_page_range,
  150. .num_ranges = 1,
  151. .max_register = CS42L42_MAX_REGISTER,
  152. .reg_defaults = cs42l83_reg_defaults,
  153. .num_reg_defaults = ARRAY_SIZE(cs42l83_reg_defaults),
  154. .cache_type = REGCACHE_RBTREE,
  155. .use_single_read = true,
  156. .use_single_write = true,
  157. };
  158. static int cs42l83_i2c_probe(struct i2c_client *i2c_client)
  159. {
  160. struct device *dev = &i2c_client->dev;
  161. struct cs42l42_private *cs42l83;
  162. struct regmap *regmap;
  163. int ret;
  164. cs42l83 = devm_kzalloc(dev, sizeof(*cs42l83), GFP_KERNEL);
  165. if (!cs42l83)
  166. return -ENOMEM;
  167. regmap = devm_regmap_init_i2c(i2c_client, &cs42l83_regmap);
  168. if (IS_ERR(regmap))
  169. return dev_err_probe(&i2c_client->dev, PTR_ERR(regmap),
  170. "regmap_init() failed\n");
  171. cs42l83->devid = CS42L83_CHIP_ID;
  172. cs42l83->dev = dev;
  173. cs42l83->regmap = regmap;
  174. cs42l83->irq = i2c_client->irq;
  175. ret = cs42l42_common_probe(cs42l83, &cs42l42_soc_component, &cs42l42_dai);
  176. if (ret)
  177. return ret;
  178. return cs42l42_init(cs42l83);
  179. }
  180. static void cs42l83_i2c_remove(struct i2c_client *i2c_client)
  181. {
  182. struct cs42l42_private *cs42l83 = dev_get_drvdata(&i2c_client->dev);
  183. cs42l42_common_remove(cs42l83);
  184. }
  185. static int __maybe_unused cs42l83_i2c_resume(struct device *dev)
  186. {
  187. int ret;
  188. ret = cs42l42_resume(dev);
  189. if (ret)
  190. return ret;
  191. cs42l42_resume_restore(dev);
  192. return 0;
  193. }
  194. static const struct dev_pm_ops cs42l83_i2c_pm_ops = {
  195. SET_SYSTEM_SLEEP_PM_OPS(cs42l42_suspend, cs42l83_i2c_resume)
  196. };
  197. static const struct of_device_id __maybe_unused cs42l83_of_match[] = {
  198. { .compatible = "cirrus,cs42l83", },
  199. {}
  200. };
  201. MODULE_DEVICE_TABLE(of, cs42l83_of_match);
  202. static struct i2c_driver cs42l83_i2c_driver = {
  203. .driver = {
  204. .name = "cs42l83",
  205. .pm = &cs42l83_i2c_pm_ops,
  206. .of_match_table = of_match_ptr(cs42l83_of_match),
  207. },
  208. .probe_new = cs42l83_i2c_probe,
  209. .remove = cs42l83_i2c_remove,
  210. };
  211. module_i2c_driver(cs42l83_i2c_driver);
  212. MODULE_DESCRIPTION("ASoC CS42L83 I2C driver");
  213. MODULE_AUTHOR("Martin Povišer <[email protected]>");
  214. MODULE_LICENSE("GPL");
  215. MODULE_IMPORT_NS(SND_SOC_CS42L42_CORE);