timpani.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483
  1. /* Copyright (c) 2010, The Linux Foundation. All rights reserved.
  2. *
  3. * This program is free software; you can redistribute it and/or modify
  4. * it under the terms of the GNU General Public License version 2 and
  5. * only version 2 as published by the Free Software Foundation.
  6. *
  7. * This program is distributed in the hope that it will be useful,
  8. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. * GNU General Public License for more details.
  11. *
  12. */
  13. #include <linux/module.h>
  14. #include <linux/delay.h>
  15. #include <linux/err.h>
  16. #include <linux/init.h>
  17. #include <linux/slab.h>
  18. #include <linux/platform_device.h>
  19. #include <linux/mfd/marimba.h>
  20. #include <linux/mfd/timpani-audio.h>
  21. #include <sound/soc.h>
  22. #include <sound/initval.h>
  23. #include <sound/soc-dapm.h>
  24. /* Debug purpose */
  25. #include <linux/gpio.h>
  26. #include <linux/clk.h>
  27. #include <mach/mpp.h>
  28. /* End of debug purpose */
  29. #define ADIE_CODEC_MAX 2
  30. struct adie_codec_register {
  31. u8 reg;
  32. u8 mask;
  33. u8 val;
  34. };
  35. static struct adie_codec_register dmic_on[] = {
  36. {0x80, 0x05, 0x05},
  37. {0x80, 0x05, 0x00},
  38. {0x83, 0x0C, 0x00},
  39. {0x8A, 0xF0, 0x30},
  40. {0x86, 0xFF, 0xAC},
  41. {0x87, 0xFF, 0xAC},
  42. {0x8A, 0xF0, 0xF0},
  43. {0x82, 0x1F, 0x1E},
  44. {0x83, 0x0C, 0x0C},
  45. {0x92, 0x3F, 0x21},
  46. {0x94, 0x3F, 0x24},
  47. {0xA3, 0x39, 0x01},
  48. {0xA8, 0x0F, 0x00},
  49. {0xAB, 0x3F, 0x00},
  50. {0x86, 0xFF, 0x00},
  51. {0x87, 0xFF, 0x00},
  52. {0x8A, 0xF0, 0xC0},
  53. };
  54. static struct adie_codec_register dmic_off[] = {
  55. {0x8A, 0xF0, 0xF0},
  56. {0x83, 0x0C, 0x00},
  57. {0x92, 0xFF, 0x00},
  58. {0x94, 0xFF, 0x1B},
  59. };
  60. static struct adie_codec_register spk_on[] = {
  61. {0x80, 0x02, 0x02},
  62. {0x80, 0x02, 0x00},
  63. {0x83, 0x03, 0x00},
  64. {0x8A, 0x0F, 0x03},
  65. {0xA3, 0x02, 0x02},
  66. {0x84, 0xFF, 0x00},
  67. {0x85, 0xFF, 0x00},
  68. {0x8A, 0x0F, 0x0C},
  69. {0x81, 0xFF, 0x0E},
  70. {0x83, 0x03, 0x03},
  71. {0x24, 0x6F, 0x6C},
  72. {0xB7, 0x01, 0x01},
  73. {0x31, 0x01, 0x01},
  74. {0x32, 0xF8, 0x08},
  75. {0x32, 0xF8, 0x48},
  76. {0x32, 0xF8, 0xF8},
  77. {0xE0, 0xFE, 0xAC},
  78. {0xE1, 0xFE, 0xAC},
  79. {0x3A, 0x24, 0x24},
  80. {0xE0, 0xFE, 0x3C},
  81. {0xE1, 0xFE, 0x3C},
  82. {0xE0, 0xFE, 0x1C},
  83. {0xE1, 0xFE, 0x1C},
  84. {0xE0, 0xFE, 0x10},
  85. {0xE1, 0xFE, 0x10},
  86. };
  87. static struct adie_codec_register spk_off[] = {
  88. {0x8A, 0x0F, 0x0F},
  89. {0xE0, 0xFE, 0x1C},
  90. {0xE1, 0xFE, 0x1C},
  91. {0xE0, 0xFE, 0x3C},
  92. {0xE1, 0xFE, 0x3C},
  93. {0xE0, 0xFC, 0xAC},
  94. {0xE1, 0xFC, 0xAC},
  95. {0x32, 0xF8, 0x00},
  96. {0x31, 0x05, 0x00},
  97. {0x3A, 0x24, 0x00},
  98. };
  99. static struct adie_codec_register spk_mute[] = {
  100. {0x84, 0xFF, 0xAC},
  101. {0x85, 0xFF, 0xAC},
  102. {0x8A, 0x0F, 0x0C},
  103. };
  104. static struct adie_codec_register spk_unmute[] = {
  105. {0x84, 0xFF, 0x00},
  106. {0x85, 0xFF, 0x00},
  107. {0x8A, 0x0F, 0x0C},
  108. };
  109. struct adie_codec_path {
  110. int rate; /* sample rate of path */
  111. u32 reg_owner;
  112. };
  113. struct timpani_drv_data { /* member undecided */
  114. struct snd_soc_codec codec;
  115. struct adie_codec_path path[ADIE_CODEC_MAX];
  116. u32 ref_cnt;
  117. struct marimba_codec_platform_data *codec_pdata;
  118. };
  119. static struct snd_soc_codec *timpani_codec;
  120. enum /* regaccess blk id */
  121. {
  122. RA_BLOCK_RX1 = 0,
  123. RA_BLOCK_RX2,
  124. RA_BLOCK_TX1,
  125. RA_BLOCK_TX2,
  126. RA_BLOCK_LB,
  127. RA_BLOCK_SHARED_RX_LB,
  128. RA_BLOCK_SHARED_TX,
  129. RA_BLOCK_TXFE1,
  130. RA_BLOCK_TXFE2,
  131. RA_BLOCK_PA_COMMON,
  132. RA_BLOCK_PA_EAR,
  133. RA_BLOCK_PA_HPH,
  134. RA_BLOCK_PA_LINE,
  135. RA_BLOCK_PA_AUX,
  136. RA_BLOCK_ADC,
  137. RA_BLOCK_DMIC,
  138. RA_BLOCK_TX_I2S,
  139. RA_BLOCK_DRV,
  140. RA_BLOCK_TEST,
  141. RA_BLOCK_RESERVED,
  142. RA_BLOCK_NUM,
  143. };
  144. enum /* regaccess onwer ID */
  145. {
  146. RA_OWNER_NONE = 0,
  147. RA_OWNER_PATH_RX1,
  148. RA_OWNER_PATH_RX2,
  149. RA_OWNER_PATH_TX1,
  150. RA_OWNER_PATH_TX2,
  151. RA_OWNER_PATH_LB,
  152. RA_OWNER_DRV,
  153. RA_OWNER_NUM,
  154. };
  155. struct reg_acc_blk_cfg {
  156. u8 valid_owners[RA_OWNER_NUM];
  157. };
  158. struct timpani_regaccess {
  159. u8 reg_addr;
  160. u8 blk_mask[RA_BLOCK_NUM];
  161. u8 reg_mask;
  162. u8 reg_default;
  163. };
  164. static unsigned int timpani_codec_read(struct snd_soc_codec *codec,
  165. unsigned int reg)
  166. {
  167. struct marimba *pdrv = codec->control_data;
  168. int rc;
  169. u8 val;
  170. rc = marimba_read(pdrv, reg, &val, 1);
  171. if (IS_ERR_VALUE(rc)) {
  172. pr_err("%s: fail to write reg %x\n", __func__, reg);
  173. return 0;
  174. }
  175. return val;
  176. }
  177. static int timpani_codec_write(struct snd_soc_codec *codec, unsigned int reg,
  178. unsigned int value)
  179. {
  180. struct marimba *pdrv = codec->control_data;
  181. int rc;
  182. rc = marimba_write_bit_mask(pdrv, reg, (u8 *)&value, 1, 0xFF);
  183. if (IS_ERR_VALUE(rc)) {
  184. pr_err("%s: fail to write reg %x\n", __func__, reg);
  185. return -EIO;
  186. }
  187. pr_debug("%s: write reg %x val %x\n", __func__, reg, value);
  188. return 0;
  189. }
  190. static void timpani_codec_bring_up(struct snd_soc_codec *codec)
  191. {
  192. struct timpani_drv_data *timpani = snd_soc_codec_get_drvdata(codec);
  193. int rc;
  194. if (timpani->codec_pdata &&
  195. timpani->codec_pdata->marimba_codec_power) {
  196. if (timpani->ref_cnt)
  197. return;
  198. /* Codec power up sequence */
  199. rc = timpani->codec_pdata->marimba_codec_power(1);
  200. if (rc)
  201. pr_err("%s: could not power up timpani "
  202. "codec\n", __func__);
  203. else {
  204. timpani_codec_write(codec, 0xFF, 0x08);
  205. timpani_codec_write(codec, 0xFF, 0x0A);
  206. timpani_codec_write(codec, 0xFF, 0x0E);
  207. timpani_codec_write(codec, 0xFF, 0x07);
  208. timpani_codec_write(codec, 0xFF, 0x17);
  209. timpani_codec_write(codec, TIMPANI_A_MREF, 0x22);
  210. msleep(15);
  211. timpani->ref_cnt++;
  212. }
  213. }
  214. }
  215. static void timpani_codec_bring_down(struct snd_soc_codec *codec)
  216. {
  217. struct timpani_drv_data *timpani = snd_soc_codec_get_drvdata(codec);
  218. int rc;
  219. if (timpani->codec_pdata &&
  220. timpani->codec_pdata->marimba_codec_power) {
  221. timpani->ref_cnt--;
  222. if (timpani->ref_cnt >= 1)
  223. return;
  224. timpani_codec_write(codec, TIMPANI_A_MREF, TIMPANI_MREF_POR);
  225. timpani_codec_write(codec, 0xFF, 0x07);
  226. timpani_codec_write(codec, 0xFF, 0x06);
  227. timpani_codec_write(codec, 0xFF, 0x0E);
  228. timpani_codec_write(codec, 0xFF, 0x08);
  229. rc = timpani->codec_pdata->marimba_codec_power(0);
  230. if (rc)
  231. pr_err("%s: could not power down timpani "
  232. "codec\n", __func__);
  233. }
  234. }
  235. static void timpani_dmic_config(struct snd_soc_codec *codec, int on)
  236. {
  237. struct adie_codec_register *regs;
  238. int regs_sz, i;
  239. if (on) {
  240. regs = dmic_on;
  241. regs_sz = ARRAY_SIZE(dmic_on);
  242. } else {
  243. regs = dmic_off;
  244. regs_sz = ARRAY_SIZE(dmic_off);
  245. }
  246. for (i = 0; i < regs_sz; i++)
  247. timpani_codec_write(codec, regs[i].reg,
  248. (regs[i].mask & regs[i].val));
  249. }
  250. static void timpani_spk_config(struct snd_soc_codec *codec, int on)
  251. {
  252. struct adie_codec_register *regs;
  253. int regs_sz, i;
  254. if (on) {
  255. regs = spk_on;
  256. regs_sz = ARRAY_SIZE(spk_on);
  257. } else {
  258. regs = spk_off;
  259. regs_sz = ARRAY_SIZE(spk_off);
  260. }
  261. for (i = 0; i < regs_sz; i++)
  262. timpani_codec_write(codec, regs[i].reg,
  263. (regs[i].mask & regs[i].val));
  264. }
  265. static int timpani_startup(struct snd_pcm_substream *substream,
  266. struct snd_soc_dai *dai)
  267. {
  268. struct snd_soc_pcm_runtime *rtd = substream->private_data;
  269. struct snd_soc_device *socdev = rtd->socdev;
  270. struct snd_soc_codec *codec = socdev->card->codec;
  271. pr_info("%s()\n", __func__);
  272. if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
  273. pr_info("%s: playback\n", __func__);
  274. timpani_codec_bring_up(codec);
  275. timpani_spk_config(codec, 1);
  276. } else {
  277. pr_info("%s: Capture\n", __func__);
  278. timpani_codec_bring_up(codec);
  279. timpani_dmic_config(codec, 1);
  280. }
  281. return 0;
  282. }
  283. static void timpani_shutdown(struct snd_pcm_substream *substream,
  284. struct snd_soc_dai *dai)
  285. {
  286. struct snd_soc_pcm_runtime *rtd = substream->private_data;
  287. struct snd_soc_device *socdev = rtd->socdev;
  288. struct snd_soc_codec *codec = socdev->card->codec;
  289. pr_info("%s()\n", __func__);
  290. if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
  291. timpani_codec_bring_down(codec);
  292. timpani_spk_config(codec, 0);
  293. } else {
  294. timpani_codec_bring_down(codec);
  295. timpani_dmic_config(codec, 0);
  296. }
  297. return;
  298. }
  299. int digital_mute(struct snd_soc_dai *dai, int mute)
  300. {
  301. struct snd_soc_codec *codec = dai->codec;
  302. struct adie_codec_register *regs;
  303. int regs_sz, i;
  304. if (mute) {
  305. regs = spk_mute;
  306. regs_sz = ARRAY_SIZE(spk_mute);
  307. } else {
  308. regs = spk_unmute;
  309. regs_sz = ARRAY_SIZE(spk_unmute);
  310. }
  311. for (i = 0; i < regs_sz; i++) {
  312. timpani_codec_write(codec, regs[i].reg,
  313. (regs[i].mask & regs[i].val));
  314. msleep(10);
  315. }
  316. return 0;
  317. }
  318. static struct snd_soc_dai_ops timpani_dai_ops = {
  319. .startup = timpani_startup,
  320. .shutdown = timpani_shutdown,
  321. };
  322. struct snd_soc_dai timpani_codec_dai[] = {
  323. {
  324. .name = "TIMPANI Rx",
  325. .playback = {
  326. .stream_name = "Handset Playback",
  327. .rates = SNDRV_PCM_RATE_8000_96000,
  328. .formats = SNDRV_PCM_FMTBIT_S16_LE,
  329. .rate_max = 96000,
  330. .rate_min = 8000,
  331. .channels_min = 1,
  332. .channels_max = 2,
  333. },
  334. .ops = &timpani_dai_ops,
  335. },
  336. {
  337. .name = "TIMPANI Tx",
  338. .capture = {
  339. .stream_name = "Handset Capture",
  340. .rates = SNDRV_PCM_RATE_8000_96000,
  341. .formats = SNDRV_PCM_FMTBIT_S16_LE,
  342. .rate_max = 96000,
  343. .rate_min = 8000,
  344. .channels_min = 1,
  345. .channels_max = 2,
  346. },
  347. .ops = &timpani_dai_ops,
  348. }
  349. };
  350. static int timpani_soc_probe(struct platform_device *pdev)
  351. {
  352. struct snd_soc_device *socdev = platform_get_drvdata(pdev);
  353. struct snd_soc_codec *codec;
  354. int ret = 0;
  355. if (!timpani_codec) {
  356. dev_err(&pdev->dev, "core driver not yet probed\n");
  357. return -ENODEV;
  358. }
  359. socdev->card->codec = timpani_codec;
  360. codec = timpani_codec;
  361. ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
  362. if (ret < 0)
  363. dev_err(codec->dev, "failed to create pcms\n");
  364. return ret;
  365. }
  366. /* power down chip */
  367. static int timpani_soc_remove(struct platform_device *pdev)
  368. {
  369. struct snd_soc_device *socdev = platform_get_drvdata(pdev);
  370. snd_soc_free_pcms(socdev);
  371. return 0;
  372. }
  373. struct snd_soc_codec_device soc_codec_dev_timpani = {
  374. .probe = timpani_soc_probe,
  375. .remove = timpani_soc_remove,
  376. };
  377. EXPORT_SYMBOL_GPL(soc_codec_dev_timpani);
  378. static int timpani_codec_probe(struct platform_device *pdev)
  379. {
  380. struct snd_soc_codec *codec;
  381. struct timpani_drv_data *priv;
  382. pr_info("%s()\n", __func__);
  383. priv = kzalloc(sizeof(struct timpani_drv_data), GFP_KERNEL);
  384. if (priv == NULL)
  385. return -ENOMEM;
  386. codec = &priv->codec;
  387. snd_soc_codec_set_drvdata(codec, priv);
  388. priv->codec_pdata = pdev->dev.platform_data;
  389. mutex_init(&codec->mutex);
  390. INIT_LIST_HEAD(&codec->dapm_widgets);
  391. INIT_LIST_HEAD(&codec->dapm_paths);
  392. codec->name = "TIMPANI";
  393. codec->owner = THIS_MODULE;
  394. codec->read = timpani_codec_read;
  395. codec->write = timpani_codec_write;
  396. codec->dai = timpani_codec_dai;
  397. codec->num_dai = ARRAY_SIZE(timpani_codec_dai);
  398. codec->control_data = platform_get_drvdata(pdev);
  399. timpani_codec = codec;
  400. snd_soc_register_dais(timpani_codec_dai, ARRAY_SIZE(timpani_codec_dai));
  401. snd_soc_register_codec(codec);
  402. return 0;
  403. }
  404. static struct platform_driver timpani_codec_driver = {
  405. .probe = timpani_codec_probe,
  406. .driver = {
  407. .name = "timpani_codec",
  408. .owner = THIS_MODULE,
  409. },
  410. };
  411. static int __init timpani_codec_init(void)
  412. {
  413. return platform_driver_register(&timpani_codec_driver);
  414. }
  415. static void __exit timpani_codec_exit(void)
  416. {
  417. platform_driver_unregister(&timpani_codec_driver);
  418. }
  419. module_init(timpani_codec_init);
  420. module_exit(timpani_codec_exit);
  421. MODULE_DESCRIPTION("Timpani codec driver");
  422. MODULE_VERSION("1.0");
  423. MODULE_LICENSE("GPL v2");