1 /* arch/arm/mach-msm/qdsp6/mp3.c
3 * Copyright (C) 2009 Google, Inc.
4 * Copyright (C) 2009 HTC Corporation
6 * This software is licensed under the terms of the GNU General Public
7 * License version 2, as published by the Free Software Foundation, and
8 * may be copied, distributed, and modified under those terms.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
18 #include <linux/module.h>
19 #include <linux/miscdevice.h>
20 #include <linux/mutex.h>
21 #include <linux/sched.h>
22 #include <linux/wait.h>
23 #include <linux/uaccess.h>
25 #include <linux/msm_audio.h>
27 #include <mach/msm_qdsp6_audio.h>
28 #include "dal_audio.h"
31 #define DMASZ (BUFSZ * 2)
35 struct audio_client
*ac
;
37 uint32_t channel_count
;
40 static long mp3_ioctl(struct file
*file
, unsigned int cmd
, unsigned long arg
)
42 struct mp3
*mp3
= file
->private_data
;
43 struct cad_audio_eq_cfg eq_cfg
;
46 if (cmd
== AUDIO_GET_STATS
) {
47 struct msm_audio_stats stats
;
48 memset(&stats
, 0, sizeof(stats
));
49 if (copy_to_user((void*) arg
, &stats
, sizeof(stats
)))
54 mutex_lock(&mp3
->lock
);
56 case AUDIO_SET_VOLUME
: {
58 if (copy_from_user(&vol
, (void*) arg
, sizeof(vol
))) {
62 rc
= q6audio_set_stream_volume(mp3
->ac
, vol
);
66 if (copy_from_user(&eq_cfg
, (void *)arg
, sizeof(struct cad_audio_eq_cfg
))) {
70 rc
= q6audio_set_stream_eq(mp3
->ac
, &eq_cfg
);
77 } else if (copy_from_user(&acdb_id
, (void*) arg
, sizeof(acdb_id
))) {
78 pr_info("pcm_out: copy acdb_id from user failed\n");
85 mp3
->ac
= q6audio_open_mp3(BUFSZ
,
86 mp3
->sample_rate
, mp3
->channel_count
, acdb_id
);
96 case AUDIO_SET_CONFIG
: {
97 struct msm_audio_config config
;
102 if (copy_from_user(&config
, (void*) arg
, sizeof(config
))) {
106 if (config
.channel_count
< 1 || config
.channel_count
> 2) {
110 mp3
->sample_rate
= config
.sample_rate
;
111 mp3
->channel_count
= config
.channel_count
;
114 case AUDIO_GET_CONFIG
: {
115 struct msm_audio_config config
;
116 config
.buffer_size
= BUFSZ
;
117 config
.buffer_count
= 2;
118 config
.sample_rate
= mp3
->sample_rate
;
119 config
.channel_count
= mp3
->channel_count
;
120 config
.unused
[0] = 0;
121 config
.unused
[1] = 0;
122 config
.unused
[2] = 0;
123 if (copy_to_user((void*) arg
, &config
, sizeof(config
))) {
131 mutex_unlock(&mp3
->lock
);
135 static int mp3_open(struct inode
*inode
, struct file
*file
)
140 mp3
= kzalloc(sizeof(struct mp3
), GFP_KERNEL
);
145 mutex_init(&mp3
->lock
);
146 mp3
->channel_count
= 2;
147 mp3
->sample_rate
= 44100;
149 file
->private_data
= mp3
;
153 static ssize_t
mp3_write(struct file
*file
, const char __user
*buf
,
154 size_t count
, loff_t
*pos
)
156 struct mp3
*mp3
= file
->private_data
;
157 struct audio_client
*ac
;
158 struct audio_buffer
*ab
;
159 const char __user
*start
= buf
;
163 mp3_ioctl(file
, AUDIO_START
, 0);
170 ab
= ac
->buf
+ ac
->cpu_buf
;
173 wait_event(ac
->wait
, (ab
->used
== 0));
179 if (copy_from_user(ab
->data
, buf
, xfer
))
186 q6audio_write(ac
, ab
);
193 static int mp3_fsync(struct file
*f
, struct dentry
*dentry
, int datasync
)
195 struct mp3
*mp3
= f
->private_data
;
197 return q6audio_async(mp3
->ac
);
201 static int mp3_release(struct inode
*inode
, struct file
*file
)
203 struct mp3
*mp3
= file
->private_data
;
205 q6audio_mp3_close(mp3
->ac
);
210 static struct file_operations mp3_fops
= {
211 .owner
= THIS_MODULE
,
215 .release
= mp3_release
,
216 .unlocked_ioctl
= mp3_ioctl
,
219 struct miscdevice mp3_misc
= {
220 .minor
= MISC_DYNAMIC_MINOR
,
225 static int __init
mp3_init(void) {
226 return misc_register(&mp3_misc
);
229 device_initcall(mp3_init
);