blob: 0efcd647f9d6c819703a6f341638b0859b602f23 [file] [log] [blame]
Deepa Madiregama55cbf782011-09-10 05:44:39 +05301/* Copyright (C) 2008 Google, Inc.
2 * Copyright (C) 2008 HTC Corporation
Deepa Madiregama75d0b932012-11-28 14:57:43 +05303 * Copyright (c) 2009-2013, The Linux Foundation. All rights reserved.
Deepa Madiregama55cbf782011-09-10 05:44:39 +05304 *
5 * This software is licensed under the terms of the GNU General Public
6 * License version 2, as published by the Free Software Foundation, and
7 * may be copied, distributed, and modified under those terms.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 */
15
16#include <linux/fs.h>
17#include <linux/module.h>
18#include <linux/miscdevice.h>
19#include <linux/mutex.h>
20#include <linux/sched.h>
21#include <linux/uaccess.h>
22#include <linux/wait.h>
23#include <linux/msm_audio.h>
24#include <linux/debugfs.h>
25#include <linux/list.h>
Deepa Madiregama55cbf782011-09-10 05:44:39 +053026#include <linux/slab.h>
Mitchel Humpherys1da6ebe2012-09-06 10:15:56 -070027#include <linux/msm_ion.h>
Deepa Madiregama55cbf782011-09-10 05:44:39 +053028#include <asm/ioctls.h>
29#include <asm/atomic.h>
Harmandeep Singhc35fa07d2012-05-31 07:08:59 -070030#include "q6audio_common.h"
Deepa Madiregama55cbf782011-09-10 05:44:39 +053031
Deepa Madiregama55cbf782011-09-10 05:44:39 +053032#define TUNNEL_MODE 0x0000
33#define NON_TUNNEL_MODE 0x0001
34
35#define ADRV_STATUS_AIO_INTF 0x00000001 /* AIO interface */
36#define ADRV_STATUS_FSYNC 0x00000008
37#define ADRV_STATUS_PAUSE 0x00000010
38#define AUDIO_DEC_EOS_SET 0x00000001
Swaminathan Sathappan08508ac2012-10-11 19:51:25 -070039#define AUDIO_DEC_EOF_SET 0x00000010
Deepa Madiregama55cbf782011-09-10 05:44:39 +053040#define AUDIO_EVENT_NUM 10
41
42#define __CONTAINS(r, v, l) ({ \
43 typeof(r) __r = r; \
44 typeof(v) __v = v; \
45 typeof(v) __e = __v + l; \
46 int res = ((__v >= __r->vaddr) && \
47 (__e <= __r->vaddr + __r->len)); \
48 res; \
49})
50
51#define CONTAINS(r1, r2) ({ \
52 typeof(r2) __r2 = r2; \
53 __CONTAINS(r1, __r2->vaddr, __r2->len); \
54})
55
56#define IN_RANGE(r, v) ({ \
57 typeof(r) __r = r; \
58 typeof(v) __vv = v; \
59 int res = ((__vv >= __r->vaddr) && \
60 (__vv < (__r->vaddr + __r->len))); \
61 res; \
62})
63
64#define OVERLAPS(r1, r2) ({ \
65 typeof(r1) __r1 = r1; \
66 typeof(r2) __r2 = r2; \
67 typeof(__r2->vaddr) __v = __r2->vaddr; \
68 typeof(__v) __e = __v + __r2->len - 1; \
69 int res = (IN_RANGE(__r1, __v) || IN_RANGE(__r1, __e)); \
70 res; \
71})
72
73struct timestamp {
74 unsigned long lowpart;
75 unsigned long highpart;
76} __packed;
77
78struct meta_out_dsp {
79 u32 offset_to_frame;
80 u32 frame_size;
81 u32 encoded_pcm_samples;
82 u32 msw_ts;
83 u32 lsw_ts;
84 u32 nflags;
85} __packed;
86
87struct dec_meta_in {
88 unsigned char reserved[18];
89 unsigned short offset;
90 struct timestamp ntimestamp;
91 unsigned int nflags;
92} __packed;
93
94struct dec_meta_out {
95 unsigned int reserved[7];
96 unsigned int num_of_frames;
97 struct meta_out_dsp meta_out_dsp[];
98} __packed;
99
100/* General meta field to store meta info
101locally */
102union meta_data {
103 struct dec_meta_out meta_out;
104 struct dec_meta_in meta_in;
105} __packed;
106
107#define PCM_BUF_COUNT (2)
108/* Buffer with meta */
109#define PCM_BUFSZ_MIN ((4*1024) + sizeof(struct dec_meta_out))
110
111/* FRAME_NUM must be a power of two */
112#define FRAME_NUM (2)
113#define FRAME_SIZE ((4*1536) + sizeof(struct dec_meta_in))
114
Chaithanya Krishna Bacharajubbc2e702012-02-16 14:46:55 +0530115struct audio_aio_ion_region {
Deepa Madiregama55cbf782011-09-10 05:44:39 +0530116 struct list_head list;
Chaithanya Krishna Bacharajubbc2e702012-02-16 14:46:55 +0530117 struct ion_handle *handle;
Deepa Madiregama55cbf782011-09-10 05:44:39 +0530118 int fd;
119 void *vaddr;
120 unsigned long paddr;
121 unsigned long kvaddr;
122 unsigned long len;
123 unsigned ref_cnt;
124};
125
126struct audio_aio_event {
127 struct list_head list;
128 int event_type;
129 union msm_audio_event_payload payload;
130};
131
132struct audio_aio_buffer_node {
133 struct list_head list;
134 struct msm_audio_aio_buf buf;
135 unsigned long paddr;
136 unsigned long token;
137 void *kvaddr;
138 union meta_data meta_info;
139};
140
141struct q6audio_aio;
142struct audio_aio_drv_operations {
143 void (*out_flush) (struct q6audio_aio *);
144 void (*in_flush) (struct q6audio_aio *);
145};
146
147struct q6audio_aio {
148 atomic_t in_bytes;
149 atomic_t in_samples;
150
151 struct msm_audio_stream_config str_cfg;
152 struct msm_audio_buf_cfg buf_cfg;
153 struct msm_audio_config pcm_cfg;
154 void *codec_cfg;
155
156 struct audio_client *ac;
157
158 struct mutex lock;
159 struct mutex read_lock;
160 struct mutex write_lock;
161 struct mutex get_event_lock;
162 wait_queue_head_t cmd_wait;
163 wait_queue_head_t write_wait;
164 wait_queue_head_t event_wait;
165 spinlock_t dsp_lock;
166 spinlock_t event_queue_lock;
167
168#ifdef CONFIG_DEBUG_FS
169 struct dentry *dentry;
170#endif
171 struct list_head out_queue; /* queue to retain output buffers */
172 struct list_head in_queue; /* queue to retain input buffers */
173 struct list_head free_event_queue;
174 struct list_head event_queue;
Chaithanya Krishna Bacharajubbc2e702012-02-16 14:46:55 +0530175 struct list_head ion_region_queue; /* protected by lock */
Deepa Madiregamaa4795072012-06-15 22:35:52 +0530176 struct ion_client *client;
Deepa Madiregama55cbf782011-09-10 05:44:39 +0530177 struct audio_aio_drv_operations drv_ops;
178 union msm_audio_event_payload eos_write_payload;
Sidipotu Ashokbf84d4d2012-11-06 17:13:28 +0530179 uint32_t device_events;
180 uint16_t volume;
Deepa Madiregama55cbf782011-09-10 05:44:39 +0530181 uint32_t drv_status;
182 int event_abort;
183 int eos_rsp;
184 int eos_flag;
185 int opened;
186 int enabled;
187 int stopped;
188 int feedback;
189 int rflush; /* Read flush */
190 int wflush; /* Write flush */
191 long (*codec_ioctl)(struct file *, unsigned int, unsigned long);
192};
193
Harmandeep Singhc35fa07d2012-05-31 07:08:59 -0700194void audio_aio_async_write_ack(struct q6audio_aio *audio, uint32_t token,
195 uint32_t *payload);
196
197void audio_aio_async_read_ack(struct q6audio_aio *audio, uint32_t token,
198 uint32_t *payload);
199
Harmandeep Singheaf59b42012-06-05 21:46:02 -0700200int insert_eos_buf(struct q6audio_aio *audio,
201 struct audio_aio_buffer_node *buf_node);
202
203void extract_meta_out_info(struct q6audio_aio *audio,
204 struct audio_aio_buffer_node *buf_node, int dir);
205
Deepa Madiregama55cbf782011-09-10 05:44:39 +0530206int audio_aio_open(struct q6audio_aio *audio, struct file *file);
207int audio_aio_enable(struct q6audio_aio *audio);
208void audio_aio_post_event(struct q6audio_aio *audio, int type,
209 union msm_audio_event_payload payload);
210int audio_aio_release(struct inode *inode, struct file *file);
211long audio_aio_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
Steve Mucklef132c6c2012-06-06 18:30:57 -0700212int audio_aio_fsync(struct file *file, loff_t start, loff_t end, int datasync);
Deepa Madiregama55cbf782011-09-10 05:44:39 +0530213void audio_aio_async_out_flush(struct q6audio_aio *audio);
214void audio_aio_async_in_flush(struct q6audio_aio *audio);
Deepa Madiregama75d0b932012-11-28 14:57:43 +0530215void audio_aio_ioport_reset(struct q6audio_aio *audio);
Deepa Madiregamacb6ab2c2012-11-28 12:41:19 +0530216int enable_volume_ramp(struct q6audio_aio *audio);
Deepa Madiregama55cbf782011-09-10 05:44:39 +0530217#ifdef CONFIG_DEBUG_FS
218ssize_t audio_aio_debug_open(struct inode *inode, struct file *file);
Harmandeep Singheaf59b42012-06-05 21:46:02 -0700219ssize_t audio_aio_debug_read(struct file *file, char __user *buf,
Deepa Madiregama55cbf782011-09-10 05:44:39 +0530220 size_t count, loff_t *ppos);
221#endif