blob: 2e61e908707fe3af37c7be5a0bb2d858cf6258ad [file] [log] [blame]
Ben Romberger48fabc32012-01-06 17:39:39 -08001/* Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 */
13#include <linux/fs.h>
14#include <linux/module.h>
15#include <linux/miscdevice.h>
16#include <linux/mutex.h>
17#include <linux/uaccess.h>
18#include <linux/android_pmem.h>
19#include <linux/mm.h>
20#include <mach/qdsp6v2/audio_acdb.h>
21
22
Ben Romberger3652ed72011-08-09 16:21:49 -070023#define MAX_NETWORKS 12
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070024
Ben Rombergerb7603232011-11-23 17:16:27 -080025struct sidetone_atomic_cal {
26 atomic_t enable;
27 atomic_t gain;
28};
29
30
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070031struct acdb_data {
32 struct mutex acdb_mutex;
33
34 /* ANC Cal */
Ben Rombergerb7603232011-11-23 17:16:27 -080035 struct acdb_atomic_cal_block anc_cal;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070036
37 /* AudProc Cal */
Ben Rombergerb7603232011-11-23 17:16:27 -080038 atomic_t asm_topology;
39 atomic_t adm_topology[MAX_AUDPROC_TYPES];
40 struct acdb_atomic_cal_block audproc_cal[MAX_AUDPROC_TYPES];
41 struct acdb_atomic_cal_block audstrm_cal[MAX_AUDPROC_TYPES];
42 struct acdb_atomic_cal_block audvol_cal[MAX_AUDPROC_TYPES];
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070043
44 /* VocProc Cal */
Ben Rombergerb7603232011-11-23 17:16:27 -080045 atomic_t voice_rx_topology;
46 atomic_t voice_tx_topology;
47 struct acdb_atomic_cal_block vocproc_cal[MAX_NETWORKS];
48 struct acdb_atomic_cal_block vocstrm_cal[MAX_NETWORKS];
49 struct acdb_atomic_cal_block vocvol_cal[MAX_NETWORKS];
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070050 /* size of cal block tables above*/
Ben Rombergerb7603232011-11-23 17:16:27 -080051 atomic_t vocproc_cal_size;
52 atomic_t vocstrm_cal_size;
53 atomic_t vocvol_cal_size;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070054 /* Total size of cal data for all networks */
Ben Rombergerb7603232011-11-23 17:16:27 -080055 atomic_t vocproc_total_cal_size;
56 atomic_t vocstrm_total_cal_size;
57 atomic_t vocvol_total_cal_size;
58
59 /* AFE cal */
60 struct acdb_atomic_cal_block afe_cal[MAX_AUDPROC_TYPES];
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070061
62 /* Sidetone Cal */
Ben Rombergerb7603232011-11-23 17:16:27 -080063 struct sidetone_atomic_cal sidetone_cal;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070064
65 /* PMEM information */
Ben Rombergerb7603232011-11-23 17:16:27 -080066 atomic_t pmem_fd;
67 atomic64_t paddr;
68 atomic64_t kvaddr;
69 atomic64_t pmem_len;
70 struct file *file;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070071
72};
73
74static struct acdb_data acdb_data;
75static atomic_t usage_count;
76
77uint32_t get_voice_rx_topology(void)
78{
Ben Rombergerb7603232011-11-23 17:16:27 -080079 return atomic_read(&acdb_data.voice_rx_topology);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070080}
81
82void store_voice_rx_topology(uint32_t topology)
83{
Ben Rombergerb7603232011-11-23 17:16:27 -080084 atomic_set(&acdb_data.voice_rx_topology, topology);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070085}
86
87uint32_t get_voice_tx_topology(void)
88{
Ben Rombergerb7603232011-11-23 17:16:27 -080089 return atomic_read(&acdb_data.voice_tx_topology);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070090}
91
92void store_voice_tx_topology(uint32_t topology)
93{
Ben Rombergerb7603232011-11-23 17:16:27 -080094 atomic_set(&acdb_data.voice_tx_topology, topology);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070095}
96
Ben Rombergerc49b85d2011-07-15 18:55:34 -070097uint32_t get_adm_rx_topology(void)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070098{
Ben Rombergerb7603232011-11-23 17:16:27 -080099 return atomic_read(&acdb_data.adm_topology[RX_CAL]);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700100}
101
Ben Rombergerc49b85d2011-07-15 18:55:34 -0700102void store_adm_rx_topology(uint32_t topology)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700103{
Ben Rombergerb7603232011-11-23 17:16:27 -0800104 atomic_set(&acdb_data.adm_topology[RX_CAL], topology);
Ben Rombergerc49b85d2011-07-15 18:55:34 -0700105}
106
107uint32_t get_adm_tx_topology(void)
108{
Ben Rombergerb7603232011-11-23 17:16:27 -0800109 return atomic_read(&acdb_data.adm_topology[TX_CAL]);
Ben Rombergerc49b85d2011-07-15 18:55:34 -0700110}
111
112void store_adm_tx_topology(uint32_t topology)
113{
Ben Rombergerb7603232011-11-23 17:16:27 -0800114 atomic_set(&acdb_data.adm_topology[TX_CAL], topology);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700115}
116
117uint32_t get_asm_topology(void)
118{
Ben Rombergerb7603232011-11-23 17:16:27 -0800119 return atomic_read(&acdb_data.asm_topology);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700120}
121
122void store_asm_topology(uint32_t topology)
123{
Ben Rombergerb7603232011-11-23 17:16:27 -0800124 atomic_set(&acdb_data.asm_topology, topology);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700125}
126
127void get_all_voice_cal(struct acdb_cal_block *cal_block)
128{
Ben Rombergerb7603232011-11-23 17:16:27 -0800129 cal_block->cal_kvaddr =
130 atomic_read(&acdb_data.vocproc_cal[0].cal_kvaddr);
131 cal_block->cal_paddr =
132 atomic_read(&acdb_data.vocproc_cal[0].cal_paddr);
133 cal_block->cal_size =
134 atomic_read(&acdb_data.vocproc_total_cal_size) +
135 atomic_read(&acdb_data.vocstrm_total_cal_size) +
136 atomic_read(&acdb_data.vocvol_total_cal_size);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700137}
138
139void get_all_cvp_cal(struct acdb_cal_block *cal_block)
140{
Ben Rombergerb7603232011-11-23 17:16:27 -0800141 cal_block->cal_kvaddr =
142 atomic_read(&acdb_data.vocproc_cal[0].cal_kvaddr);
143 cal_block->cal_paddr =
144 atomic_read(&acdb_data.vocproc_cal[0].cal_paddr);
145 cal_block->cal_size =
146 atomic_read(&acdb_data.vocproc_total_cal_size) +
147 atomic_read(&acdb_data.vocvol_total_cal_size);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700148}
149
150void get_all_vocproc_cal(struct acdb_cal_block *cal_block)
151{
Ben Rombergerb7603232011-11-23 17:16:27 -0800152 cal_block->cal_kvaddr =
153 atomic_read(&acdb_data.vocproc_cal[0].cal_kvaddr);
154 cal_block->cal_paddr =
155 atomic_read(&acdb_data.vocproc_cal[0].cal_paddr);
156 cal_block->cal_size =
157 atomic_read(&acdb_data.vocproc_total_cal_size);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700158}
159
160void get_all_vocstrm_cal(struct acdb_cal_block *cal_block)
161{
Ben Rombergerb7603232011-11-23 17:16:27 -0800162 cal_block->cal_kvaddr =
163 atomic_read(&acdb_data.vocstrm_cal[0].cal_kvaddr);
164 cal_block->cal_paddr =
165 atomic_read(&acdb_data.vocstrm_cal[0].cal_paddr);
166 cal_block->cal_size =
167 atomic_read(&acdb_data.vocstrm_total_cal_size);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700168}
169
170void get_all_vocvol_cal(struct acdb_cal_block *cal_block)
171{
Ben Rombergerb7603232011-11-23 17:16:27 -0800172 cal_block->cal_kvaddr =
173 atomic_read(&acdb_data.vocvol_cal[0].cal_kvaddr);
174 cal_block->cal_paddr =
175 atomic_read(&acdb_data.vocvol_cal[0].cal_paddr);
176 cal_block->cal_size =
177 atomic_read(&acdb_data.vocvol_total_cal_size);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700178}
179
180void get_anc_cal(struct acdb_cal_block *cal_block)
181{
182 pr_debug("%s\n", __func__);
183
184 if (cal_block == NULL) {
185 pr_err("ACDB=> NULL pointer sent to %s\n", __func__);
186 goto done;
187 }
188
Ben Rombergerb7603232011-11-23 17:16:27 -0800189 cal_block->cal_kvaddr =
190 atomic_read(&acdb_data.anc_cal.cal_kvaddr);
191 cal_block->cal_paddr =
192 atomic_read(&acdb_data.anc_cal.cal_paddr);
193 cal_block->cal_size =
194 atomic_read(&acdb_data.anc_cal.cal_size);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700195done:
196 return;
197}
198
199void store_anc_cal(struct cal_block *cal_block)
200{
201 pr_debug("%s,\n", __func__);
202
Ben Rombergerb7603232011-11-23 17:16:27 -0800203 if (cal_block->cal_offset > atomic64_read(&acdb_data.pmem_len)) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700204 pr_err("%s: offset %d is > pmem_len %ld\n",
205 __func__, cal_block->cal_offset,
Ben Rombergerb7603232011-11-23 17:16:27 -0800206 (long)atomic64_read(&acdb_data.pmem_len));
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700207 goto done;
208 }
209
Ben Rombergerb7603232011-11-23 17:16:27 -0800210 atomic_set(&acdb_data.anc_cal.cal_kvaddr,
211 cal_block->cal_offset + atomic64_read(&acdb_data.kvaddr));
212 atomic_set(&acdb_data.anc_cal.cal_paddr,
213 cal_block->cal_offset + atomic64_read(&acdb_data.paddr));
214 atomic_set(&acdb_data.anc_cal.cal_size,
215 cal_block->cal_size);
216done:
217 return;
218}
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700219
Ben Rombergerb7603232011-11-23 17:16:27 -0800220void store_afe_cal(int32_t path, struct cal_block *cal_block)
221{
222 pr_debug("%s, path = %d\n", __func__, path);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700223
Ben Rombergerb7603232011-11-23 17:16:27 -0800224 if (cal_block->cal_offset > atomic64_read(&acdb_data.pmem_len)) {
225 pr_err("%s: offset %d is > pmem_len %ld\n",
226 __func__, cal_block->cal_offset,
227 (long)atomic64_read(&acdb_data.pmem_len));
228 goto done;
229 }
230 if ((path >= MAX_AUDPROC_TYPES) || (path < 0)) {
231 pr_err("ACDB=> Bad path sent to %s, path: %d\n",
232 __func__, path);
233 goto done;
234 }
235
236 atomic_set(&acdb_data.afe_cal[path].cal_kvaddr,
237 cal_block->cal_offset + atomic64_read(&acdb_data.kvaddr));
238 atomic_set(&acdb_data.afe_cal[path].cal_paddr,
239 cal_block->cal_offset + atomic64_read(&acdb_data.paddr));
240 atomic_set(&acdb_data.afe_cal[path].cal_size,
241 cal_block->cal_size);
242done:
243 return;
244}
245
246void get_afe_cal(int32_t path, struct acdb_cal_block *cal_block)
247{
248 pr_debug("%s, path = %d\n", __func__, path);
249
250 if (cal_block == NULL) {
251 pr_err("ACDB=> NULL pointer sent to %s\n", __func__);
252 goto done;
253 }
254 if ((path >= MAX_AUDPROC_TYPES) || (path < 0)) {
255 pr_err("ACDB=> Bad path sent to %s, path: %d\n",
256 __func__, path);
257 goto done;
258 }
259
260 cal_block->cal_kvaddr =
261 atomic_read(&acdb_data.afe_cal[path].cal_kvaddr);
262 cal_block->cal_paddr =
263 atomic_read(&acdb_data.afe_cal[path].cal_paddr);
264 cal_block->cal_size =
265 atomic_read(&acdb_data.afe_cal[path].cal_size);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700266done:
267 return;
268}
269
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700270void store_audproc_cal(int32_t path, struct cal_block *cal_block)
271{
272 pr_debug("%s, path = %d\n", __func__, path);
273
Ben Rombergerb7603232011-11-23 17:16:27 -0800274 if (cal_block->cal_offset > atomic64_read(&acdb_data.pmem_len)) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700275 pr_err("%s: offset %d is > pmem_len %ld\n",
276 __func__, cal_block->cal_offset,
Ben Rombergerb7603232011-11-23 17:16:27 -0800277 (long)atomic64_read(&acdb_data.pmem_len));
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700278 goto done;
279 }
280 if (path >= MAX_AUDPROC_TYPES) {
281 pr_err("ACDB=> Bad path sent to %s, path: %d\n",
282 __func__, path);
283 goto done;
284 }
285
Ben Rombergerb7603232011-11-23 17:16:27 -0800286 atomic_set(&acdb_data.audproc_cal[path].cal_kvaddr,
287 cal_block->cal_offset + atomic64_read(&acdb_data.kvaddr));
288 atomic_set(&acdb_data.audproc_cal[path].cal_paddr,
289 cal_block->cal_offset + atomic64_read(&acdb_data.paddr));
290 atomic_set(&acdb_data.audproc_cal[path].cal_size,
291 cal_block->cal_size);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700292done:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700293 return;
294}
295
296void get_audproc_cal(int32_t path, struct acdb_cal_block *cal_block)
297{
298 pr_debug("%s, path = %d\n", __func__, path);
299
300 if (cal_block == NULL) {
301 pr_err("ACDB=> NULL pointer sent to %s\n", __func__);
302 goto done;
303 }
304 if (path >= MAX_AUDPROC_TYPES) {
305 pr_err("ACDB=> Bad path sent to %s, path: %d\n",
306 __func__, path);
307 goto done;
308 }
309
Ben Rombergerb7603232011-11-23 17:16:27 -0800310 cal_block->cal_kvaddr =
311 atomic_read(&acdb_data.audproc_cal[path].cal_kvaddr);
312 cal_block->cal_paddr =
313 atomic_read(&acdb_data.audproc_cal[path].cal_paddr);
314 cal_block->cal_size =
315 atomic_read(&acdb_data.audproc_cal[path].cal_size);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700316done:
317 return;
318}
319
320void store_audstrm_cal(int32_t path, struct cal_block *cal_block)
321{
322 pr_debug("%s, path = %d\n", __func__, path);
323
Ben Rombergerb7603232011-11-23 17:16:27 -0800324 if (cal_block->cal_offset > atomic64_read(&acdb_data.pmem_len)) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700325 pr_err("%s: offset %d is > pmem_len %ld\n",
326 __func__, cal_block->cal_offset,
Ben Rombergerb7603232011-11-23 17:16:27 -0800327 (long)atomic64_read(&acdb_data.pmem_len));
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700328 goto done;
329 }
330 if (path >= MAX_AUDPROC_TYPES) {
331 pr_err("ACDB=> Bad path sent to %s, path: %d\n",
332 __func__, path);
333 goto done;
334 }
335
Ben Rombergerb7603232011-11-23 17:16:27 -0800336 atomic_set(&acdb_data.audstrm_cal[path].cal_kvaddr,
337 cal_block->cal_offset + atomic64_read(&acdb_data.kvaddr));
338 atomic_set(&acdb_data.audstrm_cal[path].cal_paddr,
339 cal_block->cal_offset + atomic64_read(&acdb_data.paddr));
340 atomic_set(&acdb_data.audstrm_cal[path].cal_size,
341 cal_block->cal_size);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700342done:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700343 return;
344}
345
346void get_audstrm_cal(int32_t path, struct acdb_cal_block *cal_block)
347{
348 pr_debug("%s, path = %d\n", __func__, path);
349
350 if (cal_block == NULL) {
351 pr_err("ACDB=> NULL pointer sent to %s\n", __func__);
352 goto done;
353 }
354 if (path >= MAX_AUDPROC_TYPES) {
355 pr_err("ACDB=> Bad path sent to %s, path: %d\n",
356 __func__, path);
357 goto done;
358 }
359
Ben Rombergerb7603232011-11-23 17:16:27 -0800360 cal_block->cal_kvaddr =
361 atomic_read(&acdb_data.audstrm_cal[path].cal_kvaddr);
362 cal_block->cal_paddr =
363 atomic_read(&acdb_data.audstrm_cal[path].cal_paddr);
364 cal_block->cal_size =
365 atomic_read(&acdb_data.audstrm_cal[path].cal_size);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700366done:
367 return;
368}
369
370void store_audvol_cal(int32_t path, struct cal_block *cal_block)
371{
372 pr_debug("%s, path = %d\n", __func__, path);
373
Ben Rombergerb7603232011-11-23 17:16:27 -0800374 if (cal_block->cal_offset > atomic64_read(&acdb_data.pmem_len)) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700375 pr_err("%s: offset %d is > pmem_len %ld\n",
376 __func__, cal_block->cal_offset,
Ben Rombergerb7603232011-11-23 17:16:27 -0800377 (long)atomic64_read(&acdb_data.pmem_len));
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700378 goto done;
379 }
380 if (path >= MAX_AUDPROC_TYPES) {
381 pr_err("ACDB=> Bad path sent to %s, path: %d\n",
382 __func__, path);
383 goto done;
384 }
385
Ben Rombergerb7603232011-11-23 17:16:27 -0800386 atomic_set(&acdb_data.audvol_cal[path].cal_kvaddr,
387 cal_block->cal_offset + atomic64_read(&acdb_data.kvaddr));
388 atomic_set(&acdb_data.audvol_cal[path].cal_paddr,
389 cal_block->cal_offset + atomic64_read(&acdb_data.paddr));
390 atomic_set(&acdb_data.audvol_cal[path].cal_size,
391 cal_block->cal_size);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700392done:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700393 return;
394}
395
396void get_audvol_cal(int32_t path, struct acdb_cal_block *cal_block)
397{
398 pr_debug("%s, path = %d\n", __func__, path);
399
400 if (cal_block == NULL) {
401 pr_err("ACDB=> NULL pointer sent to %s\n", __func__);
402 goto done;
403 }
Vasudeva Rao Thumati86edf6c2011-07-06 16:25:13 +0530404 if (path >= MAX_AUDPROC_TYPES || path < 0) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700405 pr_err("ACDB=> Bad path sent to %s, path: %d\n",
406 __func__, path);
407 goto done;
408 }
409
Ben Rombergerb7603232011-11-23 17:16:27 -0800410 cal_block->cal_kvaddr =
411 atomic_read(&acdb_data.audvol_cal[path].cal_kvaddr);
412 cal_block->cal_paddr =
413 atomic_read(&acdb_data.audvol_cal[path].cal_paddr);
414 cal_block->cal_size =
415 atomic_read(&acdb_data.audvol_cal[path].cal_size);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700416done:
417 return;
418}
419
420
421void store_vocproc_cal(int32_t len, struct cal_block *cal_blocks)
422{
423 int i;
424 pr_debug("%s\n", __func__);
425
426 if (len > MAX_NETWORKS) {
427 pr_err("%s: Calibration sent for %d networks, only %d are "
428 "supported!\n", __func__, len, MAX_NETWORKS);
429 goto done;
430 }
431
Ben Rombergerb7603232011-11-23 17:16:27 -0800432 atomic_set(&acdb_data.vocproc_total_cal_size, 0);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700433 for (i = 0; i < len; i++) {
Ben Rombergerb7603232011-11-23 17:16:27 -0800434 if (cal_blocks[i].cal_offset >
435 atomic64_read(&acdb_data.pmem_len)) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700436 pr_err("%s: offset %d is > pmem_len %ld\n",
437 __func__, cal_blocks[i].cal_offset,
Ben Rombergerb7603232011-11-23 17:16:27 -0800438 (long)atomic64_read(&acdb_data.pmem_len));
439 atomic_set(&acdb_data.vocproc_cal[i].cal_size, 0);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700440 } else {
Ben Rombergerb7603232011-11-23 17:16:27 -0800441 atomic_add(cal_blocks[i].cal_size,
442 &acdb_data.vocproc_total_cal_size);
443 atomic_set(&acdb_data.vocproc_cal[i].cal_size,
444 cal_blocks[i].cal_size);
445 atomic_set(&acdb_data.vocproc_cal[i].cal_paddr,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700446 cal_blocks[i].cal_offset +
Ben Rombergerb7603232011-11-23 17:16:27 -0800447 atomic64_read(&acdb_data.paddr));
448 atomic_set(&acdb_data.vocproc_cal[i].cal_kvaddr,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700449 cal_blocks[i].cal_offset +
Ben Rombergerb7603232011-11-23 17:16:27 -0800450 atomic64_read(&acdb_data.kvaddr));
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700451 }
452 }
Ben Rombergerb7603232011-11-23 17:16:27 -0800453 atomic_set(&acdb_data.vocproc_cal_size, len);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700454done:
455 return;
456}
457
458void get_vocproc_cal(struct acdb_cal_data *cal_data)
459{
460 pr_debug("%s\n", __func__);
461
462 if (cal_data == NULL) {
463 pr_err("ACDB=> NULL pointer sent to %s\n", __func__);
464 goto done;
465 }
466
Ben Rombergerb7603232011-11-23 17:16:27 -0800467 cal_data->num_cal_blocks = atomic_read(&acdb_data.vocproc_cal_size);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700468 cal_data->cal_blocks = &acdb_data.vocproc_cal[0];
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700469done:
470 return;
471}
472
473void store_vocstrm_cal(int32_t len, struct cal_block *cal_blocks)
474{
475 int i;
476 pr_debug("%s\n", __func__);
477
478 if (len > MAX_NETWORKS) {
479 pr_err("%s: Calibration sent for %d networks, only %d are "
480 "supported!\n", __func__, len, MAX_NETWORKS);
481 goto done;
482 }
483
Ben Rombergerb7603232011-11-23 17:16:27 -0800484 atomic_set(&acdb_data.vocstrm_total_cal_size, 0);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700485 for (i = 0; i < len; i++) {
Ben Rombergerb7603232011-11-23 17:16:27 -0800486 if (cal_blocks[i].cal_offset >
487 atomic64_read(&acdb_data.pmem_len)) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700488 pr_err("%s: offset %d is > pmem_len %ld\n",
489 __func__, cal_blocks[i].cal_offset,
Ben Rombergerb7603232011-11-23 17:16:27 -0800490 (long)atomic64_read(&acdb_data.pmem_len));
491 atomic_set(&acdb_data.vocstrm_cal[i].cal_size, 0);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700492 } else {
Ben Rombergerb7603232011-11-23 17:16:27 -0800493 atomic_add(cal_blocks[i].cal_size,
494 &acdb_data.vocstrm_total_cal_size);
495 atomic_set(&acdb_data.vocstrm_cal[i].cal_size,
496 cal_blocks[i].cal_size);
497 atomic_set(&acdb_data.vocstrm_cal[i].cal_paddr,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700498 cal_blocks[i].cal_offset +
Ben Rombergerb7603232011-11-23 17:16:27 -0800499 atomic64_read(&acdb_data.paddr));
500 atomic_set(&acdb_data.vocstrm_cal[i].cal_kvaddr,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700501 cal_blocks[i].cal_offset +
Ben Rombergerb7603232011-11-23 17:16:27 -0800502 atomic64_read(&acdb_data.kvaddr));
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700503 }
504 }
Ben Rombergerb7603232011-11-23 17:16:27 -0800505 atomic_set(&acdb_data.vocstrm_cal_size, len);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700506done:
507 return;
508}
509
510void get_vocstrm_cal(struct acdb_cal_data *cal_data)
511{
512 pr_debug("%s\n", __func__);
513
514 if (cal_data == NULL) {
515 pr_err("ACDB=> NULL pointer sent to %s\n", __func__);
516 goto done;
517 }
518
Ben Rombergerb7603232011-11-23 17:16:27 -0800519 cal_data->num_cal_blocks = atomic_read(&acdb_data.vocstrm_cal_size);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700520 cal_data->cal_blocks = &acdb_data.vocstrm_cal[0];
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700521done:
522 return;
523}
524
525void store_vocvol_cal(int32_t len, struct cal_block *cal_blocks)
526{
527 int i;
528 pr_debug("%s\n", __func__);
529
530 if (len > MAX_NETWORKS) {
531 pr_err("%s: Calibration sent for %d networks, only %d are "
532 "supported!\n", __func__, len, MAX_NETWORKS);
533 goto done;
534 }
535
Ben Rombergerb7603232011-11-23 17:16:27 -0800536 atomic_set(&acdb_data.vocvol_total_cal_size, 0);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700537 for (i = 0; i < len; i++) {
Ben Rombergerb7603232011-11-23 17:16:27 -0800538 if (cal_blocks[i].cal_offset >
539 atomic64_read(&acdb_data.pmem_len)) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700540 pr_err("%s: offset %d is > pmem_len %ld\n",
541 __func__, cal_blocks[i].cal_offset,
Ben Rombergerb7603232011-11-23 17:16:27 -0800542 (long)atomic64_read(&acdb_data.pmem_len));
543 atomic_set(&acdb_data.vocvol_cal[i].cal_size, 0);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700544 } else {
Ben Rombergerb7603232011-11-23 17:16:27 -0800545 atomic_add(cal_blocks[i].cal_size,
546 &acdb_data.vocvol_total_cal_size);
547 atomic_set(&acdb_data.vocvol_cal[i].cal_size,
548 cal_blocks[i].cal_size);
549 atomic_set(&acdb_data.vocvol_cal[i].cal_paddr,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700550 cal_blocks[i].cal_offset +
Ben Rombergerb7603232011-11-23 17:16:27 -0800551 atomic64_read(&acdb_data.paddr));
552 atomic_set(&acdb_data.vocvol_cal[i].cal_kvaddr,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700553 cal_blocks[i].cal_offset +
Ben Rombergerb7603232011-11-23 17:16:27 -0800554 atomic64_read(&acdb_data.kvaddr));
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700555 }
556 }
Ben Rombergerb7603232011-11-23 17:16:27 -0800557 atomic_set(&acdb_data.vocvol_cal_size, len);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700558done:
559 return;
560}
561
562void get_vocvol_cal(struct acdb_cal_data *cal_data)
563{
564 pr_debug("%s\n", __func__);
565
566 if (cal_data == NULL) {
567 pr_err("ACDB=> NULL pointer sent to %s\n", __func__);
568 goto done;
569 }
570
Ben Rombergerb7603232011-11-23 17:16:27 -0800571 cal_data->num_cal_blocks = atomic_read(&acdb_data.vocvol_cal_size);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700572 cal_data->cal_blocks = &acdb_data.vocvol_cal[0];
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700573done:
574 return;
575}
576
577void store_sidetone_cal(struct sidetone_cal *cal_data)
578{
579 pr_debug("%s\n", __func__);
580
Ben Rombergerb7603232011-11-23 17:16:27 -0800581 atomic_set(&acdb_data.sidetone_cal.enable, cal_data->enable);
582 atomic_set(&acdb_data.sidetone_cal.gain, cal_data->gain);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700583}
584
585
586void get_sidetone_cal(struct sidetone_cal *cal_data)
587{
588 pr_debug("%s\n", __func__);
589
590 if (cal_data == NULL) {
591 pr_err("ACDB=> NULL pointer sent to %s\n", __func__);
592 goto done;
593 }
594
Ben Rombergerb7603232011-11-23 17:16:27 -0800595 cal_data->enable = atomic_read(&acdb_data.sidetone_cal.enable);
596 cal_data->gain = atomic_read(&acdb_data.sidetone_cal.gain);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700597done:
598 return;
599}
600
601static int acdb_open(struct inode *inode, struct file *f)
602{
603 s32 result = 0;
Ben Rombergerb7603232011-11-23 17:16:27 -0800604 pr_debug("%s\n", __func__);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700605
Ben Rombergerb7603232011-11-23 17:16:27 -0800606 if (atomic_read(&acdb_data.pmem_fd)) {
607 pr_debug("%s: ACDB opened but PMEM allocated, using existing PMEM!\n",
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700608 __func__);
609 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700610
611 atomic_inc(&usage_count);
612 return result;
613}
614
615static int deregister_pmem(void)
616{
Ben Rombergerb7603232011-11-23 17:16:27 -0800617 if (atomic_read(&acdb_data.pmem_fd)) {
618 mutex_lock(&acdb_data.acdb_mutex);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700619 put_pmem_file(acdb_data.file);
Ben Rombergerb7603232011-11-23 17:16:27 -0800620 mutex_unlock(&acdb_data.acdb_mutex);
621 atomic_set(&acdb_data.pmem_fd, 0);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700622 }
Ben Romberger48fabc32012-01-06 17:39:39 -0800623 return 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700624}
625
626static int register_pmem(void)
627{
628 int result;
Ben Rombergerb7603232011-11-23 17:16:27 -0800629 unsigned long paddr;
630 unsigned long kvaddr;
631 unsigned long pmem_len;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700632
Ben Rombergerb7603232011-11-23 17:16:27 -0800633 mutex_lock(&acdb_data.acdb_mutex);
634 result = get_pmem_file(atomic_read(&acdb_data.pmem_fd),
635 &paddr, &kvaddr, &pmem_len,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700636 &acdb_data.file);
Ben Rombergerb7603232011-11-23 17:16:27 -0800637 mutex_unlock(&acdb_data.acdb_mutex);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700638 if (result != 0) {
Ben Rombergerb7603232011-11-23 17:16:27 -0800639 atomic_set(&acdb_data.pmem_fd, 0);
640 atomic64_set(&acdb_data.pmem_len, 0);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700641 pr_err("%s: Could not register PMEM!!!\n", __func__);
642 goto done;
643 }
644
Ben Rombergerb7603232011-11-23 17:16:27 -0800645 atomic64_set(&acdb_data.paddr, paddr);
646 atomic64_set(&acdb_data.kvaddr, kvaddr);
647 atomic64_set(&acdb_data.pmem_len, pmem_len);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700648 pr_debug("AUDIO_REGISTER_PMEM done! paddr = 0x%lx, "
Ben Rombergerb7603232011-11-23 17:16:27 -0800649 "kvaddr = 0x%lx, len = x%lx\n",
650 (long)atomic64_read(&acdb_data.paddr),
651 (long)atomic64_read(&acdb_data.kvaddr),
652 (long)atomic64_read(&acdb_data.pmem_len));
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700653
654done:
655 return result;
656}
657static long acdb_ioctl(struct file *f,
658 unsigned int cmd, unsigned long arg)
659{
Ben Rombergerb7603232011-11-23 17:16:27 -0800660 int32_t result = 0;
661 int32_t size;
662 int32_t pmem_fd;
663 uint32_t topology;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700664 struct cal_block data[MAX_NETWORKS];
665 pr_debug("%s\n", __func__);
666
667 switch (cmd) {
668 case AUDIO_REGISTER_PMEM:
669 pr_debug("AUDIO_REGISTER_PMEM\n");
Ben Rombergerb7603232011-11-23 17:16:27 -0800670 if (atomic_read(&acdb_data.pmem_fd)) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700671 deregister_pmem();
Ben Rombergerb7603232011-11-23 17:16:27 -0800672 pr_debug("Remove the existing PMEM\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700673 }
674
Ben Rombergerb7603232011-11-23 17:16:27 -0800675 if (copy_from_user(&pmem_fd, (void *)arg, sizeof(pmem_fd))) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700676 pr_err("%s: fail to copy pmem handle!\n", __func__);
677 result = -EFAULT;
678 } else {
Ben Rombergerb7603232011-11-23 17:16:27 -0800679 atomic_set(&acdb_data.pmem_fd, pmem_fd);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700680 result = register_pmem();
681 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700682 goto done;
683
684 case AUDIO_DEREGISTER_PMEM:
685 pr_debug("AUDIO_DEREGISTER_PMEM\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700686 deregister_pmem();
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700687 goto done;
688 case AUDIO_SET_VOICE_RX_TOPOLOGY:
689 if (copy_from_user(&topology, (void *)arg,
690 sizeof(topology))) {
691 pr_err("%s: fail to copy topology!\n", __func__);
692 result = -EFAULT;
693 }
694 store_voice_rx_topology(topology);
695 goto done;
696 case AUDIO_SET_VOICE_TX_TOPOLOGY:
697 if (copy_from_user(&topology, (void *)arg,
698 sizeof(topology))) {
699 pr_err("%s: fail to copy topology!\n", __func__);
700 result = -EFAULT;
701 }
702 store_voice_tx_topology(topology);
703 goto done;
Ben Rombergerc49b85d2011-07-15 18:55:34 -0700704 case AUDIO_SET_ADM_RX_TOPOLOGY:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700705 if (copy_from_user(&topology, (void *)arg,
706 sizeof(topology))) {
707 pr_err("%s: fail to copy topology!\n", __func__);
708 result = -EFAULT;
709 }
Ben Rombergerc49b85d2011-07-15 18:55:34 -0700710 store_adm_rx_topology(topology);
711 goto done;
712 case AUDIO_SET_ADM_TX_TOPOLOGY:
713 if (copy_from_user(&topology, (void *)arg,
714 sizeof(topology))) {
715 pr_err("%s: fail to copy topology!\n", __func__);
716 result = -EFAULT;
717 }
718 store_adm_tx_topology(topology);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700719 goto done;
720 case AUDIO_SET_ASM_TOPOLOGY:
721 if (copy_from_user(&topology, (void *)arg,
722 sizeof(topology))) {
723 pr_err("%s: fail to copy topology!\n", __func__);
724 result = -EFAULT;
725 }
726 store_asm_topology(topology);
727 goto done;
728 }
729
730 if (copy_from_user(&size, (void *) arg, sizeof(size))) {
731
732 result = -EFAULT;
733 goto done;
734 }
735
736 if (size <= 0) {
737 pr_err("%s: Invalid size sent to driver: %d\n",
738 __func__, size);
739 result = -EFAULT;
740 goto done;
741 }
742
743 if (copy_from_user(data, (void *)(arg + sizeof(size)), size)) {
744
745 pr_err("%s: fail to copy table size %d\n", __func__, size);
746 result = -EFAULT;
747 goto done;
748 }
749
750 if (data == NULL) {
751 pr_err("%s: NULL pointer sent to driver!\n", __func__);
752 result = -EFAULT;
753 goto done;
754 }
755
756 switch (cmd) {
757 case AUDIO_SET_AUDPROC_TX_CAL:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700758 if (size > sizeof(struct cal_block))
759 pr_err("%s: More Audproc Cal then expected, "
760 "size received: %d\n", __func__, size);
Ben Rombergerb7603232011-11-23 17:16:27 -0800761 store_audproc_cal(TX_CAL, data);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700762 break;
763 case AUDIO_SET_AUDPROC_RX_CAL:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700764 if (size > sizeof(struct cal_block))
765 pr_err("%s: More Audproc Cal then expected, "
766 "size received: %d\n", __func__, size);
Ben Rombergerb7603232011-11-23 17:16:27 -0800767 store_audproc_cal(RX_CAL, data);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700768 break;
769 case AUDIO_SET_AUDPROC_TX_STREAM_CAL:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700770 if (size > sizeof(struct cal_block))
771 pr_err("%s: More Audproc Cal then expected, "
772 "size received: %d\n", __func__, size);
Ben Rombergerb7603232011-11-23 17:16:27 -0800773 store_audstrm_cal(TX_CAL, data);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700774 break;
775 case AUDIO_SET_AUDPROC_RX_STREAM_CAL:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700776 if (size > sizeof(struct cal_block))
777 pr_err("%s: More Audproc Cal then expected, "
778 "size received: %d\n", __func__, size);
Ben Rombergerb7603232011-11-23 17:16:27 -0800779 store_audstrm_cal(RX_CAL, data);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700780 break;
781 case AUDIO_SET_AUDPROC_TX_VOL_CAL:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700782 if (size > sizeof(struct cal_block))
783 pr_err("%s: More Audproc Cal then expected, "
784 "size received: %d\n", __func__, size);
Ben Rombergerb7603232011-11-23 17:16:27 -0800785 store_audvol_cal(TX_CAL, data);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700786 case AUDIO_SET_AUDPROC_RX_VOL_CAL:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700787 if (size > sizeof(struct cal_block))
788 pr_err("%s: More Audproc Cal then expected, "
789 "size received: %d\n", __func__, size);
Ben Rombergerb7603232011-11-23 17:16:27 -0800790 store_audvol_cal(RX_CAL, data);
791 break;
792 case AUDIO_SET_AFE_TX_CAL:
793 if (size > sizeof(struct cal_block))
794 pr_err("%s: More AFE Cal then expected, "
795 "size received: %d\n", __func__, size);
796 store_afe_cal(TX_CAL, data);
797 break;
798 case AUDIO_SET_AFE_RX_CAL:
799 if (size > sizeof(struct cal_block))
800 pr_err("%s: More AFE Cal then expected, "
801 "size received: %d\n", __func__, size);
802 store_afe_cal(RX_CAL, data);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700803 break;
804 case AUDIO_SET_VOCPROC_CAL:
805 store_vocproc_cal(size / sizeof(struct cal_block), data);
806 break;
807 case AUDIO_SET_VOCPROC_STREAM_CAL:
808 store_vocstrm_cal(size / sizeof(struct cal_block), data);
809 break;
810 case AUDIO_SET_VOCPROC_VOL_CAL:
811 store_vocvol_cal(size / sizeof(struct cal_block), data);
812 break;
813 case AUDIO_SET_SIDETONE_CAL:
814 if (size > sizeof(struct sidetone_cal))
815 pr_err("%s: More sidetone cal then expected, "
816 "size received: %d\n", __func__, size);
817 store_sidetone_cal((struct sidetone_cal *)data);
818 break;
819 case AUDIO_SET_ANC_CAL:
820 store_anc_cal(data);
821 break;
822 default:
823 pr_err("ACDB=> ACDB ioctl not found!\n");
824 }
825
826done:
827 return result;
828}
829
830static int acdb_mmap(struct file *file, struct vm_area_struct *vma)
831{
832 int result = 0;
833 int size = vma->vm_end - vma->vm_start;
834
835 pr_debug("%s\n", __func__);
836
Ben Rombergerb7603232011-11-23 17:16:27 -0800837 if (atomic_read(&acdb_data.pmem_fd)) {
838 if (size <= atomic64_read(&acdb_data.pmem_len)) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700839 vma->vm_page_prot = pgprot_noncached(
840 vma->vm_page_prot);
841 result = remap_pfn_range(vma,
842 vma->vm_start,
Ben Rombergerb7603232011-11-23 17:16:27 -0800843 atomic64_read(&acdb_data.paddr) >> PAGE_SHIFT,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700844 size,
845 vma->vm_page_prot);
846 } else {
847 pr_err("%s: Not enough PMEM memory!\n", __func__);
848 result = -ENOMEM;
849 }
850 } else {
851 pr_err("%s: PMEM is not allocated, yet!\n", __func__);
852 result = -ENODEV;
853 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700854
855 return result;
856}
857
858static int acdb_release(struct inode *inode, struct file *f)
859{
860 s32 result = 0;
861
862 atomic_dec(&usage_count);
863 atomic_read(&usage_count);
864
Ben Rombergerb7603232011-11-23 17:16:27 -0800865 pr_debug("%s: ref count %d!\n", __func__,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700866 atomic_read(&usage_count));
867
Ben Rombergerb7603232011-11-23 17:16:27 -0800868 if (atomic_read(&usage_count) >= 1)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700869 result = -EBUSY;
Ben Rombergerb7603232011-11-23 17:16:27 -0800870 else
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700871 result = deregister_pmem();
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700872
873 return result;
874}
875
876static const struct file_operations acdb_fops = {
877 .owner = THIS_MODULE,
878 .open = acdb_open,
879 .release = acdb_release,
880 .unlocked_ioctl = acdb_ioctl,
881 .mmap = acdb_mmap,
882};
883
884struct miscdevice acdb_misc = {
885 .minor = MISC_DYNAMIC_MINOR,
886 .name = "msm_acdb",
887 .fops = &acdb_fops,
888};
889
890static int __init acdb_init(void)
891{
892 memset(&acdb_data, 0, sizeof(acdb_data));
893 mutex_init(&acdb_data.acdb_mutex);
894 atomic_set(&usage_count, 0);
895 return misc_register(&acdb_misc);
896}
897
898static void __exit acdb_exit(void)
899{
900}
901
902module_init(acdb_init);
903module_exit(acdb_exit);
904
905MODULE_DESCRIPTION("MSM 8x60 Audio ACDB driver");
906MODULE_LICENSE("GPL v2");