aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMijhail Moreyra <mijhail.moreyra@gmail.com>2011-10-10 10:09:52 -0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2011-10-14 15:44:54 -0400
commit9e44d63246a9c884900e56e2aa16fba94dee5f0c (patch)
treeec804ca3a11d9eba24972aa646945685cb52b62d
parent873c07da6abd5519a7850caa90f226d3b15e3fba (diff)
[media] cx23885: Add ALSA support
[stoth@kernellabs.com: add it to the makefile and fix snd_card binding] [liplianin@netup.ru: videobuf: Remove the videobuf_sg_dma_map/unmap functions] Signed-off-by: Mijhail Moreyra <mijhail.moreyra@gmail.com> Signed-off-by: Steven Toth <stoth@kernellabs.com> Signed-off-by: Igor M. Liplianin <liplianin@netup.ru> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
-rw-r--r--drivers/media/video/cx23885/Makefile2
-rw-r--r--drivers/media/video/cx23885/cx23885-alsa.c535
-rw-r--r--drivers/media/video/cx23885/cx23885-core.c48
-rw-r--r--drivers/media/video/cx23885/cx23885.h42
4 files changed, 611 insertions, 16 deletions
diff --git a/drivers/media/video/cx23885/Makefile b/drivers/media/video/cx23885/Makefile
index 185cc019d3db..f81f2796a0f9 100644
--- a/drivers/media/video/cx23885/Makefile
+++ b/drivers/media/video/cx23885/Makefile
@@ -2,7 +2,7 @@ cx23885-objs := cx23885-cards.o cx23885-video.o cx23885-vbi.o \
2 cx23885-core.o cx23885-i2c.o cx23885-dvb.o cx23885-417.o \ 2 cx23885-core.o cx23885-i2c.o cx23885-dvb.o cx23885-417.o \
3 cx23885-ioctl.o cx23885-ir.o cx23885-av.o cx23885-input.o \ 3 cx23885-ioctl.o cx23885-ir.o cx23885-av.o cx23885-input.o \
4 cx23888-ir.o netup-init.o cimax2.o netup-eeprom.o \ 4 cx23888-ir.o netup-init.o cimax2.o netup-eeprom.o \
5 cx23885-f300.o 5 cx23885-f300.o cx23885-alsa.o
6 6
7obj-$(CONFIG_VIDEO_CX23885) += cx23885.o 7obj-$(CONFIG_VIDEO_CX23885) += cx23885.o
8obj-$(CONFIG_MEDIA_ALTERA_CI) += altera-ci.o 8obj-$(CONFIG_MEDIA_ALTERA_CI) += altera-ci.o
diff --git a/drivers/media/video/cx23885/cx23885-alsa.c b/drivers/media/video/cx23885/cx23885-alsa.c
new file mode 100644
index 000000000000..31a89b3ac1d0
--- /dev/null
+++ b/drivers/media/video/cx23885/cx23885-alsa.c
@@ -0,0 +1,535 @@
1/*
2 *
3 * Support for CX23885 analog audio capture
4 *
5 * (c) 2008 Mijhail Moreyra <mijhail.moreyra@gmail.com>
6 * Adapted from cx88-alsa.c
7 * (c) 2009 Steven Toth <stoth@kernellabs.com>
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
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. See the
17 * GNU General Public License for more details.
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., 675 Mass Ave, Cambridge, MA 02139, USA.
22 */
23
24#include <linux/module.h>
25#include <linux/init.h>
26#include <linux/device.h>
27#include <linux/interrupt.h>
28#include <linux/vmalloc.h>
29#include <linux/dma-mapping.h>
30#include <linux/pci.h>
31
32#include <asm/delay.h>
33
34#include <sound/core.h>
35#include <sound/pcm.h>
36#include <sound/pcm_params.h>
37#include <sound/control.h>
38#include <sound/initval.h>
39
40#include <sound/tlv.h>
41
42
43#include "cx23885.h"
44#include "cx23885-reg.h"
45
46#define AUDIO_SRAM_CHANNEL SRAM_CH07
47
48#define dprintk(level, fmt, arg...) if (audio_debug >= level) \
49 printk(KERN_INFO "%s/1: " fmt, chip->dev->name , ## arg)
50
51#define dprintk_core(level, fmt, arg...) if (audio_debug >= level) \
52 printk(KERN_DEBUG "%s/1: " fmt, chip->dev->name , ## arg)
53
54/****************************************************************************
55 Module global static vars
56 ****************************************************************************/
57
58static unsigned int disable_analog_audio;
59module_param(disable_analog_audio, int, 0644);
60MODULE_PARM_DESC(disable_analog_audio, "disable analog audio ALSA driver");
61
62static unsigned int audio_debug;
63module_param(audio_debug, int, 0644);
64MODULE_PARM_DESC(audio_debug, "enable debug messages [analog audio]");
65
66/****************************************************************************
67 Board specific funtions
68 ****************************************************************************/
69
70/* Constants taken from cx88-reg.h */
71#define AUD_INT_DN_RISCI1 (1 << 0)
72#define AUD_INT_UP_RISCI1 (1 << 1)
73#define AUD_INT_RDS_DN_RISCI1 (1 << 2)
74#define AUD_INT_DN_RISCI2 (1 << 4) /* yes, 3 is skipped */
75#define AUD_INT_UP_RISCI2 (1 << 5)
76#define AUD_INT_RDS_DN_RISCI2 (1 << 6)
77#define AUD_INT_DN_SYNC (1 << 12)
78#define AUD_INT_UP_SYNC (1 << 13)
79#define AUD_INT_RDS_DN_SYNC (1 << 14)
80#define AUD_INT_OPC_ERR (1 << 16)
81#define AUD_INT_BER_IRQ (1 << 20)
82#define AUD_INT_MCHG_IRQ (1 << 21)
83#define GP_COUNT_CONTROL_RESET 0x3
84
85/*
86 * BOARD Specific: Sets audio DMA
87 */
88
89static int cx23885_start_audio_dma(struct cx23885_audio_dev *chip)
90{
91 struct cx23885_audio_buffer *buf = chip->buf;
92 struct cx23885_dev *dev = chip->dev;
93 struct sram_channel *audio_ch =
94 &dev->sram_channels[AUDIO_SRAM_CHANNEL];
95
96 dprintk(1, "%s()\n", __func__);
97
98 /* Make sure RISC/FIFO are off before changing FIFO/RISC settings */
99 cx_clear(AUD_INT_DMA_CTL, 0x11);
100
101 /* setup fifo + format - out channel */
102 cx23885_sram_channel_setup(chip->dev, audio_ch, buf->bpl,
103 buf->risc.dma);
104
105 /* sets bpl size */
106 cx_write(AUD_INT_A_LNGTH, buf->bpl);
107
108 /* This is required to get good audio (1 seems to be ok) */
109 cx_write(AUD_INT_A_MODE, 1);
110
111 /* reset counter */
112 cx_write(AUD_INT_A_GPCNT_CTL, GP_COUNT_CONTROL_RESET);
113 atomic_set(&chip->count, 0);
114
115 dprintk(1, "Start audio DMA, %d B/line, %d lines/FIFO, %d periods, %d "
116 "byte buffer\n", buf->bpl, cx_read(audio_ch->cmds_start+12)>>1,
117 chip->num_periods, buf->bpl * chip->num_periods);
118
119 /* Enables corresponding bits at AUD_INT_STAT */
120 cx_write(AUDIO_INT_INT_MSK, AUD_INT_OPC_ERR | AUD_INT_DN_SYNC |
121 AUD_INT_DN_RISCI1);
122
123 /* Clean any pending interrupt bits already set */
124 cx_write(AUDIO_INT_INT_STAT, ~0);
125
126 /* enable audio irqs */
127 cx_set(PCI_INT_MSK, chip->dev->pci_irqmask | PCI_MSK_AUD_INT);
128
129 /* start dma */
130 cx_set(DEV_CNTRL2, (1<<5)); /* Enables Risc Processor */
131 cx_set(AUD_INT_DMA_CTL, 0x11); /* audio downstream FIFO and
132 RISC enable */
133 if (audio_debug)
134 cx23885_sram_channel_dump(chip->dev, audio_ch);
135
136 return 0;
137}
138
139/*
140 * BOARD Specific: Resets audio DMA
141 */
142static int cx23885_stop_audio_dma(struct cx23885_audio_dev *chip)
143{
144 struct cx23885_dev *dev = chip->dev;
145 dprintk(1, "Stopping audio DMA\n");
146
147 /* stop dma */
148 cx_clear(AUD_INT_DMA_CTL, 0x11);
149
150 /* disable irqs */
151 cx_clear(PCI_INT_MSK, PCI_MSK_AUD_INT);
152 cx_clear(AUDIO_INT_INT_MSK, AUD_INT_OPC_ERR | AUD_INT_DN_SYNC |
153 AUD_INT_DN_RISCI1);
154
155 if (audio_debug)
156 cx23885_sram_channel_dump(chip->dev,
157 &dev->sram_channels[AUDIO_SRAM_CHANNEL]);
158
159 return 0;
160}
161
162/*
163 * BOARD Specific: Handles audio IRQ
164 */
165int cx23885_audio_irq(struct cx23885_dev *dev, u32 status, u32 mask)
166{
167 struct cx23885_audio_dev *chip = dev->audio_dev;
168
169 if (0 == (status & mask))
170 return 0;
171
172 cx_write(AUDIO_INT_INT_STAT, status);
173
174 /* risc op code error */
175 if (status & AUD_INT_OPC_ERR) {
176 printk(KERN_WARNING "%s/1: Audio risc op code error\n",
177 dev->name);
178 cx_clear(AUD_INT_DMA_CTL, 0x11);
179 cx23885_sram_channel_dump(dev,
180 &dev->sram_channels[AUDIO_SRAM_CHANNEL]);
181 }
182 if (status & AUD_INT_DN_SYNC) {
183 dprintk(1, "Downstream sync error\n");
184 cx_write(AUD_INT_A_GPCNT_CTL, GP_COUNT_CONTROL_RESET);
185 return 1;
186 }
187 /* risc1 downstream */
188 if (status & AUD_INT_DN_RISCI1) {
189 atomic_set(&chip->count, cx_read(AUD_INT_A_GPCNT));
190 snd_pcm_period_elapsed(chip->substream);
191 }
192 /* FIXME: Any other status should deserve a special handling? */
193
194 return 1;
195}
196
197static int dsp_buffer_free(struct cx23885_audio_dev *chip)
198{
199 BUG_ON(!chip->dma_size);
200
201 dprintk(2, "Freeing buffer\n");
202 videobuf_dma_unmap(&chip->pci->dev, chip->dma_risc);
203 videobuf_dma_free(chip->dma_risc);
204 btcx_riscmem_free(chip->pci, &chip->buf->risc);
205 kfree(chip->buf);
206
207 chip->dma_risc = NULL;
208 chip->dma_size = 0;
209
210 return 0;
211}
212
213/****************************************************************************
214 ALSA PCM Interface
215 ****************************************************************************/
216
217/*
218 * Digital hardware definition
219 */
220#define DEFAULT_FIFO_SIZE 4096
221
222static struct snd_pcm_hardware snd_cx23885_digital_hw = {
223 .info = SNDRV_PCM_INFO_MMAP |
224 SNDRV_PCM_INFO_INTERLEAVED |
225 SNDRV_PCM_INFO_BLOCK_TRANSFER |
226 SNDRV_PCM_INFO_MMAP_VALID,
227 .formats = SNDRV_PCM_FMTBIT_S16_LE,
228
229 .rates = SNDRV_PCM_RATE_48000,
230 .rate_min = 48000,
231 .rate_max = 48000,
232 .channels_min = 2,
233 .channels_max = 2,
234 /* Analog audio output will be full of clicks and pops if there
235 are not exactly four lines in the SRAM FIFO buffer. */
236 .period_bytes_min = DEFAULT_FIFO_SIZE/4,
237 .period_bytes_max = DEFAULT_FIFO_SIZE/4,
238 .periods_min = 1,
239 .periods_max = 1024,
240 .buffer_bytes_max = (1024*1024),
241};
242
243/*
244 * audio pcm capture open callback
245 */
246static int snd_cx23885_pcm_open(struct snd_pcm_substream *substream)
247{
248 struct cx23885_audio_dev *chip = snd_pcm_substream_chip(substream);
249 struct snd_pcm_runtime *runtime = substream->runtime;
250 int err;
251
252 if (!chip) {
253 printk(KERN_ERR "BUG: cx23885 can't find device struct."
254 " Can't proceed with open\n");
255 return -ENODEV;
256 }
257
258 err = snd_pcm_hw_constraint_pow2(runtime, 0,
259 SNDRV_PCM_HW_PARAM_PERIODS);
260 if (err < 0)
261 goto _error;
262
263 chip->substream = substream;
264
265 runtime->hw = snd_cx23885_digital_hw;
266
267 if (chip->dev->sram_channels[AUDIO_SRAM_CHANNEL].fifo_size !=
268 DEFAULT_FIFO_SIZE) {
269 unsigned int bpl = chip->dev->
270 sram_channels[AUDIO_SRAM_CHANNEL].fifo_size / 4;
271 bpl &= ~7; /* must be multiple of 8 */
272 runtime->hw.period_bytes_min = bpl;
273 runtime->hw.period_bytes_max = bpl;
274 }
275
276 return 0;
277_error:
278 dprintk(1, "Error opening PCM!\n");
279 return err;
280}
281
282/*
283 * audio close callback
284 */
285static int snd_cx23885_close(struct snd_pcm_substream *substream)
286{
287 return 0;
288}
289
290/*
291 * hw_params callback
292 */
293static int snd_cx23885_hw_params(struct snd_pcm_substream *substream,
294 struct snd_pcm_hw_params *hw_params)
295{
296 struct cx23885_audio_dev *chip = snd_pcm_substream_chip(substream);
297 struct videobuf_dmabuf *dma;
298
299 struct cx23885_audio_buffer *buf;
300 int ret;
301
302 if (substream->runtime->dma_area) {
303 dsp_buffer_free(chip);
304 substream->runtime->dma_area = NULL;
305 }
306
307 chip->period_size = params_period_bytes(hw_params);
308 chip->num_periods = params_periods(hw_params);
309 chip->dma_size = chip->period_size * params_periods(hw_params);
310
311 BUG_ON(!chip->dma_size);
312 BUG_ON(chip->num_periods & (chip->num_periods-1));
313
314 buf = kzalloc(sizeof(*buf), GFP_KERNEL);
315 if (NULL == buf)
316 return -ENOMEM;
317
318 buf->bpl = chip->period_size;
319
320 dma = &buf->dma;
321 videobuf_dma_init(dma);
322 ret = videobuf_dma_init_kernel(dma, PCI_DMA_FROMDEVICE,
323 (PAGE_ALIGN(chip->dma_size) >> PAGE_SHIFT));
324 if (ret < 0)
325 goto error;
326
327 ret = videobuf_dma_map(&chip->pci->dev, dma);
328 if (ret < 0)
329 goto error;
330
331 ret = cx23885_risc_databuffer(chip->pci, &buf->risc, dma->sglist,
332 chip->period_size, chip->num_periods, 1);
333 if (ret < 0)
334 goto error;
335
336 /* Loop back to start of program */
337 buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP|RISC_IRQ1|RISC_CNT_INC);
338 buf->risc.jmp[1] = cpu_to_le32(buf->risc.dma);
339 buf->risc.jmp[2] = cpu_to_le32(0); /* bits 63-32 */
340
341 chip->buf = buf;
342 chip->dma_risc = dma;
343
344 substream->runtime->dma_area = chip->dma_risc->vaddr;
345 substream->runtime->dma_bytes = chip->dma_size;
346 substream->runtime->dma_addr = 0;
347
348 return 0;
349
350error:
351 kfree(buf);
352 return ret;
353}
354
355/*
356 * hw free callback
357 */
358static int snd_cx23885_hw_free(struct snd_pcm_substream *substream)
359{
360
361 struct cx23885_audio_dev *chip = snd_pcm_substream_chip(substream);
362
363 if (substream->runtime->dma_area) {
364 dsp_buffer_free(chip);
365 substream->runtime->dma_area = NULL;
366 }
367
368 return 0;
369}
370
371/*
372 * prepare callback
373 */
374static int snd_cx23885_prepare(struct snd_pcm_substream *substream)
375{
376 return 0;
377}
378
379/*
380 * trigger callback
381 */
382static int snd_cx23885_card_trigger(struct snd_pcm_substream *substream,
383 int cmd)
384{
385 struct cx23885_audio_dev *chip = snd_pcm_substream_chip(substream);
386 int err;
387
388 /* Local interrupts are already disabled by ALSA */
389 spin_lock(&chip->lock);
390
391 switch (cmd) {
392 case SNDRV_PCM_TRIGGER_START:
393 err = cx23885_start_audio_dma(chip);
394 break;
395 case SNDRV_PCM_TRIGGER_STOP:
396 err = cx23885_stop_audio_dma(chip);
397 break;
398 default:
399 err = -EINVAL;
400 break;
401 }
402
403 spin_unlock(&chip->lock);
404
405 return err;
406}
407
408/*
409 * pointer callback
410 */
411static snd_pcm_uframes_t snd_cx23885_pointer(
412 struct snd_pcm_substream *substream)
413{
414 struct cx23885_audio_dev *chip = snd_pcm_substream_chip(substream);
415 struct snd_pcm_runtime *runtime = substream->runtime;
416 u16 count;
417
418 count = atomic_read(&chip->count);
419
420 return runtime->period_size * (count & (runtime->periods-1));
421}
422
423/*
424 * page callback (needed for mmap)
425 */
426static struct page *snd_cx23885_page(struct snd_pcm_substream *substream,
427 unsigned long offset)
428{
429 void *pageptr = substream->runtime->dma_area + offset;
430 return vmalloc_to_page(pageptr);
431}
432
433/*
434 * operators
435 */
436static struct snd_pcm_ops snd_cx23885_pcm_ops = {
437 .open = snd_cx23885_pcm_open,
438 .close = snd_cx23885_close,
439 .ioctl = snd_pcm_lib_ioctl,
440 .hw_params = snd_cx23885_hw_params,
441 .hw_free = snd_cx23885_hw_free,
442 .prepare = snd_cx23885_prepare,
443 .trigger = snd_cx23885_card_trigger,
444 .pointer = snd_cx23885_pointer,
445 .page = snd_cx23885_page,
446};
447
448/*
449 * create a PCM device
450 */
451static int snd_cx23885_pcm(struct cx23885_audio_dev *chip, int device,
452 char *name)
453{
454 int err;
455 struct snd_pcm *pcm;
456
457 err = snd_pcm_new(chip->card, name, device, 0, 1, &pcm);
458 if (err < 0)
459 return err;
460 pcm->private_data = chip;
461 strcpy(pcm->name, name);
462 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_cx23885_pcm_ops);
463
464 return 0;
465}
466
467/****************************************************************************
468 Basic Flow for Sound Devices
469 ****************************************************************************/
470
471/*
472 * Alsa Constructor - Component probe
473 */
474
475struct cx23885_audio_dev *cx23885_audio_initdev(struct cx23885_dev *dev)
476{
477 struct snd_card *card;
478 struct cx23885_audio_dev *chip;
479 int err;
480
481 if (disable_analog_audio)
482 return NULL;
483
484 if (dev->sram_channels[AUDIO_SRAM_CHANNEL].cmds_start == 0) {
485 printk(KERN_WARNING "%s(): Missing SRAM channel configuration "
486 "for analog TV Audio\n", __func__);
487 return NULL;
488 }
489
490 err = snd_card_create(SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1,
491 THIS_MODULE, sizeof(struct cx23885_audio_dev), &card);
492 if (err < 0)
493 goto error;
494
495 chip = (struct cx23885_audio_dev *) card->private_data;
496 chip->dev = dev;
497 chip->pci = dev->pci;
498 chip->card = card;
499 spin_lock_init(&chip->lock);
500
501 snd_card_set_dev(card, &dev->pci->dev);
502
503 err = snd_cx23885_pcm(chip, 0, "CX23885 Digital");
504 if (err < 0)
505 goto error;
506
507 strcpy(card->driver, "CX23885");
508 sprintf(card->shortname, "Conexant CX23885");
509 sprintf(card->longname, "%s at %s", card->shortname, dev->name);
510
511 err = snd_card_register(card);
512 if (err < 0)
513 goto error;
514
515 dprintk(0, "registered ALSA audio device\n");
516
517 return chip;
518
519error:
520 snd_card_free(card);
521 printk(KERN_ERR "%s(): Failed to register analog "
522 "audio adapter\n", __func__);
523
524 return NULL;
525}
526
527/*
528 * ALSA destructor
529 */
530void cx23885_audio_finidev(struct cx23885_dev *dev)
531{
532 struct cx23885_audio_dev *chip = dev->audio_dev;
533
534 snd_card_free(chip->card);
535}
diff --git a/drivers/media/video/cx23885/cx23885-core.c b/drivers/media/video/cx23885/cx23885-core.c
index ee41a8882f58..d8dfa40b4af9 100644
--- a/drivers/media/video/cx23885/cx23885-core.c
+++ b/drivers/media/video/cx23885/cx23885-core.c
@@ -156,11 +156,12 @@ static struct sram_channel cx23885_sram_channels[] = {
156 }, 156 },
157 [SRAM_CH07] = { 157 [SRAM_CH07] = {
158 .name = "ch7", 158 .name = "ch7",
159 .cmds_start = 0x0, 159 .name = "TV Audio",
160 .ctrl_start = 0x0, 160 .cmds_start = 0x10190,
161 .cdt = 0x0, 161 .ctrl_start = 0x10480,
162 .fifo_start = 0x0, 162 .cdt = 0x10a00,
163 .fifo_size = 0x0, 163 .fifo_start = 0x7000,
164 .fifo_size = 0x1000,
164 .ptr1_reg = DMA6_PTR1, 165 .ptr1_reg = DMA6_PTR1,
165 .ptr2_reg = DMA6_PTR2, 166 .ptr2_reg = DMA6_PTR2,
166 .cnt1_reg = DMA6_CNT1, 167 .cnt1_reg = DMA6_CNT1,
@@ -1082,10 +1083,10 @@ static void cx23885_dev_unregister(struct cx23885_dev *dev)
1082static __le32 *cx23885_risc_field(__le32 *rp, struct scatterlist *sglist, 1083static __le32 *cx23885_risc_field(__le32 *rp, struct scatterlist *sglist,
1083 unsigned int offset, u32 sync_line, 1084 unsigned int offset, u32 sync_line,
1084 unsigned int bpl, unsigned int padding, 1085 unsigned int bpl, unsigned int padding,
1085 unsigned int lines) 1086 unsigned int lines, unsigned int lpi)
1086{ 1087{
1087 struct scatterlist *sg; 1088 struct scatterlist *sg;
1088 unsigned int line, todo; 1089 unsigned int line, todo, sol;
1089 1090
1090 /* sync instruction */ 1091 /* sync instruction */
1091 if (sync_line != NO_SYNC_LINE) 1092 if (sync_line != NO_SYNC_LINE)
@@ -1098,16 +1099,22 @@ static __le32 *cx23885_risc_field(__le32 *rp, struct scatterlist *sglist,
1098 offset -= sg_dma_len(sg); 1099 offset -= sg_dma_len(sg);
1099 sg++; 1100 sg++;
1100 } 1101 }
1102
1103 if (lpi && line > 0 && !(line % lpi))
1104 sol = RISC_SOL | RISC_IRQ1 | RISC_CNT_INC;
1105 else
1106 sol = RISC_SOL;
1107
1101 if (bpl <= sg_dma_len(sg)-offset) { 1108 if (bpl <= sg_dma_len(sg)-offset) {
1102 /* fits into current chunk */ 1109 /* fits into current chunk */
1103 *(rp++) = cpu_to_le32(RISC_WRITE|RISC_SOL|RISC_EOL|bpl); 1110 *(rp++) = cpu_to_le32(RISC_WRITE|sol|RISC_EOL|bpl);
1104 *(rp++) = cpu_to_le32(sg_dma_address(sg)+offset); 1111 *(rp++) = cpu_to_le32(sg_dma_address(sg)+offset);
1105 *(rp++) = cpu_to_le32(0); /* bits 63-32 */ 1112 *(rp++) = cpu_to_le32(0); /* bits 63-32 */
1106 offset += bpl; 1113 offset += bpl;
1107 } else { 1114 } else {
1108 /* scanline needs to be split */ 1115 /* scanline needs to be split */
1109 todo = bpl; 1116 todo = bpl;
1110 *(rp++) = cpu_to_le32(RISC_WRITE|RISC_SOL| 1117 *(rp++) = cpu_to_le32(RISC_WRITE|sol|
1111 (sg_dma_len(sg)-offset)); 1118 (sg_dma_len(sg)-offset));
1112 *(rp++) = cpu_to_le32(sg_dma_address(sg)+offset); 1119 *(rp++) = cpu_to_le32(sg_dma_address(sg)+offset);
1113 *(rp++) = cpu_to_le32(0); /* bits 63-32 */ 1120 *(rp++) = cpu_to_le32(0); /* bits 63-32 */
@@ -1164,10 +1171,10 @@ int cx23885_risc_buffer(struct pci_dev *pci, struct btcx_riscmem *risc,
1164 rp = risc->cpu; 1171 rp = risc->cpu;
1165 if (UNSET != top_offset) 1172 if (UNSET != top_offset)
1166 rp = cx23885_risc_field(rp, sglist, top_offset, 0, 1173 rp = cx23885_risc_field(rp, sglist, top_offset, 0,
1167 bpl, padding, lines); 1174 bpl, padding, lines, 0);
1168 if (UNSET != bottom_offset) 1175 if (UNSET != bottom_offset)
1169 rp = cx23885_risc_field(rp, sglist, bottom_offset, 0x200, 1176 rp = cx23885_risc_field(rp, sglist, bottom_offset, 0x200,
1170 bpl, padding, lines); 1177 bpl, padding, lines, 0);
1171 1178
1172 /* save pointer to jmp instruction address */ 1179 /* save pointer to jmp instruction address */
1173 risc->jmp = rp; 1180 risc->jmp = rp;
@@ -1175,11 +1182,11 @@ int cx23885_risc_buffer(struct pci_dev *pci, struct btcx_riscmem *risc,
1175 return 0; 1182 return 0;
1176} 1183}
1177 1184
1178static int cx23885_risc_databuffer(struct pci_dev *pci, 1185int cx23885_risc_databuffer(struct pci_dev *pci,
1179 struct btcx_riscmem *risc, 1186 struct btcx_riscmem *risc,
1180 struct scatterlist *sglist, 1187 struct scatterlist *sglist,
1181 unsigned int bpl, 1188 unsigned int bpl,
1182 unsigned int lines) 1189 unsigned int lines, unsigned int lpi)
1183{ 1190{
1184 u32 instructions; 1191 u32 instructions;
1185 __le32 *rp; 1192 __le32 *rp;
@@ -1199,7 +1206,8 @@ static int cx23885_risc_databuffer(struct pci_dev *pci,
1199 1206
1200 /* write risc instructions */ 1207 /* write risc instructions */
1201 rp = risc->cpu; 1208 rp = risc->cpu;
1202 rp = cx23885_risc_field(rp, sglist, 0, NO_SYNC_LINE, bpl, 0, lines); 1209 rp = cx23885_risc_field(rp, sglist, 0, NO_SYNC_LINE,
1210 bpl, 0, lines, lpi);
1203 1211
1204 /* save pointer to jmp instruction address */ 1212 /* save pointer to jmp instruction address */
1205 risc->jmp = rp; 1213 risc->jmp = rp;
@@ -1517,7 +1525,7 @@ int cx23885_buf_prepare(struct videobuf_queue *q, struct cx23885_tsport *port,
1517 goto fail; 1525 goto fail;
1518 cx23885_risc_databuffer(dev->pci, &buf->risc, 1526 cx23885_risc_databuffer(dev->pci, &buf->risc,
1519 videobuf_to_dma(&buf->vb)->sglist, 1527 videobuf_to_dma(&buf->vb)->sglist,
1520 buf->vb.width, buf->vb.height); 1528 buf->vb.width, buf->vb.height, 0);
1521 } 1529 }
1522 buf->vb.state = VIDEOBUF_PREPARED; 1530 buf->vb.state = VIDEOBUF_PREPARED;
1523 return 0; 1531 return 0;
@@ -1741,15 +1749,19 @@ static irqreturn_t cx23885_irq(int irq, void *dev_id)
1741 struct cx23885_tsport *ts2 = &dev->ts2; 1749 struct cx23885_tsport *ts2 = &dev->ts2;
1742 u32 pci_status, pci_mask; 1750 u32 pci_status, pci_mask;
1743 u32 vida_status, vida_mask; 1751 u32 vida_status, vida_mask;
1752 u32 audint_status, audint_mask;
1744 u32 ts1_status, ts1_mask; 1753 u32 ts1_status, ts1_mask;
1745 u32 ts2_status, ts2_mask; 1754 u32 ts2_status, ts2_mask;
1746 int vida_count = 0, ts1_count = 0, ts2_count = 0, handled = 0; 1755 int vida_count = 0, ts1_count = 0, ts2_count = 0, handled = 0;
1756 int audint_count = 0;
1747 bool subdev_handled; 1757 bool subdev_handled;
1748 1758
1749 pci_status = cx_read(PCI_INT_STAT); 1759 pci_status = cx_read(PCI_INT_STAT);
1750 pci_mask = cx23885_irq_get_mask(dev); 1760 pci_mask = cx23885_irq_get_mask(dev);
1751 vida_status = cx_read(VID_A_INT_STAT); 1761 vida_status = cx_read(VID_A_INT_STAT);
1752 vida_mask = cx_read(VID_A_INT_MSK); 1762 vida_mask = cx_read(VID_A_INT_MSK);
1763 audint_status = cx_read(AUDIO_INT_INT_STAT);
1764 audint_mask = cx_read(AUDIO_INT_INT_MSK);
1753 ts1_status = cx_read(VID_B_INT_STAT); 1765 ts1_status = cx_read(VID_B_INT_STAT);
1754 ts1_mask = cx_read(VID_B_INT_MSK); 1766 ts1_mask = cx_read(VID_B_INT_MSK);
1755 ts2_status = cx_read(VID_C_INT_STAT); 1767 ts2_status = cx_read(VID_C_INT_STAT);
@@ -1759,12 +1771,15 @@ static irqreturn_t cx23885_irq(int irq, void *dev_id)
1759 goto out; 1771 goto out;
1760 1772
1761 vida_count = cx_read(VID_A_GPCNT); 1773 vida_count = cx_read(VID_A_GPCNT);
1774 audint_count = cx_read(AUD_INT_A_GPCNT);
1762 ts1_count = cx_read(ts1->reg_gpcnt); 1775 ts1_count = cx_read(ts1->reg_gpcnt);
1763 ts2_count = cx_read(ts2->reg_gpcnt); 1776 ts2_count = cx_read(ts2->reg_gpcnt);
1764 dprintk(7, "pci_status: 0x%08x pci_mask: 0x%08x\n", 1777 dprintk(7, "pci_status: 0x%08x pci_mask: 0x%08x\n",
1765 pci_status, pci_mask); 1778 pci_status, pci_mask);
1766 dprintk(7, "vida_status: 0x%08x vida_mask: 0x%08x count: 0x%x\n", 1779 dprintk(7, "vida_status: 0x%08x vida_mask: 0x%08x count: 0x%x\n",
1767 vida_status, vida_mask, vida_count); 1780 vida_status, vida_mask, vida_count);
1781 dprintk(7, "audint_status: 0x%08x audint_mask: 0x%08x count: 0x%x\n",
1782 audint_status, audint_mask, audint_count);
1768 dprintk(7, "ts1_status: 0x%08x ts1_mask: 0x%08x count: 0x%x\n", 1783 dprintk(7, "ts1_status: 0x%08x ts1_mask: 0x%08x count: 0x%x\n",
1769 ts1_status, ts1_mask, ts1_count); 1784 ts1_status, ts1_mask, ts1_count);
1770 dprintk(7, "ts2_status: 0x%08x ts2_mask: 0x%08x count: 0x%x\n", 1785 dprintk(7, "ts2_status: 0x%08x ts2_mask: 0x%08x count: 0x%x\n",
@@ -1861,6 +1876,9 @@ static irqreturn_t cx23885_irq(int irq, void *dev_id)
1861 if (vida_status) 1876 if (vida_status)
1862 handled += cx23885_video_irq(dev, vida_status); 1877 handled += cx23885_video_irq(dev, vida_status);
1863 1878
1879 if (audint_status)
1880 handled += cx23885_audio_irq(dev, audint_status, audint_mask);
1881
1864 if (pci_status & PCI_MSK_IR) { 1882 if (pci_status & PCI_MSK_IR) {
1865 subdev_handled = false; 1883 subdev_handled = false;
1866 v4l2_subdev_call(dev->sd_ir, core, interrupt_service_routine, 1884 v4l2_subdev_call(dev->sd_ir, core, interrupt_service_routine,
diff --git a/drivers/media/video/cx23885/cx23885.h b/drivers/media/video/cx23885/cx23885.h
index d86bc0b1317b..abeba7a35cea 100644
--- a/drivers/media/video/cx23885/cx23885.h
+++ b/drivers/media/video/cx23885/cx23885.h
@@ -318,6 +318,34 @@ struct cx23885_kernel_ir {
318 struct rc_dev *rc; 318 struct rc_dev *rc;
319}; 319};
320 320
321struct cx23885_audio_buffer {
322 unsigned int bpl;
323 struct btcx_riscmem risc;
324 struct videobuf_dmabuf dma;
325};
326
327struct cx23885_audio_dev {
328 struct cx23885_dev *dev;
329
330 struct pci_dev *pci;
331
332 struct snd_card *card;
333
334 spinlock_t lock;
335
336 atomic_t count;
337
338 unsigned int dma_size;
339 unsigned int period_size;
340 unsigned int num_periods;
341
342 struct videobuf_dmabuf *dma_risc;
343
344 struct cx23885_audio_buffer *buf;
345
346 struct snd_pcm_substream *substream;
347};
348
321struct cx23885_dev { 349struct cx23885_dev {
322 atomic_t refcount; 350 atomic_t refcount;
323 struct v4l2_device v4l2_dev; 351 struct v4l2_device v4l2_dev;
@@ -400,6 +428,9 @@ struct cx23885_dev {
400 atomic_t v4l_reader_count; 428 atomic_t v4l_reader_count;
401 struct cx23885_tvnorm encodernorm; 429 struct cx23885_tvnorm encodernorm;
402 430
431 /* Analog raw audio */
432 struct cx23885_audio_dev *audio_dev;
433
403}; 434};
404 435
405static inline struct cx23885_dev *to_cx23885(struct v4l2_device *v4l2_dev) 436static inline struct cx23885_dev *to_cx23885(struct v4l2_device *v4l2_dev)
@@ -563,6 +594,17 @@ extern void mc417_gpio_set(struct cx23885_dev *dev, u32 mask);
563extern void mc417_gpio_clear(struct cx23885_dev *dev, u32 mask); 594extern void mc417_gpio_clear(struct cx23885_dev *dev, u32 mask);
564extern void mc417_gpio_enable(struct cx23885_dev *dev, u32 mask, int asoutput); 595extern void mc417_gpio_enable(struct cx23885_dev *dev, u32 mask, int asoutput);
565 596
597/* ----------------------------------------------------------- */
598/* cx23885-alsa.c */
599extern struct cx23885_audio_dev *cx23885_audio_initdev(struct cx23885_dev *dev);
600extern void cx23885_audio_finidev(struct cx23885_dev *dev);
601extern int cx23885_audio_irq(struct cx23885_dev *dev, u32 status, u32 mask);
602extern int cx23885_risc_databuffer(struct pci_dev *pci,
603 struct btcx_riscmem *risc,
604 struct scatterlist *sglist,
605 unsigned int bpl,
606 unsigned int lines,
607 unsigned int lpi);
566 608
567/* ----------------------------------------------------------- */ 609/* ----------------------------------------------------------- */
568/* tv norms */ 610/* tv norms */