blob: 84eeeba21d743cefe108fe65c64f6cd5220e4759 [file] [log] [blame]
Nickolay V. Shmyrev5f7591c2005-11-08 21:37:04 -08001/*
Ricardo Cerqueirabd15eba2005-11-08 21:37:11 -08002 * SAA713x ALSA support for V4L
3 * Ricardo Cerqueira <v4l@cerqueira.org>
Nickolay V. Shmyrev5f7591c2005-11-08 21:37:04 -08004 *
Nickolay V. Shmyrev5f7591c2005-11-08 21:37:04 -08005 *
Ricardo Cerqueirabd15eba2005-11-08 21:37:11 -08006 * Caveats:
7 * I still haven't got the mixer settings right.
Nickolay V. Shmyrev5f7591c2005-11-08 21:37:04 -08008 *
Ricardo Cerqueirabd15eba2005-11-08 21:37:11 -08009 * - Volume doesn't work (it's always at max)
10 * - There's no "memory" of the capture channel. It can be changed,
11 * but alsamixer doesn't show it after a module restart (rmmod/insmod)
Nickolay V. Shmyrev5f7591c2005-11-08 21:37:04 -080012 *
Ricardo Cerqueirabd15eba2005-11-08 21:37:11 -080013 * Hotswapping DOES NOT work yet! Please remove the module before
14 * inserting cardbus cards. pcmcia-cs or pccardd should load it
15 * properly after insertion, and things will work
Nickolay V. Shmyrev5f7591c2005-11-08 21:37:04 -080016 *
Ricardo Cerqueirabd15eba2005-11-08 21:37:11 -080017 * This program is free software; you can redistribute it and/or modify
18 * it under the terms of the GNU General Public License as published by
19 * the Free Software Foundation, version 2
20 *
21 * This program is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 * GNU General Public License for more details.
25 *
26 * You should have received a copy of the GNU General Public License
27 * along with this program; if not, write to the Free Software
28 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
29 *
Nickolay V. Shmyrev5f7591c2005-11-08 21:37:04 -080030 */
31
Nickolay V. Shmyrev5f7591c2005-11-08 21:37:04 -080032#include <sound/driver.h>
Ricardo Cerqueirabd15eba2005-11-08 21:37:11 -080033#include <linux/init.h>
34#include <linux/slab.h>
35#include <linux/time.h>
36#include <linux/wait.h>
37#include <linux/moduleparam.h>
38#include <linux/module.h>
Nickolay V. Shmyrev5f7591c2005-11-08 21:37:04 -080039#include <sound/core.h>
Nickolay V. Shmyrev5f7591c2005-11-08 21:37:04 -080040#include <sound/control.h>
Ricardo Cerqueirabd15eba2005-11-08 21:37:11 -080041#include <sound/pcm.h>
42#include <sound/rawmidi.h>
Nickolay V. Shmyrev5f7591c2005-11-08 21:37:04 -080043#include <sound/initval.h>
44
45#include "saa7134.h"
46#include "saa7134-reg.h"
47
Ricardo Cerqueirabd15eba2005-11-08 21:37:11 -080048static unsigned int alsa_debug = 0;
49module_param(alsa_debug, int, 0644);
50MODULE_PARM_DESC(alsa_debug,"enable debug messages [alsa]");
51
52#define MAX_PCM_DEVICES 1
53#define MAX_PCM_SUBSTREAMS 1
54
55/* defaults */
56#define MAX_BUFFER_SIZE (256*1024)
57#define USE_FORMATS SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE | SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_U16_LE | SNDRV_PCM_FMTBIT_U16_BE
58#define USE_RATE SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000
59#define USE_RATE_MIN 32000
60#define USE_RATE_MAX 48000
61#define USE_CHANNELS_MIN 1
62#define USE_CHANNELS_MAX 2
63#ifndef USE_PERIODS_MIN
64#define USE_PERIODS_MIN 2
65#endif
66#ifndef USE_PERIODS_MAX
67#define USE_PERIODS_MAX 1024
68#endif
Nickolay V. Shmyrev5f7591c2005-11-08 21:37:04 -080069
70
Ricardo Cerqueirabd15eba2005-11-08 21:37:11 -080071#define dprintk(fmt, arg...) if (alsa_debug) \
72 printk(KERN_DEBUG "%s/alsa: " fmt, dev->name , ## arg)
Nickolay V. Shmyrev5f7591c2005-11-08 21:37:04 -080073
Nickolay V. Shmyrev5f7591c2005-11-08 21:37:04 -080074
75static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */
76static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */
Ricardo Cerqueirabd15eba2005-11-08 21:37:11 -080077static int enable[SNDRV_CARDS] = {1, [1 ... (SNDRV_CARDS - 1)] = 0};
Nickolay V. Shmyrev5f7591c2005-11-08 21:37:04 -080078
Ricardo Cerqueirabd15eba2005-11-08 21:37:11 -080079#define MIXER_ADDR_TVTUNER 0
80#define MIXER_ADDR_LINE1 1
81#define MIXER_ADDR_LINE2 2
82#define MIXER_ADDR_LAST 2
Nickolay V. Shmyrev5f7591c2005-11-08 21:37:04 -080083
Ricardo Cerqueirabd15eba2005-11-08 21:37:11 -080084typedef struct snd_card_saa7134 {
85 snd_card_t *card;
86 spinlock_t mixer_lock;
87 int mixer_volume[MIXER_ADDR_LAST+1][2];
88 int capture_source[MIXER_ADDR_LAST+1][2];
89 struct pci_dev *pci;
90 struct saa7134_dev *saadev;
Nickolay V. Shmyrev5f7591c2005-11-08 21:37:04 -080091
Ricardo Cerqueirabd15eba2005-11-08 21:37:11 -080092 unsigned long iobase;
93 int irq;
Nickolay V. Shmyrev5f7591c2005-11-08 21:37:04 -080094
Ricardo Cerqueirabd15eba2005-11-08 21:37:11 -080095 spinlock_t lock;
96} snd_card_saa7134_t;
Nickolay V. Shmyrev5f7591c2005-11-08 21:37:04 -080097
Ricardo Cerqueirabd15eba2005-11-08 21:37:11 -080098typedef struct snd_card_saa7134_pcm {
99 struct saa7134_dev *saadev;
Nickolay V. Shmyrev5f7591c2005-11-08 21:37:04 -0800100
Ricardo Cerqueirabd15eba2005-11-08 21:37:11 -0800101 spinlock_t lock;
102 unsigned int pcm_size; /* buffer size */
103 unsigned int pcm_count; /* bytes per period */
104 unsigned int pcm_bps; /* bytes per second */
105 snd_pcm_substream_t *substream;
106} snd_card_saa7134_pcm_t;
107
108static snd_card_t *snd_saa7134_cards[SNDRV_CARDS] = SNDRV_DEFAULT_PTR;
109
110static void saa7134_dma_stop(struct saa7134_dev *dev)
Nickolay V. Shmyrev5f7591c2005-11-08 21:37:04 -0800111{
Ricardo Cerqueirabd15eba2005-11-08 21:37:11 -0800112 dev->oss.dma_blk = -1;
113 dev->oss.dma_running = 0;
114 saa7134_set_dmabits(dev);
Nickolay V. Shmyrev5f7591c2005-11-08 21:37:04 -0800115}
116
Ricardo Cerqueirabd15eba2005-11-08 21:37:11 -0800117static void saa7134_dma_start(struct saa7134_dev *dev)
Nickolay V. Shmyrev5f7591c2005-11-08 21:37:04 -0800118{
Ricardo Cerqueirabd15eba2005-11-08 21:37:11 -0800119 dev->oss.dma_blk = 0;
120 dev->oss.dma_running = 1;
121 saa7134_set_dmabits(dev);
Nickolay V. Shmyrev5f7591c2005-11-08 21:37:04 -0800122}
123
Ricardo Cerqueirabd15eba2005-11-08 21:37:11 -0800124void saa7134_irq_alsa_done(struct saa7134_dev *dev, unsigned long status)
Nickolay V. Shmyrev5f7591c2005-11-08 21:37:04 -0800125{
Ricardo Cerqueirabd15eba2005-11-08 21:37:11 -0800126 int next_blk, reg = 0;
127
128 spin_lock(&dev->slock);
129 if (UNSET == dev->oss.dma_blk) {
130 dprintk("irq: recording stopped\n");
131 goto done;
132 }
133 if (0 != (status & 0x0f000000))
134 dprintk("irq: lost %ld\n", (status >> 24) & 0x0f);
135 if (0 == (status & 0x10000000)) {
136 /* odd */
137 if (0 == (dev->oss.dma_blk & 0x01))
138 reg = SAA7134_RS_BA1(6);
139 } else {
140 /* even */
141 if (1 == (dev->oss.dma_blk & 0x01))
142 reg = SAA7134_RS_BA2(6);
143 }
144 if (0 == reg) {
145 dprintk("irq: field oops [%s]\n",
146 (status & 0x10000000) ? "even" : "odd");
147 goto done;
148 }
149
150 if (dev->oss.read_count >= dev->oss.blksize * (dev->oss.blocks-2)) {
151 dprintk("irq: overrun [full=%d/%d] - Blocks in %d\n",dev->oss.read_count,
152 dev->oss.bufsize, dev->oss.blocks);
153 saa7134_dma_stop(dev);
154 goto done;
155 }
156
157 /* next block addr */
158 next_blk = (dev->oss.dma_blk + 2) % dev->oss.blocks;
159 saa_writel(reg,next_blk * dev->oss.blksize);
160 if (alsa_debug > 2)
161 dprintk("irq: ok, %s, next_blk=%d, addr=%x, blocks=%u, size=%u, read=%u\n",
162 (status & 0x10000000) ? "even" : "odd ", next_blk,
163 next_blk * dev->oss.blksize, dev->oss.blocks, dev->oss.blksize, dev->oss.read_count);
164
165
166 /* update status & wake waiting readers */
167 dev->oss.dma_blk = (dev->oss.dma_blk + 1) % dev->oss.blocks;
168 dev->oss.read_count += dev->oss.blksize;
169
170 dev->oss.recording_on = reg;
171
172 if (dev->oss.read_count >= snd_pcm_lib_period_bytes(dev->oss.substream)) {
173 spin_unlock(&dev->slock);
174 snd_pcm_period_elapsed(dev->oss.substream);
175 spin_lock(&dev->slock);
176 }
177 done:
178 spin_unlock(&dev->slock);
179
Nickolay V. Shmyrev5f7591c2005-11-08 21:37:04 -0800180}
181
Nickolay V. Shmyrev5f7591c2005-11-08 21:37:04 -0800182
Ricardo Cerqueirabd15eba2005-11-08 21:37:11 -0800183static int snd_card_saa7134_capture_trigger(snd_pcm_substream_t * substream,
184 int cmd)
Nickolay V. Shmyrev5f7591c2005-11-08 21:37:04 -0800185{
186 return 0;
187}
188
Ricardo Cerqueirabd15eba2005-11-08 21:37:11 -0800189static int dsp_buffer_conf(struct saa7134_dev *dev, int blksize, int blocks)
Nickolay V. Shmyrev5f7591c2005-11-08 21:37:04 -0800190{
Ricardo Cerqueirabd15eba2005-11-08 21:37:11 -0800191 if (blksize < 0x100)
192 blksize = 0x100;
193 if (blksize > 0x10000)
194 blksize = 0x10000;
195
196 if (blocks < 2)
197 blocks = 2;
198 if ((blksize * blocks) > 1024*1024)
199 blocks = 1024*1024 / blksize;
200
201 dev->oss.blocks = blocks;
202 dev->oss.blksize = blksize;
203 dev->oss.bufsize = blksize * blocks;
204
205 dprintk("buffer config: %d blocks / %d bytes, %d kB total\n",
206 blocks,blksize,blksize * blocks / 1024);
207 return 0;
208}
209
210static int dsp_buffer_init(struct saa7134_dev *dev)
211{
212 int err;
213
214 if (!dev->oss.bufsize)
215 BUG();
216 videobuf_dma_init(&dev->oss.dma);
217 err = videobuf_dma_init_kernel(&dev->oss.dma, PCI_DMA_FROMDEVICE,
218 (dev->oss.bufsize + PAGE_SIZE) >> PAGE_SHIFT);
219 if (0 != err)
220 return err;
221 return 0;
222}
223
224
225static int snd_card_saa7134_pcm_prepare(snd_pcm_substream_t * substream)
226{
Nickolay V. Shmyrev5f7591c2005-11-08 21:37:04 -0800227 snd_pcm_runtime_t *runtime = substream->runtime;
Ricardo Cerqueirabd15eba2005-11-08 21:37:11 -0800228 int err, bswap, sign;
229 u32 fmt, control;
230 unsigned long flags;
231 snd_card_saa7134_t *saa7134 = snd_pcm_substream_chip(substream);
232 struct saa7134_dev *dev;
233 snd_card_saa7134_pcm_t *saapcm = runtime->private_data;
234 unsigned int bps;
235 unsigned long size;
236 unsigned count;
Nickolay V. Shmyrev5f7591c2005-11-08 21:37:04 -0800237
Ricardo Cerqueirabd15eba2005-11-08 21:37:11 -0800238 size = snd_pcm_lib_buffer_bytes(substream);
239 count = snd_pcm_lib_period_bytes(substream);
Nickolay V. Shmyrev5f7591c2005-11-08 21:37:04 -0800240
Ricardo Cerqueirabd15eba2005-11-08 21:37:11 -0800241 saapcm->saadev->oss.substream = substream;
242 bps = runtime->rate * runtime->channels;
243 bps *= snd_pcm_format_width(runtime->format);
244 bps /= 8;
245 if (bps <= 0)
246 return -EINVAL;
247 saapcm->pcm_bps = bps;
248 saapcm->pcm_size = snd_pcm_lib_buffer_bytes(substream);
249 saapcm->pcm_count = snd_pcm_lib_period_bytes(substream);
Nickolay V. Shmyrev5f7591c2005-11-08 21:37:04 -0800250
Nickolay V. Shmyrev5f7591c2005-11-08 21:37:04 -0800251
Ricardo Cerqueirabd15eba2005-11-08 21:37:11 -0800252 dev=saa7134->saadev;
Nickolay V. Shmyrev5f7591c2005-11-08 21:37:04 -0800253
Ricardo Cerqueirabd15eba2005-11-08 21:37:11 -0800254 dsp_buffer_conf(dev,saapcm->pcm_count,(saapcm->pcm_size/saapcm->pcm_count));
255
256 err = dsp_buffer_init(dev);
257 if (0 != err)
258 goto fail2;
259
260 /* prepare buffer */
261 if (0 != (err = videobuf_dma_pci_map(dev->pci,&dev->oss.dma)))
262 return err;
263 if (0 != (err = saa7134_pgtable_alloc(dev->pci,&dev->oss.pt)))
264 goto fail1;
265 if (0 != (err = saa7134_pgtable_build(dev->pci,&dev->oss.pt,
266 dev->oss.dma.sglist,
267 dev->oss.dma.sglen,
268 0)))
269 goto fail2;
270
271
272
273 switch (runtime->format) {
274 case SNDRV_PCM_FORMAT_U8:
275 case SNDRV_PCM_FORMAT_S8:
276 fmt = 0x00;
277 break;
278 case SNDRV_PCM_FORMAT_U16_LE:
279 case SNDRV_PCM_FORMAT_U16_BE:
280 case SNDRV_PCM_FORMAT_S16_LE:
281 case SNDRV_PCM_FORMAT_S16_BE:
282 fmt = 0x01;
283 break;
284 default:
285 err = -EINVAL;
286 return 1;
287 }
288
289 switch (runtime->format) {
290 case SNDRV_PCM_FORMAT_S8:
291 case SNDRV_PCM_FORMAT_S16_LE:
292 case SNDRV_PCM_FORMAT_S16_BE:
293 sign = 1;
294 break;
295 default:
296 sign = 0;
297 break;
298 }
299
300 switch (runtime->format) {
301 case SNDRV_PCM_FORMAT_U16_BE:
302 case SNDRV_PCM_FORMAT_S16_BE:
303 bswap = 1; break;
304 default:
305 bswap = 0; break;
306 }
307
308 switch (dev->pci->device) {
309 case PCI_DEVICE_ID_PHILIPS_SAA7134:
310 if (1 == runtime->channels)
311 fmt |= (1 << 3);
312 if (2 == runtime->channels)
313 fmt |= (3 << 3);
314 if (sign)
315 fmt |= 0x04;
316
317 fmt |= (MIXER_ADDR_TVTUNER == dev->oss.input) ? 0xc0 : 0x80;
318 saa_writeb(SAA7134_NUM_SAMPLES0, ((dev->oss.blksize - 1) & 0x0000ff));
319 saa_writeb(SAA7134_NUM_SAMPLES1, ((dev->oss.blksize - 1) & 0x00ff00) >> 8);
320 saa_writeb(SAA7134_NUM_SAMPLES2, ((dev->oss.blksize - 1) & 0xff0000) >> 16);
321 saa_writeb(SAA7134_AUDIO_FORMAT_CTRL, fmt);
322
323 break;
324 case PCI_DEVICE_ID_PHILIPS_SAA7133:
325 case PCI_DEVICE_ID_PHILIPS_SAA7135:
326 if (1 == runtime->channels)
327 fmt |= (1 << 4);
328 if (2 == runtime->channels)
329 fmt |= (2 << 4);
330 if (!sign)
331 fmt |= 0x04;
332 //saa_writel(SAA7133_NUM_SAMPLES, dev->oss.blksize -1);
333 saa_writel(SAA7133_NUM_SAMPLES, dev->oss.blksize -1);
334 saa_writel(SAA7133_AUDIO_CHANNEL, 0x543210 | (fmt << 24));
335 //saa_writel(SAA7133_AUDIO_CHANNEL, 0x543210);
336 break;
337 }
338
339 dprintk("rec_start: afmt=%d ch=%d => fmt=0x%x swap=%c\n",
340 runtime->format, runtime->channels, fmt,
341 bswap ? 'b' : '-');
342 /* dma: setup channel 6 (= AUDIO) */
343 control = SAA7134_RS_CONTROL_BURST_16 |
344 SAA7134_RS_CONTROL_ME |
345 (dev->oss.pt.dma >> 12);
346 if (bswap)
347 control |= SAA7134_RS_CONTROL_BSWAP;
348
349 runtime->dma_area = dev->oss.dma.vmalloc;
350 saa_writel(SAA7134_RS_BA1(6),0);
351 saa_writel(SAA7134_RS_BA2(6),dev->oss.blksize);
352 saa_writel(SAA7134_RS_PITCH(6),0);
353 saa_writel(SAA7134_RS_CONTROL(6),control);
354
355 dev->oss.rate = runtime->rate;
356 /* start dma */
357 spin_lock_irqsave(&dev->slock,flags);
358 saa7134_dma_start(dev);
359 spin_unlock_irqrestore(&dev->slock,flags);
360
Nickolay V. Shmyrev5f7591c2005-11-08 21:37:04 -0800361 return 0;
Ricardo Cerqueirabd15eba2005-11-08 21:37:11 -0800362 fail2:
363 saa7134_pgtable_free(dev->pci,&dev->oss.pt);
364 fail1:
365 videobuf_dma_pci_unmap(dev->pci,&dev->oss.dma);
366 return err;
Nickolay V. Shmyrev5f7591c2005-11-08 21:37:04 -0800367
Ricardo Cerqueirabd15eba2005-11-08 21:37:11 -0800368
Nickolay V. Shmyrev5f7591c2005-11-08 21:37:04 -0800369}
370
Ricardo Cerqueirabd15eba2005-11-08 21:37:11 -0800371static int snd_card_saa7134_capture_prepare(snd_pcm_substream_t * substream)
Nickolay V. Shmyrev5f7591c2005-11-08 21:37:04 -0800372{
Ricardo Cerqueirabd15eba2005-11-08 21:37:11 -0800373 return snd_card_saa7134_pcm_prepare(substream);
Nickolay V. Shmyrev5f7591c2005-11-08 21:37:04 -0800374}
375
Ricardo Cerqueirabd15eba2005-11-08 21:37:11 -0800376static snd_pcm_uframes_t snd_card_saa7134_pointer(snd_pcm_substream_t * substream)
Nickolay V. Shmyrev5f7591c2005-11-08 21:37:04 -0800377{
Ricardo Cerqueirabd15eba2005-11-08 21:37:11 -0800378 snd_pcm_runtime_t *runtime = substream->runtime;
379 snd_card_saa7134_pcm_t *saapcm = runtime->private_data;
380 struct saa7134_dev *dev=saapcm->saadev;
381
382
383
384 if (dev->oss.read_count) {
385 dev->oss.read_count -= snd_pcm_lib_period_bytes(substream);
386 dev->oss.read_offset += snd_pcm_lib_period_bytes(substream);
387 if (dev->oss.read_offset == dev->oss.bufsize)
388 dev->oss.read_offset = 0;
389 }
390
391 //return bytes_to_frames(runtime, saa_readl(dev->oss.recording_on));
392 return bytes_to_frames(runtime, dev->oss.read_offset);
393}
394
395
396static snd_pcm_uframes_t snd_card_saa7134_capture_pointer(snd_pcm_substream_t * substream)
397{
398 return snd_card_saa7134_pointer(substream);
399}
400
401static snd_pcm_hardware_t snd_card_saa7134_capture =
402{
403 .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
404 SNDRV_PCM_INFO_BLOCK_TRANSFER |
405 SNDRV_PCM_INFO_MMAP_VALID),
406 .formats = USE_FORMATS,
407 .rates = USE_RATE,
408 .rate_min = USE_RATE_MIN,
409 .rate_max = USE_RATE_MAX,
410 .channels_min = USE_CHANNELS_MIN,
411 .channels_max = USE_CHANNELS_MAX,
412 .buffer_bytes_max = MAX_BUFFER_SIZE,
413 .period_bytes_min = 64,
414 .period_bytes_max = MAX_BUFFER_SIZE,
415 .periods_min = USE_PERIODS_MIN,
416 .periods_max = USE_PERIODS_MAX,
417 .fifo_size = 0x08070503,
418};
419
420static void snd_card_saa7134_runtime_free(snd_pcm_runtime_t *runtime)
421{
422 snd_card_saa7134_pcm_t *saapcm = runtime->private_data;
423
424 kfree(saapcm);
425}
426
427
428static int snd_card_saa7134_hw_params(snd_pcm_substream_t * substream,
429 snd_pcm_hw_params_t * hw_params)
430{
431
Nickolay V. Shmyrev5f7591c2005-11-08 21:37:04 -0800432 return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params));
Ricardo Cerqueirabd15eba2005-11-08 21:37:11 -0800433
434
Nickolay V. Shmyrev5f7591c2005-11-08 21:37:04 -0800435}
436
Ricardo Cerqueirabd15eba2005-11-08 21:37:11 -0800437static int snd_card_saa7134_hw_free(snd_pcm_substream_t * substream)
Nickolay V. Shmyrev5f7591c2005-11-08 21:37:04 -0800438{
439 return snd_pcm_lib_free_pages(substream);
440}
441
Ricardo Cerqueirabd15eba2005-11-08 21:37:11 -0800442static int dsp_buffer_free(struct saa7134_dev *dev)
Nickolay V. Shmyrev5f7591c2005-11-08 21:37:04 -0800443{
Ricardo Cerqueirabd15eba2005-11-08 21:37:11 -0800444 if (!dev->oss.blksize)
445 BUG();
446
447 videobuf_dma_free(&dev->oss.dma);
448
449 dev->oss.blocks = 0;
450 dev->oss.blksize = 0;
451 dev->oss.bufsize = 0;
452
453 return 0;
454}
455
456
457static int saa7134_cap_close(struct saa7134_dev *dev)
458{
459 unsigned long flags;
460
461 /* stop dma */
462 spin_lock_irqsave(&dev->slock,flags);
463 saa7134_dma_stop(dev);
464 spin_unlock_irqrestore(&dev->slock,flags);
465
466 /* unlock buffer */
467 saa7134_pgtable_free(dev->pci,&dev->oss.pt);
468 videobuf_dma_pci_unmap(dev->pci,&dev->oss.dma);
469
470 dsp_buffer_free(dev);
471 return 0;
472}
473
474
475static int saa7134_cap_open(struct saa7134_dev *dev) {
476
477 down(&dev->oss.lock);
478
479 dev->oss.afmt = SNDRV_PCM_FORMAT_U8;
480 dev->oss.channels = 2;
481 dev->oss.read_count = 0;
482 dev->oss.read_offset = 0;
483
484 up(&dev->oss.lock);
485
Nickolay V. Shmyrev5f7591c2005-11-08 21:37:04 -0800486 return 0;
487}
488
Ricardo Cerqueirabd15eba2005-11-08 21:37:11 -0800489static int snd_card_saa7134_capture_open(snd_pcm_substream_t * substream)
Nickolay V. Shmyrev5f7591c2005-11-08 21:37:04 -0800490{
Ricardo Cerqueirabd15eba2005-11-08 21:37:11 -0800491 snd_pcm_runtime_t *runtime = substream->runtime;
492 snd_card_saa7134_pcm_t *saapcm;
493 snd_card_saa7134_t *saa7134 = snd_pcm_substream_chip(substream);
Nickolay V. Shmyrev5f7591c2005-11-08 21:37:04 -0800494 int err;
Ricardo Cerqueirabd15eba2005-11-08 21:37:11 -0800495
496 saa7134_cap_open(saa7134->saadev);
497
498 saapcm = kcalloc(1, sizeof(*saapcm), GFP_KERNEL);
499 if (saapcm == NULL)
500 return -ENOMEM;
501 saapcm->saadev=saa7134->saadev;
502
503 spin_lock_init(&saapcm->lock);
504
505 saapcm->substream = substream;
506 runtime->private_data = saapcm;
507 runtime->private_free = snd_card_saa7134_runtime_free;
508 runtime->hw = snd_card_saa7134_capture;
509
510 if ((err = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS)) < 0)
511 return err;
512
513 return 0;
514}
515
516static int snd_card_saa7134_capture_close(snd_pcm_substream_t * substream)
517{
518 snd_card_saa7134_t *chip = snd_pcm_substream_chip(substream);
519
520 saa7134_cap_close(chip->saadev);
521 return 0;
522}
523
524static snd_pcm_ops_t snd_card_saa7134_capture_ops = {
525 .open = snd_card_saa7134_capture_open,
526 .close = snd_card_saa7134_capture_close,
527 .ioctl = snd_pcm_lib_ioctl,
528 .hw_params = snd_card_saa7134_hw_params,
529 .hw_free = snd_card_saa7134_hw_free,
530 .prepare = snd_card_saa7134_capture_prepare,
531 .trigger = snd_card_saa7134_capture_trigger,
532 .pointer = snd_card_saa7134_capture_pointer,
533};
534
535static int __init snd_card_saa7134_pcm(snd_card_saa7134_t *saa7134, int device)
536{
Nickolay V. Shmyrev5f7591c2005-11-08 21:37:04 -0800537 snd_pcm_t *pcm;
Ricardo Cerqueirabd15eba2005-11-08 21:37:11 -0800538 int err;
Nickolay V. Shmyrev5f7591c2005-11-08 21:37:04 -0800539
Ricardo Cerqueirabd15eba2005-11-08 21:37:11 -0800540 if ((err = snd_pcm_new(saa7134->card, "SAA7134 PCM", device, 0, 1, &pcm)) < 0)
Nickolay V. Shmyrev5f7591c2005-11-08 21:37:04 -0800541 return err;
Ricardo Cerqueirabd15eba2005-11-08 21:37:11 -0800542 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_card_saa7134_capture_ops);
543 pcm->private_data = saa7134;
544 pcm->info_flags = 0;
545 strcpy(pcm->name, "SAA7134 PCM");
546 snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
547 snd_dma_pci_data(saa7134->pci),
548 128*1024, 256*1024);
Nickolay V. Shmyrev5f7591c2005-11-08 21:37:04 -0800549 return 0;
550}
551
Ricardo Cerqueirabd15eba2005-11-08 21:37:11 -0800552#define SAA713x_VOLUME(xname, xindex, addr) \
553{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \
554 .info = snd_saa7134_volume_info, \
555 .get = snd_saa7134_volume_get, .put = snd_saa7134_volume_put, \
556 .private_value = addr }
Nickolay V. Shmyrev5f7591c2005-11-08 21:37:04 -0800557
Ricardo Cerqueirabd15eba2005-11-08 21:37:11 -0800558static int snd_saa7134_volume_info(snd_kcontrol_t * kcontrol, snd_ctl_elem_info_t * uinfo)
559{
560 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
561 uinfo->count = 2;
562 uinfo->value.integer.min = 0;
563 uinfo->value.integer.max = 20;
Nickolay V. Shmyrev5f7591c2005-11-08 21:37:04 -0800564 return 0;
565}
566
Ricardo Cerqueirabd15eba2005-11-08 21:37:11 -0800567static int snd_saa7134_volume_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
Nickolay V. Shmyrev5f7591c2005-11-08 21:37:04 -0800568{
Ricardo Cerqueirabd15eba2005-11-08 21:37:11 -0800569 snd_card_saa7134_t *chip = snd_kcontrol_chip(kcontrol);
570 unsigned long flags;
571 int addr = kcontrol->private_value;
Nickolay V. Shmyrev5f7591c2005-11-08 21:37:04 -0800572
Ricardo Cerqueirabd15eba2005-11-08 21:37:11 -0800573 spin_lock_irqsave(&chip->mixer_lock, flags);
574 ucontrol->value.integer.value[0] = chip->mixer_volume[addr][0];
575 ucontrol->value.integer.value[1] = chip->mixer_volume[addr][1];
576 spin_unlock_irqrestore(&chip->mixer_lock, flags);
Nickolay V. Shmyrev5f7591c2005-11-08 21:37:04 -0800577 return 0;
578}
579
Ricardo Cerqueirabd15eba2005-11-08 21:37:11 -0800580static int snd_saa7134_volume_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
581{
582 snd_card_saa7134_t *chip = snd_kcontrol_chip(kcontrol);
583 unsigned long flags;
584 int change, addr = kcontrol->private_value;
585 int left, right;
586
587 left = ucontrol->value.integer.value[0];
588 if (left < 0)
589 left = 0;
590 if (left > 20)
591 left = 20;
592 right = ucontrol->value.integer.value[1];
593 if (right < 0)
594 right = 0;
595 if (right > 20)
596 right = 20;
597 spin_lock_irqsave(&chip->mixer_lock, flags);
598 change = chip->mixer_volume[addr][0] != left ||
599 chip->mixer_volume[addr][1] != right;
600 chip->mixer_volume[addr][0] = left;
601 chip->mixer_volume[addr][1] = right;
602 spin_unlock_irqrestore(&chip->mixer_lock, flags);
603 return change;
604}
605
606#define SAA713x_CAPSRC(xname, xindex, addr) \
607{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \
608 .info = snd_saa7134_capsrc_info, \
609 .get = snd_saa7134_capsrc_get, .put = snd_saa7134_capsrc_put, \
610 .private_value = addr }
611
612static int snd_saa7134_capsrc_info(snd_kcontrol_t * kcontrol, snd_ctl_elem_info_t * uinfo)
613{
614 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
615 uinfo->count = 1;
616 uinfo->value.integer.min = 0;
617 uinfo->value.integer.max = 1;
618 return 0;
619}
620
621static int snd_saa7134_capsrc_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
622{
623 snd_card_saa7134_t *chip = snd_kcontrol_chip(kcontrol);
624 unsigned long flags;
625 int addr = kcontrol->private_value;
626
627 spin_lock_irqsave(&chip->mixer_lock, flags);
628 ucontrol->value.integer.value[0] = chip->capture_source[addr][0];
629 ucontrol->value.integer.value[1] = chip->capture_source[addr][1];
630 spin_unlock_irqrestore(&chip->mixer_lock, flags);
631 return 0;
632}
633
634static int snd_saa7134_capsrc_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
635{
636 snd_card_saa7134_t *chip = snd_kcontrol_chip(kcontrol);
637 unsigned long flags;
638 int change, addr = kcontrol->private_value;
639 int left, right;
640 u32 anabar, xbarin;
641 int analog_io, rate;
642 struct saa7134_dev *dev;
643
644 dev = chip->saadev;
645
646 left = ucontrol->value.integer.value[0] & 1;
647 right = ucontrol->value.integer.value[1] & 1;
648 spin_lock_irqsave(&chip->mixer_lock, flags);
649
650 change = chip->capture_source[addr][0] != left &&
651 chip->capture_source[addr][1] != right;
652 chip->capture_source[addr][0] = left;
653 chip->capture_source[addr][1] = right;
654 dev->oss.input=addr;
655 spin_unlock_irqrestore(&chip->mixer_lock, flags);
656
657
658 switch (dev->pci->device) {
659
660 case PCI_DEVICE_ID_PHILIPS_SAA7134:
661 switch (addr) {
662 case MIXER_ADDR_TVTUNER:
663 saa_andorb(SAA7134_AUDIO_FORMAT_CTRL, 0xc0, 0xc0);
664 saa_andorb(SAA7134_SIF_SAMPLE_FREQ, 0x03, 0x00);
665 break;
666 case MIXER_ADDR_LINE1:
667 case MIXER_ADDR_LINE2:
668 analog_io = (MIXER_ADDR_LINE1 == addr) ? 0x00 : 0x08;
669 rate = (32000 == dev->oss.rate) ? 0x01 : 0x03;
670 saa_andorb(SAA7134_ANALOG_IO_SELECT, 0x08, analog_io);
671 saa_andorb(SAA7134_AUDIO_FORMAT_CTRL, 0xc0, 0x80);
672 saa_andorb(SAA7134_SIF_SAMPLE_FREQ, 0x03, rate);
673 break;
674 }
675
676 case PCI_DEVICE_ID_PHILIPS_SAA7133:
677 case PCI_DEVICE_ID_PHILIPS_SAA7135:
678 xbarin = 0x03; // adc
679 anabar = 0;
680 switch (addr) {
681 case MIXER_ADDR_TVTUNER:
682 xbarin = 0; // Demodulator
683 anabar = 2; // DACs
684 break;
685 case MIXER_ADDR_LINE1:
686 anabar = 0; // aux1, aux1
687 break;
688 case MIXER_ADDR_LINE2:
689 anabar = 9; // aux2, aux2
690 break;
691 }
692
693 /* output xbar always main channel */
694 saa_dsp_writel(dev, SAA7133_DIGITAL_OUTPUT_SEL1, 0xbbbb10);
695
696 if (left || right) { // We've got data, turn the input on
697 //saa_dsp_writel(dev, SAA7133_DIGITAL_OUTPUT_SEL2, 0x101010);
698 saa_dsp_writel(dev, SAA7133_DIGITAL_INPUT_XBAR1, xbarin);
699 saa_writel(SAA7133_ANALOG_IO_SELECT, anabar);
700 } else {
701 //saa_dsp_writel(dev, SAA7133_DIGITAL_OUTPUT_SEL2, 0x101010);
702 saa_dsp_writel(dev, SAA7133_DIGITAL_INPUT_XBAR1, 0);
703 saa_writel(SAA7133_ANALOG_IO_SELECT, 0);
704 }
705 }
706
707 return change;
708}
709
710static snd_kcontrol_new_t snd_saa7134_controls[] = {
711SAA713x_VOLUME("Video Volume", 0, MIXER_ADDR_TVTUNER),
712SAA713x_CAPSRC("Video Capture Switch", 0, MIXER_ADDR_TVTUNER),
713SAA713x_VOLUME("Line Volume", 1, MIXER_ADDR_LINE1),
714SAA713x_CAPSRC("Line Capture Switch", 1, MIXER_ADDR_LINE1),
715SAA713x_VOLUME("Line Volume", 2, MIXER_ADDR_LINE2),
716SAA713x_CAPSRC("Line Capture Switch", 2, MIXER_ADDR_LINE2),
Nickolay V. Shmyrev5f7591c2005-11-08 21:37:04 -0800717};
718
Ricardo Cerqueirabd15eba2005-11-08 21:37:11 -0800719static int __init snd_card_saa7134_new_mixer(snd_card_saa7134_t * chip)
Nickolay V. Shmyrev5f7591c2005-11-08 21:37:04 -0800720{
Ricardo Cerqueirabd15eba2005-11-08 21:37:11 -0800721 snd_card_t *card = chip->card;
722 unsigned int idx;
723 int err;
Nickolay V. Shmyrev5f7591c2005-11-08 21:37:04 -0800724
Ricardo Cerqueirabd15eba2005-11-08 21:37:11 -0800725 snd_assert(chip != NULL, return -EINVAL);
726 strcpy(card->mixername, "SAA7134 Mixer");
Nickolay V. Shmyrev5f7591c2005-11-08 21:37:04 -0800727
Ricardo Cerqueirabd15eba2005-11-08 21:37:11 -0800728 for (idx = 0; idx < ARRAY_SIZE(snd_saa7134_controls); idx++) {
729 if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_saa7134_controls[idx], chip))) < 0)
730 return err;
731 }
Nickolay V. Shmyrev5f7591c2005-11-08 21:37:04 -0800732 return 0;
733}
734
Ricardo Cerqueirabd15eba2005-11-08 21:37:11 -0800735static int snd_saa7134_free(snd_card_saa7134_t *chip)
736{
737 return 0;
738}
739
Nickolay V. Shmyrev5f7591c2005-11-08 21:37:04 -0800740static int snd_saa7134_dev_free(snd_device_t *device)
741{
Ricardo Cerqueirabd15eba2005-11-08 21:37:11 -0800742 snd_card_saa7134_t *chip = device->device_data;
743 return snd_saa7134_free(chip);
Nickolay V. Shmyrev5f7591c2005-11-08 21:37:04 -0800744}
745
Ricardo Cerqueirabd15eba2005-11-08 21:37:11 -0800746int alsa_card_saa7134_create(struct saa7134_dev *saadev)
Nickolay V. Shmyrev5f7591c2005-11-08 21:37:04 -0800747{
Ricardo Cerqueirabd15eba2005-11-08 21:37:11 -0800748 static int dev;
749 snd_card_t *card;
750 struct snd_card_saa7134 *chip;
751 int err;
752 static snd_device_ops_t ops = {
753 .dev_free = snd_saa7134_dev_free,
754 };
Nickolay V. Shmyrev5f7591c2005-11-08 21:37:04 -0800755
Ricardo Cerqueirabd15eba2005-11-08 21:37:11 -0800756 if (dev >= SNDRV_CARDS)
757 return -ENODEV;
758 if (!enable[dev])
759 return -ENODEV;
760 card = snd_card_new(index[dev], id[dev], THIS_MODULE,
761 sizeof(struct snd_card_saa7134));
762 if (card == NULL)
763 return -ENOMEM;
Nickolay V. Shmyrev5f7591c2005-11-08 21:37:04 -0800764
Ricardo Cerqueirabd15eba2005-11-08 21:37:11 -0800765 strcpy(card->driver, "SAA7134");
Nickolay V. Shmyrev5f7591c2005-11-08 21:37:04 -0800766
Ricardo Cerqueirabd15eba2005-11-08 21:37:11 -0800767 /* Card "creation" */
768 chip = kcalloc(1, sizeof(*chip), GFP_KERNEL);
769 if (chip == NULL) {
770 return -ENOMEM;
771 }
772
773 spin_lock_init(&chip->lock);
774
775 chip->saadev = saadev;
776
777 chip->card = card;
778 chip->pci = saadev->pci;
779 chip->irq = saadev->pci->irq;
780 chip->iobase = pci_resource_start(saadev->pci, 0);
781
782 if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0) {
783 snd_saa7134_free(chip);
784 return err;
785 }
786
787
788 if ((err = snd_card_saa7134_new_mixer(chip)) < 0)
789 goto __nodev;
790
791 if ((err = snd_card_saa7134_pcm(chip, 0)) < 0)
792 goto __nodev;
793 spin_lock_init(&chip->mixer_lock);
794
795 snd_card_set_dev(card, &chip->pci->dev);
796
797 /* End of "creation" */
798
799 strcpy(card->shortname, "SAA7134");
800 sprintf(card->longname, "%s at 0x%lx irq %d",
801 card->shortname, chip->iobase, chip->irq);
802
803
804 if ((err = snd_card_register(card)) == 0) {
805 snd_saa7134_cards[dev] = card;
806 return 0;
Nickolay V. Shmyrev5f7591c2005-11-08 21:37:04 -0800807 }
808
Ricardo Cerqueirabd15eba2005-11-08 21:37:11 -0800809__nodev:
810 snd_card_free(card);
811 kfree(card);
812 return err;
813}
Nickolay V. Shmyrev5f7591c2005-11-08 21:37:04 -0800814
Ricardo Cerqueirabd15eba2005-11-08 21:37:11 -0800815void alsa_card_saa7134_exit(void)
816{
817 int idx;
818 for (idx = 0; idx < SNDRV_CARDS; idx++) {
819 snd_card_free(snd_saa7134_cards[idx]);
Nickolay V. Shmyrev5f7591c2005-11-08 21:37:04 -0800820 }
Nickolay V. Shmyrev5f7591c2005-11-08 21:37:04 -0800821}