forked from Minki/linux
399426cadf
Usually, I don't like fixing coding style issues on non-staging drivers, as it could be a mess pretty easy, and could become like a snow ball. That's the case of recent changes on two changesets: they disalign some statements. Yet, a care a lot with cx88 driver, as it was the first driver I touched at the Kernel, and I've been maintaining it since 2005. So, several of the coding style issues were due to my code. Per Andrey's suggestion, I ran checkpatch.pl in strict mode, with fixed several other issues, did some function alinments, but broke other alinments. So, I had to manually apply another round of manual fixes to make sure that everything is ok, and to make checkpatch happy with this patch. With this patch, checkpatch.pl is now happy when called with: ./scripts/checkpatch.pl -f --max-line-length=998 --ignore PREFER_PR_LEVEL Also, the 80-cols violations that made sense were fixed. Checkpatch would be happier if we convert it to use dev_foo(), but this is a more complex change. NOTE: there are some places with msleep(1). As this driver was written at the time that the default was to sleep at least 10ms on such calls (e. g. CONFIG_HZ=100), I replaced those calls by usleep_range(10000, 20000), with should be safe to avoid breakages. Fixes:65bc2fe86e
("[media] cx88: convert it to use pr_foo() macros") Fixes:7b61ba8ff8
("[media] cx88: make checkpatch happier") Suggested-by: Andrey Utkin <andrey_utkin@fastmail.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com> Reviewed-by: Andrey Utkin <andrey_utkin@fastmail.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
236 lines
6.3 KiB
C
236 lines
6.3 KiB
C
/*
|
|
*/
|
|
|
|
#include "cx88.h"
|
|
|
|
#include <linux/kernel.h>
|
|
#include <linux/module.h>
|
|
#include <linux/init.h>
|
|
|
|
static unsigned int vbi_debug;
|
|
module_param(vbi_debug, int, 0644);
|
|
MODULE_PARM_DESC(vbi_debug, "enable debug messages [vbi]");
|
|
|
|
#define dprintk(level, fmt, arg...) do { \
|
|
if (vbi_debug >= level) \
|
|
printk(KERN_DEBUG pr_fmt("%s: vbi:" fmt), \
|
|
__func__, ##arg); \
|
|
} while (0)
|
|
|
|
/* ------------------------------------------------------------------ */
|
|
|
|
int cx8800_vbi_fmt(struct file *file, void *priv,
|
|
struct v4l2_format *f)
|
|
{
|
|
struct cx8800_dev *dev = video_drvdata(file);
|
|
|
|
f->fmt.vbi.samples_per_line = VBI_LINE_LENGTH;
|
|
f->fmt.vbi.sample_format = V4L2_PIX_FMT_GREY;
|
|
f->fmt.vbi.offset = 244;
|
|
|
|
if (dev->core->tvnorm & V4L2_STD_525_60) {
|
|
/* ntsc */
|
|
f->fmt.vbi.sampling_rate = 28636363;
|
|
f->fmt.vbi.start[0] = 10;
|
|
f->fmt.vbi.start[1] = 273;
|
|
f->fmt.vbi.count[0] = VBI_LINE_NTSC_COUNT;
|
|
f->fmt.vbi.count[1] = VBI_LINE_NTSC_COUNT;
|
|
|
|
} else if (dev->core->tvnorm & V4L2_STD_625_50) {
|
|
/* pal */
|
|
f->fmt.vbi.sampling_rate = 35468950;
|
|
f->fmt.vbi.start[0] = V4L2_VBI_ITU_625_F1_START + 5;
|
|
f->fmt.vbi.start[1] = V4L2_VBI_ITU_625_F2_START + 5;
|
|
f->fmt.vbi.count[0] = VBI_LINE_PAL_COUNT;
|
|
f->fmt.vbi.count[1] = VBI_LINE_PAL_COUNT;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static int cx8800_start_vbi_dma(struct cx8800_dev *dev,
|
|
struct cx88_dmaqueue *q,
|
|
struct cx88_buffer *buf)
|
|
{
|
|
struct cx88_core *core = dev->core;
|
|
|
|
/* setup fifo + format */
|
|
cx88_sram_channel_setup(dev->core, &cx88_sram_channels[SRAM_CH24],
|
|
VBI_LINE_LENGTH, buf->risc.dma);
|
|
|
|
cx_write(MO_VBOS_CONTROL, (1 << 18) | /* comb filter delay fixup */
|
|
(1 << 15) | /* enable vbi capture */
|
|
(1 << 11));
|
|
|
|
/* reset counter */
|
|
cx_write(MO_VBI_GPCNTRL, GP_COUNT_CONTROL_RESET);
|
|
q->count = 0;
|
|
|
|
/* enable irqs */
|
|
cx_set(MO_PCI_INTMSK, core->pci_irqmask | PCI_INT_VIDINT);
|
|
cx_set(MO_VID_INTMSK, 0x0f0088);
|
|
|
|
/* enable capture */
|
|
cx_set(VID_CAPTURE_CONTROL, 0x18);
|
|
|
|
/* start dma */
|
|
cx_set(MO_DEV_CNTRL2, (1 << 5));
|
|
cx_set(MO_VID_DMACNTRL, 0x88);
|
|
|
|
return 0;
|
|
}
|
|
|
|
void cx8800_stop_vbi_dma(struct cx8800_dev *dev)
|
|
{
|
|
struct cx88_core *core = dev->core;
|
|
|
|
/* stop dma */
|
|
cx_clear(MO_VID_DMACNTRL, 0x88);
|
|
|
|
/* disable capture */
|
|
cx_clear(VID_CAPTURE_CONTROL, 0x18);
|
|
|
|
/* disable irqs */
|
|
cx_clear(MO_PCI_INTMSK, PCI_INT_VIDINT);
|
|
cx_clear(MO_VID_INTMSK, 0x0f0088);
|
|
}
|
|
|
|
int cx8800_restart_vbi_queue(struct cx8800_dev *dev,
|
|
struct cx88_dmaqueue *q)
|
|
{
|
|
struct cx88_buffer *buf;
|
|
|
|
if (list_empty(&q->active))
|
|
return 0;
|
|
|
|
buf = list_entry(q->active.next, struct cx88_buffer, list);
|
|
dprintk(2, "restart_queue [%p/%d]: restart dma\n",
|
|
buf, buf->vb.vb2_buf.index);
|
|
cx8800_start_vbi_dma(dev, q, buf);
|
|
return 0;
|
|
}
|
|
|
|
/* ------------------------------------------------------------------ */
|
|
|
|
static int queue_setup(struct vb2_queue *q,
|
|
unsigned int *num_buffers, unsigned int *num_planes,
|
|
unsigned int sizes[], struct device *alloc_devs[])
|
|
{
|
|
struct cx8800_dev *dev = q->drv_priv;
|
|
|
|
*num_planes = 1;
|
|
if (dev->core->tvnorm & V4L2_STD_525_60)
|
|
sizes[0] = VBI_LINE_NTSC_COUNT * VBI_LINE_LENGTH * 2;
|
|
else
|
|
sizes[0] = VBI_LINE_PAL_COUNT * VBI_LINE_LENGTH * 2;
|
|
return 0;
|
|
}
|
|
|
|
static int buffer_prepare(struct vb2_buffer *vb)
|
|
{
|
|
struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
|
|
struct cx8800_dev *dev = vb->vb2_queue->drv_priv;
|
|
struct cx88_buffer *buf = container_of(vbuf, struct cx88_buffer, vb);
|
|
struct sg_table *sgt = vb2_dma_sg_plane_desc(vb, 0);
|
|
unsigned int lines;
|
|
unsigned int size;
|
|
|
|
if (dev->core->tvnorm & V4L2_STD_525_60)
|
|
lines = VBI_LINE_NTSC_COUNT;
|
|
else
|
|
lines = VBI_LINE_PAL_COUNT;
|
|
size = lines * VBI_LINE_LENGTH * 2;
|
|
if (vb2_plane_size(vb, 0) < size)
|
|
return -EINVAL;
|
|
vb2_set_plane_payload(vb, 0, size);
|
|
|
|
cx88_risc_buffer(dev->pci, &buf->risc, sgt->sgl,
|
|
0, VBI_LINE_LENGTH * lines,
|
|
VBI_LINE_LENGTH, 0,
|
|
lines);
|
|
return 0;
|
|
}
|
|
|
|
static void buffer_finish(struct vb2_buffer *vb)
|
|
{
|
|
struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
|
|
struct cx8800_dev *dev = vb->vb2_queue->drv_priv;
|
|
struct cx88_buffer *buf = container_of(vbuf, struct cx88_buffer, vb);
|
|
struct cx88_riscmem *risc = &buf->risc;
|
|
|
|
if (risc->cpu)
|
|
pci_free_consistent(dev->pci, risc->size, risc->cpu, risc->dma);
|
|
memset(risc, 0, sizeof(*risc));
|
|
}
|
|
|
|
static void buffer_queue(struct vb2_buffer *vb)
|
|
{
|
|
struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
|
|
struct cx8800_dev *dev = vb->vb2_queue->drv_priv;
|
|
struct cx88_buffer *buf = container_of(vbuf, struct cx88_buffer, vb);
|
|
struct cx88_buffer *prev;
|
|
struct cx88_dmaqueue *q = &dev->vbiq;
|
|
|
|
/* add jump to start */
|
|
buf->risc.cpu[1] = cpu_to_le32(buf->risc.dma + 8);
|
|
buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP | RISC_CNT_INC);
|
|
buf->risc.jmp[1] = cpu_to_le32(buf->risc.dma + 8);
|
|
|
|
if (list_empty(&q->active)) {
|
|
list_add_tail(&buf->list, &q->active);
|
|
cx8800_start_vbi_dma(dev, q, buf);
|
|
dprintk(2, "[%p/%d] vbi_queue - first active\n",
|
|
buf, buf->vb.vb2_buf.index);
|
|
|
|
} else {
|
|
buf->risc.cpu[0] |= cpu_to_le32(RISC_IRQ1);
|
|
prev = list_entry(q->active.prev, struct cx88_buffer, list);
|
|
list_add_tail(&buf->list, &q->active);
|
|
prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma);
|
|
dprintk(2, "[%p/%d] buffer_queue - append to active\n",
|
|
buf, buf->vb.vb2_buf.index);
|
|
}
|
|
}
|
|
|
|
static int start_streaming(struct vb2_queue *q, unsigned int count)
|
|
{
|
|
struct cx8800_dev *dev = q->drv_priv;
|
|
struct cx88_dmaqueue *dmaq = &dev->vbiq;
|
|
struct cx88_buffer *buf = list_entry(dmaq->active.next,
|
|
struct cx88_buffer, list);
|
|
|
|
cx8800_start_vbi_dma(dev, dmaq, buf);
|
|
return 0;
|
|
}
|
|
|
|
static void stop_streaming(struct vb2_queue *q)
|
|
{
|
|
struct cx8800_dev *dev = q->drv_priv;
|
|
struct cx88_core *core = dev->core;
|
|
struct cx88_dmaqueue *dmaq = &dev->vbiq;
|
|
unsigned long flags;
|
|
|
|
cx_clear(MO_VID_DMACNTRL, 0x11);
|
|
cx_clear(VID_CAPTURE_CONTROL, 0x06);
|
|
cx8800_stop_vbi_dma(dev);
|
|
spin_lock_irqsave(&dev->slock, flags);
|
|
while (!list_empty(&dmaq->active)) {
|
|
struct cx88_buffer *buf = list_entry(dmaq->active.next,
|
|
struct cx88_buffer, list);
|
|
|
|
list_del(&buf->list);
|
|
vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
|
|
}
|
|
spin_unlock_irqrestore(&dev->slock, flags);
|
|
}
|
|
|
|
const struct vb2_ops cx8800_vbi_qops = {
|
|
.queue_setup = queue_setup,
|
|
.buf_prepare = buffer_prepare,
|
|
.buf_finish = buffer_finish,
|
|
.buf_queue = buffer_queue,
|
|
.wait_prepare = vb2_ops_wait_prepare,
|
|
.wait_finish = vb2_ops_wait_finish,
|
|
.start_streaming = start_streaming,
|
|
.stop_streaming = stop_streaming,
|
|
};
|