sun8iw18-codec.c 38 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049
  1. /*
  2. * Copyright (c) 2019-2025 Allwinner Technology Co., Ltd. ALL rights reserved.
  3. *
  4. * Allwinner is a trademark of Allwinner Technology Co.,Ltd., registered in
  5. * the the people's Republic of China and other countries.
  6. * All Allwinner Technology Co.,Ltd. trademarks are used with permission.
  7. *
  8. * DISCLAIMER
  9. * THIRD PARTY LICENCES MAY BE REQUIRED TO IMPLEMENT THE SOLUTION/PRODUCT.
  10. * IF YOU NEED TO INTEGRATE THIRD PARTY’S TECHNOLOGY (SONY, DTS, DOLBY, AVS OR MPEGLA, ETC.)
  11. * IN ALLWINNERS’SDK OR PRODUCTS, YOU SHALL BE SOLELY RESPONSIBLE TO OBTAIN
  12. * ALL APPROPRIATELY REQUIRED THIRD PARTY LICENCES.
  13. * ALLWINNER SHALL HAVE NO WARRANTY, INDEMNITY OR OTHER OBLIGATIONS WITH RESPECT TO MATTERS
  14. * COVERED UNDER ANY REQUIRED THIRD PARTY LICENSE.
  15. * YOU ARE SOLELY RESPONSIBLE FOR YOUR USAGE OF THIRD PARTY’S TECHNOLOGY.
  16. *
  17. *
  18. * THIS SOFTWARE IS PROVIDED BY ALLWINNER"AS IS" AND TO THE MAXIMUM EXTENT
  19. * PERMITTED BY LAW, ALLWINNER EXPRESSLY DISCLAIMS ALL WARRANTIES OF ANY KIND,
  20. * WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING WITHOUT LIMITATION REGARDING
  21. * THE TITLE, NON-INFRINGEMENT, ACCURACY, CONDITION, COMPLETENESS, PERFORMANCE
  22. * OR MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  23. * IN NO EVENT SHALL ALLWINNER BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  24. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  25. * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  26. * LOSS OF USE, DATA, OR PROFITS, OR BUSINESS INTERRUPTION)
  27. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  28. * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  29. * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
  30. * OF THE POSSIBILITY OF SUCH DAMAGE.
  31. */
  32. #include <stdio.h>
  33. #include <stdlib.h>
  34. #include <string.h>
  35. #include <sound/snd_core.h>
  36. #include <sound/snd_pcm.h>
  37. #include <sound/pcm_common.h>
  38. #include <aw_common.h>
  39. #include <hal_timer.h>
  40. #include <sound/snd_dma.h>
  41. #include <sound/dma_wrap.h>
  42. #include <hal_dma.h>
  43. #include "sunxi-codec.h"
  44. #include "hal_clk.h"
  45. #include "hal_gpio.h"
  46. #include "sun8iw18-codec.h"
  47. #ifndef ARRAY_SIZE
  48. #define ARRAY_SIZE(x) (sizeof(x)/sizeof((x)[0]))
  49. #endif
  50. #define SUNXI_AUDIOCODEC_REG_DEBUG
  51. #ifdef SUNXI_AUDIOCODEC_REG_DEBUG
  52. struct snd_codec sun8iw18_codec;
  53. #define REG_LABEL(constant) {#constant, constant}
  54. #define REG_LABEL_END {NULL, 0}
  55. struct audiocodec_label {
  56. const char *name;
  57. const unsigned int address;
  58. /*int value;*/
  59. } reg_labels[] = {
  60. REG_LABEL(SUNXI_DAC_DPC),
  61. REG_LABEL(SUNXI_DAC_FIFO_CTL),
  62. REG_LABEL(SUNXI_DAC_FIFO_STA),
  63. REG_LABEL(SUNXI_DAC_CNT),
  64. REG_LABEL(SUNXI_DAC_DG),
  65. REG_LABEL(SUNXI_ADC_FIFO_CTL),
  66. REG_LABEL(SUNXI_ADC_FIFO_STA),
  67. REG_LABEL(SUNXI_ADC_CNT),
  68. REG_LABEL(SUNXI_ADC_DG),
  69. REG_LABEL(SUNXI_DAC_DAP_CTL),
  70. REG_LABEL(SUNXI_ADC_DAP_CTL),
  71. REG_LABEL(SUNXI_HP_CTL),
  72. REG_LABEL(SUNXI_MIX_DAC_CTL),
  73. REG_LABEL(SUNXI_LINEOUT_CTL0),
  74. REG_LABEL(SUNXI_LINEOUT_CTL1),
  75. REG_LABEL(SUNXI_MIC1_CTL),
  76. REG_LABEL(SUNXI_MIC2_MIC3_CTL),
  77. REG_LABEL(SUNXI_LADCMIX_SRC),
  78. REG_LABEL(SUNXI_RADCMIX_SRC),
  79. REG_LABEL(SUNXI_XADCMIX_SRC),
  80. REG_LABEL(SUNXI_ADC_CTL),
  81. REG_LABEL(SUNXI_MBIAS_CTL),
  82. REG_LABEL(SUNXI_APT_REG),
  83. REG_LABEL(SUNXI_OP_BIAS_CTL0),
  84. REG_LABEL(SUNXI_OP_BIAS_CTL1),
  85. REG_LABEL(SUNXI_ZC_VOL_CTL),
  86. REG_LABEL(SUNXI_BIAS_CAL_CTRL),
  87. REG_LABEL_END,
  88. };
  89. void sunxi_audiocodec_reg_dump(void)
  90. {
  91. struct snd_codec *codec = &sun8iw18_codec;
  92. int i = 0;
  93. while (reg_labels[i].name != NULL) {
  94. printf("%-20s[0x%03x]: 0x%-10x\n",
  95. reg_labels[i].name,
  96. reg_labels[i].address,
  97. snd_codec_read(codec, reg_labels[i].address));
  98. i++;
  99. }
  100. return;
  101. }
  102. #else
  103. void sunxi_audiocodec_reg_dump(void)
  104. {
  105. return ;
  106. }
  107. #endif
  108. static int sunxi_spk_gpio_get_data(struct snd_kcontrol *kcontrol,
  109. struct snd_ctl_info *info)
  110. {
  111. struct snd_codec *codec = kcontrol->private_data;
  112. struct sunxi_codec_info *sunxi_codec = codec->private_data;
  113. if (sunxi_codec->param.gpio_spk > 0) {
  114. hal_gpio_get_data(sunxi_codec->param.gpio_spk,
  115. (gpio_data_t *)&info->value);
  116. snd_print("get spk value:%u\n", info->value);
  117. info->id = kcontrol->id;
  118. info->name = kcontrol->name;
  119. info->min = kcontrol->min;
  120. info->max = kcontrol->max;
  121. return 0;
  122. }
  123. return -1;
  124. }
  125. static int sunxi_spk_gpio_set_data(struct snd_kcontrol *kcontrol, unsigned long val)
  126. {
  127. struct snd_codec *codec = kcontrol->private_data;
  128. struct sunxi_codec_info *sunxi_codec = codec->private_data;
  129. if (val != GPIO_DATA_LOW && val != GPIO_DATA_HIGH)
  130. return -1;
  131. if (sunxi_codec->param.gpio_spk > 0) {
  132. hal_gpio_set_direction(sunxi_codec->param.gpio_spk, GPIO_DIRECTION_OUTPUT);
  133. hal_gpio_set_data(sunxi_codec->param.gpio_spk, (gpio_data_t)val);
  134. snd_print("set spk value:%u\n", val);
  135. return 0;
  136. }
  137. return -1;
  138. }
  139. static const char * const codec_format_function[] = {
  140. "hub_disable", "hub_enable"};
  141. static struct snd_kcontrol sunxi_codec_controls[] = {
  142. SND_CTL_KCONTROL("digital volume", SUNXI_DAC_DPC, DVOL, 0x3F),
  143. SND_CTL_KCONTROL("MIC1 gain volume", SUNXI_MIC1_CTL, MIC1BOOST, 0x7),
  144. SND_CTL_KCONTROL("MIC2 gain volume", SUNXI_MIC2_MIC3_CTL, MIC2BOOST, 0x7),
  145. SND_CTL_KCONTROL("MIC3 gain volume", SUNXI_MIC2_MIC3_CTL, MIC3BOOST, 0x7),
  146. SND_CTL_KCONTROL("ADC gain volume", SUNXI_ADC_CTL, ADCG, 0x7),
  147. SND_CTL_KCONTROL("LINEOUT volume", SUNXI_LINEOUT_CTL1, LINEOUT_VOL, 0x1f),
  148. SND_CTL_KCONTROL_EXT("Spk PA Switch", 1, 0,
  149. sunxi_spk_gpio_get_data,
  150. sunxi_spk_gpio_set_data),
  151. SND_CTL_KCONTROL("Left Input Mixer DACL Switch", SUNXI_LADCMIX_SRC, LADC_DACL, 1),
  152. SND_CTL_KCONTROL("Left Input Mixer MIC1 Boost Switch", SUNXI_LADCMIX_SRC, LADC_MIC1_STAGE, 1),
  153. SND_CTL_KCONTROL("Left Input Mixer MIC2 Boost Switch", SUNXI_LADCMIX_SRC, LADC_MIC2_STAGE, 1),
  154. SND_CTL_KCONTROL("Left Input Mixer MIC3 Boost Switch", SUNXI_LADCMIX_SRC, LADC_MIC3_STAGE, 1),
  155. SND_CTL_KCONTROL("Right Input Mixer DACL Switch", SUNXI_RADCMIX_SRC, RADC_DACL, 1),
  156. SND_CTL_KCONTROL("Right Input Mixer MIC1 Boost Switch", SUNXI_RADCMIX_SRC, RADC_MIC1_STAGE, 1),
  157. SND_CTL_KCONTROL("Right Input Mixer MIC2 Boost Switch", SUNXI_RADCMIX_SRC, RADC_MIC2_STAGE, 1),
  158. SND_CTL_KCONTROL("Right Input Mixer MIC3 Boost Switch", SUNXI_RADCMIX_SRC, RADC_MIC3_STAGE, 1),
  159. SND_CTL_KCONTROL("Xadc Input Mixer DACL Switch", SUNXI_XADCMIX_SRC, XADC_DACL, 1),
  160. SND_CTL_KCONTROL("Xadc Input Mixer MIC1 Boost Switch", SUNXI_XADCMIX_SRC, XADC_MIC1_STAGE, 1),
  161. SND_CTL_KCONTROL("Xadc Input Mixer MIC2 Boost Switch", SUNXI_XADCMIX_SRC, XADC_MIC2_STAGE, 1),
  162. SND_CTL_KCONTROL("Xadc Input Mixer MIC3 Boost Switch", SUNXI_XADCMIX_SRC, XADC_MIC3_STAGE, 1),
  163. SND_CTL_KCONTROL("Left LINEOUT Mux", SUNXI_LINEOUT_CTL0, LINEOUTL_SRC, 1),
  164. SND_CTL_KCONTROL("Right LINEOUT Mux", SUNXI_LINEOUT_CTL0, LINEOUTR_SRC, 1),
  165. SND_CTL_ENUM("sunxi codec audio hub mode",
  166. ARRAY_SIZE(codec_format_function), codec_format_function,
  167. SUNXI_DAC_DPC, DAC_HUB_EN),
  168. SND_CTL_KCONTROL_USER("Soft Volume Master", 255, 0, 255),
  169. };
  170. static void adchpf_config(struct snd_codec *codec)
  171. {
  172. snd_codec_write(codec, AC_ADC_DRC_HHPFC, (0xFFFAC1 >> 16) & 0xFFFF);
  173. snd_codec_write(codec, AC_ADC_DRC_LHPFC, 0xFFE644 & 0xFFFF);
  174. }
  175. static void adchpf_enable(struct snd_codec *codec, bool on)
  176. {
  177. if (on) {
  178. snd_codec_update_bits(codec, SUNXI_ADC_DAP_CTL,
  179. (0x1 << ADC_HPF0_EN | 0x1 << ADC_HPF1_EN),
  180. (0x1 << ADC_HPF0_EN | 0x1 << ADC_HPF1_EN));
  181. snd_codec_update_bits(codec, SUNXI_ADC_DAP_CTL,
  182. (0x1 << ADC_DAP0_EN | 0x1 << ADC_DAP1_EN),
  183. (0x1 << ADC_DAP0_EN | 0x1 << ADC_DAP1_EN));
  184. } else {
  185. snd_codec_update_bits(codec, SUNXI_ADC_DAP_CTL,
  186. (0x1 << ADC_HPF0_EN | 0x1 << ADC_HPF1_EN),
  187. (0x0 << ADC_HPF0_EN | 0x0 << ADC_HPF1_EN));
  188. snd_codec_update_bits(codec, SUNXI_ADC_DAP_CTL,
  189. (0x1 << ADC_DAP0_EN | 0x1 << ADC_DAP1_EN),
  190. (0x0 << ADC_DAP0_EN | 0x0 << ADC_DAP1_EN));
  191. }
  192. }
  193. static void adcdrc_config(struct snd_codec *codec)
  194. {
  195. /* Left peak filter attack time */
  196. snd_codec_write(codec, AC_ADC_DRC_LPFHAT, (0x000B77BF >> 16) & 0xFFFF);
  197. snd_codec_write(codec, AC_ADC_DRC_LPFLAT, 0x000B77BF & 0xFFFF);
  198. /* Right peak filter attack time */
  199. snd_codec_write(codec, AC_ADC_DRC_RPFHAT, (0x000B77BF >> 16) & 0xFFFF);
  200. snd_codec_write(codec, AC_ADC_DRC_RPFLAT, 0x000B77BF & 0xFFFF);
  201. /* Left peak filter release time */
  202. snd_codec_write(codec, AC_ADC_DRC_LPFHRT, (0x00FFE1F8 >> 16) & 0xFFFF);
  203. snd_codec_write(codec, AC_ADC_DRC_LPFLRT, 0x00FFE1F8 & 0xFFFF);
  204. /* Right peak filter release time */
  205. snd_codec_write(codec, AC_ADC_DRC_RPFHRT, (0x00FFE1F8 >> 16) & 0xFFFF);
  206. snd_codec_write(codec, AC_ADC_DRC_RPFLRT, 0x00FFE1F8 & 0xFFFF);
  207. /* Left RMS filter attack time */
  208. snd_codec_write(codec, AC_ADC_DRC_LPFHAT, (0x00012BAF >> 16) & 0xFFFF);
  209. snd_codec_write(codec, AC_ADC_DRC_LPFLAT, 0x00012BAF & 0xFFFF);
  210. /* Right RMS filter attack time */
  211. snd_codec_write(codec, AC_ADC_DRC_RPFHAT, (0x00012BAF >> 16) & 0xFFFF);
  212. snd_codec_write(codec, AC_ADC_DRC_RPFLAT, 0x00012BAF & 0xFFFF);
  213. /* smooth filter attack time */
  214. snd_codec_write(codec, AC_ADC_DRC_SFHAT, (0x00025600 >> 16) & 0xFFFF);
  215. snd_codec_write(codec, AC_ADC_DRC_SFLAT, 0x00025600 & 0xFFFF);
  216. /* gain smooth filter release time */
  217. snd_codec_write(codec, AC_ADC_DRC_SFHRT, (0x00000F04 >> 16) & 0xFFFF);
  218. snd_codec_write(codec, AC_ADC_DRC_SFLRT, 0x00000F04 & 0xFFFF);
  219. /* OPL */
  220. snd_codec_write(codec, AC_ADC_DRC_HOPL, (0xFBD8FBA7 >> 16) & 0xFFFF);
  221. snd_codec_write(codec, AC_ADC_DRC_LOPL, 0xFBD8FBA7 & 0xFFFF);
  222. /* OPC */
  223. snd_codec_write(codec, AC_ADC_DRC_HOPC, (0xF95B2C3F >> 16) & 0xFFFF);
  224. snd_codec_write(codec, AC_ADC_DRC_LOPC, 0xF95B2C3F & 0xFFFF);
  225. /* OPE */
  226. snd_codec_write(codec, AC_ADC_DRC_HOPE, (0xF45F8D6E >> 16) & 0xFFFF);
  227. snd_codec_write(codec, AC_ADC_DRC_LOPE, 0xF45F8D6E & 0xFFFF);
  228. /* LT */
  229. snd_codec_write(codec, AC_ADC_DRC_HLT, (0x01A934F0 >> 16) & 0xFFFF);
  230. snd_codec_write(codec, AC_ADC_DRC_LLT, 0x01A934F0 & 0xFFFF);
  231. /* CT */
  232. snd_codec_write(codec, AC_ADC_DRC_HCT, (0x06A4D3C0 >> 16) & 0xFFFF);
  233. snd_codec_write(codec, AC_ADC_DRC_LCT, 0x06A4D3C0 & 0xFFFF);
  234. /* ET */
  235. snd_codec_write(codec, AC_ADC_DRC_HET, (0x0BA07291 >> 16) & 0xFFFF);
  236. snd_codec_write(codec, AC_ADC_DRC_LET, 0x0BA07291 & 0xFFFF);
  237. /* Ki */
  238. snd_codec_write(codec, AC_ADC_DRC_HKI, (0x00051EB8 >> 16) & 0xFFFF);
  239. snd_codec_write(codec, AC_ADC_DRC_LKI, 0x00051EB8 & 0xFFFF);
  240. /* Kc */
  241. snd_codec_write(codec, AC_ADC_DRC_HKC, (0x00800000 >> 16) & 0xFFFF);
  242. snd_codec_write(codec, AC_ADC_DRC_LKC, 0x00800000 & 0xFFFF);
  243. /* Kn */
  244. snd_codec_write(codec, AC_ADC_DRC_HKN, (0x01000000 >> 16) & 0xFFFF);
  245. snd_codec_write(codec, AC_ADC_DRC_LKN, 0x01000000 & 0xFFFF);
  246. /* Ke */
  247. snd_codec_write(codec, AC_ADC_DRC_HKE, (0x0000F45F >> 16) & 0xFFFF);
  248. snd_codec_write(codec, AC_ADC_DRC_LKE, 0x0000F45F & 0xFFFF);
  249. }
  250. static void adcdrc_enable(struct snd_codec *codec, bool on)
  251. {
  252. if (on) {
  253. snd_codec_update_bits(codec, SUNXI_ADC_DAP_CTL,
  254. (0x1 << ADC_DRC0_EN | 0x1 << ADC_DRC1_EN),
  255. (0x1 << ADC_DRC0_EN | 0x1 << ADC_DRC1_EN));
  256. snd_codec_update_bits(codec, SUNXI_ADC_DAP_CTL,
  257. (0x1 << ADC_DAP0_EN | 0x1 << ADC_DAP1_EN),
  258. (0x1 << ADC_DAP0_EN | 0x1 << ADC_DAP1_EN));
  259. } else {
  260. snd_codec_update_bits(codec, SUNXI_ADC_DAP_CTL,
  261. (0x1 << ADC_DAP0_EN | 0x1 << ADC_DAP1_EN),
  262. (0x0 << ADC_DAP0_EN | 0x0 << ADC_DAP1_EN));
  263. snd_codec_update_bits(codec, SUNXI_ADC_DAP_CTL,
  264. (0x1 << ADC_DRC0_EN | 0x1 << ADC_DRC1_EN),
  265. (0x0 << ADC_DRC0_EN | 0x0 << ADC_DRC1_EN));
  266. }
  267. }
  268. static void dachpf_config(struct snd_codec *codec)
  269. {
  270. /* HPF */
  271. snd_codec_write(codec, AC_DAC_DRC_HHPFC, (0xFFFAC1 >> 16) & 0xFFFF);
  272. snd_codec_write(codec, AC_DAC_DRC_LHPFC, 0xFFFAC1 & 0xFFFF);
  273. }
  274. static void dachpf_enable(struct snd_codec *codec, bool on)
  275. {
  276. if (on) {
  277. snd_codec_update_bits(codec, SUNXI_DAC_DAP_CTL,
  278. (0x1 << DDAP_HPF_EN),
  279. (0x1 << DDAP_HPF_EN));
  280. snd_codec_update_bits(codec, SUNXI_DAC_DAP_CTL,
  281. (0x1 << DDAP_EN),
  282. (0x1 << DDAP_EN));
  283. } else {
  284. snd_codec_update_bits(codec, SUNXI_DAC_DAP_CTL,
  285. (0x1 << DDAP_EN),
  286. (0x0 << DDAP_EN));
  287. snd_codec_update_bits(codec, SUNXI_DAC_DAP_CTL,
  288. (0x1 << DDAP_HPF_EN),
  289. (0x0 << DDAP_HPF_EN));
  290. }
  291. }
  292. static void dacdrc_config(struct snd_codec *codec)
  293. {
  294. /* Left peak filter attack time */
  295. snd_codec_write(codec, AC_DAC_DRC_LPFHAT, (0x000B77BF >> 16) & 0xFFFF);
  296. snd_codec_write(codec, AC_DAC_DRC_LPFLAT, 0x000B77BF & 0xFFFF);
  297. /* Right peak filter attack time */
  298. snd_codec_write(codec, AC_DAC_DRC_RPFHAT, (0x000B77BF >> 16) & 0xFFFF);
  299. snd_codec_write(codec, AC_DAC_DRC_RPFLAT, 0x000B77BF & 0xFFFF);
  300. /* Left peak filter release time */
  301. snd_codec_write(codec, AC_DAC_DRC_LPFHRT, (0x00FFE1F8 >> 16) & 0xFFFF);
  302. snd_codec_write(codec, AC_DAC_DRC_LPFLRT, 0x00FFE1F8 & 0xFFFF);
  303. /* Right peak filter release time */
  304. snd_codec_write(codec, AC_DAC_DRC_RPFHRT, (0x00FFE1F8 >> 16) & 0xFFFF);
  305. snd_codec_write(codec, AC_DAC_DRC_RPFLRT, 0x00FFE1F8 & 0xFFFF);
  306. /* Left RMS filter attack time */
  307. snd_codec_write(codec, AC_DAC_DRC_LPFHAT, (0x00012BAF >> 16) & 0xFFFF);
  308. snd_codec_write(codec, AC_DAC_DRC_LPFLAT, 0x00012BAF & 0xFFFF);
  309. /* Right RMS filter attack time */
  310. snd_codec_write(codec, AC_DAC_DRC_RPFHAT, (0x00012BAF >> 16) & 0xFFFF);
  311. snd_codec_write(codec, AC_DAC_DRC_RPFLAT, 0x00012BAF & 0xFFFF);
  312. /* smooth filter attack time */
  313. snd_codec_write(codec, AC_DAC_DRC_SFHAT, (0x00025600 >> 16) & 0xFFFF);
  314. snd_codec_write(codec, AC_DAC_DRC_SFLAT, 0x00025600 & 0xFFFF);
  315. /* gain smooth filter release time */
  316. snd_codec_write(codec, AC_DAC_DRC_SFHRT, (0x00000F04 >> 16) & 0xFFFF);
  317. snd_codec_write(codec, AC_DAC_DRC_SFLRT, 0x00000F04 & 0xFFFF);
  318. /* OPL */
  319. snd_codec_write(codec, AC_DAC_DRC_HOPL, (0xFBD8FBA7 >> 16) & 0xFFFF);
  320. snd_codec_write(codec, AC_DAC_DRC_LOPL, 0xFBD8FBA7 & 0xFFFF);
  321. /* OPC */
  322. snd_codec_write(codec, AC_DAC_DRC_HOPC, (0xF95B2C3F >> 16) & 0xFFFF);
  323. snd_codec_write(codec, AC_DAC_DRC_LOPC, 0xF95B2C3F & 0xFFFF);
  324. /* OPE */
  325. snd_codec_write(codec, AC_DAC_DRC_HOPE, (0xF45F8D6E >> 16) & 0xFFFF);
  326. snd_codec_write(codec, AC_DAC_DRC_LOPE, 0xF45F8D6E & 0xFFFF);
  327. /* LT */
  328. snd_codec_write(codec, AC_DAC_DRC_HLT, (0x01A934F0 >> 16) & 0xFFFF);
  329. snd_codec_write(codec, AC_DAC_DRC_LLT, 0x01A934F0 & 0xFFFF);
  330. /* CT */
  331. snd_codec_write(codec, AC_DAC_DRC_HCT, (0x06A4D3C0 >> 16) & 0xFFFF);
  332. snd_codec_write(codec, AC_DAC_DRC_LCT, 0x06A4D3C0 & 0xFFFF);
  333. /* ET */
  334. snd_codec_write(codec, AC_DAC_DRC_HET, (0x0BA07291 >> 16) & 0xFFFF);
  335. snd_codec_write(codec, AC_DAC_DRC_LET, 0x0BA07291 & 0xFFFF);
  336. /* Ki */
  337. snd_codec_write(codec, AC_DAC_DRC_HKI, (0x00051EB8 >> 16) & 0xFFFF);
  338. snd_codec_write(codec, AC_DAC_DRC_LKI, 0x00051EB8 & 0xFFFF);
  339. /* Kc */
  340. snd_codec_write(codec, AC_DAC_DRC_HKC, (0x00800000 >> 16) & 0xFFFF);
  341. snd_codec_write(codec, AC_DAC_DRC_LKC, 0x00800000 & 0xFFFF);
  342. /* Kn */
  343. snd_codec_write(codec, AC_DAC_DRC_HKN, (0x01000000 >> 16) & 0xFFFF);
  344. snd_codec_write(codec, AC_DAC_DRC_LKN, 0x01000000 & 0xFFFF);
  345. /* Ke */
  346. snd_codec_write(codec, AC_DAC_DRC_HKE, (0x0000F45F >> 16) & 0xFFFF);
  347. snd_codec_write(codec, AC_DAC_DRC_LKE, 0x0000F45F & 0xFFFF);
  348. }
  349. static void dacdrc_enable(struct snd_codec *codec, bool on)
  350. {
  351. if (on) {
  352. /* detect noise when ET enable */
  353. snd_codec_update_bits(codec, AC_DAC_DRC_CTL,
  354. (0x1 << DAC_DRC_CTL_CONTROL_DRC_EN),
  355. (0x1 << DAC_DRC_CTL_CONTROL_DRC_EN));
  356. /* 0x0:RMS filter; 0x1:Peak filter */
  357. snd_codec_update_bits(codec, AC_DAC_DRC_CTL,
  358. (0x1 << DAC_DRC_CTL_SIGNAL_FUN_SEL),
  359. (0x1 << DAC_DRC_CTL_SIGNAL_FUN_SEL));
  360. /* delay function enable */
  361. snd_codec_update_bits(codec, AC_DAC_DRC_CTL,
  362. (0x1 << DAC_DRC_CTL_DEL_FUN_EN),
  363. (0x0 << DAC_DRC_CTL_DEL_FUN_EN));
  364. snd_codec_update_bits(codec, AC_DAC_DRC_CTL,
  365. (0x1 << DAC_DRC_CTL_DRC_LT_EN),
  366. (0x1 << DAC_DRC_CTL_DRC_LT_EN));
  367. snd_codec_update_bits(codec, AC_DAC_DRC_CTL,
  368. (0x1 << DAC_DRC_CTL_DRC_ET_EN),
  369. (0x1 << DAC_DRC_CTL_DRC_ET_EN));
  370. snd_codec_update_bits(codec, SUNXI_DAC_DAP_CTL,
  371. (0x1 << DDAP_DRC_EN),
  372. (0x1 << DDAP_DRC_EN));
  373. snd_codec_update_bits(codec, SUNXI_DAC_DAP_CTL,
  374. (0x1 << DDAP_EN),
  375. (0x1 << DDAP_EN));
  376. } else {
  377. snd_codec_update_bits(codec, SUNXI_DAC_DAP_CTL,
  378. (0x1 << DDAP_EN),
  379. (0x0 << DDAP_EN));
  380. snd_codec_update_bits(codec, SUNXI_DAC_DAP_CTL,
  381. (0x1 << DDAP_DRC_EN),
  382. (0x0 << DDAP_DRC_EN));
  383. /* detect noise when ET enable */
  384. snd_codec_update_bits(codec, AC_DAC_DRC_CTL,
  385. (0x1 << DAC_DRC_CTL_CONTROL_DRC_EN),
  386. (0x0 << DAC_DRC_CTL_CONTROL_DRC_EN));
  387. /* 0x0:RMS filter; 0x1:Peak filter */
  388. snd_codec_update_bits(codec, AC_DAC_DRC_CTL,
  389. (0x1 << DAC_DRC_CTL_SIGNAL_FUN_SEL),
  390. (0x1 << DAC_DRC_CTL_SIGNAL_FUN_SEL));
  391. /* delay function enable */
  392. snd_codec_update_bits(codec, AC_DAC_DRC_CTL,
  393. (0x1 << DAC_DRC_CTL_DEL_FUN_EN),
  394. (0x0 << DAC_DRC_CTL_DEL_FUN_EN));
  395. snd_codec_update_bits(codec, AC_DAC_DRC_CTL,
  396. (0x1 << DAC_DRC_CTL_DRC_LT_EN),
  397. (0x0 << DAC_DRC_CTL_DRC_LT_EN));
  398. snd_codec_update_bits(codec, AC_DAC_DRC_CTL,
  399. (0x1 << DAC_DRC_CTL_DRC_ET_EN),
  400. (0x0 << DAC_DRC_CTL_DRC_ET_EN));
  401. }
  402. }
  403. static int sunxi_codec_init(struct snd_codec *codec)
  404. {
  405. struct sunxi_codec_info *sunxi_codec = codec->private_data;
  406. struct sunxi_codec_param *param = &sunxi_codec->param;
  407. /* Disable DRC function for playback */
  408. snd_codec_write(codec, SUNXI_DAC_DAP_CTL, 0);
  409. /* Disable HPF(high passed filter) */
  410. snd_codec_update_bits(codec, SUNXI_DAC_DPC,
  411. (1 << HPF_EN), (0x0 << HPF_EN));
  412. /* Enable ADCFDT to overcome niose at the beginning */
  413. snd_codec_update_bits(codec, SUNXI_ADC_FIFO_CTL,
  414. (7 << ADCDFEN), (7 << ADCDFEN));
  415. /* set digital volume */
  416. snd_codec_update_bits(codec, SUNXI_DAC_DPC,
  417. (0x3f << DVOL), (param->digital_vol << DVOL));
  418. /* set LINEOUT volume */
  419. snd_codec_update_bits(codec, SUNXI_LINEOUT_CTL1,
  420. (0x1f << LINEOUT_VOL),
  421. (param->lineout_vol << LINEOUT_VOL));
  422. /* set MIC2,3 Boost AMP disable */
  423. snd_codec_write(codec, SUNXI_MIC2_MIC3_CTL, 0x44);
  424. /* set LADC Mixer mute */
  425. snd_codec_write(codec, SUNXI_LADCMIX_SRC, 0x0);
  426. /* MIC1 AMP gain */
  427. snd_codec_update_bits(codec, SUNXI_MIC1_CTL,
  428. 0x7 << MIC1BOOST,
  429. param->mic1gain << MIC1BOOST);
  430. /* MIC2,MIC3 AMP gain */
  431. snd_codec_update_bits(codec, SUNXI_MIC2_MIC3_CTL,
  432. 0x7 << MIC2BOOST,
  433. param->mic2gain << MIC2BOOST);
  434. snd_codec_update_bits(codec, SUNXI_MIC2_MIC3_CTL,
  435. 0x7 << MIC3BOOST,
  436. param->mic3gain << MIC3BOOST);
  437. /* adc gain */
  438. snd_codec_update_bits(codec, SUNXI_ADC_CTL,
  439. 0x1f << ADCG,
  440. param->adcgain << ADCG);
  441. /* LINEOUT Mux */
  442. snd_codec_update_bits(codec, SUNXI_LINEOUT_CTL0,
  443. (0x1<<LINEOUTL_SRC), (0x0<<LINEOUTL_SRC));
  444. snd_codec_update_bits(codec, SUNXI_LINEOUT_CTL0,
  445. (0x1<<LINEOUTR_SRC), (0x1<<LINEOUTR_SRC));
  446. /* Left Input Mixer */
  447. snd_codec_update_bits(codec, SUNXI_LADCMIX_SRC,
  448. (0x1<<LADC_MIC1_STAGE), (0x1<<LADC_MIC1_STAGE));
  449. /* Right Input Mixer */
  450. snd_codec_update_bits(codec, SUNXI_RADCMIX_SRC,
  451. (0x1<<RADC_MIC2_STAGE), (0x1<<RADC_MIC2_STAGE));
  452. /* X Input Mixer */
  453. snd_codec_update_bits(codec, SUNXI_XADCMIX_SRC,
  454. (0x1<<XADC_MIC3_STAGE), (0x1<<XADC_MIC3_STAGE));
  455. if (param->adcdrc_cfg) {
  456. adcdrc_config(codec);
  457. adcdrc_enable(codec, 1);
  458. }
  459. if (param->adchpf_cfg) {
  460. adchpf_config(codec);
  461. adchpf_enable(codec, 1);
  462. }
  463. if (param->dacdrc_cfg) {
  464. dacdrc_config(codec);
  465. dacdrc_enable(codec, 1);
  466. }
  467. if (param->dachpf_cfg) {
  468. dachpf_config(codec);
  469. dachpf_enable(codec, 1);
  470. }
  471. return 0;
  472. }
  473. static int sun8iw18_codec_probe(struct snd_codec *codec)
  474. {
  475. struct sunxi_codec_info *sunxi_codec = NULL;
  476. struct sunxi_codec_param default_param = {
  477. .digital_vol = 0x0,
  478. .lineout_vol = 0x0a,
  479. .mic1gain = 0x4,
  480. .mic2gain = 0x4,
  481. .mic3gain = 0x0,
  482. .adcgain = 0x3,
  483. .gpio_spk = GPIOH(9),
  484. .gpio_spk_power = GPIOH(2),
  485. .pa_msleep_time = 50,
  486. .adcdrc_cfg = 0,
  487. .adchpf_cfg = 1,
  488. .dacdrc_cfg = 0,
  489. .dachpf_cfg = 0,
  490. };
  491. if (!codec->codec_dai)
  492. return -1;
  493. sunxi_codec = snd_malloc(sizeof(struct sunxi_codec_info));
  494. if (!sunxi_codec) {
  495. snd_err("no memory\n");
  496. return -ENOMEM;
  497. }
  498. codec->private_data = (void *)sunxi_codec;
  499. snd_print("codec para init\n");
  500. /* get codec para from board config? */
  501. sunxi_codec->param = default_param;
  502. codec->codec_base_addr = (void *)SUNXI_CODEC_BASE_ADDR;
  503. codec->codec_dai->component = codec;
  504. sunxi_codec->pllclk = HAL_CLK_PLL_AUDIO;
  505. sunxi_codec->pllclkx4 = HAL_CLK_PLL_AUDIOX4;
  506. sunxi_codec->moduleclk = HAL_CLK_PERIPH_AUDIOCODEC_1X;
  507. hal_clk_set_parent(sunxi_codec->moduleclk, sunxi_codec->pllclkx4);
  508. hal_clock_enable(sunxi_codec->pllclk);
  509. hal_clock_enable(sunxi_codec->pllclkx4);
  510. hal_clock_enable(sunxi_codec->moduleclk);
  511. sunxi_codec_init(codec);
  512. return 0;
  513. }
  514. static int sun8iw18_codec_remove(struct snd_codec *codec)
  515. {
  516. struct sunxi_codec_info *sunxi_codec = codec->private_data;
  517. struct sunxi_codec_param *param = &sunxi_codec->param;
  518. if (param->adcdrc_cfg)
  519. adcdrc_enable(codec, 0);
  520. if (param->adchpf_cfg)
  521. adchpf_enable(codec, 0);
  522. if (param->dacdrc_cfg)
  523. dacdrc_enable(codec, 0);
  524. if (param->dachpf_cfg)
  525. dachpf_enable(codec, 0);
  526. hal_clock_disable(sunxi_codec->moduleclk);
  527. hal_clock_disable(sunxi_codec->pllclkx4);
  528. hal_clock_disable(sunxi_codec->pllclk);
  529. snd_free(sunxi_codec);
  530. codec->private_data = NULL;
  531. return 0;
  532. }
  533. static const struct sample_rate sample_rate_conv[] = {
  534. {44100, 0},
  535. {48000, 0},
  536. {8000, 5},
  537. {32000, 1},
  538. {22050, 2},
  539. {24000, 2},
  540. {16000, 3},
  541. {11025, 4},
  542. {12000, 4},
  543. {192000, 6},
  544. {96000, 7},
  545. };
  546. static int sunxi_codec_hw_params(struct snd_pcm_substream *substream,
  547. struct snd_pcm_hw_params *params, struct snd_dai *dai)
  548. {
  549. struct snd_codec *codec = dai->component;
  550. int i = 0;
  551. snd_print("\n");
  552. switch (params_format(params)) {
  553. case SND_PCM_FORMAT_S16_LE:
  554. if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
  555. snd_codec_update_bits(codec, SUNXI_DAC_FIFO_CTL,
  556. (3<<FIFO_MODE), (3<<FIFO_MODE));
  557. snd_codec_update_bits(codec, SUNXI_DAC_FIFO_CTL,
  558. (1<<TX_SAMPLE_BITS), (0<<TX_SAMPLE_BITS));
  559. } else {
  560. snd_codec_update_bits(codec, SUNXI_ADC_FIFO_CTL,
  561. (1<<RX_FIFO_MODE), (1<<RX_FIFO_MODE));
  562. snd_codec_update_bits(codec, SUNXI_ADC_FIFO_CTL,
  563. (1<<RX_SAMPLE_BITS), (0<<RX_SAMPLE_BITS));
  564. }
  565. break;
  566. case SND_PCM_FORMAT_S32_LE:
  567. /* only for the compatible of tinyalsa */
  568. case SND_PCM_FORMAT_S24_LE:
  569. if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
  570. snd_codec_update_bits(codec, SUNXI_DAC_FIFO_CTL,
  571. (3<<FIFO_MODE), (0<<FIFO_MODE));
  572. snd_codec_update_bits(codec, SUNXI_DAC_FIFO_CTL,
  573. (1<<TX_SAMPLE_BITS), (1<<TX_SAMPLE_BITS));
  574. } else {
  575. snd_codec_update_bits(codec, SUNXI_ADC_FIFO_CTL,
  576. (1<<RX_FIFO_MODE), (0<<RX_FIFO_MODE));
  577. snd_codec_update_bits(codec, SUNXI_ADC_FIFO_CTL,
  578. (1<<RX_SAMPLE_BITS), (1<<RX_SAMPLE_BITS));
  579. }
  580. break;
  581. default:
  582. snd_err("params_format[%d] error!\n", params_format(params));
  583. return -EINVAL;
  584. }
  585. for (i = 0; i < ARRAY_SIZE(sample_rate_conv); i++) {
  586. if (sample_rate_conv[i].samplerate == params_rate(params)) {
  587. if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
  588. snd_codec_update_bits(codec, SUNXI_DAC_FIFO_CTL,
  589. (0x7<<DAC_FS),
  590. (sample_rate_conv[i].rate_bit<<DAC_FS));
  591. } else {
  592. if (sample_rate_conv[i].samplerate > 48000)
  593. return -EINVAL;
  594. snd_codec_update_bits(codec, SUNXI_ADC_FIFO_CTL,
  595. (0x7<<ADC_FS),
  596. (sample_rate_conv[i].rate_bit<<ADC_FS));
  597. }
  598. }
  599. }
  600. if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
  601. switch (params_channels(params)) {
  602. case 1:
  603. snd_codec_update_bits(codec, SUNXI_DAC_FIFO_CTL,
  604. (1<<DAC_MONO_EN), 1<<DAC_MONO_EN);
  605. break;
  606. case 2:
  607. snd_codec_update_bits(codec, SUNXI_DAC_FIFO_CTL,
  608. (1<<DAC_MONO_EN), (0<<DAC_MONO_EN));
  609. break;
  610. default:
  611. snd_err("cannot support the channels:%u.\n",
  612. params_channels(params));
  613. return -EINVAL;
  614. }
  615. } else {
  616. switch (params_channels(params)) {
  617. case 1:
  618. snd_codec_update_bits(codec, SUNXI_ADC_FIFO_CTL,
  619. (0xf<<ADC_CHAN_SEL), (1<<ADC_CHAN_SEL));
  620. break;
  621. case 2:
  622. snd_codec_update_bits(codec, SUNXI_ADC_FIFO_CTL,
  623. (0xf<<ADC_CHAN_SEL), (3<<ADC_CHAN_SEL));
  624. break;
  625. case 3:
  626. snd_codec_update_bits(codec, SUNXI_ADC_FIFO_CTL,
  627. (0xf<<ADC_CHAN_SEL), (7<<ADC_CHAN_SEL));
  628. break;
  629. case 4:
  630. snd_codec_update_bits(codec, SUNXI_ADC_FIFO_CTL,
  631. (0xf<<ADC_CHAN_SEL), (0xf<<ADC_CHAN_SEL));
  632. break;
  633. default:
  634. snd_err("cannot support the channels:%u.\n",
  635. params_channels(params));
  636. return -EINVAL;
  637. }
  638. }
  639. return 0;
  640. }
  641. static void sunxi_codec_shutdown(struct snd_pcm_substream *substream,
  642. struct snd_dai *dai)
  643. {
  644. return;
  645. }
  646. static int sunxi_codec_dapm_control(struct snd_pcm_substream *substream,
  647. struct snd_dai *dai, int onoff)
  648. {
  649. struct snd_codec *codec = dai->component;
  650. struct sunxi_codec_info *sunxi_codec = codec->private_data;
  651. struct sunxi_codec_param *param = &sunxi_codec->param;
  652. if (substream->dapm_state == onoff)
  653. return 0;
  654. if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
  655. /*
  656. * Playback:
  657. * Playback --> DACL --> Left LINEOUT Mux --> LINEOUTL --> External Speaker
  658. *
  659. */
  660. if (onoff) {
  661. /* Playback on */
  662. /* analog DAC enable */
  663. snd_codec_update_bits(codec, SUNXI_MIX_DAC_CTL,
  664. (0x1<<DACALEN), (0x1<<DACALEN));
  665. /* digital DAC enable */
  666. snd_codec_update_bits(codec, SUNXI_DAC_DPC,
  667. (0x1<<EN_DAC), (0x1<<EN_DAC));
  668. /* delay 10ms to avoid digitabl DAC square wave */
  669. hal_msleep(10);
  670. /* LINEOUT */
  671. snd_codec_update_bits(codec, SUNXI_LINEOUT_CTL0,
  672. (0x1<<LINEOUTL_EN), (0x1<<LINEOUTL_EN));
  673. snd_codec_update_bits(codec, SUNXI_LINEOUT_CTL0,
  674. (0x1<<LINEOUTR_EN), (0x1<<LINEOUTR_EN));
  675. if (param->gpio_spk > 0) {
  676. hal_gpio_set_direction(param->gpio_spk,
  677. GPIO_DIRECTION_OUTPUT);
  678. hal_gpio_set_data(param->gpio_spk,
  679. GPIO_DATA_HIGH);
  680. }
  681. if (param->gpio_spk_power > 0) {
  682. hal_gpio_set_direction(param->gpio_spk_power,
  683. GPIO_DIRECTION_OUTPUT);
  684. hal_gpio_set_data(param->gpio_spk_power,
  685. GPIO_DATA_HIGH);
  686. }
  687. /* delay to wait PA stable */
  688. hal_msleep(param->pa_msleep_time);
  689. } else {
  690. /* Playback off */
  691. if (param->gpio_spk > 0) {
  692. hal_gpio_set_direction(param->gpio_spk,
  693. GPIO_DIRECTION_OUTPUT);
  694. hal_gpio_set_data(param->gpio_spk,
  695. GPIO_DATA_LOW);
  696. }
  697. if (param->gpio_spk_power > 0) {
  698. hal_gpio_set_direction(param->gpio_spk_power,
  699. GPIO_DIRECTION_OUTPUT);
  700. hal_gpio_set_data(param->gpio_spk_power,
  701. GPIO_DATA_LOW);
  702. }
  703. hal_msleep(param->pa_msleep_time);
  704. /* LINEOUT */
  705. snd_codec_update_bits(codec, SUNXI_LINEOUT_CTL0,
  706. (0x1<<LINEOUTL_EN), (0x0<<LINEOUTL_EN));
  707. snd_codec_update_bits(codec, SUNXI_LINEOUT_CTL0,
  708. (0x1<<LINEOUTR_EN), (0x0<<LINEOUTR_EN));
  709. /* digital DAC */
  710. snd_codec_update_bits(codec, SUNXI_DAC_DPC,
  711. (0x1<<EN_DAC), (0x0<<EN_DAC));
  712. /* analog DAC */
  713. snd_codec_update_bits(codec, SUNXI_MIX_DAC_CTL,
  714. (0x1<<DACALEN), (0x0<<DACALEN));
  715. }
  716. } else {
  717. /*
  718. * Capture:
  719. * Capture <-- ADCL <-- Left Input Mixer <-- MIC1 PGA <-- MIC1 <-- MainMic Bias
  720. * Capture <-- ADCR <-- Right Input Mixer <-- MIC2 PGA <-- MIC2 <-- MainMic Bias
  721. * Capture <-- ADCX <-- Xadc Input Mixer <-- MIC3 PGA <-- MIC3 <-- MainMic Bias
  722. *
  723. */
  724. unsigned int channels = 0;
  725. channels = substream->runtime->channels;
  726. snd_print("channels = %u\n", channels);
  727. if (onoff) {
  728. /* Capture on */
  729. /* digital ADC enable */
  730. #ifndef CONFIG_SND_MULTI_SOUNDCARD
  731. snd_codec_update_bits(codec, SUNXI_ADC_FIFO_CTL,
  732. (0x1<<EN_AD), (0x1<<EN_AD));
  733. #endif
  734. switch (channels) {
  735. case 4:
  736. case 3:
  737. /* analog ADCX enable */
  738. snd_codec_update_bits(codec, SUNXI_ADC_CTL,
  739. (0x1<<ADCXEN), (0x1<<ADCXEN));
  740. case 2:
  741. /* analog ADCR enable */
  742. snd_codec_update_bits(codec, SUNXI_ADC_CTL,
  743. (0x1<<ADCREN), (0x1<<ADCREN));
  744. case 1:
  745. /* analog ADCL enable */
  746. snd_codec_update_bits(codec, SUNXI_ADC_CTL,
  747. (0x1<<ADCLEN), (0x1<<ADCLEN));
  748. break;
  749. default:
  750. snd_err("unknown channels:%u\n", channels);
  751. return -1;
  752. }
  753. switch (channels) {
  754. case 4:
  755. case 3:
  756. /* MIC3 PGA */
  757. snd_codec_update_bits(codec, SUNXI_MIC2_MIC3_CTL,
  758. (0x1<<MIC3AMPEN), (0x1<<MIC3AMPEN));
  759. case 2:
  760. /* MIC2 PGA */
  761. snd_codec_update_bits(codec, SUNXI_MIC2_MIC3_CTL,
  762. (0x1<<MIC2AMPEN), (0x1<<MIC2AMPEN));
  763. case 1:
  764. /* MIC1 PGA */
  765. snd_codec_update_bits(codec, SUNXI_MIC1_CTL,
  766. (0x1<<MIC1AMPEN), (0x1<<MIC1AMPEN));
  767. break;
  768. default:
  769. snd_err("unknown channels:%u\n", channels);
  770. return -1;
  771. }
  772. /* MainMic Bias */
  773. snd_codec_update_bits(codec, SUNXI_MBIAS_CTL,
  774. (0x1<<MMICBIASEN), (0x1<<MMICBIASEN));
  775. } else {
  776. /* Capture off */
  777. /* MainMic Bias */
  778. snd_codec_update_bits(codec, SUNXI_MBIAS_CTL,
  779. (0x1<<MMICBIASEN), (0x0<<MMICBIASEN));
  780. switch (channels) {
  781. case 4:
  782. case 3:
  783. /* MIC3 PGA */
  784. snd_codec_update_bits(codec, SUNXI_MIC2_MIC3_CTL,
  785. (0x1<<MIC3AMPEN), (0x0<<MIC3AMPEN));
  786. case 2:
  787. /* MIC2 PGA */
  788. snd_codec_update_bits(codec, SUNXI_MIC2_MIC3_CTL,
  789. (0x1<<MIC2AMPEN), (0x0<<MIC2AMPEN));
  790. case 1:
  791. /* MIC1 PGA */
  792. snd_codec_update_bits(codec, SUNXI_MIC1_CTL,
  793. (0x1<<MIC1AMPEN), (0x0<<MIC1AMPEN));
  794. break;
  795. default:
  796. snd_err("unknown channels:%u\n", channels);
  797. return -1;
  798. }
  799. switch (channels) {
  800. case 4:
  801. case 3:
  802. /* analog ADCX enable */
  803. snd_codec_update_bits(codec, SUNXI_ADC_CTL,
  804. (0x1<<ADCXEN), (0x0<<ADCXEN));
  805. case 2:
  806. /* analog ADCR enable */
  807. snd_codec_update_bits(codec, SUNXI_ADC_CTL,
  808. (0x1<<ADCREN), (0x0<<ADCREN));
  809. case 1:
  810. /* analog ADCL enable */
  811. snd_codec_update_bits(codec, SUNXI_ADC_CTL,
  812. (0x1<<ADCLEN), (0x0<<ADCLEN));
  813. break;
  814. default:
  815. snd_err("unknown channels:%u\n", channels);
  816. return -1;
  817. }
  818. #ifndef CONFIG_SND_MULTI_SOUNDCARD
  819. /* digital ADC enable */
  820. snd_codec_update_bits(codec, SUNXI_ADC_FIFO_CTL,
  821. (0x1<<EN_AD), (0x0<<EN_AD));
  822. #endif
  823. }
  824. }
  825. substream->dapm_state = onoff;
  826. return 0;
  827. }
  828. static int sunxi_codec_startup(struct snd_pcm_substream *substream,
  829. struct snd_dai *dai)
  830. {
  831. snd_print("\n");
  832. return 0;
  833. }
  834. static int sunxi_codec_trigger(struct snd_pcm_substream *substream,
  835. int cmd, struct snd_dai *dai)
  836. {
  837. struct snd_codec *codec = dai->component;
  838. snd_print("cmd=%d\n", cmd);
  839. switch (cmd) {
  840. case SNDRV_PCM_TRIGGER_START:
  841. case SNDRV_PCM_TRIGGER_RESUME:
  842. case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
  843. if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
  844. snd_codec_update_bits(codec,
  845. SUNXI_DAC_FIFO_CTL,
  846. (1<<DAC_DRQ_EN), (1<<DAC_DRQ_EN));
  847. else {
  848. #ifndef CONFIG_SND_MULTI_SOUNDCARD
  849. snd_codec_update_bits(codec,
  850. SUNXI_ADC_FIFO_CTL,
  851. (1 << ADC_DRQ_EN), (1 << ADC_DRQ_EN));
  852. #endif
  853. }
  854. break;
  855. case SNDRV_PCM_TRIGGER_STOP:
  856. case SNDRV_PCM_TRIGGER_SUSPEND:
  857. case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
  858. if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
  859. snd_codec_update_bits(codec,
  860. SUNXI_DAC_FIFO_CTL,
  861. (1 << DAC_DRQ_EN), (0 << DAC_DRQ_EN));
  862. else {
  863. #ifndef CONFIG_SND_MULTI_SOUNDCARD
  864. snd_codec_update_bits(codec,
  865. SUNXI_ADC_FIFO_CTL,
  866. (1 << ADC_DRQ_EN), (0 << ADC_DRQ_EN));
  867. #endif
  868. }
  869. break;
  870. default:
  871. return -EINVAL;
  872. }
  873. return 0;
  874. }
  875. static int sunxi_codec_prepare(struct snd_pcm_substream *substream,
  876. struct snd_dai *dai)
  877. {
  878. struct snd_codec *codec = dai->component;
  879. snd_print("\n");
  880. if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
  881. snd_codec_update_bits(codec, SUNXI_DAC_FIFO_CTL,
  882. (1<<FIFO_FLUSH), (1<<FIFO_FLUSH));
  883. snd_codec_write(codec, SUNXI_DAC_FIFO_STA,
  884. (1 << DAC_TXE_INT | 1 << DAC_TXU_INT | 1 << DAC_TXO_INT));
  885. snd_codec_write(codec, SUNXI_DAC_CNT, 0);
  886. } else {
  887. snd_codec_update_bits(codec, SUNXI_ADC_FIFO_CTL,
  888. (1<<ADC_FIFO_FLUSH), (1<<ADC_FIFO_FLUSH));
  889. snd_codec_write(codec, SUNXI_ADC_FIFO_STA,
  890. (1 << ADC_RXA_INT | 1 << ADC_RXO_INT));
  891. snd_codec_write(codec, SUNXI_ADC_CNT, 0);
  892. }
  893. return 0;
  894. }
  895. static int sunxi_codec_set_sysclk(struct snd_dai *dai,
  896. int clk_id, unsigned int freq, int dir)
  897. {
  898. struct snd_codec *codec = dai->component;
  899. struct sunxi_codec_info *sunxi_codec = codec->private_data;
  900. snd_print("\n");
  901. if (hal_clk_set_rate(sunxi_codec->pllclk, freq)) {
  902. snd_err("set pllclk rate %u failed\n", freq);
  903. return -EINVAL;
  904. }
  905. return 0;
  906. }
  907. static struct snd_dai_ops sun8iw18_codec_dai_ops = {
  908. .hw_params = sunxi_codec_hw_params,
  909. .shutdown = sunxi_codec_shutdown,
  910. .startup = sunxi_codec_startup,
  911. .trigger = sunxi_codec_trigger,
  912. .prepare = sunxi_codec_prepare,
  913. .set_sysclk = sunxi_codec_set_sysclk,
  914. .dapm_control = sunxi_codec_dapm_control,
  915. };
  916. static struct snd_dai sun8iw18_codec_dai[] = {
  917. {
  918. .name = "AC-codecdai",
  919. .playback = {
  920. .stream_name = "Playback",
  921. .channels_min = 1,
  922. .channels_max = 2,
  923. .rates = SNDRV_PCM_RATE_8000_192000
  924. | SNDRV_PCM_RATE_KNOT,
  925. .formats = SNDRV_PCM_FMTBIT_S16_LE
  926. | SNDRV_PCM_FMTBIT_S24_LE
  927. | SNDRV_PCM_FMTBIT_S32_LE,
  928. .rate_min = 8000,
  929. .rate_max = 192000,
  930. },
  931. .capture = {
  932. .stream_name = "Capture",
  933. .channels_min = 1,
  934. .channels_max = 4,
  935. .rates = SNDRV_PCM_RATE_8000_48000
  936. | SNDRV_PCM_RATE_KNOT,
  937. .formats = SNDRV_PCM_FMTBIT_S16_LE
  938. | SNDRV_PCM_FMTBIT_S24_LE,
  939. .rate_min = 8000,
  940. .rate_max = 48000,
  941. },
  942. .ops = &sun8iw18_codec_dai_ops,
  943. },
  944. };
  945. struct snd_codec sun8iw18_codec = {
  946. .name = "audiocodec",
  947. .codec_dai = sun8iw18_codec_dai,
  948. .codec_dai_num = ARRAY_SIZE(sun8iw18_codec_dai),
  949. .private_data = NULL,
  950. .probe = sun8iw18_codec_probe,
  951. .remove = sun8iw18_codec_remove,
  952. .read = sunxi_codec_read,
  953. .write = sunxi_codec_write,
  954. .controls = sunxi_codec_controls,
  955. .num_controls = ARRAY_SIZE(sunxi_codec_controls),
  956. };
  957. #if 0
  958. extern struct snd_platform gAudioCodecPlatform;
  959. struct snd_card gAudioCodec = {
  960. .name = "AudioCodec",
  961. .codec = &sun8iw18_codec,
  962. .platform = &gAudioCodecPlatform,
  963. };
  964. #endif