audio_evrc.c 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184
  1. /* evrc audio output device
  2. *
  3. * Copyright (C) 2008 Google, Inc.
  4. * Copyright (C) 2008 HTC Corporation
  5. * Copyright (c) 2011-2017, The Linux Foundation. All rights reserved.
  6. *
  7. * This software is licensed under the terms of the GNU General Public
  8. * License version 2, as published by the Free Software Foundation, and
  9. * may be copied, distributed, and modified under those terms.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. */
  17. #include "audio_utils_aio.h"
  18. static struct miscdevice audio_evrc_misc;
  19. static struct ws_mgr audio_evrc_ws_mgr;
  20. #ifdef CONFIG_DEBUG_FS
  21. static const struct file_operations audio_evrc_debug_fops = {
  22. .read = audio_aio_debug_read,
  23. .open = audio_aio_debug_open,
  24. };
  25. #endif
  26. static long audio_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
  27. {
  28. struct q6audio_aio *audio = file->private_data;
  29. int rc = 0;
  30. switch (cmd) {
  31. case AUDIO_START: {
  32. pr_debug("%s[%pK]: AUDIO_START session_id[%d]\n", __func__,
  33. audio, audio->ac->session);
  34. if (audio->feedback == NON_TUNNEL_MODE) {
  35. /* Configure PCM output block */
  36. rc = q6asm_enc_cfg_blk_pcm(audio->ac,
  37. audio->pcm_cfg.sample_rate,
  38. audio->pcm_cfg.channel_count);
  39. if (rc < 0) {
  40. pr_err("pcm output block config failed\n");
  41. break;
  42. }
  43. }
  44. rc = audio_aio_enable(audio);
  45. audio->eos_rsp = 0;
  46. audio->eos_flag = 0;
  47. if (!rc) {
  48. audio->enabled = 1;
  49. } else {
  50. audio->enabled = 0;
  51. pr_err("Audio Start procedure failed rc=%d\n", rc);
  52. break;
  53. }
  54. pr_debug("%s: AUDIO_START sessionid[%d]enable[%d]\n", __func__,
  55. audio->ac->session,
  56. audio->enabled);
  57. if (audio->stopped == 1)
  58. audio->stopped = 0;
  59. break;
  60. }
  61. default:
  62. pr_debug("%s[%pK]: Calling utils ioctl\n", __func__, audio);
  63. rc = audio->codec_ioctl(file, cmd, arg);
  64. }
  65. return rc;
  66. }
  67. static int audio_open(struct inode *inode, struct file *file)
  68. {
  69. struct q6audio_aio *audio = NULL;
  70. int rc = 0;
  71. #ifdef CONFIG_DEBUG_FS
  72. /* 4 bytes represents decoder number, 1 byte for terminate string */
  73. char name[sizeof "msm_evrc_" + 5];
  74. #endif
  75. audio = kzalloc(sizeof(struct q6audio_aio), GFP_KERNEL);
  76. if (audio == NULL)
  77. return -ENOMEM;
  78. /* Settings will be re-config at AUDIO_SET_CONFIG,
  79. * but at least we need to have initial config
  80. */
  81. audio->pcm_cfg.buffer_size = PCM_BUFSZ_MIN;
  82. audio->miscdevice = &audio_evrc_misc;
  83. audio->wakelock_voted = false;
  84. audio->audio_ws_mgr = &audio_evrc_ws_mgr;
  85. audio->ac = q6asm_audio_client_alloc((app_cb) q6_audio_cb,
  86. (void *)audio);
  87. if (!audio->ac) {
  88. pr_err("Could not allocate memory for audio client\n");
  89. kfree(audio);
  90. return -ENOMEM;
  91. }
  92. rc = audio_aio_open(audio, file);
  93. if (rc < 0) {
  94. pr_err("%s: audio_aio_open rc=%d\n",
  95. __func__, rc);
  96. goto fail;
  97. }
  98. /* open in T/NT mode */
  99. if ((file->f_mode & FMODE_WRITE) && (file->f_mode & FMODE_READ)) {
  100. rc = q6asm_open_read_write(audio->ac, FORMAT_LINEAR_PCM,
  101. FORMAT_EVRC);
  102. if (rc < 0) {
  103. pr_err("NT mode Open failed rc=%d\n", rc);
  104. rc = -ENODEV;
  105. goto fail;
  106. }
  107. audio->feedback = NON_TUNNEL_MODE;
  108. audio->buf_cfg.frames_per_buf = 0x01;
  109. audio->buf_cfg.meta_info_enable = 0x01;
  110. } else if ((file->f_mode & FMODE_WRITE) &&
  111. !(file->f_mode & FMODE_READ)) {
  112. rc = q6asm_open_write(audio->ac, FORMAT_EVRC);
  113. if (rc < 0) {
  114. pr_err("T mode Open failed rc=%d\n", rc);
  115. rc = -ENODEV;
  116. goto fail;
  117. }
  118. audio->feedback = TUNNEL_MODE;
  119. audio->buf_cfg.meta_info_enable = 0x00;
  120. } else {
  121. pr_err("Not supported mode\n");
  122. rc = -EACCES;
  123. goto fail;
  124. }
  125. #ifdef CONFIG_DEBUG_FS
  126. snprintf(name, sizeof(name), "msm_evrc_%04x", audio->ac->session);
  127. audio->dentry = debugfs_create_file(name, S_IFREG | 0444,
  128. NULL, (void *)audio,
  129. &audio_evrc_debug_fops);
  130. if (IS_ERR(audio->dentry))
  131. pr_debug("debugfs_create_file failed\n");
  132. #endif
  133. pr_info("%s:dec success mode[%d]session[%d]\n", __func__,
  134. audio->feedback,
  135. audio->ac->session);
  136. return rc;
  137. fail:
  138. q6asm_audio_client_free(audio->ac);
  139. kfree(audio);
  140. return rc;
  141. }
  142. static const struct file_operations audio_evrc_fops = {
  143. .owner = THIS_MODULE,
  144. .open = audio_open,
  145. .release = audio_aio_release,
  146. .unlocked_ioctl = audio_ioctl,
  147. .fsync = audio_aio_fsync,
  148. };
  149. static struct miscdevice audio_evrc_misc = {
  150. .minor = MISC_DYNAMIC_MINOR,
  151. .name = "msm_evrc",
  152. .fops = &audio_evrc_fops,
  153. };
  154. static int __init audio_evrc_init(void)
  155. {
  156. int ret = misc_register(&audio_evrc_misc);
  157. if (ret == 0)
  158. device_init_wakeup(audio_evrc_misc.this_device, true);
  159. audio_evrc_ws_mgr.ref_cnt = 0;
  160. mutex_init(&audio_evrc_ws_mgr.ws_lock);
  161. return ret;
  162. }
  163. device_initcall(audio_evrc_init);