blob: 07f9f4ce17324133343905cee641174ed6bf77c6 [file] [log] [blame]
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001/* arch/arm/mach-msm/qdsp5/audio_out.c
2 *
3 * pcm audio output device
4 *
5 * Copyright (C) 2008 Google, Inc.
6 * Copyright (C) 2008 HTC Corporation
Chaithanya Krishna Bacharaju4fa5ab02013-01-07 11:43:56 +05307 * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07008 *
9 * This software is licensed under the terms of the GNU General Public
10 * License version 2, as published by the Free Software Foundation, and
11 * may be copied, distributed, and modified under those terms.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 */
19
20#include <linux/module.h>
21#include <linux/fs.h>
22#include <linux/miscdevice.h>
23#include <linux/uaccess.h>
24#include <linux/kthread.h>
Sidipotu Ashok3144aa22012-03-16 10:55:24 +053025#include <linux/slab.h>
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070026#include <linux/wait.h>
27#include <linux/dma-mapping.h>
28#include <linux/debugfs.h>
29#include <linux/delay.h>
30#include <linux/wakelock.h>
Stephen Boyd2fcabf92012-05-30 10:41:11 -070031#include <linux/pm_qos.h>
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070032
33#include <linux/msm_audio.h>
34
35#include <asm/atomic.h>
36#include <asm/ioctls.h>
37#include <mach/msm_adsp.h>
Stephen Boyd2fcabf92012-05-30 10:41:11 -070038#include <mach/cpuidle.h>
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070039
40#include "audmgr.h"
41
Chaithanya Krishna Bacharaju4fa5ab02013-01-07 11:43:56 +053042#include <mach/qdsp5/audio_acdb_def.h>
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070043#include <mach/qdsp5/qdsp5audppcmdi.h>
44#include <mach/qdsp5/qdsp5audppmsg.h>
Manish Dewanganfa8a6b62012-07-09 16:23:27 +053045#include <mach/qdsp5/qdsp5audpp.h>
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070046
47#include <mach/htc_pwrsink.h>
48#include <mach/debug_mm.h>
49
50#include "evlog.h"
51
52#define LOG_AUDIO_EVENTS 1
53#define LOG_AUDIO_FAULTS 0
54
Sidipotu Ashok3144aa22012-03-16 10:55:24 +053055#define SRS_ID_GLOBAL 0x00000001
56#define SRS_ID_WOWHD 0x00000002
57#define SRS_ID_CSHP 0x00000003
58#define SRS_ID_HPF 0x00000004
59#define SRS_ID_PEQ 0x00000005
60#define SRS_ID_HL 0x00000006
61
62#define SRS_MASK_G 1
63#define SRS_MASK_W 2
64#define SRS_MASK_C 4
65#define SRS_MASK_HP 8
66#define SRS_MASK_P 16
67#define SRS_MASK_HL 32
68
69
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070070enum {
71 EV_NULL,
72 EV_OPEN,
73 EV_WRITE,
74 EV_RETURN,
75 EV_IOCTL,
76 EV_WRITE_WAIT,
77 EV_WAIT_EVENT,
78 EV_FILL_BUFFER,
79 EV_SEND_BUFFER,
80 EV_DSP_EVENT,
81 EV_ENABLE,
82};
83
84#if (LOG_AUDIO_EVENTS != 1)
85static inline void LOG(unsigned id, unsigned arg) {}
86#else
87static const char *pcm_log_strings[] = {
88 "NULL",
89 "OPEN",
90 "WRITE",
91 "RETURN",
92 "IOCTL",
93 "WRITE_WAIT",
94 "WAIT_EVENT",
95 "FILL_BUFFER",
96 "SEND_BUFFER",
97 "DSP_EVENT",
98 "ENABLE",
99};
100
101DECLARE_LOG(pcm_log, 64, pcm_log_strings);
102
103static int __init _pcm_log_init(void)
104{
105 return ev_log_init(&pcm_log);
106}
107module_init(_pcm_log_init);
108
109#define LOG(id,arg) ev_log_write(&pcm_log, id, arg)
110#endif
111
112
113
114
115
Sidipotu Ashokbe85d1e2012-07-26 10:11:01 +0530116#define BUFSZ (5248)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700117#define DMASZ (BUFSZ * 2)
118
119#define COMMON_OBJ_ID 6
120
121struct buffer {
122 void *data;
123 unsigned size;
124 unsigned used;
125 unsigned addr;
126};
127
128struct audio {
129 struct buffer out[2];
130
131 spinlock_t dsp_lock;
132
133 uint8_t out_head;
134 uint8_t out_tail;
135 uint8_t out_needed; /* number of buffers the dsp is waiting for */
136
137 atomic_t out_bytes;
138
139 struct mutex lock;
140 struct mutex write_lock;
141 wait_queue_head_t wait;
142
143 /* configuration to use on next enable */
144 uint32_t out_sample_rate;
145 uint32_t out_channel_mode;
146 uint32_t out_weight;
147 uint32_t out_buffer_size;
148
149 struct audmgr audmgr;
150
151 /* data allocated for various buffers */
152 char *data;
153 dma_addr_t phys;
154
155 int teos; /* valid only if tunnel mode & no data left for decoder */
156 int opened;
157 int enabled;
158 int running;
159 int stopped; /* set when stopped, cleared on flush */
160
161 struct wake_lock wakelock;
Stephen Boyd2fcabf92012-05-30 10:41:11 -0700162 struct pm_qos_request pm_qos_req;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700163
164 audpp_cmd_cfg_object_params_volume vol_pan;
165};
166
167struct audio_copp {
168 int mbadrc_enable;
169 int mbadrc_needs_commit;
170 char *mbadrc_data;
171 dma_addr_t mbadrc_phys;
172
173 audpp_cmd_cfg_object_params_mbadrc mbadrc;
174
175 int eq_enable;
176 int eq_needs_commit;
177 audpp_cmd_cfg_object_params_eqalizer eq;
178
179 int rx_iir_enable;
180 int rx_iir_needs_commit;
181 audpp_cmd_cfg_object_params_pcm iir;
182
183 audpp_cmd_cfg_object_params_volume vol_pan;
184
185 int qconcert_plus_enable;
186 int qconcert_plus_needs_commit;
Sidipotu Ashok3144aa22012-03-16 10:55:24 +0530187
188 int srs_enable;
189 int srs_needs_commit;
190 int srs_feature_mask;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700191 audpp_cmd_cfg_object_params_qconcert qconcert_plus;
Sriranjan Srikantam87a6c292013-01-25 16:39:58 +0530192 int srs_current_feature_mask;
193 uint32_t audpp_disabled_features;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700194
195 int status;
196 int opened;
197 struct mutex lock;
198
199 struct audpp_event_callback ecb;
Sidipotu Ashok3144aa22012-03-16 10:55:24 +0530200
201 struct audpp_cmd_cfg_object_params_srstm_g g;
202 struct audpp_cmd_cfg_object_params_srstm_w w;
203 struct audpp_cmd_cfg_object_params_srstm_c c;
204 struct audpp_cmd_cfg_object_params_srstm_h h;
205 struct audpp_cmd_cfg_object_params_srstm_p p;
206 struct audpp_cmd_cfg_object_params_srstm_l l;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700207} the_audio_copp;
208
209static void audio_prevent_sleep(struct audio *audio)
210{
211 MM_DBG("\n"); /* Macro prints the file name and function */
212 wake_lock(&audio->wakelock);
Stephen Boyd2fcabf92012-05-30 10:41:11 -0700213 pm_qos_update_request(&audio->pm_qos_req,
214 msm_cpuidle_get_deep_idle_latency());
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700215}
216
217static void audio_allow_sleep(struct audio *audio)
218{
Stephen Boyd2fcabf92012-05-30 10:41:11 -0700219 pm_qos_update_request(&audio->pm_qos_req, PM_QOS_DEFAULT_VALUE);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700220 wake_unlock(&audio->wakelock);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700221 MM_DBG("\n"); /* Macro prints the file name and function */
222}
223
224static int audio_dsp_out_enable(struct audio *audio, int yes);
225static int audio_dsp_send_buffer(struct audio *audio, unsigned id, unsigned len);
226
227static void audio_dsp_event(void *private, unsigned id, uint16_t *msg);
Sidipotu Ashok3144aa22012-03-16 10:55:24 +0530228static int audio_enable_srs_trumedia(struct audio_copp *audio_copp, int enable);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700229/* must be called with audio->lock held */
230static int audio_enable(struct audio *audio)
231{
232 struct audmgr_config cfg;
233 int rc;
234
235 MM_DBG("\n"); /* Macro prints the file name and function */
236
237 if (audio->enabled)
238 return 0;
239
240 /* refuse to start if we're not ready */
241 if (!audio->out[0].used || !audio->out[1].used)
242 return -EIO;
243
244 /* we start buffers 0 and 1, so buffer 0 will be the
245 * next one the dsp will want
246 */
247 audio->out_tail = 0;
248 audio->out_needed = 0;
249
250 cfg.tx_rate = RPC_AUD_DEF_SAMPLE_RATE_NONE;
251 cfg.rx_rate = RPC_AUD_DEF_SAMPLE_RATE_48000;
252 cfg.def_method = RPC_AUD_DEF_METHOD_HOST_PCM;
253 cfg.codec = RPC_AUD_DEF_CODEC_PCM;
254 cfg.snd_method = RPC_SND_METHOD_MIDI;
255
256 audio_prevent_sleep(audio);
257 rc = audmgr_enable(&audio->audmgr, &cfg);
258 if (rc < 0) {
259 audio_allow_sleep(audio);
260 return rc;
261 }
262
263 if (audpp_enable(-1, audio_dsp_event, audio)) {
264 MM_ERR("audpp_enable() failed\n");
265 audmgr_disable(&audio->audmgr);
266 audio_allow_sleep(audio);
267 return -ENODEV;
268 }
269
270 audio->enabled = 1;
271 htc_pwrsink_set(PWRSINK_AUDIO, 100);
272 return 0;
273}
274
275/* must be called with audio->lock held */
276static int audio_disable(struct audio *audio)
277{
278 MM_DBG("\n"); /* Macro prints the file name and function */
279 if (audio->enabled) {
280 audio->enabled = 0;
281 audio_dsp_out_enable(audio, 0);
282
283 audpp_disable(-1, audio);
284
Manish Dewangan89a9f232012-02-09 17:14:40 +0530285 audio->stopped = 1;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700286 wake_up(&audio->wait);
287 audmgr_disable(&audio->audmgr);
288 audio->out_needed = 0;
289 audio_allow_sleep(audio);
290 }
291 return 0;
292}
293
294void audio_commit_pending_pp_params(void *priv, unsigned id, uint16_t *msg)
295{
296 struct audio_copp *audio_copp = priv;
297
Manish Dewangan16aeb5f2013-01-16 18:24:42 +0530298 if (audio_copp == NULL) {
299 MM_ERR("NULL audio copp pointer\n");
300 return;
301 }
302
Sriranjan Srikantam87a6c292013-01-25 16:39:58 +0530303 if (AUDPP_MSG_CFG_MSG == id && msg[0] == AUDPP_MSG_ENA_DIS) {
304 audio_copp->audpp_disabled_features = 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700305 return;
Sriranjan Srikantam87a6c292013-01-25 16:39:58 +0530306 }
307 if (AUDPP_MSG_CFG_MSG == id && msg[0] == AUDPP_MSG_ENA_ENA)
308 audio_copp->audpp_disabled_features = 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700309
310 if (!audio_copp->status)
311 return;
312
Sriranjan Srikantam87a6c292013-01-25 16:39:58 +0530313 if (id == AUDPP_MSG_PP_DISABLE_FEEDBACK) {
314 audio_copp->audpp_disabled_features |=
315 ((uint32_t)(msg[AUDPP_DISABLE_FEATS_MSW] << 16) |
316 msg[AUDPP_DISABLE_FEATS_LSW]);
317 MM_DBG("AUDPP disable feedback: %x",
318 audio_copp->audpp_disabled_features);
319 return;
320 } else if (id == AUDPP_MSG_PP_FEATS_RE_ENABLE) {
321 MM_DBG("AUDPP re-enable messaage: %x, acdb_enabled %d",
322 audio_copp->audpp_disabled_features, is_acdb_enabled());
323 if (!is_acdb_enabled()) {
324 if ((audio_copp->audpp_disabled_features &
325 (1 << AUDPP_CMD_MBADRC)) ==
326 (1 << AUDPP_CMD_MBADRC)) {
327 audpp_dsp_set_mbadrc(COMMON_OBJ_ID,
328 audio_copp->mbadrc_enable,
329 &audio_copp->mbadrc);
330 }
331 if ((audio_copp->audpp_disabled_features &
332 (1 << AUDPP_CMD_EQUALIZER)) ==
333 (1 << AUDPP_CMD_EQUALIZER)) {
334 audpp_dsp_set_eq(COMMON_OBJ_ID,
335 audio_copp->eq_enable,
336 &audio_copp->eq);
337 }
338 if ((audio_copp->audpp_disabled_features &
339 (1 << AUDPP_CMD_IIR_TUNING_FILTER)) ==
340 (1 << AUDPP_CMD_IIR_TUNING_FILTER)) {
341 audpp_dsp_set_rx_iir(COMMON_OBJ_ID,
342 audio_copp->rx_iir_enable,
343 &audio_copp->iir);
344 }
345 if ((audio_copp->audpp_disabled_features &
346 (1 << AUDPP_CMD_QCONCERT)) ==
347 (1 << AUDPP_CMD_QCONCERT)) {
348 audpp_dsp_set_qconcert_plus(COMMON_OBJ_ID,
349 audio_copp->qconcert_plus_enable,
350 &audio_copp->qconcert_plus);
351 }
352 }
353 if ((audio_copp->audpp_disabled_features & (1 << AUDPP_CMD_SRS))
354 == (1 << AUDPP_CMD_SRS)) {
355 if (audio_copp->srs_current_feature_mask & SRS_MASK_W)
356 audpp_dsp_set_rx_srs_trumedia_w(&audio_copp->w);
357 if (audio_copp->srs_current_feature_mask & SRS_MASK_C)
358 audpp_dsp_set_rx_srs_trumedia_c(&audio_copp->c);
359 if (audio_copp->srs_current_feature_mask & SRS_MASK_HP)
360 audpp_dsp_set_rx_srs_trumedia_h(&audio_copp->h);
361 if (audio_copp->srs_current_feature_mask & SRS_MASK_P)
362 audpp_dsp_set_rx_srs_trumedia_p(&audio_copp->p);
363 if (audio_copp->srs_current_feature_mask & SRS_MASK_HL)
364 audpp_dsp_set_rx_srs_trumedia_l(&audio_copp->l);
365 if (audio_copp->srs_current_feature_mask & SRS_MASK_G)
366 audpp_dsp_set_rx_srs_trumedia_g(&audio_copp->g);
367 }
368 audio_copp->audpp_disabled_features = 0;
369 return;
370 }
371
Chaithanya Krishna Bacharaju4fa5ab02013-01-07 11:43:56 +0530372 if (!is_acdb_enabled()) {
373 audpp_dsp_set_mbadrc(COMMON_OBJ_ID, audio_copp->mbadrc_enable,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700374 &audio_copp->mbadrc);
375
Chaithanya Krishna Bacharaju4fa5ab02013-01-07 11:43:56 +0530376 audpp_dsp_set_eq(COMMON_OBJ_ID, audio_copp->eq_enable,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700377 &audio_copp->eq);
Chaithanya Krishna Bacharaju4fa5ab02013-01-07 11:43:56 +0530378 audpp_dsp_set_rx_iir(COMMON_OBJ_ID, audio_copp->rx_iir_enable,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700379 &audio_copp->iir);
Chaithanya Krishna Bacharaju4fa5ab02013-01-07 11:43:56 +0530380 audpp_dsp_set_vol_pan(COMMON_OBJ_ID, &audio_copp->vol_pan);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700381
Chaithanya Krishna Bacharaju4fa5ab02013-01-07 11:43:56 +0530382 audpp_dsp_set_qconcert_plus(COMMON_OBJ_ID,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700383 audio_copp->qconcert_plus_enable,
384 &audio_copp->qconcert_plus);
Chaithanya Krishna Bacharaju4fa5ab02013-01-07 11:43:56 +0530385 }
Sidipotu Ashok3144aa22012-03-16 10:55:24 +0530386 audio_enable_srs_trumedia(audio_copp, true);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700387}
388EXPORT_SYMBOL(audio_commit_pending_pp_params);
389
390/* ------------------- dsp --------------------- */
391static void audio_dsp_event(void *private, unsigned id, uint16_t *msg)
392{
393 struct audio *audio = private;
394 struct buffer *frame;
395 unsigned long flags;
396
397 LOG(EV_DSP_EVENT, id);
398 switch (id) {
399 case AUDPP_MSG_HOST_PCM_INTF_MSG: {
400 unsigned id = msg[2];
401 unsigned idx = msg[3] - 1;
402
403 /* MM_INFO("HOST_PCM id %d idx %d\n", id, idx); */
404 if (id != AUDPP_MSG_HOSTPCM_ID_ARM_RX) {
405 MM_ERR("bogus id\n");
406 break;
407 }
408 if (idx > 1) {
409 MM_ERR("bogus buffer idx\n");
410 break;
411 }
412
413 spin_lock_irqsave(&audio->dsp_lock, flags);
414 if (audio->running) {
415 atomic_add(audio->out[idx].used, &audio->out_bytes);
416 audio->out[idx].used = 0;
417
418 frame = audio->out + audio->out_tail;
419 if (frame->used) {
420 audio_dsp_send_buffer(
421 audio, audio->out_tail, frame->used);
422 audio->out_tail ^= 1;
423 } else {
424 audio->out_needed++;
425 }
426 wake_up(&audio->wait);
427 }
428 spin_unlock_irqrestore(&audio->dsp_lock, flags);
429 break;
430 }
431 case AUDPP_MSG_PCMDMAMISSED:
432 MM_INFO("PCMDMAMISSED %d\n", msg[0]);
433 audio->teos = 1;
434 wake_up(&audio->wait);
435 break;
436 case AUDPP_MSG_CFG_MSG:
437 if (msg[0] == AUDPP_MSG_ENA_ENA) {
438 LOG(EV_ENABLE, 1);
439 MM_DBG("CFG_MSG ENABLE\n");
440 audio->out_needed = 0;
441 audio->running = 1;
442 audpp_dsp_set_vol_pan(5, &audio->vol_pan);
443 audio_dsp_out_enable(audio, 1);
444 } else if (msg[0] == AUDPP_MSG_ENA_DIS) {
445 LOG(EV_ENABLE, 0);
446 MM_DBG("CFG_MSG DISABLE\n");
447 audio->running = 0;
448 } else {
449 MM_ERR("CFG_MSG %d?\n", msg[0]);
450 }
451 break;
452 default:
453 MM_ERR("UNKNOWN (%d)\n", id);
454 }
455}
456
457static int audio_dsp_out_enable(struct audio *audio, int yes)
458{
459 audpp_cmd_pcm_intf cmd;
460
461 memset(&cmd, 0, sizeof(cmd));
462 cmd.cmd_id = AUDPP_CMD_PCM_INTF_2;
463 cmd.object_num = AUDPP_CMD_PCM_INTF_OBJECT_NUM;
464 cmd.config = AUDPP_CMD_PCM_INTF_CONFIG_CMD_V;
465 cmd.intf_type = AUDPP_CMD_PCM_INTF_RX_ENA_ARMTODSP_V;
466
467 if (yes) {
468 cmd.write_buf1LSW = audio->out[0].addr;
469 cmd.write_buf1MSW = audio->out[0].addr >> 16;
470 if (audio->out[0].used)
471 cmd.write_buf1_len = audio->out[0].used;
472 else
473 cmd.write_buf1_len = audio->out[0].size;
474 cmd.write_buf2LSW = audio->out[1].addr;
475 cmd.write_buf2MSW = audio->out[1].addr >> 16;
476 if (audio->out[1].used)
477 cmd.write_buf2_len = audio->out[1].used;
478 else
479 cmd.write_buf2_len = audio->out[1].size;
480 cmd.arm_to_rx_flag = AUDPP_CMD_PCM_INTF_ENA_V;
481 cmd.weight_decoder_to_rx = audio->out_weight;
482 cmd.weight_arm_to_rx = 1;
483 cmd.partition_number_arm_to_dsp = 0;
484 cmd.sample_rate = audio->out_sample_rate;
485 cmd.channel_mode = audio->out_channel_mode;
486 }
487
488 return audpp_send_queue2(&cmd, sizeof(cmd));
489}
490
491static int audio_dsp_send_buffer(struct audio *audio, unsigned idx, unsigned len)
492{
493 audpp_cmd_pcm_intf_send_buffer cmd;
494
495 cmd.cmd_id = AUDPP_CMD_PCM_INTF_2;
496 cmd.host_pcm_object = AUDPP_CMD_PCM_INTF_OBJECT_NUM;
497 cmd.config = AUDPP_CMD_PCM_INTF_BUFFER_CMD_V;
498 cmd.intf_type = AUDPP_CMD_PCM_INTF_RX_ENA_ARMTODSP_V;
499 cmd.dsp_to_arm_buf_id = 0;
500 cmd.arm_to_dsp_buf_id = idx + 1;
501 cmd.arm_to_dsp_buf_len = len;
502
503 LOG(EV_SEND_BUFFER, idx);
504 dma_coherent_pre_ops();
505 return audpp_send_queue2(&cmd, sizeof(cmd));
506}
507
508/* ------------------- device --------------------- */
509
510static int audio_enable_mbadrc(struct audio_copp *audio_copp, int enable)
511{
512 if (audio_copp->mbadrc_enable == enable &&
513 !audio_copp->mbadrc_needs_commit)
514 return 0;
515
516 audio_copp->mbadrc_enable = enable;
517 if (is_audpp_enable()) {
518 audpp_dsp_set_mbadrc(COMMON_OBJ_ID, enable,
519 &audio_copp->mbadrc);
520 audio_copp->mbadrc_needs_commit = 0;
521 }
522
523 return 0;
524}
525
526static int audio_enable_eq(struct audio_copp *audio_copp, int enable)
527{
528 if (audio_copp->eq_enable == enable &&
529 !audio_copp->eq_needs_commit)
530 return 0;
531
532 audio_copp->eq_enable = enable;
533
534 if (is_audpp_enable()) {
535 audpp_dsp_set_eq(COMMON_OBJ_ID, enable, &audio_copp->eq);
536 audio_copp->eq_needs_commit = 0;
537 }
538 return 0;
539}
540
541static int audio_enable_rx_iir(struct audio_copp *audio_copp, int enable)
542{
543 if (audio_copp->rx_iir_enable == enable &&
544 !audio_copp->rx_iir_needs_commit)
545 return 0;
546
547 audio_copp->rx_iir_enable = enable;
548
549 if (is_audpp_enable()) {
550 audpp_dsp_set_rx_iir(COMMON_OBJ_ID, enable, &audio_copp->iir);
551 audio_copp->rx_iir_needs_commit = 0;
552 }
553 return 0;
554}
555
Sidipotu Ashok3144aa22012-03-16 10:55:24 +0530556static int audio_enable_srs_trumedia(struct audio_copp *audio_copp, int enable)
557{
558
559 if (!audio_copp->srs_needs_commit)
560 return 0;
561
562 audio_copp->srs_enable = enable;
563
564 MM_DBG("Enable SRS flags 0x%x enable %d\n",
565 audio_copp->srs_feature_mask, enable);
566 if (is_audpp_enable()) {
567 MM_DBG("Updating audpp for srs\n");
568 if (audio_copp->srs_feature_mask & SRS_MASK_W)
569 audpp_dsp_set_rx_srs_trumedia_w(&audio_copp->w);
570 if (audio_copp->srs_feature_mask & SRS_MASK_C)
571 audpp_dsp_set_rx_srs_trumedia_c(&audio_copp->c);
572 if (audio_copp->srs_feature_mask & SRS_MASK_HP)
573 audpp_dsp_set_rx_srs_trumedia_h(&audio_copp->h);
574 if (audio_copp->srs_feature_mask & SRS_MASK_P)
575 audpp_dsp_set_rx_srs_trumedia_p(&audio_copp->p);
576 if (audio_copp->srs_feature_mask & SRS_MASK_HL)
577 audpp_dsp_set_rx_srs_trumedia_l(&audio_copp->l);
578 if (audio_copp->srs_feature_mask & SRS_MASK_G)
579 audpp_dsp_set_rx_srs_trumedia_g(&audio_copp->g);
580
Sriranjan Srikantam87a6c292013-01-25 16:39:58 +0530581 audio_copp->srs_current_feature_mask =
582 audio_copp->srs_feature_mask;
Sidipotu Ashok3144aa22012-03-16 10:55:24 +0530583 audio_copp->srs_needs_commit = 0;
584 audio_copp->srs_feature_mask = 0;
585 }
586 return 0;
587}
588
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700589static int audio_enable_vol_pan(struct audio_copp *audio_copp)
590{
591 if (is_audpp_enable())
592 audpp_dsp_set_vol_pan(COMMON_OBJ_ID, &audio_copp->vol_pan);
593 return 0;
594}
595
596static int audio_enable_qconcert_plus(struct audio_copp *audio_copp, int enable)
597{
598 if (audio_copp->qconcert_plus_enable == enable &&
599 !audio_copp->qconcert_plus_needs_commit)
600 return 0;
601
602 audio_copp->qconcert_plus_enable = enable;
603
604 if (is_audpp_enable()) {
605 audpp_dsp_set_qconcert_plus(COMMON_OBJ_ID, enable,
606 &audio_copp->qconcert_plus);
607 audio_copp->qconcert_plus_needs_commit = 0;
608 }
609 return 0;
610}
611
612static void audio_flush(struct audio *audio)
613{
614 audio->out[0].used = 0;
615 audio->out[1].used = 0;
616 audio->out_head = 0;
617 audio->out_tail = 0;
618 audio->stopped = 0;
619}
620
621static long audio_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
622{
623 struct audio *audio = file->private_data;
624 int rc = -EINVAL;
625 unsigned long flags = 0;
626
627 if (cmd == AUDIO_GET_STATS) {
628 struct msm_audio_stats stats;
629 stats.byte_count = atomic_read(&audio->out_bytes);
630 if (copy_to_user((void*) arg, &stats, sizeof(stats)))
631 return -EFAULT;
632 return 0;
633 }
634
635 switch (cmd) {
636 case AUDIO_SET_VOLUME:
637 spin_lock_irqsave(&audio->dsp_lock, flags);
638 audio->vol_pan.volume = arg;
639 if (audio->running)
640 audpp_dsp_set_vol_pan(5, &audio->vol_pan);
641 spin_unlock_irqrestore(&audio->dsp_lock, flags);
642 return 0;
643
644 case AUDIO_SET_PAN:
645 spin_lock_irqsave(&audio->dsp_lock, flags);
646 audio->vol_pan.pan = arg;
647 if (audio->running)
648 audpp_dsp_set_vol_pan(5, &audio->vol_pan);
649 spin_unlock_irqrestore(&audio->dsp_lock, flags);
650 return 0;
651 }
652
653 LOG(EV_IOCTL, cmd);
654 mutex_lock(&audio->lock);
655 switch (cmd) {
656 case AUDIO_START:
657 rc = audio_enable(audio);
658 break;
659 case AUDIO_STOP:
660 rc = audio_disable(audio);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700661 break;
662 case AUDIO_FLUSH:
663 if (audio->stopped) {
664 /* Make sure we're stopped and we wake any threads
665 * that might be blocked holding the write_lock.
666 * While audio->stopped write threads will always
667 * exit immediately.
668 */
669 wake_up(&audio->wait);
670 mutex_lock(&audio->write_lock);
671 audio_flush(audio);
672 mutex_unlock(&audio->write_lock);
673 }
Phani Kumar Alladaee940eb2012-05-10 11:13:04 +0530674 break;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700675 case AUDIO_SET_CONFIG: {
676 struct msm_audio_config config;
677 if (copy_from_user(&config, (void*) arg, sizeof(config))) {
678 rc = -EFAULT;
679 break;
680 }
681 if (config.channel_count == 1) {
682 config.channel_count = AUDPP_CMD_PCM_INTF_MONO_V;
683 } else if (config.channel_count == 2) {
684 config.channel_count= AUDPP_CMD_PCM_INTF_STEREO_V;
685 } else {
686 rc = -EINVAL;
687 break;
688 }
689 audio->out_sample_rate = config.sample_rate;
690 audio->out_channel_mode = config.channel_count;
691 rc = 0;
692 break;
693 }
694 case AUDIO_GET_CONFIG: {
695 struct msm_audio_config config;
696 config.buffer_size = BUFSZ;
697 config.buffer_count = 2;
698 config.sample_rate = audio->out_sample_rate;
699 if (audio->out_channel_mode == AUDPP_CMD_PCM_INTF_MONO_V) {
700 config.channel_count = 1;
701 } else {
702 config.channel_count = 2;
703 }
704 config.unused[0] = 0;
705 config.unused[1] = 0;
706 config.unused[2] = 0;
707 if (copy_to_user((void*) arg, &config, sizeof(config))) {
708 rc = -EFAULT;
709 } else {
710 rc = 0;
711 }
712 break;
713 }
714 default:
715 rc = -EINVAL;
716 }
717 mutex_unlock(&audio->lock);
718 return rc;
719}
720
721/* Only useful in tunnel-mode */
Steve Mucklef132c6c2012-06-06 18:30:57 -0700722static int audio_fsync(struct file *file, loff_t a, loff_t b, int datasync)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700723{
724 struct audio *audio = file->private_data;
725 int rc = 0;
726
727 if (!audio->running)
728 return -EINVAL;
729
730 mutex_lock(&audio->write_lock);
731
732 rc = wait_event_interruptible(audio->wait,
733 (!audio->out[0].used &&
734 !audio->out[1].used));
735
736 if (rc < 0)
737 goto done;
738
739 /* pcm dmamiss message is sent continously when
740 * decoder is starved so no race condition concern
741 */
742
743 audio->teos = 0;
744
745 rc = wait_event_interruptible(audio->wait,
746 audio->teos);
747
748done:
749 mutex_unlock(&audio->write_lock);
750 return rc;
751}
752
753static ssize_t audio_read(struct file *file, char __user *buf, size_t count, loff_t *pos)
754{
755 return -EINVAL;
756}
757
758static inline int rt_policy(int policy)
759{
760 if (unlikely(policy == SCHED_FIFO) || unlikely(policy == SCHED_RR))
761 return 1;
762 return 0;
763}
764
765static inline int task_has_rt_policy(struct task_struct *p)
766{
767 return rt_policy(p->policy);
768}
769
770static ssize_t audio_write(struct file *file, const char __user *buf,
771 size_t count, loff_t *pos)
772{
773 struct sched_param s = { .sched_priority = 1 };
774 struct audio *audio = file->private_data;
775 unsigned long flags;
776 const char __user *start = buf;
777 struct buffer *frame;
778 size_t xfer;
779 int old_prio = current->rt_priority;
780 int old_policy = current->policy;
781 int cap_nice = cap_raised(current_cap(), CAP_SYS_NICE);
782 int rc = 0;
783
784 LOG(EV_WRITE, count | (audio->running << 28) | (audio->stopped << 24));
785
786 /* just for this write, set us real-time */
787 if (!task_has_rt_policy(current)) {
788 struct cred *new = prepare_creds();
789 cap_raise(new->cap_effective, CAP_SYS_NICE);
790 commit_creds(new);
791 if ((sched_setscheduler(current, SCHED_RR, &s)) < 0)
792 MM_ERR("sched_setscheduler failed\n");
793 }
794
795 mutex_lock(&audio->write_lock);
796 while (count > 0) {
797 frame = audio->out + audio->out_head;
798
799 LOG(EV_WAIT_EVENT, 0);
800 rc = wait_event_interruptible(audio->wait,
801 (frame->used == 0) || (audio->stopped));
802 LOG(EV_WAIT_EVENT, 1);
803
804 if (rc < 0)
805 break;
806 if (audio->stopped) {
807 rc = -EBUSY;
808 break;
809 }
810 xfer = count > frame->size ? frame->size : count;
811 if (copy_from_user(frame->data, buf, xfer)) {
812 rc = -EFAULT;
813 break;
814 }
815 frame->used = xfer;
816 audio->out_head ^= 1;
817 count -= xfer;
818 buf += xfer;
819
820 spin_lock_irqsave(&audio->dsp_lock, flags);
821 LOG(EV_FILL_BUFFER, audio->out_head ^ 1);
822 frame = audio->out + audio->out_tail;
823 if (frame->used && audio->out_needed) {
824 audio_dsp_send_buffer(audio, audio->out_tail, frame->used);
825 audio->out_tail ^= 1;
826 audio->out_needed--;
827 }
828 spin_unlock_irqrestore(&audio->dsp_lock, flags);
829 }
830
831 mutex_unlock(&audio->write_lock);
832
833 /* restore scheduling policy and priority */
834 if (!rt_policy(old_policy)) {
835 struct sched_param v = { .sched_priority = old_prio };
836 if ((sched_setscheduler(current, old_policy, &v)) < 0)
837 MM_ERR("sched_setscheduler failed\n");
838 if (likely(!cap_nice)) {
839 struct cred *new = prepare_creds();
840 cap_lower(new->cap_effective, CAP_SYS_NICE);
841 commit_creds(new);
842 }
843 }
844
845 LOG(EV_RETURN,(buf > start) ? (buf - start) : rc);
846 if (buf > start)
847 return buf - start;
848 return rc;
849}
850
851static int audio_release(struct inode *inode, struct file *file)
852{
853 struct audio *audio = file->private_data;
854
855 LOG(EV_OPEN, 0);
856 mutex_lock(&audio->lock);
857 audio_disable(audio);
858 audio_flush(audio);
859 audio->opened = 0;
860 mutex_unlock(&audio->lock);
861 htc_pwrsink_set(PWRSINK_AUDIO, 0);
862 return 0;
863}
864
865struct audio the_audio;
866
867static int audio_open(struct inode *inode, struct file *file)
868{
869 struct audio *audio = &the_audio;
870 int rc;
871
872 mutex_lock(&audio->lock);
873
874 if (audio->opened) {
875 MM_ERR("busy\n");
876 rc = -EBUSY;
877 goto done;
878 }
879
880 if (!audio->data) {
881 audio->data = dma_alloc_coherent(NULL, DMASZ,
882 &audio->phys, GFP_KERNEL);
883 if (!audio->data) {
884 MM_ERR("could not allocate DMA buffers\n");
885 rc = -ENOMEM;
886 goto done;
887 }
888 }
889
890 rc = audmgr_open(&audio->audmgr);
891 if (rc)
892 goto done;
893
894 audio->out_buffer_size = BUFSZ;
Sidipotu Ashokbe85d1e2012-07-26 10:11:01 +0530895 audio->out_sample_rate = 48000;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700896 audio->out_channel_mode = AUDPP_CMD_PCM_INTF_STEREO_V;
897 audio->out_weight = 100;
898
899 audio->out[0].data = audio->data + 0;
900 audio->out[0].addr = audio->phys + 0;
901 audio->out[0].size = BUFSZ;
902
903 audio->out[1].data = audio->data + BUFSZ;
904 audio->out[1].addr = audio->phys + BUFSZ;
905 audio->out[1].size = BUFSZ;
906
907 audio->vol_pan.volume = 0x2000;
908 audio->vol_pan.pan = 0x0;
909
910 audio_flush(audio);
911
912 file->private_data = audio;
913 audio->opened = 1;
914 rc = 0;
915 LOG(EV_OPEN, 1);
916done:
917 mutex_unlock(&audio->lock);
918 return rc;
919}
920
921static long audpp_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
922{
923 struct audio_copp *audio_copp = file->private_data;
924 int rc = 0, enable;
925 uint16_t enable_mask;
926 int prev_state;
Sidipotu Ashok3144aa22012-03-16 10:55:24 +0530927 uint32_t to_set, size = 0;
928 void *tmpbuf, *srs_params = NULL;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700929
930 mutex_lock(&audio_copp->lock);
931 switch (cmd) {
932 case AUDIO_ENABLE_AUDPP:
933 if (copy_from_user(&enable_mask, (void *) arg,
934 sizeof(enable_mask))) {
935 rc = -EFAULT;
936 break;
937 }
938
939 enable = ((enable_mask & ADRC_ENABLE) ||
940 (enable_mask & MBADRC_ENABLE)) ? 1 : 0;
941 audio_enable_mbadrc(audio_copp, enable);
942 enable = (enable_mask & EQ_ENABLE) ? 1 : 0;
943 audio_enable_eq(audio_copp, enable);
944 enable = (enable_mask & IIR_ENABLE) ? 1 : 0;
945 audio_enable_rx_iir(audio_copp, enable);
946 enable = (enable_mask & QCONCERT_PLUS_ENABLE) ? 1 : 0;
947 audio_enable_qconcert_plus(audio_copp, enable);
Sidipotu Ashok3144aa22012-03-16 10:55:24 +0530948 enable = (enable_mask & SRS_ENABLE) ? 1 : 0;
949 audio_enable_srs_trumedia(audio_copp, enable);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700950 break;
951
952 case AUDIO_SET_MBADRC: {
953 uint32_t mbadrc_coeff_buf;
954 prev_state = audio_copp->mbadrc_enable;
955 audio_copp->mbadrc_enable = 0;
956 if (copy_from_user(&audio_copp->mbadrc.num_bands, (void *) arg,
957 sizeof(audio_copp->mbadrc) -
958 (AUDPP_CMD_CFG_OBJECT_PARAMS_COMMON_LEN + 2)))
959 rc = -EFAULT;
960 else if (audio_copp->mbadrc.ext_buf_size) {
961 mbadrc_coeff_buf = (uint32_t) ((char *) arg +
962 sizeof(audio_copp->mbadrc) -
963 (AUDPP_CMD_CFG_OBJECT_PARAMS_COMMON_LEN + 2));
964 if ((copy_from_user(audio_copp->mbadrc_data,
965 (void *) mbadrc_coeff_buf,
966 AUDPP_MBADRC_EXTERNAL_BUF_SIZE * 2))) {
967 rc = -EFAULT;
968 break;
969 }
970 audio_copp->mbadrc.ext_buf_lsw =
971 audio_copp->mbadrc_phys & 0xFFFF;
972 audio_copp->mbadrc.ext_buf_msw =
973 ((audio_copp->mbadrc_phys & 0xFFFF0000) >> 16);
974 }
975 audio_copp->mbadrc_enable = prev_state;
976 if (!rc)
977 audio_copp->mbadrc_needs_commit = 1;
978 break;
979 }
980
981 case AUDIO_SET_ADRC: {
982 struct audpp_cmd_cfg_object_params_adrc adrc;
983 prev_state = audio_copp->mbadrc_enable;
984 audio_copp->mbadrc_enable = 0;
985 if (copy_from_user(&adrc.compression_th, (void *) arg,
986 sizeof(adrc) - 2)) {
987 rc = -EFAULT;
988 audio_copp->mbadrc_enable = prev_state;
989 break;
990 }
991 audio_copp->mbadrc.num_bands = 1;
992 audio_copp->mbadrc.down_samp_level = 8;
993 audio_copp->mbadrc.adrc_delay = adrc.adrc_delay;
994 audio_copp->mbadrc.ext_buf_size = 0;
995 audio_copp->mbadrc.ext_partition = 0;
996 audio_copp->mbadrc.adrc_band[0].subband_enable = 1;
997 audio_copp->mbadrc.adrc_band[0].adrc_sub_mute = 0;
998 audio_copp->mbadrc.adrc_band[0].rms_time =
999 adrc.rms_time;
1000 audio_copp->mbadrc.adrc_band[0].compression_th =
1001 adrc.compression_th;
1002 audio_copp->mbadrc.adrc_band[0].compression_slope =
1003 adrc.compression_slope;
1004 audio_copp->mbadrc.adrc_band[0].attack_const_lsw =
1005 adrc.attack_const_lsw;
1006 audio_copp->mbadrc.adrc_band[0].attack_const_msw =
1007 adrc.attack_const_msw;
1008 audio_copp->mbadrc.adrc_band[0].release_const_lsw =
1009 adrc.release_const_lsw;
1010 audio_copp->mbadrc.adrc_band[0].release_const_msw =
1011 adrc.release_const_msw;
1012 audio_copp->mbadrc.adrc_band[0].makeup_gain = 0x2000;
1013 audio_copp->mbadrc_enable = prev_state;
1014 audio_copp->mbadrc_needs_commit = 1;
1015 break;
1016 }
1017
1018 case AUDIO_SET_EQ:
1019 prev_state = audio_copp->eq_enable;
1020 audio_copp->eq_enable = 0;
1021 if (copy_from_user(&audio_copp->eq.num_bands, (void *) arg,
1022 sizeof(audio_copp->eq) -
1023 (AUDPP_CMD_CFG_OBJECT_PARAMS_COMMON_LEN + 2)))
1024 rc = -EFAULT;
1025 audio_copp->eq_enable = prev_state;
1026 audio_copp->eq_needs_commit = 1;
1027 break;
1028
1029 case AUDIO_SET_RX_IIR:
1030 prev_state = audio_copp->rx_iir_enable;
1031 audio_copp->rx_iir_enable = 0;
1032 if (copy_from_user(&audio_copp->iir.num_bands, (void *) arg,
1033 sizeof(audio_copp->iir) -
1034 (AUDPP_CMD_CFG_OBJECT_PARAMS_COMMON_LEN + 2)))
1035 rc = -EFAULT;
1036 audio_copp->rx_iir_enable = prev_state;
1037 audio_copp->rx_iir_needs_commit = 1;
1038 break;
1039
1040 case AUDIO_SET_VOLUME:
1041 audio_copp->vol_pan.volume = arg;
1042 audio_enable_vol_pan(audio_copp);
1043 break;
1044
1045 case AUDIO_SET_PAN:
1046 audio_copp->vol_pan.pan = arg;
1047 audio_enable_vol_pan(audio_copp);
1048 break;
1049
1050 case AUDIO_SET_QCONCERT_PLUS:
1051 prev_state = audio_copp->qconcert_plus_enable;
1052 audio_copp->qconcert_plus_enable = 0;
1053 if (copy_from_user(&audio_copp->qconcert_plus.op_mode,
1054 (void *) arg,
1055 sizeof(audio_copp->qconcert_plus) -
1056 (AUDPP_CMD_CFG_OBJECT_PARAMS_COMMON_LEN + 2)))
1057 rc = -EFAULT;
1058 audio_copp->qconcert_plus_enable = prev_state;
1059 audio_copp->qconcert_plus_needs_commit = 1;
1060 break;
1061
Sidipotu Ashok3144aa22012-03-16 10:55:24 +05301062 case AUDIO_SET_SRS_TRUMEDIA_PARAM: {
1063 prev_state = audio_copp->srs_enable;
1064 audio_copp->srs_enable = 0;
1065
1066 if (copy_from_user(&to_set, (void *)arg, sizeof(uint32_t))) {
1067 rc = -EFAULT;
1068 break;
1069 }
1070 switch (to_set) {
1071 case SRS_ID_GLOBAL:
1072 srs_params = (void *)audio_copp->g.v;
1073 size = sizeof(audio_copp->g.v);
1074 audio_copp->srs_feature_mask |= SRS_MASK_G;
1075 break;
1076 case SRS_ID_WOWHD:
1077 srs_params = (void *)audio_copp->w.v;
1078 size = sizeof(audio_copp->w.v);
1079 audio_copp->srs_feature_mask |= SRS_MASK_W;
1080 break;
1081 case SRS_ID_CSHP:
1082 srs_params = (void *)audio_copp->c.v;
1083 size = sizeof(audio_copp->c.v);
1084 audio_copp->srs_feature_mask |= SRS_MASK_C;
1085 break;
1086 case SRS_ID_HPF:
1087 srs_params = (void *)audio_copp->h.v;
1088 size = sizeof(audio_copp->h.v);
1089 audio_copp->srs_feature_mask |= SRS_MASK_HP;
1090 break;
1091 case SRS_ID_PEQ:
1092 srs_params = (void *)audio_copp->p.v;
1093 size = sizeof(audio_copp->p.v);
1094 audio_copp->srs_feature_mask |= SRS_MASK_P;
1095 break;
1096 case SRS_ID_HL:
1097 srs_params = (void *)audio_copp->l.v;
1098 size = sizeof(audio_copp->l.v);
1099 audio_copp->srs_feature_mask |= SRS_MASK_HL;
1100 break;
1101 default:
1102 MM_ERR("SRS TruMedia error: invalid ioctl\n");
1103 rc = -EINVAL;
1104 }
1105
1106 if (rc >= 0) {
1107 tmpbuf = kzalloc(sizeof(uint32_t) + size , GFP_KERNEL);
1108 if (!tmpbuf) {
1109 MM_ERR("SRS TruMedia error: no kernel mem\n");
1110 rc = -ENOMEM;
1111 } else {
1112 if (copy_from_user(tmpbuf, (void *)arg,
1113 sizeof(uint32_t) + size))
1114 rc = -EFAULT;
1115 memcpy(srs_params,
1116 &(((uint32_t *)tmpbuf)[1]), size);
1117 kfree(tmpbuf);
1118 }
1119 }
1120
1121 MM_DBG("Ioctl SRS flags=0x%x\n", audio_copp->srs_feature_mask);
1122 if (rc < 0)
1123 MM_ERR("SRS TruMedia error setting params failed.\n");
1124 else{
1125 audio_copp->srs_needs_commit = 1;
1126 audio_copp->srs_enable = prev_state;
1127 }
1128 break;
1129 }
1130
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001131 default:
1132 rc = -EINVAL;
1133 }
1134
1135 mutex_unlock(&audio_copp->lock);
1136 return rc;
1137}
1138
1139static int audpp_open(struct inode *inode, struct file *file)
1140{
1141 struct audio_copp *audio_copp = &the_audio_copp;
1142 int rc;
1143
1144 mutex_lock(&audio_copp->lock);
1145 if (audio_copp->opened) {
1146 mutex_unlock(&audio_copp->lock);
1147 return -EBUSY;
1148 }
1149
1150 audio_copp->opened = 1;
1151
1152 if (!audio_copp->status) {
1153 audio_copp->ecb.fn = audio_commit_pending_pp_params;
1154 audio_copp->ecb.private = audio_copp;
1155 rc = audpp_register_event_callback(&audio_copp->ecb);
1156 if (rc) {
1157 audio_copp->opened = 0;
1158 mutex_unlock(&audio_copp->lock);
1159 return rc;
1160 }
1161 audio_copp->mbadrc_data = dma_alloc_coherent(NULL,
1162 AUDPP_MBADRC_EXTERNAL_BUF_SIZE * 2,
1163 &audio_copp->mbadrc_phys, GFP_KERNEL);
1164 if (!audio_copp->mbadrc_data) {
1165 MM_ERR("could not allocate DMA buffers\n");
1166 audio_copp->opened = 0;
1167 audpp_unregister_event_callback(&audio_copp->ecb);
1168 mutex_unlock(&audio_copp->lock);
1169 return -ENOMEM;
1170 }
1171 audio_copp->vol_pan.volume = 0x2000;
1172 audio_copp->vol_pan.pan = 0x0;
1173 audio_copp->status = 1;
1174 }
1175
1176 file->private_data = audio_copp;
1177 mutex_unlock(&audio_copp->lock);
1178
1179 return 0;
1180}
1181
1182static int audpp_release(struct inode *inode, struct file *file)
1183{
1184 struct audio_copp *audio_copp = &the_audio_copp;
1185
1186 audio_copp->opened = 0;
1187
1188 return 0;
1189}
1190
1191static struct file_operations audio_fops = {
1192 .owner = THIS_MODULE,
1193 .open = audio_open,
1194 .release = audio_release,
1195 .read = audio_read,
1196 .write = audio_write,
1197 .unlocked_ioctl = audio_ioctl,
1198 .fsync = audio_fsync,
1199};
1200
1201static struct file_operations audpp_fops = {
1202 .owner = THIS_MODULE,
1203 .open = audpp_open,
1204 .release = audpp_release,
1205 .unlocked_ioctl = audpp_ioctl,
1206};
1207
1208struct miscdevice audio_misc = {
1209 .minor = MISC_DYNAMIC_MINOR,
1210 .name = "msm_pcm_out",
1211 .fops = &audio_fops,
1212};
1213
1214struct miscdevice audpp_misc = {
1215 .minor = MISC_DYNAMIC_MINOR,
1216 .name = "msm_pcm_ctl",
1217 .fops = &audpp_fops,
1218};
1219
1220static int __init audio_init(void)
1221{
1222 mutex_init(&the_audio.lock);
1223 mutex_init(&the_audio.write_lock);
1224 mutex_init(&the_audio_copp.lock);
1225 spin_lock_init(&the_audio.dsp_lock);
1226 init_waitqueue_head(&the_audio.wait);
1227 wake_lock_init(&the_audio.wakelock, WAKE_LOCK_SUSPEND, "audio_pcm");
Stephen Boyd2fcabf92012-05-30 10:41:11 -07001228 pm_qos_add_request(&the_audio.pm_qos_req, PM_QOS_CPU_DMA_LATENCY,
1229 PM_QOS_DEFAULT_VALUE);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001230 return (misc_register(&audio_misc) || misc_register(&audpp_misc));
1231}
1232
1233device_initcall(audio_init);