hpm_sgtl5000.c 26 KB

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