/arch/arm/mach-fsm/qdsp5v2/snddev_mi2s.c

https://bitbucket.org/sammyz/iscream_thunderc-2.6.35-rebase · C · 410 lines · 304 code · 82 blank · 24 comment · 45 complexity · c2d75d0dd4edc913dd1404a07dfa0fd7 MD5 · raw file

  1. /* Copyright (c) 2010, Code Aurora Forum. 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. * You should have received a copy of the GNU General Public License
  13. * along with this program; if not, write to the Free Software
  14. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  15. * 02110-1301, USA.
  16. */
  17. #include <linux/module.h>
  18. #include <linux/platform_device.h>
  19. #include <linux/clk.h>
  20. #include <linux/err.h>
  21. #include <linux/io.h>
  22. #include <linux/uaccess.h>
  23. #include <mach/qdsp5v2/audio_dev_ctl.h>
  24. #include <mach/qdsp5v2/audio_interct.h>
  25. #include <mach/qdsp5v2/mi2s.h>
  26. #include <mach/qdsp5v2/afe.h>
  27. #include <mach/debug_mm.h>
  28. #include <mach/qdsp5v2/snddev_mi2s.h>
  29. /* Global state for the driver */
  30. struct snddev_mi2s_drv_state {
  31. struct clk *mclk;
  32. struct clk *sclk;
  33. struct mutex lock;
  34. u8 sd_lines_used;
  35. u8 clocks_enabled;
  36. };
  37. static struct snddev_mi2s_drv_state snddev_mi2s_drv;
  38. static int snddev_mi2s_open_tx(struct msm_snddev_info *dev_info)
  39. {
  40. u8 channels;
  41. struct msm_afe_config afe_config;
  42. int rc;
  43. struct snddev_mi2s_data *snddev_mi2s_data = dev_info->private_data;
  44. MM_DBG("%s: channel_mode = %u sd_line_mask = 0x%x "
  45. "default_sample_rate = %u\n", __func__,
  46. snddev_mi2s_data->channel_mode, snddev_mi2s_data->sd_lines,
  47. snddev_mi2s_data->default_sample_rate);
  48. if (snddev_mi2s_data->channel_mode == 2) {
  49. channels = MI2S_CHAN_STEREO;
  50. } else {
  51. MM_ERR("%s: Invalid number of channels = %u\n", __func__,
  52. snddev_mi2s_data->channel_mode);
  53. return -EINVAL;
  54. }
  55. /* Set MI2S */
  56. mi2s_set_hdmi_input_path(channels, WT_16_BIT,
  57. snddev_mi2s_data->sd_lines);
  58. afe_config.sample_rate = snddev_mi2s_data->default_sample_rate / 1000;
  59. afe_config.channel_mode = snddev_mi2s_data->channel_mode;
  60. afe_config.volume = AFE_VOLUME_UNITY;
  61. rc = afe_enable(AFE_HW_PATH_MI2S_TX, &afe_config);
  62. if (IS_ERR_VALUE(rc)) {
  63. MM_ERR("%s: afe_enable failed for AFE_HW_PATH_MI2S_TX "
  64. "rc = %d\n", __func__, rc);
  65. return -ENODEV;
  66. }
  67. /* Enable audio path */
  68. if (snddev_mi2s_data->route)
  69. snddev_mi2s_data->route();
  70. return 0;
  71. }
  72. static int snddev_mi2s_open_rx(struct msm_snddev_info *dev_info)
  73. {
  74. int rc;
  75. struct msm_afe_config afe_config;
  76. u8 channels;
  77. struct snddev_mi2s_data *snddev_mi2s_data = dev_info->private_data;
  78. MM_DBG("%s: channel_mode = %u sd_line_mask = 0x%x "
  79. "default_sample_rate = %u\n", __func__,
  80. snddev_mi2s_data->channel_mode, snddev_mi2s_data->sd_lines,
  81. snddev_mi2s_data->default_sample_rate);
  82. if (snddev_mi2s_data->channel_mode == 2)
  83. channels = MI2S_CHAN_STEREO;
  84. else if (snddev_mi2s_data->channel_mode == 4)
  85. channels = MI2S_CHAN_4CHANNELS;
  86. else if (snddev_mi2s_data->channel_mode == 6)
  87. channels = MI2S_CHAN_6CHANNELS;
  88. else if (snddev_mi2s_data->channel_mode == 8)
  89. channels = MI2S_CHAN_8CHANNELS;
  90. else
  91. channels = MI2S_CHAN_MONO_RAW;
  92. /* Set MI2S */
  93. mi2s_set_hdmi_output_path(channels, WT_16_BIT,
  94. snddev_mi2s_data->sd_lines);
  95. /* Start AFE */
  96. afe_config.sample_rate = snddev_mi2s_data->default_sample_rate / 1000;
  97. afe_config.channel_mode = snddev_mi2s_data->channel_mode;
  98. afe_config.volume = AFE_VOLUME_UNITY;
  99. rc = afe_enable(AFE_HW_PATH_MI2S_RX, &afe_config);
  100. if (IS_ERR_VALUE(rc)) {
  101. MM_ERR("%s: encounter error\n", __func__);
  102. return -ENODEV;
  103. }
  104. /* Enable audio path */
  105. if (snddev_mi2s_data->route)
  106. snddev_mi2s_data->route();
  107. MM_DBG("%s: enabled %s \n", __func__, snddev_mi2s_data->name);
  108. return 0;
  109. }
  110. static int snddev_mi2s_open(struct msm_snddev_info *dev_info)
  111. {
  112. int rc = 0;
  113. struct snddev_mi2s_drv_state *drv = &snddev_mi2s_drv;
  114. u32 dir;
  115. struct snddev_mi2s_data *snddev_mi2s_data = dev_info->private_data;
  116. if (!dev_info) {
  117. MM_ERR("%s: msm_snddev_info is null \n", __func__);
  118. return -EINVAL;
  119. }
  120. mutex_lock(&drv->lock);
  121. if (drv->sd_lines_used & snddev_mi2s_data->sd_lines) {
  122. MM_ERR("%s: conflict in SD data line. can not use the device\n",
  123. __func__);
  124. mutex_unlock(&drv->lock);
  125. return -EBUSY;
  126. }
  127. if (!drv->clocks_enabled) {
  128. rc = mi2s_config_clk_gpio();
  129. if (rc) {
  130. MM_ERR("%s: mi2s GPIO config failed for %s\n",
  131. __func__, snddev_mi2s_data->name);
  132. mutex_unlock(&drv->lock);
  133. return -EIO;
  134. }
  135. clk_enable(drv->mclk);
  136. clk_enable(drv->sclk);
  137. drv->clocks_enabled = 1;
  138. MM_DBG("%s: clks enabled \n", __func__);
  139. } else
  140. MM_DBG("%s: clks already enabled \n", __func__);
  141. if (snddev_mi2s_data->capability & SNDDEV_CAP_RX) {
  142. dir = DIR_RX;
  143. rc = mi2s_config_data_gpio(dir, snddev_mi2s_data->sd_lines);
  144. if (rc) {
  145. rc = -EIO;
  146. MM_ERR("%s: mi2s GPIO config failed for %s\n",
  147. __func__, snddev_mi2s_data->name);
  148. goto mi2s_data_gpio_failure;
  149. }
  150. MM_DBG("%s: done gpio config rx SD lines\n", __func__);
  151. rc = snddev_mi2s_open_rx(dev_info);
  152. if (IS_ERR_VALUE(rc)) {
  153. MM_ERR(" snddev_mi2s_open_rx failed \n");
  154. goto mi2s_cleanup_open;
  155. }
  156. drv->sd_lines_used |= snddev_mi2s_data->sd_lines;
  157. MM_DBG("%s: sd_lines_used = 0x%x\n", __func__,
  158. drv->sd_lines_used);
  159. mutex_unlock(&drv->lock);
  160. } else {
  161. dir = DIR_TX;
  162. rc = mi2s_config_data_gpio(dir, snddev_mi2s_data->sd_lines);
  163. if (rc) {
  164. rc = -EIO;
  165. MM_ERR("%s: mi2s GPIO config failed for %s\n",
  166. __func__, snddev_mi2s_data->name);
  167. goto mi2s_data_gpio_failure;
  168. }
  169. MM_DBG("%s: done data line gpio config for %s\n",
  170. __func__, snddev_mi2s_data->name);
  171. rc = snddev_mi2s_open_tx(dev_info);
  172. if (IS_ERR_VALUE(rc)) {
  173. MM_ERR(" snddev_mi2s_open_tx failed \n");
  174. goto mi2s_cleanup_open;
  175. }
  176. drv->sd_lines_used |= snddev_mi2s_data->sd_lines;
  177. MM_DBG("%s: sd_lines_used = 0x%x\n", __func__,
  178. drv->sd_lines_used);
  179. mutex_unlock(&drv->lock);
  180. }
  181. return 0;
  182. mi2s_cleanup_open:
  183. mi2s_unconfig_data_gpio(dir, snddev_mi2s_data->sd_lines);
  184. /* Disable audio path */
  185. if (snddev_mi2s_data->deroute)
  186. snddev_mi2s_data->deroute();
  187. mi2s_data_gpio_failure:
  188. if (!drv->sd_lines_used) {
  189. clk_disable(drv->sclk);
  190. clk_disable(drv->mclk);
  191. drv->clocks_enabled = 0;
  192. mi2s_unconfig_clk_gpio();
  193. }
  194. mutex_unlock(&drv->lock);
  195. return rc;
  196. }
  197. static int snddev_mi2s_close(struct msm_snddev_info *dev_info)
  198. {
  199. struct snddev_mi2s_drv_state *drv = &snddev_mi2s_drv;
  200. int dir;
  201. struct snddev_mi2s_data *snddev_mi2s_data = dev_info->private_data;
  202. if (!dev_info) {
  203. MM_ERR("%s: msm_snddev_info is null \n", __func__);
  204. return -EINVAL;
  205. }
  206. if (!dev_info->opened) {
  207. MM_ERR(" %s: calling close device with out opening the"
  208. " device \n", __func__);
  209. return -EIO;
  210. }
  211. mutex_lock(&drv->lock);
  212. drv->sd_lines_used &= ~snddev_mi2s_data->sd_lines;
  213. MM_DBG("%s: sd_lines in use = 0x%x\n", __func__, drv->sd_lines_used);
  214. if (snddev_mi2s_data->capability & SNDDEV_CAP_RX) {
  215. dir = DIR_RX;
  216. afe_disable(AFE_HW_PATH_MI2S_RX);
  217. } else {
  218. dir = DIR_TX;
  219. afe_disable(AFE_HW_PATH_MI2S_TX);
  220. }
  221. mi2s_unconfig_data_gpio(dir, snddev_mi2s_data->sd_lines);
  222. if (!drv->sd_lines_used) {
  223. clk_disable(drv->sclk);
  224. clk_disable(drv->mclk);
  225. drv->clocks_enabled = 0;
  226. mi2s_unconfig_clk_gpio();
  227. }
  228. /* Disable audio path */
  229. if (snddev_mi2s_data->deroute)
  230. snddev_mi2s_data->deroute();
  231. mutex_unlock(&drv->lock);
  232. return 0;
  233. }
  234. static int snddev_mi2s_set_freq(struct msm_snddev_info *dev_info, u32 req_freq)
  235. {
  236. if (req_freq != 48000) {
  237. MM_DBG("%s: Unsupported Frequency:%d\n", __func__, req_freq);
  238. return -EINVAL;
  239. }
  240. return 48000;
  241. }
  242. static int snddev_mi2s_probe(struct platform_device *pdev)
  243. {
  244. int rc = 0;
  245. struct snddev_mi2s_data *pdata;
  246. struct msm_snddev_info *dev_info;
  247. if (!pdev || !pdev->dev.platform_data) {
  248. printk(KERN_ALERT "Invalid caller \n");
  249. return -ENODEV;
  250. }
  251. pdata = pdev->dev.platform_data;
  252. if ((pdata->capability & SNDDEV_CAP_RX) &&
  253. (pdata->capability & SNDDEV_CAP_TX)) {
  254. MM_ERR("%s: invalid device data either RX or TX\n", __func__);
  255. return -ENODEV;
  256. }
  257. dev_info = kzalloc(sizeof(struct msm_snddev_info), GFP_KERNEL);
  258. if (!dev_info) {
  259. MM_ERR("%s: uneable to allocate memeory for msm_snddev_info \n",
  260. __func__);
  261. return -ENOMEM;
  262. }
  263. dev_info->name = pdata->name;
  264. dev_info->copp_id = pdata->copp_id;
  265. dev_info->acdb_id = pdata->acdb_id;
  266. dev_info->private_data = (void *)pdata;
  267. dev_info->dev_ops.open = snddev_mi2s_open;
  268. dev_info->dev_ops.close = snddev_mi2s_close;
  269. dev_info->dev_ops.set_freq = snddev_mi2s_set_freq;
  270. dev_info->capability = pdata->capability;
  271. dev_info->opened = 0;
  272. msm_snddev_register(dev_info);
  273. dev_info->sample_rate = pdata->default_sample_rate;
  274. MM_DBG("%s: probe done for %s\n", __func__, pdata->name);
  275. return rc;
  276. }
  277. static int snddev_mi2s_remove(struct platform_device *pdev)
  278. {
  279. return 0;
  280. }
  281. static struct platform_driver snddev_mi2s_driver = {
  282. .probe = snddev_mi2s_probe,
  283. .remove = snddev_mi2s_remove,
  284. .driver = {.name = "snddev_mi2s"}
  285. };
  286. static int __init snddev_mi2s_init(void)
  287. {
  288. s32 rc;
  289. struct snddev_mi2s_drv_state *drv = &snddev_mi2s_drv;
  290. rc = platform_driver_register(&snddev_mi2s_driver);
  291. if (IS_ERR_VALUE(rc)) {
  292. MM_ERR("%s: platform_driver_register failed \n", __func__);
  293. goto error_platform_driver;
  294. }
  295. drv->mclk = clk_get(NULL, "mi2s_m_clk");
  296. if (IS_ERR(drv->mclk)) {
  297. MM_ERR("%s: clk_get mi2s_mclk failed \n", __func__);
  298. goto error_mclk;
  299. }
  300. drv->sclk = clk_get(NULL, "mi2s_s_clk");
  301. if (IS_ERR(drv->sclk)) {
  302. MM_ERR("%s: clk_get mi2s_sclk failed \n", __func__);
  303. goto error_sclk;
  304. }
  305. mutex_init(&drv->lock);
  306. MM_DBG("snddev_mi2s_init : done \n");
  307. return 0;
  308. error_sclk:
  309. clk_put(drv->mclk);
  310. error_mclk:
  311. platform_driver_unregister(&snddev_mi2s_driver);
  312. error_platform_driver:
  313. MM_ERR("%s: encounter error\n", __func__);
  314. return -ENODEV;
  315. }
  316. static void __exit snddev_mi2s_exit(void)
  317. {
  318. struct snddev_mi2s_drv_state *drv = &snddev_mi2s_drv;
  319. platform_driver_unregister(&snddev_mi2s_driver);
  320. clk_put(drv->sclk);
  321. clk_put(drv->mclk);
  322. return;
  323. }
  324. module_init(snddev_mi2s_init);
  325. module_exit(snddev_mi2s_exit);
  326. MODULE_DESCRIPTION("mi2s Sound Device driver");
  327. MODULE_VERSION("1.0");
  328. MODULE_LICENSE("GPL v2");