Commit b7ec3212 authored by Deborah Brouwer's avatar Deborah Brouwer Committed by Mauro Carvalho Chehab

media: bttv: convert to vb2

Convert this driver from the old videobuf framework to videobuf2.
Signed-off-by: default avatarDeborah Brouwer <deborah.brouwer@collabora.com>
Signed-off-by: default avatarHans Verkuil <hverkuil-cisco@xs4all.nl>
parent f5f17f0c
...@@ -3,7 +3,7 @@ config VIDEO_BT848 ...@@ -3,7 +3,7 @@ config VIDEO_BT848
tristate "BT848 Video For Linux" tristate "BT848 Video For Linux"
depends on PCI && I2C && VIDEO_DEV depends on PCI && I2C && VIDEO_DEV
select I2C_ALGOBIT select I2C_ALGOBIT
select VIDEOBUF_DMA_SG select VIDEOBUF2_DMA_SG
depends on RC_CORE depends on RC_CORE
depends on MEDIA_RADIO_SUPPORT depends on MEDIA_RADIO_SUPPORT
select VIDEO_TUNER select VIDEO_TUNER
......
...@@ -231,7 +231,15 @@ ...@@ -231,7 +231,15 @@
#define BT848_INT_ETBF (1<<23) #define BT848_INT_ETBF (1<<23)
#define BT848_RISC_VIDEO 1
#define BT848_RISC_TOP 2
#define BT848_RISC_VBI 4
#define BT848_INT_RISCS (0xf<<28) #define BT848_INT_RISCS (0xf<<28)
#define BT848_INT_RISCS_VIDEO (BT848_RISC_VIDEO << 28)
#define BT848_INT_RISCS_TOP (BT848_RISC_TOP << 28)
#define BT848_INT_RISCS_VBI (BT848_RISC_VBI << 28)
#define BT848_INT_RISC_EN (1<<27) #define BT848_INT_RISC_EN (1<<27)
#define BT848_INT_RACK (1<<25) #define BT848_INT_RACK (1<<25)
#define BT848_INT_FIELD (1<<24) #define BT848_INT_FIELD (1<<24)
......
This diff is collapsed.
This diff is collapsed.
...@@ -34,16 +34,6 @@ ...@@ -34,16 +34,6 @@
to be about 244. */ to be about 244. */
#define VBI_OFFSET 244 #define VBI_OFFSET 244
/* 2048 for compatibility with earlier driver versions. The driver
really stores 1024 + tvnorm->vbipack * 4 samples per line in the
buffer. Note tvnorm->vbipack is <= 0xFF (limit of VBIPACK_LO + HI
is 0x1FF DWORDs) and VBI read()s store a frame counter in the last
four bytes of the VBI image. */
#define VBI_BPL 2048
/* Compatibility. */
#define VBI_DEFLINES 16
static unsigned int vbibufs = 4; static unsigned int vbibufs = 4;
static unsigned int vbi_debug; static unsigned int vbi_debug;
...@@ -67,165 +57,123 @@ do { \ ...@@ -67,165 +57,123 @@ do { \
/* ----------------------------------------------------------------------- */ /* ----------------------------------------------------------------------- */
/* vbi risc code + mm */ /* vbi risc code + mm */
static int vbi_buffer_setup(struct videobuf_queue *q, static int queue_setup_vbi(struct vb2_queue *q, unsigned int *num_buffers,
unsigned int *count, unsigned int *size) unsigned int *num_planes, unsigned int sizes[],
struct device *alloc_devs[])
{ {
struct bttv_fh *fh = q->priv_data; struct bttv *btv = vb2_get_drv_priv(q);
struct bttv *btv = fh->btv; unsigned int size = IMAGE_SIZE(&btv->vbi_fmt.fmt);
if (0 == *count)
*count = vbibufs;
*size = IMAGE_SIZE(&fh->vbi_fmt.fmt);
dprintk("setup: samples=%u start=%d,%d count=%u,%u\n", if (*num_planes)
fh->vbi_fmt.fmt.samples_per_line, return sizes[0] < size ? -EINVAL : 0;
fh->vbi_fmt.fmt.start[0], *num_planes = 1;
fh->vbi_fmt.fmt.start[1], sizes[0] = size;
fh->vbi_fmt.fmt.count[0],
fh->vbi_fmt.fmt.count[1]);
return 0; return 0;
} }
static int vbi_buffer_prepare(struct videobuf_queue *q, static void buf_queue_vbi(struct vb2_buffer *vb)
struct videobuf_buffer *vb,
enum v4l2_field field)
{ {
struct bttv_fh *fh = q->priv_data; struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
struct bttv *btv = fh->btv; struct vb2_queue *vq = vb->vb2_queue;
struct bttv_buffer *buf = container_of(vb,struct bttv_buffer,vb); struct bttv *btv = vb2_get_drv_priv(vq);
const struct bttv_tvnorm *tvnorm; struct bttv_buffer *buf = container_of(vbuf, struct bttv_buffer, vbuf);
unsigned int skip_lines0, skip_lines1, min_vdelay; unsigned long flags;
int redo_dma_risc;
int rc; spin_lock_irqsave(&btv->s_lock, flags);
if (list_empty(&btv->vcapture)) {
buf->vb.size = IMAGE_SIZE(&fh->vbi_fmt.fmt); btv->loop_irq = BT848_RISC_VBI;
if (0 != buf->vb.baddr && buf->vb.bsize < buf->vb.size) if (vb2_is_streaming(&btv->capq))
return -EINVAL; btv->loop_irq |= BT848_RISC_VIDEO;
bttv_set_dma(btv, BT848_CAP_CTL_CAPTURE_VBI_ODD |
tvnorm = fh->vbi_fmt.tvnorm; BT848_CAP_CTL_CAPTURE_VBI_EVEN);
/* There's no VBI_VDELAY register, RISC must skip the lines
we don't want. With default parameters we skip zero lines
as earlier driver versions did. The driver permits video
standard changes while capturing, so we use vbi_fmt.tvnorm
instead of btv->tvnorm to skip zero lines after video
standard changes as well. */
skip_lines0 = 0;
skip_lines1 = 0;
if (fh->vbi_fmt.fmt.count[0] > 0)
skip_lines0 = max(0, (fh->vbi_fmt.fmt.start[0]
- tvnorm->vbistart[0]));
if (fh->vbi_fmt.fmt.count[1] > 0)
skip_lines1 = max(0, (fh->vbi_fmt.fmt.start[1]
- tvnorm->vbistart[1]));
redo_dma_risc = 0;
if (btv->vbi_skip[0] != skip_lines0 ||
btv->vbi_skip[1] != skip_lines1 ||
btv->vbi_count[0] != fh->vbi_fmt.fmt.count[0] ||
btv->vbi_count[1] != fh->vbi_fmt.fmt.count[1]) {
btv->vbi_skip[0] = skip_lines0;
btv->vbi_skip[1] = skip_lines1;
btv->vbi_count[0] = fh->vbi_fmt.fmt.count[0];
btv->vbi_count[1] = fh->vbi_fmt.fmt.count[1];
redo_dma_risc = 1;
}
if (VIDEOBUF_NEEDS_INIT == buf->vb.state) {
redo_dma_risc = 1;
if (0 != (rc = videobuf_iolock(q, &buf->vb, NULL)))
goto fail;
} }
list_add_tail(&buf->list, &btv->vcapture);
spin_unlock_irqrestore(&btv->s_lock, flags);
}
if (redo_dma_risc) { static int buf_prepare_vbi(struct vb2_buffer *vb)
unsigned int bpl, padding, offset; {
struct videobuf_dmabuf *dma=videobuf_to_dma(&buf->vb); int ret = 0;
struct vb2_queue *vq = vb->vb2_queue;
bpl = 2044; /* max. vbipack */ struct bttv *btv = vb2_get_drv_priv(vq);
padding = VBI_BPL - bpl; struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
struct bttv_buffer *buf = container_of(vbuf, struct bttv_buffer, vbuf);
if (fh->vbi_fmt.fmt.count[0] > 0) { unsigned int size = IMAGE_SIZE(&btv->vbi_fmt.fmt);
rc = bttv_risc_packed(btv, &buf->top,
dma->sglist, if (vb2_plane_size(vb, 0) < size)
/* offset */ 0, bpl, return -EINVAL;
padding, skip_lines0, vb2_set_plane_payload(vb, 0, size);
fh->vbi_fmt.fmt.count[0]); buf->vbuf.field = V4L2_FIELD_NONE;
if (0 != rc) ret = bttv_buffer_risc_vbi(btv, buf);
goto fail;
}
if (fh->vbi_fmt.fmt.count[1] > 0) {
offset = fh->vbi_fmt.fmt.count[0] * VBI_BPL;
rc = bttv_risc_packed(btv, &buf->bottom, return ret;
dma->sglist, }
offset, bpl,
padding, skip_lines1,
fh->vbi_fmt.fmt.count[1]);
if (0 != rc)
goto fail;
}
}
/* VBI capturing ends at VDELAY, start of video capturing, static void buf_cleanup_vbi(struct vb2_buffer *vb)
no matter where the RISC program ends. VDELAY minimum is 2, {
bounds.top is the corresponding first field line number struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
times two. VDELAY counts half field lines. */ struct bttv_buffer *buf = container_of(vbuf, struct bttv_buffer, vbuf);
min_vdelay = MIN_VDELAY; struct vb2_queue *vq = vb->vb2_queue;
if (fh->vbi_fmt.end >= tvnorm->cropcap.bounds.top) struct bttv *btv = vb2_get_drv_priv(vq);
min_vdelay += fh->vbi_fmt.end - tvnorm->cropcap.bounds.top;
/* For bttv_buffer_activate_vbi(). */
buf->geo.vdelay = min_vdelay;
buf->vb.state = VIDEOBUF_PREPARED;
buf->vb.field = field;
dprintk("buf prepare %p: top=%p bottom=%p field=%s\n",
vb, &buf->top, &buf->bottom,
v4l2_field_names[buf->vb.field]);
return 0;
fail: btcx_riscmem_free(btv->c.pci, &buf->top);
bttv_dma_free(q,btv,buf); btcx_riscmem_free(btv->c.pci, &buf->bottom);
return rc;
} }
static void static int start_streaming_vbi(struct vb2_queue *q, unsigned int count)
vbi_buffer_queue(struct videobuf_queue *q, struct videobuf_buffer *vb)
{ {
struct bttv_fh *fh = q->priv_data; int ret;
struct bttv *btv = fh->btv; int seqnr = 0;
struct bttv_buffer *buf = container_of(vb,struct bttv_buffer,vb); struct bttv_buffer *buf;
struct bttv *btv = vb2_get_drv_priv(q);
dprintk("queue %p\n",vb);
buf->vb.state = VIDEOBUF_QUEUED; btv->framedrop = 0;
list_add_tail(&buf->vb.queue,&btv->vcapture); ret = check_alloc_btres_lock(btv, RESOURCE_VBI);
if (NULL == btv->cvbi) { if (ret == 0) {
fh->btv->loop_irq |= 4; if (btv->field_count)
bttv_set_dma(btv,0x0c); seqnr++;
while (!list_empty(&btv->vcapture)) {
buf = list_entry(btv->vcapture.next,
struct bttv_buffer, list);
list_del(&buf->list);
buf->vbuf.sequence = (btv->field_count >> 1) + seqnr++;
vb2_buffer_done(&buf->vbuf.vb2_buf,
VB2_BUF_STATE_QUEUED);
}
return !ret;
} }
if (!vb2_is_streaming(&btv->capq)) {
init_irqreg(btv);
btv->field_count = 0;
}
return !ret;
} }
static void vbi_buffer_release(struct videobuf_queue *q, struct videobuf_buffer *vb) static void stop_streaming_vbi(struct vb2_queue *q)
{ {
struct bttv_fh *fh = q->priv_data; struct bttv *btv = vb2_get_drv_priv(q);
struct bttv *btv = fh->btv; unsigned long flags;
struct bttv_buffer *buf = container_of(vb,struct bttv_buffer,vb);
vb2_wait_for_all_buffers(q);
dprintk("free %p\n",vb); spin_lock_irqsave(&btv->s_lock, flags);
bttv_dma_free(q,fh->btv,buf); free_btres_lock(btv, RESOURCE_VBI);
if (!vb2_is_streaming(&btv->capq)) {
/* stop field counter */
btand(~BT848_INT_VSYNC, BT848_INT_MASK);
}
spin_unlock_irqrestore(&btv->s_lock, flags);
} }
const struct videobuf_queue_ops bttv_vbi_qops = { const struct vb2_ops bttv_vbi_qops = {
.buf_setup = vbi_buffer_setup, .queue_setup = queue_setup_vbi,
.buf_prepare = vbi_buffer_prepare, .buf_queue = buf_queue_vbi,
.buf_queue = vbi_buffer_queue, .buf_prepare = buf_prepare_vbi,
.buf_release = vbi_buffer_release, .buf_cleanup = buf_cleanup_vbi,
.start_streaming = start_streaming_vbi,
.stop_streaming = stop_streaming_vbi,
.wait_prepare = vb2_ops_wait_prepare,
.wait_finish = vb2_ops_wait_finish,
}; };
/* ----------------------------------------------------------------------- */ /* ----------------------------------------------------------------------- */
...@@ -316,7 +264,6 @@ int bttv_try_fmt_vbi_cap(struct file *file, void *f, struct v4l2_format *frt) ...@@ -316,7 +264,6 @@ int bttv_try_fmt_vbi_cap(struct file *file, void *f, struct v4l2_format *frt)
int bttv_s_fmt_vbi_cap(struct file *file, void *f, struct v4l2_format *frt) int bttv_s_fmt_vbi_cap(struct file *file, void *f, struct v4l2_format *frt)
{ {
struct bttv_fh *fh = f;
struct bttv *btv = video_drvdata(file); struct bttv *btv = video_drvdata(file);
const struct bttv_tvnorm *tvnorm; const struct bttv_tvnorm *tvnorm;
__s32 start1, end; __s32 start1, end;
...@@ -325,7 +272,7 @@ int bttv_s_fmt_vbi_cap(struct file *file, void *f, struct v4l2_format *frt) ...@@ -325,7 +272,7 @@ int bttv_s_fmt_vbi_cap(struct file *file, void *f, struct v4l2_format *frt)
mutex_lock(&btv->lock); mutex_lock(&btv->lock);
rc = -EBUSY; rc = -EBUSY;
if (fh->resources & RESOURCE_VBI) if (btv->resources & RESOURCE_VBI)
goto fail; goto fail;
tvnorm = &bttv_tvnorms[btv->tvnorm]; tvnorm = &bttv_tvnorms[btv->tvnorm];
...@@ -345,17 +292,10 @@ int bttv_s_fmt_vbi_cap(struct file *file, void *f, struct v4l2_format *frt) ...@@ -345,17 +292,10 @@ int bttv_s_fmt_vbi_cap(struct file *file, void *f, struct v4l2_format *frt)
because vbi_fmt.end counts field lines times two. */ because vbi_fmt.end counts field lines times two. */
end = max(frt->fmt.vbi.start[0], start1) * 2 + 2; end = max(frt->fmt.vbi.start[0], start1) * 2 + 2;
mutex_lock(&fh->vbi.vb_lock);
fh->vbi_fmt.fmt = frt->fmt.vbi;
fh->vbi_fmt.tvnorm = tvnorm;
fh->vbi_fmt.end = end;
btv->vbi_fmt.fmt = frt->fmt.vbi; btv->vbi_fmt.fmt = frt->fmt.vbi;
btv->vbi_fmt.tvnorm = tvnorm; btv->vbi_fmt.tvnorm = tvnorm;
btv->vbi_fmt.end = end; btv->vbi_fmt.end = end;
mutex_unlock(&fh->vbi.vb_lock);
rc = 0; rc = 0;
fail: fail:
......
...@@ -26,7 +26,7 @@ ...@@ -26,7 +26,7 @@
#include <media/v4l2-common.h> #include <media/v4l2-common.h>
#include <media/v4l2-ctrls.h> #include <media/v4l2-ctrls.h>
#include <media/v4l2-fh.h> #include <media/v4l2-fh.h>
#include <media/videobuf-dma-sg.h> #include <media/videobuf2-dma-sg.h>
#include <media/tveeprom.h> #include <media/tveeprom.h>
#include <media/rc-core.h> #include <media/rc-core.h>
#include <media/i2c/ir-kbd-i2c.h> #include <media/i2c/ir-kbd-i2c.h>
...@@ -142,7 +142,8 @@ struct bttv_geometry { ...@@ -142,7 +142,8 @@ struct bttv_geometry {
struct bttv_buffer { struct bttv_buffer {
/* common v4l buffer stuff -- must be first */ /* common v4l buffer stuff -- must be first */
struct videobuf_buffer vb; struct vb2_v4l2_buffer vbuf;
struct list_head list;
/* bttv specific */ /* bttv specific */
int btformat; int btformat;
...@@ -171,6 +172,8 @@ struct bttv_vbi_fmt { ...@@ -171,6 +172,8 @@ struct bttv_vbi_fmt {
}; };
/* bttv-vbi.c */ /* bttv-vbi.c */
extern const struct vb2_ops bttv_vbi_qops;
void bttv_vbi_fmt_reset(struct bttv_vbi_fmt *f, unsigned int norm); void bttv_vbi_fmt_reset(struct bttv_vbi_fmt *f, unsigned int norm);
struct bttv_crop { struct bttv_crop {
...@@ -187,28 +190,6 @@ struct bttv_crop { ...@@ -187,28 +190,6 @@ struct bttv_crop {
__s32 max_scaled_height; __s32 max_scaled_height;
}; };
struct bttv_fh {
/* This must be the first field in this struct */
struct v4l2_fh fh;
struct bttv *btv;
int resources;
enum v4l2_buf_type type;
/* video capture */
struct videobuf_queue cap;
const struct bttv_format *fmt;
int width;
int height;
/* vbi capture */
struct videobuf_queue vbi;
/* Current VBI capture window as seen through this fh (cannot
be global for compatibility with earlier drivers). Protected
by struct bttv.lock and struct bttv_fh.vbi.lock. */
struct bttv_vbi_fmt vbi_fmt;
};
/* ---------------------------------------------------------- */ /* ---------------------------------------------------------- */
/* bttv-risc.c */ /* bttv-risc.c */
...@@ -229,22 +210,27 @@ int bttv_risc_hook(struct bttv *btv, int slot, struct btcx_riscmem *risc, ...@@ -229,22 +210,27 @@ int bttv_risc_hook(struct bttv *btv, int slot, struct btcx_riscmem *risc,
int bttv_buffer_risc(struct bttv *btv, struct bttv_buffer *buf); int bttv_buffer_risc(struct bttv *btv, struct bttv_buffer *buf);
int bttv_buffer_activate_video(struct bttv *btv, int bttv_buffer_activate_video(struct bttv *btv,
struct bttv_buffer_set *set); struct bttv_buffer_set *set);
int bttv_buffer_risc_vbi(struct bttv *btv, struct bttv_buffer *buf);
int bttv_buffer_activate_vbi(struct bttv *btv, int bttv_buffer_activate_vbi(struct bttv *btv,
struct bttv_buffer *vbi); struct bttv_buffer *vbi);
void bttv_dma_free(struct videobuf_queue *q, struct bttv *btv,
struct bttv_buffer *buf);
/* ---------------------------------------------------------- */ /* ---------------------------------------------------------- */
/* bttv-vbi.c */ /* bttv-vbi.c */
/*
* 2048 for compatibility with earlier driver versions. The driver really
* stores 1024 + tvnorm->vbipack * 4 samples per line in the buffer. Note
* tvnorm->vbipack is <= 0xFF (limit of VBIPACK_LO + HI is 0x1FF DWORDs) and
* VBI read()s store a frame counter in the last four bytes of the VBI image.
*/
#define VBI_BPL 2048
#define VBI_DEFLINES 16 #define VBI_DEFLINES 16
int bttv_try_fmt_vbi_cap(struct file *file, void *fh, struct v4l2_format *f); int bttv_try_fmt_vbi_cap(struct file *file, void *fh, struct v4l2_format *f);
int bttv_g_fmt_vbi_cap(struct file *file, void *fh, struct v4l2_format *f); int bttv_g_fmt_vbi_cap(struct file *file, void *fh, struct v4l2_format *f);
int bttv_s_fmt_vbi_cap(struct file *file, void *fh, struct v4l2_format *f); int bttv_s_fmt_vbi_cap(struct file *file, void *fh, struct v4l2_format *f);
extern const struct videobuf_queue_ops bttv_vbi_qops;
/* ---------------------------------------------------------- */ /* ---------------------------------------------------------- */
/* bttv-gpio.c */ /* bttv-gpio.c */
...@@ -269,6 +255,8 @@ extern int fini_bttv_i2c(struct bttv *btv); ...@@ -269,6 +255,8 @@ extern int fini_bttv_i2c(struct bttv *btv);
extern unsigned int bttv_verbose; extern unsigned int bttv_verbose;
extern unsigned int bttv_debug; extern unsigned int bttv_debug;
extern unsigned int bttv_gpio; extern unsigned int bttv_gpio;
int check_alloc_btres_lock(struct bttv *btv, int bit);
void free_btres_lock(struct bttv *btv, int bits);
extern void bttv_gpio_tracking(struct bttv *btv, char *comment); extern void bttv_gpio_tracking(struct bttv *btv, char *comment);
#define dprintk(fmt, ...) \ #define dprintk(fmt, ...) \
...@@ -390,7 +378,7 @@ struct bttv { ...@@ -390,7 +378,7 @@ struct bttv {
v4l2_std_id std; v4l2_std_id std;
int hue, contrast, bright, saturation; int hue, contrast, bright, saturation;
struct v4l2_framebuffer fbuf; struct v4l2_framebuffer fbuf;
unsigned int field_count; __u32 field_count;
/* various options */ /* various options */
int opt_combfilter; int opt_combfilter;
...@@ -441,12 +429,21 @@ struct bttv { ...@@ -441,12 +429,21 @@ struct bttv {
unsigned int irq_me; unsigned int irq_me;
unsigned int users; unsigned int users;
struct bttv_fh init; struct v4l2_fh fh;
enum v4l2_buf_type type;
enum v4l2_field field;
int field_last;
/* video capture */
struct vb2_queue capq;
const struct bttv_format *fmt; const struct bttv_format *fmt;
int width; int width;
int height; int height;
/* vbi capture */
struct vb2_queue vbiq;
struct bttv_vbi_fmt vbi_fmt; struct bttv_vbi_fmt vbi_fmt;
unsigned int vbi_skip[2];
unsigned int vbi_count[2]; unsigned int vbi_count[2];
/* Application called VIDIOC_S_SELECTION. */ /* Application called VIDIOC_S_SELECTION. */
...@@ -489,6 +486,8 @@ static inline unsigned int bttv_muxsel(const struct bttv *btv, ...@@ -489,6 +486,8 @@ static inline unsigned int bttv_muxsel(const struct bttv *btv,
#endif #endif
void init_irqreg(struct bttv *btv);
#define btwrite(dat,adr) writel((dat), btv->bt848_mmio+(adr)) #define btwrite(dat,adr) writel((dat), btv->bt848_mmio+(adr))
#define btread(adr) readl(btv->bt848_mmio+(adr)) #define btread(adr) readl(btv->bt848_mmio+(adr))
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment