hpm_sgtl5000.c 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648
  1. /*
  2. * Copyright (c) 2015, Freescale Semiconductor, Inc.
  3. * Copyright 2016-2019 NXP
  4. * Copyright (c) 2021 HPMicro
  5. *
  6. * SPDX-License-Identifier: BSD-3-Clause
  7. *
  8. */
  9. #include "hpm_sgtl5000.h"
  10. #ifndef HPM_SGTL5000_MCLK_TOLERANCE
  11. #define HPM_SGTL5000_MCLK_TOLERANCE (4U)
  12. #endif
  13. hpm_stat_t sgtl_init(sgtl_context_t *context, sgtl_config_t *config)
  14. {
  15. assert(context != NULL);
  16. assert(config != NULL);
  17. if (sgtl_write_reg(context, CHIP_ANA_POWER, 0x6AFF) != status_success) {
  18. return status_fail;
  19. }
  20. /* Set the data route */
  21. if (sgtl_set_data_route(context, config->route) != status_success) {
  22. return status_fail;
  23. }
  24. /* Set sgtl5000 to master or slave */
  25. sgtl_set_master_mode(context, config->master);
  26. /*
  27. * Input Volume Control
  28. * Configure ADC left and right analog volume to desired default.
  29. * Example shows volume of 0dB.
  30. */
  31. if (sgtl_write_reg(context, CHIP_ANA_ADC_CTRL, 0x0000U) != status_success) {
  32. return status_fail;
  33. }
  34. /*
  35. * Volume and Mute Control
  36. * Configure HP_OUT left and right volume to minimum, unmute.
  37. * HP_OUT and ramp the volume up to desired volume.
  38. */
  39. if (sgtl_write_reg(context, CHIP_ANA_HP_CTRL, 0x1818U) != status_success) {
  40. return status_fail;
  41. }
  42. if (sgtl_modify_reg(context, CHIP_ANA_CTRL, 0xFFEFU, 0x0000U) != status_success) {
  43. return status_fail;
  44. }
  45. /* LINEOUT and DAC volume control */
  46. if (sgtl_modify_reg(context, CHIP_ANA_CTRL, 0xFEFFU, 0x0000U) != status_success) {
  47. return status_fail;
  48. }
  49. /* Configure DAC left and right digital volume */
  50. if (sgtl_write_reg(context, CHIP_DAC_VOL, 0x5C5CU) != status_success) {
  51. return status_fail;
  52. }
  53. /* Configure ADC volume, reduce 6db. */
  54. if (sgtl_write_reg(context, CHIP_ANA_ADC_CTRL, 0x0100U) != status_success) {
  55. return status_fail;
  56. }
  57. /* Unmute DAC */
  58. if (sgtl_modify_reg(context, CHIP_ADCDAC_CTRL, 0xFFFBU, 0x0000U) != status_success) {
  59. return status_fail;
  60. }
  61. if (sgtl_modify_reg(context, CHIP_ADCDAC_CTRL, 0xFFF7U, 0x0000U) != status_success) {
  62. return status_fail;
  63. }
  64. /* Unmute ADC */
  65. if (sgtl_modify_reg(context, CHIP_ANA_CTRL, 0xFFFEU, 0x0000U) != status_success) {
  66. return status_fail;
  67. }
  68. /* Set the audio format */
  69. if (sgtl_set_protocol(context, config->bus) != status_success) {
  70. return status_fail;
  71. }
  72. if (sgtl_config_data_format(context, config->format.mclk_hz, config->format.sample_rate, config->format.bit_width) !=
  73. status_success) {
  74. return status_fail;
  75. }
  76. /* sclk valid edge */
  77. if (config->format.sclk_edge == sgtl_sclk_valid_edge_rising) {
  78. if (sgtl_modify_reg(context, CHIP_I2S_CTRL, SGTL5000_I2S_SCLK_INV_CLR_MASK, SGTL5000_I2S_VAILD_RISING_EDGE) !=
  79. status_success) {
  80. return status_fail;
  81. }
  82. } else {
  83. if (sgtl_modify_reg(context, CHIP_I2S_CTRL, SGTL5000_I2S_SCLK_INV_CLR_MASK, SGTL5000_I2S_VAILD_FALLING_EDGE) !=
  84. status_success) {
  85. return status_fail;
  86. }
  87. }
  88. return status_success;
  89. }
  90. hpm_stat_t sgtl_deinit(sgtl_context_t *context)
  91. {
  92. hpm_stat_t stat = status_success;
  93. HPM_CHECK_RET(sgtl_disable_module(context, sgtl_module_adc));
  94. HPM_CHECK_RET(sgtl_disable_module(context, sgtl_module_dac));
  95. HPM_CHECK_RET(sgtl_disable_module(context, sgtl_module_dap));
  96. HPM_CHECK_RET(sgtl_disable_module(context, sgtl_module_i2sin));
  97. HPM_CHECK_RET(sgtl_disable_module(context, sgtl_module_i2sout));
  98. HPM_CHECK_RET(sgtl_disable_module(context, sgtl_module_lineout));
  99. return stat;
  100. }
  101. void sgtl_set_master_mode(sgtl_context_t *context, bool master)
  102. {
  103. if (master == true) {
  104. (void)sgtl_modify_reg(context, CHIP_I2S_CTRL, SGTL5000_I2S_MS_CLR_MASK, SGTL5000_I2S_MASTER);
  105. } else {
  106. (void)sgtl_modify_reg(context, CHIP_I2S_CTRL, SGTL5000_I2S_MS_CLR_MASK, SGTL5000_I2S_SLAVE);
  107. }
  108. }
  109. hpm_stat_t sgtl_enable_module(sgtl_context_t *context, sgtl_module_t module)
  110. {
  111. hpm_stat_t stat = status_success;
  112. switch (module) {
  113. case sgtl_module_adc:
  114. HPM_CHECK_RET(sgtl_modify_reg(context, CHIP_DIG_POWER, SGTL5000_ADC_ENABLE_CLR_MASK,
  115. ((uint16_t)1U << SGTL5000_ADC_ENABLE_SHIFT)));
  116. HPM_CHECK_RET(sgtl_modify_reg(context, CHIP_ANA_POWER, SGTL5000_ADC_POWERUP_CLR_MASK,
  117. ((uint16_t)1U << SGTL5000_ADC_POWERUP_SHIFT)));
  118. break;
  119. case sgtl_module_dac:
  120. HPM_CHECK_RET(sgtl_modify_reg(context, CHIP_DIG_POWER, SGTL5000_DAC_ENABLE_CLR_MASK,
  121. ((uint16_t)1U << SGTL5000_DAC_ENABLE_SHIFT)));
  122. HPM_CHECK_RET(sgtl_modify_reg(context, CHIP_ANA_POWER, SGTL5000_DAC_POWERUP_CLR_MASK,
  123. ((uint16_t)1U << SGTL5000_DAC_POWERUP_SHIFT)));
  124. break;
  125. case sgtl_module_dap:
  126. HPM_CHECK_RET(sgtl_modify_reg(context, CHIP_DIG_POWER, SGTL5000_DAP_ENABLE_CLR_MASK,
  127. ((uint16_t)1U << SGTL5000_DAP_ENABLE_SHIFT)));
  128. HPM_CHECK_RET(sgtl_modify_reg(context, SGTL5000_DAP_CONTROL, SGTL5000_DAP_CONTROL_DAP_EN_CLR_MASK,
  129. ((uint16_t)1U << SGTL5000_DAP_CONTROL_DAP_EN_SHIFT)));
  130. break;
  131. case sgtl_module_i2sin:
  132. HPM_CHECK_RET(sgtl_modify_reg(context, CHIP_DIG_POWER, SGTL5000_I2S_IN_ENABLE_CLR_MASK,
  133. ((uint16_t)1U << SGTL5000_I2S_IN_ENABLE_SHIFT)));
  134. break;
  135. case sgtl_module_i2sout:
  136. HPM_CHECK_RET(sgtl_modify_reg(context, CHIP_DIG_POWER, SGTL5000_I2S_OUT_ENABLE_CLR_MASK,
  137. ((uint16_t)1U << SGTL5000_I2S_OUT_ENABLE_SHIFT)));
  138. break;
  139. case sgtl_module_hp:
  140. HPM_CHECK_RET(sgtl_modify_reg(context, CHIP_ANA_POWER, SGTL5000_HEADPHONE_POWERUP_CLR_MASK,
  141. ((uint16_t)1U << SGTL5000_HEADPHONE_POWERUP_SHIFT)));
  142. break;
  143. case sgtl_module_lineout:
  144. HPM_CHECK_RET(sgtl_modify_reg(context, CHIP_ANA_POWER, SGTL5000_LINEOUT_POWERUP_CLR_MASK,
  145. ((uint16_t)1U << SGTL5000_LINEOUT_POWERUP_SHIFT)));
  146. break;
  147. default:
  148. stat = status_invalid_argument;
  149. break;
  150. }
  151. return stat;
  152. }
  153. hpm_stat_t sgtl_disable_module(sgtl_context_t *context, sgtl_module_t module)
  154. {
  155. hpm_stat_t stat = status_success;
  156. switch (module) {
  157. case sgtl_module_adc:
  158. HPM_CHECK_RET(sgtl_modify_reg(context, CHIP_DIG_POWER, SGTL5000_ADC_ENABLE_CLR_MASK,
  159. ((uint16_t)0U << SGTL5000_ADC_ENABLE_SHIFT)));
  160. HPM_CHECK_RET(sgtl_modify_reg(context, CHIP_ANA_POWER, SGTL5000_ADC_POWERUP_CLR_MASK,
  161. ((uint16_t)0U << SGTL5000_ADC_POWERUP_SHIFT)));
  162. break;
  163. case sgtl_module_dac:
  164. HPM_CHECK_RET(sgtl_modify_reg(context, CHIP_DIG_POWER, SGTL5000_DAC_ENABLE_CLR_MASK,
  165. ((uint16_t)0U << SGTL5000_DAC_ENABLE_SHIFT)));
  166. HPM_CHECK_RET(sgtl_modify_reg(context, CHIP_ANA_POWER, SGTL5000_DAC_POWERUP_CLR_MASK,
  167. ((uint16_t)0U << SGTL5000_DAC_POWERUP_SHIFT)));
  168. break;
  169. case sgtl_module_dap:
  170. HPM_CHECK_RET(sgtl_modify_reg(context, CHIP_DIG_POWER, SGTL5000_DAP_ENABLE_CLR_MASK,
  171. ((uint16_t)0U << SGTL5000_DAP_ENABLE_SHIFT)));
  172. HPM_CHECK_RET(sgtl_modify_reg(context, SGTL5000_DAP_CONTROL, SGTL5000_DAP_CONTROL_DAP_EN_CLR_MASK,
  173. ((uint16_t)0U << SGTL5000_DAP_CONTROL_DAP_EN_SHIFT)));
  174. break;
  175. case sgtl_module_i2sin:
  176. HPM_CHECK_RET(sgtl_modify_reg(context, CHIP_DIG_POWER, SGTL5000_I2S_IN_ENABLE_CLR_MASK,
  177. ((uint16_t)0U << SGTL5000_I2S_IN_ENABLE_SHIFT)));
  178. break;
  179. case sgtl_module_i2sout:
  180. HPM_CHECK_RET(sgtl_modify_reg(context, CHIP_DIG_POWER, SGTL5000_I2S_OUT_ENABLE_CLR_MASK,
  181. ((uint16_t)0U << SGTL5000_I2S_OUT_ENABLE_SHIFT)));
  182. break;
  183. case sgtl_module_hp:
  184. HPM_CHECK_RET(sgtl_modify_reg(context, CHIP_ANA_POWER, SGTL5000_HEADPHONE_POWERUP_CLR_MASK,
  185. ((uint16_t)0U << SGTL5000_HEADPHONE_POWERUP_SHIFT)));
  186. break;
  187. case sgtl_module_lineout:
  188. HPM_CHECK_RET(sgtl_modify_reg(context, CHIP_ANA_POWER, SGTL5000_LINEOUT_POWERUP_CLR_MASK,
  189. ((uint16_t)0U << SGTL5000_LINEOUT_POWERUP_SHIFT)));
  190. break;
  191. default:
  192. stat = status_invalid_argument;
  193. break;
  194. }
  195. return stat;
  196. }
  197. hpm_stat_t sgtl_set_data_route(sgtl_context_t *context, sgtl_route_t route)
  198. {
  199. hpm_stat_t stat = status_success;
  200. switch (route) {
  201. case sgtl_route_bypass:
  202. /* Bypass means from line-in to HP*/
  203. HPM_CHECK_RET(sgtl_write_reg(context, CHIP_DIG_POWER, 0x0000));
  204. HPM_CHECK_RET(sgtl_enable_module(context, sgtl_module_hp));
  205. HPM_CHECK_RET(sgtl_modify_reg(context, CHIP_ANA_CTRL, SGTL5000_SEL_HP_CLR_MASK, SGTL5000_SEL_HP_LINEIN));
  206. break;
  207. case sgtl_route_playback:
  208. /* Data route I2S_IN-> DAC-> HP */
  209. HPM_CHECK_RET(sgtl_enable_module(context, sgtl_module_hp));
  210. HPM_CHECK_RET(sgtl_enable_module(context, sgtl_module_dac));
  211. HPM_CHECK_RET(sgtl_enable_module(context, sgtl_module_i2sin));
  212. HPM_CHECK_RET(sgtl_modify_reg(context, CHIP_SSS_CTRL, SGTL5000_DAC_SEL_CLR_MASK, SGTL5000_DAC_SEL_I2S_IN));
  213. HPM_CHECK_RET(sgtl_modify_reg(context, CHIP_ANA_CTRL, SGTL5000_SEL_HP_CLR_MASK, SGTL5000_SEL_HP_DAC));
  214. break;
  215. case sgtl_route_playback_record:
  216. /* I2S IN->DAC->HP LINE_IN->ADC->I2S_OUT */
  217. HPM_CHECK_RET(sgtl_enable_module(context, sgtl_module_hp));
  218. HPM_CHECK_RET(sgtl_enable_module(context, sgtl_module_dac));
  219. HPM_CHECK_RET(sgtl_enable_module(context, sgtl_module_i2sin));
  220. HPM_CHECK_RET(sgtl_enable_module(context, sgtl_module_i2sout));
  221. HPM_CHECK_RET(sgtl_enable_module(context, sgtl_module_adc));
  222. HPM_CHECK_RET(sgtl_modify_reg(context, CHIP_SSS_CTRL, SGTL5000_DAC_SEL_CLR_MASK, SGTL5000_DAC_SEL_I2S_IN));
  223. HPM_CHECK_RET(sgtl_modify_reg(context, CHIP_ANA_CTRL, SGTL5000_SEL_HP_CLR_MASK, SGTL5000_SEL_HP_DAC));
  224. HPM_CHECK_RET(sgtl_modify_reg(context, CHIP_ANA_CTRL, SGTL5000_SEL_ADC_CLR_MASK, SGTL5000_SEL_ADC_LINEIN));
  225. HPM_CHECK_RET(sgtl_modify_reg(context, CHIP_SSS_CTRL, SGTL5000_I2S_OUT_SEL_CLR_MASK, SGTL5000_I2S_OUT_SEL_ADC));
  226. break;
  227. case sgtl_route_playback_with_dap:
  228. /* I2S_IN->DAP->DAC->HP */
  229. HPM_CHECK_RET(sgtl_enable_module(context, sgtl_module_hp));
  230. HPM_CHECK_RET(sgtl_enable_module(context, sgtl_module_dac));
  231. HPM_CHECK_RET(sgtl_enable_module(context, sgtl_module_i2sin));
  232. HPM_CHECK_RET(sgtl_enable_module(context, sgtl_module_dap));
  233. HPM_CHECK_RET(sgtl_modify_reg(context, CHIP_SSS_CTRL, SGTL5000_DAP_SEL_CLR_MASK, SGTL5000_DAP_SEL_I2S_IN));
  234. HPM_CHECK_RET(sgtl_modify_reg(context, CHIP_SSS_CTRL, SGTL5000_DAC_SEL_CLR_MASK, SGTL5000_DAC_SEL_DAP));
  235. HPM_CHECK_RET(sgtl_modify_reg(context, CHIP_ANA_CTRL, SGTL5000_SEL_HP_CLR_MASK, SGTL5000_SEL_HP_DAC));
  236. break;
  237. case sgtl_route_playback_with_dap_record:
  238. /* I2S_IN->DAP->DAC->HP, LINE_IN->ADC->I2S_OUT */
  239. HPM_CHECK_RET(sgtl_enable_module(context, sgtl_module_hp));
  240. HPM_CHECK_RET(sgtl_enable_module(context, sgtl_module_dac));
  241. HPM_CHECK_RET(sgtl_enable_module(context, sgtl_module_i2sin));
  242. HPM_CHECK_RET(sgtl_enable_module(context, sgtl_module_i2sout));
  243. HPM_CHECK_RET(sgtl_enable_module(context, sgtl_module_adc));
  244. HPM_CHECK_RET(sgtl_enable_module(context, sgtl_module_dap));
  245. HPM_CHECK_RET(sgtl_modify_reg(context, SGTL5000_DAP_CONTROL, SGTL5000_DAP_CONTROL_DAP_EN_CLR_MASK, 0x0001));
  246. HPM_CHECK_RET(sgtl_modify_reg(context, CHIP_SSS_CTRL, SGTL5000_DAP_SEL_CLR_MASK, SGTL5000_DAP_SEL_I2S_IN));
  247. HPM_CHECK_RET(sgtl_modify_reg(context, CHIP_SSS_CTRL, SGTL5000_DAC_SEL_CLR_MASK, SGTL5000_DAC_SEL_DAP));
  248. HPM_CHECK_RET(sgtl_modify_reg(context, CHIP_ANA_CTRL, SGTL5000_SEL_HP_CLR_MASK, SGTL5000_SEL_HP_DAC));
  249. HPM_CHECK_RET(sgtl_modify_reg(context, CHIP_ANA_CTRL, SGTL5000_SEL_ADC_CLR_MASK, SGTL5000_SEL_ADC_LINEIN));
  250. HPM_CHECK_RET(sgtl_modify_reg(context, CHIP_SSS_CTRL, SGTL5000_I2S_OUT_SEL_CLR_MASK, SGTL5000_I2S_OUT_SEL_ADC));
  251. break;
  252. case sgtl_route_record:
  253. /* LINE_IN->ADC->I2S_OUT */
  254. HPM_CHECK_RET(sgtl_enable_module(context, sgtl_module_i2sout));
  255. HPM_CHECK_RET(sgtl_enable_module(context, sgtl_module_adc));
  256. HPM_CHECK_RET(sgtl_modify_reg(context, CHIP_ANA_CTRL, SGTL5000_SEL_ADC_CLR_MASK, SGTL5000_SEL_ADC_LINEIN));
  257. HPM_CHECK_RET(sgtl_modify_reg(context, CHIP_SSS_CTRL, SGTL5000_I2S_OUT_SEL_CLR_MASK, SGTL5000_I2S_OUT_SEL_ADC));
  258. break;
  259. default:
  260. stat = status_invalid_argument;
  261. break;
  262. }
  263. return stat;
  264. }
  265. hpm_stat_t sgtl_set_protocol(sgtl_context_t *context, sgtl_protocol_t protocol)
  266. {
  267. hpm_stat_t stat = status_success;
  268. switch (protocol) {
  269. case sgtl_bus_i2s:
  270. HPM_CHECK_RET(sgtl_modify_reg(context, CHIP_I2S_CTRL, SGTL5000_I2S_MODE_CLR_MASK, SGTL5000_I2S_MODE_I2S_LJ));
  271. HPM_CHECK_RET(sgtl_modify_reg(context, CHIP_I2S_CTRL, SGTL5000_I2S_LRALIGN_CLR_MASK, SGTL5000_I2S_ONE_BIT_DELAY));
  272. HPM_CHECK_RET(sgtl_modify_reg(context, CHIP_I2S_CTRL, SGTL5000_I2S_SCLK_INV_CLR_MASK, SGTL5000_I2S_VAILD_RISING_EDGE));
  273. break;
  274. case sgtl_bus_left_justified:
  275. HPM_CHECK_RET(sgtl_modify_reg(context, CHIP_I2S_CTRL, SGTL5000_I2S_MODE_CLR_MASK, SGTL5000_I2S_MODE_I2S_LJ));
  276. HPM_CHECK_RET(sgtl_modify_reg(context, CHIP_I2S_CTRL, SGTL5000_I2S_LRALIGN_CLR_MASK, SGTL5000_I2S_NO_DELAY));
  277. HPM_CHECK_RET(sgtl_modify_reg(context, CHIP_I2S_CTRL, SGTL5000_I2S_SCLK_INV_CLR_MASK, SGTL5000_I2S_VAILD_RISING_EDGE));
  278. break;
  279. case sgtl_bus_right_justified:
  280. HPM_CHECK_RET(sgtl_modify_reg(context, CHIP_I2S_CTRL, SGTL5000_I2S_MODE_CLR_MASK, SGTL5000_I2S_MODE_RJ));
  281. HPM_CHECK_RET(sgtl_modify_reg(context, CHIP_I2S_CTRL, SGTL5000_I2S_SCLK_INV_CLR_MASK, SGTL5000_I2S_VAILD_RISING_EDGE));
  282. break;
  283. case sgtl_bus_pcma:
  284. HPM_CHECK_RET(sgtl_modify_reg(context, CHIP_I2S_CTRL, SGTL5000_I2S_MODE_CLR_MASK, SGTL5000_I2S_MODE_PCM));
  285. HPM_CHECK_RET(sgtl_modify_reg(context, CHIP_I2S_CTRL, SGTL5000_I2S_LRALIGN_CLR_MASK, SGTL5000_I2S_ONE_BIT_DELAY));
  286. HPM_CHECK_RET(sgtl_modify_reg(context, CHIP_I2S_CTRL, SGTL5000_I2S_SCLK_INV_CLR_MASK, SGTL5000_I2S_VAILD_FALLING_EDGE));
  287. break;
  288. case sgtl_bus_pcmb:
  289. HPM_CHECK_RET(sgtl_modify_reg(context, CHIP_I2S_CTRL, SGTL5000_I2S_MODE_CLR_MASK, SGTL5000_I2S_MODE_PCM));
  290. HPM_CHECK_RET(sgtl_modify_reg(context, CHIP_I2S_CTRL, SGTL5000_I2S_LRALIGN_CLR_MASK, SGTL5000_I2S_NO_DELAY));
  291. HPM_CHECK_RET(sgtl_modify_reg(context, CHIP_I2S_CTRL, SGTL5000_I2S_SCLK_INV_CLR_MASK, SGTL5000_I2S_VAILD_FALLING_EDGE));
  292. break;
  293. default:
  294. stat = status_invalid_argument;
  295. break;
  296. }
  297. return stat;
  298. }
  299. hpm_stat_t sgtl_set_volume(sgtl_context_t *context, sgtl_module_t module, uint32_t volume)
  300. {
  301. uint16_t vol = 0;
  302. hpm_stat_t stat = status_success;
  303. switch (module) {
  304. case sgtl_module_adc:
  305. if (volume > SGTL5000_ADC_MAX_VOLUME_VALUE) {
  306. return status_invalid_argument;
  307. }
  308. vol = (uint16_t)(volume | (volume << 4U));
  309. stat = sgtl_modify_reg(context, CHIP_ANA_ADC_CTRL,
  310. SGTL5000_ADC_VOL_LEFT_CLR_MASK & SGTL5000_ADC_VOL_RIGHT_CLR_MASK, vol);
  311. break;
  312. case sgtl_module_dac:
  313. if ((volume > SGTL5000_DAC_MAX_VOLUME_VALUE) || (volume < SGTL5000_DAC_MIN_VOLUME_VALUE)) {
  314. return status_invalid_argument;
  315. }
  316. vol = (uint16_t)(volume | (volume << 8U));
  317. stat = sgtl_write_reg(context, CHIP_DAC_VOL, vol);
  318. break;
  319. case sgtl_module_hp:
  320. if (volume > SGTL5000_HEADPHONE_MAX_VOLUME_VALUE) {
  321. return status_invalid_argument;
  322. }
  323. vol = (uint16_t)(volume | (volume << 8U));
  324. stat = sgtl_write_reg(context, CHIP_ANA_HP_CTRL, vol);
  325. break;
  326. case sgtl_module_lineout:
  327. if (volume > SGTL5000_LINE_OUT_MAX_VOLUME_VALUE) {
  328. return status_invalid_argument;
  329. }
  330. vol = (uint16_t)(volume | (volume << 8U));
  331. stat = sgtl_write_reg(context, CHIP_LINE_OUT_VOL, vol);
  332. break;
  333. default:
  334. stat = status_invalid_argument;
  335. break;
  336. }
  337. return stat;
  338. }
  339. uint32_t sgtl_get_volume(sgtl_context_t *context, sgtl_module_t module)
  340. {
  341. uint16_t vol = 0;
  342. hpm_stat_t stat = status_success;
  343. switch (module) {
  344. case sgtl_module_adc:
  345. stat = sgtl_read_reg(context, CHIP_ANA_ADC_CTRL, &vol);
  346. vol = (vol & (uint16_t)SGTL5000_ADC_VOL_LEFT_GET_MASK) >> SGTL5000_ADC_VOL_LEFT_SHIFT;
  347. break;
  348. case sgtl_module_dac:
  349. stat = sgtl_read_reg(context, CHIP_DAC_VOL, &vol);
  350. vol = (vol & (uint16_t)SGTL5000_DAC_VOL_LEFT_GET_MASK) >> SGTL5000_DAC_VOL_LEFT_SHIFT;
  351. break;
  352. case sgtl_module_hp:
  353. stat = sgtl_read_reg(context, CHIP_ANA_HP_CTRL, &vol);
  354. vol = (vol & (uint16_t)SGTL5000_HP_VOL_LEFT_GET_MASK) >> SGTL5000_HP_VOL_LEFT_SHIFT;
  355. break;
  356. case sgtl_module_lineout:
  357. stat = sgtl_read_reg(context, CHIP_LINE_OUT_VOL, &vol);
  358. vol = (vol & (uint16_t)SGTL5000_LINE_OUT_VOL_LEFT_GET_MASK) >> SGTL5000_LINE_OUT_VOL_LEFT_SHIFT;
  359. break;
  360. default:
  361. vol = 0;
  362. break;
  363. }
  364. return stat == status_success ? vol : 0U;
  365. }
  366. hpm_stat_t sgtl_set_mute(sgtl_context_t *context, sgtl_module_t module, bool mute)
  367. {
  368. hpm_stat_t stat = status_success;
  369. switch (module) {
  370. case sgtl_module_adc:
  371. stat = sgtl_modify_reg(context, CHIP_ANA_CTRL, SGTL5000_MUTE_ADC_CLR_MASK, mute ? 1U : 0U);
  372. break;
  373. case sgtl_module_dac:
  374. if (mute) {
  375. stat = sgtl_modify_reg(context, CHIP_ADCDAC_CTRL,
  376. SGTL5000_DAC_MUTE_LEFT_CLR_MASK & SGTL5000_DAC_MUTE_RIGHT_CLR_MASK, 0x000C);
  377. } else {
  378. stat = sgtl_modify_reg(context, CHIP_ADCDAC_CTRL,
  379. SGTL5000_DAC_MUTE_LEFT_CLR_MASK & SGTL5000_DAC_MUTE_RIGHT_CLR_MASK, 0x0000);
  380. }
  381. break;
  382. case sgtl_module_hp:
  383. stat = sgtl_modify_reg(context, CHIP_ANA_CTRL, SGTL5000_MUTE_HP_CLR_MASK,
  384. ((uint16_t)mute << SGTL5000_MUTE_HP_SHIFT));
  385. break;
  386. case sgtl_module_lineout:
  387. stat = sgtl_modify_reg(context, CHIP_ANA_CTRL, SGTL5000_MUTE_LO_CLR_MASK,
  388. ((uint16_t)mute << SGTL5000_MUTE_LO_SHIFT));
  389. break;
  390. default:
  391. stat = status_invalid_argument;
  392. break;
  393. }
  394. return stat;
  395. }
  396. static bool sgtl_check_clock_tolerance(uint32_t source, uint32_t target)
  397. {
  398. uint32_t delta = (source >= target) ? (source - target) : (target - source);
  399. if (delta * 100 <= HPM_SGTL5000_MCLK_TOLERANCE * target) {
  400. return true;
  401. }
  402. return false;
  403. }
  404. hpm_stat_t sgtl_config_data_format(sgtl_context_t *context, uint32_t mclk, uint32_t sample_rate, uint32_t bits)
  405. {
  406. uint16_t val = 0;
  407. uint16_t regVal = 0;
  408. uint32_t mul_div = 0U;
  409. uint32_t sysFs = 0U;
  410. hpm_stat_t stat = status_success;
  411. /* Over sample rate can only up to 512, the least to 8k */
  412. if ((mclk / (MIN(sample_rate * 6U, 96000U)) > 512U) || (mclk / sample_rate < 256U)) {
  413. return status_invalid_argument;
  414. }
  415. /* Configure the sample rate */
  416. switch (sample_rate) {
  417. case 8000:
  418. if (mclk > 32000U * 512U) {
  419. val = 0x0038;
  420. sysFs = 48000;
  421. } else {
  422. val = 0x0020;
  423. sysFs = 32000;
  424. }
  425. break;
  426. case 11025:
  427. val = 0x0024;
  428. sysFs = 44100;
  429. break;
  430. case 12000:
  431. val = 0x0028;
  432. sysFs = 48000;
  433. break;
  434. case 16000:
  435. if (mclk > 32000U * 512U) {
  436. val = 0x003C;
  437. sysFs = 96000;
  438. } else {
  439. val = 0x0010;
  440. sysFs = 32000;
  441. }
  442. break;
  443. case 22050:
  444. val = 0x0014;
  445. sysFs = 44100;
  446. break;
  447. case 24000:
  448. if (mclk > 48000U * 512U) {
  449. val = 0x002C;
  450. sysFs = 96000;
  451. } else {
  452. val = 0x0018;
  453. sysFs = 48000;
  454. }
  455. break;
  456. case 32000:
  457. val = 0x0000;
  458. sysFs = 32000;
  459. break;
  460. case 44100:
  461. val = 0x0004;
  462. sysFs = 44100;
  463. break;
  464. case 48000:
  465. if (mclk > 48000U * 512U) {
  466. val = 0x001C;
  467. sysFs = 96000;
  468. } else {
  469. val = 0x0008;
  470. sysFs = 48000;
  471. }
  472. break;
  473. case 96000:
  474. val = 0x000C;
  475. sysFs = 96000;
  476. break;
  477. default:
  478. stat = status_invalid_argument;
  479. break;
  480. }
  481. if (stat != status_success) {
  482. return stat;
  483. }
  484. if (sgtl_read_reg(context, CHIP_I2S_CTRL, &regVal) != status_success) {
  485. return status_fail;
  486. }
  487. mul_div = mclk / sysFs;
  488. if (sgtl_check_clock_tolerance(mul_div, 256)) {
  489. mul_div = 256;
  490. } else if (sgtl_check_clock_tolerance(mul_div, 384)) {
  491. mul_div = 384;
  492. } else if (sgtl_check_clock_tolerance(mul_div, 512)) {
  493. mul_div = 512;
  494. } else {
  495. return status_invalid_argument;
  496. }
  497. val |= (mul_div / 128U - 2U);
  498. if (sgtl_write_reg(context, CHIP_CLK_CTRL, val) != status_success) {
  499. return status_fail;
  500. }
  501. /* Data bits configure,sgtl supports 16bit, 20bit 24bit, 32bit */
  502. if (sgtl_modify_reg(context, CHIP_I2S_CTRL, 0xFEFF, SGTL5000_I2S_SCLKFREQ_64FS) != status_success) {
  503. return status_fail;
  504. }
  505. switch (bits) {
  506. case 16:
  507. stat = sgtl_modify_reg(context, CHIP_I2S_CTRL, SGTL5000_I2S_DLEN_CLR_MASK, SGTL5000_I2S_DLEN_16);
  508. break;
  509. case 20:
  510. stat = sgtl_modify_reg(context, CHIP_I2S_CTRL, SGTL5000_I2S_DLEN_CLR_MASK, SGTL5000_I2S_DLEN_20);
  511. break;
  512. case 24:
  513. stat = sgtl_modify_reg(context, CHIP_I2S_CTRL, SGTL5000_I2S_DLEN_CLR_MASK, SGTL5000_I2S_DLEN_24);
  514. break;
  515. case 32:
  516. stat = sgtl_modify_reg(context, CHIP_I2S_CTRL, SGTL5000_I2S_DLEN_CLR_MASK, SGTL5000_I2S_DLEN_32);
  517. break;
  518. default:
  519. stat = status_invalid_argument;
  520. break;
  521. }
  522. return stat;
  523. }
  524. hpm_stat_t sgtl_set_pay(sgtl_context_t *context, uint32_t playSource)
  525. {
  526. uint16_t regValue = 0U, regBitMask = 0x40U;
  527. /* headphone source form PGA */
  528. if (playSource == (uint32_t)sgtl_play_source_linein) {
  529. regValue = 0x40U;
  530. } else {
  531. /* headphone source from DAC */
  532. regValue = 0U;
  533. }
  534. return sgtl_modify_reg(context, CHIP_ANA_CTRL, regBitMask, regValue);
  535. }
  536. hpm_stat_t sgtl_set_record(sgtl_context_t *context, uint32_t recordSource)
  537. {
  538. uint16_t regValue = 0U, regBitMask = 0x4U;
  539. /* ADC source form LINEIN */
  540. if (recordSource == (uint32_t)sgtl_record_source_linein) {
  541. regValue = 0x4U;
  542. } else {
  543. /* ADC source from MIC */
  544. regValue = 0U;
  545. }
  546. return sgtl_modify_reg(context, CHIP_ANA_CTRL, regBitMask, regValue);
  547. }
  548. hpm_stat_t sgtl_write_reg(sgtl_context_t *context, uint16_t reg, uint16_t val)
  549. {
  550. uint8_t r[2];
  551. uint8_t d[2];
  552. r[0] = reg >> 8;
  553. r[1] = reg & 0xFF;
  554. d[0] = (uint8_t) (val>>8);
  555. d[1] = (uint8_t) (val & 0xFF);
  556. return i2c_master_address_write(context->ptr, context->slave_address, r, 2U, d, 2U);
  557. }
  558. hpm_stat_t sgtl_read_reg(sgtl_context_t *context, uint16_t reg, uint16_t *val)
  559. {
  560. hpm_stat_t stat = status_success;
  561. uint8_t r[2];
  562. uint8_t d[2];
  563. r[0] = reg >> 8;
  564. r[1] = reg & 0xFF;
  565. stat = i2c_master_address_read(context->ptr, context->slave_address, r, 2U, d, 2U);
  566. *val = (uint16_t)((d[0] << 8) | d[1]);
  567. return stat;
  568. }
  569. hpm_stat_t sgtl_modify_reg(sgtl_context_t *context, uint16_t reg, uint16_t clr_mask, uint16_t val)
  570. {
  571. hpm_stat_t retval = 0;
  572. uint16_t reg_val;
  573. /* Read the register value out */
  574. retval = sgtl_read_reg(context, reg, &reg_val);
  575. if (retval != status_success) {
  576. return status_fail;
  577. }
  578. /* Modify the value */
  579. reg_val &= clr_mask;
  580. reg_val |= val;
  581. /* Write the data to register */
  582. retval = sgtl_write_reg(context, reg, reg_val);
  583. if (retval != status_success) {
  584. return status_fail;
  585. }
  586. return status_success;
  587. }