aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/dvb/ngene/ngene-snd.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/dvb/ngene/ngene-snd.c')
-rw-r--r--drivers/media/dvb/ngene/ngene-snd.c421
1 files changed, 0 insertions, 421 deletions
diff --git a/drivers/media/dvb/ngene/ngene-snd.c b/drivers/media/dvb/ngene/ngene-snd.c
deleted file mode 100644
index 1ca343236ffb..000000000000
--- a/drivers/media/dvb/ngene/ngene-snd.c
+++ /dev/null
@@ -1,421 +0,0 @@
1/*
2 * ngene_snd.c: nGene PCIe bridge driver ALSA support
3 *
4 * Copyright (C) 2005-2007 Micronas
5 *
6 * Based on the initial ALSA support port by Thomas Eschbach.
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * version 2 only, as published by the Free Software Foundation.
11 *
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
22 * 02110-1301, USA
23 * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
24 */
25
26#include <linux/version.h>
27#include <linux/module.h>
28
29#include "ngene.h"
30#include "ngene-ioctls.h"
31
32static int sound_dev;
33
34/* sound module parameters (see "Module Parameters") */
35static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;
36static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;
37static int enable[SNDRV_CARDS] = {1, [1 ... (SNDRV_CARDS - 1)] = 1};
38
39/****************************************************************************/
40/* PCM Sound Funktions ******************************************************/
41/****************************************************************************/
42
43static struct snd_pcm_hardware snd_mychip_capture_hw = {
44 .info = (SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER),
45 .formats = SNDRV_PCM_FMTBIT_S16_LE,
46 .rates = (SNDRV_PCM_RATE_11025 | SNDRV_PCM_RATE_16000
47 | SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_32000
48 | SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000),
49 .rate_min = 11025,
50 .rate_max = 48000,
51 .channels_min = 2,
52 .channels_max = 2,
53 .buffer_bytes_max = 16384,
54 .period_bytes_min = 8192,
55 .period_bytes_max = 8192,
56 .periods_min = 1,
57 .periods_max = 2,
58};
59
60/* open callback */
61static int snd_mychip_capture_open(struct snd_pcm_substream *substream)
62{
63
64 struct mychip *chip = snd_pcm_substream_chip(substream);
65 struct snd_pcm_runtime *runtime = substream->runtime;
66
67 runtime->hw = snd_mychip_capture_hw;
68 chip->substream = substream;
69 return 0;
70}
71
72/* close callback */
73static int snd_mychip_capture_close(struct snd_pcm_substream *substream)
74{
75 struct mychip *chip = snd_pcm_substream_chip(substream);
76 chip->substream = NULL;
77 return 0;
78
79}
80
81/* hw_params callback */
82static int snd_mychip_pcm_hw_params(struct snd_pcm_substream *substream,
83 struct snd_pcm_hw_params *hw_params)
84{
85 struct mychip *chip = snd_pcm_substream_chip(substream);
86 struct ngene_channel *chan = chip->chan;
87 if (chan->soundbuffisallocated == 0) {
88 chan->soundbuffisallocated = 1;
89 return snd_pcm_lib_malloc_pages(substream,
90 params_buffer_bytes(hw_params));
91 }
92 return 0;
93}
94
95/* hw_free callback */
96static int snd_mychip_pcm_hw_free(struct snd_pcm_substream *substream)
97{
98 struct mychip *chip = snd_pcm_substream_chip(substream);
99 struct ngene_channel *chan = chip->chan;
100 int retval = 0;
101 if (chan->soundbuffisallocated == 1) {
102 chan->soundbuffisallocated = 0;
103 retval = snd_pcm_lib_free_pages(substream);
104 }
105 return retval;
106}
107
108/* prepare callback */
109static int snd_mychip_pcm_prepare(struct snd_pcm_substream *substream)
110{
111
112 struct mychip *chip = snd_pcm_substream_chip(substream);
113 struct snd_pcm_runtime *runtime = substream->runtime;
114 struct ngene_channel *chan = chip->chan;
115 struct ngene_channel *ch = &chan->dev->channel[chan->number - 2];
116 struct i2c_adapter *adap = &ch->i2c_adapter;
117
118 if (ch->soundstreamon == 1)
119 ;/*ngene_command_stream_control_sound(chan->dev, chan->number,
120 0x00, 0x00);*/
121 i2c_clients_command(adap, IOCTL_MIC_DEC_SRATE, &(runtime->rate));
122 mdelay(80);
123 if (ch->soundstreamon == 1)
124 ;/*ngene_command_stream_control_sound(chan->dev, chan->number,
125 0x80, 0x04);*/
126
127 return 0;
128}
129
130/* trigger callback */
131static int snd_mychip_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
132{
133 struct mychip *chip = snd_pcm_substream_chip(substream);
134 struct ngene_channel *chan = chip->chan;
135
136 switch (cmd) {
137 case SNDRV_PCM_TRIGGER_START:
138 /* do something to start the PCM engine */
139 chan->sndbuffflag = 0;
140 break;
141 case SNDRV_PCM_TRIGGER_STOP:
142 /* do something to stop the PCM engine */
143 chip->substream = NULL;
144 chan->sndbuffflag = 0;
145 break;
146 default:
147 return -EINVAL;
148 }
149 return 0;
150}
151
152/* pointer callback */
153static snd_pcm_uframes_t
154snd_mychip_pcm_pointer(struct snd_pcm_substream *substream)
155{
156 struct mychip *chip = snd_pcm_substream_chip(substream);
157 struct ngene_channel *chan = chip->chan;
158 unsigned int current_ptr;
159
160 if (chan->sndbuffflag == 0) {
161 current_ptr = (unsigned int)
162 bytes_to_frames(substream->runtime, 0);
163 } else {
164 current_ptr = (unsigned int)
165 bytes_to_frames(substream->runtime, 8192);
166 }
167 return current_ptr;
168}
169
170/*copy sound buffer to pcm middel layer*/
171static int snd_capture_copy(struct snd_pcm_substream *substream, int channel,
172 snd_pcm_uframes_t pos, void *dst,
173 snd_pcm_uframes_t count)
174{
175 struct snd_pcm_runtime *runtime = substream->runtime;
176 struct mychip *chip = snd_pcm_substream_chip(substream);
177 struct ngene_channel *chan = chip->chan;
178
179 memcpy(dst, chan->soundbuffer, frames_to_bytes(runtime, count));
180 return 0;
181}
182
183static int snd_pcm_capture_silence(struct snd_pcm_substream *substream,
184 int channel,
185 snd_pcm_uframes_t pos,
186 snd_pcm_uframes_t count)
187{
188 /*
189 struct snd_pcm_runtime *runtime = substream->runtime;
190 struct mychip *chip = snd_pcm_substream_chip(substream);
191 struct ngene_channel *chan = chip->chan;
192 */
193 return 0;
194}
195
196/* operators */
197static struct snd_pcm_ops snd_mychip_capture_ops = {
198 .open = snd_mychip_capture_open,
199 .close = snd_mychip_capture_close,
200 .ioctl = snd_pcm_lib_ioctl,
201 .hw_params = snd_mychip_pcm_hw_params,
202 .hw_free = snd_mychip_pcm_hw_free,
203 .prepare = snd_mychip_pcm_prepare,
204 .trigger = snd_mychip_pcm_trigger,
205 .pointer = snd_mychip_pcm_pointer,
206 .copy = snd_capture_copy,
207 .silence = snd_pcm_capture_silence,
208};
209
210static void mychip_pcm_free(struct snd_pcm *pcm)
211{
212 pcm->private_data = NULL;
213}
214
215/* create a pcm device */
216static int snd_mychip_new_pcm(struct mychip *chip, struct ngene_channel *chan)
217{
218 struct snd_pcm *pcm;
219 int err;
220 char gro[10];
221 sprintf(gro, "PCM%d", chan->number);
222
223 err = snd_pcm_new(chip->card, gro, 0, 0, 1, &pcm);
224 if (err < 0)
225 return err;
226
227 pcm->private_data = chip;
228 pcm->private_free = mychip_pcm_free;
229
230 sprintf(pcm->name, "MyPCM_%d", chan->number);
231
232 chip->pcm = pcm;
233 /* set operators */
234 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_mychip_capture_ops);
235 /* pre-allocation of buffers */
236
237 err = snd_pcm_lib_preallocate_pages_for_all(pcm,
238 SNDRV_DMA_TYPE_CONTINUOUS,
239 snd_dma_continuous_data(
240 GFP_KERNEL),
241 0, 16 * 1024);
242
243 return 0;
244}
245
246#define ngene_VOLUME(xname, xindex, addr) \
247 { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \
248 .info = snd_volume_info, \
249 .get = snd_volume_get, .put = snd_volume_put, \
250 .private_value = addr }
251
252static int snd_volume_info(struct snd_kcontrol *kcontrol,
253 struct snd_ctl_elem_info *uinfo)
254{
255 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
256 uinfo->count = 2;
257 uinfo->value.integer.min = 0;
258 uinfo->value.integer.max = 20;
259 return 0;
260}
261
262static int snd_volume_get(struct snd_kcontrol *kcontrol,
263 struct snd_ctl_elem_value *ucontrol)
264{
265 struct mychip *chip = snd_kcontrol_chip(kcontrol);
266 int addr = kcontrol->private_value;
267
268 ucontrol->value.integer.value[0] = chip->mixer_volume[addr][0];
269 ucontrol->value.integer.value[1] = chip->mixer_volume[addr][1];
270 return 0;
271}
272
273static int snd_volume_put(struct snd_kcontrol *kcontrol,
274 struct snd_ctl_elem_value *ucontrol)
275{
276 struct mychip *chip = snd_kcontrol_chip(kcontrol);
277 int change, addr = kcontrol->private_value;
278 int left, right;
279
280 left = ucontrol->value.integer.value[0];
281 if (left < 0)
282 left = 0;
283 if (left > 20)
284 left = 20;
285 right = ucontrol->value.integer.value[1];
286 if (right < 0)
287 right = 0;
288 if (right > 20)
289 right = 20;
290 spin_lock_irq(&chip->mixer_lock);
291 change = chip->mixer_volume[addr][0] != left ||
292 chip->mixer_volume[addr][1] != right;
293 chip->mixer_volume[addr][0] = left;
294 chip->mixer_volume[addr][1] = right;
295 spin_unlock_irq(&chip->mixer_lock);
296 return change;
297}
298
299#define ngene_CAPSRC(xname, xindex, addr) \
300 { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \
301 .info = snd_capsrc_info, \
302 .get = snd_capsrc_get, .put = snd_capsrc_put, \
303 .private_value = addr }
304
305static int snd_capsrc_info(struct snd_kcontrol *kcontrol,
306 struct snd_ctl_elem_info *uinfo)
307{
308 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
309 uinfo->count = 2;
310 uinfo->value.integer.min = 0;
311 uinfo->value.integer.max = 1;
312 return 0;
313}
314
315static int snd_capsrc_get(struct snd_kcontrol *kcontrol,
316 struct snd_ctl_elem_value *ucontrol)
317{
318 struct mychip *chip = snd_kcontrol_chip(kcontrol);
319 int addr = kcontrol->private_value;
320
321 spin_lock_irq(&chip->mixer_lock);
322 ucontrol->value.integer.value[0] = chip->capture_source[addr][0];
323 ucontrol->value.integer.value[1] = chip->capture_source[addr][1];
324 spin_unlock_irq(&chip->mixer_lock);
325
326 return 0;
327}
328
329static int snd_capsrc_put(struct snd_kcontrol *kcontrol,
330 struct snd_ctl_elem_value *ucontrol)
331{
332 struct mychip *chip = snd_kcontrol_chip(kcontrol);
333 int change, addr = kcontrol->private_value;
334 int left, right;
335
336 left = ucontrol->value.integer.value[0] & 1;
337 right = ucontrol->value.integer.value[1] & 1;
338 spin_lock_irq(&chip->mixer_lock);
339
340 change = chip->capture_source[addr][0] != left ||
341 chip->capture_source[addr][1] != right;
342 chip->capture_source[addr][0] = left;
343 chip->capture_source[addr][1] = right;
344
345 spin_unlock_irq(&chip->mixer_lock);
346
347 if (change)
348 printk(KERN_INFO "snd_capsrc_put change\n");
349 return 0;
350}
351
352static struct snd_kcontrol_new snd_controls[] = {
353 ngene_VOLUME("Video Volume", 0, MIXER_ADDR_TVTUNER),
354 ngene_CAPSRC("Video Capture Switch", 0, MIXER_ADDR_TVTUNER),
355};
356
357static int snd_card_new_mixer(struct mychip *chip)
358{
359 struct snd_card *card = chip->card;
360 unsigned int idx;
361 int err;
362
363 strcpy(card->mixername, "NgeneMixer");
364
365 for (idx = 0; idx < ARRAY_SIZE(snd_controls); idx++) {
366 err = snd_ctl_add(card, snd_ctl_new1(&snd_controls[idx], chip));
367 if (err < 0)
368 return err;
369 }
370 return 0;
371}
372
373int ngene_snd_init(struct ngene_channel *chan)
374{
375 struct snd_card *card;
376 struct mychip *chip;
377 int err;
378
379 if (sound_dev >= SNDRV_CARDS)
380 return -ENODEV;
381 if (!enable[sound_dev]) {
382 sound_dev++;
383 return -ENOENT;
384 }
385 card = snd_card_new(index[sound_dev], id[sound_dev],
386 THIS_MODULE, sizeof(struct mychip));
387 if (card == NULL)
388 return -ENOMEM;
389
390 chip = card->private_data;
391 chip->card = card;
392 chip->irq = -1;
393
394 sprintf(card->shortname, "MyChip%d%d", chan->dev->nr, chan->number);
395 sprintf(card->shortname, "Myown%d%d", chan->dev->nr, chan->number);
396 sprintf(card->longname, "My first Own Chip on Card Nr.%d is %d",
397 chan->dev->nr, chan->number);
398
399 spin_lock_init(&chip->lock);
400 spin_lock_init(&chip->mixer_lock);
401
402 snd_card_new_mixer(chip);
403
404 snd_mychip_new_pcm(chip, chan);
405 err = snd_card_register(card);
406 if (err < 0) {
407 snd_card_free(card);
408 return err;
409 }
410 chan->soundcard = card;
411 chan->mychip = chip;
412 chip->chan = chan;
413 sound_dev++;
414 return 0;
415}
416
417int ngene_snd_exit(struct ngene_channel *chan)
418{
419 snd_card_free(chan->soundcard);
420 return 0;
421}