aml_m1_codec.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510
  1. #include <linux/module.h>
  2. #include <linux/moduleparam.h>
  3. #include <linux/init.h>
  4. #include <linux/delay.h>
  5. #include <linux/pm.h>
  6. #include <linux/i2c.h>
  7. #include <linux/slab.h>
  8. #include <linux/platform_device.h>
  9. #include <linux/regulator/consumer.h>
  10. #include <linux/spi/spi.h>
  11. #include <sound/core.h>
  12. #include <sound/pcm.h>
  13. #include <sound/pcm_params.h>
  14. #include <sound/soc.h>
  15. #include <sound/soc-dapm.h>
  16. #include <sound/initval.h>
  17. #include <sound/tlv.h>
  18. #include <mach/am_regs.h>
  19. #include "aml_audio_hw.h"
  20. #define APB_BASE 0x5000
  21. #define ADAC_RESET 0x00
  22. #define ADAC_LATCH 0x01
  23. #define ADAC_CLOCK 0x02
  24. // 0x03-0x0b reserved
  25. #define ADAC_I2S_CONFIG_REG1 0x0c
  26. #define ADAC_I2S_CONFIG_REG2 0x0d
  27. // 0x0e - 0x0f reserved
  28. #define ADAC_POWER_CTRL_REG1 0x10
  29. #define ADAC_POWER_CTRL_REG2 0x11
  30. #define ADAC_POWER_CTRL_REG3 0x12
  31. // 0x13-0x17 reserved
  32. #define ADAC_MUTE_CTRL_REG1 0x18
  33. #define ADAC_MUTE_CTRL_REG2 0x19
  34. #define ADAC_DAC_ADC_MIXER 0x1a
  35. // 0x1b-0x1f reserved
  36. #define ADAC_PLAYBACK_VOL_CTRL_LSB 0x20
  37. #define ADAC_PLAYBACK_VOL_CTRL_MSB 0x21
  38. #define ADAC_STEREO_HS_VOL_CTRL_LSB 0x22
  39. #define ADAC_STEREO_HS_VOL_CTRL_MSB 0x23
  40. #define ADAC_MAXREG 0x24
  41. struct snd_soc_codec_device soc_codec_dev_aml_m1;
  42. static struct snd_soc_codec *aml_m1_codec;
  43. /* codec private data */
  44. struct aml_m1_codec_priv {
  45. struct snd_soc_codec codec;
  46. u16 reg_cache[ADAC_MAXREG];
  47. unsigned int sysclk;
  48. };
  49. void latch (struct snd_soc_codec* codec)
  50. {
  51. int latch;
  52. latch = 1;
  53. snd_soc_write(codec, ADAC_LATCH, latch);
  54. latch = 0;
  55. snd_soc_write(codec, ADAC_LATCH, latch);
  56. }
  57. void aml_m1_reset(struct snd_soc_codec* codec, bool first_time)
  58. {
  59. unsigned long data32;
  60. if(first_time){
  61. /* initialize clock for audiodac */
  62. audio_set_clk(AUDIO_CLK_FREQ_48,0);
  63. /* power up pll */
  64. WRITE_MPEG_REG( HHI_AUD_PLL_CNTL, READ_MPEG_REG(HHI_AUD_PLL_CNTL) & ~(1 << 15));
  65. /* enable audiodac clock */
  66. WRITE_MPEG_REG_BITS(HHI_AUD_CLK_CNTL, 1, 23, 1);
  67. msleep(100);
  68. data32 = 0;
  69. data32 |= 0 << 15; // [15] audac_soft_reset_n
  70. data32 |= 0 << 14; // [14] audac_reset_ctrl: 0=use audac_reset_n pulse from reset module; 1=use audac_soft_reset_n.
  71. data32 |= 0 << 9; // [9] delay_rd_en
  72. data32 |= 0 << 8; // [8] audac_reg_clk_inv
  73. data32 |= 0 << 1; // [7:1] audac_i2caddr
  74. data32 |= 0 << 0; // [0] audac_intfsel: 0=use host bus; 1=use I2C.
  75. WRITE_MPEG_REG(AIU_AUDAC_CTRL0, data32);
  76. // Enable APB3 fail on error
  77. data32 = 0;
  78. data32 |= 1 << 15; // [15] err_en
  79. data32 |= 255 << 0; // [11:0] max_err
  80. WRITE_MPEG_REG(AIU_AUDAC_CTRL1, data32);
  81. snd_soc_write(codec, ADAC_RESET, (0<<1));
  82. snd_soc_write(codec, ADAC_RESET, (0<<1));
  83. snd_soc_write(codec, ADAC_RESET, (0<<1));
  84. snd_soc_write(codec, ADAC_RESET, (0<<1));
  85. snd_soc_write(codec, ADAC_RESET, (0<<1));
  86. msleep(100);
  87. snd_soc_write(codec,ADAC_CLOCK, 0);
  88. snd_soc_write(codec,ADAC_I2S_CONFIG_REG1, 6);
  89. snd_soc_write(codec, ADAC_I2S_CONFIG_REG2, 1|(1<<3)); // I2S, split
  90. snd_soc_write(codec, ADAC_POWER_CTRL_REG1, 0xc3);
  91. snd_soc_write(codec, ADAC_POWER_CTRL_REG2, 0);
  92. snd_soc_write(codec, ADAC_MUTE_CTRL_REG1,0);
  93. snd_soc_write(codec,ADAC_DAC_ADC_MIXER, 0);
  94. snd_soc_write(codec,ADAC_PLAYBACK_VOL_CTRL_LSB, 0x54);
  95. snd_soc_write(codec,ADAC_PLAYBACK_VOL_CTRL_MSB, 0x54);
  96. snd_soc_write(codec,ADAC_STEREO_HS_VOL_CTRL_LSB, 0x28);
  97. snd_soc_write(codec,ADAC_STEREO_HS_VOL_CTRL_MSB, 0x28);
  98. latch(codec);
  99. snd_soc_write(codec, ADAC_POWER_CTRL_REG2, (0<<7));
  100. latch(codec);
  101. snd_soc_write(codec, ADAC_POWER_CTRL_REG2, (1<<7));
  102. latch(codec);
  103. }else{
  104. latch(codec);
  105. snd_soc_write(codec, ADAC_POWER_CTRL_REG2, (0<<7));
  106. latch(codec);
  107. snd_soc_write(codec, ADAC_POWER_CTRL_REG2, (1<<7));
  108. latch(codec);
  109. }
  110. snd_soc_write(codec, ADAC_RESET, (0<<1));
  111. latch(codec);
  112. snd_soc_write(codec, ADAC_RESET, (1<<1));
  113. latch(codec);
  114. msleep(100);
  115. }
  116. static const DECLARE_TLV_DB_SCALE(dac_volume, -12600, 150, 0);
  117. static const DECLARE_TLV_DB_SCALE(hs_volume, -4000, 100, 0);
  118. static const struct snd_kcontrol_new amlm1_snd_controls[] = {
  119. SOC_DOUBLE_R_TLV("Master Playback Volume", ADAC_PLAYBACK_VOL_CTRL_LSB, ADAC_PLAYBACK_VOL_CTRL_MSB,
  120. 0, 84, 0, dac_volume),
  121. SOC_DOUBLE_R_TLV("HeadSet Driver Volume", ADAC_STEREO_HS_VOL_CTRL_LSB, ADAC_STEREO_HS_VOL_CTRL_MSB,
  122. 0, 46, 0, hs_volume),
  123. SOC_DOUBLE("Loud Speaker Mute", ADAC_MUTE_CTRL_REG1, 0, 1, 1, 0),
  124. SOC_DOUBLE("Head Set Mute", ADAC_MUTE_CTRL_REG1, 6, 7, 1, 0),
  125. };
  126. static const struct snd_soc_dapm_widget amlm1_dapm_widgets[] = {
  127. SND_SOC_DAPM_OUTPUT("LINEOUTL"),
  128. SND_SOC_DAPM_OUTPUT("LINEOUTR"),
  129. SND_SOC_DAPM_OUTPUT("HP_L"),
  130. SND_SOC_DAPM_OUTPUT("HP_R"),
  131. SND_SOC_DAPM_DAC("DACL", "Left DAC Playback", ADAC_POWER_CTRL_REG1, 0, 0),
  132. SND_SOC_DAPM_DAC("DACR", "Right DAC Playback", ADAC_POWER_CTRL_REG1, 1, 0),
  133. SND_SOC_DAPM_PGA("HeadSet Switch Left", ADAC_POWER_CTRL_REG1, 4, 0, NULL, 0),
  134. SND_SOC_DAPM_PGA("HeadSet Switch Right", ADAC_POWER_CTRL_REG1, 5, 0, NULL, 0),
  135. };
  136. /* Target, Path, Source */
  137. static const struct snd_soc_dapm_route audio_map[] = {
  138. {"LINEOUTL", NULL, "DACL"},
  139. {"LINEOUTR", NULL, "DACR"},
  140. {"HP_L", NULL, "HeadSet Switch Left"},
  141. {"HP_R", NULL, "HeadSet Switch Right"},
  142. {"HeadSet Switch Left", NULL, "DACL"},
  143. {"HeadSet Switch Right", NULL, "DACR"},
  144. };
  145. static int amlm1_add_widgets(struct snd_soc_codec *codec)
  146. {
  147. snd_soc_dapm_new_controls(codec, amlm1_dapm_widgets,
  148. ARRAY_SIZE(amlm1_dapm_widgets));
  149. snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map));
  150. return 0;
  151. }
  152. static int aml_m1_volatile_register(unsigned int reg)
  153. {
  154. return 0;
  155. }
  156. static int aml_m1_write(struct snd_soc_codec *codec, unsigned int reg,
  157. unsigned int value)
  158. {
  159. u16 *reg_cache = codec->reg_cache;
  160. if (reg >= codec->reg_cache_size)
  161. return -EINVAL;
  162. WRITE_APB_REG((APB_BASE+(reg<<2)), value);
  163. reg_cache[reg] = value;
  164. return 0;
  165. }
  166. static unsigned int aml_m1_read(struct snd_soc_codec *codec,
  167. unsigned int reg)
  168. {
  169. return READ_APB_REG(APB_BASE+(reg<<2));
  170. }
  171. static int aml_m1_codec_hw_params(struct snd_pcm_substream *substream,
  172. struct snd_pcm_hw_params *params,
  173. struct snd_soc_dai *dai)
  174. {
  175. struct snd_soc_pcm_runtime *rtd = substream->private_data;
  176. struct snd_soc_device *socdev = rtd->socdev;
  177. struct snd_soc_codec *codec = socdev->card->codec;
  178. //struct aml_m1_codec_priv *aml = codec->private_data;
  179. u16 reg, val;
  180. switch(params_rate(params)){
  181. case 8000: val=0; break;
  182. case 11025: val=1; break;
  183. case 12000: val=2; break;
  184. case 16000: val=3; break;
  185. case 22050: val=4; break;
  186. case 24000: val=5; break;
  187. case 32000: val=6; break;
  188. case 44100: val=7; break;
  189. case 48000: val=8; break;
  190. case 88200: val=9; break;
  191. case 96000: val=10; break;
  192. case 19200: val=11; break;
  193. default: val=8; break;
  194. }
  195. reg = snd_soc_read(codec, ADAC_I2S_CONFIG_REG1);
  196. reg &= ~0xf;
  197. reg |= val;
  198. snd_soc_write(codec, ADAC_I2S_CONFIG_REG1, reg);
  199. snd_soc_write(codec, ADAC_RESET, (0<<1));
  200. latch(codec);
  201. snd_soc_write(codec, ADAC_RESET, (1<<1));
  202. latch(codec);
  203. return 0;
  204. }
  205. static int aml_m1_codec_mute(struct snd_soc_dai *dai, int mute)
  206. {
  207. struct snd_soc_codec *codec = dai->codec;
  208. u16 reg;
  209. reg = snd_soc_read(codec, ADAC_MUTE_CTRL_REG1);
  210. if(mute){
  211. reg |= 3|(3<<6); /* mute hs and ls*/
  212. }
  213. else{
  214. reg &= ~(3|(3<<6));
  215. }
  216. snd_soc_write(codec, ADAC_MUTE_CTRL_REG1, reg);
  217. snd_soc_write(codec, ADAC_RESET, (0<<1));
  218. latch(codec);
  219. snd_soc_write(codec, ADAC_RESET, (1<<1));
  220. latch(codec);
  221. return 0;
  222. }
  223. #define AML_RATES SNDRV_PCM_RATE_8000_96000
  224. #define AML_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \
  225. SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
  226. static struct snd_soc_dai_ops aml_m1_codec_dai_ops = {
  227. .hw_params = aml_m1_codec_hw_params,
  228. .digital_mute = aml_m1_codec_mute,
  229. };
  230. struct snd_soc_dai aml_m1_codec_dai = {
  231. .name = "AML-M1",
  232. .playback = {
  233. .stream_name = "Playback",
  234. .channels_min = 1,
  235. .channels_max = 2,
  236. .rates = AML_RATES,
  237. .formats = AML_FORMATS,},
  238. .capture = {
  239. .stream_name = "Capture",
  240. .channels_min = 1,
  241. .channels_max = 2,
  242. .rates = AML_RATES,
  243. .formats = AML_FORMATS,},
  244. .ops = &aml_m1_codec_dai_ops,
  245. .symmetric_rates = 1,
  246. };
  247. EXPORT_SYMBOL_GPL(aml_m1_codec_dai);
  248. static int aml_m1_set_bias_level(struct snd_soc_codec *codec,
  249. enum snd_soc_bias_level level)
  250. {
  251. switch (level) {
  252. case SND_SOC_BIAS_ON:
  253. aml_m1_reset(codec, false);
  254. break;
  255. case SND_SOC_BIAS_PREPARE:
  256. break;
  257. case SND_SOC_BIAS_STANDBY:
  258. case SND_SOC_BIAS_OFF:
  259. snd_soc_write(codec, ADAC_POWER_CTRL_REG2, 0<<7);
  260. snd_soc_write(codec, ADAC_POWER_CTRL_REG2, 0<<7);
  261. break;
  262. default:
  263. break;
  264. }
  265. codec->bias_level = level;
  266. return 0;
  267. }
  268. static int aml_m1_codec_probe(struct platform_device *pdev)
  269. {
  270. struct snd_soc_device *socdev = platform_get_drvdata(pdev);
  271. struct snd_soc_codec *codec;
  272. int ret = 0;
  273. if (!aml_m1_codec) {
  274. dev_err(&pdev->dev, "AML_M1_CODEC not yet discovered\n");
  275. return -ENODEV;
  276. }
  277. codec = aml_m1_codec;
  278. socdev->card->codec = codec;
  279. /* register pcms */
  280. ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
  281. if (ret < 0) {
  282. kfree(codec);
  283. dev_err(codec->dev, "aml m1 codec: failed to create pcms: %d\n", ret);
  284. goto pcm_err;
  285. }
  286. snd_soc_add_controls(codec, amlm1_snd_controls,
  287. ARRAY_SIZE(amlm1_snd_controls));
  288. amlm1_add_widgets(codec);
  289. pcm_err:
  290. return 0;
  291. }
  292. static int aml_m1_codec_remove(struct platform_device *pdev)
  293. {
  294. struct snd_soc_device *socdev = platform_get_drvdata(pdev);
  295. // struct snd_soc_codec *codec = socdev->card->codec;
  296. snd_soc_free_pcms(socdev);
  297. snd_soc_dapm_free(socdev);
  298. return 0;
  299. }
  300. #ifdef CONFIG_PM
  301. static int aml_m1_codec_suspend(struct platform_device* pdev)
  302. {
  303. if (!aml_m1_codec) {
  304. dev_err(&pdev->dev, "AML_M1_CODEC not yet discovered\n");
  305. return -ENODEV;
  306. }
  307. struct snd_soc_codec *codec;
  308. codec = aml_m1_codec;
  309. snd_soc_write(codec, ADAC_POWER_CTRL_REG2, 0<<7);
  310. return 0;
  311. }
  312. static int aml_m1_codec_resume(struct platform_device* pdev)
  313. {
  314. if (!aml_m1_codec) {
  315. dev_err(&pdev->dev, "AML_M1_CODEC not yet discovered\n");
  316. return -ENODEV;
  317. }
  318. struct snd_soc_codec *codec;
  319. codec = aml_m1_codec;
  320. snd_soc_write(codec, ADAC_POWER_CTRL_REG2, 0<<7);
  321. snd_soc_write(codec, ADAC_POWER_CTRL_REG2, 1<<7);
  322. return 0;
  323. }
  324. #endif
  325. struct snd_soc_codec_device soc_codec_dev_aml_m1 = {
  326. .probe = aml_m1_codec_probe,
  327. .remove = aml_m1_codec_remove,
  328. #ifdef CONFIG_PM
  329. .suspend = aml_m1_codec_suspend,
  330. .resume = aml_m1_codec_resume,
  331. #else
  332. .suspend = NULL,
  333. .resume = NULL,
  334. #endif
  335. };
  336. EXPORT_SYMBOL_GPL(soc_codec_dev_aml_m1);
  337. static int aml_m1_register(struct aml_m1_codec_priv* aml_m1)
  338. {
  339. struct snd_soc_codec* codec = &aml_m1->codec;
  340. int ret;
  341. mutex_init(&codec->mutex);
  342. INIT_LIST_HEAD(&codec->dapm_widgets);
  343. INIT_LIST_HEAD(&codec->dapm_paths);
  344. codec->name = "AML_M1_CODEC";
  345. codec->owner = THIS_MODULE;
  346. codec->private_data = aml_m1;
  347. codec->dai = &aml_m1_codec_dai;
  348. codec->num_dai = 1;
  349. codec->reg_cache = &aml_m1->reg_cache;
  350. codec->reg_cache_size = ARRAY_SIZE(aml_m1->reg_cache);
  351. codec->read = aml_m1_read;
  352. codec->write = aml_m1_write;
  353. codec->volatile_register = aml_m1_volatile_register;
  354. codec->bias_level = SND_SOC_BIAS_OFF;
  355. codec->set_bias_level = aml_m1_set_bias_level;
  356. aml_m1_codec_dai.dev = codec->dev;
  357. aml_m1_reset(codec, true);
  358. aml_m1_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
  359. aml_m1_codec = codec;
  360. ret = snd_soc_register_codec(codec);
  361. if (ret != 0) {
  362. dev_err(codec->dev, "Failed to register codec: %d\n", ret);
  363. goto err;
  364. }
  365. ret = snd_soc_register_dai(&aml_m1_codec_dai);
  366. if (ret != 0) {
  367. dev_err(codec->dev, "Failed to register DAI: %d\n", ret);
  368. goto err_codec;
  369. }
  370. return 0;
  371. err_codec:
  372. snd_soc_unregister_codec(codec);
  373. err:
  374. aml_m1_codec = NULL;
  375. kfree(aml_m1);
  376. return ret;
  377. }
  378. static void aml_m1_unregister(struct aml_m1_codec_priv *aml_m1)
  379. {
  380. snd_soc_unregister_dai(&aml_m1_codec_dai);
  381. snd_soc_unregister_codec(&aml_m1->codec);
  382. aml_m1_codec = NULL;
  383. kfree(aml_m1);
  384. }
  385. static int aml_m1_codec_platform_probe(struct platform_device *pdev)
  386. {
  387. struct aml_m1_codec_priv *aml_m1;
  388. struct snd_soc_codec *codec;
  389. aml_m1 = kzalloc(sizeof(struct aml_m1_codec_priv), GFP_KERNEL);
  390. if (aml_m1 == NULL)
  391. return -ENOMEM;
  392. codec = &aml_m1->codec;
  393. codec->control_data = NULL;
  394. codec->hw_write = NULL;
  395. codec->pop_time = 0;
  396. codec->dev = &pdev->dev;
  397. platform_set_drvdata(pdev, aml_m1);
  398. return aml_m1_register(aml_m1);
  399. }
  400. static int __exit aml_m1_codec_platform_remove(struct platform_device *pdev)
  401. {
  402. struct aml_m1_codec_priv *aml_m1 = platform_get_drvdata(pdev);
  403. aml_m1_unregister(aml_m1);
  404. return 0;
  405. }
  406. static struct platform_driver aml_m1_codec_platform_driver = {
  407. .driver = {
  408. .name = "aml_m1_codec",
  409. .owner = THIS_MODULE,
  410. },
  411. .probe = aml_m1_codec_platform_probe,
  412. .remove = __exit_p(aml_m1_codec_platform_remove),
  413. };
  414. static int __init aml_m1_codec_modinit(void)
  415. {
  416. printk("****%s %d*****", __func__, __LINE__);
  417. return platform_driver_register(&aml_m1_codec_platform_driver);
  418. }
  419. static void __exit aml_m1_codec_exit(void)
  420. {
  421. platform_driver_unregister(&aml_m1_codec_platform_driver);
  422. }
  423. module_init(aml_m1_codec_modinit);
  424. module_exit(aml_m1_codec_exit);
  425. MODULE_DESCRIPTION("ASoC AML M1 codec driver");
  426. MODULE_AUTHOR("AMLogic Inc.");
  427. MODULE_LICENSE("GPL");