Path: blob/master/drivers/media/video/cx88/cx88-vbi.c
17745 views
/*1*/2#include <linux/kernel.h>3#include <linux/module.h>4#include <linux/init.h>56#include "cx88.h"78static unsigned int vbibufs = 4;9module_param(vbibufs,int,0644);10MODULE_PARM_DESC(vbibufs,"number of vbi buffers, range 2-32");1112static unsigned int vbi_debug;13module_param(vbi_debug,int,0644);14MODULE_PARM_DESC(vbi_debug,"enable debug messages [vbi]");1516#define dprintk(level,fmt, arg...) if (vbi_debug >= level) \17printk(KERN_DEBUG "%s: " fmt, dev->core->name , ## arg)1819/* ------------------------------------------------------------------ */2021int cx8800_vbi_fmt (struct file *file, void *priv,22struct v4l2_format *f)23{24struct cx8800_fh *fh = priv;25struct cx8800_dev *dev = fh->dev;2627f->fmt.vbi.samples_per_line = VBI_LINE_LENGTH;28f->fmt.vbi.sample_format = V4L2_PIX_FMT_GREY;29f->fmt.vbi.offset = 244;30f->fmt.vbi.count[0] = VBI_LINE_COUNT;31f->fmt.vbi.count[1] = VBI_LINE_COUNT;3233if (dev->core->tvnorm & V4L2_STD_525_60) {34/* ntsc */35f->fmt.vbi.sampling_rate = 28636363;36f->fmt.vbi.start[0] = 10;37f->fmt.vbi.start[1] = 273;3839} else if (dev->core->tvnorm & V4L2_STD_625_50) {40/* pal */41f->fmt.vbi.sampling_rate = 35468950;42f->fmt.vbi.start[0] = 7 -1;43f->fmt.vbi.start[1] = 319 -1;44}45return 0;46}4748static int cx8800_start_vbi_dma(struct cx8800_dev *dev,49struct cx88_dmaqueue *q,50struct cx88_buffer *buf)51{52struct cx88_core *core = dev->core;5354/* setup fifo + format */55cx88_sram_channel_setup(dev->core, &cx88_sram_channels[SRAM_CH24],56buf->vb.width, buf->risc.dma);5758cx_write(MO_VBOS_CONTROL, ( (1 << 18) | // comb filter delay fixup59(1 << 15) | // enable vbi capture60(1 << 11) ));6162/* reset counter */63cx_write(MO_VBI_GPCNTRL, GP_COUNT_CONTROL_RESET);64q->count = 1;6566/* enable irqs */67cx_set(MO_PCI_INTMSK, core->pci_irqmask | PCI_INT_VIDINT);68cx_set(MO_VID_INTMSK, 0x0f0088);6970/* enable capture */71cx_set(VID_CAPTURE_CONTROL,0x18);7273/* start dma */74cx_set(MO_DEV_CNTRL2, (1<<5));75cx_set(MO_VID_DMACNTRL, 0x88);7677return 0;78}7980int cx8800_stop_vbi_dma(struct cx8800_dev *dev)81{82struct cx88_core *core = dev->core;8384/* stop dma */85cx_clear(MO_VID_DMACNTRL, 0x88);8687/* disable capture */88cx_clear(VID_CAPTURE_CONTROL,0x18);8990/* disable irqs */91cx_clear(MO_PCI_INTMSK, PCI_INT_VIDINT);92cx_clear(MO_VID_INTMSK, 0x0f0088);93return 0;94}9596int cx8800_restart_vbi_queue(struct cx8800_dev *dev,97struct cx88_dmaqueue *q)98{99struct cx88_buffer *buf;100101if (list_empty(&q->active))102return 0;103104buf = list_entry(q->active.next, struct cx88_buffer, vb.queue);105dprintk(2,"restart_queue [%p/%d]: restart dma\n",106buf, buf->vb.i);107cx8800_start_vbi_dma(dev, q, buf);108list_for_each_entry(buf, &q->active, vb.queue)109buf->count = q->count++;110mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT);111return 0;112}113114void cx8800_vbi_timeout(unsigned long data)115{116struct cx8800_dev *dev = (struct cx8800_dev*)data;117struct cx88_core *core = dev->core;118struct cx88_dmaqueue *q = &dev->vbiq;119struct cx88_buffer *buf;120unsigned long flags;121122cx88_sram_channel_dump(dev->core, &cx88_sram_channels[SRAM_CH24]);123124cx_clear(MO_VID_DMACNTRL, 0x88);125cx_clear(VID_CAPTURE_CONTROL, 0x18);126127spin_lock_irqsave(&dev->slock,flags);128while (!list_empty(&q->active)) {129buf = list_entry(q->active.next, struct cx88_buffer, vb.queue);130list_del(&buf->vb.queue);131buf->vb.state = VIDEOBUF_ERROR;132wake_up(&buf->vb.done);133printk("%s/0: [%p/%d] timeout - dma=0x%08lx\n", dev->core->name,134buf, buf->vb.i, (unsigned long)buf->risc.dma);135}136cx8800_restart_vbi_queue(dev,q);137spin_unlock_irqrestore(&dev->slock,flags);138}139140/* ------------------------------------------------------------------ */141142static int143vbi_setup(struct videobuf_queue *q, unsigned int *count, unsigned int *size)144{145*size = VBI_LINE_COUNT * VBI_LINE_LENGTH * 2;146if (0 == *count)147*count = vbibufs;148if (*count < 2)149*count = 2;150if (*count > 32)151*count = 32;152return 0;153}154155static int156vbi_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb,157enum v4l2_field field)158{159struct cx8800_fh *fh = q->priv_data;160struct cx8800_dev *dev = fh->dev;161struct cx88_buffer *buf = container_of(vb,struct cx88_buffer,vb);162unsigned int size;163int rc;164165size = VBI_LINE_COUNT * VBI_LINE_LENGTH * 2;166if (0 != buf->vb.baddr && buf->vb.bsize < size)167return -EINVAL;168169if (VIDEOBUF_NEEDS_INIT == buf->vb.state) {170struct videobuf_dmabuf *dma=videobuf_to_dma(&buf->vb);171buf->vb.width = VBI_LINE_LENGTH;172buf->vb.height = VBI_LINE_COUNT;173buf->vb.size = size;174buf->vb.field = V4L2_FIELD_SEQ_TB;175176if (0 != (rc = videobuf_iolock(q,&buf->vb,NULL)))177goto fail;178cx88_risc_buffer(dev->pci, &buf->risc,179dma->sglist,1800, buf->vb.width * buf->vb.height,181buf->vb.width, 0,182buf->vb.height);183}184buf->vb.state = VIDEOBUF_PREPARED;185return 0;186187fail:188cx88_free_buffer(q,buf);189return rc;190}191192static void193vbi_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb)194{195struct cx88_buffer *buf = container_of(vb,struct cx88_buffer,vb);196struct cx88_buffer *prev;197struct cx8800_fh *fh = vq->priv_data;198struct cx8800_dev *dev = fh->dev;199struct cx88_dmaqueue *q = &dev->vbiq;200201/* add jump to stopper */202buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC);203buf->risc.jmp[1] = cpu_to_le32(q->stopper.dma);204205if (list_empty(&q->active)) {206list_add_tail(&buf->vb.queue,&q->active);207cx8800_start_vbi_dma(dev, q, buf);208buf->vb.state = VIDEOBUF_ACTIVE;209buf->count = q->count++;210mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT);211dprintk(2,"[%p/%d] vbi_queue - first active\n",212buf, buf->vb.i);213214} else {215prev = list_entry(q->active.prev, struct cx88_buffer, vb.queue);216list_add_tail(&buf->vb.queue,&q->active);217buf->vb.state = VIDEOBUF_ACTIVE;218buf->count = q->count++;219prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma);220dprintk(2,"[%p/%d] buffer_queue - append to active\n",221buf, buf->vb.i);222}223}224225static void vbi_release(struct videobuf_queue *q, struct videobuf_buffer *vb)226{227struct cx88_buffer *buf = container_of(vb,struct cx88_buffer,vb);228229cx88_free_buffer(q,buf);230}231232const struct videobuf_queue_ops cx8800_vbi_qops = {233.buf_setup = vbi_setup,234.buf_prepare = vbi_prepare,235.buf_queue = vbi_queue,236.buf_release = vbi_release,237};238239/* ------------------------------------------------------------------ */240/*241* Local variables:242* c-basic-offset: 8243* End:244*/245246247