blob: b2829c3032e59832a5593f325d0c22190143c69d [file] [log] [blame]
Deepa Madiregama55cbf782011-09-10 05:44:39 +05301/* Copyright (C) 2008 Google, Inc.
2 * Copyright (C) 2008 HTC Corporation
Chaithanya Krishna Bacharajubbc2e702012-02-16 14:46:55 +05303 * Copyright (c) 2009-2012, Code Aurora Forum. 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
39#define AUDIO_EVENT_NUM 10
40
41#define __CONTAINS(r, v, l) ({ \
42 typeof(r) __r = r; \
43 typeof(v) __v = v; \
44 typeof(v) __e = __v + l; \
45 int res = ((__v >= __r->vaddr) && \
46 (__e <= __r->vaddr + __r->len)); \
47 res; \
48})
49
50#define CONTAINS(r1, r2) ({ \
51 typeof(r2) __r2 = r2; \
52 __CONTAINS(r1, __r2->vaddr, __r2->len); \
53})
54
55#define IN_RANGE(r, v) ({ \
56 typeof(r) __r = r; \
57 typeof(v) __vv = v; \
58 int res = ((__vv >= __r->vaddr) && \
59 (__vv < (__r->vaddr + __r->len))); \
60 res; \
61})
62
63#define OVERLAPS(r1, r2) ({ \
64 typeof(r1) __r1 = r1; \
65 typeof(r2) __r2 = r2; \
66 typeof(__r2->vaddr) __v = __r2->vaddr; \
67 typeof(__v) __e = __v + __r2->len - 1; \
68 int res = (IN_RANGE(__r1, __v) || IN_RANGE(__r1, __e)); \
69 res; \
70})
71
72struct timestamp {
73 unsigned long lowpart;
74 unsigned long highpart;
75} __packed;
76
77struct meta_out_dsp {
78 u32 offset_to_frame;
79 u32 frame_size;
80 u32 encoded_pcm_samples;
81 u32 msw_ts;
82 u32 lsw_ts;
83 u32 nflags;
84} __packed;
85
86struct dec_meta_in {
87 unsigned char reserved[18];
88 unsigned short offset;
89 struct timestamp ntimestamp;
90 unsigned int nflags;
91} __packed;
92
93struct dec_meta_out {
94 unsigned int reserved[7];
95 unsigned int num_of_frames;
96 struct meta_out_dsp meta_out_dsp[];
97} __packed;
98
99/* General meta field to store meta info
100locally */
101union meta_data {
102 struct dec_meta_out meta_out;
103 struct dec_meta_in meta_in;
104} __packed;
105
106#define PCM_BUF_COUNT (2)
107/* Buffer with meta */
108#define PCM_BUFSZ_MIN ((4*1024) + sizeof(struct dec_meta_out))
109
110/* FRAME_NUM must be a power of two */
111#define FRAME_NUM (2)
112#define FRAME_SIZE ((4*1536) + sizeof(struct dec_meta_in))
113
Chaithanya Krishna Bacharajubbc2e702012-02-16 14:46:55 +0530114struct audio_aio_ion_region {
Deepa Madiregama55cbf782011-09-10 05:44:39 +0530115 struct list_head list;
Chaithanya Krishna Bacharajubbc2e702012-02-16 14:46:55 +0530116 struct ion_handle *handle;
Deepa Madiregama55cbf782011-09-10 05:44:39 +0530117 int fd;
118 void *vaddr;
119 unsigned long paddr;
120 unsigned long kvaddr;
121 unsigned long len;
122 unsigned ref_cnt;
123};
124
125struct audio_aio_event {
126 struct list_head list;
127 int event_type;
128 union msm_audio_event_payload payload;
129};
130
131struct audio_aio_buffer_node {
132 struct list_head list;
133 struct msm_audio_aio_buf buf;
134 unsigned long paddr;
135 unsigned long token;
136 void *kvaddr;
137 union meta_data meta_info;
138};
139
140struct q6audio_aio;
141struct audio_aio_drv_operations {
142 void (*out_flush) (struct q6audio_aio *);
143 void (*in_flush) (struct q6audio_aio *);
144};
145
146struct q6audio_aio {
147 atomic_t in_bytes;
148 atomic_t in_samples;
149
150 struct msm_audio_stream_config str_cfg;
151 struct msm_audio_buf_cfg buf_cfg;
152 struct msm_audio_config pcm_cfg;
153 void *codec_cfg;
154
155 struct audio_client *ac;
156
157 struct mutex lock;
158 struct mutex read_lock;
159 struct mutex write_lock;
160 struct mutex get_event_lock;
161 wait_queue_head_t cmd_wait;
162 wait_queue_head_t write_wait;
163 wait_queue_head_t event_wait;
164 spinlock_t dsp_lock;
165 spinlock_t event_queue_lock;
166
167#ifdef CONFIG_DEBUG_FS
168 struct dentry *dentry;
169#endif
170 struct list_head out_queue; /* queue to retain output buffers */
171 struct list_head in_queue; /* queue to retain input buffers */
172 struct list_head free_event_queue;
173 struct list_head event_queue;
Chaithanya Krishna Bacharajubbc2e702012-02-16 14:46:55 +0530174 struct list_head ion_region_queue; /* protected by lock */
Deepa Madiregamaa4795072012-06-15 22:35:52 +0530175 struct ion_client *client;
Deepa Madiregama55cbf782011-09-10 05:44:39 +0530176 struct audio_aio_drv_operations drv_ops;
177 union msm_audio_event_payload eos_write_payload;
178
179 uint32_t drv_status;
180 int event_abort;
181 int eos_rsp;
182 int eos_flag;
183 int opened;
184 int enabled;
185 int stopped;
186 int feedback;
187 int rflush; /* Read flush */
188 int wflush; /* Write flush */
189 long (*codec_ioctl)(struct file *, unsigned int, unsigned long);
190};
191
Harmandeep Singhc35fa07d2012-05-31 07:08:59 -0700192void audio_aio_async_write_ack(struct q6audio_aio *audio, uint32_t token,
193 uint32_t *payload);
194
195void audio_aio_async_read_ack(struct q6audio_aio *audio, uint32_t token,
196 uint32_t *payload);
197
Harmandeep Singheaf59b42012-06-05 21:46:02 -0700198int insert_eos_buf(struct q6audio_aio *audio,
199 struct audio_aio_buffer_node *buf_node);
200
201void extract_meta_out_info(struct q6audio_aio *audio,
202 struct audio_aio_buffer_node *buf_node, int dir);
203
Deepa Madiregama55cbf782011-09-10 05:44:39 +0530204int audio_aio_open(struct q6audio_aio *audio, struct file *file);
205int audio_aio_enable(struct q6audio_aio *audio);
206void audio_aio_post_event(struct q6audio_aio *audio, int type,
207 union msm_audio_event_payload payload);
208int audio_aio_release(struct inode *inode, struct file *file);
209long audio_aio_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
Steve Mucklef132c6c2012-06-06 18:30:57 -0700210int audio_aio_fsync(struct file *file, loff_t start, loff_t end, int datasync);
Deepa Madiregama55cbf782011-09-10 05:44:39 +0530211void audio_aio_async_out_flush(struct q6audio_aio *audio);
212void audio_aio_async_in_flush(struct q6audio_aio *audio);
213#ifdef CONFIG_DEBUG_FS
214ssize_t audio_aio_debug_open(struct inode *inode, struct file *file);
Harmandeep Singheaf59b42012-06-05 21:46:02 -0700215ssize_t audio_aio_debug_read(struct file *file, char __user *buf,
Deepa Madiregama55cbf782011-09-10 05:44:39 +0530216 size_t count, loff_t *ppos);
217#endif