media: bttv: convert to vb2
Convert this driver from the old videobuf framework to videobuf2. Signed-off-by: Deborah Brouwer <deborah.brouwer@collabora.com> Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
This commit is contained in:
parent
f5f17f0cb5
commit
b7ec3212a7
@ -3,7 +3,7 @@ config VIDEO_BT848
|
||||
tristate "BT848 Video For Linux"
|
||||
depends on PCI && I2C && VIDEO_DEV
|
||||
select I2C_ALGOBIT
|
||||
select VIDEOBUF_DMA_SG
|
||||
select VIDEOBUF2_DMA_SG
|
||||
depends on RC_CORE
|
||||
depends on MEDIA_RADIO_SUPPORT
|
||||
select VIDEO_TUNER
|
||||
|
@ -231,7 +231,15 @@
|
||||
|
||||
#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_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_RACK (1<<25)
|
||||
#define BT848_INT_FIELD (1<<24)
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -67,8 +67,10 @@ bttv_risc_packed(struct bttv *btv, struct btcx_riscmem *risc,
|
||||
/* scan lines */
|
||||
sg = sglist;
|
||||
for (line = 0; line < store_lines; line++) {
|
||||
if ((btv->opt_vcr_hack) &&
|
||||
(line >= (store_lines - VCR_HACK_LINES)))
|
||||
if ((line >= (store_lines - VCR_HACK_LINES)) &&
|
||||
(btv->opt_vcr_hack ||
|
||||
(V4L2_FIELD_HAS_BOTH(btv->field) ||
|
||||
btv->field == V4L2_FIELD_ALTERNATE)))
|
||||
continue;
|
||||
while (offset && offset >= sg_dma_len(sg)) {
|
||||
offset -= sg_dma_len(sg);
|
||||
@ -363,13 +365,6 @@ bttv_apply_geo(struct bttv *btv, struct bttv_geometry *geo, int odd)
|
||||
static void bttv_set_risc_status(struct bttv *btv)
|
||||
{
|
||||
unsigned long cmd = BT848_RISC_JUMP;
|
||||
/*
|
||||
* The value of btv->loop_irq sets or resets the RISC_STATUS for video
|
||||
* and/or vbi by setting the value of bits [23:16] in the first dword
|
||||
* of the JUMP instruction:
|
||||
* video risc: set (1) and reset (~1)
|
||||
* vbi risc: set(4) and reset (~4)
|
||||
*/
|
||||
if (btv->loop_irq) {
|
||||
cmd |= BT848_RISC_IRQ;
|
||||
cmd |= (btv->loop_irq & 0x0f) << 16;
|
||||
@ -410,7 +405,8 @@ static void bttv_start_dma(struct bttv *btv)
|
||||
if (btv->dma_on)
|
||||
return;
|
||||
btwrite(btv->main.dma, BT848_RISC_STRT_ADD);
|
||||
btor(0x3, BT848_GPIO_DMA_CTL);
|
||||
btor(BT848_GPIO_DMA_CTL_RISC_ENABLE | BT848_GPIO_DMA_CTL_FIFO_ENABLE,
|
||||
BT848_GPIO_DMA_CTL);
|
||||
btv->dma_on = 1;
|
||||
}
|
||||
|
||||
@ -418,7 +414,8 @@ static void bttv_stop_dma(struct bttv *btv)
|
||||
{
|
||||
if (!btv->dma_on)
|
||||
return;
|
||||
btand(~0x3, BT848_GPIO_DMA_CTL);
|
||||
btand(~(BT848_GPIO_DMA_CTL_RISC_ENABLE |
|
||||
BT848_GPIO_DMA_CTL_FIFO_ENABLE), BT848_GPIO_DMA_CTL);
|
||||
btv->dma_on = 0;
|
||||
}
|
||||
|
||||
@ -509,17 +506,50 @@ bttv_risc_hook(struct bttv *btv, int slot, struct btcx_riscmem *risc,
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
bttv_dma_free(struct videobuf_queue *q,struct bttv *btv, struct bttv_buffer *buf)
|
||||
int bttv_buffer_risc_vbi(struct bttv *btv, struct bttv_buffer *buf)
|
||||
{
|
||||
struct videobuf_dmabuf *dma=videobuf_to_dma(&buf->vb);
|
||||
int r = 0;
|
||||
unsigned int offset;
|
||||
unsigned int bpl = 2044; /* max. vbipack */
|
||||
unsigned int padding = VBI_BPL - bpl;
|
||||
unsigned int skip_lines0 = 0;
|
||||
unsigned int skip_lines1 = 0;
|
||||
unsigned int min_vdelay = MIN_VDELAY;
|
||||
|
||||
videobuf_waiton(q, &buf->vb, 0, 0);
|
||||
videobuf_dma_unmap(q->dev, dma);
|
||||
videobuf_dma_free(dma);
|
||||
btcx_riscmem_free(btv->c.pci,&buf->bottom);
|
||||
btcx_riscmem_free(btv->c.pci,&buf->top);
|
||||
buf->vb.state = VIDEOBUF_NEEDS_INIT;
|
||||
const struct bttv_tvnorm *tvnorm = btv->vbi_fmt.tvnorm;
|
||||
struct sg_table *sgt = vb2_dma_sg_plane_desc(&buf->vbuf.vb2_buf, 0);
|
||||
struct scatterlist *list = sgt->sgl;
|
||||
|
||||
if (btv->vbi_fmt.fmt.count[0] > 0)
|
||||
skip_lines0 = max(0, (btv->vbi_fmt.fmt.start[0] -
|
||||
tvnorm->vbistart[0]));
|
||||
if (btv->vbi_fmt.fmt.count[1] > 0)
|
||||
skip_lines1 = max(0, (btv->vbi_fmt.fmt.start[1] -
|
||||
tvnorm->vbistart[1]));
|
||||
|
||||
if (btv->vbi_fmt.fmt.count[0] > 0) {
|
||||
r = bttv_risc_packed(btv, &buf->top, list, 0, bpl, padding,
|
||||
skip_lines0, btv->vbi_fmt.fmt.count[0]);
|
||||
if (r)
|
||||
return r;
|
||||
}
|
||||
|
||||
if (btv->vbi_fmt.fmt.count[1] > 0) {
|
||||
offset = btv->vbi_fmt.fmt.count[0] * VBI_BPL;
|
||||
r = bttv_risc_packed(btv, &buf->bottom, list, offset, bpl,
|
||||
padding, skip_lines1,
|
||||
btv->vbi_fmt.fmt.count[1]);
|
||||
if (r)
|
||||
return r;
|
||||
}
|
||||
|
||||
if (btv->vbi_fmt.end >= tvnorm->cropcap.bounds.top)
|
||||
min_vdelay += btv->vbi_fmt.end - tvnorm->cropcap.bounds.top;
|
||||
|
||||
/* For bttv_buffer_activate_vbi(). */
|
||||
buf->geo.vdelay = min_vdelay;
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
int
|
||||
@ -539,8 +569,7 @@ bttv_buffer_activate_vbi(struct bttv *btv,
|
||||
if (vbi) {
|
||||
unsigned int crop, vdelay;
|
||||
|
||||
vbi->vb.state = VIDEOBUF_ACTIVE;
|
||||
list_del(&vbi->vb.queue);
|
||||
list_del(&vbi->list);
|
||||
|
||||
/* VDELAY is start of video, end of VBI capturing. */
|
||||
crop = btread(BT848_E_CROP);
|
||||
@ -581,16 +610,13 @@ bttv_buffer_activate_video(struct bttv *btv,
|
||||
/* video capture */
|
||||
if (NULL != set->top && NULL != set->bottom) {
|
||||
if (set->top == set->bottom) {
|
||||
set->top->vb.state = VIDEOBUF_ACTIVE;
|
||||
if (set->top->vb.queue.next)
|
||||
list_del(&set->top->vb.queue);
|
||||
if (set->top->list.next)
|
||||
list_del(&set->top->list);
|
||||
} else {
|
||||
set->top->vb.state = VIDEOBUF_ACTIVE;
|
||||
set->bottom->vb.state = VIDEOBUF_ACTIVE;
|
||||
if (set->top->vb.queue.next)
|
||||
list_del(&set->top->vb.queue);
|
||||
if (set->bottom->vb.queue.next)
|
||||
list_del(&set->bottom->vb.queue);
|
||||
if (set->top->list.next)
|
||||
list_del(&set->top->list);
|
||||
if (set->bottom->list.next)
|
||||
list_del(&set->bottom->list);
|
||||
}
|
||||
bttv_apply_geo(btv, &set->top->geo, 1);
|
||||
bttv_apply_geo(btv, &set->bottom->geo,0);
|
||||
@ -603,9 +629,8 @@ bttv_buffer_activate_video(struct bttv *btv,
|
||||
btaor((set->top->btswap & 0x0a) | (set->bottom->btswap & 0x05),
|
||||
~0x0f, BT848_COLOR_CTL);
|
||||
} else if (NULL != set->top) {
|
||||
set->top->vb.state = VIDEOBUF_ACTIVE;
|
||||
if (set->top->vb.queue.next)
|
||||
list_del(&set->top->vb.queue);
|
||||
if (set->top->list.next)
|
||||
list_del(&set->top->list);
|
||||
bttv_apply_geo(btv, &set->top->geo,1);
|
||||
bttv_apply_geo(btv, &set->top->geo,0);
|
||||
bttv_risc_hook(btv, RISC_SLOT_O_FIELD, &set->top->top,
|
||||
@ -614,9 +639,8 @@ bttv_buffer_activate_video(struct bttv *btv,
|
||||
btaor(set->top->btformat & 0xff, ~0xff, BT848_COLOR_FMT);
|
||||
btaor(set->top->btswap & 0x0f, ~0x0f, BT848_COLOR_CTL);
|
||||
} else if (NULL != set->bottom) {
|
||||
set->bottom->vb.state = VIDEOBUF_ACTIVE;
|
||||
if (set->bottom->vb.queue.next)
|
||||
list_del(&set->bottom->vb.queue);
|
||||
if (set->bottom->list.next)
|
||||
list_del(&set->bottom->list);
|
||||
bttv_apply_geo(btv, &set->bottom->geo,1);
|
||||
bttv_apply_geo(btv, &set->bottom->geo,0);
|
||||
bttv_risc_hook(btv, RISC_SLOT_O_FIELD, NULL, 0);
|
||||
@ -637,58 +661,54 @@ bttv_buffer_activate_video(struct bttv *btv,
|
||||
int
|
||||
bttv_buffer_risc(struct bttv *btv, struct bttv_buffer *buf)
|
||||
{
|
||||
int r = 0;
|
||||
const struct bttv_tvnorm *tvnorm = bttv_tvnorms + btv->tvnorm;
|
||||
struct videobuf_dmabuf *dma=videobuf_to_dma(&buf->vb);
|
||||
|
||||
dprintk("%d: buffer field: %s format: 0x%08x size: %dx%d\n",
|
||||
btv->c.nr, v4l2_field_names[buf->vb.field],
|
||||
btv->fmt->fourcc, buf->vb.width, buf->vb.height);
|
||||
struct sg_table *sgt = vb2_dma_sg_plane_desc(&buf->vbuf.vb2_buf, 0);
|
||||
struct scatterlist *list = sgt->sgl;
|
||||
unsigned long size = (btv->fmt->depth * btv->width * btv->height) >> 3;
|
||||
|
||||
/* packed pixel modes */
|
||||
if (btv->fmt->flags & FORMAT_FLAGS_PACKED) {
|
||||
int bpl = (btv->fmt->depth >> 3) * buf->vb.width;
|
||||
int bpf = bpl * (buf->vb.height >> 1);
|
||||
int bpl = (btv->fmt->depth >> 3) * btv->width;
|
||||
int bpf = bpl * (btv->height >> 1);
|
||||
|
||||
bttv_calc_geo(btv,&buf->geo,buf->vb.width,buf->vb.height,
|
||||
V4L2_FIELD_HAS_BOTH(buf->vb.field),
|
||||
tvnorm, &btv->crop[!!btv->do_crop].rect);
|
||||
|
||||
switch (buf->vb.field) {
|
||||
bttv_calc_geo(btv, &buf->geo, btv->width, btv->height,
|
||||
V4L2_FIELD_HAS_BOTH(buf->vbuf.field), tvnorm,
|
||||
&btv->crop[!!btv->do_crop].rect);
|
||||
switch (buf->vbuf.field) {
|
||||
case V4L2_FIELD_TOP:
|
||||
bttv_risc_packed(btv,&buf->top,dma->sglist,
|
||||
/* offset */ 0,bpl,
|
||||
/* padding */ 0,/* skip_lines */ 0,
|
||||
buf->vb.height);
|
||||
r = bttv_risc_packed(btv, &buf->top, list, 0, bpl, 0,
|
||||
0, btv->height);
|
||||
break;
|
||||
case V4L2_FIELD_BOTTOM:
|
||||
bttv_risc_packed(btv,&buf->bottom,dma->sglist,
|
||||
0,bpl,0,0,buf->vb.height);
|
||||
r = bttv_risc_packed(btv, &buf->bottom, list, 0, bpl,
|
||||
0, 0, btv->height);
|
||||
break;
|
||||
case V4L2_FIELD_INTERLACED:
|
||||
bttv_risc_packed(btv,&buf->top,dma->sglist,
|
||||
0,bpl,bpl,0,buf->vb.height >> 1);
|
||||
bttv_risc_packed(btv,&buf->bottom,dma->sglist,
|
||||
bpl,bpl,bpl,0,buf->vb.height >> 1);
|
||||
r = bttv_risc_packed(btv, &buf->top, list, 0, bpl,
|
||||
bpl, 0, btv->height >> 1);
|
||||
r = bttv_risc_packed(btv, &buf->bottom, list, bpl,
|
||||
bpl, bpl, 0, btv->height >> 1);
|
||||
break;
|
||||
case V4L2_FIELD_SEQ_TB:
|
||||
bttv_risc_packed(btv,&buf->top,dma->sglist,
|
||||
0,bpl,0,0,buf->vb.height >> 1);
|
||||
bttv_risc_packed(btv,&buf->bottom,dma->sglist,
|
||||
bpf,bpl,0,0,buf->vb.height >> 1);
|
||||
r = bttv_risc_packed(btv, &buf->top, list, 0, bpl, 0,
|
||||
0, btv->height >> 1);
|
||||
r = bttv_risc_packed(btv, &buf->bottom, list, bpf,
|
||||
bpl, 0, 0, btv->height >> 1);
|
||||
break;
|
||||
default:
|
||||
WARN_ON(1);
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
/* planar modes */
|
||||
if (btv->fmt->flags & FORMAT_FLAGS_PLANAR) {
|
||||
int uoffset, voffset;
|
||||
int ypadding, cpadding, lines;
|
||||
|
||||
/* calculate chroma offsets */
|
||||
uoffset = buf->vb.width * buf->vb.height;
|
||||
voffset = buf->vb.width * buf->vb.height;
|
||||
uoffset = btv->width * btv->height;
|
||||
voffset = btv->width * btv->height;
|
||||
if (btv->fmt->flags & FORMAT_FLAGS_CrCb) {
|
||||
/* Y-Cr-Cb plane order */
|
||||
uoffset >>= btv->fmt->hshift;
|
||||
@ -700,93 +720,87 @@ bttv_buffer_risc(struct bttv *btv, struct bttv_buffer *buf)
|
||||
voffset >>= btv->fmt->vshift;
|
||||
voffset += uoffset;
|
||||
}
|
||||
|
||||
switch (buf->vb.field) {
|
||||
switch (buf->vbuf.field) {
|
||||
case V4L2_FIELD_TOP:
|
||||
bttv_calc_geo(btv,&buf->geo,buf->vb.width,
|
||||
buf->vb.height,/* both_fields */ 0,
|
||||
tvnorm, &btv->crop[!!btv->do_crop].rect);
|
||||
bttv_risc_planar(btv, &buf->top, dma->sglist,
|
||||
0,buf->vb.width,0,buf->vb.height,
|
||||
uoffset, voffset, btv->fmt->hshift,
|
||||
btv->fmt->vshift, 0);
|
||||
bttv_calc_geo(btv, &buf->geo, btv->width, btv->height,
|
||||
0, tvnorm,
|
||||
&btv->crop[!!btv->do_crop].rect);
|
||||
r = bttv_risc_planar(btv, &buf->top, list, 0,
|
||||
btv->width, 0, btv->height,
|
||||
uoffset, voffset,
|
||||
btv->fmt->hshift,
|
||||
btv->fmt->vshift, 0);
|
||||
break;
|
||||
case V4L2_FIELD_BOTTOM:
|
||||
bttv_calc_geo(btv,&buf->geo,buf->vb.width,
|
||||
buf->vb.height,0,
|
||||
tvnorm, &btv->crop[!!btv->do_crop].rect);
|
||||
bttv_risc_planar(btv, &buf->bottom, dma->sglist,
|
||||
0,buf->vb.width,0,buf->vb.height,
|
||||
uoffset, voffset, btv->fmt->hshift,
|
||||
btv->fmt->vshift, 0);
|
||||
bttv_calc_geo(btv, &buf->geo, btv->width, btv->height,
|
||||
0, tvnorm,
|
||||
&btv->crop[!!btv->do_crop].rect);
|
||||
r = bttv_risc_planar(btv, &buf->bottom, list, 0,
|
||||
btv->width, 0, btv->height,
|
||||
uoffset, voffset,
|
||||
btv->fmt->hshift,
|
||||
btv->fmt->vshift, 0);
|
||||
break;
|
||||
case V4L2_FIELD_INTERLACED:
|
||||
bttv_calc_geo(btv,&buf->geo,buf->vb.width,
|
||||
buf->vb.height,1,
|
||||
tvnorm, &btv->crop[!!btv->do_crop].rect);
|
||||
lines = buf->vb.height >> 1;
|
||||
ypadding = buf->vb.width;
|
||||
cpadding = buf->vb.width >> btv->fmt->hshift;
|
||||
bttv_risc_planar(btv,&buf->top,
|
||||
dma->sglist,
|
||||
0,buf->vb.width,ypadding,lines,
|
||||
uoffset,voffset,
|
||||
btv->fmt->hshift,
|
||||
btv->fmt->vshift,
|
||||
cpadding);
|
||||
bttv_risc_planar(btv,&buf->bottom,
|
||||
dma->sglist,
|
||||
ypadding,buf->vb.width,ypadding,lines,
|
||||
uoffset+cpadding,
|
||||
voffset+cpadding,
|
||||
btv->fmt->hshift,
|
||||
btv->fmt->vshift,
|
||||
cpadding);
|
||||
bttv_calc_geo(btv, &buf->geo, btv->width, btv->height,
|
||||
1, tvnorm,
|
||||
&btv->crop[!!btv->do_crop].rect);
|
||||
lines = btv->height >> 1;
|
||||
ypadding = btv->width;
|
||||
cpadding = btv->width >> btv->fmt->hshift;
|
||||
r = bttv_risc_planar(btv, &buf->top, list, 0,
|
||||
btv->width, ypadding, lines,
|
||||
uoffset, voffset,
|
||||
btv->fmt->hshift,
|
||||
btv->fmt->vshift, cpadding);
|
||||
|
||||
r = bttv_risc_planar(btv, &buf->bottom, list,
|
||||
ypadding, btv->width, ypadding,
|
||||
lines, uoffset + cpadding,
|
||||
voffset + cpadding,
|
||||
btv->fmt->hshift,
|
||||
btv->fmt->vshift, cpadding);
|
||||
break;
|
||||
case V4L2_FIELD_SEQ_TB:
|
||||
bttv_calc_geo(btv,&buf->geo,buf->vb.width,
|
||||
buf->vb.height,1,
|
||||
tvnorm, &btv->crop[!!btv->do_crop].rect);
|
||||
lines = buf->vb.height >> 1;
|
||||
ypadding = buf->vb.width;
|
||||
cpadding = buf->vb.width >> btv->fmt->hshift;
|
||||
bttv_risc_planar(btv,&buf->top,
|
||||
dma->sglist,
|
||||
0,buf->vb.width,0,lines,
|
||||
uoffset >> 1,
|
||||
voffset >> 1,
|
||||
btv->fmt->hshift,
|
||||
btv->fmt->vshift,
|
||||
0);
|
||||
bttv_risc_planar(btv,&buf->bottom,
|
||||
dma->sglist,
|
||||
lines * ypadding,buf->vb.width,0,lines,
|
||||
lines * ypadding + (uoffset >> 1),
|
||||
lines * ypadding + (voffset >> 1),
|
||||
btv->fmt->hshift,
|
||||
btv->fmt->vshift,
|
||||
0);
|
||||
bttv_calc_geo(btv, &buf->geo, btv->width, btv->height,
|
||||
1, tvnorm,
|
||||
&btv->crop[!!btv->do_crop].rect);
|
||||
lines = btv->height >> 1;
|
||||
ypadding = btv->width;
|
||||
cpadding = btv->width >> btv->fmt->hshift;
|
||||
r = bttv_risc_planar(btv, &buf->top, list, 0,
|
||||
btv->width, 0, lines,
|
||||
uoffset >> 1, voffset >> 1,
|
||||
btv->fmt->hshift,
|
||||
btv->fmt->vshift, 0);
|
||||
r = bttv_risc_planar(btv, &buf->bottom, list,
|
||||
lines * ypadding,
|
||||
btv->width, 0, lines,
|
||||
lines * ypadding + (uoffset >> 1),
|
||||
lines * ypadding + (voffset >> 1),
|
||||
btv->fmt->hshift,
|
||||
btv->fmt->vshift, 0);
|
||||
break;
|
||||
default:
|
||||
WARN_ON(1);
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
/* raw data */
|
||||
if (btv->fmt->flags & FORMAT_FLAGS_RAW) {
|
||||
/* build risc code */
|
||||
buf->vb.field = V4L2_FIELD_SEQ_TB;
|
||||
bttv_calc_geo(btv,&buf->geo,tvnorm->swidth,tvnorm->sheight,
|
||||
buf->vbuf.field = V4L2_FIELD_SEQ_TB;
|
||||
bttv_calc_geo(btv, &buf->geo, tvnorm->swidth, tvnorm->sheight,
|
||||
1, tvnorm, &btv->crop[!!btv->do_crop].rect);
|
||||
bttv_risc_packed(btv, &buf->top, dma->sglist,
|
||||
/* offset */ 0, RAW_BPL, /* padding */ 0,
|
||||
/* skip_lines */ 0, RAW_LINES);
|
||||
bttv_risc_packed(btv, &buf->bottom, dma->sglist,
|
||||
buf->vb.size/2 , RAW_BPL, 0, 0, RAW_LINES);
|
||||
r = bttv_risc_packed(btv, &buf->top, list, 0, RAW_BPL, 0, 0,
|
||||
RAW_LINES);
|
||||
r = bttv_risc_packed(btv, &buf->bottom, list, size / 2,
|
||||
RAW_BPL, 0, 0, RAW_LINES);
|
||||
}
|
||||
|
||||
/* copy format info */
|
||||
buf->btformat = btv->fmt->btformat;
|
||||
buf->btswap = btv->fmt->btswap;
|
||||
return 0;
|
||||
|
||||
return r;
|
||||
}
|
||||
|
@ -34,16 +34,6 @@
|
||||
to be about 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 vbi_debug;
|
||||
|
||||
@ -67,165 +57,123 @@ do { \
|
||||
/* ----------------------------------------------------------------------- */
|
||||
/* vbi risc code + mm */
|
||||
|
||||
static int vbi_buffer_setup(struct videobuf_queue *q,
|
||||
unsigned int *count, unsigned int *size)
|
||||
static int queue_setup_vbi(struct vb2_queue *q, unsigned int *num_buffers,
|
||||
unsigned int *num_planes, unsigned int sizes[],
|
||||
struct device *alloc_devs[])
|
||||
{
|
||||
struct bttv_fh *fh = q->priv_data;
|
||||
struct bttv *btv = fh->btv;
|
||||
struct bttv *btv = vb2_get_drv_priv(q);
|
||||
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",
|
||||
fh->vbi_fmt.fmt.samples_per_line,
|
||||
fh->vbi_fmt.fmt.start[0],
|
||||
fh->vbi_fmt.fmt.start[1],
|
||||
fh->vbi_fmt.fmt.count[0],
|
||||
fh->vbi_fmt.fmt.count[1]);
|
||||
if (*num_planes)
|
||||
return sizes[0] < size ? -EINVAL : 0;
|
||||
*num_planes = 1;
|
||||
sizes[0] = size;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int vbi_buffer_prepare(struct videobuf_queue *q,
|
||||
struct videobuf_buffer *vb,
|
||||
enum v4l2_field field)
|
||||
static void buf_queue_vbi(struct vb2_buffer *vb)
|
||||
{
|
||||
struct bttv_fh *fh = q->priv_data;
|
||||
struct bttv *btv = fh->btv;
|
||||
struct bttv_buffer *buf = container_of(vb,struct bttv_buffer,vb);
|
||||
const struct bttv_tvnorm *tvnorm;
|
||||
unsigned int skip_lines0, skip_lines1, min_vdelay;
|
||||
int redo_dma_risc;
|
||||
int rc;
|
||||
struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
|
||||
struct vb2_queue *vq = vb->vb2_queue;
|
||||
struct bttv *btv = vb2_get_drv_priv(vq);
|
||||
struct bttv_buffer *buf = container_of(vbuf, struct bttv_buffer, vbuf);
|
||||
unsigned long flags;
|
||||
|
||||
buf->vb.size = IMAGE_SIZE(&fh->vbi_fmt.fmt);
|
||||
if (0 != buf->vb.baddr && buf->vb.bsize < buf->vb.size)
|
||||
spin_lock_irqsave(&btv->s_lock, flags);
|
||||
if (list_empty(&btv->vcapture)) {
|
||||
btv->loop_irq = BT848_RISC_VBI;
|
||||
if (vb2_is_streaming(&btv->capq))
|
||||
btv->loop_irq |= BT848_RISC_VIDEO;
|
||||
bttv_set_dma(btv, BT848_CAP_CTL_CAPTURE_VBI_ODD |
|
||||
BT848_CAP_CTL_CAPTURE_VBI_EVEN);
|
||||
}
|
||||
list_add_tail(&buf->list, &btv->vcapture);
|
||||
spin_unlock_irqrestore(&btv->s_lock, flags);
|
||||
}
|
||||
|
||||
static int buf_prepare_vbi(struct vb2_buffer *vb)
|
||||
{
|
||||
int ret = 0;
|
||||
struct vb2_queue *vq = vb->vb2_queue;
|
||||
struct bttv *btv = vb2_get_drv_priv(vq);
|
||||
struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
|
||||
struct bttv_buffer *buf = container_of(vbuf, struct bttv_buffer, vbuf);
|
||||
unsigned int size = IMAGE_SIZE(&btv->vbi_fmt.fmt);
|
||||
|
||||
if (vb2_plane_size(vb, 0) < size)
|
||||
return -EINVAL;
|
||||
vb2_set_plane_payload(vb, 0, size);
|
||||
buf->vbuf.field = V4L2_FIELD_NONE;
|
||||
ret = bttv_buffer_risc_vbi(btv, buf);
|
||||
|
||||
tvnorm = fh->vbi_fmt.tvnorm;
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
if (redo_dma_risc) {
|
||||
unsigned int bpl, padding, offset;
|
||||
struct videobuf_dmabuf *dma=videobuf_to_dma(&buf->vb);
|
||||
|
||||
bpl = 2044; /* max. vbipack */
|
||||
padding = VBI_BPL - bpl;
|
||||
|
||||
if (fh->vbi_fmt.fmt.count[0] > 0) {
|
||||
rc = bttv_risc_packed(btv, &buf->top,
|
||||
dma->sglist,
|
||||
/* offset */ 0, bpl,
|
||||
padding, skip_lines0,
|
||||
fh->vbi_fmt.fmt.count[0]);
|
||||
if (0 != rc)
|
||||
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,
|
||||
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,
|
||||
no matter where the RISC program ends. VDELAY minimum is 2,
|
||||
bounds.top is the corresponding first field line number
|
||||
times two. VDELAY counts half field lines. */
|
||||
min_vdelay = MIN_VDELAY;
|
||||
if (fh->vbi_fmt.end >= tvnorm->cropcap.bounds.top)
|
||||
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:
|
||||
bttv_dma_free(q,btv,buf);
|
||||
return rc;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void
|
||||
vbi_buffer_queue(struct videobuf_queue *q, struct videobuf_buffer *vb)
|
||||
static void buf_cleanup_vbi(struct vb2_buffer *vb)
|
||||
{
|
||||
struct bttv_fh *fh = q->priv_data;
|
||||
struct bttv *btv = fh->btv;
|
||||
struct bttv_buffer *buf = container_of(vb,struct bttv_buffer,vb);
|
||||
struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
|
||||
struct bttv_buffer *buf = container_of(vbuf, struct bttv_buffer, vbuf);
|
||||
struct vb2_queue *vq = vb->vb2_queue;
|
||||
struct bttv *btv = vb2_get_drv_priv(vq);
|
||||
|
||||
dprintk("queue %p\n",vb);
|
||||
buf->vb.state = VIDEOBUF_QUEUED;
|
||||
list_add_tail(&buf->vb.queue,&btv->vcapture);
|
||||
if (NULL == btv->cvbi) {
|
||||
fh->btv->loop_irq |= 4;
|
||||
bttv_set_dma(btv,0x0c);
|
||||
}
|
||||
btcx_riscmem_free(btv->c.pci, &buf->top);
|
||||
btcx_riscmem_free(btv->c.pci, &buf->bottom);
|
||||
}
|
||||
|
||||
static void vbi_buffer_release(struct videobuf_queue *q, struct videobuf_buffer *vb)
|
||||
static int start_streaming_vbi(struct vb2_queue *q, unsigned int count)
|
||||
{
|
||||
struct bttv_fh *fh = q->priv_data;
|
||||
struct bttv *btv = fh->btv;
|
||||
struct bttv_buffer *buf = container_of(vb,struct bttv_buffer,vb);
|
||||
int ret;
|
||||
int seqnr = 0;
|
||||
struct bttv_buffer *buf;
|
||||
struct bttv *btv = vb2_get_drv_priv(q);
|
||||
|
||||
dprintk("free %p\n",vb);
|
||||
bttv_dma_free(q,fh->btv,buf);
|
||||
btv->framedrop = 0;
|
||||
ret = check_alloc_btres_lock(btv, RESOURCE_VBI);
|
||||
if (ret == 0) {
|
||||
if (btv->field_count)
|
||||
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;
|
||||
}
|
||||
|
||||
const struct videobuf_queue_ops bttv_vbi_qops = {
|
||||
.buf_setup = vbi_buffer_setup,
|
||||
.buf_prepare = vbi_buffer_prepare,
|
||||
.buf_queue = vbi_buffer_queue,
|
||||
.buf_release = vbi_buffer_release,
|
||||
static void stop_streaming_vbi(struct vb2_queue *q)
|
||||
{
|
||||
struct bttv *btv = vb2_get_drv_priv(q);
|
||||
unsigned long flags;
|
||||
|
||||
vb2_wait_for_all_buffers(q);
|
||||
spin_lock_irqsave(&btv->s_lock, flags);
|
||||
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 vb2_ops bttv_vbi_qops = {
|
||||
.queue_setup = queue_setup_vbi,
|
||||
.buf_queue = buf_queue_vbi,
|
||||
.buf_prepare = buf_prepare_vbi,
|
||||
.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)
|
||||
|
||||
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);
|
||||
const struct bttv_tvnorm *tvnorm;
|
||||
__s32 start1, end;
|
||||
@ -325,7 +272,7 @@ int bttv_s_fmt_vbi_cap(struct file *file, void *f, struct v4l2_format *frt)
|
||||
mutex_lock(&btv->lock);
|
||||
|
||||
rc = -EBUSY;
|
||||
if (fh->resources & RESOURCE_VBI)
|
||||
if (btv->resources & RESOURCE_VBI)
|
||||
goto fail;
|
||||
|
||||
tvnorm = &bttv_tvnorms[btv->tvnorm];
|
||||
@ -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. */
|
||||
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.tvnorm = tvnorm;
|
||||
btv->vbi_fmt.end = end;
|
||||
|
||||
mutex_unlock(&fh->vbi.vb_lock);
|
||||
|
||||
rc = 0;
|
||||
|
||||
fail:
|
||||
|
@ -26,7 +26,7 @@
|
||||
#include <media/v4l2-common.h>
|
||||
#include <media/v4l2-ctrls.h>
|
||||
#include <media/v4l2-fh.h>
|
||||
#include <media/videobuf-dma-sg.h>
|
||||
#include <media/videobuf2-dma-sg.h>
|
||||
#include <media/tveeprom.h>
|
||||
#include <media/rc-core.h>
|
||||
#include <media/i2c/ir-kbd-i2c.h>
|
||||
@ -142,7 +142,8 @@ struct bttv_geometry {
|
||||
|
||||
struct bttv_buffer {
|
||||
/* common v4l buffer stuff -- must be first */
|
||||
struct videobuf_buffer vb;
|
||||
struct vb2_v4l2_buffer vbuf;
|
||||
struct list_head list;
|
||||
|
||||
/* bttv specific */
|
||||
int btformat;
|
||||
@ -171,6 +172,8 @@ struct bttv_vbi_fmt {
|
||||
};
|
||||
|
||||
/* bttv-vbi.c */
|
||||
extern const struct vb2_ops bttv_vbi_qops;
|
||||
|
||||
void bttv_vbi_fmt_reset(struct bttv_vbi_fmt *f, unsigned int norm);
|
||||
|
||||
struct bttv_crop {
|
||||
@ -187,28 +190,6 @@ struct bttv_crop {
|
||||
__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 */
|
||||
|
||||
@ -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_activate_video(struct bttv *btv,
|
||||
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,
|
||||
struct bttv_buffer *vbi);
|
||||
void bttv_dma_free(struct videobuf_queue *q, struct bttv *btv,
|
||||
struct bttv_buffer *buf);
|
||||
|
||||
/* ---------------------------------------------------------- */
|
||||
/* 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
|
||||
|
||||
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_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 */
|
||||
|
||||
@ -269,6 +255,8 @@ extern int fini_bttv_i2c(struct bttv *btv);
|
||||
extern unsigned int bttv_verbose;
|
||||
extern unsigned int bttv_debug;
|
||||
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);
|
||||
|
||||
#define dprintk(fmt, ...) \
|
||||
@ -390,7 +378,7 @@ struct bttv {
|
||||
v4l2_std_id std;
|
||||
int hue, contrast, bright, saturation;
|
||||
struct v4l2_framebuffer fbuf;
|
||||
unsigned int field_count;
|
||||
__u32 field_count;
|
||||
|
||||
/* various options */
|
||||
int opt_combfilter;
|
||||
@ -441,12 +429,21 @@ struct bttv {
|
||||
unsigned int irq_me;
|
||||
|
||||
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;
|
||||
int width;
|
||||
int height;
|
||||
|
||||
/* vbi capture */
|
||||
struct vb2_queue vbiq;
|
||||
struct bttv_vbi_fmt vbi_fmt;
|
||||
unsigned int vbi_skip[2];
|
||||
unsigned int vbi_count[2];
|
||||
|
||||
/* Application called VIDIOC_S_SELECTION. */
|
||||
@ -489,6 +486,8 @@ static inline unsigned int bttv_muxsel(const struct bttv *btv,
|
||||
|
||||
#endif
|
||||
|
||||
void init_irqreg(struct bttv *btv);
|
||||
|
||||
#define btwrite(dat,adr) writel((dat), btv->bt848_mmio+(adr))
|
||||
#define btread(adr) readl(btv->bt848_mmio+(adr))
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user