power: first sketch at delivering wakeup reason to userland via /proc interface
[htc-msm-2-6-32:leviathan-incoming.git] / sound / soc / msm / qsd8k.c
1 /* linux/sound/soc/msm/qsd8k.c
2  *
3  * Copyright (c) 2009, Code Aurora Forum. All rights reserved.
4  *
5  * All source code in this file is licensed under the following license except
6  * where indicated.
7  *
8  * This program is free software; you can redistribute it and/or modify it
9  * under the terms of the GNU General Public License version 2 as published
10  * by the Free Software Foundation.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
15  *
16  * See the GNU General Public License for more details.
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, you can find it at http://www.fsf.org.
19  */
20
21 #include <linux/init.h>
22 #include <linux/err.h>
23 #include <linux/module.h>
24 #include <linux/moduleparam.h>
25 #include <linux/time.h>
26 #include <linux/wait.h>
27 #include <linux/platform_device.h>
28 #include <sound/core.h>
29 #include <sound/soc.h>
30 #include <sound/soc-dapm.h>
31 #include <sound/pcm.h>
32 #include <sound/initval.h>
33 #include <sound/control.h>
34 #include <asm/dma.h>
35 #include <linux/dma-mapping.h>
36
37 #include "qsd-pcm.h"
38
39 static struct platform_device *qsd_audio_snd_device;
40
41 static int snd_qsd_route_info(struct snd_kcontrol *kcontrol,
42                                 struct snd_ctl_elem_info *uinfo)
43 {
44         uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
45         uinfo->count = 1; /* Device */
46         uinfo->value.integer.min = (int)CAD_HW_DEVICE_ID_HANDSET_MIC;
47         uinfo->value.integer.max = (int)CAD_HW_DEVICE_ID_MAX_NUM;
48         return 0;
49 }
50
51 static int snd_qsd_route_get(struct snd_kcontrol *kcontrol,
52                                 struct snd_ctl_elem_value *ucontrol)
53 {
54         ucontrol->value.integer.value[0] =
55                         (uint32_t) qsd_glb_ctl.device;
56         return 0;
57 }
58
59 static int snd_qsd_route_put(struct snd_kcontrol *kcontrol,
60                         struct snd_ctl_elem_value *ucontrol)
61 {
62         int rc = 0;
63         int device;
64
65         device = ucontrol->value.integer.value[0];
66
67         rc = audio_switch_device(device);
68         if (rc < 0) {
69                 printk(KERN_ERR "audio_switch_device  failed\n");
70                 return rc;
71         }
72
73         qsd_glb_ctl.device = device;
74
75         return 0;
76 }
77
78 static int snd_vol_info(struct snd_kcontrol *kcontrol,
79                                 struct snd_ctl_elem_info *uinfo)
80 {
81         uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
82         uinfo->count = 1; /* Volume */
83         uinfo->value.integer.min = 0;
84         uinfo->value.integer.max = 100;
85         return 0;
86 }
87
88 static int snd_rx_vol_get(struct snd_kcontrol *kcontrol,
89                                 struct snd_ctl_elem_value *ucontrol)
90 {
91         ucontrol->value.integer.value[0] = (uint32_t) qsd_glb_ctl.rx_volume;
92         return 0;
93 }
94
95 static int snd_rx_vol_put(struct snd_kcontrol *kcontrol,
96                         struct snd_ctl_elem_value *ucontrol)
97 {
98         struct msm_vol_info vi;
99         int rc = 0;
100
101         vi.vol = ucontrol->value.integer.value[0];
102         vi.path = CAD_RX_DEVICE;
103
104         rc = audio_set_device_volume_path(&vi);
105
106         if (rc)
107                 printk(KERN_ERR "audio_set_device_volume failed\n");
108         else
109                 qsd_glb_ctl.rx_volume = ucontrol->value.integer.value[0];
110
111         return rc;
112 }
113
114 static int snd_tx_vol_get(struct snd_kcontrol *kcontrol,
115                                 struct snd_ctl_elem_value *ucontrol)
116 {
117         ucontrol->value.integer.value[0] = (uint32_t) qsd_glb_ctl.tx_volume;
118         return 0;
119 }
120
121 static int snd_tx_vol_put(struct snd_kcontrol *kcontrol,
122                         struct snd_ctl_elem_value *ucontrol)
123 {
124         struct msm_vol_info vi;
125         int rc = 0;
126
127         vi.vol = ucontrol->value.integer.value[0];
128         vi.path = CAD_TX_DEVICE;
129
130         rc = audio_set_device_volume_path(&vi);
131
132         if (rc)
133                 printk(KERN_ERR "audio_set_device_volume failed\n");
134         else
135                 qsd_glb_ctl.tx_volume = ucontrol->value.integer.value[0];
136
137         return rc;
138 }
139
140 static int snd_tx_mute_info(struct snd_kcontrol *kcontrol,
141                                 struct snd_ctl_elem_info *uinfo)
142 {
143         uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
144         uinfo->count = 1; /* MUTE */
145         uinfo->value.integer.min = 0;
146         uinfo->value.integer.max = 1;
147         return 0;
148 }
149
150 static int snd_tx_mute_get(struct snd_kcontrol *kcontrol,
151                                 struct snd_ctl_elem_value *ucontrol)
152 {
153         ucontrol->value.integer.value[0] = (uint32_t) qsd_glb_ctl.tx_mute;
154         return 0;
155 }
156
157 static int snd_tx_mute_put(struct snd_kcontrol *kcontrol,
158                         struct snd_ctl_elem_value *ucontrol)
159 {
160         int rc = 0;
161         struct msm_mute_info m;
162
163         m.path = CAD_TX_DEVICE;
164         m.mute = ucontrol->value.integer.value[0];
165
166         rc = audio_set_device_mute(&m);
167         if (rc)
168                 printk(KERN_ERR "Capture device mute failed\n");
169         else
170                 qsd_glb_ctl.tx_mute = ucontrol->value.integer.value[0];
171         return rc;
172 }
173
174 static int snd_rx_mute_info(struct snd_kcontrol *kcontrol,
175                                 struct snd_ctl_elem_info *uinfo)
176 {
177         uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
178         uinfo->count = 1; /* MUTE */
179         uinfo->value.integer.min = 0;
180         uinfo->value.integer.max = 1;
181         return 0;
182 }
183
184 static int snd_rx_mute_get(struct snd_kcontrol *kcontrol,
185                                 struct snd_ctl_elem_value *ucontrol)
186 {
187         ucontrol->value.integer.value[0] = (uint32_t) qsd_glb_ctl.rx_mute;
188         return 0;
189 }
190
191 static int snd_rx_mute_put(struct snd_kcontrol *kcontrol,
192                         struct snd_ctl_elem_value *ucontrol)
193 {
194         int rc = 0;
195         struct msm_mute_info m;
196
197         m.path = CAD_RX_DEVICE;
198         m.mute = ucontrol->value.integer.value[0];
199
200         rc = audio_set_device_mute(&m);
201         if (rc)
202                 printk(KERN_ERR "Playback device mute failed\n");
203         else
204                 qsd_glb_ctl.rx_mute = ucontrol->value.integer.value[0];
205         return rc;
206 }
207
208 static int snd_strm_vol_info(struct snd_kcontrol *kcontrol,
209                                 struct snd_ctl_elem_info *uinfo)
210 {
211         uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
212         uinfo->count = 1; /* Volume Param, in gain */
213         uinfo->value.integer.min = CAD_STREAM_MIN_GAIN;
214         uinfo->value.integer.max = CAD_STREAM_MAX_GAIN;
215         return 0;
216 }
217
218 static int snd_strm_vol_get(struct snd_kcontrol *kcontrol,
219                                 struct snd_ctl_elem_value *ucontrol)
220 {
221         ucontrol->value.integer.value[0] = qsd_glb_ctl.strm_volume;
222         return 0;
223 }
224
225 static int snd_strm_vol_put(struct snd_kcontrol *kcontrol,
226                                 struct snd_ctl_elem_value *ucontrol)
227 {
228         int change;
229         int volume;
230
231         if (ucontrol->value.integer.value[0] > CAD_STREAM_MAX_GAIN)
232                 ucontrol->value.integer.value[0] = CAD_STREAM_MAX_GAIN;
233         if (ucontrol->value.integer.value[0] < CAD_STREAM_MIN_GAIN)
234                 ucontrol->value.integer.value[0] = CAD_STREAM_MIN_GAIN;
235
236         volume = ucontrol->value.integer.value[0];
237         change = (qsd_glb_ctl.strm_volume != volume);
238         mutex_lock(&the_locks.mixer_lock);
239         if (change) {
240                 qsd_glb_ctl.strm_volume = volume;
241                 qsd_glb_ctl.update = 1;
242         }
243         mutex_unlock(&the_locks.mixer_lock);
244         return 0;
245 }
246
247 #define QSD_EXT(xname, xindex, fp_info, fp_get, fp_put, addr) \
248 { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
249   .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, \
250   .name = xname, .index = xindex, \
251   .info = fp_info,\
252   .get = fp_get, .put = fp_put, \
253   .private_value = addr, \
254 }
255
256 static struct snd_kcontrol_new snd_qsd_controls[] = {
257         QSD_EXT("Master Route", 1, snd_qsd_route_info, \
258                          snd_qsd_route_get, snd_qsd_route_put, 0),
259         QSD_EXT("Master Volume Playback", 2, snd_vol_info, \
260                          snd_rx_vol_get, snd_rx_vol_put, 0),
261         QSD_EXT("Master Volume Capture", 3, snd_vol_info, \
262                          snd_tx_vol_get, snd_tx_vol_put, 0),
263         QSD_EXT("Master Mute Playback", 4, snd_rx_mute_info, \
264                          snd_rx_mute_get, snd_rx_mute_put, 0),
265         QSD_EXT("Master Mute Capture", 5, snd_tx_mute_info, \
266                          snd_tx_mute_get, snd_tx_mute_put, 0),
267         QSD_EXT("Stream Volume", 6, snd_strm_vol_info, \
268                          snd_strm_vol_get, snd_strm_vol_put, 0),
269 };
270
271 static int qsd_new_mixer(struct snd_card *card)
272 {
273         unsigned int idx;
274         int err;
275
276         strcpy(card->mixername, "MSM Mixer");
277         for (idx = 0; idx < ARRAY_SIZE(snd_qsd_controls); idx++) {
278                 err = snd_ctl_add(card,
279                                 snd_ctl_new1(&snd_qsd_controls[idx], NULL));
280                 if (err < 0)
281                         return err;
282         }
283         return 0;
284 }
285
286 static int qsd_soc_dai_init(struct snd_soc_codec *codec)
287 {
288
289         int ret = 0;
290         ret = qsd_new_mixer(codec->card);
291         if (ret < 0) {
292                 pr_err("msm_soc: ALSA MSM Mixer Fail\n");
293         }
294
295         return ret;
296 }
297
298 static struct snd_soc_dai_link qsd_dai = {
299         .name = "ASOC",
300         .stream_name = "ASOC",
301         .codec_dai = &msm_dais[0],
302         .cpu_dai = &msm_dais[1],
303         .init   = qsd_soc_dai_init,
304 };
305
306 struct snd_soc_card snd_soc_card_qsd = {
307         .name           = "qsd-audio",
308         .dai_link       = &qsd_dai,
309         .num_links      = 1,
310         .platform = &qsd_soc_platform,
311 };
312
313 /* qsd_audio audio subsystem */
314 static struct snd_soc_device qsd_audio_snd_devdata = {
315         .card = &snd_soc_card_qsd,
316         .codec_dev = &soc_codec_dev_msm,
317 };
318
319 static int __init qsd_audio_init(void)
320 {
321         int ret;
322
323         qsd_audio_snd_device = platform_device_alloc("soc-audio", -1);
324         if (!qsd_audio_snd_device)
325                 return -ENOMEM;
326
327         platform_set_drvdata(qsd_audio_snd_device, &qsd_audio_snd_devdata);
328         qsd_audio_snd_devdata.dev = &qsd_audio_snd_device->dev;
329         ret = platform_device_add(qsd_audio_snd_device);
330         if (ret) {
331                 platform_device_put(qsd_audio_snd_device);
332                 return ret;
333         }
334         mutex_init(&the_locks.mixer_lock);
335         init_waitqueue_head(&the_locks.eos_wait);
336         spin_lock_init(&the_locks.alsa_lock);
337
338         qsd_glb_ctl.tx_volume = 100;
339         qsd_glb_ctl.rx_volume = 100;
340         qsd_glb_ctl.strm_volume = 100;
341         qsd_glb_ctl.device = CAD_HW_DEVICE_ID_HANDSET_SPKR;
342         qsd_glb_ctl.tx_mute = 0;
343         qsd_glb_ctl.rx_mute = 0;
344         qsd_glb_ctl.update = 0;
345
346         return ret;
347 }
348
349 static void __exit qsd_audio_exit(void)
350 {
351         kfree(qsd_audio_snd_devdata.codec_dev);
352         platform_device_unregister(qsd_audio_snd_device);
353 }
354
355 module_init(qsd_audio_init);
356 module_exit(qsd_audio_exit);
357
358 MODULE_DESCRIPTION("PCM module");
359 MODULE_LICENSE("GPL v2");