PageRenderTime 54ms CodeModel.GetById 20ms app.highlight 25ms RepoModel.GetById 3ms app.codeStats 0ms

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