blob: e059efaefa5cdff9cad893329fb02a30c143e531 [file] [log] [blame]
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001/*
2 * Copyright (C) 2009 Google, Inc.
3 * Copyright (C) 2009 HTC Corporation
Duy Truong790f06d2013-02-13 16:38:12 -08004 * Copyright (c) 2010, The Linux Foundation. All rights reserved.
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07005 *
6 * This software is licensed under the terms of the GNU General Public
7 * License version 2, as published by the Free Software Foundation, and
8 * may be copied, distributed, and modified under those terms.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 */
16
17#include <linux/slab.h>
18#include <linux/fs.h>
19#include <linux/module.h>
20#include <linux/miscdevice.h>
21#include <linux/mutex.h>
22#include <linux/sched.h>
23#include <linux/wait.h>
24#include <linux/uaccess.h>
25#include <linux/kthread.h>
26#include <linux/time.h>
27#include <linux/wait.h>
28
29#include <linux/msm_audio_qcp.h>
30#include <mach/msm_qdsp6_audio.h>
31#include "dal_audio_format.h"
32#include <mach/debug_mm.h>
33
34#define EVRC_FC_BUFF_CNT 10
35#define EVRC_READ_TIMEOUT 2000
36struct evrc_fc_buff {
37 struct mutex lock;
38 int empty;
39 void *data;
40 int size;
41 int actual_size;
42};
43
44struct evrc_fc {
45 struct task_struct *task;
46 wait_queue_head_t fc_wq;
47 struct evrc_fc_buff fc_buff[EVRC_FC_BUFF_CNT];
48 int buff_index;
49};
50
51struct evrc {
52 struct mutex lock;
53 struct msm_audio_evrc_enc_config cfg;
54 struct msm_audio_stream_config str_cfg;
55 struct audio_client *audio_client;
56 struct msm_voicerec_mode voicerec_mode;
57 struct evrc_fc *evrc_fc;
58};
59
60
61static int q6_evrc_flowcontrol(void *data)
62{
63 struct audio_client *ac;
64 struct audio_buffer *ab;
65 struct evrc *evrc = data;
66 int buff_index = 0;
67 int xfer = 0;
68 struct evrc_fc *fc;
69
70
71 ac = evrc->audio_client;
72 fc = evrc->evrc_fc;
73 if (!ac) {
74 pr_err("[%s:%s] audio_client is NULL\n", __MM_FILE__, __func__);
75 return 0;
76 }
77
78 while (!kthread_should_stop()) {
79 ab = ac->buf + ac->cpu_buf;
80 if (ab->used)
81 wait_event(ac->wait, (ab->used == 0));
82 pr_debug("[%s:%s] ab->data = %p, cpu_buf = %d\n", __MM_FILE__,
83 __func__, ab->data, ac->cpu_buf);
84 xfer = ab->actual_size;
85
86
87 mutex_lock(&(fc->fc_buff[buff_index].lock));
88 if (!fc->fc_buff[buff_index].empty) {
89 pr_err("[%s:%s] flow control buffer[%d] not read!\n",
90 __MM_FILE__, __func__, buff_index);
91 }
92
93 if (fc->fc_buff[buff_index].size < xfer) {
94 pr_err("[%s:%s] buffer %d too small\n", __MM_FILE__,
95 __func__, buff_index);
96 memcpy(fc->fc_buff[buff_index].data, ab->data,
97 fc->fc_buff[buff_index].size);
98 fc->fc_buff[buff_index].empty = 0;
99 fc->fc_buff[buff_index].actual_size =
100 fc->fc_buff[buff_index].size;
101 } else {
102 memcpy(fc->fc_buff[buff_index].data, ab->data, xfer);
103 fc->fc_buff[buff_index].empty = 0;
104 fc->fc_buff[buff_index].actual_size = xfer;
105 }
106 mutex_unlock(&(fc->fc_buff[buff_index].lock));
107 /*wake up client, if any*/
108 wake_up(&fc->fc_wq);
109
110 buff_index++;
111 if (buff_index >= EVRC_FC_BUFF_CNT)
112 buff_index = 0;
113
114 ab->used = 1;
115
116 q6audio_read(ac, ab);
117 ac->cpu_buf ^= 1;
118 }
119
120 return 0;
121}
122static long q6_evrc_in_ioctl(struct file *file, unsigned int cmd,
123 unsigned long arg)
124{
125 struct evrc *evrc = file->private_data;
126 int rc = 0;
127 int i = 0;
128 struct evrc_fc *fc;
129 int size = 0;
130
131 mutex_lock(&evrc->lock);
132 switch (cmd) {
133 case AUDIO_SET_VOLUME:
134 pr_debug("[%s:%s] SET_VOLUME\n", __MM_FILE__, __func__);
135 break;
136 case AUDIO_GET_STATS:
137 {
138 struct msm_audio_stats stats;
139 pr_debug("[%s:%s] GET_STATS\n", __MM_FILE__, __func__);
140 memset(&stats, 0, sizeof(stats));
141 if (copy_to_user((void *) arg, &stats, sizeof(stats)))
142 return -EFAULT;
143 return 0;
144 }
145 case AUDIO_START:
146 {
147 uint32_t acdb_id;
148 pr_debug("[%s:%s] AUDIO_START\n", __MM_FILE__, __func__);
149 if (arg == 0) {
150 acdb_id = 0;
151 } else {
152 if (copy_from_user(&acdb_id, (void *) arg,
153 sizeof(acdb_id))) {
154 rc = -EFAULT;
155 break;
156 }
157 }
158 if (evrc->audio_client) {
159 rc = -EBUSY;
160 pr_err("[%s:%s] active session already existing\n",
161 __MM_FILE__, __func__);
162 break;
163 } else {
164 evrc->audio_client = q6audio_open_qcp(
165 evrc->str_cfg.buffer_size,
166 evrc->cfg.min_bit_rate,
167 evrc->cfg.max_bit_rate,
168 evrc->voicerec_mode.rec_mode,
169 ADSP_AUDIO_FORMAT_EVRC_FS,
170 acdb_id);
171
172 if (!evrc->audio_client) {
173 pr_err("[%s:%s] evrc open session failed\n",
174 __MM_FILE__, __func__);
175 kfree(evrc);
176 rc = -ENOMEM;
177 break;
178 }
179 }
180
181 /*allocate flow control buffers*/
182 fc = evrc->evrc_fc;
183 size = evrc->str_cfg.buffer_size;
184 for (i = 0; i < EVRC_FC_BUFF_CNT; ++i) {
185 mutex_init(&(fc->fc_buff[i].lock));
186 fc->fc_buff[i].empty = 1;
187 fc->fc_buff[i].data = kmalloc(size, GFP_KERNEL);
188 if (fc->fc_buff[i].data == NULL) {
189 pr_err("[%s:%s] No memory for FC buffers\n",
190 __MM_FILE__, __func__);
191 rc = -ENOMEM;
192 goto fc_fail;
193 }
194 fc->fc_buff[i].size = size;
195 fc->fc_buff[i].actual_size = 0;
196 }
197
198 /*create flow control thread*/
199 fc->task = kthread_run(q6_evrc_flowcontrol,
200 evrc, "evrc_flowcontrol");
201 if (IS_ERR(fc->task)) {
202 rc = PTR_ERR(fc->task);
203 pr_err("[%s:%s] error creating flow control thread\n",
204 __MM_FILE__, __func__);
205 goto fc_fail;
206 }
207 break;
208fc_fail:
209 /*free flow control buffers*/
210 --i;
211 for (; i >= 0; i--) {
212 kfree(fc->fc_buff[i].data);
213 fc->fc_buff[i].data = NULL;
214 }
215 break;
216 }
217 case AUDIO_STOP:
218 pr_debug("[%s:%s] AUDIO_STOP\n", __MM_FILE__, __func__);
219 break;
220 case AUDIO_FLUSH:
221 break;
222 case AUDIO_SET_INCALL: {
223 pr_debug("[%s:%s] SET_INCALL\n", __MM_FILE__, __func__);
224 if (copy_from_user(&evrc->voicerec_mode,
225 (void *)arg, sizeof(struct msm_voicerec_mode)))
226 rc = -EFAULT;
227
228 if (evrc->voicerec_mode.rec_mode != AUDIO_FLAG_READ
229 && evrc->voicerec_mode.rec_mode !=
230 AUDIO_FLAG_INCALL_MIXED) {
231 evrc->voicerec_mode.rec_mode = AUDIO_FLAG_READ;
232 pr_err("[%s:%s] Invalid rec_mode\n", __MM_FILE__,
233 __func__);
234 rc = -EINVAL;
235 }
236 break;
237 }
238 case AUDIO_GET_STREAM_CONFIG:
239 if (copy_to_user((void *)arg, &evrc->str_cfg,
240 sizeof(struct msm_audio_stream_config)))
241 rc = -EFAULT;
242
243 pr_debug("[%s:%s] GET_STREAM_CONFIG: buffsz=%d, buffcnt=%d\n",
244 __MM_FILE__, __func__, evrc->str_cfg.buffer_size,
245 evrc->str_cfg.buffer_count);
246 break;
247 case AUDIO_SET_STREAM_CONFIG:
248 if (copy_from_user(&evrc->str_cfg, (void *)arg,
249 sizeof(struct msm_audio_stream_config))) {
250 rc = -EFAULT;
251 break;
252 }
253
254 pr_debug("[%s:%s] SET_STREAM_CONFIG: buffsz=%d, buffcnt=%d\n",
255 __MM_FILE__, __func__, evrc->str_cfg.buffer_size,
256 evrc->str_cfg.buffer_count);
257
258 if (evrc->str_cfg.buffer_size < 23) {
259 pr_err("[%s:%s] Buffer size too small\n", __MM_FILE__,
260 __func__);
261 rc = -EINVAL;
262 break;
263 }
264
265 if (evrc->str_cfg.buffer_count != 2)
266 pr_info("[%s:%s] Buffer count set to 2\n", __MM_FILE__,
267 __func__);
268 break;
269 case AUDIO_SET_EVRC_ENC_CONFIG:
270 if (copy_from_user(&evrc->cfg, (void *) arg,
271 sizeof(struct msm_audio_evrc_enc_config)))
272 rc = -EFAULT;
273 pr_debug("[%s:%s] SET_EVRC_ENC_CONFIG\n", __MM_FILE__,
274 __func__);
275
276 if (evrc->cfg.min_bit_rate > 4 || evrc->cfg.min_bit_rate < 1) {
277 pr_err("[%s:%s] invalid min bitrate\n", __MM_FILE__,
278 __func__);
279 rc = -EINVAL;
280 }
281 if (evrc->cfg.max_bit_rate > 4 || evrc->cfg.max_bit_rate < 1) {
282 pr_err("[%s:%s] invalid max bitrate\n", __MM_FILE__,
283 __func__);
284 rc = -EINVAL;
285 }
286 break;
287 case AUDIO_GET_EVRC_ENC_CONFIG:
288 if (copy_to_user((void *) arg, &evrc->cfg,
289 sizeof(struct msm_audio_evrc_enc_config)))
290 rc = -EFAULT;
291 pr_debug("[%s:%s] GET_EVRC_ENC_CONFIG\n", __MM_FILE__,
292 __func__);
293 break;
294
295 default:
296 rc = -EINVAL;
297 }
298
299 mutex_unlock(&evrc->lock);
300 pr_debug("[%s:%s] rc = %d\n", __MM_FILE__, __func__, rc);
301 return rc;
302}
303
304static int q6_evrc_in_open(struct inode *inode, struct file *file)
305{
306 struct evrc *evrc;
307 struct evrc_fc *fc;
308 int i;
309
310 pr_info("[%s:%s] open\n", __MM_FILE__, __func__);
311 evrc = kmalloc(sizeof(struct evrc), GFP_KERNEL);
312 if (evrc == NULL) {
313 pr_err("[%s:%s] Could not allocate memory for evrc driver\n",
314 __MM_FILE__, __func__);
315 return -ENOMEM;
316 }
317
318 mutex_init(&evrc->lock);
319 file->private_data = evrc;
320 evrc->audio_client = NULL;
321 evrc->str_cfg.buffer_size = 23;
322 evrc->str_cfg.buffer_count = 2;
323 evrc->cfg.cdma_rate = CDMA_RATE_FULL;
324 evrc->cfg.min_bit_rate = 1;
325 evrc->cfg.max_bit_rate = 4;
326 evrc->voicerec_mode.rec_mode = AUDIO_FLAG_READ;
327
328 evrc->evrc_fc = kmalloc(sizeof(struct evrc_fc), GFP_KERNEL);
329 if (evrc->evrc_fc == NULL) {
330 pr_err("[%s:%s] Could not allocate memory for evrc_fc\n",
331 __MM_FILE__, __func__);
332 kfree(evrc);
333 return -ENOMEM;
334 }
335 fc = evrc->evrc_fc;
336 fc->task = NULL;
337 fc->buff_index = 0;
338 for (i = 0; i < EVRC_FC_BUFF_CNT; ++i) {
339 fc->fc_buff[i].data = NULL;
340 fc->fc_buff[i].size = 0;
341 fc->fc_buff[i].actual_size = 0;
342 }
343 /*initialize wait queue head*/
344 init_waitqueue_head(&fc->fc_wq);
345 return 0;
346}
347
348static ssize_t q6_evrc_in_read(struct file *file, char __user *buf,
349 size_t count, loff_t *pos)
350{
351 struct audio_client *ac;
352 const char __user *start = buf;
353 struct evrc *evrc = file->private_data;
354 struct evrc_fc *fc;
355 int xfer = 0;
356 int res = 0;
357
358 pr_debug("[%s:%s] count = %d\n", __MM_FILE__, __func__, count);
359 mutex_lock(&evrc->lock);
360 ac = evrc->audio_client;
361 if (!ac) {
362 res = -ENODEV;
363 goto fail;
364 }
365 fc = evrc->evrc_fc;
366 while (count > xfer) {
367 /*wait for buffer to full*/
368 if (fc->fc_buff[fc->buff_index].empty != 0) {
369 res = wait_event_interruptible_timeout(fc->fc_wq,
370 (fc->fc_buff[fc->buff_index].empty == 0),
371 msecs_to_jiffies(EVRC_READ_TIMEOUT));
372
373 pr_debug("[%s:%s] buff_index = %d\n", __MM_FILE__,
374 __func__, fc->buff_index);
375 if (res == 0) {
376 pr_err("[%s:%s] Timeout!\n", __MM_FILE__,
377 __func__);
378 res = -ETIMEDOUT;
379 goto fail;
380 } else if (res < 0) {
381 pr_err("[%s:%s] Returning on Interrupt\n",
382 __MM_FILE__, __func__);
383 goto fail;
384 }
385 }
386 /*lock the buffer*/
387 mutex_lock(&(fc->fc_buff[fc->buff_index].lock));
388 xfer = fc->fc_buff[fc->buff_index].actual_size;
389
390 if (xfer > count) {
391 mutex_unlock(&(fc->fc_buff[fc->buff_index].lock));
392 pr_err("[%s:%s] read failed! byte count too small\n",
393 __MM_FILE__, __func__);
394 res = -EINVAL;
395 goto fail;
396 }
397
398 if (copy_to_user(buf, fc->fc_buff[fc->buff_index].data, xfer)) {
399 mutex_unlock(&(fc->fc_buff[fc->buff_index].lock));
400 pr_err("[%s:%s] copy_to_user failed at index %d\n",
401 __MM_FILE__, __func__, fc->buff_index);
402 res = -EFAULT;
403 goto fail;
404 }
405 buf += xfer;
406 count -= xfer;
407
408 fc->fc_buff[fc->buff_index].empty = 1;
409 fc->fc_buff[fc->buff_index].actual_size = 0;
410
411 mutex_unlock(&(fc->fc_buff[fc->buff_index].lock));
412 ++(fc->buff_index);
413 if (fc->buff_index >= EVRC_FC_BUFF_CNT)
414 fc->buff_index = 0;
415 }
416 res = buf - start;
417
418fail:
419 mutex_unlock(&evrc->lock);
420
421 return res;
422}
423
424static int q6_evrc_in_release(struct inode *inode, struct file *file)
425{
426 int rc = 0;
427 struct evrc *evrc = file->private_data;
428 int i = 0;
429 struct evrc_fc *fc;
430
431 mutex_lock(&evrc->lock);
432 fc = evrc->evrc_fc;
433 kthread_stop(fc->task);
434 fc->task = NULL;
435 /*free flow control buffers*/
436 for (i = 0; i < EVRC_FC_BUFF_CNT; ++i) {
437 kfree(fc->fc_buff[i].data);
438 fc->fc_buff[i].data = NULL;
439 }
440 kfree(fc);
441 if (evrc->audio_client)
442 rc = q6audio_close(evrc->audio_client);
443 mutex_unlock(&evrc->lock);
444 kfree(evrc);
445 pr_info("[%s:%s] release\n", __MM_FILE__, __func__);
446 return rc;
447}
448
449static const struct file_operations q6_evrc_in_fops = {
450 .owner = THIS_MODULE,
451 .open = q6_evrc_in_open,
452 .read = q6_evrc_in_read,
453 .release = q6_evrc_in_release,
454 .unlocked_ioctl = q6_evrc_in_ioctl,
455};
456
457struct miscdevice q6_evrc_in_misc = {
458 .minor = MISC_DYNAMIC_MINOR,
459 .name = "msm_evrc_in",
460 .fops = &q6_evrc_in_fops,
461};
462
463static int __init q6_evrc_in_init(void)
464{
465 return misc_register(&q6_evrc_in_misc);
466}
467
468device_initcall(q6_evrc_in_init);