blob: 230429f141db147594d09eeec8849b16d7f86037 [file] [log] [blame]
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001/*
2 * Common code to deal with the AUDPREPROC dsp task (audio preprocessing)
3 *
4 * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
5 *
6 * Based on the audpp layer in arch/arm/mach-msm/qdsp5/audpp.c
7 *
8 * Copyright (C) 2008 Google, Inc.
9 *
10 * This software is licensed under the terms of the GNU General Public
11 * License version 2, as published by the Free Software Foundation, and
12 * may be copied, distributed, and modified under those terms.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
17 *
18 */
19
20#include <linux/kernel.h>
21#include <linux/module.h>
22#include <mach/msm_adsp.h>
23#include <mach/debug_mm.h>
24#include <mach/qdsp5/qdsp5audpreproc.h>
25#include <mach/qdsp5/qdsp5audreccmdi.h>
26
27static DEFINE_MUTEX(audpreproc_lock);
28
29struct msm_adspenc_info {
30 const char *module_name;
31 unsigned module_queueids;
32 int module_encid; /* streamid */
33 int enc_formats; /* supported formats */
34 int nr_codec_support; /* number of codec suported */
35};
36
37#define ENC_MODULE_INFO(name, queueids, encid, formats, nr_codec) \
38 {.module_name = name, .module_queueids = queueids, \
39 .module_encid = encid, .enc_formats = formats, \
40 .nr_codec_support = nr_codec }
41
42#ifdef CONFIG_MSM7X27A_AUDIO
43#define ENC0_FORMAT ((1<<AUDREC_CMD_TYPE_1_INDEX_SBC)| \
44 (1<<AUDREC_CMD_TYPE_0_INDEX_AAC)| \
45 (1<<AUDREC_CMD_TYPE_0_INDEX_AMRNB)| \
46 (1<<AUDREC_CMD_TYPE_0_INDEX_EVRC)| \
47 (1<<AUDREC_CMD_TYPE_0_INDEX_QCELP))
48
49#define ENC1_FORMAT (1<<AUDREC_CMD_TYPE_0_INDEX_WAV)
50#else
51#define ENC0_FORMAT ((1<<AUDREC_CMD_TYPE_0_INDEX_WAV)| \
52 (1<<AUDREC_CMD_TYPE_1_INDEX_SBC)| \
53 (1<<AUDREC_CMD_TYPE_0_INDEX_AAC)| \
54 (1<<AUDREC_CMD_TYPE_0_INDEX_AMRNB)| \
55 (1<<AUDREC_CMD_TYPE_0_INDEX_EVRC)| \
56 (1<<AUDREC_CMD_TYPE_0_INDEX_QCELP))
57#endif
58
59struct msm_adspenc_database {
60 unsigned num_enc;
61 struct msm_adspenc_info *enc_info_list;
62};
63
64#ifdef CONFIG_MSM7X27A_AUDIO
65static struct msm_adspenc_info enc_info_list[] = {
66 ENC_MODULE_INFO("AUDRECTASK", \
67 ((QDSP_uPAudRecBitStreamQueue << 16)| \
68 QDSP_uPAudRecCmdQueue), 0, \
69 (ENC0_FORMAT | (1 << MSM_ADSP_ENC_MODE_TUNNEL) | \
70 (1 << MSM_ADSP_ENC_MODE_NON_TUNNEL)), 5),
71
72 ENC_MODULE_INFO("AUDREC1TASK", \
73 ((QDSP_uPAudRec1BitStreamQueue << 16)| \
74 QDSP_uPAudRec1CmdQueue), 1, \
75 (ENC1_FORMAT | (1 << MSM_ADSP_ENC_MODE_TUNNEL)), 1),
76};
77#else
78static struct msm_adspenc_info enc_info_list[] = {
79 ENC_MODULE_INFO("AUDRECTASK",
80 ((QDSP_uPAudRecBitStreamQueue << 16)| \
81 QDSP_uPAudRecCmdQueue), 0, \
82 (ENC0_FORMAT | (1 << MSM_ADSP_ENC_MODE_TUNNEL)), 6),
83};
84#endif
85
86static struct msm_adspenc_database msm_enc_database = {
87 .num_enc = ARRAY_SIZE(enc_info_list),
88 .enc_info_list = enc_info_list,
89};
90
91struct audpreproc_state {
92 struct msm_adsp_module *mod;
93 struct mutex *lock;
94 unsigned open_count;
95 unsigned enc_inuse;
96};
97
98static struct audpreproc_state the_audpreproc_state = {
99 .lock = &audpreproc_lock,
100};
101
102/* enc_type = supported encode format *
103 * like pcm, aac, sbc, evrc, qcelp, amrnb etc ... *
104 */
105int audpreproc_aenc_alloc(unsigned enc_type, const char **module_name,
106 unsigned *queue_ids)
107{
108 struct audpreproc_state *audpreproc = &the_audpreproc_state;
109 int encid = -1, idx, lidx, mode, codec;
110 int codecs_supported, min_codecs_supported;
111
112 mutex_lock(audpreproc->lock);
113 /* Represents in bit mask */
114 mode = ((enc_type & AUDPREPROC_MODE_MASK) << 16);
115 codec = (1 << (enc_type & AUDPREPROC_CODEC_MASK));
116
117 lidx = msm_enc_database.num_enc;
118 min_codecs_supported = sizeof(unsigned int) * 8;
119 MM_DBG("mode = 0x%08x codec = 0x%08x\n", mode, codec);
120
121 for (idx = lidx-1; idx >= 0; idx--) {
122 /* encoder free and supports the format */
123 if (!(audpreproc->enc_inuse & (1 << (idx))) &&
124 ((mode & msm_enc_database.enc_info_list[idx].enc_formats)
125 == mode) && ((codec &
126 msm_enc_database.enc_info_list[idx].enc_formats)
127 == codec)){
128 /* Check supports minimum number codecs */
129 codecs_supported =
130 msm_enc_database.enc_info_list[idx].nr_codec_support;
131 if (codecs_supported < min_codecs_supported) {
132 lidx = idx;
133 min_codecs_supported = codecs_supported;
134 }
135 }
136 }
137
138 if (lidx < msm_enc_database.num_enc) {
139 audpreproc->enc_inuse |= (1 << lidx);
140 *module_name =
141 msm_enc_database.enc_info_list[lidx].module_name;
142 *queue_ids =
143 msm_enc_database.enc_info_list[lidx].module_queueids;
144 encid = msm_enc_database.enc_info_list[lidx].module_encid;
145 }
146
147 mutex_unlock(audpreproc->lock);
148 return encid;
149}
150EXPORT_SYMBOL(audpreproc_aenc_alloc);
151
152void audpreproc_aenc_free(int enc_id)
153{
154 struct audpreproc_state *audpreproc = &the_audpreproc_state;
155 int idx;
156
157 mutex_lock(audpreproc->lock);
158 for (idx = 0; idx < msm_enc_database.num_enc; idx++) {
159 if (msm_enc_database.enc_info_list[idx].module_encid ==
160 enc_id) {
161 audpreproc->enc_inuse &= ~(1 << idx);
162 break;
163 }
164 }
165 mutex_unlock(audpreproc->lock);
166 return;
167
168}
169EXPORT_SYMBOL(audpreproc_aenc_free);