blob: db3a1abaeccb2814652d01c18c1e645f8aa20f1e [file] [log] [blame]
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001/* linux/arch/arm/mach-msm/qdsp5/audio_amrwb.c
2 *
3 * amrwb audio decoder device
4 *
5 * Based on the mp3 native driver in arch/arm/mach-msm/qdsp5/audio_mp3.c
6 *
7 * Copyright (C) 2008 Google, Inc.
8 * Copyright (C) 2008 HTC Corporation
Duy Truong790f06d2013-02-13 16:38:12 -08009 * Copyright (c) 2009, 2011-2012 The Linux Foundation. All rights reserved.
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070010 *
11 * All source code in this file is licensed under the following license except
12 * where indicated.
13 *
14 * This program is free software; you can redistribute it and/or modify it
15 * under the terms of the GNU General Public License version 2 as published
16 * by the Free Software Foundation.
17 *
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
21 *
22 * See the GNU General Public License for more details.
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, you can find it at http://www.fsf.org
25 */
26
Santosh Mardi0be3b8e2011-07-06 10:00:21 +053027#include <asm/atomic.h>
28#include <asm/ioctls.h>
29
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070030#include <linux/module.h>
31#include <linux/fs.h>
32#include <linux/miscdevice.h>
33#include <linux/uaccess.h>
34#include <linux/kthread.h>
35#include <linux/wait.h>
36#include <linux/dma-mapping.h>
37#include <linux/debugfs.h>
38#include <linux/delay.h>
39#include <linux/list.h>
40#include <linux/earlysuspend.h>
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070041#include <linux/slab.h>
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070042#include <linux/msm_audio.h>
Santosh Mardi0be3b8e2011-07-06 10:00:21 +053043#include <linux/memory_alloc.h>
Mitchel Humpherys1da6ebe2012-09-06 10:15:56 -070044#include <linux/msm_ion.h>
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070045
Santosh Mardi0be3b8e2011-07-06 10:00:21 +053046#include <mach/msm_adsp.h>
47#include <mach/iommu.h>
48#include <mach/iommu_domains.h>
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070049#include <mach/qdsp5/qdsp5audppcmdi.h>
50#include <mach/qdsp5/qdsp5audppmsg.h>
Manish Dewanganfa8a6b62012-07-09 16:23:27 +053051#include <mach/qdsp5/qdsp5audpp.h>
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070052#include <mach/qdsp5/qdsp5audplaycmdi.h>
53#include <mach/qdsp5/qdsp5audplaymsg.h>
54#include <mach/qdsp5/qdsp5rmtcmdi.h>
55#include <mach/debug_mm.h>
Santosh Mardi0be3b8e2011-07-06 10:00:21 +053056#include <mach/msm_memtypes.h>
57
58#include "audmgr.h"
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070059
60#define BUFSZ 4110 /* Hold minimum 700ms voice data and 14 bytes of meta in*/
61#define DMASZ (BUFSZ * 2)
62
63#define AUDPLAY_INVALID_READ_PTR_OFFSET 0xFFFF
64#define AUDDEC_DEC_AMRWB 11
65
66#define PCM_BUFSZ_MIN 8216 /* 100ms worth of data and 24 bytes of meta out*/
67#define PCM_BUF_MAX_COUNT 5 /* DSP only accepts 5 buffers at most
68 but support 2 buffers currently */
69#define ROUTING_MODE_FTRT 1
70#define ROUTING_MODE_RT 2
71/* Decoder status received from AUDPPTASK */
72#define AUDPP_DEC_STATUS_SLEEP 0
73#define AUDPP_DEC_STATUS_INIT 1
74#define AUDPP_DEC_STATUS_CFG 2
75#define AUDPP_DEC_STATUS_PLAY 3
76
77#define AUDAMRWB_METAFIELD_MASK 0xFFFF0000
78#define AUDAMRWB_EOS_FLG_OFFSET 0x0A /* Offset from beginning of buffer */
79#define AUDAMRWB_EOS_FLG_MASK 0x01
80#define AUDAMRWB_EOS_NONE 0x0 /* No EOS detected */
81#define AUDAMRWB_EOS_SET 0x1 /* EOS set in meta field */
82
83#define AUDAMRWB_EVENT_NUM 10 /* Default number of pre-allocated event pkts */
84
85struct buffer {
86 void *data;
87 unsigned size;
88 unsigned used; /* Input usage actual DSP produced PCM size */
89 unsigned addr;
90 unsigned short mfield_sz; /*only useful for data has meta field */
91};
92
93#ifdef CONFIG_HAS_EARLYSUSPEND
94struct audamrwb_suspend_ctl {
95 struct early_suspend node;
96 struct audio *audio;
97};
98#endif
99
100struct audamrwb_event{
101 struct list_head list;
102 int event_type;
103 union msm_audio_event_payload payload;
104};
105
106struct audio {
107 struct buffer out[2];
108
109 spinlock_t dsp_lock;
110
111 uint8_t out_head;
112 uint8_t out_tail;
113 uint8_t out_needed; /* number of buffers the dsp is waiting for */
114
115 atomic_t out_bytes;
116
117 struct mutex lock;
118 struct mutex write_lock;
119 wait_queue_head_t write_wait;
120
121 /* Host PCM section */
122 struct buffer in[PCM_BUF_MAX_COUNT];
123 struct mutex read_lock;
124 wait_queue_head_t read_wait; /* Wait queue for read */
125 char *read_data; /* pointer to reader buffer */
126 int32_t read_phys; /* physical address of reader buffer */
127 uint8_t read_next; /* index to input buffers to be read next */
128 uint8_t fill_next; /* index to buffer that DSP should be filling */
129 uint8_t pcm_buf_count; /* number of pcm buffer allocated */
130 /* ---- End of Host PCM section */
131
132 struct msm_adsp_module *audplay;
133 struct audmgr audmgr;
134
135 /* configuration to use on next enable */
136 uint32_t out_sample_rate;
137 uint32_t out_channel_mode;
138
139 /* data allocated for various buffers */
140 char *data;
141 int32_t phys; /* physical address of write buffer */
Laura Abbott35111d32012-04-27 18:41:48 -0700142 void *map_v_read;
143 void *map_v_write;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700144 int mfield; /* meta field embedded in data */
145 int rflush; /* Read flush */
146 int wflush; /* Write flush */
147 int opened;
148 int enabled;
149 int running;
150 int stopped; /* set when stopped, cleared on flush */
151 int pcm_feedback;
152 int buf_refresh;
153 int rmt_resource_released;
154 int teos; /* valid only if tunnel mode & no data left for decoder */
155 enum msm_aud_decoder_state dec_state; /* Represents decoder state */
156 int reserved; /* A byte is being reserved */
157 char rsv_byte; /* Handle odd length user data */
158
159 const char *module_name;
160 unsigned queue_id;
161 uint16_t dec_id;
162 uint32_t read_ptr_offset;
163
164#ifdef CONFIG_HAS_EARLYSUSPEND
165 struct audamrwb_suspend_ctl suspend_ctl;
166#endif
167
168#ifdef CONFIG_DEBUG_FS
169 struct dentry *dentry;
170#endif
171
172 wait_queue_head_t wait;
173 struct list_head free_event_queue;
174 struct list_head event_queue;
175 wait_queue_head_t event_wait;
176 spinlock_t event_queue_lock;
177 struct mutex get_event_lock;
178 int event_abort;
179
180 int eq_enable;
181 int eq_needs_commit;
182 audpp_cmd_cfg_object_params_eqalizer eq;
183 audpp_cmd_cfg_object_params_volume vol_pan;
Sidipotu Ashok172c98b2012-06-26 17:58:29 +0530184 struct ion_client *client;
185 struct ion_handle *input_buff_handle;
186 struct ion_handle *output_buff_handle;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700187};
188
189static int auddec_dsp_config(struct audio *audio, int enable);
190static void audpp_cmd_cfg_adec_params(struct audio *audio);
191static void audpp_cmd_cfg_routing_mode(struct audio *audio);
192static void audamrwb_send_data(struct audio *audio, unsigned needed);
193static void audamrwb_config_hostpcm(struct audio *audio);
194static void audamrwb_buffer_refresh(struct audio *audio);
195static void audamrwb_dsp_event(void *private, unsigned id, uint16_t *msg);
196#ifdef CONFIG_HAS_EARLYSUSPEND
197static void audamrwb_post_event(struct audio *audio, int type,
198 union msm_audio_event_payload payload);
199#endif
200
201static int rmt_put_resource(struct audio *audio)
202{
203 struct aud_codec_config_cmd cmd;
204 unsigned short client_idx;
205
206 cmd.cmd_id = RM_CMD_AUD_CODEC_CFG;
207 cmd.client_id = RM_AUD_CLIENT_ID;
208 cmd.task_id = audio->dec_id;
209 cmd.enable = RMT_DISABLE;
210 cmd.dec_type = AUDDEC_DEC_AMRWB;
211 client_idx = ((cmd.client_id << 8) | cmd.task_id);
212
213 return put_adsp_resource(client_idx, &cmd, sizeof(cmd));
214}
215
216static int rmt_get_resource(struct audio *audio)
217{
218 struct aud_codec_config_cmd cmd;
219 unsigned short client_idx;
220
221 cmd.cmd_id = RM_CMD_AUD_CODEC_CFG;
222 cmd.client_id = RM_AUD_CLIENT_ID;
223 cmd.task_id = audio->dec_id;
224 cmd.enable = RMT_ENABLE;
225 cmd.dec_type = AUDDEC_DEC_AMRWB;
226 client_idx = ((cmd.client_id << 8) | cmd.task_id);
227
228 return get_adsp_resource(client_idx, &cmd, sizeof(cmd));
229}
230
231/* must be called with audio->lock held */
232static int audamrwb_enable(struct audio *audio)
233{
234 struct audmgr_config cfg;
235 int rc;
236
237 MM_DBG("\n"); /* Macro prints the file name and function */
238
239 if (audio->enabled)
240 return 0;
241
242 if (audio->rmt_resource_released == 1) {
243 audio->rmt_resource_released = 0;
244 rc = rmt_get_resource(audio);
245 if (rc) {
246 MM_ERR("ADSP resources are not available for AMRWB \
247 session 0x%08x on decoder: %d\n Ignoring \
248 error and going ahead with the playback\n",
249 (int)audio, audio->dec_id);
250 }
251 }
252
253 audio->dec_state = MSM_AUD_DECODER_STATE_NONE;
254 audio->out_tail = 0;
255 audio->out_needed = 0;
256
257 if (audio->pcm_feedback == TUNNEL_MODE_PLAYBACK) {
258 cfg.tx_rate = RPC_AUD_DEF_SAMPLE_RATE_NONE;
259 cfg.rx_rate = RPC_AUD_DEF_SAMPLE_RATE_48000;
260 cfg.def_method = RPC_AUD_DEF_METHOD_PLAYBACK;
261 cfg.codec = RPC_AUD_DEF_CODEC_AMR_WB;
262 cfg.snd_method = RPC_SND_METHOD_MIDI;
263
264 rc = audmgr_enable(&audio->audmgr, &cfg);
=Chaithanya Krishna Bacharajub5c4e982012-12-06 09:53:18 +0530265 if (rc < 0) {
266 msm_adsp_dump(audio->audplay);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700267 return rc;
=Chaithanya Krishna Bacharajub5c4e982012-12-06 09:53:18 +0530268 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700269 }
270
271 if (msm_adsp_enable(audio->audplay)) {
272 MM_ERR("msm_adsp_enable(audplay) failed\n");
273 if (audio->pcm_feedback == TUNNEL_MODE_PLAYBACK)
274 audmgr_disable(&audio->audmgr);
275 return -ENODEV;
276 }
277
278 if (audpp_enable(audio->dec_id, audamrwb_dsp_event, audio)) {
279 MM_ERR("audpp_enable() failed\n");
280 msm_adsp_disable(audio->audplay);
281 if (audio->pcm_feedback == TUNNEL_MODE_PLAYBACK)
282 audmgr_disable(&audio->audmgr);
283 return -ENODEV;
284 }
285 audio->enabled = 1;
286 return 0;
287}
288
289/* must be called with audio->lock held */
290static int audamrwb_disable(struct audio *audio)
291{
292 int rc = 0;
293 MM_DBG("\n"); /* Macro prints the file name and function */
294 if (audio->enabled) {
295 audio->enabled = 0;
296 audio->dec_state = MSM_AUD_DECODER_STATE_NONE;
297 auddec_dsp_config(audio, 0);
298 rc = wait_event_interruptible_timeout(audio->wait,
299 audio->dec_state != MSM_AUD_DECODER_STATE_NONE,
300 msecs_to_jiffies(MSM_AUD_DECODER_WAIT_MS));
301 if (rc == 0)
302 rc = -ETIMEDOUT;
303 else if (audio->dec_state != MSM_AUD_DECODER_STATE_CLOSE)
304 rc = -EFAULT;
305 else
306 rc = 0;
Manish Dewangan89a9f232012-02-09 17:14:40 +0530307 audio->stopped = 1;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700308 wake_up(&audio->write_wait);
309 wake_up(&audio->read_wait);
310 msm_adsp_disable(audio->audplay);
311 audpp_disable(audio->dec_id, audio);
=Chaithanya Krishna Bacharajub5c4e982012-12-06 09:53:18 +0530312 if (audio->pcm_feedback == TUNNEL_MODE_PLAYBACK) {
313 rc = audmgr_disable(&audio->audmgr);
314 if (rc < 0)
315 msm_adsp_dump(audio->audplay);
316 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700317 audio->out_needed = 0;
318 rmt_put_resource(audio);
319 audio->rmt_resource_released = 1;
320 }
321 return rc;
322}
323
324/* ------------------- dsp --------------------- */
325static void audamrwb_update_pcm_buf_entry(struct audio *audio,
326 uint32_t *payload)
327{
328 uint8_t index;
329 unsigned long flags;
330
331 if (audio->rflush)
332 return;
333
334 spin_lock_irqsave(&audio->dsp_lock, flags);
335 for (index = 0; index < payload[1]; index++) {
336 if (audio->in[audio->fill_next].addr ==
337 payload[2 + index * 2]) {
338 MM_DBG("in[%d] ready\n", audio->fill_next);
339 audio->in[audio->fill_next].used =
340 payload[3 + index * 2];
341 if ((++audio->fill_next) == audio->pcm_buf_count)
342 audio->fill_next = 0;
343
344 } else {
345 MM_ERR("expected=%x ret=%x\n",
346 audio->in[audio->fill_next].addr,
347 payload[1 + index * 2]);
348 break;
349 }
350 }
351 if (audio->in[audio->fill_next].used == 0) {
352 audamrwb_buffer_refresh(audio);
353 } else {
354 MM_DBG("read cannot keep up\n");
355 audio->buf_refresh = 1;
356 }
357 wake_up(&audio->read_wait);
358 spin_unlock_irqrestore(&audio->dsp_lock, flags);
359}
360
361static void audplay_dsp_event(void *data, unsigned id, size_t len,
362 void (*getevent) (void *ptr, size_t len))
363{
364 struct audio *audio = data;
365 uint32_t msg[28];
366 getevent(msg, sizeof(msg));
367
368 MM_DBG("msg_id=%x\n", id);
369
370 switch (id) {
371 case AUDPLAY_MSG_DEC_NEEDS_DATA:
372 audamrwb_send_data(audio, 1);
373 break;
374
375 case AUDPLAY_MSG_BUFFER_UPDATE:
376 audamrwb_update_pcm_buf_entry(audio, msg);
377 break;
378
379 default:
380 MM_ERR("unexpected message from decoder\n");
381 }
382}
383
384static void audamrwb_dsp_event(void *private, unsigned id, uint16_t *msg)
385{
386 struct audio *audio = private;
387
388 switch (id) {
389 case AUDPP_MSG_STATUS_MSG:{
390 unsigned status = msg[1];
391
392 switch (status) {
393 case AUDPP_DEC_STATUS_SLEEP: {
394 uint16_t reason = msg[2];
395 MM_DBG("decoder status:sleep reason=0x%04x\n",
396 reason);
397 if ((reason == AUDPP_MSG_REASON_MEM)
398 || (reason ==
399 AUDPP_MSG_REASON_NODECODER)) {
400 audio->dec_state =
401 MSM_AUD_DECODER_STATE_FAILURE;
402 wake_up(&audio->wait);
403 } else if (reason == AUDPP_MSG_REASON_NONE) {
404 /* decoder is in disable state */
405 audio->dec_state =
406 MSM_AUD_DECODER_STATE_CLOSE;
407 wake_up(&audio->wait);
408 }
409 break;
410 }
411 case AUDPP_DEC_STATUS_INIT:
412 MM_DBG("decoder status: init\n");
413 if (audio->pcm_feedback)
414 audpp_cmd_cfg_routing_mode(audio);
415 else
416 audpp_cmd_cfg_adec_params(audio);
417 break;
418
419 case AUDPP_DEC_STATUS_CFG:
420 MM_DBG("decoder status: cfg\n");
421 break;
422 case AUDPP_DEC_STATUS_PLAY:
423 MM_DBG("decoder status: play\n");
424 if (audio->pcm_feedback) {
425 audamrwb_config_hostpcm(audio);
426 audamrwb_buffer_refresh(audio);
427 }
428 audio->dec_state =
429 MSM_AUD_DECODER_STATE_SUCCESS;
430 wake_up(&audio->wait);
431 break;
432 default:
433 MM_DBG("unknown decoder status\n");
434 break;
435 }
436 break;
437 }
438 case AUDPP_MSG_CFG_MSG:
439 if (msg[0] == AUDPP_MSG_ENA_ENA) {
440 MM_DBG("CFG_MSG ENABLE\n");
441 auddec_dsp_config(audio, 1);
442 audio->out_needed = 0;
443 audio->running = 1;
444 audpp_dsp_set_vol_pan(audio->dec_id, &audio->vol_pan);
445 audpp_dsp_set_eq(audio->dec_id, audio->eq_enable,
446 &audio->eq);
447 audpp_avsync(audio->dec_id, 22050);
448 } else if (msg[0] == AUDPP_MSG_ENA_DIS) {
449 MM_DBG("CFG_MSG DISABLE\n");
450 audpp_avsync(audio->dec_id, 0);
451 audio->running = 0;
452 } else {
453 MM_DBG("CFG_MSG %d?\n", msg[0]);
454 }
455 break;
456 case AUDPP_MSG_ROUTING_ACK:
457 MM_DBG("ROUTING_ACK mode=%d\n", msg[1]);
458 audpp_cmd_cfg_adec_params(audio);
459 break;
460 case AUDPP_MSG_FLUSH_ACK:
461 MM_DBG("FLUSH_ACK\n");
462 audio->wflush = 0;
463 audio->rflush = 0;
464 wake_up(&audio->write_wait);
465 if (audio->pcm_feedback)
466 audamrwb_buffer_refresh(audio);
467 break;
468 case AUDPP_MSG_PCMDMAMISSED:
469 MM_DBG("PCMDMAMISSED\n");
470 audio->teos = 1;
471 wake_up(&audio->write_wait);
472 break;
473 default:
474 MM_DBG("UNKNOWN (%d)\n", id);
475 }
476
477}
478
479struct msm_adsp_ops audplay_adsp_ops_amrwb = {
480 .event = audplay_dsp_event,
481};
482
483#define audplay_send_queue0(audio, cmd, len) \
484 msm_adsp_write(audio->audplay, audio->queue_id, \
485 cmd, len)
486
487static int auddec_dsp_config(struct audio *audio, int enable)
488{
489 u16 cfg_dec_cmd[AUDPP_CMD_CFG_DEC_TYPE_LEN / sizeof(unsigned short)];
490
491 memset(cfg_dec_cmd, 0, sizeof(cfg_dec_cmd));
492 cfg_dec_cmd[0] = AUDPP_CMD_CFG_DEC_TYPE;
493 if (enable)
494 cfg_dec_cmd[1 + audio->dec_id] = AUDPP_CMD_UPDATDE_CFG_DEC |
495 AUDPP_CMD_ENA_DEC_V | AUDDEC_DEC_AMRWB;
496 else
497 cfg_dec_cmd[1 + audio->dec_id] = AUDPP_CMD_UPDATDE_CFG_DEC |
498 AUDPP_CMD_DIS_DEC_V;
499
500 return audpp_send_queue1(&cfg_dec_cmd, sizeof(cfg_dec_cmd));
501}
502
503static void audpp_cmd_cfg_adec_params(struct audio *audio)
504{
505 struct audpp_cmd_cfg_adec_params_amrwb cmd;
506
507 memset(&cmd, 0, sizeof(cmd));
508 cmd.common.cmd_id = AUDPP_CMD_CFG_ADEC_PARAMS;
509 cmd.common.length = AUDPP_CMD_CFG_ADEC_PARAMS_AMRWB_LEN;
510 cmd.common.dec_id = audio->dec_id;
511 cmd.common.input_sampling_frequency = audio->out_sample_rate;
512 cmd.stereo_cfg = audio->out_channel_mode;
513 audpp_send_queue2(&cmd, sizeof(cmd));
514}
515
516static void audpp_cmd_cfg_routing_mode(struct audio *audio)
517{
518 struct audpp_cmd_routing_mode cmd;
519 MM_DBG("\n"); /* Macro prints the file name and function */
520 memset(&cmd, 0, sizeof(cmd));
521 cmd.cmd_id = AUDPP_CMD_ROUTING_MODE;
522 cmd.object_number = audio->dec_id;
523 if (audio->pcm_feedback)
524 cmd.routing_mode = ROUTING_MODE_FTRT;
525 else
526 cmd.routing_mode = ROUTING_MODE_RT;
527
528 audpp_send_queue1(&cmd, sizeof(cmd));
529}
530
531static int audplay_dsp_send_data_avail(struct audio *audio,
532 unsigned idx, unsigned len)
533{
534 struct audplay_cmd_bitstream_data_avail_nt2 cmd;
535
536 cmd.cmd_id = AUDPLAY_CMD_BITSTREAM_DATA_AVAIL_NT2;
537 if (audio->mfield)
538 cmd.decoder_id = AUDAMRWB_METAFIELD_MASK |
539 (audio->out[idx].mfield_sz >> 1);
540 else
541 cmd.decoder_id = audio->dec_id;
542 cmd.buf_ptr = audio->out[idx].addr;
543 cmd.buf_size = len / 2;
544 cmd.partition_number = 0;
545 return audplay_send_queue0(audio, &cmd, sizeof(cmd));
546}
547
548static void audamrwb_buffer_refresh(struct audio *audio)
549{
550 struct audplay_cmd_buffer_refresh refresh_cmd;
551
552 refresh_cmd.cmd_id = AUDPLAY_CMD_BUFFER_REFRESH;
553 refresh_cmd.num_buffers = 1;
554 refresh_cmd.buf0_address = audio->in[audio->fill_next].addr;
555 refresh_cmd.buf0_length = audio->in[audio->fill_next].size;
556 refresh_cmd.buf_read_count = 0;
557 MM_DBG("buf0_addr=%x buf0_len=%d\n", refresh_cmd.buf0_address,
558 refresh_cmd.buf0_length);
559 (void)audplay_send_queue0(audio, &refresh_cmd, sizeof(refresh_cmd));
560}
561
562static void audamrwb_config_hostpcm(struct audio *audio)
563{
564 struct audplay_cmd_hpcm_buf_cfg cfg_cmd;
565
566 MM_DBG("\n"); /* Macro prints the file name and function */
567 cfg_cmd.cmd_id = AUDPLAY_CMD_HPCM_BUF_CFG;
568 cfg_cmd.max_buffers = audio->pcm_buf_count;
569 cfg_cmd.byte_swap = 0;
570 cfg_cmd.hostpcm_config = (0x8000) | (0x4000);
571 cfg_cmd.feedback_frequency = 1;
572 cfg_cmd.partition_number = 0;
573 (void)audplay_send_queue0(audio, &cfg_cmd, sizeof(cfg_cmd));
574
575}
576
577static void audamrwb_send_data(struct audio *audio, unsigned needed)
578{
579 struct buffer *frame;
580 unsigned long flags;
581
582 spin_lock_irqsave(&audio->dsp_lock, flags);
583 if (!audio->running)
584 goto done;
585
586 if (needed && !audio->wflush) {
587 /* We were called from the callback because the DSP
588 * requested more data. Note that the DSP does want
589 * more data, and if a buffer was in-flight, mark it
590 * as available (since the DSP must now be done with
591 * it).
592 */
593 audio->out_needed = 1;
594 frame = audio->out + audio->out_tail;
595 if (frame->used == 0xffffffff) {
596 frame->used = 0;
597 audio->out_tail ^= 1;
598 wake_up(&audio->write_wait);
599 }
600 }
601
602 if (audio->out_needed) {
603 /* If the DSP currently wants data and we have a
604 * buffer available, we will send it and reset
605 * the needed flag. We'll mark the buffer as in-flight
606 * so that it won't be recycled until the next buffer
607 * is requested
608 */
609
610 frame = audio->out + audio->out_tail;
611 if (frame->used) {
612 BUG_ON(frame->used == 0xffffffff);
613 MM_DBG("frame %d busy\n", audio->out_tail);
614 audplay_dsp_send_data_avail(audio, audio->out_tail,
615 frame->used);
616 frame->used = 0xffffffff;
617 audio->out_needed = 0;
618 }
619 }
620 done:
621 spin_unlock_irqrestore(&audio->dsp_lock, flags);
622}
623
624/* ------------------- device --------------------- */
625
626static void audamrwb_flush(struct audio *audio)
627{
Manish Dewangana4f1df02012-02-08 17:06:54 +0530628 unsigned long flags;
629
630 spin_lock_irqsave(&audio->dsp_lock, flags);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700631 audio->out[0].used = 0;
632 audio->out[1].used = 0;
633 audio->out_head = 0;
634 audio->out_tail = 0;
635 audio->reserved = 0;
636 audio->out_needed = 0;
Manish Dewangana4f1df02012-02-08 17:06:54 +0530637 spin_unlock_irqrestore(&audio->dsp_lock, flags);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700638 atomic_set(&audio->out_bytes, 0);
639}
640
641static void audamrwb_flush_pcm_buf(struct audio *audio)
642{
643 uint8_t index;
Manish Dewangana4f1df02012-02-08 17:06:54 +0530644 unsigned long flags;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700645
Manish Dewangana4f1df02012-02-08 17:06:54 +0530646 spin_lock_irqsave(&audio->dsp_lock, flags);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700647 for (index = 0; index < PCM_BUF_MAX_COUNT; index++)
648 audio->in[index].used = 0;
649
650 audio->buf_refresh = 0;
651 audio->read_next = 0;
652 audio->fill_next = 0;
Manish Dewangana4f1df02012-02-08 17:06:54 +0530653 spin_unlock_irqrestore(&audio->dsp_lock, flags);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700654}
655
656static void audamrwb_ioport_reset(struct audio *audio)
657{
658 /* Make sure read/write thread are free from
659 * sleep and knowing that system is not able
660 * to process io request at the moment
661 */
662 wake_up(&audio->write_wait);
663 mutex_lock(&audio->write_lock);
664 audamrwb_flush(audio);
665 mutex_unlock(&audio->write_lock);
666 wake_up(&audio->read_wait);
667 mutex_lock(&audio->read_lock);
668 audamrwb_flush_pcm_buf(audio);
669 mutex_unlock(&audio->read_lock);
670}
671
672static int audamrwb_events_pending(struct audio *audio)
673{
674 unsigned long flags;
675 int empty;
676
677 spin_lock_irqsave(&audio->event_queue_lock, flags);
678 empty = !list_empty(&audio->event_queue);
679 spin_unlock_irqrestore(&audio->event_queue_lock, flags);
680 return empty || audio->event_abort;
681}
682
683static void audamrwb_reset_event_queue(struct audio *audio)
684{
685 unsigned long flags;
686 struct audamrwb_event *drv_evt;
687 struct list_head *ptr, *next;
688
689 spin_lock_irqsave(&audio->event_queue_lock, flags);
690 list_for_each_safe(ptr, next, &audio->event_queue) {
691 drv_evt = list_first_entry(&audio->event_queue,
692 struct audamrwb_event, list);
693 list_del(&drv_evt->list);
694 kfree(drv_evt);
695 }
696 list_for_each_safe(ptr, next, &audio->free_event_queue) {
697 drv_evt = list_first_entry(&audio->free_event_queue,
698 struct audamrwb_event, list);
699 list_del(&drv_evt->list);
700 kfree(drv_evt);
701 }
702 spin_unlock_irqrestore(&audio->event_queue_lock, flags);
703
704 return;
705}
706
707static long audamrwb_process_event_req(struct audio *audio, void __user *arg)
708{
709 long rc;
710 struct msm_audio_event usr_evt;
711 struct audamrwb_event *drv_evt = NULL;
712 int timeout;
713 unsigned long flags;
714
715 if (copy_from_user(&usr_evt, arg, sizeof(struct msm_audio_event)))
716 return -EFAULT;
717
718 timeout = (int) usr_evt.timeout_ms;
719
720 if (timeout > 0) {
721 rc = wait_event_interruptible_timeout(
722 audio->event_wait, audamrwb_events_pending(audio),
723 msecs_to_jiffies(timeout));
724 if (rc == 0)
725 return -ETIMEDOUT;
726 } else {
727 rc = wait_event_interruptible(
728 audio->event_wait, audamrwb_events_pending(audio));
729 }
730
731 if (rc < 0)
732 return rc;
733
734 if (audio->event_abort) {
735 audio->event_abort = 0;
736 return -ENODEV;
737 }
738
739 rc = 0;
740
741 spin_lock_irqsave(&audio->event_queue_lock, flags);
742 if (!list_empty(&audio->event_queue)) {
743 drv_evt = list_first_entry(&audio->event_queue,
744 struct audamrwb_event, list);
745 list_del(&drv_evt->list);
746 }
747
748 if (drv_evt) {
749 usr_evt.event_type = drv_evt->event_type;
750 usr_evt.event_payload = drv_evt->payload;
751 list_add_tail(&drv_evt->list, &audio->free_event_queue);
752 } else
753 rc = -1;
754 spin_unlock_irqrestore(&audio->event_queue_lock, flags);
755
756 if (!rc && copy_to_user(arg, &usr_evt, sizeof(usr_evt)))
757 rc = -EFAULT;
758
759 return rc;
760}
761
762static int audio_enable_eq(struct audio *audio, int enable)
763{
764 if (audio->eq_enable == enable && !audio->eq_needs_commit)
765 return 0;
766
767 audio->eq_enable = enable;
768
769 if (audio->running) {
770 audpp_dsp_set_eq(audio->dec_id, enable, &audio->eq);
771 audio->eq_needs_commit = 0;
772 }
773 return 0;
774}
775
776static long audamrwb_ioctl(struct file *file, unsigned int cmd,
777 unsigned long arg)
778{
779 struct audio *audio = file->private_data;
780 int rc = -EINVAL;
781 unsigned long flags = 0;
782 uint16_t enable_mask;
783 int enable;
784 int prev_state;
Sidipotu Ashok172c98b2012-06-26 17:58:29 +0530785 unsigned long ionflag = 0;
786 ion_phys_addr_t addr = 0;
787 struct ion_handle *handle = NULL;
788 int len = 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700789
790 MM_DBG("cmd = %d\n", cmd);
791
792 if (cmd == AUDIO_GET_STATS) {
793 struct msm_audio_stats stats;
794 stats.byte_count = audpp_avsync_byte_count(audio->dec_id);
795 stats.sample_count = audpp_avsync_sample_count(audio->dec_id);
796 if (copy_to_user((void *)arg, &stats, sizeof(stats)))
797 return -EFAULT;
798 return 0;
799 }
800
801 switch (cmd) {
802 case AUDIO_ENABLE_AUDPP:
803 if (copy_from_user(&enable_mask, (void *) arg,
804 sizeof(enable_mask))) {
805 rc = -EFAULT;
806 break;
807 }
808
809 spin_lock_irqsave(&audio->dsp_lock, flags);
810 enable = (enable_mask & EQ_ENABLE) ? 1 : 0;
811 audio_enable_eq(audio, enable);
812 spin_unlock_irqrestore(&audio->dsp_lock, flags);
813 rc = 0;
814 break;
815 case AUDIO_SET_VOLUME:
816 spin_lock_irqsave(&audio->dsp_lock, flags);
817 audio->vol_pan.volume = arg;
818 if (audio->running)
819 audpp_dsp_set_vol_pan(audio->dec_id, &audio->vol_pan);
820 spin_unlock_irqrestore(&audio->dsp_lock, flags);
821 rc = 0;
822 break;
823
824 case AUDIO_SET_PAN:
825 spin_lock_irqsave(&audio->dsp_lock, flags);
826 audio->vol_pan.pan = arg;
827 if (audio->running)
828 audpp_dsp_set_vol_pan(audio->dec_id, &audio->vol_pan);
829 spin_unlock_irqrestore(&audio->dsp_lock, flags);
830 rc = 0;
831 break;
832
833 case AUDIO_SET_EQ:
834 prev_state = audio->eq_enable;
835 audio->eq_enable = 0;
836 if (copy_from_user(&audio->eq.num_bands, (void *) arg,
837 sizeof(audio->eq) -
838 (AUDPP_CMD_CFG_OBJECT_PARAMS_COMMON_LEN + 2))) {
839 rc = -EFAULT;
840 break;
841 }
842 audio->eq_enable = prev_state;
843 audio->eq_needs_commit = 1;
844 rc = 0;
845 break;
846 }
847
848 if (-EINVAL != rc)
849 return rc;
850
851 if (cmd == AUDIO_GET_EVENT) {
852 MM_DBG("AUDIO_GET_EVENT\n");
853 if (mutex_trylock(&audio->get_event_lock)) {
854 rc = audamrwb_process_event_req(audio,
855 (void __user *) arg);
856 mutex_unlock(&audio->get_event_lock);
857 } else
858 rc = -EBUSY;
859 return rc;
860 }
861
862 if (cmd == AUDIO_ABORT_GET_EVENT) {
863 audio->event_abort = 1;
864 wake_up(&audio->event_wait);
865 return 0;
866 }
867
868 mutex_lock(&audio->lock);
869 switch (cmd) {
870 case AUDIO_START:
871 MM_DBG("AUDIO_START\n");
872 rc = audamrwb_enable(audio);
873 if (!rc) {
874 rc = wait_event_interruptible_timeout(audio->wait,
875 audio->dec_state != MSM_AUD_DECODER_STATE_NONE,
876 msecs_to_jiffies(MSM_AUD_DECODER_WAIT_MS));
877 MM_INFO("dec_state %d rc = %d\n", audio->dec_state, rc);
878
879 if (audio->dec_state != MSM_AUD_DECODER_STATE_SUCCESS)
880 rc = -ENODEV;
881 else
882 rc = 0;
883 }
884 break;
885 case AUDIO_STOP:
886 MM_DBG("AUDIO_STOP\n");
887 rc = audamrwb_disable(audio);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700888 audamrwb_ioport_reset(audio);
889 audio->stopped = 0;
890 break;
891 case AUDIO_FLUSH:
892 MM_DBG(" AUDIO_FLUSH\n");
893 audio->rflush = 1;
894 audio->wflush = 1;
895 audamrwb_ioport_reset(audio);
896 if (audio->running) {
897 audpp_flush(audio->dec_id);
898 rc = wait_event_interruptible(audio->write_wait,
899 !audio->wflush);
900 if (rc < 0) {
901 MM_ERR("AUDIO_FLUSH interrupted\n");
902 rc = -EINTR;
903 }
904 } else {
905 audio->rflush = 0;
906 audio->wflush = 0;
907 }
908 break;
909 case AUDIO_SET_CONFIG:{
910 struct msm_audio_config config;
911 if (copy_from_user
912 (&config, (void *)arg, sizeof(config))) {
913 rc = -EFAULT;
914 break;
915 }
916 if (config.channel_count == 1)
917 config.channel_count =
918 AUDPP_CMD_PCM_INTF_MONO_V;
919 else if (config.channel_count == 2)
920 config.channel_count =
921 AUDPP_CMD_PCM_INTF_STEREO_V;
922 else
923 rc = -EINVAL;
924 audio->out_channel_mode = config.channel_count;
925 audio->out_sample_rate = config.sample_rate;
926 audio->mfield = config.meta_field;
927 rc = 0;
928 break;
929 }
930 case AUDIO_GET_CONFIG:{
931 struct msm_audio_config config;
932 config.buffer_size = BUFSZ;
933 config.buffer_count = 2;
934 config.sample_rate = audio->out_sample_rate;
935 if (audio->out_channel_mode ==
936 AUDPP_CMD_PCM_INTF_MONO_V)
937 config.channel_count = 1;
938 else
939 config.channel_count = 2;
940 config.meta_field = 0;
941 config.unused[0] = 0;
942 config.unused[1] = 0;
943 config.unused[2] = 0;
944 if (copy_to_user((void *)arg, &config,
945 sizeof(config)))
946 rc = -EFAULT;
947 else
948 rc = 0;
949
950 break;
951 }
952 case AUDIO_GET_PCM_CONFIG:{
953 struct msm_audio_pcm_config config;
954 config.pcm_feedback = 0;
955 config.buffer_count = PCM_BUF_MAX_COUNT;
956 config.buffer_size = PCM_BUFSZ_MIN;
957 if (copy_to_user((void *)arg, &config,
958 sizeof(config)))
959 rc = -EFAULT;
960 else
961 rc = 0;
962 break;
963 }
964 case AUDIO_SET_PCM_CONFIG:{
965 struct msm_audio_pcm_config config;
966 if (copy_from_user
967 (&config, (void *)arg, sizeof(config))) {
968 rc = -EFAULT;
969 break;
970 }
971 if ((config.buffer_count > PCM_BUF_MAX_COUNT) ||
972 (config.buffer_count == 1))
973 config.buffer_count = PCM_BUF_MAX_COUNT;
974
975 if (config.buffer_size < PCM_BUFSZ_MIN)
976 config.buffer_size = PCM_BUFSZ_MIN;
977
978 /* Check if pcm feedback is required */
979 if ((config.pcm_feedback) && (!audio->read_data)) {
980 MM_DBG("allocate PCM buf %d\n", config.buffer_count *
981 config.buffer_size);
Sidipotu Ashok172c98b2012-06-26 17:58:29 +0530982 handle = ion_alloc(audio->client,
983 (config.buffer_size *
984 config.buffer_count),
Hanumant Singh7d72bad2012-08-29 18:39:44 -0700985 SZ_4K, ION_HEAP(ION_AUDIO_HEAP_ID), 0);
Sidipotu Ashok172c98b2012-06-26 17:58:29 +0530986 if (IS_ERR_OR_NULL(handle)) {
987 MM_ERR("Unable to alloc I/P buffs\n");
988 audio->input_buff_handle = NULL;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700989 rc = -ENOMEM;
990 break;
Sidipotu Ashok172c98b2012-06-26 17:58:29 +0530991 }
992
993 audio->input_buff_handle = handle;
994
995 rc = ion_phys(audio->client ,
996 handle, &addr, &len);
997 if (rc) {
998 MM_ERR("Invalid phy: %x sz: %x\n",
999 (unsigned int) addr,
1000 (unsigned int) len);
1001 ion_free(audio->client, handle);
1002 audio->input_buff_handle = NULL;
1003 rc = -ENOMEM;
1004 break;
1005 } else {
1006 MM_INFO("Got valid phy: %x sz: %x\n",
1007 (unsigned int) audio->read_phys,
1008 (unsigned int) len);
1009 }
1010 audio->read_phys = (int32_t)addr;
1011
1012 rc = ion_handle_get_flags(audio->client,
1013 handle, &ionflag);
1014 if (rc) {
1015 MM_ERR("could not get flags\n");
1016 ion_free(audio->client, handle);
1017 audio->input_buff_handle = NULL;
1018 rc = -ENOMEM;
1019 break;
1020 }
1021 audio->map_v_read = ion_map_kernel(
Mitchel Humpherys911b4b72012-09-12 14:42:50 -07001022 audio->client, handle);
Santosh Mardi0be3b8e2011-07-06 10:00:21 +05301023 if (IS_ERR(audio->map_v_read)) {
1024 MM_ERR("failed to map mem for read buf\n");
Sidipotu Ashok172c98b2012-06-26 17:58:29 +05301025 ion_free(audio->client, handle);
1026 audio->input_buff_handle = NULL;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001027 rc = -ENOMEM;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001028 } else {
1029 uint8_t index;
1030 uint32_t offset = 0;
Laura Abbott35111d32012-04-27 18:41:48 -07001031 audio->read_data = audio->map_v_read;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001032 audio->pcm_feedback = 1;
1033 audio->buf_refresh = 0;
1034 audio->pcm_buf_count =
1035 config.buffer_count;
1036 audio->read_next = 0;
1037 audio->fill_next = 0;
1038
1039 for (index = 0;
1040 index < config.buffer_count; index++) {
1041 audio->in[index].data =
1042 audio->read_data + offset;
1043 audio->in[index].addr =
1044 audio->read_phys + offset;
1045 audio->in[index].size =
1046 config.buffer_size;
1047 audio->in[index].used = 0;
1048 offset += config.buffer_size;
1049 }
1050 MM_DBG("read buf: phy addr 0x%08x \
1051 kernel addr 0x%08x\n",
1052 audio->read_phys,
1053 (int)audio->read_data);
1054 rc = 0;
1055 }
1056 } else {
1057 rc = 0;
1058 }
1059 break;
1060 }
1061 default:
1062 rc = -EINVAL;
1063 }
1064 mutex_unlock(&audio->lock);
1065 return rc;
1066}
1067
1068/* Only useful in tunnel-mode */
Sidipotu Ashok172c98b2012-06-26 17:58:29 +05301069static int audamrwb_fsync(struct file *file, loff_t a, loff_t b,
1070 int datasync)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001071{
1072 struct audio *audio = file->private_data;
1073 struct buffer *frame;
1074 int rc = 0;
1075
1076 MM_DBG("\n"); /* Macro prints the file name and function */
1077
1078 if (!audio->running || audio->pcm_feedback) {
1079 rc = -EINVAL;
1080 goto done_nolock;
1081 }
1082
1083 mutex_lock(&audio->write_lock);
1084
1085 rc = wait_event_interruptible(audio->write_wait,
1086 (!audio->out[0].used &&
1087 !audio->out[1].used &&
1088 audio->out_needed) || audio->wflush);
1089
1090 if (rc < 0)
1091 goto done;
1092 else if (audio->wflush) {
1093 rc = -EBUSY;
1094 goto done;
1095 }
1096
1097 if (audio->reserved) {
1098 MM_DBG("send reserved byte\n");
1099 frame = audio->out + audio->out_tail;
1100 ((char *) frame->data)[0] = audio->rsv_byte;
1101 ((char *) frame->data)[1] = 0;
1102 frame->used = 2;
1103 audamrwb_send_data(audio, 0);
1104
1105 rc = wait_event_interruptible(audio->write_wait,
1106 (!audio->out[0].used &&
1107 !audio->out[1].used &&
1108 audio->out_needed) || audio->wflush);
1109
1110 if (rc < 0)
1111 goto done;
1112 else if (audio->wflush) {
1113 rc = -EBUSY;
1114 goto done;
1115 }
1116 }
1117
1118 /* pcm dmamiss message is sent continously
1119 * when decoder is starved so no race
1120 * condition concern
1121 */
1122 audio->teos = 0;
1123
1124 rc = wait_event_interruptible(audio->write_wait,
1125 audio->teos || audio->wflush);
1126
1127 if (audio->wflush)
1128 rc = -EBUSY;
1129
1130done:
1131 mutex_unlock(&audio->write_lock);
1132done_nolock:
1133 return rc;
1134}
1135
1136static ssize_t audamrwb_read(struct file *file, char __user *buf, size_t count,
1137 loff_t *pos)
1138{
1139 struct audio *audio = file->private_data;
1140 const char __user *start = buf;
1141 int rc = 0;
1142
1143 if (!audio->pcm_feedback)
1144 return 0; /* PCM feedback is not enabled. Nothing to read */
1145
1146 mutex_lock(&audio->read_lock);
1147 MM_DBG("count %d\n", count);
1148 while (count > 0) {
1149 rc = wait_event_interruptible(audio->read_wait,
1150 (audio->in[audio->read_next].used > 0) ||
1151 (audio->stopped) || (audio->rflush));
1152
1153 if (rc < 0)
1154 break;
1155
1156 if (audio->stopped || audio->rflush) {
1157 rc = -EBUSY;
1158 break;
1159 }
1160
1161 if (count < audio->in[audio->read_next].used) {
1162 /* Read must happen in frame boundary. Since driver does
1163 * not know frame size, read count must be greater or
1164 * equal to size of PCM samples
1165 */
1166 MM_DBG("read stop - partial frame\n");
1167 break;
1168 } else {
1169 MM_DBG("read from in[%d]\n",
1170 audio->read_next);
1171
1172 if (copy_to_user
1173 (buf, audio->in[audio->read_next].data,
1174 audio->in[audio->read_next].used)) {
1175 MM_ERR("invalid addr %x \n", (unsigned int)buf);
1176 rc = -EFAULT;
1177 break;
1178 }
1179 count -= audio->in[audio->read_next].used;
1180 buf += audio->in[audio->read_next].used;
1181 audio->in[audio->read_next].used = 0;
1182 if ((++audio->read_next) == audio->pcm_buf_count)
1183 audio->read_next = 0;
1184 break;
1185 }
1186 }
1187
1188 /* don't feed output buffer to HW decoder during flushing
1189 * buffer refresh command will be sent once flush completes
1190 * send buf refresh command here can confuse HW decoder
1191 */
1192 if (audio->buf_refresh && !audio->rflush) {
1193 audio->buf_refresh = 0;
1194 MM_ERR("kick start pcm feedback again\n");
1195 audamrwb_buffer_refresh(audio);
1196 }
1197
1198 mutex_unlock(&audio->read_lock);
1199
1200 if (buf > start)
1201 rc = buf - start;
1202
1203 MM_DBG("read %d bytes\n", rc);
1204 return rc;
1205}
1206
1207static int audamrwb_process_eos(struct audio *audio,
1208 const char __user *buf_start, unsigned short mfield_size)
1209{
1210 struct buffer *frame;
1211 char *buf_ptr;
1212 int rc = 0;
1213
1214 MM_DBG("signal input EOS reserved=%d\n", audio->reserved);
1215 if (audio->reserved) {
1216 MM_DBG("Pass reserve byte\n");
1217 frame = audio->out + audio->out_head;
1218 buf_ptr = frame->data;
1219 rc = wait_event_interruptible(audio->write_wait,
1220 (frame->used == 0)
1221 || (audio->stopped)
1222 || (audio->wflush));
1223 if (rc < 0)
1224 goto done;
1225 if (audio->stopped || audio->wflush) {
1226 rc = -EBUSY;
1227 goto done;
1228 }
1229 buf_ptr[0] = audio->rsv_byte;
1230 buf_ptr[1] = 0;
1231 audio->out_head ^= 1;
1232 frame->mfield_sz = 0;
1233 audio->reserved = 0;
1234 frame->used = 2;
1235 audamrwb_send_data(audio, 0);
1236 }
1237
1238 MM_DBG("Now signal input EOS after reserved bytes %d %d %d\n",
1239 audio->out[0].used, audio->out[1].used, audio->out_needed);
1240
1241 frame = audio->out + audio->out_head;
1242
1243 rc = wait_event_interruptible(audio->write_wait,
1244 (audio->out_needed &&
1245 audio->out[0].used == 0 &&
1246 audio->out[1].used == 0)
1247 || (audio->stopped)
1248 || (audio->wflush));
1249
1250 if (rc < 0)
1251 goto done;
1252 if (audio->stopped || audio->wflush) {
1253 rc = -EBUSY;
1254 goto done;
1255 }
1256
1257 if (copy_from_user(frame->data, buf_start, mfield_size)) {
1258 rc = -EFAULT;
1259 goto done;
1260 }
1261
1262 frame->mfield_sz = mfield_size;
1263 audio->out_head ^= 1;
1264 frame->used = mfield_size;
1265 audamrwb_send_data(audio, 0);
1266
1267done:
1268 return rc;
1269}
1270
1271static ssize_t audamrwb_write(struct file *file, const char __user *buf,
1272 size_t count, loff_t *pos)
1273{
1274 struct audio *audio = file->private_data;
1275 const char __user *start = buf;
1276 struct buffer *frame;
1277 size_t xfer;
1278 char *cpy_ptr;
1279 int rc = 0, eos_condition = AUDAMRWB_EOS_NONE;
1280 unsigned short mfield_size = 0;
1281 unsigned dsize;
1282
1283 MM_DBG("cnt=%d\n", count);
1284
1285 mutex_lock(&audio->write_lock);
1286 while (count > 0) {
1287 frame = audio->out + audio->out_head;
1288 cpy_ptr = frame->data;
1289 dsize = 0;
1290 rc = wait_event_interruptible(audio->write_wait,
1291 (frame->used == 0)
1292 || (audio->stopped)
1293 || (audio->wflush));
1294
1295 MM_DBG("buffer available\n");
1296 if (rc < 0)
1297 break;
1298 if (audio->stopped || audio->wflush) {
1299 rc = -EBUSY;
1300 break;
1301 }
1302
1303 if (audio->mfield) {
1304 if (buf == start) {
1305 /* Processing beginning of user buffer */
1306 if (__get_user(mfield_size,
1307 (unsigned short __user *) buf)) {
1308 rc = -EFAULT;
1309 break;
1310 } else if (mfield_size > count) {
1311 rc = -EINVAL;
1312 break;
1313 }
1314 MM_DBG("mf offset_val %x\n", mfield_size);
1315 if (copy_from_user(cpy_ptr, buf, mfield_size)) {
1316 rc = -EFAULT;
1317 break;
1318 }
1319 /* Check if EOS flag is set and buffer
1320 * contains just meta field
1321 */
1322 if (cpy_ptr[AUDAMRWB_EOS_FLG_OFFSET] &
1323 AUDAMRWB_EOS_FLG_MASK) {
1324 MM_DBG("eos set\n");
1325 eos_condition = AUDAMRWB_EOS_SET;
1326 if (mfield_size == count) {
1327 buf += mfield_size;
1328 break;
1329 } else
1330 cpy_ptr[AUDAMRWB_EOS_FLG_OFFSET] &=
1331 ~AUDAMRWB_EOS_FLG_MASK;
1332 }
1333 cpy_ptr += mfield_size;
1334 count -= mfield_size;
1335 dsize += mfield_size;
1336 buf += mfield_size;
1337 } else {
1338 mfield_size = 0;
1339 MM_DBG("continuous buffer\n");
1340 }
1341 frame->mfield_sz = mfield_size;
1342 }
1343
1344 if (audio->reserved) {
1345 MM_DBG("append reserved byte %x\n", audio->rsv_byte);
1346 *cpy_ptr = audio->rsv_byte;
1347 xfer = (count > ((frame->size - mfield_size) - 1)) ?
1348 ((frame->size - mfield_size) - 1) : count;
1349 cpy_ptr++;
1350 dsize += 1;
1351 audio->reserved = 0;
1352 } else
1353 xfer = (count > (frame->size - mfield_size)) ?
1354 (frame->size - mfield_size) : count;
1355
1356 if (copy_from_user(cpy_ptr, buf, xfer)) {
1357 rc = -EFAULT;
1358 break;
1359 }
1360
1361 dsize += xfer;
1362 if (dsize & 1) {
1363 audio->rsv_byte = ((char *) frame->data)[dsize - 1];
1364 MM_DBG("odd length buf reserve last byte %x\n",
1365 audio->rsv_byte);
1366 audio->reserved = 1;
1367 dsize--;
1368 }
1369 count -= xfer;
1370 buf += xfer;
1371
1372 if (dsize > 0) {
1373 audio->out_head ^= 1;
1374 frame->used = dsize;
1375 audamrwb_send_data(audio, 0);
1376 }
1377 }
1378 MM_DBG("eos_condition %x buf[0x%x] start[0x%x]\n", eos_condition,
1379 (int) buf, (int) start);
1380 if (eos_condition == AUDAMRWB_EOS_SET)
1381 rc = audamrwb_process_eos(audio, start, mfield_size);
1382 mutex_unlock(&audio->write_lock);
1383 if (!rc) {
1384 if (buf > start)
1385 return buf - start;
1386 }
1387 return rc;
1388}
1389
1390static int audamrwb_release(struct inode *inode, struct file *file)
1391{
1392 struct audio *audio = file->private_data;
1393
1394 MM_INFO("audio instance 0x%08x freeing\n", (int)audio);
1395 mutex_lock(&audio->lock);
1396 audamrwb_disable(audio);
1397 if (audio->rmt_resource_released == 0)
1398 rmt_put_resource(audio);
1399 audamrwb_flush(audio);
1400 audamrwb_flush_pcm_buf(audio);
1401 msm_adsp_put(audio->audplay);
1402 audpp_adec_free(audio->dec_id);
1403#ifdef CONFIG_HAS_EARLYSUSPEND
1404 unregister_early_suspend(&audio->suspend_ctl.node);
1405#endif
1406 audio->event_abort = 1;
1407 wake_up(&audio->event_wait);
1408 audamrwb_reset_event_queue(audio);
Sidipotu Ashok172c98b2012-06-26 17:58:29 +05301409 ion_unmap_kernel(audio->client, audio->output_buff_handle);
1410 ion_free(audio->client, audio->output_buff_handle);
1411 if (audio->input_buff_handle != NULL) {
1412 ion_unmap_kernel(audio->client, audio->input_buff_handle);
1413 ion_free(audio->client, audio->input_buff_handle);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001414 }
Sidipotu Ashok172c98b2012-06-26 17:58:29 +05301415 ion_client_destroy(audio->client);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001416 mutex_unlock(&audio->lock);
1417#ifdef CONFIG_DEBUG_FS
1418 if (audio->dentry)
1419 debugfs_remove(audio->dentry);
1420#endif
1421 kfree(audio);
1422 return 0;
1423}
1424
1425#ifdef CONFIG_HAS_EARLYSUSPEND
1426static void audamrwb_post_event(struct audio *audio, int type,
1427 union msm_audio_event_payload payload)
1428{
1429 struct audamrwb_event *e_node = NULL;
1430 unsigned long flags;
1431
1432 spin_lock_irqsave(&audio->event_queue_lock, flags);
1433
1434 if (!list_empty(&audio->free_event_queue)) {
1435 e_node = list_first_entry(&audio->free_event_queue,
1436 struct audamrwb_event, list);
1437 list_del(&e_node->list);
1438 } else {
1439 e_node = kmalloc(sizeof(struct audamrwb_event), GFP_ATOMIC);
1440 if (!e_node) {
1441 MM_ERR("No mem to post event %d\n", type);
1442 spin_unlock_irqrestore(&audio->event_queue_lock, flags);
1443 return;
1444 }
1445 }
1446
1447 e_node->event_type = type;
1448 e_node->payload = payload;
1449
1450 list_add_tail(&e_node->list, &audio->event_queue);
1451 spin_unlock_irqrestore(&audio->event_queue_lock, flags);
1452 wake_up(&audio->event_wait);
1453}
1454
1455static void audamrwb_suspend(struct early_suspend *h)
1456{
1457 struct audamrwb_suspend_ctl *ctl =
1458 container_of(h, struct audamrwb_suspend_ctl, node);
1459 union msm_audio_event_payload payload;
1460
1461 MM_DBG("\n"); /* Macro prints the file name and function */
1462 audamrwb_post_event(ctl->audio, AUDIO_EVENT_SUSPEND, payload);
1463}
1464
1465static void audamrwb_resume(struct early_suspend *h)
1466{
1467 struct audamrwb_suspend_ctl *ctl =
1468 container_of(h, struct audamrwb_suspend_ctl, node);
1469 union msm_audio_event_payload payload;
1470
1471 MM_DBG("\n"); /* Macro prints the file name and function */
1472 audamrwb_post_event(ctl->audio, AUDIO_EVENT_RESUME, payload);
1473}
1474#endif
1475
1476#ifdef CONFIG_DEBUG_FS
1477static ssize_t audamrwb_debug_open(struct inode *inode, struct file *file)
1478{
1479 file->private_data = inode->i_private;
1480 return 0;
1481}
1482
1483static ssize_t audamrwb_debug_read(struct file *file, char __user *buf,
1484 size_t count, loff_t *ppos)
1485{
1486 const int debug_bufmax = 1024;
1487 static char buffer[1024];
1488 int n = 0, i;
1489 struct audio *audio = file->private_data;
1490
1491 mutex_lock(&audio->lock);
1492 n = scnprintf(buffer, debug_bufmax, "opened %d\n", audio->opened);
1493 n += scnprintf(buffer + n, debug_bufmax - n,
1494 "enabled %d\n", audio->enabled);
1495 n += scnprintf(buffer + n, debug_bufmax - n,
1496 "stopped %d\n", audio->stopped);
1497 n += scnprintf(buffer + n, debug_bufmax - n,
1498 "pcm_feedback %d\n", audio->pcm_feedback);
1499 n += scnprintf(buffer + n, debug_bufmax - n,
1500 "out_buf_sz %d\n", audio->out[0].size);
1501 n += scnprintf(buffer + n, debug_bufmax - n,
1502 "pcm_buf_count %d \n", audio->pcm_buf_count);
1503 n += scnprintf(buffer + n, debug_bufmax - n,
1504 "pcm_buf_sz %d \n", audio->in[0].size);
1505 n += scnprintf(buffer + n, debug_bufmax - n,
1506 "volume %x \n", audio->vol_pan.volume);
1507 n += scnprintf(buffer + n, debug_bufmax - n,
1508 "sample rate %d \n", audio->out_sample_rate);
1509 n += scnprintf(buffer + n, debug_bufmax - n,
1510 "channel mode %d \n", audio->out_channel_mode);
1511 mutex_unlock(&audio->lock);
1512 /* Following variables are only useful for debugging when
1513 * when playback halts unexpectedly. Thus, no mutual exclusion
1514 * enforced
1515 */
1516 n += scnprintf(buffer + n, debug_bufmax - n,
1517 "wflush %d\n", audio->wflush);
1518 n += scnprintf(buffer + n, debug_bufmax - n,
1519 "rflush %d\n", audio->rflush);
1520 n += scnprintf(buffer + n, debug_bufmax - n,
1521 "running %d \n", audio->running);
1522 n += scnprintf(buffer + n, debug_bufmax - n,
1523 "dec state %d \n", audio->dec_state);
1524 n += scnprintf(buffer + n, debug_bufmax - n,
1525 "out_needed %d \n", audio->out_needed);
1526 n += scnprintf(buffer + n, debug_bufmax - n,
1527 "out_head %d \n", audio->out_head);
1528 n += scnprintf(buffer + n, debug_bufmax - n,
1529 "out_tail %d \n", audio->out_tail);
1530 n += scnprintf(buffer + n, debug_bufmax - n,
1531 "out[0].used %d \n", audio->out[0].used);
1532 n += scnprintf(buffer + n, debug_bufmax - n,
1533 "out[1].used %d \n", audio->out[1].used);
1534 n += scnprintf(buffer + n, debug_bufmax - n,
1535 "buffer_refresh %d \n", audio->buf_refresh);
1536 n += scnprintf(buffer + n, debug_bufmax - n,
1537 "read_next %d \n", audio->read_next);
1538 n += scnprintf(buffer + n, debug_bufmax - n,
1539 "fill_next %d \n", audio->fill_next);
1540 for (i = 0; i < audio->pcm_buf_count; i++)
1541 n += scnprintf(buffer + n, debug_bufmax - n,
1542 "in[%d].used %d \n", i, audio->in[i].used);
1543 buffer[n] = 0;
1544 return simple_read_from_buffer(buf, count, ppos, buffer, n);
1545}
1546
1547static const struct file_operations audamrwb_debug_fops = {
1548 .read = audamrwb_debug_read,
1549 .open = audamrwb_debug_open,
1550};
1551#endif
1552
1553static int audamrwb_open(struct inode *inode, struct file *file)
1554{
1555 struct audio *audio = NULL;
Sidipotu Ashok172c98b2012-06-26 17:58:29 +05301556 int rc = 0, dec_attrb, decid, i;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001557 struct audamrwb_event *e_node = NULL;
Sidipotu Ashok172c98b2012-06-26 17:58:29 +05301558 unsigned mem_sz = DMASZ;
1559 unsigned long ionflag = 0;
1560 ion_phys_addr_t addr = 0;
1561 struct ion_handle *handle = NULL;
1562 struct ion_client *client = NULL;
1563 int len = 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001564#ifdef CONFIG_DEBUG_FS
1565 /* 4 bytes represents decoder number, 1 byte for terminate string */
1566 char name[sizeof "msm_amrwb_" + 5];
1567#endif
1568
1569 /* Allocate Mem for audio instance */
1570 audio = kzalloc(sizeof(struct audio), GFP_KERNEL);
1571 if (!audio) {
1572 MM_ERR("No memory to allocate audio instance\n");
1573 rc = -ENOMEM;
1574 goto done;
1575 }
1576 MM_INFO("audio instance 0x%08x created\n", (int)audio);
1577
1578 /* Allocate the decoder */
1579 dec_attrb = AUDDEC_DEC_AMRWB;
1580 if (file->f_mode & FMODE_READ)
1581 dec_attrb |= MSM_AUD_MODE_NONTUNNEL;
1582 else
1583 dec_attrb |= MSM_AUD_MODE_TUNNEL;
1584
1585 decid = audpp_adec_alloc(dec_attrb, &audio->module_name,
1586 &audio->queue_id);
1587
1588 if (decid < 0) {
1589 MM_ERR("No free decoder available, freeing instance 0x%08x\n",
1590 (int)audio);
1591 rc = -ENODEV;
1592 kfree(audio);
1593 goto done;
1594 }
1595
1596 audio->dec_id = decid & MSM_AUD_DECODER_MASK;
1597
Sidipotu Ashok172c98b2012-06-26 17:58:29 +05301598 client = msm_ion_client_create(UINT_MAX, "Audio_AMR_WB_Client");
1599 if (IS_ERR_OR_NULL(client)) {
1600 pr_err("Unable to create ION client\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001601 rc = -ENOMEM;
Sidipotu Ashok172c98b2012-06-26 17:58:29 +05301602 goto client_create_error;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001603 }
Sidipotu Ashok172c98b2012-06-26 17:58:29 +05301604 audio->client = client;
1605
1606 handle = ion_alloc(client, mem_sz, SZ_4K,
Hanumant Singh7d72bad2012-08-29 18:39:44 -07001607 ION_HEAP(ION_AUDIO_HEAP_ID), 0);
Sidipotu Ashok172c98b2012-06-26 17:58:29 +05301608 if (IS_ERR_OR_NULL(handle)) {
1609 MM_ERR("Unable to create allocate O/P buffers\n");
1610 goto output_buff_alloc_error;
1611 }
1612 audio->output_buff_handle = handle;
1613
1614 rc = ion_phys(client, handle, &addr, &len);
1615 if (rc) {
1616 MM_ERR("O/P buffers:Invalid phy: %x sz: %x\n",
1617 (unsigned int) addr, (unsigned int) len);
1618 goto output_buff_get_phys_error;
1619 } else {
1620 MM_INFO("O/P buffers:valid phy: %x sz: %x\n",
1621 (unsigned int) addr, (unsigned int) len);
1622 }
1623 audio->phys = (int32_t)addr;
1624
1625
1626 rc = ion_handle_get_flags(client, handle, &ionflag);
1627 if (rc) {
1628 MM_ERR("could not get flags for the handle\n");
1629 goto output_buff_get_flags_error;
1630 }
1631
Mitchel Humpherys911b4b72012-09-12 14:42:50 -07001632 audio->map_v_write = ion_map_kernel(client, handle);
Sidipotu Ashok172c98b2012-06-26 17:58:29 +05301633 if (IS_ERR(audio->map_v_write)) {
1634 MM_ERR("could not map write buffers\n");
1635 rc = -ENOMEM;
1636 goto output_buff_map_error;
1637 }
1638 audio->data = audio->map_v_write;
1639 MM_DBG("write buf: phy addr 0x%08x kernel addr 0x%08x\n",
1640 audio->phys, (int)audio->data);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001641
1642 if (audio->pcm_feedback == TUNNEL_MODE_PLAYBACK) {
1643 rc = audmgr_open(&audio->audmgr);
1644 if (rc) {
1645 MM_ERR("audmgr open failed, freeing instance \
1646 0x%08x\n", (int)audio);
1647 goto err;
1648 }
1649 }
1650
1651 rc = msm_adsp_get(audio->module_name, &audio->audplay,
1652 &audplay_adsp_ops_amrwb, audio);
1653 if (rc) {
1654 MM_ERR("failed to get %s module, freeing instance 0x%08x\n",
1655 audio->module_name, (int)audio);
1656 if (audio->pcm_feedback == TUNNEL_MODE_PLAYBACK)
1657 audmgr_close(&audio->audmgr);
1658 goto err;
1659 }
1660
1661 rc = rmt_get_resource(audio);
1662 if (rc) {
1663 MM_ERR("ADSP resources are not available for AMRWB session \
1664 0x%08x on decoder: %d\n", (int)audio, audio->dec_id);
1665 if (audio->pcm_feedback == TUNNEL_MODE_PLAYBACK)
1666 audmgr_close(&audio->audmgr);
1667 msm_adsp_put(audio->audplay);
1668 goto err;
1669 }
1670
Sidipotu Ashok172c98b2012-06-26 17:58:29 +05301671 audio->input_buff_handle = NULL;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001672 mutex_init(&audio->lock);
1673 mutex_init(&audio->write_lock);
1674 mutex_init(&audio->read_lock);
1675 mutex_init(&audio->get_event_lock);
1676 spin_lock_init(&audio->dsp_lock);
1677 spin_lock_init(&audio->event_queue_lock);
1678 INIT_LIST_HEAD(&audio->free_event_queue);
1679 INIT_LIST_HEAD(&audio->event_queue);
1680 init_waitqueue_head(&audio->write_wait);
1681 init_waitqueue_head(&audio->read_wait);
1682 init_waitqueue_head(&audio->wait);
1683 init_waitqueue_head(&audio->event_wait);
1684
1685 audio->out[0].data = audio->data + 0;
1686 audio->out[0].addr = audio->phys + 0;
1687 audio->out[0].size = BUFSZ;
1688
1689 audio->out[1].data = audio->data + BUFSZ;
1690 audio->out[1].addr = audio->phys + BUFSZ;
1691 audio->out[1].size = BUFSZ;
1692
1693 audio->vol_pan.volume = 0x2000;
1694 audio->vol_pan.pan = 0x0;
1695 audio->eq_enable = 0;
1696 audio->out_sample_rate = 44100;
1697 audio->out_channel_mode = AUDPP_CMD_PCM_INTF_STEREO_V;
1698
1699 audamrwb_flush(audio);
1700
1701 file->private_data = audio;
1702 audio->opened = 1;
1703 audio->event_abort = 0;
1704#ifdef CONFIG_DEBUG_FS
1705 snprintf(name, sizeof name, "msm_amrwb_%04x", audio->dec_id);
1706 audio->dentry = debugfs_create_file(name, S_IFREG | S_IRUGO,
1707 NULL, (void *) audio, &audamrwb_debug_fops);
1708
1709 if (IS_ERR(audio->dentry))
1710 MM_DBG("debugfs_create_file failed\n");
1711#endif
1712#ifdef CONFIG_HAS_EARLYSUSPEND
1713 audio->suspend_ctl.node.level = EARLY_SUSPEND_LEVEL_DISABLE_FB;
1714 audio->suspend_ctl.node.resume = audamrwb_resume;
1715 audio->suspend_ctl.node.suspend = audamrwb_suspend;
1716 audio->suspend_ctl.audio = audio;
1717 register_early_suspend(&audio->suspend_ctl.node);
1718#endif
1719 for (i = 0; i < AUDAMRWB_EVENT_NUM; i++) {
1720 e_node = kmalloc(sizeof(struct audamrwb_event), GFP_KERNEL);
1721 if (e_node)
1722 list_add_tail(&e_node->list, &audio->free_event_queue);
1723 else {
1724 MM_ERR("event pkt alloc failed\n");
1725 break;
1726 }
1727 }
1728done:
1729 return rc;
1730err:
Sidipotu Ashok172c98b2012-06-26 17:58:29 +05301731 ion_unmap_kernel(client, audio->output_buff_handle);
1732output_buff_map_error:
1733output_buff_get_phys_error:
1734output_buff_get_flags_error:
1735 ion_free(client, audio->output_buff_handle);
1736output_buff_alloc_error:
1737 ion_client_destroy(client);
1738client_create_error:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001739 audpp_adec_free(audio->dec_id);
1740 kfree(audio);
1741 return rc;
1742}
1743
1744static const struct file_operations audio_amrwb_fops = {
1745 .owner = THIS_MODULE,
1746 .open = audamrwb_open,
1747 .release = audamrwb_release,
1748 .read = audamrwb_read,
1749 .write = audamrwb_write,
1750 .unlocked_ioctl = audamrwb_ioctl,
1751 .fsync = audamrwb_fsync,
1752};
1753
1754struct miscdevice audio_amrwb_misc = {
1755 .minor = MISC_DYNAMIC_MINOR,
1756 .name = "msm_amrwb",
1757 .fops = &audio_amrwb_fops,
1758};
1759
1760static int __init audamrwb_init(void)
1761{
1762 return misc_register(&audio_amrwb_misc);
1763}
1764
1765static void __exit audamrwb_exit(void)
1766{
1767 misc_deregister(&audio_amrwb_misc);
1768}
1769
1770module_init(audamrwb_init);
1771module_exit(audamrwb_exit);
1772
1773MODULE_DESCRIPTION("MSM AMR-WB driver");
1774MODULE_LICENSE("GPL v2");