Hi Steven, Em 31-07-2010 13:31, Steven Toth escreveu: > Mauro, > > Please pull from http://www.kernellabs.com/hg/~stoth/cx23885-mpx > > - cx23885: prepare the cx23885 makefile for alsa support > - cx23885: merge mijhail's header changes for alsa > - cx23885: ALSA support > - cx23885: core changes requireed for ALSA > - cx23885: add definitions for HVR1500 to support audio > - cx23885: correct the contrast, saturation and hue controls > - cx23885: hooks the alsa changes into the video subsystem > - cx23885: convert call clients into subdevices > - cx23885: replaced spinlock with mutex > - cx23885: minor function renaming to ensure uniformity > - cx23885: setup the dma mapping for raw audio support > - cx23885: mute the audio during channel change > - cx23885: add two additional defines to simplify VBI register > bitmap handling > - cx23885: initial support for VBI with the cx23885 > - cx23885: initialize VBI support in the core, add IRQ support, > register vbi device > - cx23885: minor printk cleanups and device registration > - cx25840: enable raw cc processing only for the cx23885 hardware > - cx23885: vbi line window adjustments > - cx23885: add vbi buffer formatting, window changes and video core changes > - cx23885: Ensure the VBI pixel format is established correctly. > - cx23885: convert from snd_card_new() to snd_card_create() > - cx23885: ensure video is streaming before allowing vbi to stream > - cx23885: vbi related codingstyle cleanups > - cx23885: removal of VBI and earlier VBI printk debugging > - cx23885: removal of redundant code, this is no longer required. > - cx23885: remove channel dump diagnostics when a vbi buffer times out. > - cx23885: Ensure VBI buffers timeout quickly - bugfix for vbi > hangs during streaming. > - cx23885: coding style violation cleanups > - cx23885: Convert a mutex back to a spinlock > - cx23885: Name an internal i2c part and declare a bitfield by name > - cx25840: Enable support for non-tuner LR1/LR2 audio inputs > - cx23885: Allow the audio mux config to be specified on a per input basis. > - cx23885: remove a line of debug > - cx23885: Enable audio line in support from the back panel > - cx25840: Ensure AUDIO6 and AUDIO7 trigger line-in baseband use. > - cx23885: Initial support for the MPX-885 mini-card > - cx23885: fixes related to maximum number of inputs and range checking > - cx23885: add generic functions for dealing with audio input selection > - cx23885: hook the audio selection functions into the main driver > - cx23885: v4l2 api compliance, set the audioset field correctly > - cx23885: Removed a spurious function cx23885_set_scale(). > - cx23885: Avoid stopping the risc engine during buffer timeout. > - cx23885: Avoid incorrect error handling and reporting > - cx23885: Stop the risc video fifo before reconfiguring it. > > b/linux/drivers/media/video/cx23885/cx23885-alsa.c | 542 +++++++++ > linux/Documentation/video4linux/CARDLIST.cx23885 | 1 > linux/drivers/media/video/cx23885/Makefile | 2 > linux/drivers/media/video/cx23885/cx23885-alsa.c | 28 > linux/drivers/media/video/cx23885/cx23885-cards.c | 53 > linux/drivers/media/video/cx23885/cx23885-core.c | 127 +- > linux/drivers/media/video/cx23885/cx23885-i2c.c | 1 > linux/drivers/media/video/cx23885/cx23885-reg.h | 3 > linux/drivers/media/video/cx23885/cx23885-vbi.c | 96 + > linux/drivers/media/video/cx23885/cx23885-video.c | 556 ++++++---- > linux/drivers/media/video/cx23885/cx23885.h | 65 + > linux/drivers/media/video/cx25840/cx25840-audio.c | 9 > linux/drivers/media/video/cx25840/cx25840-core.c | 21 > 13 files changed, 1257 insertions(+), 247 deletions(-) > > A pretty large patch set which adds a number of important features to > the cx23885 driver. It is always a good idea to not wait for a large patch set when submitting, as waiting for a long time to merge increase the chances of conflicts. That's the case of this changeset. It breaks compilation due to an API change at the videobuf-dma-sg: drivers/media/video/cx23885/cx23885-alsa.c: In function ‘dsp_buffer_free’: drivers/media/video/cx23885/cx23885-alsa.c:199: error: implicit declaration of function ‘videobuf_sg_dma_unmap’ drivers/media/video/cx23885/cx23885-alsa.c: In function ‘snd_cx23885_hw_params’: drivers/media/video/cx23885/cx23885-alsa.c:329: error: implicit declaration of function ‘videobuf_sg_dma_map’ drivers/media/video/cx23885/cx23885-alsa.c:348: error: ‘struct videobuf_dmabuf’ has no member named ‘vmalloc’ I suspect it is caused by commit fecfedeb27ab9497cbdd2c6: Author: Laurent Pinchart <laurent.pinchart@xxxxxxxxxxxxxxxx> Date: Tue May 11 10:36:31 2010 -0300 V4L/DVB: Remove videobuf_sg_alloc abuse The cx88 and cx25821 drivers abuse videobuf_buffer to handle audio data. Remove the abuse by creating private audio buffer structures with a videobuf_dmabuf field. Signed-off-by: Laurent Pinchart <laurent.pinchart@xxxxxxxxxxxxxxxx> Signed-off-by: Mauro Carvalho Chehab <mchehab@xxxxxxxxxx> I also had to solve a few trivial conflicts against awalls pull request, that also submitted a large sets of change due to IR and had to move the Makefile changes to the end - to avoid bisect issues.If you want, I may send you a quilt tree with the fixed patches. > Some early patches for the HVR1500 with add support for analog audio > (very rough, much rework on these). > The University of California sponsored work for the HVR1800 and > HVR1850 and raw video and raw audio and VBI support. > The Belac Group sponsored changes related to the MPX cx23885 8 input > design, adding raw video and audio support. > Mencoder now works correctly with the raw video and audio portions of > the driver. > GStreamer now works correctly using the v4l interfaces from the > driver, live video and audio viewing are now possible. > NTSC-ZZ-VBI now works correctly for RAW VBI decoding (although TVTime > still refuses to work correctly - tvtime bug) I have a few other comments. In order to make simpler for me to comment, I just folded everything into one single diff, as enclosed. Cheers, Mauro. > diff --git a/Documentation/video4linux/CARDLIST.cx23885 b/Documentation/video4linux/CARDLIST.cx23885 > index 87c4634..30309f0 100644 > --- a/Documentation/video4linux/CARDLIST.cx23885 > +++ b/Documentation/video4linux/CARDLIST.cx23885 > @@ -27,3 +27,4 @@ > 26 -> Hauppauge WinTV-HVR1290 [0070:8551] > 27 -> Mygica X8558 PRO DMB-TH [14f1:8578] > 28 -> LEADTEK WinFast PxTV1200 [107d:6f22] > + 29 -> MPX-885 > diff --git a/drivers/media/video/cx23885/Makefile b/drivers/media/video/cx23885/Makefile > index e2ee95f..ed739f9 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 \ > cx23885-core.o cx23885-i2c.o cx23885-dvb.o cx23885-417.o \ > cx23885-ioctl.o cx23885-ir.o cx23885-av.o cx23885-input.o \ > cx23888-ir.o netup-init.o cimax2.o netup-eeprom.o \ > - cx23885-f300.o > + cx23885-f300.o cx23885-alsa.o > > obj-$(CONFIG_VIDEO_CX23885) += cx23885.o > > diff --git a/drivers/media/video/cx23885/cx23885-cards.c b/drivers/media/video/cx23885/cx23885-cards.c > index e76ce87..d07eedf 100644 > --- a/drivers/media/video/cx23885/cx23885-cards.c > +++ b/drivers/media/video/cx23885/cx23885-cards.c > @@ -95,12 +95,14 @@ struct cx23885_board cx23885_boards[] = { > .vmux = CX25840_VIN7_CH3 | > CX25840_VIN5_CH2 | > CX25840_VIN2_CH1, > + .amux = CX25840_AUDIO8, > .gpio0 = 0, > }, { > .type = CX23885_VMUX_COMPOSITE1, > .vmux = CX25840_VIN7_CH3 | > CX25840_VIN4_CH2 | > CX25840_VIN6_CH1, > + .amux = CX25840_AUDIO7, > .gpio0 = 0, > }, { > .type = CX23885_VMUX_SVIDEO, > @@ -108,6 +110,7 @@ struct cx23885_board cx23885_boards[] = { > CX25840_VIN4_CH2 | > CX25840_VIN8_CH1 | > CX25840_SVIDEO_ON, > + .amux = CX25840_AUDIO7, > .gpio0 = 0, > } }, > }, > @@ -142,7 +145,30 @@ struct cx23885_board cx23885_boards[] = { > }, > [CX23885_BOARD_HAUPPAUGE_HVR1500] = { > .name = "Hauppauge WinTV-HVR1500", > + .porta = CX23885_ANALOG_VIDEO, > .portc = CX23885_MPEG_DVB, > + .tuner_type = TUNER_XC2028, > + .tuner_addr = 0x61, /* 0xc2 >> 1 */ > + .input = {{ > + .type = CX23885_VMUX_TELEVISION, > + .vmux = CX25840_VIN7_CH3 | > + CX25840_VIN5_CH2 | > + CX25840_VIN2_CH1, > + .gpio0 = 0, > + }, { > + .type = CX23885_VMUX_COMPOSITE1, > + .vmux = CX25840_VIN7_CH3 | > + CX25840_VIN4_CH2 | > + CX25840_VIN6_CH1, > + .gpio0 = 0, > + }, { > + .type = CX23885_VMUX_SVIDEO, > + .vmux = CX25840_VIN7_CH3 | > + CX25840_VIN4_CH2 | > + CX25840_VIN8_CH1 | > + CX25840_SVIDEO_ON, > + .gpio0 = 0, > + } }, > }, > [CX23885_BOARD_HAUPPAUGE_HVR1200] = { > .name = "Hauppauge WinTV-HVR1200", > @@ -309,6 +335,31 @@ struct cx23885_board cx23885_boards[] = { > CX25840_COMPONENT_ON, > } }, > }, > + [CX23885_BOARD_MPX885] = { > + .name = "MPX-885", > + .porta = CX23885_ANALOG_VIDEO, > + .input = {{ > + .type = CX23885_VMUX_COMPOSITE1, > + .vmux = CX25840_COMPOSITE1, > + .amux = CX25840_AUDIO6, > + .gpio0 = 0, > + }, { > + .type = CX23885_VMUX_COMPOSITE2, > + .vmux = CX25840_COMPOSITE2, > + .amux = CX25840_AUDIO6, > + .gpio0 = 0, > + }, { > + .type = CX23885_VMUX_COMPOSITE3, > + .vmux = CX25840_COMPOSITE3, > + .amux = CX25840_AUDIO7, > + .gpio0 = 0, > + }, { > + .type = CX23885_VMUX_COMPOSITE4, > + .vmux = CX25840_COMPOSITE4, > + .amux = CX25840_AUDIO7, > + .gpio0 = 0, > + } }, > + }, > }; > const unsigned int cx23885_bcount = ARRAY_SIZE(cx23885_boards); > > @@ -1245,6 +1296,8 @@ void cx23885_card_setup(struct cx23885_dev *dev) > case CX23885_BOARD_MAGICPRO_PROHDTVE2: > case CX23885_BOARD_HAUPPAUGE_HVR1290: > case CX23885_BOARD_LEADTEK_WINFAST_PXTV1200: > + case CX23885_BOARD_HAUPPAUGE_HVR1500: > + case CX23885_BOARD_MPX885: > dev->sd_cx25840 = v4l2_i2c_new_subdev(&dev->v4l2_dev, > &dev->i2c_bus[2].i2c_adap, > "cx25840", "cx25840", 0x88 >> 1, NULL); > diff --git a/drivers/media/video/cx23885/cx23885-core.c b/drivers/media/video/cx23885/cx23885-core.c > index f6b62e7..6118b56 100644 > --- a/drivers/media/video/cx23885/cx23885-core.c > +++ b/drivers/media/video/cx23885/cx23885-core.c > @@ -51,7 +51,7 @@ MODULE_PARM_DESC(card, "card type"); > > #define dprintk(level, fmt, arg...)\ > do { if (debug >= level)\ > - printk(KERN_DEBUG "%s/0: " fmt, dev->name, ## arg);\ > + printk(KERN_DEBUG "%s: " fmt, dev->name, ## arg);\ > } while (0) > > static unsigned int cx23885_devcount; > @@ -152,12 +152,12 @@ static struct sram_channel cx23885_sram_channels[] = { > .cnt2_reg = DMA5_CNT2, > }, > [SRAM_CH07] = { > - .name = "ch7", > - .cmds_start = 0x0, > - .ctrl_start = 0x0, > - .cdt = 0x0, > - .fifo_start = 0x0, > - .fifo_size = 0x0, > + .name = "TV Audio", > + .cmds_start = 0x10190, > + .ctrl_start = 0x10480, > + .cdt = 0x10a00, > + .fifo_start = 0x7000, > + .fifo_size = 0x1000, > .ptr1_reg = DMA6_PTR1, > .ptr2_reg = DMA6_PTR2, > .cnt1_reg = DMA6_CNT1, > @@ -203,12 +203,12 @@ static struct sram_channel cx23887_sram_channels[] = { > .cnt2_reg = DMA1_CNT2, > }, > [SRAM_CH02] = { > - .name = "ch2", > - .cmds_start = 0x0, > - .ctrl_start = 0x0, > - .cdt = 0x0, > - .fifo_start = 0x0, > - .fifo_size = 0x0, > + .name = "VID A (VBI)", > + .cmds_start = 0x10050, > + .ctrl_start = 0x105F0, > + .cdt = 0x10810, > + .fifo_start = 0x3000, > + .fifo_size = 0x1000, > .ptr1_reg = DMA2_PTR1, > .ptr2_reg = DMA2_PTR2, > .cnt1_reg = DMA2_CNT1, > @@ -263,12 +263,12 @@ static struct sram_channel cx23887_sram_channels[] = { > .cnt2_reg = DMA5_CNT2, > }, > [SRAM_CH07] = { > - .name = "ch7", > - .cmds_start = 0x0, > - .ctrl_start = 0x0, > - .cdt = 0x0, > - .fifo_start = 0x0, > - .fifo_size = 0x0, > + .name = "TV Audio", > + .cmds_start = 0x10190, > + .ctrl_start = 0x106B0, > + .cdt = 0x10930, > + .fifo_start = 0x7000, > + .fifo_size = 0x1000, > .ptr1_reg = DMA6_PTR1, > .ptr2_reg = DMA6_PTR2, > .cnt1_reg = DMA6_CNT1, > @@ -1069,10 +1069,10 @@ static void cx23885_dev_unregister(struct cx23885_dev *dev) > static __le32 *cx23885_risc_field(__le32 *rp, struct scatterlist *sglist, > unsigned int offset, u32 sync_line, > unsigned int bpl, unsigned int padding, > - unsigned int lines) > + unsigned int lines, unsigned int lpi) > { > struct scatterlist *sg; > - unsigned int line, todo; > + unsigned int line, todo, sol; > > /* sync instruction */ > if (sync_line != NO_SYNC_LINE) > @@ -1085,16 +1085,22 @@ static __le32 *cx23885_risc_field(__le32 *rp, struct scatterlist *sglist, > offset -= sg_dma_len(sg); > sg++; > } > + > + if (lpi && line > 0 && !(line % lpi)) > + sol = RISC_SOL | RISC_IRQ1 | RISC_CNT_INC; > + else > + sol = RISC_SOL; > + > if (bpl <= sg_dma_len(sg)-offset) { > /* fits into current chunk */ > - *(rp++) = cpu_to_le32(RISC_WRITE|RISC_SOL|RISC_EOL|bpl); > + *(rp++) = cpu_to_le32(RISC_WRITE|sol|RISC_EOL|bpl); > *(rp++) = cpu_to_le32(sg_dma_address(sg)+offset); > *(rp++) = cpu_to_le32(0); /* bits 63-32 */ > offset += bpl; > } else { > /* scanline needs to be split */ > todo = bpl; > - *(rp++) = cpu_to_le32(RISC_WRITE|RISC_SOL| > + *(rp++) = cpu_to_le32(RISC_WRITE|sol| > (sg_dma_len(sg)-offset)); > *(rp++) = cpu_to_le32(sg_dma_address(sg)+offset); > *(rp++) = cpu_to_le32(0); /* bits 63-32 */ > @@ -1151,10 +1157,10 @@ int cx23885_risc_buffer(struct pci_dev *pci, struct btcx_riscmem *risc, > rp = risc->cpu; > if (UNSET != top_offset) > rp = cx23885_risc_field(rp, sglist, top_offset, 0, > - bpl, padding, lines); > + bpl, padding, lines, 0); > if (UNSET != bottom_offset) > rp = cx23885_risc_field(rp, sglist, bottom_offset, 0x200, > - bpl, padding, lines); > + bpl, padding, lines, 0); > > /* save pointer to jmp instruction address */ > risc->jmp = rp; > @@ -1162,11 +1168,11 @@ int cx23885_risc_buffer(struct pci_dev *pci, struct btcx_riscmem *risc, > return 0; > } > > -static int cx23885_risc_databuffer(struct pci_dev *pci, > +int cx23885_risc_databuffer(struct pci_dev *pci, > struct btcx_riscmem *risc, > struct scatterlist *sglist, > unsigned int bpl, > - unsigned int lines) > + unsigned int lines, unsigned int lpi) > { > u32 instructions; > __le32 *rp; > @@ -1186,7 +1192,55 @@ static int cx23885_risc_databuffer(struct pci_dev *pci, > > /* write risc instructions */ > rp = risc->cpu; > - rp = cx23885_risc_field(rp, sglist, 0, NO_SYNC_LINE, bpl, 0, lines); > + rp = cx23885_risc_field(rp, sglist, 0, NO_SYNC_LINE, bpl, 0, > + lines, lpi); > + > + /* save pointer to jmp instruction address */ > + risc->jmp = rp; > + BUG_ON((risc->jmp - risc->cpu + 2) * sizeof(*risc->cpu) > risc->size); > + return 0; > +} > + > +int cx23885_risc_vbibuffer(struct pci_dev *pci, struct btcx_riscmem *risc, > + struct scatterlist *sglist, unsigned int top_offset, > + unsigned int bottom_offset, unsigned int bpl, > + unsigned int padding, unsigned int lines) > +{ > + u32 instructions, fields; > + __le32 *rp; > + int rc; > + > + fields = 0; > + if (UNSET != top_offset) > + fields++; > + if (UNSET != bottom_offset) > + fields++; > + > + /* estimate risc mem: worst case is one write per page border + > + one write per scan line + syncs + jump (all 2 dwords). Padding > + can cause next bpl to start close to a page border. First DMA > + region may be smaller than PAGE_SIZE */ > + /* write and jump need and extra dword */ > + instructions = fields * (1 + ((bpl + padding) * lines) > + / PAGE_SIZE + lines); > + instructions += 2; > + rc = btcx_riscmem_alloc(pci, risc, instructions*12); > + if (rc < 0) > + return rc; > + /* write risc instructions */ > + rp = risc->cpu; > + > + /* Sync to line 6, so US CC line 21 will appear in line '12' > + * in the userland vbi payload */ > + if (UNSET != top_offset) > + rp = cx23885_risc_field(rp, sglist, top_offset, 6, > + bpl, padding, lines, 0); > + > + if (UNSET != bottom_offset) > + rp = cx23885_risc_field(rp, sglist, bottom_offset, 0x207, > + bpl, padding, lines, 0); > + > + > > /* save pointer to jmp instruction address */ > risc->jmp = rp; > @@ -1194,6 +1248,7 @@ static int cx23885_risc_databuffer(struct pci_dev *pci, > return 0; > } > > + > int cx23885_risc_stopper(struct pci_dev *pci, struct btcx_riscmem *risc, > u32 reg, u32 mask, u32 value) > { > @@ -1504,7 +1559,7 @@ int cx23885_buf_prepare(struct videobuf_queue *q, struct cx23885_tsport *port, > goto fail; > cx23885_risc_databuffer(dev->pci, &buf->risc, > videobuf_to_dma(&buf->vb)->sglist, > - buf->vb.width, buf->vb.height); > + buf->vb.width, buf->vb.height, 0); > } > buf->vb.state = VIDEOBUF_PREPARED; > return 0; > @@ -1728,15 +1783,19 @@ static irqreturn_t cx23885_irq(int irq, void *dev_id) > struct cx23885_tsport *ts2 = &dev->ts2; > u32 pci_status, pci_mask; > u32 vida_status, vida_mask; > + u32 audint_status, audint_mask; > u32 ts1_status, ts1_mask; > u32 ts2_status, ts2_mask; > int vida_count = 0, ts1_count = 0, ts2_count = 0, handled = 0; > + int audint_count = 0; > bool subdev_handled; > > pci_status = cx_read(PCI_INT_STAT); > pci_mask = cx23885_irq_get_mask(dev); > vida_status = cx_read(VID_A_INT_STAT); > vida_mask = cx_read(VID_A_INT_MSK); > + audint_status = cx_read(AUDIO_INT_INT_STAT); > + audint_mask = cx_read(AUDIO_INT_INT_MSK); > ts1_status = cx_read(VID_B_INT_STAT); > ts1_mask = cx_read(VID_B_INT_MSK); > ts2_status = cx_read(VID_C_INT_STAT); > @@ -1746,12 +1805,15 @@ static irqreturn_t cx23885_irq(int irq, void *dev_id) > goto out; > > vida_count = cx_read(VID_A_GPCNT); > + audint_count = cx_read(AUD_INT_A_GPCNT); > ts1_count = cx_read(ts1->reg_gpcnt); > ts2_count = cx_read(ts2->reg_gpcnt); > dprintk(7, "pci_status: 0x%08x pci_mask: 0x%08x\n", > pci_status, pci_mask); > dprintk(7, "vida_status: 0x%08x vida_mask: 0x%08x count: 0x%x\n", > vida_status, vida_mask, vida_count); > + dprintk(7, "audint_status: 0x%08x audint_mask: 0x%08x count: 0x%x\n", > + audint_status, audint_mask, audint_count); > dprintk(7, "ts1_status: 0x%08x ts1_mask: 0x%08x count: 0x%x\n", > ts1_status, ts1_mask, ts1_count); > dprintk(7, "ts2_status: 0x%08x ts2_mask: 0x%08x count: 0x%x\n", > @@ -1849,6 +1911,9 @@ static irqreturn_t cx23885_irq(int irq, void *dev_id) > if (vida_status) > handled += cx23885_video_irq(dev, vida_status); > > + if (audint_status) > + handled += cx23885_audio_irq(dev, audint_status, audint_mask); > + > if (pci_status & PCI_MSK_IR) { > subdev_handled = false; > v4l2_subdev_call(dev->sd_ir, core, interrupt_service_routine, > diff --git a/drivers/media/video/cx23885/cx23885-i2c.c b/drivers/media/video/cx23885/cx23885-i2c.c > index 1a39148..46027ee 100644 > --- a/drivers/media/video/cx23885/cx23885-i2c.c > +++ b/drivers/media/video/cx23885/cx23885-i2c.c > @@ -297,6 +297,7 @@ static char *i2c_devs[128] = { > [0x32 >> 1] = "cx24227", > [0x88 >> 1] = "cx25837", > [0x84 >> 1] = "tda8295", > + [0x98 >> 1] = "flatiron", > [0xa0 >> 1] = "eeprom", > [0xc0 >> 1] = "tuner/mt2131/tda8275", > [0xc2 >> 1] = "tuner/mt2131/tda8275/xc5000/xc3028", > diff --git a/drivers/media/video/cx23885/cx23885-reg.h b/drivers/media/video/cx23885/cx23885-reg.h > index a28772d..0c648ac 100644 > --- a/drivers/media/video/cx23885/cx23885-reg.h > +++ b/drivers/media/video/cx23885/cx23885-reg.h > @@ -203,6 +203,7 @@ Channel manager Data Structure entry = 20 DWORD > #define SD2_BIAS_CTRL 0x0000000A > #define AMP_BIAS_CTRL 0x0000000C > #define CH_PWR_CTRL1 0x0000000E > +#define FLD_CH_SEL (1 << 3) > #define CH_PWR_CTRL2 0x0000000F > #define DSM_STATUS1 0x00000010 > #define DSM_STATUS2 0x00000011 > @@ -271,7 +272,9 @@ Channel manager Data Structure entry = 20 DWORD > #define VID_BC_MSK_OPC_ERR (1 << 16) > #define VID_BC_MSK_SYNC (1 << 12) > #define VID_BC_MSK_OF (1 << 8) > +#define VID_BC_MSK_VBI_RISCI2 (1 << 5) > #define VID_BC_MSK_RISCI2 (1 << 4) > +#define VID_BC_MSK_VBI_RISCI1 (1 << 1) > #define VID_BC_MSK_RISCI1 1 > > #define VID_C_INT_MSK 0x00040040 > diff --git a/drivers/media/video/cx23885/cx23885-vbi.c b/drivers/media/video/cx23885/cx23885-vbi.c > index c0b6038..d2b25d9 100644 > --- a/drivers/media/video/cx23885/cx23885-vbi.c > +++ b/drivers/media/video/cx23885/cx23885-vbi.c > @@ -41,6 +41,12 @@ MODULE_PARM_DESC(vbi_debug, "enable debug messages [vbi]"); > > /* ------------------------------------------------------------------ */ > > +#define VBI_LINE_LENGTH 1440 > +#define NTSC_VBI_START_LINE 10 /* line 10 - 21 */ > +#define NTSC_VBI_END_LINE 21 > +#define NTSC_VBI_LINES (NTSC_VBI_END_LINE - NTSC_VBI_START_LINE + 1) > + > + > int cx23885_vbi_fmt(struct file *file, void *priv, > struct v4l2_format *f) > { > @@ -49,28 +55,71 @@ int cx23885_vbi_fmt(struct file *file, void *priv, > > if (dev->tvnorm & V4L2_STD_525_60) { > /* ntsc */ > - f->fmt.vbi.sampling_rate = 28636363; > + f->fmt.vbi.samples_per_line = VBI_LINE_LENGTH; > + f->fmt.vbi.sampling_rate = 27000000; > + f->fmt.vbi.sample_format = V4L2_PIX_FMT_GREY; > + f->fmt.vbi.offset = 0; > + f->fmt.vbi.flags = 0; > f->fmt.vbi.start[0] = 10; > - f->fmt.vbi.start[1] = 273; > - > + f->fmt.vbi.count[0] = 17; > + f->fmt.vbi.start[1] = 263 + 10 + 1; > + f->fmt.vbi.count[1] = 17; > } else if (dev->tvnorm & V4L2_STD_625_50) { > /* pal */ > f->fmt.vbi.sampling_rate = 35468950; I suspect that the sampling rate is wrong here. If PAL/SECAM with 625 lines are not supported yet, better to just prevent VBI from work with 625 lines. > f->fmt.vbi.start[0] = 7 - 1; > f->fmt.vbi.start[1] = 319 - 1; > } > + > return 0; > } > > +/* We're given the Video Interrupt status register. > + * The cx23885_video_irq() func has already validated > + * the potential error bits, we just need to > + * deal with vbi payload and return indication if > + * we actually processed any payload. > + */ > +int cx23885_vbi_irq(struct cx23885_dev *dev, u32 status) > +{ > + u32 count; > + int handled = 0; > + > + if (status & VID_BC_MSK_VBI_RISCI1) { > + dprintk(1, "%s() VID_BC_MSK_VBI_RISCI1\n", __func__); > + spin_lock(&dev->slock); > + count = cx_read(VID_A_GPCNT); > + cx23885_video_wakeup(dev, &dev->vbiq, count); > + spin_unlock(&dev->slock); > + handled++; > + } > + > + if (status & VID_BC_MSK_VBI_RISCI2) { > + dprintk(1, "%s() VID_BC_MSK_VBI_RISCI2\n", __func__); > + dprintk(2, "stopper vbi\n"); > + spin_lock(&dev->slock); > + cx23885_restart_vbi_queue(dev, &dev->vbiq); > + spin_unlock(&dev->slock); > + handled++; > + } > + > + return handled; > +} > + > static int cx23885_start_vbi_dma(struct cx23885_dev *dev, > struct cx23885_dmaqueue *q, > struct cx23885_buffer *buf) > { > + dprintk(1, "%s()\n", __func__); > + > /* setup fifo + format */ > cx23885_sram_channel_setup(dev, &dev->sram_channels[SRAM_CH02], > buf->vb.width, buf->risc.dma); > > /* reset counter */ > + cx_write(VID_A_GPCNT_CTL, 3); > + cx_write(VID_A_VBI_CTRL, 3); > + cx_write(VBI_A_GPCNT_CTL, 3); > q->count = 1; > > /* enable irqs */ > @@ -79,13 +128,13 @@ static int cx23885_start_vbi_dma(struct cx23885_dev *dev, > > /* start dma */ > cx_set(DEV_CNTRL2, (1<<5)); > - cx_set(VID_A_DMA_CTL, 0x00000022); > + cx_set(VID_A_DMA_CTL, 0x22); /* FIFO and RISC enable */ > > return 0; > } > > > -static int cx23885_restart_vbi_queue(struct cx23885_dev *dev, > +int cx23885_restart_vbi_queue(struct cx23885_dev *dev, > struct cx23885_dmaqueue *q) > { > struct cx23885_buffer *buf; > @@ -102,7 +151,7 @@ static int cx23885_restart_vbi_queue(struct cx23885_dev *dev, > buf = list_entry(item, struct cx23885_buffer, vb.queue); > buf->count = q->count++; > } > - mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT); > + mod_timer(&q->timeout, jiffies + (BUFFER_TIMEOUT / 30)); > return 0; > } > > @@ -113,8 +162,7 @@ void cx23885_vbi_timeout(unsigned long data) > struct cx23885_buffer *buf; > unsigned long flags; > > - cx23885_sram_channel_dump(dev, &dev->sram_channels[SRAM_CH02]); > - > + /* Stop the VBI engine */ > cx_clear(VID_A_DMA_CTL, 0x22); > > spin_lock_irqsave(&dev->slock, flags); > @@ -132,7 +180,7 @@ void cx23885_vbi_timeout(unsigned long data) > } > > /* ------------------------------------------------------------------ */ > -#define VBI_LINE_LENGTH 2048 > +#define VBI_LINE_LENGTH 1440 > #define VBI_LINE_COUNT 17 > > static int > @@ -173,7 +221,7 @@ vbi_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb, > rc = videobuf_iolock(q, &buf->vb, NULL); > if (0 != rc) > goto fail; > - cx23885_risc_buffer(dev->pci, &buf->risc, > + cx23885_risc_vbibuffer(dev->pci, &buf->risc, > dma->sglist, > 0, buf->vb.width * buf->vb.height, > buf->vb.width, 0, > @@ -207,7 +255,7 @@ vbi_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb) > cx23885_start_vbi_dma(dev, q, buf); > buf->vb.state = VIDEOBUF_ACTIVE; > buf->count = q->count++; > - mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT); > + mod_timer(&q->timeout, jiffies + (BUFFER_TIMEOUT / 30)); > dprintk(2, "[%p/%d] vbi_queue - first active\n", > buf, buf->vb.i); > > diff --git a/drivers/media/video/cx23885/cx23885-video.c b/drivers/media/video/cx23885/cx23885-video.c > index da66e5f..b7f01bd 100644 > --- a/drivers/media/video/cx23885/cx23885-video.c > +++ b/drivers/media/video/cx23885/cx23885-video.c > @@ -38,6 +38,8 @@ > #include "cx23885-ioctl.h" > #include "tuner-xc2028.h" > > +#include <media/cx25840.h> > + > MODULE_DESCRIPTION("v4l2 driver module for cx23885 based TV cards"); > MODULE_AUTHOR("Steven Toth <stoth@xxxxxxxxxxx>"); > MODULE_LICENSE("GPL"); > @@ -70,66 +72,20 @@ MODULE_PARM_DESC(vid_limit, "capture memory limit in megabytes"); > > #define dprintk(level, fmt, arg...)\ > do { if (video_debug >= level)\ > - printk(KERN_DEBUG "%s/0: " fmt, dev->name, ## arg);\ > + printk(KERN_DEBUG "%s: " fmt, dev->name, ## arg);\ > } while (0) > > /* ------------------------------------------------------------------- */ > /* static data */ > > #define FORMAT_FLAGS_PACKED 0x01 > - > static struct cx23885_fmt formats[] = { > { > - .name = "8 bpp, gray", > - .fourcc = V4L2_PIX_FMT_GREY, > - .depth = 8, > - .flags = FORMAT_FLAGS_PACKED, > - }, { > - .name = "15 bpp RGB, le", > - .fourcc = V4L2_PIX_FMT_RGB555, > - .depth = 16, > - .flags = FORMAT_FLAGS_PACKED, > - }, { > - .name = "15 bpp RGB, be", > - .fourcc = V4L2_PIX_FMT_RGB555X, > - .depth = 16, > - .flags = FORMAT_FLAGS_PACKED, > - }, { > - .name = "16 bpp RGB, le", > - .fourcc = V4L2_PIX_FMT_RGB565, > - .depth = 16, > - .flags = FORMAT_FLAGS_PACKED, > - }, { > - .name = "16 bpp RGB, be", > - .fourcc = V4L2_PIX_FMT_RGB565X, > - .depth = 16, > - .flags = FORMAT_FLAGS_PACKED, > - }, { > - .name = "24 bpp RGB, le", > - .fourcc = V4L2_PIX_FMT_BGR24, > - .depth = 24, > - .flags = FORMAT_FLAGS_PACKED, > - }, { > - .name = "32 bpp RGB, le", > - .fourcc = V4L2_PIX_FMT_BGR32, > - .depth = 32, > - .flags = FORMAT_FLAGS_PACKED, > - }, { > - .name = "32 bpp RGB, be", > - .fourcc = V4L2_PIX_FMT_RGB32, > - .depth = 32, > - .flags = FORMAT_FLAGS_PACKED, > - }, { > .name = "4:2:2, packed, YUYV", > .fourcc = V4L2_PIX_FMT_YUYV, > .depth = 16, > .flags = FORMAT_FLAGS_PACKED, > - }, { > - .name = "4:2:2, packed, UYVY", > - .fourcc = V4L2_PIX_FMT_UYVY, > - .depth = 16, > - .flags = FORMAT_FLAGS_PACKED, > - }, > + } Hmm... why did you remove the other standards? This looks like a regression to me. > }; > > static struct cx23885_fmt *format_by_fourcc(unsigned int fourcc) > @@ -140,7 +96,12 @@ static struct cx23885_fmt *format_by_fourcc(unsigned int fourcc) > if (formats[i].fourcc == fourcc) > return formats+i; > > - printk(KERN_ERR "%s(0x%08x) NOT FOUND\n", __func__, fourcc); > + printk(KERN_ERR "%s(%c%c%c%c) NOT FOUND\n", __func__, > + (fourcc & 0xff), > + ((fourcc >> 8) & 0xff), > + ((fourcc >> 16) & 0xff), > + ((fourcc >> 24) & 0xff) > + ); > return NULL; > } > > @@ -172,7 +133,7 @@ static struct cx23885_ctrl cx23885_ctls[] = { > .id = V4L2_CID_CONTRAST, > .name = "Contrast", > .minimum = 0, > - .maximum = 0xff, > + .maximum = 0x7f, > .step = 1, > .default_value = 0x3f, > .type = V4L2_CTRL_TYPE_INTEGER, > @@ -185,10 +146,10 @@ static struct cx23885_ctrl cx23885_ctls[] = { > .v = { > .id = V4L2_CID_HUE, > .name = "Hue", > - .minimum = 0, > - .maximum = 0xff, > + .minimum = -127, > + .maximum = 128, > .step = 1, > - .default_value = 0x7f, > + .default_value = 0x0, > .type = V4L2_CTRL_TYPE_INTEGER, > }, > .off = 128, > @@ -203,9 +164,9 @@ static struct cx23885_ctrl cx23885_ctls[] = { > .id = V4L2_CID_SATURATION, > .name = "Saturation", > .minimum = 0, > - .maximum = 0xff, > + .maximum = 0x7f, > .step = 1, > - .default_value = 0x7f, > + .default_value = 0x3f, > .type = V4L2_CTRL_TYPE_INTEGER, > }, > .off = 0, > @@ -259,8 +220,8 @@ static const u32 *ctrl_classes[] = { > NULL > }; > > -static void cx23885_video_wakeup(struct cx23885_dev *dev, > - struct cx23885_dmaqueue *q, u32 count) > +void cx23885_video_wakeup(struct cx23885_dev *dev, > + struct cx23885_dmaqueue *q, u32 count) > { > struct cx23885_buffer *buf; > int bc; > @@ -394,6 +355,71 @@ static void res_free(struct cx23885_dev *dev, struct cx23885_fh *fh, > mutex_unlock(&dev->lock); > } > > +static int cx23885_flatiron_write(struct cx23885_dev *dev, u8 reg, u8 data) > +{ > + /* 8 bit registers, 8 bit values */ > + u8 buf[] = { reg, data }; > + > + struct i2c_msg msg = { .addr = 0x98 >> 1, > + .flags = 0, .buf = buf, .len = 2 }; > + > + return i2c_transfer(&dev->i2c_bus[2].i2c_adap, &msg, 1); > +} > + > +static u8 cx23885_flatiron_read(struct cx23885_dev *dev, u8 reg) > +{ > + /* 8 bit registers, 8 bit values */ > + int ret; > + u8 b0[] = { reg }; > + u8 b1[] = { 0 }; > + > + struct i2c_msg msg[] = { > + { .addr = 0x98 >> 1, .flags = 0, .buf = b0, .len = 1 }, > + { .addr = 0x98 >> 1, .flags = I2C_M_RD, .buf = b1, .len = 1 } > + }; > + > + ret = i2c_transfer(&dev->i2c_bus[2].i2c_adap, &msg[0], 2); > + if (ret != 2) > + printk(KERN_ERR "%s() error\n", __func__); > + > + return b1[0]; > +} > + > +static void cx23885_flatiron_dump(struct cx23885_dev *dev) > +{ > + int i; > + dprintk(1, "Flatiron dump\n"); > + for (i = 0; i < 0x24; i++) { > + dprintk(1, "FI[%02x] = %02x\n", i, > + cx23885_flatiron_read(dev, i)); > + } > +} > + > +static int cx23885_flatiron_mux(struct cx23885_dev *dev, int input) > +{ > + u8 val; > + dprintk(1, "%s(input = %d)\n", __func__, input); > + > + if (input == 1) > + val = cx23885_flatiron_read(dev, CH_PWR_CTRL1) & ~FLD_CH_SEL; > + else if (input == 2) > + val = cx23885_flatiron_read(dev, CH_PWR_CTRL1) | FLD_CH_SEL; > + else > + return -EINVAL; > + > + val |= 0x20; /* Enable clock to delta-sigma and dec filter */ > + > + cx23885_flatiron_write(dev, CH_PWR_CTRL1, val); > + > + /* Wake up */ > + cx23885_flatiron_write(dev, CH_PWR_CTRL2, 0); > + > + if (video_debug) > + cx23885_flatiron_dump(dev); > + > + return 0; > +} > + > static int cx23885_video_mux(struct cx23885_dev *dev, unsigned int input) > { > dprintk(1, "%s() video_mux: %d [vmux=%d, gpio=0x%x,0x%x,0x%x,0x%x]\n", > @@ -414,27 +440,59 @@ static int cx23885_video_mux(struct cx23885_dev *dev, unsigned int input) > v4l2_subdev_call(dev->sd_cx25840, video, s_routing, > INPUT(input)->vmux, 0, 0); > > + if ((dev->board == CX23885_BOARD_HAUPPAUGE_HVR1800) || > + (dev->board == CX23885_BOARD_MPX885)) { > + /* Configure audio routing */ > + v4l2_subdev_call(dev->sd_cx25840, audio, s_routing, > + INPUT(input)->amux, 0, 0); > + > + if (INPUT(input)->amux == CX25840_AUDIO7) > + cx23885_flatiron_mux(dev, 1); > + else if (INPUT(input)->amux == CX25840_AUDIO6) > + cx23885_flatiron_mux(dev, 2); > + } > + > return 0; > } > > -/* ------------------------------------------------------------------ */ > -static int cx23885_set_scale(struct cx23885_dev *dev, unsigned int width, > - unsigned int height, enum v4l2_field field) > +static int cx23885_audio_mux(struct cx23885_dev *dev, unsigned int input) > { > - dprintk(1, "%s()\n", __func__); > + dprintk(1, "%s(input=%d)\n", __func__, input); > + > + /* The baseband video core of the cx23885 has two audio inputs. > + * LR1 and LR2. In almost every single case so far only HVR1xxx > + * cards we've only ever supported LR1. Time to support LR2, > + * which is available via the optional white breakout header on > + * the board. > + * We'll use a could of existing enums in the card struct to allow > + * devs to specify which baseband input they need, or just default > + * to what we've always used. > + */ > + if (INPUT(input)->amux == CX25840_AUDIO7) > + cx23885_flatiron_mux(dev, 1); > + else if (INPUT(input)->amux == CX25840_AUDIO6) > + cx23885_flatiron_mux(dev, 2); > + else { > + /* Not specifically defined, assume the default. */ > + cx23885_flatiron_mux(dev, 1); > + } > + > return 0; > } > > +/* ------------------------------------------------------------------ */ > static int cx23885_start_video_dma(struct cx23885_dev *dev, > struct cx23885_dmaqueue *q, > struct cx23885_buffer *buf) > { > dprintk(1, "%s()\n", __func__); > > + /* Stop the dma/fifo before we tamper with it's risc programs */ > + cx_clear(VID_A_DMA_CTL, 0x11); > + > /* setup fifo + format */ > cx23885_sram_channel_setup(dev, &dev->sram_channels[SRAM_CH01], > buf->bpl, buf->risc.dma); > - cx23885_set_scale(dev, buf->vb.width, buf->vb.height, buf->vb.field); > > /* reset counter */ > cx_write(VID_A_GPCNT_CTL, 3); > @@ -751,7 +809,7 @@ static int video_open(struct file *file) > fh->type = type; > fh->width = 320; > fh->height = 240; > - fh->fmt = format_by_fourcc(V4L2_PIX_FMT_BGR24); > + fh->fmt = format_by_fourcc(V4L2_PIX_FMT_YUYV); > > videobuf_queue_sg_init(&fh->vidq, &cx23885_video_qops, > &dev->pci->dev, &dev->slock, > @@ -760,6 +818,14 @@ static int video_open(struct file *file) > sizeof(struct cx23885_buffer), > fh); > > + videobuf_queue_sg_init(&fh->vbiq, &cx23885_vbi_qops, > + &dev->pci->dev, &dev->slock, > + V4L2_BUF_TYPE_VBI_CAPTURE, > + V4L2_FIELD_SEQ_TB, > + sizeof(struct cx23885_buffer), > + fh); > + > + > dprintk(1, "post videobuf_queue_init()\n"); > > unlock_kernel(); > @@ -857,6 +923,8 @@ static int video_release(struct file *file) > } > > videobuf_mmap_free(&fh->vidq); > + videobuf_mmap_free(&fh->vbiq); > + > file->private_data = NULL; > kfree(fh); > > @@ -889,8 +957,9 @@ static int cx23885_get_control(struct cx23885_dev *dev, > static int cx23885_set_control(struct cx23885_dev *dev, > struct v4l2_control *ctl) > { > - dprintk(1, "%s() calling cx25840(VIDIOC_S_CTRL)" > - " (disabled - no action)\n", __func__); > + dprintk(1, "%s() calling cx25840(VIDIOC_S_CTRL)\n", __func__); > + call_all(dev, core, s_ctrl, ctl); > + > return 0; > } > > @@ -1094,13 +1163,22 @@ static int vidioc_streamon(struct file *file, void *priv, > struct cx23885_dev *dev = fh->dev; > dprintk(1, "%s()\n", __func__); > > - if (unlikely(fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)) > + if ((fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) && > + (fh->type != V4L2_BUF_TYPE_VBI_CAPTURE)) > return -EINVAL; > if (unlikely(i != fh->type)) > return -EINVAL; > > if (unlikely(!res_get(dev, fh, get_resource(fh)))) > return -EBUSY; > + > + /* Don't start VBI streaming unless vida streaming > + * has already started. > + */ > + if ((fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) && > + ((cx_read(VID_A_DMA_CTL) & 0x11) == 0)) > + return -EINVAL; > + > return videobuf_streamon(get_queue(fh)); > } > > @@ -1111,7 +1189,8 @@ static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i) > int err, res; > dprintk(1, "%s()\n", __func__); > > - if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) > + if ((fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) && > + (fh->type != V4L2_BUF_TYPE_VBI_CAPTURE)) > return -EINVAL; > if (i != fh->type) > return -EINVAL; > @@ -1154,7 +1233,7 @@ static int cx23885_enum_input(struct cx23885_dev *dev, struct v4l2_input *i) > dprintk(1, "%s()\n", __func__); > > n = i->index; > - if (n >= 4) > + if (n >= MAX_CX23885_INPUT) > return -EINVAL; > > if (0 == INPUT(n)->type) > @@ -1168,6 +1247,11 @@ static int cx23885_enum_input(struct cx23885_dev *dev, struct v4l2_input *i) > (CX23885_VMUX_CABLE == INPUT(n)->type)) > i->type = V4L2_INPUT_TYPE_TUNER; > i->std = CX23885_NORMS; > + > + /* Two selectable audio inputs for non-tv inputs */ > + if (INPUT(n)->type != CX23885_VMUX_TELEVISION) > + i->audioset = 0x3; > + > return 0; > } > > @@ -1194,13 +1278,20 @@ static int vidioc_s_input(struct file *file, void *priv, unsigned int i) > > dprintk(1, "%s(%d)\n", __func__, i); > > - if (i >= 4) { > + if (i >= MAX_CX23885_INPUT) { > dprintk(1, "%s() -EINVAL\n", __func__); > return -EINVAL; > } > > + if (INPUT(i)->type == 0) > + return -EINVAL; > + > mutex_lock(&dev->lock); > cx23885_video_mux(dev, i); > + > + /* By default establish the default audio input for the card also */ > + /* Caller is free to use VIDIOC_S_AUDIO to override afterwards */ > + cx23885_audio_mux(dev, i); > mutex_unlock(&dev->lock); > return 0; > } > @@ -1220,6 +1311,64 @@ static int vidioc_log_status(struct file *file, void *priv) > return 0; > } > > +static int cx23885_query_audinput(struct file *file, void *priv, > + struct v4l2_audio *i) > +{ > + struct cx23885_dev *dev = ((struct cx23885_fh *)priv)->dev; > + static const char *iname[] = { > + [0] = "Baseband L/R 1", > + [1] = "Baseband L/R 2", > + }; > + unsigned int n; > + dprintk(1, "%s()\n", __func__); > + > + n = i->index; > + if (n >= 2) > + return -EINVAL; > + > + memset(i, 0, sizeof(*i)); > + i->index = n; > + strcpy(i->name, iname[n]); > + i->capability = V4L2_AUDCAP_STEREO; > + i->mode = V4L2_AUDMODE_AVL; > + return 0; > + > +} > + > +static int vidioc_enum_audinput(struct file *file, void *priv, > + struct v4l2_audio *i) > +{ > + return cx23885_query_audinput(file, priv, i); > +} > + > +static int vidioc_g_audinput(struct file *file, void *priv, > + struct v4l2_audio *i) > +{ > + struct cx23885_dev *dev = ((struct cx23885_fh *)priv)->dev; > + > + i->index = dev->audinput; > + dprintk(1, "%s(input=%d)\n", __func__, i->index); > + > + return cx23885_query_audinput(file, priv, i); > +} > + > +static int vidioc_s_audinput(struct file *file, void *priv, > + struct v4l2_audio *i) > +{ > + struct cx23885_dev *dev = ((struct cx23885_fh *)priv)->dev; > + if (i->index >= 2) > + return -EINVAL; > + > + dprintk(1, "%s(%d)\n", __func__, i->index); > + > + dev->audinput = i->index; > + > + /* Skip the audio defaults from the cards struct, caller wants > + * directly touch the audio mux hardware. */ > + cx23885_flatiron_mux(dev, dev->audinput + 1); > + return 0; > +} > + > static int vidioc_queryctrl(struct file *file, void *priv, > struct v4l2_queryctrl *qctrl) > { > @@ -1255,11 +1404,11 @@ static int vidioc_g_tuner(struct file *file, void *priv, > if (0 != t->index) > return -EINVAL; > > + memset(t, 0, sizeof(*t)); There's no need. video_ioctl2 should already cleanup the return parameters. > strcpy(t->name, "Television"); > - t->type = V4L2_TUNER_ANALOG_TV; > - t->capability = V4L2_TUNER_CAP_NORM; > - t->rangehigh = 0xffffffffUL; > - t->signal = 0xffff ; /* LOCKED */ > + > + call_all(dev, tuner, g_tuner, t); > + > return 0; > } > > @@ -1272,6 +1421,9 @@ static int vidioc_s_tuner(struct file *file, void *priv, > return -EINVAL; > if (0 != t->index) > return -EINVAL; > + /* Update the A/V core */ > + call_all(dev, tuner, s_tuner, t); > + > return 0; > } > > @@ -1295,18 +1447,30 @@ static int vidioc_g_frequency(struct file *file, void *priv, > > static int cx23885_set_freq(struct cx23885_dev *dev, struct v4l2_frequency *f) > { > + struct v4l2_control ctrl; > + > if (unlikely(UNSET == dev->tuner_type)) > return -EINVAL; > if (unlikely(f->tuner != 0)) > return -EINVAL; > > + > mutex_lock(&dev->lock); > dev->freq = f->frequency; > > + /* I need to mute audio here */ > + ctrl.id = V4L2_CID_AUDIO_MUTE; > + ctrl.value = 1; > + cx23885_set_control(dev, &ctrl); > + > call_all(dev, tuner, s_frequency, f); > > /* When changing channels it is required to reset TVAUDIO */ > - msleep(10); > + msleep(100); > + > + /* I need to unmute audio here */ > + ctrl.value = 0; > + cx23885_set_control(dev, &ctrl); > > mutex_unlock(&dev->lock); > > @@ -1337,9 +1501,7 @@ static void cx23885_vid_timeout(unsigned long data) > struct cx23885_buffer *buf; > unsigned long flags; > > - cx23885_sram_channel_dump(dev, &dev->sram_channels[SRAM_CH01]); > - > - cx_clear(VID_A_DMA_CTL, 0x11); > + dprintk(1, "%s()\n", __func__); > > spin_lock_irqsave(&dev->slock, flags); > while (!list_empty(&q->active)) { > @@ -1348,7 +1510,7 @@ static void cx23885_vid_timeout(unsigned long data) > list_del(&buf->vb.queue); > buf->vb.state = VIDEOBUF_ERROR; > wake_up(&buf->vb.done); > - printk(KERN_ERR "%s/0: [%p/%d] timeout - dma=0x%08lx\n", > + printk(KERN_ERR "%s: [%p/%d] timeout - dma=0x%08lx\n", > dev->name, buf, buf->vb.i, > (unsigned long)buf->risc.dma); > } > @@ -1361,30 +1523,46 @@ int cx23885_video_irq(struct cx23885_dev *dev, u32 status) > u32 mask, count; > int handled = 0; > > - mask = cx_read(VID_A_INT_MSK); > + mask = cx_read(VID_A_INT_MSK); > if (0 == (status & mask)) > return handled; > + > cx_write(VID_A_INT_STAT, status); > > - dprintk(2, "%s() status = 0x%08x\n", __func__, status); > - /* risc op code error */ > - if (status & (1 << 16)) { > - printk(KERN_WARNING "%s/0: video risc op code error\n", > - dev->name); > - cx_clear(VID_A_DMA_CTL, 0x11); > - cx23885_sram_channel_dump(dev, &dev->sram_channels[SRAM_CH01]); > + /* risc op code error, fifo overflow or line sync detection error */ > + if ((status & VID_BC_MSK_OPC_ERR) || > + (status & VID_BC_MSK_SYNC) || > + (status & VID_BC_MSK_OF)) { > + > + if (status & VID_BC_MSK_OPC_ERR) { > + dprintk(7, " (VID_BC_MSK_OPC_ERR 0x%08x)\n", > + VID_BC_MSK_OPC_ERR); > + printk(KERN_WARNING "%s: video risc op code error\n", > + dev->name); > + cx23885_sram_channel_dump(dev, > + &dev->sram_channels[SRAM_CH01]); > + } > + > + if (status & VID_BC_MSK_SYNC) > + dprintk(7, " (VID_BC_MSK_SYNC 0x%08x) " > + "video lines miss-match\n", > + VID_BC_MSK_SYNC); > + > + if (status & VID_BC_MSK_OF) > + dprintk(7, " (VID_BC_MSK_OF 0x%08x) fifo overflow\n", > + VID_BC_MSK_OF); > + > } > > - /* risc1 y */ > - if (status & 0x01) { > + /* Video */ > + if (status & VID_BC_MSK_RISCI1) { > spin_lock(&dev->slock); > count = cx_read(VID_A_GPCNT); > cx23885_video_wakeup(dev, &dev->vidq, count); > spin_unlock(&dev->slock); > handled++; > } > - /* risc2 y */ > - if (status & 0x10) { > + if (status & VID_BC_MSK_RISCI2) { > dprintk(2, "stopper video\n"); > spin_lock(&dev->slock); > cx23885_restart_video_queue(dev, &dev->vidq); > @@ -1392,6 +1570,9 @@ int cx23885_video_irq(struct cx23885_dev *dev, u32 status) > handled++; > } > > + /* Allow the VBI framework to process it's payload */ > + handled += cx23885_vbi_irq(dev, status); > + > return handled; > } > > @@ -1443,6 +1624,9 @@ static const struct v4l2_ioctl_ops video_ioctl_ops = { > .vidioc_g_register = cx23885_g_register, > .vidioc_s_register = cx23885_s_register, > #endif > + .vidioc_enumaudio = vidioc_enum_audinput, > + .vidioc_g_audio = vidioc_g_audinput, > + .vidioc_s_audio = vidioc_s_audinput, > }; > > static struct video_device cx23885_vbi_template; > @@ -1467,6 +1651,14 @@ void cx23885_video_unregister(struct cx23885_dev *dev) > dprintk(1, "%s()\n", __func__); > cx23885_irq_remove(dev, 0x01); > > + if (dev->vbi_dev) { > + if (video_is_registered(dev->vbi_dev)) > + video_unregister_device(dev->vbi_dev); > + else > + video_device_release(dev->vbi_dev); > + dev->vbi_dev = NULL; > + btcx_riscmem_free(dev->pci, &dev->vbiq.stopper); > + } > if (dev->video_dev) { > if (video_is_registered(dev->video_dev)) > video_unregister_device(dev->video_dev); > @@ -1476,6 +1668,9 @@ void cx23885_video_unregister(struct cx23885_dev *dev) > > btcx_riscmem_free(dev->pci, &dev->vidq.stopper); > } > + > + if (dev->audio_dev) > + cx23885_audio_unregister(dev); > } > > int cx23885_video_register(struct cx23885_dev *dev) > @@ -1502,6 +1697,13 @@ int cx23885_video_register(struct cx23885_dev *dev) > VID_A_DMA_CTL, 0x11, 0x00); > > /* Don't enable VBI yet */ > + INIT_LIST_HEAD(&dev->vbiq.active); > + INIT_LIST_HEAD(&dev->vbiq.queued); > + dev->vbiq.timeout.function = cx23885_vbi_timeout; > + dev->vbiq.timeout.data = (unsigned long)dev; > + init_timer(&dev->vbiq.timeout); > + cx23885_risc_stopper(dev->pci, &dev->vbiq.stopper, > + VID_A_DMA_CTL, 0x22, 0x00); > > cx23885_irq_add_enable(dev, 0x01); > > @@ -1515,7 +1717,8 @@ int cx23885_video_register(struct cx23885_dev *dev) > else > sd = v4l2_i2c_new_subdev(&dev->v4l2_dev, > &dev->i2c_bus[1].i2c_adap, > - "tuner", "tuner", 0, v4l2_i2c_tuner_addrs(ADDRS_TV)); > + "tuner", "tuner", 0, > + v4l2_i2c_tuner_addrs(ADDRS_TV)); > if (sd) { > struct tuner_setup tun_setup; > > @@ -1527,7 +1730,8 @@ int cx23885_video_register(struct cx23885_dev *dev) > > v4l2_subdev_call(sd, tuner, s_type_addr, &tun_setup); > > - if (dev->board == CX23885_BOARD_LEADTEK_WINFAST_PXTV1200) { > + if (dev->board == > + CX23885_BOARD_LEADTEK_WINFAST_PXTV1200) { > struct xc2028_ctrl ctrl = { > .fname = XC2028_DEFAULT_FIRMWARE, > .max_len = 64 > @@ -1541,8 +1745,7 @@ int cx23885_video_register(struct cx23885_dev *dev) > } > } > > - > - /* register v4l devices */ > + /* register Video device */ > dev->video_dev = cx23885_vdev_init(dev, dev->pci, > &cx23885_video_template, "video"); > err = video_register_device(dev->video_dev, VFL_TYPE_GRABBER, > @@ -1552,13 +1755,32 @@ int cx23885_video_register(struct cx23885_dev *dev) > dev->name); > goto fail_unreg; > } > - printk(KERN_INFO "%s/0: registered device %s [v4l2]\n", > + printk(KERN_INFO "%s: registered device %s [v4l2]\n", > dev->name, video_device_node_name(dev->video_dev)); > + > + /* register VBI device */ > + dev->vbi_dev = cx23885_vdev_init(dev, dev->pci, > + &cx23885_vbi_template, "vbi"); > + err = video_register_device(dev->vbi_dev, VFL_TYPE_VBI, > + vbi_nr[dev->nr]); > + if (err < 0) { > + printk(KERN_INFO "%s: can't register vbi device\n", > + dev->name); > + goto fail_unreg; > + } > + printk(KERN_INFO "%s: registered device %s\n", > + dev->name, video_device_node_name(dev->vbi_dev)); > + > + > + /* Register ALSA audio device */ > + dev->audio_dev = cx23885_audio_register(dev); > + > /* initial device configuration */ > mutex_lock(&dev->lock); > cx23885_set_tvnorm(dev, dev->tvnorm); > init_controls(dev); > cx23885_video_mux(dev, 0); > + cx23885_audio_mux(dev, 0); > mutex_unlock(&dev->lock); > > return 0; > diff --git a/drivers/media/video/cx23885/cx23885.h b/drivers/media/video/cx23885/cx23885.h > index ed94b17..d3468d6 100644 > --- a/drivers/media/video/cx23885/cx23885.h > +++ b/drivers/media/video/cx23885/cx23885.h > @@ -84,6 +84,7 @@ > #define CX23885_BOARD_HAUPPAUGE_HVR1290 26 > #define CX23885_BOARD_MYGICA_X8558PRO 27 > #define CX23885_BOARD_LEADTEK_WINFAST_PXTV1200 28 > +#define CX23885_BOARD_MPX885 29 > > #define GPIO_0 0x00000001 > #define GPIO_1 0x00000002 > @@ -190,6 +191,7 @@ struct cx23885_buffer { > struct cx23885_input { > enum cx23885_itype type; > unsigned int vmux; > + unsigned int amux; > u32 gpio0, gpio1, gpio2, gpio3; > }; > > @@ -314,6 +316,28 @@ struct cx23885_kernel_ir { > struct ir_dev_props props; > }; > > +struct cx23885_audio_dev { > + struct cx23885_dev *dev; > + > + struct pci_dev *pci; > + > + struct snd_card *card; > + > + spinlock_t lock; > + > + atomic_t count; > + > + unsigned int dma_size; > + unsigned int period_size; > + unsigned int num_periods; > + > + struct videobuf_dmabuf *dma_risc; > + > + struct cx23885_buffer *buf; > + > + struct snd_pcm_substream *substream; > +}; > + > struct cx23885_dev { > atomic_t refcount; > struct v4l2_device v4l2_dev; > @@ -358,6 +382,7 @@ struct cx23885_dev { > /* Analog video */ > u32 resources; > unsigned int input; > + unsigned int audinput; /* Selectable audio input */ > u32 tvaudio; > v4l2_std_id tvnorm; > unsigned int tuner_type; > @@ -395,6 +420,9 @@ struct cx23885_dev { > atomic_t v4l_reader_count; > struct cx23885_tvnorm encodernorm; > > + /* Analog raw audio */ > + struct cx23885_audio_dev *audio_dev; > + > }; > > static inline struct cx23885_dev *to_cx23885(struct v4l2_device *v4l2_dev) > @@ -473,6 +501,12 @@ extern int cx23885_risc_buffer(struct pci_dev *pci, struct btcx_riscmem *risc, > unsigned int top_offset, unsigned int bottom_offset, > unsigned int bpl, unsigned int padding, unsigned int lines); > > +extern int cx23885_risc_vbibuffer(struct pci_dev *pci, > + struct btcx_riscmem *risc, > + struct scatterlist *sglist, > + unsigned int top_offset, unsigned int bottom_offset, > + unsigned int bpl, unsigned int padding, unsigned int lines); > + > void cx23885_cancel_buffers(struct cx23885_tsport *port); > > extern int cx23885_restart_queue(struct cx23885_tsport *port, > @@ -528,6 +562,8 @@ extern void cx23885_free_buffer(struct videobuf_queue *q, > extern int cx23885_video_register(struct cx23885_dev *dev); > extern void cx23885_video_unregister(struct cx23885_dev *dev); > extern int cx23885_video_irq(struct cx23885_dev *dev, u32 status); > +extern void cx23885_video_wakeup(struct cx23885_dev *dev, > + struct cx23885_dmaqueue *q, u32 count); > > /* ----------------------------------------------------------- */ > /* cx23885-vbi.c */ > @@ -535,6 +571,9 @@ extern int cx23885_vbi_fmt(struct file *file, void *priv, > struct v4l2_format *f); > extern void cx23885_vbi_timeout(unsigned long data); > extern struct videobuf_queue_ops cx23885_vbi_qops; > +extern int cx23885_restart_vbi_queue(struct cx23885_dev *dev, > + struct cx23885_dmaqueue *q); > +extern int cx23885_vbi_irq(struct cx23885_dev *dev, u32 status); > > /* cx23885-i2c.c */ > extern int cx23885_i2c_register(struct cx23885_i2c *bus); > @@ -558,6 +597,18 @@ extern void mc417_gpio_set(struct cx23885_dev *dev, u32 mask); > extern void mc417_gpio_clear(struct cx23885_dev *dev, u32 mask); > extern void mc417_gpio_enable(struct cx23885_dev *dev, u32 mask, int asoutput); > > +/* ----------------------------------------------------------- */ > +/* cx23885-alsa.c */ > +extern struct cx23885_audio_dev *cx23885_audio_register( > + struct cx23885_dev *dev); > +extern void cx23885_audio_unregister(struct cx23885_dev *dev); > +extern int cx23885_audio_irq(struct cx23885_dev *dev, u32 status, u32 mask); > +extern int cx23885_risc_databuffer(struct pci_dev *pci, > + struct btcx_riscmem *risc, > + struct scatterlist *sglist, > + unsigned int bpl, > + unsigned int lines, > + unsigned int lpi); > > /* ----------------------------------------------------------- */ > /* tv norms */ > diff --git a/drivers/media/video/cx25840/cx25840-audio.c b/drivers/media/video/cx25840/cx25840-audio.c > index 45608d5..e25c012 100644 > --- a/drivers/media/video/cx25840/cx25840-audio.c > +++ b/drivers/media/video/cx25840/cx25840-audio.c > @@ -514,7 +514,14 @@ static void set_volume(struct i2c_client *client, int volume) > } > > /* PATH1_VOLUME */ > - cx25840_write(client, 0x8d4, 228 - (vol * 2)); > + if (is_cx2388x(state)) { > + /* for cx23885 volume doesn't work, > + * the calculation always results in > + * e4 regardless. > + */ > + cx25840_write(client, 0x8d4, volume); > + } else > + cx25840_write(client, 0x8d4, 228 - (vol * 2)); > } > If I understood well, from Andy's comments, the 228 - (vol * 2) formula is only there to make ivtv driver happy. If ivtv expects a different scale for whatever reason, the scale logic should be at ivtv, and not at cx25840. > static int get_bass(struct i2c_client *client) > diff --git a/drivers/media/video/cx25840/cx25840-core.c b/drivers/media/video/cx25840/cx25840-core.c > index 9fab0b1..eca8656 100644 > --- a/drivers/media/video/cx25840/cx25840-core.c > +++ b/drivers/media/video/cx25840/cx25840-core.c > @@ -703,6 +703,13 @@ static void cx231xx_initialize(struct i2c_client *client) > > /* start microcontroller */ > cx25840_and_or(client, 0x803, ~0x10, 0x10); > + > + /* CC raw enable */ > + cx25840_write(client, 0x404, 0x0b); > + > + /* CC on */ > + cx25840_write(client, 0x42f, 0x66); > + cx25840_write4(client, 0x474, 0x1e1e601a); > } > > /* ----------------------------------------------------------------------- */ > @@ -1065,6 +1072,18 @@ static int set_input(struct i2c_client *client, enum cx25840_video_input vid_inp > cx25840_write(client, 0x919, 0x01); > } > > + if (is_cx2388x(state) && ((aud_input == CX25840_AUDIO7) || > + (aud_input == CX25840_AUDIO6))) { > + /* Configure audio from LR1 or LR2 input */ > + cx25840_write4(client, 0x910, 0); > + cx25840_write4(client, 0x8d0, 0x63073); > + } else > + if (is_cx2388x(state) && (aud_input == CX25840_AUDIO8)) { > + /* Configure audio from tuner/sif input */ > + cx25840_write4(client, 0x910, 0x12b000c9); > + cx25840_write4(client, 0x8d0, 0x1f063870); > + } > + > return 0; > } > -- To unsubscribe from this list: send the line "unsubscribe linux-media" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html