/arch/arm/mach-fsm/qdsp6/audiov2/voice.c

https://bitbucket.org/sammyz/iscream_thunderc-2.6.35-rebase · C · 193 lines · 148 code · 28 blank · 17 comment · 7 complexity · d43b8b7830d98c72ef9848e2b4962143 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. */
  18. #include <linux/kernel.h>
  19. #include <linux/module.h>
  20. #include <linux/miscdevice.h>
  21. #include <linux/uaccess.h>
  22. #include <linux/fs.h>
  23. #include <linux/mutex.h>
  24. #include <linux/sched.h>
  25. #include <linux/kthread.h>
  26. #include <linux/completion.h>
  27. #include <linux/wait.h>
  28. #include <mach/msm_qdsp6_audiov2.h>
  29. #include "../dal.h"
  30. #include "dal_voice.h"
  31. #include <mach/debug_mm.h>
  32. struct voice_struct {
  33. struct dal_client *cvd;
  34. struct apr_command_pkt apr_pkt;
  35. struct completion compl;
  36. };
  37. static struct voice_struct voice;
  38. static int cvd_send_response(void)
  39. {
  40. struct apr_command_pkt *pkt;
  41. uint16_t src_addr;
  42. uint16_t src_token;
  43. uint16_t dst_token;
  44. uint16_t dst_addr;
  45. pkt = &voice.apr_pkt;
  46. src_addr = pkt->dst_addr;
  47. dst_addr = pkt->src_addr;
  48. src_token = pkt->dst_token;
  49. dst_token = pkt->src_token;
  50. pkt->header &= ~APR_PKTV1_TYPE_MASK;
  51. pkt->header |= APR_SET_FIELD(APR_PKTV1_TYPE, APR_PKTV1_TYPE_EVENT_V);
  52. pkt->src_addr = src_addr;
  53. pkt->dst_addr = dst_addr;
  54. pkt->src_token = src_token;
  55. pkt->dst_token = dst_token;
  56. pkt->opcode = APR_IBASIC_RSP_RESULT;
  57. dal_call(voice.cvd, VOICE_OP_CONTROL, 5, pkt,
  58. sizeof(struct apr_command_pkt),
  59. pkt, sizeof(u32));
  60. return 0;
  61. }
  62. static int cvd_process_voice_setup(void)
  63. {
  64. q6voice_setup();
  65. cvd_send_response();
  66. return 0;
  67. }
  68. static int cvd_process_voice_teardown(void)
  69. {
  70. q6voice_teardown();
  71. cvd_send_response();
  72. return 0;
  73. }
  74. static int cvd_process_set_network(void)
  75. {
  76. cvd_send_response();
  77. return 0;
  78. }
  79. static int voice_thread(void *data)
  80. {
  81. while (!kthread_should_stop()) {
  82. wait_for_completion(&voice.compl);
  83. init_completion(&voice.compl);
  84. switch (voice.apr_pkt.opcode) {
  85. case APR_OP_CMD_CREATE:
  86. cvd_send_response();
  87. break;
  88. case VOICE_OP_CMD_BRINGUP:
  89. cvd_process_voice_setup();
  90. break;
  91. case APR_OP_CMD_DESTROY:
  92. cvd_send_response();
  93. break;
  94. case VOICE_OP_CMD_TEARDOWN:
  95. cvd_process_voice_teardown();
  96. break;
  97. case VOICE_OP_CMD_SET_NETWORK:
  98. cvd_process_set_network();
  99. break;
  100. default:
  101. pr_err("[%s:%s] Undefined event\n", __MM_FILE__,
  102. __func__);
  103. }
  104. }
  105. return 0;
  106. }
  107. static void remote_cb_function(void *data, int len, void *cookie)
  108. {
  109. struct apr_command_pkt *apr = data + 2*sizeof(uint32_t);
  110. memcpy(&voice.apr_pkt, apr, sizeof(struct apr_command_pkt));
  111. if (len <= 0) {
  112. pr_err("[%s:%s] unexpected event with length %d\n",
  113. __MM_FILE__, __func__, len);
  114. return;
  115. }
  116. pr_debug("[%s:%s] APR = %x,%x,%x,%x,%x,%x,%x,%x,%x,%x\n", __MM_FILE__,
  117. __func__,
  118. apr->header,
  119. apr->reserved1,
  120. apr->src_addr,
  121. apr->dst_addr,
  122. apr->ret_addr,
  123. apr->src_token,
  124. apr->dst_token,
  125. apr->ret_token,
  126. apr->context,
  127. apr->opcode);
  128. complete(&voice.compl);
  129. }
  130. static int __init voice_init(void)
  131. {
  132. int res = 0;
  133. struct task_struct *task;
  134. u32 tmp[2];
  135. tmp[0] = sizeof(u32);
  136. tmp[1] = 0;
  137. voice.cvd = dal_attach(VOICE_DAL_DEVICE, VOICE_DAL_PORT, 0,
  138. remote_cb_function, 0);
  139. if (!voice.cvd) {
  140. pr_err("[%s:%s] audio_init: cannot attach to cvd\n",
  141. __MM_FILE__, __func__);
  142. res = -ENODEV;
  143. goto done;
  144. }
  145. if (check_version(voice.cvd, VOICE_DAL_VERSION) != 0) {
  146. pr_err("[%s:%s] Incompatible cvd version\n",
  147. __MM_FILE__, __func__);
  148. res = -ENODEV;
  149. goto done;
  150. }
  151. dal_call(voice.cvd, VOICE_OP_INIT, 5, tmp, sizeof(tmp),
  152. tmp, sizeof(u32));
  153. init_completion(&voice.compl);
  154. task = kthread_run(voice_thread, &voice, "voice_thread");
  155. if (IS_ERR(task)) {
  156. pr_err("[%s:%s] Cannot start the voice thread\n", __MM_FILE__,
  157. __func__);
  158. res = PTR_ERR(task);
  159. task = NULL;
  160. } else
  161. goto done;
  162. done:
  163. return res;
  164. }
  165. late_initcall(voice_init);