Advertisement
codekipper

sun6i-codec.c

Jul 3rd, 2016
202
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 47.79 KB | None | 0 0
  1. /*
  2. * sound/soc/sunxi\sun6i-codec.c
  3. * (C) Copyright 2010-2015
  4. * reuuimllatech Technology Co., Ltd. <www.reuuimllatech.com>
  5. * huangxin <huangxin@reuuimllatech.com>
  6. *
  7. * some simple description for this code
  8. *
  9. * This program is free software; you can redistribute it and/or
  10. * modify it under the terms of the GNU General Public License as
  11. * published by the Free Software Foundation; either version 2 of
  12. * the License, or (at your option) any later version.
  13. *
  14. */
  15. #define DEBUG
  16. #include <linux/module.h>
  17. #include <linux/moduleparam.h>
  18. #include <linux/init.h>
  19. #include <linux/err.h>
  20. #include <linux/platform_device.h>
  21. #include <linux/errno.h>
  22. #include <linux/ioctl.h>
  23. #include <linux/delay.h>
  24. #include <linux/slab.h>
  25. #include <linux/gpio.h>
  26. #include <sound/core.h>
  27. #include <sound/pcm.h>
  28. #include <sound/pcm_params.h>
  29. #include <sound/control.h>
  30. #include <sound/initval.h>
  31. #include <sound/soc.h>
  32. #include <sound/soc-dapm.h>
  33. #include <sound/tlv.h>
  34. #include <linux/clk.h>
  35. #include <linux/timer.h>
  36. #include <linux/io.h>
  37. #include <linux/reset.h>
  38. #include <linux/of.h>
  39. #include <linux/of_address.h>
  40. #include <linux/of_gpio.h>
  41. #include <linux/of_platform.h>
  42. #include <sound/dmaengine_pcm.h>
  43.  
  44. #define SUNXI_DAC_DPC (0x00) //the same as a10
  45. #define SUNXI_DAC_DPC_EN_DA (31)
  46. #define SUNXI_DAC_DPC_DVOL (12)
  47. #define SUNXI_DAC_FIFOC (0x04) //the same as a10
  48. #define SUNXI_DAC_FIFOC_DAC_FS (29)
  49. #define SUNXI_DAC_FIFOC_FIR_VERSION (28)
  50. #define SUNXI_DAC_FIFOC_SEND_LASAT (26)
  51. #define SUNXI_DAC_FIFOC_TX_FIFO_MODE (24)
  52. #define SUNXI_DAC_FIFOC_DRQ_CLR_CNT (21)
  53. #define SUNXI_DAC_FIFOC_TX_TRIG_LEVEL (8)
  54. #define SUNXI_DAC_FIFOC_MONO_EN (6)
  55. #define SUNXI_DAC_FIFOC_TX_SAMPLE_BITS (5)
  56. #define SUNXI_DAC_FIFOC_DAC_DRQ_EN (4)
  57. #define SUNXI_DAC_FIFOC_FIFO_FLUSH (0)
  58. #define SUNXI_DAC_FIFOS (0x08) //the same as a10
  59. #define SUNXI_DAC_TXDATA (0x0c) //the same as a10
  60. #define SUN6I_ADC_FIFOC (0x10) //33 ADC FIFO Control Register, different with a10
  61. #define SUNXI_ADC_FIFOC_DAC_FS (29)
  62. #define SUNXI_ADC_FIFOC_EN_AD (28)
  63. #define SUN6I_ADC_DIG_MIC_EN (27)
  64. #define SUNXI_ADC_FIFOC_RX_FIFO_MODE (24)
  65. #define SUN6I_ADC_DFEN (16)
  66. #define SUNXI_ADC_FIFOC_RX_TRIG_LEVEL (8)
  67. #define SUNXI_ADC_FIFOC_MONO_EN (7)
  68. #define SUNXI_ADC_FIFOC_RX_SAMPLE_BITS (6)
  69. #define SUNXI_ADC_FIFOC_ADC_DRQ_EN (4)
  70. #define SUNXI_ADC_FIFOC_FIFO_FLUSH (0)
  71.  
  72. #define SUN6I_ADC_FIFOS (0x14) //33 ADC FIFO Status Register, different with a10
  73. #define SUN6I_ADC_RXDATA (0x18) //33 ADC RX Data Register
  74. #define SUN6I_HMIC_CTRL (0x1c) //Earpiece MIC bias detect register,new func
  75. #define SUN6I_DAC_ACTL (0x20) //Output Mixer & DAC Analog Control Register
  76. #define SUNXI_DAC_ACTL_DACAENR (31)
  77. #define SUNXI_DAC_ACTL_DACAENL (30)
  78. #define SUN6I_DAC_ACTL_MIXENR (29)
  79. #define SUN6I_DAC_ACTL_MIXENL (28)
  80. #define SUN6I_DAC_ACTL_MIXMUTER_MIC1 (23)
  81. #define SUN6I_DAC_ACTL_MIXMUTER_MIC2 (22)
  82. #define SUN6I_DAC_ACTL_MIXMUTER_PHP_PHN (21)
  83. #define SUN6I_DAC_ACTL_MIXMUTER_PHP (20)
  84. #define SUN6I_DAC_ACTL_MIXMUTER_LINEINR (19)
  85. #define SUN6I_DAC_ACTL_MIXMUTER_DACR (18)
  86. #define SUN6I_DAC_ACTL_MIXMUTER_DACL (17)
  87. #define SUN6I_DAC_ACTL_MIXMUTER GENMASK(23,17)
  88. #define SUN6I_DAC_ACTL_MIXMUTEL_MIC1 (16)
  89. #define SUN6I_DAC_ACTL_MIXMUTEL_MIC2 (15)
  90. #define SUN6I_DAC_ACTL_MIXMUTEL_PHP_PHN (14)
  91. #define SUN6I_DAC_ACTL_MIXMUTEL_PHN (13)
  92. #define SUN6I_DAC_ACTL_MIXMUTEL_LINEINL (12)
  93. #define SUN6I_DAC_ACTL_MIXMUTEL_DACL (11)
  94. #define SUN6I_DAC_ACTL_MIXMUTEL_DACR (10)
  95. #define SUN6I_DAC_ACTL_MIXMUTEL GENMASK(16,10)
  96. #define SUN6I_DAC_ACTL_HPISR (9)
  97. #define SUN6I_DAC_ACTL_HPISL (8)
  98. #define SUN6I_DAC_ACTL_HPPAMUTER (7)
  99. #define SUN6I_DAC_ACTL_HPPAMUTEL (6)
  100. #define SUN6I_DAC_ACTL_HPVOL (0)
  101. #define SUNXI_DAC_ACTL_PA_VOL (0)
  102.  
  103. #define SUN6I_PA_CTRL (0x24) //new func
  104. #define SUN6I_PA_CTRL_HPPAEN (31)
  105. #define SUN6I_PA_CTRL_HPCOM_CTL (29)
  106. #define SUN6I_PA_CTRL_HPCOM_PRO (28)
  107. #define SUN6I_PA_CTRL_PA_ANTI_POP_CTL (26)
  108. #define SUN6I_PA_CTRL_LTRNMUTE (25)
  109. #define SUN6I_PA_CTRL_RTLNMUTE (24)
  110. #define SUN6I_PA_CTRL_MIC1G (15)
  111. #define SUN6I_PA_CTRL_MIG2G (12)
  112. #define SUN6I_PA_CTRL_LINEING (9)
  113. #define SUN6I_PA_CTRL_PHONEG (6)
  114. #define SUN6I_PA_CTRL_PHONEPG (3)
  115. #define SUN6I_PA_CTRL_PHONENG (0)
  116.  
  117. #define SUN6I_MIC_CTRL (0x28) //Microphone,Lineout and Phoneout Control Register,new func
  118. #define SUN6I_MIC_CTRL_HBIASEN (31)
  119. #define SUN6I_MIC_CTRL_MBIASEN (30)
  120. #define SUN6I_MIC_CTRL_HBIASADCEN (29)
  121. #define SUN6I_MIC_CTRL_MIC1AMPEN (28)
  122. #define SUN6I_MIC_CTRL_MIC1BOOST (25)
  123. #define SUN6I_MIC_CTRL_MIC2AMPEN (24)
  124. #define SUN6I_MIC_CTRL_MIC2BOOST (21)
  125. #define SUN6I_MIC_CTRL_MIC2_SEL (20)
  126. #define SUN6I_MIC_CTRL_LINEOUTL_EN (19)
  127. #define SUN6I_MIC_CTRL_LINEOUTR_EN (18)
  128. #define SUN6I_MIC_CTRL_LINEOUTL_SRC_SEL (17)
  129. #define SUN6I_MIC_CTRL_LINEOUTR_SRC_SEL (16)
  130. #define SUN6I_MIC_CTRL_LINEOUT_VOL (11)
  131. #define SUN6I_MIC_CTRL_PHONEPREG (8)
  132. #define SUN6I_MIC_CTRL_PHONEOUTG (5)
  133. #define SUN6I_MIC_CTRL_PHONEOUT_EN (4)
  134. #define SUN6I_MIC_CTRL_PHONEOUTS0 (3)
  135. #define SUN6I_MIC_CTRL_PHONEOUTS1 (2)
  136. #define SUN6I_MIC_CTRL_PHONEOUTS2 (1)
  137. #define SUN6I_MIC_CTRL_PHONEOUTS3 (0)
  138.  
  139. #define SUN6I_ADC_ACTL (0x2c) //diff with a10, ADC Analog Control Register
  140. #define SUNXI_ADC_ACTL_ADCREN (31)
  141. #define SUNXI_ADC_ACTL_ADCLEN (30)
  142. #define SUNXI_ADC_ACTL_PREG1EN (29)
  143. #define SUNXI_ADC_ACTL_PREG2EN (28)
  144. #define SUNXI_ADC_ACTL_VMICEN (27)
  145. #define SUN6I_ADC_ACTL_ADCRG (27)
  146. #define SUN6I_ADC_ACTL_ADCLG (24)
  147. #define SUNXI_ADC_ACTL_VADCG (20)
  148. #define SUNXI_ADC_ACTL_ADCIS (17)
  149. #define SUN6I_ADC_ACTL_RADCMIXMUTEMIC1BOOST (13)
  150. #define SUN6I_ADC_ACTL_RADCMIXMUTEMIC2BOOST (12)
  151. #define SUN6I_ADC_ACTL_RADCMIXMUTEPHONEPN (11)
  152. #define SUN6I_ADC_ACTL_RADCMIXMUTEPHONEP (10)
  153. #define SUN6I_ADC_ACTL_RADCMIXMUTELINEINR (9)
  154. #define SUN6I_ADC_ACTL_RADCMIXMUTEROUTPUT (8)
  155. #define SUN6I_ADC_ACTL_RADCMIXMUTELOUTPUT (7)
  156. #define SUN6I_ADC_ACTL_LADCMIXMUTEMIC1BOOST (6)
  157. #define SUN6I_ADC_ACTL_LADCMIXMUTEMIC2BOOST (5)
  158. #define SUNXI_ADC_ACTL_PA_EN (4)
  159. #define SUN6I_ADC_ACTL_LADCMIXMUTEPHONEPN (4)
  160. #define SUNXI_ADC_ACTL_DDE (3)
  161. #define SUN6I_ADC_ACTL_LADCMIXMUTEPHONEP (3)
  162. #define SUN6I_ADC_ACTL_LADCMIXMUTELINEINL (2)
  163. #define SUN6I_ADC_ACTL_LADCMIXMUTELOUTPUT (1)
  164. #define SUN6I_ADC_ACTL_LADCMIXMUTEROUTPUT (0)
  165.  
  166. #define SUN6I_ADDAC_TUNE (0x30)
  167. #define SUN6I_ADDAC_TUNE_PA_SLOPE_SECECT (30)
  168. #define SUN6I_ADDAC_TUNE_DITHER (25)
  169. #define SUN6I_ADDAC_TUNE_ZERO_CROSS_EN (22)
  170. #define SUN6I_BIAS_CRT (0x34)
  171. #define SUN6I_BIAS_CRT_OPMIC_BIAS_CUR (30)
  172. #define SUN6I_BIAS_CRT_BIASCALIVERIFY (29)
  173. #define SUN6I_BIAS_CRT_BIASVERIFY (23)
  174. #define SUN6I_BIAS_CRT_BIASCALI (17)
  175. #define SUN6I_BIAS_CRT_DA16CALIVERIFY (16)
  176. #define SUN6I_BIAS_CRT_DA16VERIFY (8)
  177. #define SUN6I_BIAS_CRT_DA16CALI (0)
  178.  
  179. #define SUN6I_DAC_TXCNT (0x40)
  180. #define SUN6I_ADC_RXCNT (0x44)
  181. #define SUN6I_DAC_DEBUG (0x48)
  182. #define SUN6I_ADC_DEBUG (0x4c)
  183. #define SUN6I_HMIC_CTL (0x50) //new func
  184. #define SUN6I_HMIC_DATA (0x54) //new func
  185. #define SUN6I_DAC_DAP_CTL (0x60) //DAC DAP control Register
  186. #define SUN6I_DAC_DAP_VOL (0x64) //DAC DAP volume Register
  187. #define SUN6I_DAC_DAP_COF (0x68) //DAC DAP Coefficient Register
  188. #define SUN6I_DAC_DAP_OPT (0x6c) //DAC DAP Optimum Register
  189. #define SUN6I_ADC_DAP_CTL (0x70) //ADC DAP Control Register
  190. #define SUN6I_ADC_DAP_VOL (0x74) //ADC DAP volume Register
  191. #define SUN6I_ADC_DAP_LCTL (0x78) //ADC DAP Left Control Register
  192. #define SUN6I_ADC_DAP_RCTL (0x7c) //ADC DAP Right Control Register
  193. #define SUN6I_ADC_DAP_PARA (0x80) //ADC DAP Parameter Control Register
  194. #define SUN6I_ADC_DAP_LAC (0x84) //ADC DAP Left Average Coefficient Register
  195. #define SUN6I_ADC_DAP_LDAT (0x88) //ADC DAP Left Decay&Attack Time Register
  196. #define SUN6I_ADC_DAP_RAC (0x8c) //ADC DAP Right Average Coefficient Register
  197. #define SUN6I_ADC_DAP_RDAC (0x90) //ADC DAP Right Decay&Attack time Register
  198. #define SUN6I_ADC_DAP_HPFC (0x94) //ADC DAP HPF Coefficient Register
  199.  
  200.  
  201. #define RADCMIXMUTE (7)
  202. #define LADCMIXMUTE (0)
  203.  
  204. /*DAC Debug Register
  205. * codecbase+0x48
  206. */
  207. #define DAC_SWP (6)
  208.  
  209. /*HMIC Control Register
  210. *codecbase+0x50
  211. */
  212. #define HMIC_M (28)
  213. #define HMIC_N (24)
  214. #define HMIC_DIRQ (23)
  215. #define HMIC_TH1_HYS (21)
  216. #define HMIC_EARPHONE_OUT_IRQ_EN (20)
  217. #define HMIC_EARPHONE_IN_IRQ_EN (19)
  218. #define HMIC_KEY_UP_IRQ_EN (18)
  219. #define HMIC_KEY_DOWN_IRQ_EN (17)
  220. #define HMIC_DATA_IRQ_EN (16)
  221. #define HMIC_DS_SAMP (14)
  222. #define HMIC_TH2_HYS (13)
  223. #define HMIC_TH2_KEY (8)
  224. #define HMIC_SF_SMOOTH_FIL (6)
  225. #define KEY_UP_IRQ_PEND (5)
  226. #define HMIC_TH1_EARPHONE (0)
  227.  
  228. /*HMIC Data Register
  229. * codecbase+0x54
  230. */
  231. #define HMIC_EARPHONE_OUT_IRQ_PEND (20)
  232. #define HMIC_EARPHONE_IN_IRQ_PEND (19)
  233. #define HMIC_KEY_UP_IRQ_PEND (18)
  234. #define HMIC_KEY_DOWN_IRQ_PEND (17)
  235. #define HMIC_DATA_IRQ_PEND (16)
  236. #define HMIC_ADC_DATA (0)
  237.  
  238. /*DAC DAP Control Register
  239. * codecbase+0x60
  240. */
  241. #define DAC_DAP_EN (31)
  242. #define DAC_DAP_CTL (30)
  243. #define DAC_DAP_STATE (29)
  244. #define DAC_BQ_EN (16)
  245. #define DAC_DRC_EN (15)
  246. #define DAC_HPF_EN (14)
  247. #define DAC_DE_CTL (12)
  248. #define DAC_RAM_ADDR (0)
  249.  
  250. /* DAC DAP volume register
  251. * codecbase+0x64
  252. */
  253. #define DAC_LEFT_CHAN_SOFT_MUTE_CTL (30)
  254. #define DAC_RIGHT_CHAN_SOFT_MUTE_CTL (29)
  255. #define DAC_MASTER_SOFT_MUTE_CTL (28)
  256. #define DAC_SKEW_TIME_VOL_CTL (24)
  257. #define DAC_MASTER_VOL (16)
  258. #define DAC_LEFT_CHAN_VOL (8)
  259. #define DAC_RIGHT_CHAN_VOL (0)
  260.  
  261. /*ADC DAP Control Register
  262. * codecbase+0x70
  263. */
  264. #define ADC_DAP_EN (31)
  265. #define ADC_DAP_START (30)
  266. #define AGC_LEFT_SATURATION_FLAG (21)
  267. #define AGC_LEFT_NOISE_THRES_FLAG (20)
  268. #define AGC_LEFT_GAIN_APP (12)
  269. #define AGC_RIGHT_SATURATION_FLAG (9)
  270. #define AGC_RIGHT_NOISE_THRES_FLAG (8)
  271. #define AGC_RIGHT_GAIN_APP (0)
  272.  
  273. /*ADC DAP Volume Register
  274. * codecbase+0x74
  275. */
  276. #define ADC_LEFT_CHAN_VOL_MUTE (18)
  277. #define ADC_RIGHT_CHAN_VOL_MUTE (17)
  278. #define ADC_SKEW_TIME_VOL (16)
  279. #define ADC_LEFT_CHAN_VOL (8)
  280. #define ADC_RIGHT_CHAN_VOL (0)
  281.  
  282. /*ADC DAP Left control register
  283. * codecbase+0x78
  284. */
  285. #define ADC_LEFT_CHAN_NOISE_THRES_SET (16)
  286. #define ADC_LEFT_AGC_EN (14)
  287. #define ADC_LEFT_HPF_EN (13)
  288. #define ADC_LEFT_NOISE_DET_EN (12)
  289. #define ADC_LEFT_HYS_SET (8)
  290. #define ADC_LEFT_NOISE_DEBOURCE_TIME (4)
  291. #define ADC_LEFT_SIGNAL_DEBOUNCE_TIME (0)
  292.  
  293. /*ADC DAP Right Control Register
  294. * codecbase+0x7c
  295. */
  296. #define ADC_RIGHT_CHAN_NOISE_THRES_SET (16)
  297. #define ADC_RIGHT_AGC_EN (14)
  298. #define ADC_RIGHT_HPF_EN (13)
  299. #define ADC_RIGHT_NOISE_DET_EN (12)
  300. #define ADC_RIGHT_HYS_SET (8)
  301. #define ADC_RIGHT_NOISE_DEBOURCE_TIME (4)
  302. #define ADC_RIGHT_SIGNAL_DEBOUNCE_TIME (0)
  303.  
  304. /*ADC DAP Parameter Register
  305. * codecbase+0x80
  306. */
  307. #define ADC_LEFT_CHAN_TARG_LEVEL_SET (24)
  308. #define ADC_RIGHT_CHAN_TARG_LEVEL_SET (16)
  309. #define ADC_LEFT_CHAN_MAX_GAIN_SET (8)
  310. #define ADC_RIGHT_CHAN_MAX_GAIN_SET (0)
  311.  
  312. /*ADC DAP Left Decay&Attack time register
  313. * codecbase+0x88
  314. */
  315. #define ADC_LEFT_ATTACK_TIME_COEFF_SET (16)
  316. #define ADC_LEFT_DECAY_TIME_COEFF_SET (0)
  317.  
  318. /*ADC DAP Right decay&Attack Time register
  319. * codecbae+0x90
  320. */
  321. #define ADC_RIGHT_ATTACK_TIME_COEFF_SET (16)
  322. #define ADC_RIGHT_DECAY_TIME_COEFF_SET (0)
  323.  
  324. struct sun6i_codec {
  325. struct platform_device *pdev;
  326. struct regmap *regmap;
  327.  
  328. struct clk *clk_apb;
  329. struct clk *clk_module;
  330. struct gpio_desc *gpio_pa;
  331. struct reset_control *rst;
  332.  
  333. bool linein_playback;
  334. bool linein_capture;
  335. bool headphone_playback;
  336. bool earpiece_playback;
  337. bool speaker_playback;
  338. bool speaker_active;
  339.  
  340. struct snd_dmaengine_dai_dma_data playback_dma_data;
  341. struct snd_dmaengine_dai_dma_data capture_dma_data;
  342. };
  343.  
  344. static void sun6i_codec_hp_chan_mute(struct sun6i_codec *scodec, bool left, bool right)
  345. {
  346. regmap_update_bits(scodec->regmap, SUN6I_DAC_ACTL,
  347. BIT(SUN6I_DAC_ACTL_HPPAMUTEL),
  348. left ? 0 : BIT(SUN6I_DAC_ACTL_HPPAMUTEL));
  349. regmap_update_bits(scodec->regmap, SUN6I_DAC_ACTL,
  350. BIT(SUN6I_DAC_ACTL_HPPAMUTER),
  351. right ? 0 : BIT(SUN6I_DAC_ACTL_HPPAMUTER));
  352. }
  353.  
  354. static int sun6i_codec_pa_play_open(struct sun6i_codec *scodec)
  355. {
  356. /* int pa_vol = 0; */
  357. /* script_item_u val; */
  358. /* script_item_value_type_e type; */
  359. /* int pa_double_used = 0; */
  360.  
  361. /* type = script_get_item("audio_para", "pa_double_used", &val); */
  362. /* if (SCIRPT_ITEM_VALUE_TYPE_INT != type) { */
  363. /* printk("[audiocodec] type err!\n"); */
  364. /* } */
  365. /* pa_double_used = val.val; */
  366. /* if (!pa_double_used) { */
  367. /* type = script_get_item("audio_para", "pa_single_vol", &val); */
  368. /* if (SCIRPT_ITEM_VALUE_TYPE_INT != type) { */
  369. /* printk("[audiocodec] type err!\n"); */
  370. /* } */
  371. /* pa_vol = val.val; */
  372. /* } else { */
  373. /* type = script_get_item("audio_para", "pa_double_vol", &val); */
  374. /* if (SCIRPT_ITEM_VALUE_TYPE_INT != type) { */
  375. /* printk("[audiocodec] type err!\n"); */
  376. /* } */
  377. /* pa_vol = val.val; */
  378. /* } */
  379.  
  380. /*mute l_pa and r_pa*/
  381. regmap_update_bits(scodec->regmap, SUN6I_DAC_ACTL,
  382. BIT(SUN6I_DAC_ACTL_HPPAMUTEL), 0);
  383. regmap_update_bits(scodec->regmap, SUN6I_DAC_ACTL,
  384. BIT(SUN6I_DAC_ACTL_HPPAMUTER), 0);
  385.  
  386. /*enable dac digital*/
  387. regmap_update_bits(scodec->regmap, SUNXI_DAC_DPC,
  388. BIT(SUNXI_DAC_DPC_EN_DA),
  389. BIT(SUNXI_DAC_DPC_EN_DA));
  390. /*set TX FIFO send drq level*/
  391. regmap_update_bits(scodec->regmap, SUNXI_DAC_FIFOC,
  392. 0x7f << SUNXI_DAC_FIFOC_TX_TRIG_LEVEL,
  393. 0x0f << SUNXI_DAC_FIFOC_TX_TRIG_LEVEL);
  394. /*set TX FIFO MODE*/
  395. regmap_update_bits(scodec->regmap, SUNXI_DAC_FIFOC,
  396. BIT(SUNXI_DAC_FIFOC_TX_FIFO_MODE),
  397. BIT(SUNXI_DAC_FIFOC_TX_FIFO_MODE));
  398.  
  399. //send last sample when dac fifo under run
  400. regmap_update_bits(scodec->regmap, SUNXI_DAC_FIFOC,
  401. BIT(SUNXI_DAC_FIFOC_SEND_LASAT), 0);
  402.  
  403. /*enable dac_l and dac_r*/
  404. regmap_update_bits(scodec->regmap, SUN6I_DAC_ACTL,
  405. BIT(SUNXI_DAC_ACTL_DACAENL),
  406. BIT(SUNXI_DAC_ACTL_DACAENL));
  407. regmap_update_bits(scodec->regmap, SUN6I_DAC_ACTL,
  408. BIT(SUNXI_DAC_ACTL_DACAENR),
  409. BIT(SUNXI_DAC_ACTL_DACAENR));
  410.  
  411. regmap_update_bits(scodec->regmap, SUN6I_MIC_CTRL,
  412. BIT(SUN6I_MIC_CTRL_LINEOUTL_EN),
  413. BIT(SUN6I_MIC_CTRL_LINEOUTL_EN));
  414. regmap_update_bits(scodec->regmap, SUN6I_MIC_CTRL,
  415. BIT(SUN6I_MIC_CTRL_LINEOUTR_EN),
  416. BIT(SUN6I_MIC_CTRL_LINEOUTR_EN));
  417.  
  418. /* TODO: This used to be retrieved by FEX */
  419. /* if (!pa_double_used) { */
  420. regmap_update_bits(scodec->regmap, SUN6I_MIC_CTRL,
  421. BIT(SUN6I_MIC_CTRL_LINEOUTR_SRC_SEL),
  422. BIT(SUN6I_MIC_CTRL_LINEOUTR_SRC_SEL));
  423. regmap_update_bits(scodec->regmap, SUN6I_MIC_CTRL,
  424. BIT(SUN6I_MIC_CTRL_LINEOUTL_SRC_SEL),
  425. BIT(SUN6I_MIC_CTRL_LINEOUTL_SRC_SEL));
  426. /* } else { */
  427. /* codec_wr_control(sun6i, SUN6I_MIC_CTRL, 0x1, LINEOUTL_SRC_SEL, 0x0); */
  428. /* codec_wr_control(sun6i, SUN6I_MIC_CTRL, 0x1, LINEOUTR_SRC_SEL, 0x0); */
  429. /* } */
  430.  
  431. regmap_update_bits(scodec->regmap, SUN6I_DAC_ACTL,
  432. BIT(SUN6I_DAC_ACTL_HPISL),
  433. BIT(SUN6I_DAC_ACTL_HPISL));
  434. regmap_update_bits(scodec->regmap, SUN6I_DAC_ACTL,
  435. BIT(SUN6I_DAC_ACTL_HPISR),
  436. BIT(SUN6I_DAC_ACTL_HPISR));
  437.  
  438. regmap_update_bits(scodec->regmap, SUN6I_DAC_ACTL,
  439. SUN6I_DAC_ACTL_MIXMUTER,
  440. SUN6I_DAC_ACTL_MIXMUTER_DACR);
  441. regmap_update_bits(scodec->regmap, SUN6I_DAC_ACTL,
  442. SUN6I_DAC_ACTL_MIXMUTEL,
  443. SUN6I_DAC_ACTL_MIXMUTEL_DACL);
  444.  
  445. regmap_update_bits(scodec->regmap, SUN6I_DAC_ACTL,
  446. BIT(SUN6I_DAC_ACTL_MIXENL),
  447. BIT(SUN6I_DAC_ACTL_MIXENL));
  448. regmap_update_bits(scodec->regmap, SUN6I_DAC_ACTL,
  449. BIT(SUN6I_DAC_ACTL_MIXENR),
  450. BIT(SUN6I_DAC_ACTL_MIXENR));
  451.  
  452. /*
  453. * TODO: This used to be retrieved by FEX.
  454. * The script has nice comments explaining what values mean in term of dB output
  455. */
  456. regmap_update_bits(scodec->regmap, SUN6I_MIC_CTRL,
  457. 0x1f << SUN6I_MIC_CTRL_LINEOUT_VOL,
  458. 0x19 << SUN6I_MIC_CTRL_LINEOUT_VOL);
  459.  
  460. /* TODO: Configure the GPIO using gpiolib */
  461. /* mdelay(3); */
  462. /* item.gpio.data = 1; */
  463. /* /\*config gpio info of audio_pa_ctrl open*\/ */
  464. /* if (0 != sw_gpio_setall_range(&item.gpio, 1)) { */
  465. /* printk("sw_gpio_setall_range failed\n"); */
  466. /* } */
  467. /* mdelay(62); */
  468.  
  469. return 0;
  470. }
  471.  
  472. static int sun6i_codec_capture_open(struct sun6i_codec *scodec)
  473. {
  474. int cap_vol = 0;
  475. /* script_item_u val; */
  476. /* script_item_value_type_e type; */
  477.  
  478. /* type = script_get_item("audio_para", "cap_vol", &val); */
  479. /* if (SCIRPT_ITEM_VALUE_TYPE_INT != type) { */
  480. /* printk("[audiocodec] type err!\n"); */
  481. /* } */
  482. /* cap_vol = val.val; */
  483.  
  484. /* TODO: This used to be retrieved by FEX */
  485. cap_vol = 5;
  486.  
  487. /*enable mic1 pa*/
  488. regmap_update_bits(scodec->regmap, SUN6I_MIC_CTRL,
  489. BIT(SUN6I_MIC_CTRL_MIC1AMPEN),
  490. BIT(SUN6I_MIC_CTRL_MIC1AMPEN));
  491. /*mic1 gain 36dB,if capture volume is too small, enlarge the mic1boost*/
  492. regmap_update_bits(scodec->regmap, SUN6I_MIC_CTRL,
  493. 0x7 << SUN6I_MIC_CTRL_MIC1BOOST,
  494. cap_vol << SUN6I_MIC_CTRL_MIC1BOOST);
  495. /*enable Master microphone bias*/
  496. regmap_update_bits(scodec->regmap, SUN6I_MIC_CTRL,
  497. BIT(SUN6I_MIC_CTRL_MBIASEN),
  498. BIT(SUN6I_MIC_CTRL_MBIASEN));
  499.  
  500. /*enable Right MIC1 Boost stage*/
  501. regmap_update_bits(scodec->regmap, SUN6I_ADC_ACTL,
  502. BIT(SUN6I_ADC_ACTL_RADCMIXMUTEMIC1BOOST),
  503. BIT(SUN6I_ADC_ACTL_RADCMIXMUTEMIC1BOOST));
  504. /*enable Left MIC1 Boost stage*/
  505. regmap_update_bits(scodec->regmap, SUN6I_ADC_ACTL,
  506. BIT(SUN6I_ADC_ACTL_LADCMIXMUTEMIC1BOOST),
  507. BIT(SUN6I_ADC_ACTL_LADCMIXMUTEMIC1BOOST));
  508. /*enable adc_r adc_l analog*/
  509. regmap_update_bits(scodec->regmap, SUN6I_ADC_ACTL,
  510. BIT(SUNXI_ADC_ACTL_ADCREN),
  511. BIT(SUNXI_ADC_ACTL_ADCREN));
  512. regmap_update_bits(scodec->regmap, SUN6I_ADC_ACTL,
  513. BIT(SUNXI_ADC_ACTL_ADCLEN),
  514. BIT(SUNXI_ADC_ACTL_ADCLEN));
  515. /*set RX FIFO mode*/
  516. regmap_update_bits(scodec->regmap, SUN6I_ADC_FIFOC,
  517. BIT(SUNXI_ADC_FIFOC_RX_FIFO_MODE),
  518. BIT(SUNXI_ADC_FIFOC_RX_FIFO_MODE));
  519. /*set RX FIFO rec drq level*/
  520. regmap_update_bits(scodec->regmap, SUN6I_ADC_FIFOC,
  521. 0x1f << SUNXI_ADC_FIFOC_RX_TRIG_LEVEL,
  522. 0xf << SUNXI_ADC_FIFOC_RX_TRIG_LEVEL);
  523. /*enable adc digital part*/
  524. regmap_update_bits(scodec->regmap, SUN6I_ADC_FIFOC,
  525. BIT(SUNXI_ADC_FIFOC_EN_AD),
  526. BIT(SUNXI_ADC_FIFOC_EN_AD));
  527.  
  528. return 0;
  529. }
  530.  
  531. static int sun6i_codec_play_start(struct sun6i_codec *scodec)
  532. {
  533. /*enable dac drq*/
  534. regmap_update_bits(scodec->regmap, SUNXI_DAC_FIFOC,
  535. BIT(SUNXI_DAC_FIFOC_DAC_DRQ_EN),
  536. BIT(SUNXI_DAC_FIFOC_DAC_DRQ_EN));
  537. /*DAC FIFO Flush,Write '1' to flush TX FIFO, self clear to '0'*/
  538. regmap_update_bits(scodec->regmap, SUNXI_DAC_FIFOC,
  539. BIT(SUNXI_DAC_FIFOC_FIFO_FLUSH),
  540. BIT(SUNXI_DAC_FIFOC_FIFO_FLUSH));
  541.  
  542. return 0;
  543. }
  544.  
  545. static int sun6i_codec_play_stop(struct sun6i_codec *scodec)
  546. {
  547. int i = 0;
  548. int headphone_vol = 0;
  549. /* script_item_u val; */
  550. /* script_item_value_type_e type; */
  551.  
  552. /* type = script_get_item("audio_para", "headphone_vol", &val); */
  553. /* if (SCIRPT_ITEM_VALUE_TYPE_INT != type) { */
  554. /* printk("[audiocodec] type err!\n"); */
  555. /* } */
  556. /* headphone_vol = val.val; */
  557.  
  558. /* TODO: This used to be retrieved by FEX*/
  559. headphone_vol = 0x3b;
  560.  
  561. regmap_update_bits(scodec->regmap, SUN6I_ADDAC_TUNE,
  562. BIT(SUN6I_ADDAC_TUNE_ZERO_CROSS_EN),
  563. 0);
  564. for (i = 0; i < headphone_vol; i++) {
  565. /*set HPVOL volume*/
  566. regmap_update_bits(scodec->regmap, SUN6I_DAC_ACTL,
  567. 0x3f << SUNXI_DAC_ACTL_PA_VOL,
  568. headphone_vol << SUNXI_DAC_ACTL_PA_VOL);
  569. headphone_vol = headphone_vol - i;
  570. mdelay(1);
  571. i++;
  572. if (i > headphone_vol-1) {
  573. regmap_update_bits(scodec->regmap, SUN6I_DAC_ACTL,
  574. 0x3f << SUNXI_DAC_ACTL_PA_VOL, 0);
  575. break;
  576. }
  577. }
  578. /*mute l_pa and r_pa*/
  579. regmap_update_bits(scodec->regmap, SUN6I_DAC_ACTL,
  580. BIT(SUN6I_DAC_ACTL_HPPAMUTEL)|BIT(SUN6I_DAC_ACTL_HPPAMUTER),
  581. 0);
  582.  
  583. /*disable dac drq*/
  584. regmap_update_bits(scodec->regmap, SUNXI_DAC_FIFOC,
  585. BIT(SUNXI_DAC_FIFOC_DAC_DRQ_EN), 0);
  586.  
  587. /*disable dac_l and dac_r*/
  588. regmap_update_bits(scodec->regmap, SUN6I_DAC_ACTL,
  589. BIT(SUNXI_DAC_ACTL_DACAENL)|BIT(SUNXI_DAC_ACTL_DACAENR),
  590. 0);
  591.  
  592.  
  593. /*disable dac digital*/
  594. regmap_update_bits(scodec->regmap, SUNXI_DAC_DPC,
  595. BIT(SUNXI_DAC_DPC_EN_DA), 0);
  596.  
  597. /* TODO: Configure the GPIO */
  598. /* item.gpio.data = 0; */
  599. /* /\*config gpio info of audio_pa_ctrl open*\/ */
  600. /* if (0 != sw_gpio_setall_range(&item.gpio, 1)) { */
  601. /* printk("sw_gpio_setall_range failed\n"); */
  602. /* } */
  603.  
  604. regmap_update_bits(scodec->regmap, SUN6I_MIC_CTRL,
  605. BIT(SUN6I_MIC_CTRL_LINEOUTL_EN)|BIT(SUN6I_MIC_CTRL_LINEOUTR_EN),
  606. 0);
  607.  
  608. regmap_update_bits(scodec->regmap, SUN6I_MIC_CTRL,
  609. BIT(SUN6I_MIC_CTRL_LINEOUTL_SRC_SEL)|BIT(SUN6I_MIC_CTRL_LINEOUTR_SRC_SEL),
  610. 0);
  611.  
  612. regmap_update_bits(scodec->regmap, SUN6I_DAC_ACTL,
  613. BIT(SUN6I_DAC_ACTL_HPISL)|BIT(SUN6I_DAC_ACTL_HPISR),
  614. 0);
  615.  
  616. regmap_update_bits(scodec->regmap, SUN6I_MIC_CTRL,
  617. BIT(SUN6I_MIC_CTRL_PHONEOUTS2)|BIT(SUN6I_MIC_CTRL_PHONEOUTS3),
  618. 0);
  619. return 0;
  620. }
  621.  
  622. static int sun6i_codec_capture_start(struct sun6i_codec *scodec)
  623. {
  624. /*enable adc drq*/
  625. regmap_update_bits(scodec->regmap, SUN6I_ADC_FIFOC,
  626. BIT(SUNXI_ADC_FIFOC_ADC_DRQ_EN),
  627. BIT(SUNXI_ADC_FIFOC_ADC_DRQ_EN));
  628. return 0;
  629. }
  630.  
  631. static int sun6i_codec_capture_stop(struct sun6i_codec *scodec)
  632. {
  633. /*disable adc digital part*/
  634. regmap_update_bits(scodec->regmap, SUN6I_ADC_FIFOC,
  635. BIT(SUNXI_ADC_FIFOC_EN_AD),
  636. 0);
  637. /*disable adc drq*/
  638. regmap_update_bits(scodec->regmap, SUN6I_ADC_FIFOC,
  639. BIT(SUNXI_ADC_FIFOC_ADC_DRQ_EN), 0);
  640. /*disable mic1 pa*/
  641. regmap_update_bits(scodec->regmap, SUN6I_MIC_CTRL,
  642. BIT(SUN6I_MIC_CTRL_MIC1AMPEN), 0);
  643. /*disable Master microphone bias*/
  644. regmap_update_bits(scodec->regmap, SUN6I_MIC_CTRL,
  645. BIT(SUN6I_MIC_CTRL_MBIASEN), 0);
  646. /*disable adc_r adc_l analog*/
  647. regmap_update_bits(scodec->regmap, SUN6I_ADC_ACTL,
  648. BIT(SUNXI_ADC_ACTL_ADCLEN) | BIT(SUNXI_ADC_ACTL_ADCREN), 0);
  649.  
  650. return 0;
  651. }
  652.  
  653. static int sun6i_codec_prepare(struct snd_pcm_substream *substream,
  654. struct snd_soc_dai *dai)
  655. {
  656. struct snd_soc_pcm_runtime *rtd = substream->private_data;
  657. struct sun6i_codec *scodec = snd_soc_card_get_drvdata(rtd->card);
  658.  
  659. if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
  660. if (scodec->speaker_active) {
  661. /* return codec_pa_play_open(sun6i); */
  662. } else {
  663. /*set TX FIFO send drq level*/
  664. regmap_update_bits(scodec->regmap, SUNXI_DAC_FIFOC,
  665. 0x7f << SUNXI_DAC_FIFOC_TX_TRIG_LEVEL,
  666. 0xf << SUNXI_DAC_FIFOC_TX_TRIG_LEVEL);
  667.  
  668. /*set TX FIFO MODE*/
  669. regmap_update_bits(scodec->regmap, SUNXI_DAC_FIFOC,
  670. BIT(SUNXI_DAC_FIFOC_TX_FIFO_MODE),
  671. BIT(SUNXI_DAC_FIFOC_TX_FIFO_MODE));
  672.  
  673. //send last sample when dac fifo under run
  674. regmap_update_bits(scodec->regmap, SUNXI_DAC_FIFOC,
  675. BIT(SUNXI_DAC_FIFOC_SEND_LASAT),
  676. BIT(SUNXI_DAC_FIFOC_SEND_LASAT));
  677. }
  678. } else {
  679. /* return codec_capture_open(sun6i); */
  680. }
  681.  
  682. return 0;
  683. }
  684.  
  685. static int sun6i_codec_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
  686. {
  687. return 0;
  688. }
  689.  
  690. static int sun6i_codec_digital_mute(struct snd_soc_dai *dai, int mute)
  691. {
  692. struct snd_soc_card *card = snd_soc_dai_get_drvdata(dai);
  693. struct sun6i_codec *scodec = snd_soc_card_get_drvdata(card);
  694.  
  695. sun6i_codec_hp_chan_mute(scodec, mute, mute);
  696.  
  697. return 0;
  698. }
  699.  
  700. static int sun6i_codec_trigger(struct snd_pcm_substream *substream, int cmd,
  701. struct snd_soc_dai *dai)
  702. {
  703. struct snd_soc_pcm_runtime *rtd = substream->private_data;
  704. struct sun6i_codec *scodec = snd_soc_card_get_drvdata(rtd->card);
  705.  
  706. switch (cmd) {
  707. case SNDRV_PCM_TRIGGER_START:
  708. case SNDRV_PCM_TRIGGER_RESUME:
  709. case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
  710. if(substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
  711. sun6i_codec_play_start(scodec);
  712.  
  713. if (!scodec->speaker_active)
  714. /* set the default output is HPOUTL/R for pad headphone */
  715. sun6i_codec_hp_chan_mute(scodec, 0, 0);
  716. } else {
  717. sun6i_codec_capture_start(scodec);
  718.  
  719. /*hardware fifo delay*/
  720. mdelay(200);
  721. regmap_update_bits(scodec->regmap, SUN6I_ADC_FIFOC,
  722. BIT(SUNXI_ADC_FIFOC_FIFO_FLUSH),
  723. BIT(SUNXI_ADC_FIFOC_FIFO_FLUSH));
  724. }
  725. break;
  726.  
  727. case SNDRV_PCM_TRIGGER_SUSPEND:
  728. case SNDRV_PCM_TRIGGER_STOP:
  729. case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
  730. if(substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
  731. sun6i_codec_play_stop(scodec);
  732. else
  733. sun6i_codec_capture_stop(scodec);
  734. break;
  735. default:
  736. dev_err(dai->dev, "Unsupported trigger operation\n");
  737. return -EINVAL;
  738.  
  739. }
  740. {
  741. /* COOPS DEBUGGING FOR NOW */
  742. u32 reg_val = 0;
  743.  
  744. printk("%s Command State %d Audio Clock is %lu\n", __func__, cmd, clk_get_rate(scodec->clk_module));
  745.  
  746. regmap_read(scodec->regmap, SUNXI_DAC_DPC, &reg_val);
  747. printk("%s %s 0x%x\n", __func__,
  748. "SUNXI_DAC_DPC", reg_val);
  749. regmap_read(scodec->regmap, SUNXI_DAC_FIFOC, &reg_val);
  750. printk("%s %s 0x%x\n", __func__,
  751. "SUNXI_DAC_FIFOC", reg_val);
  752. regmap_read(scodec->regmap, SUNXI_DAC_FIFOS, &reg_val);
  753. printk("%s %s 0x%x\n", __func__,
  754. "SUNXI_DAC_FIFOS", reg_val);
  755. regmap_read(scodec->regmap, SUN6I_DAC_ACTL, &reg_val);
  756. printk("%s %s 0x%x\n", __func__,
  757. "SUN6I_DAC_ACTL", reg_val);
  758. regmap_read(scodec->regmap, SUN6I_PA_CTRL, &reg_val);
  759. printk("%s %s 0x%x\n", __func__,
  760. "SUN6I_PA_CTRL", reg_val);
  761. regmap_read(scodec->regmap, SUN6I_MIC_CTRL, &reg_val);
  762. printk("%s %s 0x%x\n", __func__,
  763. "SUN6I_MIC_CTRL", reg_val);
  764. regmap_read(scodec->regmap, SUN6I_DAC_TXCNT, &reg_val);
  765. printk("%s %s 0x%x\n", __func__,
  766. "SUN6I_DAC_TXCNT", reg_val);
  767. }
  768. return 0;
  769. }
  770.  
  771. static int sun6i_codec_hw_params(struct snd_pcm_substream *substream,
  772. struct snd_pcm_hw_params *params,
  773. struct snd_soc_dai *dai)
  774. {
  775. struct snd_soc_pcm_runtime *rtd = substream->private_data;
  776. struct sun6i_codec *scodec = snd_soc_card_get_drvdata(rtd->card);
  777. int is_mono = !!(params_channels(params) == 1);
  778. int is_24bit = !!(hw_param_interval(params, SNDRV_PCM_HW_PARAM_SAMPLE_BITS)->min == 32);
  779. unsigned int rate = params_rate(params);
  780. unsigned int hwrate;
  781.  
  782. switch (rate) {
  783. case 192000:
  784. case 96000:
  785. case 48000:
  786. case 32000:
  787. case 24000:
  788. case 16000:
  789. case 12000:
  790. case 8000:
  791. clk_set_rate(scodec->clk_module, 24576000);
  792. break;
  793. case 176400:
  794. case 88200:
  795. case 44100:
  796. case 33075:
  797. case 22050:
  798. case 14700:
  799. case 11025:
  800. case 7350:
  801. default:
  802. clk_set_rate(scodec->clk_module, 22579200);
  803. break;
  804. }
  805.  
  806. switch (rate) {
  807. case 192000:
  808. case 176400:
  809. hwrate = 6;
  810. break;
  811. case 96000:
  812. case 88200:
  813. hwrate = 7;
  814. break;
  815. default:
  816. case 48000:
  817. case 44100:
  818. hwrate = 0;
  819. break;
  820. case 32000:
  821. case 33075:
  822. hwrate = 1;
  823. break;
  824. case 24000:
  825. case 22050:
  826. hwrate = 2;
  827. break;
  828. case 16000:
  829. case 14700:
  830. hwrate = 3;
  831. break;
  832. case 12000:
  833. case 11025:
  834. hwrate = 4;
  835. break;
  836. case 8000:
  837. case 7350:
  838. hwrate = 5;
  839. break;
  840. }
  841.  
  842. if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
  843. regmap_update_bits(scodec->regmap, SUNXI_DAC_FIFOC, 7 << SUNXI_DAC_FIFOC_DAC_FS, hwrate << SUNXI_DAC_FIFOC_DAC_FS);
  844. regmap_update_bits(scodec->regmap, SUNXI_DAC_FIFOC, 1 << SUNXI_DAC_FIFOC_MONO_EN, is_mono << SUNXI_DAC_FIFOC_MONO_EN);
  845. regmap_update_bits(scodec->regmap, SUNXI_DAC_FIFOC, 1 << SUNXI_DAC_FIFOC_TX_SAMPLE_BITS, is_24bit << SUNXI_DAC_FIFOC_TX_SAMPLE_BITS);
  846. regmap_update_bits(scodec->regmap, SUNXI_DAC_FIFOC, 1 << SUNXI_DAC_FIFOC_TX_FIFO_MODE, !is_24bit << SUNXI_DAC_FIFOC_TX_FIFO_MODE);
  847. if (is_24bit)
  848. scodec->playback_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
  849. else
  850. scodec->playback_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES;
  851. } else {
  852. regmap_update_bits(scodec->regmap, SUN6I_ADC_FIFOC, 7 << SUNXI_ADC_FIFOC_DAC_FS, hwrate << SUNXI_ADC_FIFOC_DAC_FS);
  853. regmap_update_bits(scodec->regmap, SUN6I_ADC_FIFOC, 1 << SUNXI_ADC_FIFOC_MONO_EN, is_mono << SUNXI_ADC_FIFOC_MONO_EN);
  854. }
  855.  
  856. return 0;
  857. }
  858.  
  859. /* EVEN IN sunxi-codec this isn't used */
  860. static const struct snd_kcontrol_new sun6i_dac_ctl_ctls[] = {
  861. /*SUN6I_DAC_ACTL = 0x20,PAVOL**/
  862. SOC_SINGLE("Master Playback Volume", SUN6I_DAC_ACTL,0,0x3f,0), /*0*/
  863. /*total output switch PAMUTE, if set this bit to 0, the voice is mute*/
  864. SOC_SINGLE("Playback LPAMUTE SWITCH", SUN6I_DAC_ACTL,6,0x1,0), /*1*/
  865. SOC_SINGLE("Playback RPAMUTE SWITCH", SUN6I_DAC_ACTL,7,0x1,0), /*2*/
  866. SOC_SINGLE("Left Headphone PA input src select", SUN6I_DAC_ACTL,8,0x1,0), /*3*/
  867. SOC_SINGLE("Right Headphone PA input src select", SUN6I_DAC_ACTL,9,0x1,0), /*4*/
  868. SOC_SINGLE("Left output mixer mute control", SUN6I_DAC_ACTL,10,0x7f,0), /*5*/
  869. SOC_SINGLE("Right output mixer mute control", SUN6I_DAC_ACTL,17,0x7f,0), /*6*/
  870. SOC_SINGLE("Left analog output mixer en", SUN6I_DAC_ACTL,28,0x1,0), /*7*/
  871. SOC_SINGLE("Right analog output mixer en", SUN6I_DAC_ACTL,29,0x1,0), /*8*/
  872. SOC_SINGLE("Inter DAC analog left channel en", SUN6I_DAC_ACTL,30,0x1,0), /*9*/
  873. SOC_SINGLE("Inter DAC analog right channel en", SUN6I_DAC_ACTL,31,0x1,0), /*10*/
  874. };
  875.  
  876. static int sun6i_codec_dai_probe(struct snd_soc_dai *dai)
  877. {
  878. struct snd_soc_card *card = snd_soc_dai_get_drvdata(dai);
  879. struct sun6i_codec *scodec = snd_soc_card_get_drvdata(card);
  880.  
  881. snd_soc_dai_init_dma_data(dai,
  882. &scodec->playback_dma_data,
  883. &scodec->capture_dma_data);
  884. return 0;
  885. }
  886.  
  887. static void sun6i_codec_init(struct sun6i_codec *scodec)
  888. {
  889. /*
  890. * Stop doing DMA requests whenever there's only 16 samples
  891. * left available in the TX FIFO.
  892. */
  893. regmap_update_bits(scodec->regmap, SUNXI_DAC_FIFOC,
  894. 0x3 << SUNXI_DAC_FIFOC_DRQ_CLR_CNT,
  895. 0x3 << SUNXI_DAC_FIFOC_DRQ_CLR_CNT);
  896.  
  897. /* Flush TX FIFO */
  898. regmap_update_bits(scodec->regmap, SUNXI_DAC_FIFOC,
  899. BIT(SUNXI_DAC_FIFOC_FIFO_FLUSH),
  900. BIT(SUNXI_DAC_FIFOC_FIFO_FLUSH));
  901.  
  902. /* Flush RX FIFO */
  903. regmap_update_bits(scodec->regmap, SUN6I_ADC_FIFOC,
  904. BIT(SUNXI_ADC_FIFOC_FIFO_FLUSH),
  905. BIT(SUNXI_ADC_FIFOC_FIFO_FLUSH));
  906.  
  907. /* Do DRQ whenever the FIFO is empty */
  908. regmap_update_bits(scodec->regmap, SUNXI_DAC_FIFOC,
  909. BIT(SUNXI_DAC_FIFOC_DAC_DRQ_EN),
  910. BIT(SUNXI_DAC_FIFOC_DAC_DRQ_EN));
  911.  
  912. /* /\* Use a 32 bits FIR *\/ */
  913. /* codec_wr_control(sun6i, SUNXI_DAC_FIFOC, 0x1, FIR_VERSION, 0x1); */
  914.  
  915. }
  916.  
  917. static int sun6i_codec_startup(struct snd_pcm_substream *substream,
  918. struct snd_soc_dai *dai)
  919. {
  920. struct snd_soc_pcm_runtime *rtd = substream->private_data;
  921. struct sun6i_codec *scodec = snd_soc_card_get_drvdata(rtd->card);
  922.  
  923. sun6i_codec_init(scodec);
  924.  
  925. clk_prepare_enable(scodec->clk_module);
  926.  
  927. return 0;
  928. }
  929.  
  930. static void sun6i_codec_shutdown(struct snd_pcm_substream *substream,
  931. struct snd_soc_dai *dai)
  932. {
  933. struct snd_soc_pcm_runtime *rtd = substream->private_data;
  934. struct sun6i_codec *scodec = snd_soc_card_get_drvdata(rtd->card);
  935.  
  936. clk_disable_unprepare(scodec->clk_module);
  937. }
  938.  
  939. /*** Codec DAI ***/
  940.  
  941. static const struct snd_soc_dai_ops sun6i_codec_dai_ops = {
  942. .startup = sun6i_codec_startup,
  943. .shutdown = sun6i_codec_shutdown,
  944. .set_fmt = sun6i_codec_set_fmt,
  945. .digital_mute = sun6i_codec_digital_mute,
  946. .prepare = sun6i_codec_prepare,
  947. .hw_params = sun6i_codec_hw_params,
  948. .trigger = sun6i_codec_trigger,
  949. };
  950.  
  951. #define SUN6I_RATES SNDRV_PCM_RATE_8000_192000
  952. #define SUN6I_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \
  953. SNDRV_PCM_FMTBIT_S24_LE)
  954. static struct snd_soc_dai_driver sun6i_codec_dai = {
  955. .name = "Codec",
  956. .playback = {
  957. .stream_name = "Codec Playback",
  958. .channels_min = 1,
  959. .channels_max = 2,
  960. .rate_min = 8000,
  961. .rate_max = 192000,
  962. .rates = SUN6I_RATES | SNDRV_PCM_RATE_KNOT,
  963. .formats = SUN6I_FORMATS,
  964. },
  965. /*
  966. .capture = {
  967. .stream_name = "Codec Capture",
  968. .channels_min = 1,
  969. .channels_max = 2,
  970. .rate_min = 8000,
  971. .rate_max = 192000,
  972. .rates = SUN6I_RATES | SNDRV_PCM_RATE_KNOT,
  973. .formats = SUN6I_FORMATS,
  974. },
  975. */ .ops = &sun6i_codec_dai_ops,
  976. };
  977.  
  978. /*** Codec ***/
  979.  
  980. static const char *sun6i_zero_crossover_time[] = {"32ms", "64ms"};
  981. static const struct soc_enum sun6i_zero_crossover_time_enum =
  982. SOC_ENUM_SINGLE(SUN6I_ADDAC_TUNE, 21, 2, sun6i_zero_crossover_time);
  983.  
  984. static const char *sun6i_fir_length[] = {"64 bits", "32 bits"};
  985. static const struct soc_enum sun6i_fir_length_enum =
  986. SOC_ENUM_SINGLE(SUNXI_DAC_FIFOC, 28, 2, sun6i_fir_length);
  987.  
  988. static const char *sun6i_left_hp_mux[] = {"Left DAC", "Left Output Mixer"};
  989. static const struct soc_enum sun6i_left_hp_mux_enum =
  990. SOC_ENUM_SINGLE(SUN6I_DAC_ACTL, SUN6I_DAC_ACTL_HPISL, 2, sun6i_left_hp_mux);
  991.  
  992. static const char *sun6i_right_hp_mux[] = {"Right DAC", "Right Output Mixer"};
  993. static const struct soc_enum sun6i_right_hp_mux_enum =
  994. SOC_ENUM_SINGLE(SUN6I_DAC_ACTL, SUN6I_DAC_ACTL_HPISR, 2, sun6i_right_hp_mux);
  995.  
  996. static const char *sun6i_left_lineout_mux[] = {"Left Output Mixer", "Left + Right Output Mixer"};
  997. static const struct soc_enum sun6i_left_lineout_mux_enum =
  998. SOC_ENUM_SINGLE(SUN6I_MIC_CTRL, SUN6I_MIC_CTRL_LINEOUTL_SRC_SEL, 2, sun6i_left_lineout_mux);
  999.  
  1000. static const char *sun6i_right_lineout_mux[] = {"Right Output Mixer", "Left Lineout"};
  1001. static const struct soc_enum sun6i_right_lineout_mux_enum =
  1002. SOC_ENUM_SINGLE(SUN6I_MIC_CTRL, SUN6I_MIC_CTRL_LINEOUTR_SRC_SEL, 2, sun6i_right_lineout_mux);
  1003.  
  1004. /* NOTE DB VALUE IS WRONG */
  1005. static DECLARE_TLV_DB_SCALE(sun6i_codec_digital_volume_scale, -6300, 100, 1);
  1006. static DECLARE_TLV_DB_SCALE(sun6i_codec_headphone_volume_scale, -6200, 100, 0);
  1007. static DECLARE_TLV_DB_SCALE(sun6i_codec_lineout_volume_scale, -4800, 150, 0);
  1008.  
  1009. static const struct snd_kcontrol_new sun6i_snd_controls[] = {
  1010. /* This is actually an attenuation by 64 steps of -1.16dB */
  1011. SOC_SINGLE_TLV("DAC Volume",
  1012. SUNXI_DAC_DPC, SUNXI_DAC_DPC_DVOL, 0x3f, 0,
  1013. sun6i_codec_digital_volume_scale),
  1014.  
  1015. SOC_SINGLE_TLV("Headphone Volume",
  1016. SUN6I_DAC_ACTL, SUN6I_DAC_ACTL_HPVOL, 0x3f, 0,
  1017. sun6i_codec_headphone_volume_scale),
  1018.  
  1019. SOC_SINGLE_TLV("Lineout Volume",
  1020. SUN6I_MIC_CTRL, SUN6I_MIC_CTRL_LINEOUT_VOL, 0x1f, 0,
  1021. sun6i_codec_lineout_volume_scale),
  1022. /* SOC_SINGLE("DAC High Pass Filter Switch",
  1023. SUNXI_DAC_DPC, 18, 1, 0),
  1024.  
  1025. SOC_SINGLE("Zero-crossover Switch",
  1026. SUN6I_ADDAC_TUNE, 22, 1, 0),
  1027.  
  1028. SOC_ENUM("Zero-crossover Time", sun6i_zero_crossover_time_enum),
  1029. SOC_ENUM("FIR Length", sun6i_fir_length_enum),
  1030. */
  1031. };
  1032.  
  1033. static const struct snd_kcontrol_new sun6i_left_output_mixer_controls[] = {
  1034. //SOC_DAPM_SINGLE("Right DAC Switch", SUN6I_DAC_ACTL, 10, 1, 0),
  1035. SOC_DAPM_SINGLE("Left DAC Switch", SUN6I_DAC_ACTL, SUN6I_DAC_ACTL_MIXMUTEL_DACL, 1, 0),
  1036. //SOC_DAPM_SINGLE("Left LineIn Switch", SUN6I_DAC_ACTL, 12, 1, 0),
  1037. //SOC_DAPM_SINGLE("Microphone 2 Boost Switch", SUN6I_DAC_ACTL, 15, 1, 0),
  1038. //SOC_DAPM_SINGLE("Microphone 1 Boost Switch", SUN6I_DAC_ACTL, 16, 1, 0),
  1039. };
  1040.  
  1041. static const struct snd_kcontrol_new sun6i_right_output_mixer_controls[] = {
  1042. //SOC_DAPM_SINGLE("Left DAC Switch", SUN6I_DAC_ACTL, 17, 1, 0),
  1043. SOC_DAPM_SINGLE("Right DAC Switch", SUN6I_DAC_ACTL, SUN6I_DAC_ACTL_MIXMUTER_DACR, 1, 0),
  1044. //SOC_DAPM_SINGLE("Right LineIn Switch", SUN6I_DAC_ACTL, 19, 1, 0),
  1045. //SOC_DAPM_SINGLE("Microphone 2 Boost Switch", SUN6I_DAC_ACTL, 22, 1, 0),
  1046. //SOC_DAPM_SINGLE("Microphone 1 Boost Switch", SUN6I_DAC_ACTL, 23, 1, 0),
  1047. };
  1048.  
  1049. static const struct snd_kcontrol_new sun6i_left_hp_mux_controls =
  1050. SOC_DAPM_ENUM("Left Headphone Amplifier Select", sun6i_left_hp_mux_enum);
  1051.  
  1052. static const struct snd_kcontrol_new sun6i_right_hp_mux_controls =
  1053. SOC_DAPM_ENUM("Right Headphone Amplifier Select", sun6i_right_hp_mux_enum);
  1054.  
  1055. static const struct snd_kcontrol_new sun6i_left_lineout_mux_controls =
  1056. SOC_DAPM_ENUM("Left Lineout Amplifier Select", sun6i_left_lineout_mux_enum);
  1057.  
  1058. static const struct snd_kcontrol_new sun6i_right_lineout_mux_controls =
  1059. SOC_DAPM_ENUM("Right Lineout Amplifier Select", sun6i_right_lineout_mux_enum);
  1060.  
  1061. static const struct snd_soc_dapm_widget sun6i_dapm_widgets[] = {
  1062. /* Digital controls of the DACs */
  1063. SND_SOC_DAPM_SUPPLY("DAC", SUNXI_DAC_DPC, SUNXI_DAC_DPC_EN_DA, 0, NULL, 0),
  1064.  
  1065. /* Analog parts of the DACs */
  1066. SND_SOC_DAPM_DAC("Left DAC", "Codec Playback", SUN6I_DAC_ACTL, SUNXI_DAC_ACTL_DACAENL, 0),
  1067. SND_SOC_DAPM_DAC("Right DAC", "Codec Playback", SUN6I_DAC_ACTL, SUNXI_DAC_ACTL_DACAENR, 0),
  1068.  
  1069. /* Power up of the Headphone amplifier */
  1070. SND_SOC_DAPM_PGA("Headphone Amplifier",
  1071. SUN6I_PA_CTRL, SUN6I_PA_CTRL_HPPAEN, 0, NULL, 0),
  1072.  
  1073. /* Mutes of both channels coming to the headphone amplifier */
  1074. SND_SOC_DAPM_PGA("Left Headphone Amplifier",
  1075. SUN6I_DAC_ACTL, SUN6I_DAC_ACTL_HPPAMUTEL, 0, NULL, 0),
  1076. SND_SOC_DAPM_PGA("Right Headphone Amplifier",
  1077. SUN6I_DAC_ACTL, SUN6I_DAC_ACTL_HPPAMUTER, 0, NULL, 0),
  1078.  
  1079. /* Mutes of both channels coming to the lineout amplifier */
  1080. SND_SOC_DAPM_PGA("Left Lineout Amplifier",
  1081. SUN6I_MIC_CTRL, SUN6I_MIC_CTRL_LINEOUTL_EN, 0, NULL, 0),
  1082. SND_SOC_DAPM_PGA("Right Lineout Amplifier",
  1083. SUN6I_MIC_CTRL, SUN6I_MIC_CTRL_LINEOUTR_EN, 0, NULL, 0),
  1084.  
  1085. /* Mixers */
  1086. SND_SOC_DAPM_MIXER("Left Mixer Output", SUN6I_DAC_ACTL, 28, 0,
  1087. sun6i_left_output_mixer_controls,
  1088. ARRAY_SIZE(sun6i_left_output_mixer_controls)),
  1089. SND_SOC_DAPM_MIXER("Right Mixer Output", SUN6I_DAC_ACTL, 29, 0,
  1090. sun6i_right_output_mixer_controls,
  1091. ARRAY_SIZE(sun6i_right_output_mixer_controls)),
  1092.  
  1093. /* Global Mixer Enable */
  1094. SND_SOC_DAPM_SUPPLY("Left Mixer Enable", SUN6I_DAC_ACTL,
  1095. SUN6I_DAC_ACTL_MIXENL, 0, NULL, 0),
  1096. SND_SOC_DAPM_SUPPLY("Right Mixer Enable", SUN6I_DAC_ACTL,
  1097. SUN6I_DAC_ACTL_MIXENR, 0, NULL, 0),
  1098.  
  1099. SND_SOC_DAPM_MUX("Left Headphone Amplifier Mux", SND_SOC_NOPM, 0, 0,
  1100. &sun6i_left_hp_mux_controls),
  1101. SND_SOC_DAPM_MUX("Right Headphone Amplifier Mux", SND_SOC_NOPM, 0, 0,
  1102. &sun6i_right_hp_mux_controls),
  1103.  
  1104. SND_SOC_DAPM_MUX("Left Lineout Amplifier Mux", SND_SOC_NOPM, 0, 0,
  1105. &sun6i_left_lineout_mux_controls),
  1106. SND_SOC_DAPM_MUX("Right Lineout Amplifier Mux", SND_SOC_NOPM, 0, 0,
  1107. &sun6i_right_lineout_mux_controls),
  1108.  
  1109. SND_SOC_DAPM_OUTPUT("HP Left"),
  1110. SND_SOC_DAPM_OUTPUT("HP Right"),
  1111. SND_SOC_DAPM_OUTPUT("Lineout Left"),
  1112. SND_SOC_DAPM_OUTPUT("Lineout Right"),
  1113. };
  1114.  
  1115. static const struct snd_soc_dapm_route sun6i_dapm_routes[] = {
  1116. /* DACs */
  1117. { "Left DAC", NULL, "DAC" },
  1118. { "Right DAC", NULL, "DAC" },
  1119.  
  1120. /* Left Mixer */
  1121. { "Left Mixer", NULL, "Left Mixer Enable" },
  1122. { "Left Mixer", NULL, "Left DAC" },/* sun4i has switch here */
  1123. { "Left Mixer", NULL, "Right DAC" },/* sun4i has switch here */
  1124.  
  1125. /* Right Mixer */
  1126. { "Right Mixer", NULL, "Right Mixer Enable" },
  1127. { "Right Mixer", NULL, "Left DAC" },/* sun4i has switch here */
  1128. { "Right Mixer", NULL, "Right DAC" },/* sun4i has switch here */
  1129.  
  1130. /* Left Output Mixer */
  1131. { "Left Output Mixer", NULL, "Left Mixer" },
  1132.  
  1133. /* Right Output Mixer */
  1134. { "Right Output Mixer", NULL, "Right Mixer" },
  1135.  
  1136. /* Left HP Mux */
  1137. { "Left Headphone Amplifier Mux", NULL, "Left Output Mixer" },
  1138. { "Left Headphone Amplifier Mux", NULL, "Left DAC" },
  1139.  
  1140. /* Right HP Mux */
  1141. { "Right Headphone Amplifier Mux", NULL, "Right Output Mixer" },
  1142. { "Right Headphone Amplifier Mux", NULL, "Right DAC" },
  1143.  
  1144. /* Left HP Amplifier */
  1145. { "Headphone Amplifier", NULL, "Left Headphone Amplifier Mux" },
  1146.  
  1147. /* Right HP Amplifier */
  1148. { "Headphone Amplifier", NULL, "Right Headphone Amplifier Mux" },
  1149.  
  1150. /* Left Lineout Mux */
  1151. { "Left Lineout Amplifier Mux", NULL, "Left Output Mixer" },
  1152. { "Left Lineout Amplifier Mux", NULL, "Left + Right Output Mixer" },
  1153.  
  1154. /* Right Lineout Mux */
  1155. { "Right Lineout Amplifier Mux", NULL, "Right Output Mixer" },
  1156. { "Right Lineout Amplifier Mux", NULL, "Lineout Left" },
  1157.  
  1158. /* Left Lineout Amplifier */
  1159. { "Left Lineout Amplifier", NULL, "Left Lineout Amplifier Mux" },
  1160.  
  1161. /* Right Lineout Amplifier */
  1162. { "Right Lineout Amplifier", NULL, "Right Lineout Amplifier Mux" },
  1163.  
  1164. /* Power up the headphone amplifiers */
  1165. { "Left Headphone Amplifier", NULL, "Headphone Amplifier" },
  1166. { "Right Headphone Amplifier", NULL, "Headphone Amplifier" },
  1167.  
  1168. /* Headphone outputs */
  1169. { "HP Left", NULL, "Left Headphone Amplifier" },
  1170. { "HP Right", NULL, "Right Headphone Amplifier" },
  1171.  
  1172. /* Lineout outputs */
  1173. { "Lineout Left", NULL, "Left Lineout Amplifier" },
  1174. { "Lineout Right", NULL, "Right Lineout Amplifier" },
  1175. };
  1176.  
  1177. static struct snd_soc_codec_driver sun6i_codec_codec = {
  1178.  
  1179. .controls = sun6i_snd_controls,
  1180. .num_controls = ARRAY_SIZE(sun6i_snd_controls),
  1181. .dapm_widgets = sun6i_dapm_widgets,
  1182. .num_dapm_widgets = ARRAY_SIZE(sun6i_dapm_widgets),
  1183. .dapm_routes = sun6i_dapm_routes,
  1184. .num_dapm_routes = ARRAY_SIZE(sun6i_dapm_routes),
  1185. };
  1186.  
  1187. /*** Board routing ***/
  1188. /* TODO: do this with DT */
  1189.  
  1190. static const struct snd_soc_dapm_widget sun6i_board_dapm_widgets[] = {
  1191. SND_SOC_DAPM_HP("Headphone Jack", NULL),
  1192. };
  1193.  
  1194. static const struct snd_soc_dapm_route sun6i_board_routing[] = {
  1195. { "Headphone Jack", NULL, "HPL" },
  1196. { "Headphone Jack", NULL, "HPR" },
  1197. };
  1198.  
  1199. static int sun6i_dai_init(struct snd_soc_pcm_runtime *rtd)
  1200. {
  1201. struct snd_soc_codec *codec = rtd->codec;
  1202. struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec);
  1203.  
  1204. snd_soc_dapm_enable_pin(dapm, "Headphone Jack");
  1205.  
  1206. return 0;
  1207. }
  1208.  
  1209. /*** Card and DAI Link ***/
  1210.  
  1211. static struct snd_soc_dai_link sun6i_card_dai[] = {
  1212. {
  1213. .name = "sun6i-audio",
  1214. .stream_name = "CDC PCM",
  1215. .codec_dai_name = "Codec",
  1216. .cpu_dai_name = "1c22c00.codec",
  1217. .codec_name = "1c22c00.codec",
  1218. .platform_name = "1c22c00.codec",
  1219. .dai_fmt = SND_SOC_DAIFMT_I2S,
  1220. .init = sun6i_dai_init,
  1221. },
  1222. };
  1223.  
  1224. static struct snd_soc_card snd_soc_sun6i_codec = {
  1225. .name = "sun6i-codec",
  1226. .owner = THIS_MODULE,
  1227.  
  1228. .dai_link = &sun6i_card_dai,
  1229. .num_links = ARRAY_SIZE(sun6i_card_dai),
  1230.  
  1231. .dapm_widgets = sun6i_board_dapm_widgets,
  1232. .num_dapm_widgets = ARRAY_SIZE(sun6i_board_dapm_widgets),
  1233. .dapm_routes = sun6i_board_routing,
  1234. .num_dapm_routes = ARRAY_SIZE(sun6i_board_routing),
  1235. };
  1236.  
  1237. /*** CPU DAI ***/
  1238.  
  1239. static const struct snd_soc_component_driver sun6i_codec_component = {
  1240. .name = "sun6i-codec",
  1241. };
  1242.  
  1243. static struct snd_soc_dai_driver dummy_cpu_dai = {
  1244. .name = "sun6i-cpu-dai",
  1245. .probe = sun6i_codec_dai_probe,
  1246. .playback = {
  1247. .channels_min = 1,
  1248. .channels_max = 2,
  1249. .rates = SUN6I_RATES,
  1250. .formats = SUN6I_FORMATS,
  1251. .sig_bits = 24,
  1252. },
  1253.  
  1254. .capture = {
  1255. .channels_min = 1,
  1256. .channels_max = 2,
  1257. .rates = SUN6I_RATES,
  1258. .formats = SUN6I_FORMATS,
  1259. .sig_bits = 24,
  1260. },
  1261. };
  1262.  
  1263. static struct regmap_config sun6i_codec_regmap_config = {
  1264. .reg_bits = 32,
  1265. .reg_stride = 4,
  1266. .val_bits = 32,
  1267. .max_register = SUN6I_ADC_DAP_HPFC,
  1268. };
  1269.  
  1270. static const struct of_device_id sun6i_codec_of_match[] = {
  1271. { .compatible = "allwinner,sun6i-a31-codec" },
  1272. {}
  1273. };
  1274. MODULE_DEVICE_TABLE(of, sun6i_codec_of_match);
  1275.  
  1276. static int sun6i_codec_spk_event(struct snd_soc_dapm_widget *w,
  1277. struct snd_kcontrol *k, int event)
  1278. {
  1279. struct sun6i_codec *scodec = snd_soc_card_get_drvdata(w->dapm->card);
  1280.  
  1281. if (scodec->gpio_pa)
  1282. gpiod_set_value_cansleep(scodec->gpio_pa,
  1283. !!SND_SOC_DAPM_EVENT_ON(event));
  1284.  
  1285. return 0;
  1286. }
  1287.  
  1288. static const struct snd_soc_dapm_widget sun6i_codec_card_dapm_widgets[] = {
  1289. SND_SOC_DAPM_SPK("Speaker", sun6i_codec_spk_event),
  1290. };
  1291.  
  1292. static const struct snd_soc_dapm_route sun6i_codec_card_dapm_routes[] = {
  1293. { "Speaker", NULL, "HP Right" },
  1294. { "Speaker", NULL, "HP Left" },
  1295. };
  1296.  
  1297. static struct snd_soc_dai_link *sun6i_codec_create_link(struct device *dev,
  1298. int *num_links)
  1299. {
  1300. struct snd_soc_dai_link *link = devm_kzalloc(dev, sizeof(*link),
  1301. GFP_KERNEL);
  1302. if (!link)
  1303. return NULL;
  1304.  
  1305. link->name = "cdc";
  1306. link->stream_name = "CDC PCM";
  1307. link->codec_dai_name = "Codec";
  1308. link->cpu_dai_name = dev_name(dev);
  1309. link->codec_name = dev_name(dev);
  1310. link->platform_name = dev_name(dev);
  1311. link->dai_fmt = SND_SOC_DAIFMT_I2S;
  1312.  
  1313. *num_links = 1;
  1314.  
  1315. return link;
  1316. };
  1317.  
  1318. static struct snd_soc_card *sun6i_codec_create_card(struct device *dev)
  1319. {
  1320. struct snd_soc_card *card;
  1321.  
  1322. card = devm_kzalloc(dev, sizeof(*card), GFP_KERNEL);
  1323. if (!card)
  1324. return NULL;
  1325.  
  1326. card->dai_link = sun6i_codec_create_link(dev, &card->num_links);
  1327. if (!card->dai_link)
  1328. return NULL;
  1329.  
  1330. card->dev = dev;
  1331. card->name = "sun6i-codec";
  1332. card->dapm_widgets = sun6i_codec_card_dapm_widgets;
  1333. card->num_dapm_widgets = ARRAY_SIZE(sun6i_codec_card_dapm_widgets);
  1334. card->dapm_routes = sun6i_codec_card_dapm_routes;
  1335. card->num_dapm_routes = ARRAY_SIZE(sun6i_codec_card_dapm_routes);
  1336.  
  1337. return card;
  1338. };
  1339.  
  1340. static int sun6i_codec_probe(struct platform_device *pdev)
  1341. {
  1342. struct snd_soc_card *card;
  1343. struct sun6i_codec *scodec;
  1344. struct resource *res;
  1345. void __iomem *base;
  1346. int ret;
  1347.  
  1348. scodec = devm_kzalloc(&pdev->dev, sizeof(*scodec), GFP_KERNEL);
  1349. if (!scodec)
  1350. return -ENOMEM;
  1351.  
  1352. scodec->pdev = &pdev->dev;
  1353.  
  1354. res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
  1355. base = devm_ioremap_resource(&pdev->dev, res);
  1356. if (IS_ERR(base)) {
  1357. dev_err(&pdev->dev, "Failed to map the registers\n");
  1358. return PTR_ERR(base);
  1359. }
  1360.  
  1361. scodec->regmap = devm_regmap_init_mmio(&pdev->dev, base,
  1362. &sun6i_codec_regmap_config);
  1363. if (IS_ERR(scodec->regmap)) {
  1364. dev_err(&pdev->dev, "Failed to create our regmap\n");
  1365. return PTR_ERR(scodec->regmap);
  1366. }
  1367.  
  1368. /* Get the clocks from the DT */
  1369. scodec->clk_apb = devm_clk_get(&pdev->dev, "apb");
  1370. if (IS_ERR(scodec->clk_apb)) {
  1371. dev_err(&pdev->dev, "failed to get apb clock\n");
  1372. return PTR_ERR(scodec->clk_apb);
  1373. }
  1374.  
  1375. scodec->clk_module = devm_clk_get(&pdev->dev, "codec");
  1376. if (IS_ERR(scodec->clk_module)) {
  1377. dev_err(&pdev->dev, "failed to get codec clock\n");
  1378. return PTR_ERR(scodec->clk_module);
  1379. }
  1380.  
  1381. /* Enable the bus clock */
  1382. if (clk_prepare_enable(scodec->clk_apb)) {
  1383. dev_err(&pdev->dev, "failed to enable apb clock\n");
  1384. clk_disable_unprepare(scodec->clk_module);
  1385. return -EINVAL;
  1386. }
  1387.  
  1388. scodec->gpio_pa = devm_gpiod_get_optional(&pdev->dev, "allwinner,pa",
  1389. GPIOD_OUT_LOW);
  1390. if (IS_ERR(scodec->gpio_pa)) {
  1391. ret = PTR_ERR(scodec->gpio_pa);
  1392. if (ret != -EPROBE_DEFER)
  1393. dev_err(&pdev->dev, "Failed to get pa gpio: %d\n", ret);
  1394. return ret;
  1395. }
  1396.  
  1397. /* DMA configuration for TX FIFO */
  1398. scodec->playback_dma_data.addr = res->start + SUNXI_DAC_TXDATA;
  1399. scodec->playback_dma_data.maxburst = 4;
  1400. scodec->playback_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES;
  1401.  
  1402. /* DMA configuration for RX FIFO */
  1403. scodec->capture_dma_data.addr = res->start + SUN6I_ADC_RXDATA;
  1404. scodec->capture_dma_data.maxburst = 4;
  1405. scodec->capture_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES;
  1406.  
  1407. scodec->rst = devm_reset_control_get_optional(&pdev->dev, NULL);
  1408. if (IS_ERR(scodec->rst) && PTR_ERR(scodec->rst) == -EPROBE_DEFER) {
  1409. ret = -EPROBE_DEFER;
  1410. dev_err(&pdev->dev, "Failed to get audio codec reset: %d\n", ret);
  1411. goto err_clk_disable;
  1412. }
  1413.  
  1414. if (!IS_ERR(scodec->rst))
  1415. reset_control_deassert(scodec->rst);
  1416.  
  1417. ret = snd_soc_register_codec(&pdev->dev, &sun6i_codec_codec, &sun6i_codec_dai, 1);
  1418.  
  1419. ret = devm_snd_soc_register_component(&pdev->dev, &sun6i_codec_component, &dummy_cpu_dai, 1);
  1420. if (ret)
  1421. goto err_clk_disable;
  1422.  
  1423. ret = devm_snd_dmaengine_pcm_register(&pdev->dev, NULL, 0);
  1424. if (ret)
  1425. goto err_clk_disable;
  1426.  
  1427. //sun6i_codec_init(scodec);
  1428.  
  1429. card = sun6i_codec_create_card(&pdev->dev);
  1430. if (!card) {
  1431. dev_err(&pdev->dev, "Failed to create our card\n");
  1432. goto err;
  1433. }
  1434.  
  1435. platform_set_drvdata(pdev, card);
  1436. snd_soc_card_set_drvdata(card, scodec);
  1437.  
  1438. ret = snd_soc_register_card(card);
  1439. if (ret) {
  1440. dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n", ret);
  1441. goto err_fini_utils;
  1442. }
  1443.  
  1444. return 0;
  1445.  
  1446. err_fini_utils:
  1447. err:
  1448. err_clk_disable:
  1449. clk_disable_unprepare(scodec->clk_apb);
  1450. return ret;
  1451. }
  1452.  
  1453. static int sun6i_codec_remove(struct platform_device *pdev)
  1454. {
  1455. struct sun6i_codec *scodec = platform_get_drvdata(pdev);
  1456.  
  1457. clk_disable_unprepare(scodec->clk_apb);
  1458. clk_disable_unprepare(scodec->clk_module);
  1459.  
  1460. return 0;
  1461. }
  1462.  
  1463. static struct platform_driver sun6i_codec_driver = {
  1464. .driver = {
  1465. .name = "sun6i-codec",
  1466. .owner = THIS_MODULE,
  1467. .of_match_table = sun6i_codec_of_match,
  1468. },
  1469. .probe = sun6i_codec_probe,
  1470. .remove = sun6i_codec_remove,
  1471. };
  1472. module_platform_driver(sun6i_codec_driver);
  1473.  
  1474. MODULE_DESCRIPTION("sun6i CODEC ALSA codec driver");
  1475. MODULE_AUTHOR("huangxin");
  1476. MODULE_LICENSE("GPL");
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement