msm_common.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463
  1. /* Copyright (c) 2020, 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. #include <linux/gpio.h>
  13. #include <linux/of_gpio.h>
  14. #include <linux/platform_device.h>
  15. #include <linux/slab.h>
  16. #include <linux/of_device.h>
  17. #include <sound/control.h>
  18. #include <sound/core.h>
  19. #include <sound/soc.h>
  20. #include <asoc/msm-cdc-pinctrl.h>
  21. #include <dsp/spf-core.h>
  22. #include <dsp/msm_audio_ion.h>
  23. #include <sound/info.h>
  24. #include "msm_common.h"
  25. #define to_asoc_mach_common_pdata(kobj) \
  26. container_of((kobj), struct msm_common_pdata, aud_dev_kobj)
  27. #define DEVICE_ENABLE 1
  28. #define DEVICE_DISABLE 0
  29. #define ARRAY_SZ 21
  30. static struct attribute device_state_attr = {
  31. .name = "state",
  32. .mode = 0660,
  33. };
  34. #define MAX_PORT 20
  35. #define CODEC_CHMAP "Channel Map"
  36. enum backend_id {
  37. SLIM = 1,
  38. CODEC_DMA,
  39. };
  40. struct chmap_pdata {
  41. int id;
  42. struct snd_soc_dai *dai;
  43. };
  44. #define MAX_USR_INPUT 10
  45. static ssize_t aud_dev_sysfs_store(struct kobject *kobj,
  46. struct attribute *attr,
  47. const char *buf, size_t count)
  48. {
  49. ssize_t ret = -EINVAL;
  50. struct msm_common_pdata *pdata = to_asoc_mach_common_pdata(kobj);
  51. uint32_t pcm_id, state = 0;
  52. if (count > MAX_USR_INPUT) {
  53. pr_err("%s: invalid string written", __func__);
  54. goto done;
  55. }
  56. sscanf(buf, "%d %d", &pcm_id, &state);
  57. if ((pcm_id > pdata->num_aud_devs) || (pcm_id < 0)) {
  58. pr_err("%s: invalid pcm id %d \n", __func__, pcm_id);
  59. goto done;
  60. }
  61. if ((state > DEVICE_ENABLE) || (state < DEVICE_DISABLE)) {
  62. pr_err("%s: invalid state %d \n", __func__, state);
  63. goto done;
  64. }
  65. pr_debug("%s: pcm_id %d state %d \n", __func__, pcm_id, state);
  66. pdata->aud_dev_state[pcm_id] = state;
  67. if ( state == DEVICE_ENABLE && (pdata->dsp_sessions_closed != 0))
  68. pdata->dsp_sessions_closed = 0;
  69. ret = count;
  70. done:
  71. return ret;
  72. }
  73. static const struct sysfs_ops aud_dev_sysfs_ops = {
  74. .store = aud_dev_sysfs_store,
  75. };
  76. static struct kobj_type aud_dev_ktype = {
  77. .sysfs_ops = &aud_dev_sysfs_ops,
  78. };
  79. static int aud_dev_sysfs_init(struct msm_common_pdata *pdata)
  80. {
  81. int ret = 0;
  82. char dir[10] = "aud_dev";
  83. ret = kobject_init_and_add(&pdata->aud_dev_kobj, &aud_dev_ktype,
  84. kernel_kobj, dir);
  85. if (ret < 0) {
  86. pr_err("%s: Failed to add kobject %s, err = %d\n",
  87. __func__, dir, ret);
  88. goto done;
  89. }
  90. ret = sysfs_create_file(&pdata->aud_dev_kobj, &device_state_attr);
  91. if (ret < 0) {
  92. pr_err("%s: Failed to add wdsp_boot sysfs entry to %s\n",
  93. __func__, dir);
  94. goto fail_create_file;
  95. }
  96. return ret;
  97. fail_create_file:
  98. kobject_put(&pdata->aud_dev_kobj);
  99. done:
  100. return ret;
  101. }
  102. static void check_userspace_service_state(struct snd_soc_pcm_runtime *rtd,
  103. struct msm_common_pdata *pdata)
  104. {
  105. dev_info(rtd->card->dev,"%s: pcm_id %d state %d\n", __func__,
  106. rtd->num, pdata->aud_dev_state[rtd->num]);
  107. if (pdata->aud_dev_state[rtd->num] == DEVICE_ENABLE) {
  108. dev_info(rtd->card->dev, "%s userspace service crashed\n",
  109. __func__);
  110. if (pdata->dsp_sessions_closed == 0) {
  111. /*Issue close all graph cmd to DSP*/
  112. spf_core_apm_close_all();
  113. /*unmap all dma mapped buffers*/
  114. msm_audio_ion_crash_handler();
  115. pdata->dsp_sessions_closed = 1;
  116. }
  117. /*Reset the state as sysfs node wont be triggred*/
  118. pdata->aud_dev_state[rtd->num] = 0;
  119. }
  120. }
  121. static int get_intf_index(const char *stream_name)
  122. {
  123. if (strnstr(stream_name, "PRIMARY", strlen(stream_name)))
  124. return PRI_MI2S_TDM_AUXPCM;
  125. else if (strnstr(stream_name, "SECONDARY", strlen(stream_name)))
  126. return SEC_MI2S_TDM_AUXPCM;
  127. else if (strnstr(stream_name, "TERTIARY", strlen(stream_name)))
  128. return TER_MI2S_TDM_AUXPCM;
  129. else if (strnstr(stream_name, "QUATERNARY", strlen(stream_name)))
  130. return QUAT_MI2S_TDM_AUXPCM;
  131. else if (strnstr(stream_name, "QUINARY", strlen(stream_name)))
  132. return QUIN_MI2S_TDM_AUXPCM;
  133. else if (strnstr(stream_name, "SENARY", strlen(stream_name)))
  134. return SEN_MI2S_TDM_AUXPCM;
  135. else {
  136. pr_debug("%s: stream name %s does not match\n", __func__, stream_name);
  137. return -EINVAL;
  138. }
  139. }
  140. int msm_common_snd_startup(struct snd_pcm_substream *substream)
  141. {
  142. int ret = 0;
  143. struct snd_soc_pcm_runtime *rtd = substream->private_data;
  144. struct snd_soc_card *card = rtd->card;
  145. struct msm_common_pdata *pdata = msm_common_get_pdata(card);
  146. const char *stream_name = rtd->dai_link->stream_name;
  147. int index = get_intf_index(stream_name);
  148. dev_dbg(rtd->card->dev,
  149. "%s: substream = %s stream = %d\n",
  150. __func__, substream->name, substream->stream);
  151. if (!pdata) {
  152. dev_err(rtd->card->dev, "%s: pdata is NULL\n", __func__);
  153. return -EINVAL;
  154. }
  155. if (index >= 0) {
  156. mutex_lock(&pdata->lock[index]);
  157. if (pdata->mi2s_gpio_p[index]) {
  158. if (atomic_read(&(pdata->mi2s_gpio_ref_cnt[index])) == 0) {
  159. ret = msm_cdc_pinctrl_select_active_state(
  160. pdata->mi2s_gpio_p[index]);
  161. if (ret) {
  162. pr_err("%s:pinctrl set actve fail with %d\n",
  163. __func__, ret);
  164. goto done;
  165. }
  166. }
  167. atomic_inc(&(pdata->mi2s_gpio_ref_cnt[index]));
  168. }
  169. done:
  170. mutex_unlock(&pdata->lock[index]);
  171. }
  172. return ret;
  173. }
  174. void msm_common_snd_shutdown(struct snd_pcm_substream *substream)
  175. {
  176. int ret;
  177. struct snd_soc_pcm_runtime *rtd = substream->private_data;
  178. struct snd_soc_card *card = rtd->card;
  179. struct msm_common_pdata *pdata = msm_common_get_pdata(card);
  180. const char *stream_name = rtd->dai_link->stream_name;
  181. int index = get_intf_index(stream_name);
  182. pr_debug("%s(): substream = %s stream = %d\n", __func__,
  183. substream->name, substream->stream);
  184. if (!pdata) {
  185. dev_err(card->dev, "%s: pdata is NULL\n", __func__);
  186. return;
  187. }
  188. check_userspace_service_state(rtd, pdata);
  189. if (index >= 0) {
  190. mutex_lock(&pdata->lock[index]);
  191. if (pdata->mi2s_gpio_p[index]) {
  192. atomic_dec(&pdata->mi2s_gpio_ref_cnt[index]);
  193. if (atomic_read(&pdata->mi2s_gpio_ref_cnt[index]) == 0) {
  194. ret = msm_cdc_pinctrl_select_active_state(
  195. pdata->mi2s_gpio_p[index]);
  196. if (ret)
  197. dev_err(card->dev,
  198. "%s: pinctrl set actv fail %d\n",
  199. __func__, ret);
  200. }
  201. }
  202. mutex_unlock(&pdata->lock[index]);
  203. }
  204. }
  205. int msm_common_snd_init(struct platform_device *pdev, struct snd_soc_card *card)
  206. {
  207. struct msm_common_pdata *common_pdata = NULL;
  208. int count;
  209. common_pdata = kcalloc(1, sizeof(struct msm_common_pdata), GFP_KERNEL);
  210. if (!common_pdata)
  211. return -ENOMEM;
  212. for (count = 0; count < MI2S_TDM_AUXPCM_MAX; count++) {
  213. mutex_init(&common_pdata->lock[count]);
  214. atomic_set(&common_pdata->mi2s_gpio_ref_cnt[count], 0);
  215. }
  216. common_pdata->mi2s_gpio_p[PRI_MI2S_TDM_AUXPCM] = of_parse_phandle(pdev->dev.of_node,
  217. "qcom,pri-mi2s-gpios", 0);
  218. common_pdata->mi2s_gpio_p[SEC_MI2S_TDM_AUXPCM] = of_parse_phandle(pdev->dev.of_node,
  219. "qcom,sec-mi2s-gpios", 0);
  220. common_pdata->mi2s_gpio_p[TER_MI2S_TDM_AUXPCM] = of_parse_phandle(pdev->dev.of_node,
  221. "qcom,tert-mi2s-gpios", 0);
  222. common_pdata->mi2s_gpio_p[QUAT_MI2S_TDM_AUXPCM] = of_parse_phandle(pdev->dev.of_node,
  223. "qcom,quat-mi2s-gpios", 0);
  224. common_pdata->mi2s_gpio_p[QUIN_MI2S_TDM_AUXPCM] = of_parse_phandle(pdev->dev.of_node,
  225. "qcom,quin-mi2s-gpios", 0);
  226. common_pdata->mi2s_gpio_p[SEN_MI2S_TDM_AUXPCM] = of_parse_phandle(pdev->dev.of_node,
  227. "qcom,sen-mi2s-gpios", 0);
  228. common_pdata->aud_dev_state = devm_kcalloc(&pdev->dev, card->num_links,
  229. sizeof(uint8_t), GFP_KERNEL);
  230. dev_info(&pdev->dev, "num_links %d \n", card->num_links);
  231. common_pdata->num_aud_devs = card->num_links;
  232. aud_dev_sysfs_init(common_pdata);
  233. msm_common_set_pdata(card, common_pdata);
  234. return 0;
  235. };
  236. void msm_common_snd_deinit(struct msm_common_pdata *common_pdata)
  237. {
  238. int count;
  239. if (!common_pdata)
  240. return;
  241. for (count = 0; count < MI2S_TDM_AUXPCM_MAX; count++) {
  242. mutex_destroy(&common_pdata->lock[count]);
  243. }
  244. }
  245. int msm_channel_map_info(struct snd_kcontrol *kcontrol,
  246. struct snd_ctl_elem_info *uinfo)
  247. {
  248. uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES;
  249. uinfo->count = sizeof(uint32_t) * MAX_PORT;
  250. return 0;
  251. }
  252. int msm_channel_map_get(struct snd_kcontrol *kcontrol,
  253. struct snd_ctl_elem_value *ucontrol)
  254. {
  255. struct chmap_pdata *kctl_pdata =
  256. (struct chmap_pdata *)kcontrol->private_data;
  257. struct snd_soc_dai *codec_dai = kctl_pdata->dai;
  258. int backend_id = kctl_pdata->id;
  259. uint32_t rx_ch[MAX_PORT], tx_ch[MAX_PORT];
  260. uint32_t rx_ch_cnt = 0, tx_ch_cnt = 0;
  261. uint32_t *chmap_data = NULL;
  262. int ret = 0, len = 0;
  263. if (kctl_pdata == NULL) {
  264. pr_debug("%s: chmap_pdata is not initialized\n", __func__);
  265. return -EINVAL;
  266. }
  267. ret = snd_soc_dai_get_channel_map(codec_dai,
  268. &tx_ch_cnt, tx_ch, &rx_ch_cnt, rx_ch);
  269. if (ret || (tx_ch_cnt == 0 && rx_ch_cnt == 0)) {
  270. pr_err("%s: get channel map failed for %d\n",
  271. __func__, backend_id);
  272. return ret;
  273. }
  274. switch (backend_id) {
  275. case SLIM: {
  276. uint32_t *chmap;
  277. uint32_t ch_cnt, i;
  278. if (rx_ch_cnt) {
  279. chmap = rx_ch;
  280. ch_cnt = rx_ch_cnt;
  281. } else {
  282. chmap = tx_ch;
  283. ch_cnt = tx_ch_cnt;
  284. }
  285. len = sizeof(uint32_t) * (ch_cnt + 1);
  286. chmap_data = kzalloc(len, GFP_KERNEL);
  287. if (!chmap_data)
  288. return -ENOMEM;
  289. chmap_data[0] = ch_cnt;
  290. for (i = 0; i < ch_cnt; i++)
  291. chmap_data[i+1] = chmap[i];
  292. memcpy(ucontrol->value.bytes.data, chmap_data, len);
  293. break;
  294. }
  295. case CODEC_DMA: {
  296. chmap_data = kzalloc(sizeof(uint32_t) * 2, GFP_KERNEL);
  297. if (!chmap_data)
  298. return -ENOMEM;
  299. if (rx_ch_cnt) {
  300. chmap_data[0] = rx_ch_cnt;
  301. chmap_data[1] = rx_ch[0];
  302. } else {
  303. chmap_data[0] = tx_ch_cnt;
  304. chmap_data[1] = tx_ch[0];
  305. }
  306. memcpy(ucontrol->value.bytes.data, chmap_data,
  307. sizeof(uint32_t) * 2);
  308. break;
  309. }
  310. default:
  311. pr_err("%s, Invalid backend %d\n", __func__, backend_id);
  312. ret = -EINVAL;
  313. break;
  314. }
  315. kfree(chmap_data);
  316. return ret;
  317. }
  318. void msm_common_get_backend_name(const char *stream_name, char **backend_name)
  319. {
  320. char arg[ARRAY_SZ] = {0};
  321. char value[61] = {0};
  322. sscanf(stream_name, "%20[^-]-%60s", arg, value);
  323. *backend_name = kzalloc(ARRAY_SZ, GFP_KERNEL);
  324. if (!(*backend_name))
  325. return;
  326. strlcpy(*backend_name, arg, ARRAY_SZ);
  327. }
  328. int msm_common_dai_link_init(struct snd_soc_pcm_runtime *rtd)
  329. {
  330. struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
  331. struct snd_soc_component *component = NULL;
  332. struct snd_soc_dai_link *dai_link = rtd->dai_link;
  333. struct device *dev = rtd->card->dev;
  334. int ret = 0;
  335. const char *mixer_ctl_name = CODEC_CHMAP;
  336. char *mixer_str = NULL;
  337. char *backend_name = NULL;
  338. uint32_t ctl_len = 0;
  339. struct chmap_pdata *pdata;
  340. struct snd_kcontrol *kctl;
  341. struct snd_kcontrol_new msm_common_channel_map[1] = {
  342. {
  343. .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
  344. .name = "?",
  345. .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
  346. .info = msm_channel_map_info,
  347. .get = msm_channel_map_get,
  348. .private_value = 0,
  349. }
  350. };
  351. if (!codec_dai) {
  352. pr_err("%s: failed to get codec dai", __func__);
  353. return -EINVAL;
  354. }
  355. component = codec_dai->component;
  356. msm_common_get_backend_name(dai_link->stream_name, &backend_name);
  357. if (!backend_name) {
  358. pr_err("%s: failed to get backend name", __func__);
  359. return -EINVAL;
  360. }
  361. pdata = devm_kzalloc(dev, sizeof(struct chmap_pdata), GFP_KERNEL);
  362. if (!pdata)
  363. return -ENOMEM;
  364. if ((!strncmp(backend_name, "SLIM", strlen("SLIM"))) ||
  365. (!strncmp(backend_name, "CODEC_DMA", strlen("CODEC_DMA")))) {
  366. ctl_len = strlen(dai_link->stream_name) + 1 +
  367. strlen(mixer_ctl_name) + 1;
  368. mixer_str = kzalloc(ctl_len, GFP_KERNEL);
  369. if (!mixer_str)
  370. return -ENOMEM;
  371. snprintf(mixer_str, ctl_len, "%s %s", dai_link->stream_name,
  372. mixer_ctl_name);
  373. msm_common_channel_map[0].name = mixer_str;
  374. msm_common_channel_map[0].private_value = 0;
  375. pr_debug("Registering new mixer ctl %s\n", mixer_str);
  376. ret = snd_soc_add_component_controls(component,
  377. msm_common_channel_map,
  378. ARRAY_SIZE(msm_common_channel_map));
  379. kctl = snd_soc_card_get_kcontrol(rtd->card, mixer_str);
  380. if (!kctl) {
  381. pr_err("failed to get kctl %s\n", mixer_str);
  382. ret = -EINVAL;
  383. goto free_mixer_str;
  384. }
  385. if (!strncmp(backend_name, "SLIM", strlen("SLIM")))
  386. pdata->id = SLIM;
  387. else
  388. pdata->id = CODEC_DMA;
  389. pdata->dai = codec_dai;
  390. kctl->private_data = pdata;
  391. free_mixer_str:
  392. kfree(backend_name);
  393. kfree(mixer_str);
  394. }
  395. return ret;
  396. }