msm7201.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426
  1. /* linux/sound/soc/msm/msm7201.c
  2. *
  3. * Copyright (c) 2008-2009, 2011, 2012 The Linux Foundation. All rights reserved.
  4. *
  5. * All source code in this file is licensed under the following license except
  6. * where indicated.
  7. *
  8. * This program is free software; you can redistribute it and/or modify it
  9. * under the terms of the GNU General Public License version 2 as published
  10. * by the Free Software Foundation.
  11. *
  12. * This program is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  15. *
  16. * See the GNU General Public License for more details.
  17. * You should have received a copy of the GNU General Public License
  18. * along with this program; if not, you can find it at http://www.fsf.org.
  19. */
  20. #include <linux/init.h>
  21. #include <linux/err.h>
  22. #include <linux/module.h>
  23. #include <linux/moduleparam.h>
  24. #include <linux/time.h>
  25. #include <linux/wait.h>
  26. #include <linux/platform_device.h>
  27. #include <linux/msm_audio.h>
  28. #include <sound/core.h>
  29. #include <sound/soc.h>
  30. #include <sound/soc-dapm.h>
  31. #include <sound/pcm.h>
  32. #include <sound/tlv.h>
  33. #include <sound/initval.h>
  34. #include <sound/control.h>
  35. #include <asm/dma.h>
  36. #include <linux/dma-mapping.h>
  37. #include "msm-pcm.h"
  38. #include <asm/mach-types.h>
  39. #include <mach/msm_rpcrouter.h>
  40. static struct msm_rpc_endpoint *snd_ep;
  41. static uint32_t snd_mute_ear_mute;
  42. static uint32_t snd_mute_mic_mute;
  43. struct msm_snd_rpc_ids {
  44. unsigned long prog;
  45. unsigned long vers;
  46. unsigned long rpc_set_snd_device;
  47. unsigned long rpc_set_device_vol;
  48. struct cad_devices_type device;
  49. };
  50. struct rpc_cad_set_device_args {
  51. struct cad_devices_type device;
  52. uint32_t ear_mute;
  53. uint32_t mic_mute;
  54. uint32_t cb_func;
  55. uint32_t client_data;
  56. };
  57. struct rpc_cad_set_volume_args {
  58. struct cad_devices_type device;
  59. uint32_t method;
  60. uint32_t volume;
  61. uint32_t cb_func;
  62. uint32_t client_data;
  63. };
  64. static struct msm_snd_rpc_ids snd_rpc_ids;
  65. static struct platform_device *msm_audio_snd_device;
  66. static int snd_msm_volume_info(struct snd_kcontrol *kcontrol,
  67. struct snd_ctl_elem_info *uinfo)
  68. {
  69. uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
  70. uinfo->count = 1; /* Volume Param, in dB */
  71. uinfo->value.integer.min = MIN_DB;
  72. uinfo->value.integer.max = MAX_DB;
  73. return 0;
  74. }
  75. static int snd_msm_volume_get(struct snd_kcontrol *kcontrol,
  76. struct snd_ctl_elem_value *ucontrol)
  77. {
  78. spin_lock_irq(&the_locks.mixer_lock);
  79. ucontrol->value.integer.value[0] = msm_vol_ctl.volume;
  80. spin_unlock_irq(&the_locks.mixer_lock);
  81. return 0;
  82. }
  83. static int snd_msm_volume_put(struct snd_kcontrol *kcontrol,
  84. struct snd_ctl_elem_value *ucontrol)
  85. {
  86. int change;
  87. int volume;
  88. volume = ucontrol->value.integer.value[0];
  89. spin_lock_irq(&the_locks.mixer_lock);
  90. change = (msm_vol_ctl.volume != volume);
  91. if (change) {
  92. msm_vol_ctl.volume = volume;
  93. msm_audio_volume_update(PCMPLAYBACK_DECODERID,
  94. msm_vol_ctl.volume, msm_vol_ctl.pan);
  95. }
  96. spin_unlock_irq(&the_locks.mixer_lock);
  97. return 0;
  98. }
  99. static int snd_msm_device_info(struct snd_kcontrol *kcontrol,
  100. struct snd_ctl_elem_info *uinfo)
  101. {
  102. uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
  103. uinfo->count = 4; /* Device */
  104. /*
  105. * The number of devices supported is 26 (0 to 25)
  106. */
  107. uinfo->value.integer.min = 0;
  108. uinfo->value.integer.max = 36;
  109. return 0;
  110. }
  111. static int snd_msm_device_get(struct snd_kcontrol *kcontrol,
  112. struct snd_ctl_elem_value *ucontrol)
  113. {
  114. ucontrol->value.integer.value[0]
  115. = (uint32_t)snd_rpc_ids.device.rx_device;
  116. ucontrol->value.integer.value[1]
  117. = (uint32_t)snd_rpc_ids.device.tx_device;
  118. ucontrol->value.integer.value[2] = snd_mute_ear_mute;
  119. ucontrol->value.integer.value[3] = snd_mute_mic_mute;
  120. return 0;
  121. }
  122. int msm_snd_init_rpc_ids(void)
  123. {
  124. snd_rpc_ids.prog = 0x30000002;
  125. snd_rpc_ids.vers = 0x00030003;
  126. /*
  127. * The magic number 2 corresponds to the rpc call
  128. * index for snd_set_device
  129. */
  130. snd_rpc_ids.rpc_set_snd_device = 40;
  131. snd_rpc_ids.rpc_set_device_vol = 39;
  132. return 0;
  133. }
  134. int msm_snd_rpc_connect(void)
  135. {
  136. if (snd_ep) {
  137. printk(KERN_INFO "%s: snd_ep already connected\n", __func__);
  138. return 0;
  139. }
  140. /* Initialize rpc ids */
  141. if (msm_snd_init_rpc_ids()) {
  142. pr_err("%s: snd rpc ids initialization failed\n"
  143. , __func__);
  144. return -ENODATA;
  145. }
  146. snd_ep = msm_rpc_connect_compatible(snd_rpc_ids.prog,
  147. snd_rpc_ids.vers, 0);
  148. if (IS_ERR(snd_ep)) {
  149. pr_err("%s: failed (compatible VERS = %ld)\n",
  150. __func__, snd_rpc_ids.vers);
  151. snd_ep = NULL;
  152. return -EAGAIN;
  153. }
  154. return 0;
  155. }
  156. int msm_snd_rpc_close(void)
  157. {
  158. int rc = 0;
  159. if (IS_ERR(snd_ep)) {
  160. pr_err("%s: snd handle unavailable, rc = %ld\n",
  161. __func__, PTR_ERR(snd_ep));
  162. return -EAGAIN;
  163. }
  164. rc = msm_rpc_close(snd_ep);
  165. snd_ep = NULL;
  166. if (rc < 0) {
  167. pr_err("%s: close rpc failed! rc = %d\n",
  168. __func__, rc);
  169. return -EAGAIN;
  170. } else
  171. printk(KERN_INFO "rpc close success\n");
  172. return rc;
  173. }
  174. static int snd_msm_device_put(struct snd_kcontrol *kcontrol,
  175. struct snd_ctl_elem_value *ucontrol)
  176. {
  177. int rc = 0;
  178. struct snd_cad_set_device_msg {
  179. struct rpc_request_hdr hdr;
  180. struct rpc_cad_set_device_args args;
  181. } dmsg;
  182. snd_rpc_ids.device.rx_device
  183. = (int)ucontrol->value.integer.value[0];
  184. snd_rpc_ids.device.tx_device
  185. = (int)ucontrol->value.integer.value[1];
  186. snd_rpc_ids.device.pathtype = CAD_DEVICE_PATH_RX_TX;
  187. dmsg.args.device.rx_device
  188. = cpu_to_be32(snd_rpc_ids.device.rx_device);
  189. dmsg.args.device.tx_device
  190. = cpu_to_be32(snd_rpc_ids.device.tx_device);
  191. dmsg.args.device.pathtype = cpu_to_be32(CAD_DEVICE_PATH_RX_TX);
  192. dmsg.args.ear_mute = cpu_to_be32(ucontrol->value.integer.value[2]);
  193. dmsg.args.mic_mute = cpu_to_be32(ucontrol->value.integer.value[3]);
  194. if (!(dmsg.args.ear_mute == SND_MUTE_MUTED ||
  195. dmsg.args.ear_mute == SND_MUTE_UNMUTED) ||
  196. (!(dmsg.args.mic_mute == SND_MUTE_MUTED ||
  197. dmsg.args.ear_mute == SND_MUTE_UNMUTED))) {
  198. pr_err("snd_cad_ioctl set device: invalid mute status\n");
  199. rc = -EINVAL;
  200. return rc;
  201. }
  202. dmsg.args.cb_func = -1;
  203. dmsg.args.client_data = 0;
  204. rc = msm_rpc_call(snd_ep, snd_rpc_ids.rpc_set_snd_device ,
  205. &dmsg, sizeof(dmsg), 5 * HZ);
  206. if (rc < 0) {
  207. pr_err("%s: snd rpc call failed! rc = %d\n",
  208. __func__, rc);
  209. } else {
  210. printk(KERN_INFO "snd device connected\n");
  211. snd_mute_ear_mute = ucontrol->value.integer.value[2];
  212. snd_mute_mic_mute = ucontrol->value.integer.value[3];
  213. pr_err("%s: snd_mute_ear_mute =%d, snd_mute_mic_mute = %d\n",
  214. __func__, snd_mute_ear_mute, snd_mute_mic_mute);
  215. }
  216. return rc;
  217. }
  218. static int snd_msm_device_vol_info(struct snd_kcontrol *kcontrol,
  219. struct snd_ctl_elem_info *uinfo)
  220. {
  221. uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
  222. uinfo->count = 1; /* Device/Volume */
  223. /*
  224. * The volume ranges from (0 to 6)
  225. */
  226. uinfo->value.integer.min = 0;
  227. uinfo->value.integer.max = 6;
  228. return 0;
  229. }
  230. static int snd_msm_device_vol_put(struct snd_kcontrol *kcontrol,
  231. struct snd_ctl_elem_value *ucontrol)
  232. {
  233. int rc = 0;
  234. struct snd_cad_set_volume_msg {
  235. struct rpc_request_hdr hdr;
  236. struct rpc_cad_set_volume_args args;
  237. } vmsg;
  238. vmsg.args.device.rx_device
  239. = cpu_to_be32(snd_rpc_ids.device.rx_device);
  240. vmsg.args.device.tx_device
  241. = cpu_to_be32(snd_rpc_ids.device.tx_device);
  242. vmsg.args.method = cpu_to_be32(SND_METHOD_VOICE);
  243. vmsg.args.volume = cpu_to_be32(ucontrol->value.integer.value[0]);
  244. vmsg.args.cb_func = -1;
  245. vmsg.args.client_data = 0;
  246. rc = msm_rpc_call(snd_ep, snd_rpc_ids.rpc_set_device_vol ,
  247. &vmsg, sizeof(vmsg), 5 * HZ);
  248. if (rc < 0) {
  249. pr_err("%s: snd rpc call failed! rc = %d\n",
  250. __func__, rc);
  251. } else {
  252. pr_debug("%s:rx device [%d]", __func__,
  253. snd_rpc_ids.device.rx_device);
  254. pr_debug("%s:tx device [%d]", __func__,
  255. snd_rpc_ids.device.tx_device);
  256. pr_debug("%s:volume set to [%ld]\n", __func__,
  257. snd_rpc_ids.rpc_set_device_vol);
  258. }
  259. return rc;
  260. }
  261. /* Supported range -50dB to 18dB */
  262. static const DECLARE_TLV_DB_LINEAR(db_scale_linear, -5000, 1800);
  263. #define MSM_EXT(xname, xindex, fp_info, fp_get, fp_put, addr) \
  264. { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
  265. .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, \
  266. .name = xname, .index = xindex, \
  267. .info = fp_info,\
  268. .get = fp_get, .put = fp_put, \
  269. .private_value = addr, \
  270. }
  271. #define MSM_EXT_TLV(xname, xindex, fp_info, fp_get, fp_put, addr, tlv_array) \
  272. { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
  273. .access = (SNDRV_CTL_ELEM_ACCESS_TLV_READ | \
  274. SNDRV_CTL_ELEM_ACCESS_READWRITE), \
  275. .name = xname, .index = xindex, \
  276. .info = fp_info,\
  277. .get = fp_get, .put = fp_put, .tlv.p = tlv_array, \
  278. .private_value = addr, \
  279. }
  280. static struct snd_kcontrol_new snd_msm_controls[] = {
  281. MSM_EXT_TLV("PCM Playback Volume", 0, snd_msm_volume_info, \
  282. snd_msm_volume_get, snd_msm_volume_put, 0, db_scale_linear),
  283. MSM_EXT("device", 0, snd_msm_device_info, snd_msm_device_get, \
  284. snd_msm_device_put, 0),
  285. MSM_EXT("Device Volume", 0, snd_msm_device_vol_info, NULL, \
  286. snd_msm_device_vol_put, 0),
  287. };
  288. static int msm_new_mixer(struct snd_soc_codec *codec)
  289. {
  290. unsigned int idx;
  291. int err;
  292. pr_err("msm_soc: ALSA MSM Mixer Setting\n");
  293. strcpy(codec->card->snd_card->mixername, "MSM Mixer");
  294. for (idx = 0; idx < ARRAY_SIZE(snd_msm_controls); idx++) {
  295. err = snd_ctl_add(codec->card->snd_card,
  296. snd_ctl_new1(&snd_msm_controls[idx], NULL));
  297. if (err < 0)
  298. return err;
  299. }
  300. return 0;
  301. }
  302. static int msm_soc_dai_init(
  303. struct snd_soc_pcm_runtime *rtd)
  304. {
  305. int ret = 0;
  306. struct snd_soc_codec *codec = rtd->codec;
  307. mutex_init(&the_locks.lock);
  308. mutex_init(&the_locks.write_lock);
  309. mutex_init(&the_locks.read_lock);
  310. spin_lock_init(&the_locks.read_dsp_lock);
  311. spin_lock_init(&the_locks.write_dsp_lock);
  312. spin_lock_init(&the_locks.mixer_lock);
  313. init_waitqueue_head(&the_locks.eos_wait);
  314. init_waitqueue_head(&the_locks.write_wait);
  315. init_waitqueue_head(&the_locks.read_wait);
  316. msm_vol_ctl.volume = MSM_PLAYBACK_DEFAULT_VOLUME;
  317. msm_vol_ctl.pan = MSM_PLAYBACK_DEFAULT_PAN;
  318. ret = msm_new_mixer(codec);
  319. if (ret < 0) {
  320. pr_err("msm_soc: ALSA MSM Mixer Fail\n");
  321. }
  322. return ret;
  323. }
  324. static struct snd_soc_dai_link msm_dai[] = {
  325. {
  326. .name = "MSM Primary I2S",
  327. .stream_name = "DSP 1",
  328. .cpu_dai_name = "msm-cpu-dai.0",
  329. .platform_name = "msm-dsp-audio.0",
  330. .codec_name = "msm-codec-dai.0",
  331. .codec_dai_name = "msm-codec-dai",
  332. .init = &msm_soc_dai_init,
  333. },
  334. };
  335. static struct snd_soc_card snd_soc_card_msm = {
  336. .name = "msm-audio",
  337. .dai_link = msm_dai,
  338. .num_links = ARRAY_SIZE(msm_dai),
  339. };
  340. static int __init msm_audio_init(void)
  341. {
  342. int ret;
  343. msm_audio_snd_device = platform_device_alloc("soc-audio", -1);
  344. if (!msm_audio_snd_device)
  345. return -ENOMEM;
  346. platform_set_drvdata(msm_audio_snd_device, &snd_soc_card_msm);
  347. ret = platform_device_add(msm_audio_snd_device);
  348. if (ret) {
  349. platform_device_put(msm_audio_snd_device);
  350. return ret;
  351. }
  352. ret = msm_snd_rpc_connect();
  353. snd_mute_ear_mute = 0;
  354. snd_mute_mic_mute = 0;
  355. return ret;
  356. }
  357. static void __exit msm_audio_exit(void)
  358. {
  359. msm_snd_rpc_close();
  360. platform_device_unregister(msm_audio_snd_device);
  361. }
  362. module_init(msm_audio_init);
  363. module_exit(msm_audio_exit);
  364. MODULE_DESCRIPTION("PCM module");
  365. MODULE_LICENSE("GPL v2");