diff --git a/drivers/media/dvb-frontends/af9013.c b/drivers/media/dvb-frontends/af9013.c index a829c89792a4..5afdbe244596 100644 --- a/drivers/media/dvb-frontends/af9013.c +++ b/drivers/media/dvb-frontends/af9013.c @@ -1480,7 +1480,7 @@ static int af9013_probe(struct i2c_client *client) goto err_regmap_exit; } state->muxc->priv = state; - ret = i2c_mux_add_adapter(state->muxc, 0, 0, 0); + ret = i2c_mux_add_adapter(state->muxc, 0, 0); if (ret) goto err_regmap_exit; diff --git a/drivers/media/dvb-frontends/gx1133.c b/drivers/media/dvb-frontends/gx1133.c index 45e8abfa91a2..6d616de86d78 100644 --- a/drivers/media/dvb-frontends/gx1133.c +++ b/drivers/media/dvb-frontends/gx1133.c @@ -810,10 +810,10 @@ struct dvb_frontend *gx1133_attach(const struct gx1133_config *cfg, goto err1; } priv->muxc->priv = priv; - ret = i2c_mux_add_adapter(priv->muxc, 0, 0, 0); + ret = i2c_mux_add_adapter(priv->muxc, 0, 0); if (ret) goto err1; - ret = i2c_mux_add_adapter(priv->muxc, 0, 1, 0); + ret = i2c_mux_add_adapter(priv->muxc, 0, 1); if (ret) goto err1; priv->i2c_demod = priv->muxc->adapter[0]; diff --git a/drivers/media/dvb-frontends/gx1503.c b/drivers/media/dvb-frontends/gx1503.c index 8107d63c2ce8..18b7b4f9feb4 100644 --- a/drivers/media/dvb-frontends/gx1503.c +++ b/drivers/media/dvb-frontends/gx1503.c @@ -516,7 +516,7 @@ static int gx1503_probe(struct i2c_client *client) goto err_regmap_exit; } dev->muxc->priv = client; - ret = i2c_mux_add_adapter(dev->muxc,0,0,0); + ret = i2c_mux_add_adapter(dev->muxc,0,0); if(ret) goto err_regmap_exit; diff --git a/drivers/media/dvb-frontends/lgdt3306a.c b/drivers/media/dvb-frontends/lgdt3306a.c index 2d7750649850..a1cb424527cc 100644 --- a/drivers/media/dvb-frontends/lgdt3306a.c +++ b/drivers/media/dvb-frontends/lgdt3306a.c @@ -2203,7 +2203,7 @@ static int lgdt3306a_probe(struct i2c_client *client) goto err_kfree; } state->muxc->priv = client; - ret = i2c_mux_add_adapter(state->muxc, 0, 0, 0); + ret = i2c_mux_add_adapter(state->muxc, 0, 0); if (ret) goto err_kfree; diff --git a/drivers/media/dvb-frontends/m88ds3103.c b/drivers/media/dvb-frontends/m88ds3103.c index cf037b61b226..fae55c4563ff 100644 --- a/drivers/media/dvb-frontends/m88ds3103.c +++ b/drivers/media/dvb-frontends/m88ds3103.c @@ -1866,7 +1866,7 @@ static int m88ds3103_probe(struct i2c_client *client) goto err_kfree; } dev->muxc->priv = dev; - ret = i2c_mux_add_adapter(dev->muxc, 0, 0, 0); + ret = i2c_mux_add_adapter(dev->muxc, 0, 0); if (ret) goto err_kfree; diff --git a/drivers/media/dvb-frontends/rtl2830.c b/drivers/media/dvb-frontends/rtl2830.c index 35c969fd2cb5..30d10fe4b33e 100644 --- a/drivers/media/dvb-frontends/rtl2830.c +++ b/drivers/media/dvb-frontends/rtl2830.c @@ -838,7 +838,7 @@ static int rtl2830_probe(struct i2c_client *client) goto err_regmap_exit; } dev->muxc->priv = client; - ret = i2c_mux_add_adapter(dev->muxc, 0, 0, 0); + ret = i2c_mux_add_adapter(dev->muxc, 0, 0); if (ret) goto err_regmap_exit; diff --git a/drivers/media/dvb-frontends/rtl2832.c b/drivers/media/dvb-frontends/rtl2832.c index 601cf45c3935..5142820b1b3d 100644 --- a/drivers/media/dvb-frontends/rtl2832.c +++ b/drivers/media/dvb-frontends/rtl2832.c @@ -1082,7 +1082,7 @@ static int rtl2832_probe(struct i2c_client *client) goto err_regmap_exit; } dev->muxc->priv = dev; - ret = i2c_mux_add_adapter(dev->muxc, 0, 0, 0); + ret = i2c_mux_add_adapter(dev->muxc, 0, 0); if (ret) goto err_regmap_exit; diff --git a/drivers/media/dvb-frontends/si2168.c b/drivers/media/dvb-frontends/si2168.c index 9dc02f7c30c4..dc33eb8ead8b 100644 --- a/drivers/media/dvb-frontends/si2168.c +++ b/drivers/media/dvb-frontends/si2168.c @@ -911,7 +911,7 @@ static int si2168_probe(struct i2c_client *client) goto err_kfree; } dev->muxc->priv = client; - ret = i2c_mux_add_adapter(dev->muxc, 0, 0, 0); + ret = i2c_mux_add_adapter(dev->muxc, 0, 0); if (ret) goto err_kfree; diff --git a/drivers/media/dvb-frontends/si2183.c b/drivers/media/dvb-frontends/si2183.c index fd1e78d9f0d8..6f07d7a89e2a 100644 --- a/drivers/media/dvb-frontends/si2183.c +++ b/drivers/media/dvb-frontends/si2183.c @@ -1734,7 +1734,7 @@ static int si2183_probe(struct i2c_client *client) goto err_base_kfree; } base->muxc->priv = client; - ret = i2c_mux_add_adapter(base->muxc, 0, 0, 0); + ret = i2c_mux_add_adapter(base->muxc, 0, 0); if (ret) goto err_base_kfree; base->tuner_adapter = base->muxc->adapter[0]; diff --git a/drivers/media/dvb-frontends/tas2101.c b/drivers/media/dvb-frontends/tas2101.c index dbbc3a8c65e2..ef2211d30010 100644 --- a/drivers/media/dvb-frontends/tas2101.c +++ b/drivers/media/dvb-frontends/tas2101.c @@ -624,10 +624,10 @@ struct dvb_frontend *tas2101_attach(const struct tas2101_config *cfg, goto err1; } priv->muxc->priv = priv; - ret = i2c_mux_add_adapter(priv->muxc, 0, 0, 0); + ret = i2c_mux_add_adapter(priv->muxc, 0, 0); if (ret) goto err1; - ret = i2c_mux_add_adapter(priv->muxc, 0, 1, 0); + ret = i2c_mux_add_adapter(priv->muxc, 0, 1); if (ret) goto err1; priv->i2c_demod = priv->muxc->adapter[0]; diff --git a/drivers/media/dvb-frontends/tas2971.c b/drivers/media/dvb-frontends/tas2971.c index 059ef8305ad8..f12c5e3770db 100644 --- a/drivers/media/dvb-frontends/tas2971.c +++ b/drivers/media/dvb-frontends/tas2971.c @@ -294,10 +294,10 @@ struct dvb_frontend *tas2971_attach(const struct tas2101_config *cfg, goto err1; } base->muxc->priv = priv; - ret = i2c_mux_add_adapter(base->muxc, 0, 0, 0); + ret = i2c_mux_add_adapter(base->muxc, 0, 0); if (ret) goto err1; - ret = i2c_mux_add_adapter(base->muxc, 0, 1, 0); + ret = i2c_mux_add_adapter(base->muxc, 0, 1); if (ret) goto err1; base->i2c_demod = base->muxc->adapter[0]; diff --git a/drivers/media/i2c/max9286.c b/drivers/media/i2c/max9286.c index 88c58e0c49aa..bf591bf5da25 100644 --- a/drivers/media/i2c/max9286.c +++ b/drivers/media/i2c/max9286.c @@ -382,7 +382,7 @@ static int max9286_i2c_mux_init(struct max9286_priv *priv) for_each_source(priv, source) { unsigned int index = to_index(priv, source); - ret = i2c_mux_add_adapter(priv->mux, 0, index, 0); + ret = i2c_mux_add_adapter(priv->mux, 0, index); if (ret < 0) goto error; } diff --git a/drivers/media/pci/bt8xx/Kconfig b/drivers/media/pci/bt8xx/Kconfig index 2d674dc28cec..2f77628246e9 100644 --- a/drivers/media/pci/bt8xx/Kconfig +++ b/drivers/media/pci/bt8xx/Kconfig @@ -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 diff --git a/drivers/media/pci/bt8xx/bt848.h b/drivers/media/pci/bt8xx/bt848.h index 16999e717d18..c8a0e1ab001f 100644 --- a/drivers/media/pci/bt8xx/bt848.h +++ b/drivers/media/pci/bt8xx/bt848.h @@ -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) diff --git a/drivers/media/pci/bt8xx/bt878.c b/drivers/media/pci/bt8xx/bt878.c index 90972d6952f1..5c9ba4bfc1be 100644 --- a/drivers/media/pci/bt8xx/bt878.c +++ b/drivers/media/pci/bt8xx/bt878.c @@ -563,4 +563,5 @@ static void __exit bt878_cleanup_module(void) module_init(bt878_init_module); module_exit(bt878_cleanup_module); +MODULE_DESCRIPTION("DVB/ATSC Support for bt878 based TV cards"); MODULE_LICENSE("GPL"); diff --git a/drivers/media/pci/bt8xx/bttv-audio-hook.c b/drivers/media/pci/bt8xx/bttv-audio-hook.c index da1914a20b81..b5d071835354 100644 --- a/drivers/media/pci/bt8xx/bttv-audio-hook.c +++ b/drivers/media/pci/bt8xx/bttv-audio-hook.c @@ -293,16 +293,8 @@ void winfast2000_audio(struct bttv *btv, struct v4l2_tuner *t, int set) { unsigned long val; - if (!set) { - /* Not much to do here */ - t->audmode = V4L2_TUNER_MODE_LANG1; - t->rxsubchans = V4L2_TUNER_SUB_MONO | - V4L2_TUNER_SUB_STEREO | - V4L2_TUNER_SUB_LANG1 | - V4L2_TUNER_SUB_LANG2; - + if (!set) return; - } /*btor (0xc32000, BT848_GPIO_OUT_EN);*/ switch (t->audmode) { diff --git a/drivers/media/pci/bt8xx/bttv-cards.c b/drivers/media/pci/bt8xx/bttv-cards.c index ec78f7fc5e1b..867c1308de23 100644 --- a/drivers/media/pci/bt8xx/bttv-cards.c +++ b/drivers/media/pci/bt8xx/bttv-cards.c @@ -126,6 +126,7 @@ MODULE_PARM_DESC(audiodev, "specify audio device:\n" "\t\t 3 = tvaudio"); MODULE_PARM_DESC(saa6588, "if 1, then load the saa6588 RDS module, default (0) is to use the card definition."); +MODULE_FIRMWARE("hcwamc.rbf"); /* I2C addresses list */ #define I2C_ADDR_TDA7432 0x8a diff --git a/drivers/media/pci/bt8xx/bttv-driver.c b/drivers/media/pci/bt8xx/bttv-driver.c index 734f02b91aa3..49a3dd70ec0f 100644 --- a/drivers/media/pci/bt8xx/bttv-driver.c +++ b/drivers/media/pci/bt8xx/bttv-driver.c @@ -641,15 +641,10 @@ static const unsigned int FORMATS = ARRAY_SIZE(formats); #define VIDEO_RESOURCES (RESOURCE_VIDEO_READ | \ RESOURCE_VIDEO_STREAM) -static -int check_alloc_btres_lock(struct bttv *btv, struct bttv_fh *fh, int bit) +int check_alloc_btres_lock(struct bttv *btv, int bit) { int xbits; /* mutual exclusive resources */ - if (fh->resources & bit) - /* have it already allocated */ - return 1; - xbits = bit; if (bit & (RESOURCE_VIDEO_READ | RESOURCE_VIDEO_STREAM)) xbits |= RESOURCE_VIDEO_READ | RESOURCE_VIDEO_STREAM; @@ -663,7 +658,7 @@ int check_alloc_btres_lock(struct bttv *btv, struct bttv_fh *fh, int bit) if ((bit & VIDEO_RESOURCES) && 0 == (btv->resources & VIDEO_RESOURCES)) { /* Do crop - use current, don't - use default parameters. */ - __s32 top = btv->crop[!!fh->do_crop].rect.top; + __s32 top = btv->crop[!!btv->do_crop].rect.top; if (btv->vbi_end > top) goto fail; @@ -672,17 +667,16 @@ int check_alloc_btres_lock(struct bttv *btv, struct bttv_fh *fh, int bit) Claim scan lines crop[].rect.top to bottom. */ btv->crop_start = top; } else if (bit & VBI_RESOURCES) { - __s32 end = fh->vbi_fmt.end; + __s32 end = btv->vbi_fmt.end; if (end > btv->crop_start) goto fail; - /* Claim scan lines above fh->vbi_fmt.end. */ + /* Claim scan lines above btv->vbi_fmt.end. */ btv->vbi_end = end; } /* it's free, grab it */ - fh->resources |= bit; btv->resources |= bit; return 1; @@ -691,9 +685,9 @@ int check_alloc_btres_lock(struct bttv *btv, struct bttv_fh *fh, int bit) } static -int check_btres(struct bttv_fh *fh, int bit) +int check_btres(struct bttv *btv, int bit) { - return (fh->resources & bit); + return (btv->resources & bit); } static @@ -731,14 +725,12 @@ disclaim_video_lines(struct bttv *btv) btwrite(0xfe, BT848_O_VDELAY_LO); } -static -void free_btres_lock(struct bttv *btv, struct bttv_fh *fh, int bits) +void free_btres_lock(struct bttv *btv, int bits) { - if ((fh->resources & bits) != bits) { + if ((btv->resources & bits) != bits) { /* trying to free resources not allocated by us ... */ pr_err("BUG! (btres)\n"); } - fh->resources &= ~bits; btv->resources &= ~bits; bits = btv->resources; @@ -1111,8 +1103,8 @@ set_tvnorm(struct bttv *btv, unsigned int norm) const struct bttv_tvnorm *tvnorm; v4l2_std_id id; - BUG_ON(norm >= BTTV_TVNORMS); - BUG_ON(btv->tvnorm >= BTTV_TVNORMS); + WARN_ON(norm >= BTTV_TVNORMS); + WARN_ON(btv->tvnorm >= BTTV_TVNORMS); tvnorm = &bttv_tvnorms[norm]; @@ -1174,7 +1166,7 @@ set_input(struct bttv *btv, unsigned int input, unsigned int norm) set_tvnorm(btv, norm); } -static void init_irqreg(struct bttv *btv) +void init_irqreg(struct bttv *btv) { /* clear status */ btwrite(0xfffffUL, BT848_INT_STAT); @@ -1453,23 +1445,6 @@ void bttv_gpio_tracking(struct bttv *btv, char *comment) btv->c.nr, outbits, data & outbits, data & ~outbits, comment); } -static void bttv_field_count(struct bttv *btv) -{ - int need_count = 0; - - if (btv->users) - need_count++; - - if (need_count) { - /* start field counter */ - btor(BT848_INT_VSYNC,BT848_INT_MASK); - } else { - /* stop field counter */ - btand(~BT848_INT_VSYNC,BT848_INT_MASK); - btv->field_count = 0; - } -} - static const struct bttv_format* format_by_fourcc(int fourcc) { @@ -1487,158 +1462,130 @@ format_by_fourcc(int fourcc) /* ----------------------------------------------------------------------- */ /* video4linux (1) interface */ -static int bttv_prepare_buffer(struct videobuf_queue *q,struct bttv *btv, - struct bttv_buffer *buf, - const struct bttv_format *fmt, - unsigned int width, unsigned int height, - enum v4l2_field field) +static int queue_setup(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; - int redo_dma_risc = 0; - struct bttv_crop c; - int norm; - int rc; + struct bttv *btv = vb2_get_drv_priv(q); + unsigned int size = btv->fmt->depth * btv->width * btv->height >> 3; - /* check settings */ - if (NULL == fmt) + if (*num_planes) + return sizes[0] < size ? -EINVAL : 0; + *num_planes = 1; + sizes[0] = size; + + return 0; +} + +static void buf_queue(struct vb2_buffer *vb) +{ + 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; + + spin_lock_irqsave(&btv->s_lock, flags); + if (list_empty(&btv->capture)) { + btv->loop_irq = BT848_RISC_VIDEO; + if (vb2_is_streaming(&btv->vbiq)) + btv->loop_irq |= BT848_RISC_VBI; + bttv_set_dma(btv, BT848_CAP_CTL_CAPTURE_ODD | + BT848_CAP_CTL_CAPTURE_EVEN); + } + list_add_tail(&buf->list, &btv->capture); + spin_unlock_irqrestore(&btv->s_lock, flags); +} + +static int buf_prepare(struct vb2_buffer *vb) +{ + 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 = (btv->fmt->depth * btv->width * btv->height) >> 3; + + if (vb2_plane_size(vb, 0) < size) return -EINVAL; - if (fmt->btformat == BT848_COLOR_FMT_RAW) { - width = RAW_BPL; - height = RAW_LINES*2; - if (width*height > buf->vb.bsize) - return -EINVAL; - buf->vb.size = buf->vb.bsize; + vb2_set_plane_payload(vb, 0, size); - /* Make sure tvnorm and vbi_end remain consistent - until we're done. */ - - norm = btv->tvnorm; - - /* In this mode capturing always starts at defrect.top - (default VDELAY), ignoring cropping parameters. */ - if (btv->vbi_end > bttv_tvnorms[norm].cropcap.defrect.top) { - return -EINVAL; - } - - c.rect = bttv_tvnorms[norm].cropcap.defrect; + if (btv->field != V4L2_FIELD_ALTERNATE) { + buf->vbuf.field = btv->field; + } else if (btv->field_last == V4L2_FIELD_TOP) { + buf->vbuf.field = V4L2_FIELD_BOTTOM; + btv->field_last = V4L2_FIELD_BOTTOM; } else { - norm = btv->tvnorm; - c = btv->crop[!!fh->do_crop]; + buf->vbuf.field = V4L2_FIELD_TOP; + btv->field_last = V4L2_FIELD_TOP; + } - if (width < c.min_scaled_width || - width > c.max_scaled_width || - height < c.min_scaled_height) - return -EINVAL; + /* Allocate memory for risc struct and create the risc program. */ + return bttv_buffer_risc(btv, buf); +} - switch (field) { - case V4L2_FIELD_TOP: - case V4L2_FIELD_BOTTOM: - case V4L2_FIELD_ALTERNATE: - /* btv->crop counts frame lines. Max. scale - factor is 16:1 for frames, 8:1 for fields. */ - if (height * 2 > c.max_scaled_height) - return -EINVAL; - break; +static void buf_cleanup(struct vb2_buffer *vb) +{ + 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); - default: - if (height > c.max_scaled_height) - return -EINVAL; - break; + btcx_riscmem_free(btv->c.pci, &buf->top); + btcx_riscmem_free(btv->c.pci, &buf->bottom); +} + +static int start_streaming(struct vb2_queue *q, unsigned int count) +{ + int seqnr = 0; + struct bttv_buffer *buf; + struct bttv *btv = vb2_get_drv_priv(q); + + if (!check_alloc_btres_lock(btv, RESOURCE_VIDEO_STREAM)) { + if (btv->field_count) + seqnr++; + while (!list_empty(&btv->capture)) { + buf = list_entry(btv->capture.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); } - - buf->vb.size = (width * height * fmt->depth) >> 3; - if (0 != buf->vb.baddr && buf->vb.bsize < buf->vb.size) - return -EINVAL; + return -EBUSY; } - - /* alloc + fill struct bttv_buffer (if changed) */ - if (buf->vb.width != width || buf->vb.height != height || - buf->vb.field != field || - buf->tvnorm != norm || buf->fmt != fmt || - buf->crop.top != c.rect.top || - buf->crop.left != c.rect.left || - buf->crop.width != c.rect.width || - buf->crop.height != c.rect.height) { - buf->vb.width = width; - buf->vb.height = height; - buf->vb.field = field; - buf->tvnorm = norm; - buf->fmt = fmt; - buf->crop = c.rect; - redo_dma_risc = 1; + if (!vb2_is_streaming(&btv->vbiq)) { + init_irqreg(btv); + btv->field_count = 0; } + btv->framedrop = 0; - /* alloc risc memory */ - if (VIDEOBUF_NEEDS_INIT == buf->vb.state) { - redo_dma_risc = 1; - if (0 != (rc = videobuf_iolock(q,&buf->vb,&btv->fbuf))) - goto fail; - } - - if (redo_dma_risc) - if (0 != (rc = bttv_buffer_risc(btv,buf))) - goto fail; - - buf->vb.state = VIDEOBUF_PREPARED; - return 0; - - fail: - bttv_dma_free(q,btv,buf); - return rc; -} - -static int -buffer_setup(struct videobuf_queue *q, unsigned int *count, unsigned int *size) -{ - struct bttv_fh *fh = q->priv_data; - - *size = fh->fmt->depth*fh->width*fh->height >> 3; - if (0 == *count) - *count = gbuffers; - if (*size * *count > gbuffers * gbufsize) - *count = (gbuffers * gbufsize) / *size; return 0; } -static int -buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb, - enum v4l2_field field) +static void stop_streaming(struct vb2_queue *q) { - struct bttv_buffer *buf = container_of(vb,struct bttv_buffer,vb); - struct bttv_fh *fh = q->priv_data; + unsigned long flags; + struct bttv *btv = vb2_get_drv_priv(q); - return bttv_prepare_buffer(q,fh->btv, buf, fh->fmt, - fh->width, fh->height, field); -} - -static void -buffer_queue(struct videobuf_queue *q, struct videobuf_buffer *vb) -{ - struct bttv_buffer *buf = container_of(vb,struct bttv_buffer,vb); - struct bttv_fh *fh = q->priv_data; - struct bttv *btv = fh->btv; - - buf->vb.state = VIDEOBUF_QUEUED; - list_add_tail(&buf->vb.queue,&btv->capture); - if (!btv->curr.frame_irq) { - btv->loop_irq |= 1; - bttv_set_dma(btv, 0x03); + vb2_wait_for_all_buffers(q); + spin_lock_irqsave(&btv->s_lock, flags); + free_btres_lock(btv, RESOURCE_VIDEO_STREAM); + if (!vb2_is_streaming(&btv->vbiq)) { + /* stop field counter */ + btand(~BT848_INT_VSYNC, BT848_INT_MASK); } + spin_unlock_irqrestore(&btv->s_lock, flags); } -static void buffer_release(struct videobuf_queue *q, struct videobuf_buffer *vb) -{ - struct bttv_buffer *buf = container_of(vb,struct bttv_buffer,vb); - struct bttv_fh *fh = q->priv_data; - - bttv_dma_free(q,fh->btv,buf); -} - -static const struct videobuf_queue_ops bttv_video_qops = { - .buf_setup = buffer_setup, - .buf_prepare = buffer_prepare, - .buf_queue = buffer_queue, - .buf_release = buffer_release, +static const struct vb2_ops bttv_video_qops = { + .queue_setup = queue_setup, + .buf_queue = buf_queue, + .buf_prepare = buf_prepare, + .buf_cleanup = buf_cleanup, + .start_streaming = start_streaming, + .stop_streaming = stop_streaming, + .wait_prepare = vb2_ops_wait_prepare, + .wait_finish = vb2_ops_wait_finish, }; static void radio_enable(struct bttv *btv) @@ -1654,8 +1601,7 @@ static void radio_enable(struct bttv *btv) static int bttv_s_std(struct file *file, void *priv, v4l2_std_id id) { - struct bttv_fh *fh = priv; - struct bttv *btv = fh->btv; + struct bttv *btv = video_drvdata(file); unsigned int i; for (i = 0; i < BTTV_TVNORMS; i++) @@ -1670,8 +1616,7 @@ static int bttv_s_std(struct file *file, void *priv, v4l2_std_id id) static int bttv_g_std(struct file *file, void *priv, v4l2_std_id *id) { - struct bttv_fh *fh = priv; - struct bttv *btv = fh->btv; + struct bttv *btv = video_drvdata(file); *id = btv->std; return 0; @@ -1679,8 +1624,7 @@ static int bttv_g_std(struct file *file, void *priv, v4l2_std_id *id) static int bttv_querystd(struct file *file, void *f, v4l2_std_id *id) { - struct bttv_fh *fh = f; - struct bttv *btv = fh->btv; + struct bttv *btv = video_drvdata(file); if (btread(BT848_DSTATUS) & BT848_DSTATUS_NUML) *id &= V4L2_STD_625_50; @@ -1692,8 +1636,7 @@ static int bttv_querystd(struct file *file, void *f, v4l2_std_id *id) static int bttv_enum_input(struct file *file, void *priv, struct v4l2_input *i) { - struct bttv_fh *fh = priv; - struct bttv *btv = fh->btv; + struct bttv *btv = video_drvdata(file); if (i->index >= bttv_tvcards[btv->c.type].video_inputs) return -EINVAL; @@ -1725,8 +1668,7 @@ static int bttv_enum_input(struct file *file, void *priv, static int bttv_g_input(struct file *file, void *priv, unsigned int *i) { - struct bttv_fh *fh = priv; - struct bttv *btv = fh->btv; + struct bttv *btv = video_drvdata(file); *i = btv->input; @@ -1735,8 +1677,7 @@ static int bttv_g_input(struct file *file, void *priv, unsigned int *i) static int bttv_s_input(struct file *file, void *priv, unsigned int i) { - struct bttv_fh *fh = priv; - struct bttv *btv = fh->btv; + struct bttv *btv = video_drvdata(file); if (i >= bttv_tvcards[btv->c.type].video_inputs) return -EINVAL; @@ -1748,8 +1689,7 @@ static int bttv_s_input(struct file *file, void *priv, unsigned int i) static int bttv_s_tuner(struct file *file, void *priv, const struct v4l2_tuner *t) { - struct bttv_fh *fh = priv; - struct bttv *btv = fh->btv; + struct bttv *btv = video_drvdata(file); if (t->index) return -EINVAL; @@ -1767,8 +1707,7 @@ static int bttv_s_tuner(struct file *file, void *priv, static int bttv_g_frequency(struct file *file, void *priv, struct v4l2_frequency *f) { - struct bttv_fh *fh = priv; - struct bttv *btv = fh->btv; + struct bttv *btv = video_drvdata(file); if (f->tuner) return -EINVAL; @@ -1804,8 +1743,7 @@ static void bttv_set_frequency(struct bttv *btv, const struct v4l2_frequency *f) static int bttv_s_frequency(struct file *file, void *priv, const struct v4l2_frequency *f) { - struct bttv_fh *fh = priv; - struct bttv *btv = fh->btv; + struct bttv *btv = video_drvdata(file); if (f->tuner) return -EINVAL; @@ -1817,8 +1755,7 @@ static int bttv_s_frequency(struct file *file, void *priv, static int bttv_log_status(struct file *file, void *f) { struct video_device *vdev = video_devdata(file); - struct bttv_fh *fh = f; - struct bttv *btv = fh->btv; + struct bttv *btv = video_drvdata(file); v4l2_ctrl_handler_log_status(vdev->ctrl_handler, btv->c.v4l2_dev.name); bttv_call_all(btv, core, log_status); @@ -1829,8 +1766,7 @@ static int bttv_log_status(struct file *file, void *f) static int bttv_g_register(struct file *file, void *f, struct v4l2_dbg_register *reg) { - struct bttv_fh *fh = f; - struct bttv *btv = fh->btv; + struct bttv *btv = video_drvdata(file); /* bt848 has a 12-bit register space */ reg->reg &= 0xfff; @@ -1843,8 +1779,7 @@ static int bttv_g_register(struct file *file, void *f, static int bttv_s_register(struct file *file, void *f, const struct v4l2_dbg_register *reg) { - struct bttv_fh *fh = f; - struct bttv *btv = fh->btv; + struct bttv *btv = video_drvdata(file); /* bt848 has a 12-bit register space */ btwrite(reg->val, reg->reg & 0xfff); @@ -1904,16 +1839,11 @@ bttv_crop_adjust (struct bttv_crop * c, also adjust the current cropping parameters to get closer to the desired image size. */ static int -limit_scaled_size_lock (struct bttv_fh * fh, - __s32 * width, - __s32 * height, - enum v4l2_field field, - unsigned int width_mask, - unsigned int width_bias, - int adjust_size, - int adjust_crop) +limit_scaled_size_lock(struct bttv *btv, __s32 *width, __s32 *height, + enum v4l2_field field, unsigned int width_mask, + unsigned int width_bias, int adjust_size, + int adjust_crop) { - struct bttv *btv = fh->btv; const struct v4l2_rect *b; struct bttv_crop *c; __s32 min_width; @@ -1922,8 +1852,8 @@ limit_scaled_size_lock (struct bttv_fh * fh, __s32 max_height; int rc; - BUG_ON((int) width_mask >= 0 || - width_bias >= (unsigned int) -width_mask); + WARN_ON((int)width_mask >= 0 || + width_bias >= (unsigned int)(-width_mask)); /* Make sure tvnorm, vbi_end and the current cropping parameters remain consistent until we're done. */ @@ -1931,9 +1861,9 @@ limit_scaled_size_lock (struct bttv_fh * fh, b = &bttv_tvnorms[btv->tvnorm].cropcap.bounds; /* Do crop - use current, don't - use default parameters. */ - c = &btv->crop[!!fh->do_crop]; + c = &btv->crop[!!btv->do_crop]; - if (fh->do_crop + if (btv->do_crop && adjust_size && adjust_crop && !locked_btres(btv, VIDEO_RESOURCES)) { @@ -2007,52 +1937,31 @@ limit_scaled_size_lock (struct bttv_fh * fh, return rc; } -/* ----------------------------------------------------------------------- */ - -static struct videobuf_queue* bttv_queue(struct bttv_fh *fh) +static int bttv_switch_type(struct bttv *btv, enum v4l2_buf_type type) { - struct videobuf_queue* q = NULL; + int res; + struct vb2_queue *q; - switch (fh->type) { - case V4L2_BUF_TYPE_VIDEO_CAPTURE: - q = &fh->cap; - break; - case V4L2_BUF_TYPE_VBI_CAPTURE: - q = &fh->vbi; - break; - default: - BUG(); - } - return q; -} - -static int bttv_resource(struct bttv_fh *fh) -{ - int res = 0; - - switch (fh->type) { + switch (type) { case V4L2_BUF_TYPE_VIDEO_CAPTURE: + q = &btv->capq; res = RESOURCE_VIDEO_STREAM; break; case V4L2_BUF_TYPE_VBI_CAPTURE: + q = &btv->vbiq; res = RESOURCE_VBI; break; default: - BUG(); + WARN_ON(1); + return -EINVAL; } - return res; -} -static int bttv_switch_type(struct bttv_fh *fh, enum v4l2_buf_type type) -{ - struct videobuf_queue *q = bttv_queue(fh); - int res = bttv_resource(fh); + if (check_btres(btv, res)) + return -EBUSY; + if (vb2_is_busy(q)) + return -EBUSY; + btv->type = type; - if (check_btres(fh,res)) - return -EBUSY; - if (videobuf_queue_is_busy(q)) - return -EBUSY; - fh->type = type; return 0; } @@ -2077,12 +1986,11 @@ pix_format_set_size (struct v4l2_pix_format * f, static int bttv_g_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *f) { - struct bttv_fh *fh = priv; + struct bttv *btv = video_drvdata(file); - pix_format_set_size(&f->fmt.pix, fh->fmt, - fh->width, fh->height); - f->fmt.pix.field = fh->cap.field; - f->fmt.pix.pixelformat = fh->fmt->fourcc; + pix_format_set_size(&f->fmt.pix, btv->fmt, btv->width, btv->height); + f->fmt.pix.field = btv->field; + f->fmt.pix.pixelformat = btv->fmt->fourcc; f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; return 0; @@ -2105,8 +2013,7 @@ static int bttv_try_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *f) { const struct bttv_format *fmt; - struct bttv_fh *fh = priv; - struct bttv *btv = fh->btv; + struct bttv *btv = video_drvdata(file); enum v4l2_field field; __s32 width, height; __s32 height2; @@ -2133,7 +2040,7 @@ static int bttv_try_fmt_vid_cap(struct file *file, void *priv, } fallthrough; default: /* FIELD_ANY case */ - height2 = btv->crop[!!fh->do_crop].rect.height >> 1; + height2 = btv->crop[!!btv->do_crop].rect.height >> 1; field = (f->fmt.pix.height > height2) ? V4L2_FIELD_INTERLACED : V4L2_FIELD_BOTTOM; @@ -2144,10 +2051,8 @@ static int bttv_try_fmt_vid_cap(struct file *file, void *priv, height = f->fmt.pix.height; bttv_get_width_mask_vid_cap(fmt, &width_mask, &width_bias); - rc = limit_scaled_size_lock(fh, &width, &height, field, - width_mask, width_bias, - /* adjust_size */ 1, - /* adjust_crop */ 0); + rc = limit_scaled_size_lock(btv, &width, &height, field, width_mask, + width_bias, 1, 0); if (0 != rc) return rc; @@ -2160,17 +2065,16 @@ static int bttv_try_fmt_vid_cap(struct file *file, void *priv, } static int bttv_s_fmt_vid_cap(struct file *file, void *priv, - struct v4l2_format *f) + struct v4l2_format *f) { int retval; const struct bttv_format *fmt; - struct bttv_fh *fh = priv; - struct bttv *btv = fh->btv; + struct bttv *btv = video_drvdata(file); __s32 width, height; unsigned int width_mask, width_bias; enum v4l2_field field; - retval = bttv_switch_type(fh, f->type); + retval = bttv_switch_type(btv, f->type); if (0 != retval) return retval; @@ -2184,24 +2088,25 @@ static int bttv_s_fmt_vid_cap(struct file *file, void *priv, fmt = format_by_fourcc(f->fmt.pix.pixelformat); bttv_get_width_mask_vid_cap(fmt, &width_mask, &width_bias); - retval = limit_scaled_size_lock(fh, &width, &height, f->fmt.pix.field, - width_mask, width_bias, - /* adjust_size */ 1, - /* adjust_crop */ 1); + retval = limit_scaled_size_lock(btv, &width, &height, f->fmt.pix.field, + width_mask, width_bias, 1, 1); if (0 != retval) return retval; f->fmt.pix.field = field; /* update our state information */ - fh->fmt = fmt; - fh->cap.field = f->fmt.pix.field; - fh->cap.last = V4L2_FIELD_NONE; - fh->width = f->fmt.pix.width; - fh->height = f->fmt.pix.height; - btv->init.fmt = fmt; - btv->init.width = f->fmt.pix.width; - btv->init.height = f->fmt.pix.height; + btv->fmt = fmt; + btv->width = f->fmt.pix.width; + btv->height = f->fmt.pix.height; + btv->field = f->fmt.pix.field; + /* + * When field is V4L2_FIELD_ALTERNATE, buffers will be either + * V4L2_FIELD_TOP or V4L2_FIELD_BOTTOM depending on the value of + * field_last. Initialize field_last to V4L2_FIELD_BOTTOM so that + * streaming starts with a V4L2_FIELD_TOP buffer. + */ + btv->field_last = V4L2_FIELD_BOTTOM; return 0; } @@ -2209,8 +2114,7 @@ static int bttv_s_fmt_vid_cap(struct file *file, void *priv, static int bttv_querycap(struct file *file, void *priv, struct v4l2_capability *cap) { - struct bttv_fh *fh = priv; - struct bttv *btv = fh->btv; + struct bttv *btv = video_drvdata(file); if (0 == v4l2) return -EINVAL; @@ -2257,73 +2161,10 @@ static int bttv_enum_fmt_vid_cap(struct file *file, void *priv, return 0; } -static int bttv_reqbufs(struct file *file, void *priv, - struct v4l2_requestbuffers *p) -{ - struct bttv_fh *fh = priv; - return videobuf_reqbufs(bttv_queue(fh), p); -} - -static int bttv_querybuf(struct file *file, void *priv, - struct v4l2_buffer *b) -{ - struct bttv_fh *fh = priv; - return videobuf_querybuf(bttv_queue(fh), b); -} - -static int bttv_qbuf(struct file *file, void *priv, struct v4l2_buffer *b) -{ - struct bttv_fh *fh = priv; - struct bttv *btv = fh->btv; - int res = bttv_resource(fh); - - if (!check_alloc_btres_lock(btv, fh, res)) - return -EBUSY; - - return videobuf_qbuf(bttv_queue(fh), b); -} - -static int bttv_dqbuf(struct file *file, void *priv, struct v4l2_buffer *b) -{ - struct bttv_fh *fh = priv; - return videobuf_dqbuf(bttv_queue(fh), b, - file->f_flags & O_NONBLOCK); -} - -static int bttv_streamon(struct file *file, void *priv, - enum v4l2_buf_type type) -{ - struct bttv_fh *fh = priv; - struct bttv *btv = fh->btv; - int res = bttv_resource(fh); - - if (!check_alloc_btres_lock(btv, fh, res)) - return -EBUSY; - return videobuf_streamon(bttv_queue(fh)); -} - - -static int bttv_streamoff(struct file *file, void *priv, - enum v4l2_buf_type type) -{ - struct bttv_fh *fh = priv; - struct bttv *btv = fh->btv; - int retval; - int res = bttv_resource(fh); - - - retval = videobuf_streamoff(bttv_queue(fh)); - if (retval < 0) - return retval; - free_btres_lock(btv, fh, res); - return 0; -} - static int bttv_g_parm(struct file *file, void *f, struct v4l2_streamparm *parm) { - struct bttv_fh *fh = f; - struct bttv *btv = fh->btv; + struct bttv *btv = video_drvdata(file); if (parm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) return -EINVAL; @@ -2337,8 +2178,7 @@ static int bttv_g_parm(struct file *file, void *f, static int bttv_g_tuner(struct file *file, void *priv, struct v4l2_tuner *t) { - struct bttv_fh *fh = priv; - struct bttv *btv = fh->btv; + struct bttv *btv = video_drvdata(file); if (0 != t->index) return -EINVAL; @@ -2360,8 +2200,7 @@ static int bttv_g_tuner(struct file *file, void *priv, static int bttv_g_pixelaspect(struct file *file, void *priv, int type, struct v4l2_fract *f) { - struct bttv_fh *fh = priv; - struct bttv *btv = fh->btv; + struct bttv *btv = video_drvdata(file); if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE) return -EINVAL; @@ -2373,20 +2212,14 @@ static int bttv_g_pixelaspect(struct file *file, void *priv, static int bttv_g_selection(struct file *file, void *f, struct v4l2_selection *sel) { - struct bttv_fh *fh = f; - struct bttv *btv = fh->btv; + struct bttv *btv = video_drvdata(file); if (sel->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) return -EINVAL; switch (sel->target) { case V4L2_SEL_TGT_CROP: - /* - * No fh->do_crop = 1; because btv->crop[1] may be - * inconsistent with fh->width or fh->height and apps - * do not expect a change here. - */ - sel->r = btv->crop[!!fh->do_crop].rect; + sel->r = btv->crop[!!btv->do_crop].rect; break; case V4L2_SEL_TGT_CROP_DEFAULT: sel->r = bttv_tvnorms[btv->tvnorm].cropcap.defrect; @@ -2403,8 +2236,7 @@ static int bttv_g_selection(struct file *file, void *f, struct v4l2_selection *s static int bttv_s_selection(struct file *file, void *f, struct v4l2_selection *sel) { - struct bttv_fh *fh = f; - struct bttv *btv = fh->btv; + struct bttv *btv = video_drvdata(file); const struct v4l2_rect *b; int retval; struct bttv_crop c; @@ -2424,9 +2256,8 @@ static int bttv_s_selection(struct file *file, void *f, struct v4l2_selection *s read() may change vbi_end in check_alloc_btres_lock(). */ retval = -EBUSY; - if (locked_btres(fh->btv, VIDEO_RESOURCES)) { + if (locked_btres(btv, VIDEO_RESOURCES)) return retval; - } b = &bttv_tvnorms[btv->tvnorm].cropcap.bounds; @@ -2460,249 +2291,30 @@ static int bttv_s_selection(struct file *file, void *f, struct v4l2_selection *s btv->crop[1] = c; - fh->do_crop = 1; + btv->do_crop = 1; - if (fh->width < c.min_scaled_width) { - fh->width = c.min_scaled_width; - btv->init.width = c.min_scaled_width; - } else if (fh->width > c.max_scaled_width) { - fh->width = c.max_scaled_width; - btv->init.width = c.max_scaled_width; - } + if (btv->width < c.min_scaled_width) + btv->width = c.min_scaled_width; + else if (btv->width > c.max_scaled_width) + btv->width = c.max_scaled_width; - if (fh->height < c.min_scaled_height) { - fh->height = c.min_scaled_height; - btv->init.height = c.min_scaled_height; - } else if (fh->height > c.max_scaled_height) { - fh->height = c.max_scaled_height; - btv->init.height = c.max_scaled_height; - } + if (btv->height < c.min_scaled_height) + btv->height = c.min_scaled_height; + else if (btv->height > c.max_scaled_height) + btv->height = c.max_scaled_height; return 0; } -static ssize_t bttv_read(struct file *file, char __user *data, - size_t count, loff_t *ppos) -{ - struct bttv_fh *fh = file->private_data; - int retval = 0; - - if (fh->btv->errors) - bttv_reinit_bt848(fh->btv); - dprintk("%d: read count=%d type=%s\n", - fh->btv->c.nr, (int)count, v4l2_type_names[fh->type]); - - switch (fh->type) { - case V4L2_BUF_TYPE_VIDEO_CAPTURE: - if (!check_alloc_btres_lock(fh->btv, fh, RESOURCE_VIDEO_READ)) { - /* VIDEO_READ in use by another fh, - or VIDEO_STREAM by any fh. */ - return -EBUSY; - } - retval = videobuf_read_one(&fh->cap, data, count, ppos, - file->f_flags & O_NONBLOCK); - free_btres_lock(fh->btv, fh, RESOURCE_VIDEO_READ); - break; - case V4L2_BUF_TYPE_VBI_CAPTURE: - if (!check_alloc_btres_lock(fh->btv,fh,RESOURCE_VBI)) - return -EBUSY; - retval = videobuf_read_stream(&fh->vbi, data, count, ppos, 1, - file->f_flags & O_NONBLOCK); - break; - default: - BUG(); - } - return retval; -} - -static __poll_t bttv_poll(struct file *file, poll_table *wait) -{ - struct bttv_fh *fh = file->private_data; - struct bttv_buffer *buf; - enum v4l2_field field; - __poll_t rc = 0; - __poll_t req_events = poll_requested_events(wait); - - if (v4l2_event_pending(&fh->fh)) - rc = EPOLLPRI; - else if (req_events & EPOLLPRI) - poll_wait(file, &fh->fh.wait, wait); - - if (!(req_events & (EPOLLIN | EPOLLRDNORM))) - return rc; - - if (V4L2_BUF_TYPE_VBI_CAPTURE == fh->type) { - if (!check_alloc_btres_lock(fh->btv,fh,RESOURCE_VBI)) - return rc | EPOLLERR; - return rc | videobuf_poll_stream(file, &fh->vbi, wait); - } - - if (check_btres(fh,RESOURCE_VIDEO_STREAM)) { - /* streaming capture */ - if (list_empty(&fh->cap.stream)) - return rc | EPOLLERR; - buf = list_entry(fh->cap.stream.next,struct bttv_buffer,vb.stream); - } else { - /* read() capture */ - if (NULL == fh->cap.read_buf) { - /* need to capture a new frame */ - if (locked_btres(fh->btv,RESOURCE_VIDEO_STREAM)) - return rc | EPOLLERR; - fh->cap.read_buf = videobuf_sg_alloc(fh->cap.msize); - if (NULL == fh->cap.read_buf) - return rc | EPOLLERR; - fh->cap.read_buf->memory = V4L2_MEMORY_USERPTR; - field = videobuf_next_field(&fh->cap); - if (0 != fh->cap.ops->buf_prepare(&fh->cap,fh->cap.read_buf,field)) { - kfree (fh->cap.read_buf); - fh->cap.read_buf = NULL; - return rc | EPOLLERR; - } - fh->cap.ops->buf_queue(&fh->cap,fh->cap.read_buf); - fh->cap.read_off = 0; - } - buf = (struct bttv_buffer*)fh->cap.read_buf; - } - - poll_wait(file, &buf->vb.done, wait); - if (buf->vb.state == VIDEOBUF_DONE || - buf->vb.state == VIDEOBUF_ERROR) - rc = rc | EPOLLIN|EPOLLRDNORM; - return rc; -} - -static int bttv_open(struct file *file) -{ - struct video_device *vdev = video_devdata(file); - struct bttv *btv = video_drvdata(file); - struct bttv_fh *fh; - enum v4l2_buf_type type = 0; - - dprintk("open dev=%s\n", video_device_node_name(vdev)); - - if (vdev->vfl_type == VFL_TYPE_VIDEO) { - type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - } else if (vdev->vfl_type == VFL_TYPE_VBI) { - type = V4L2_BUF_TYPE_VBI_CAPTURE; - } else { - WARN_ON(1); - return -ENODEV; - } - - dprintk("%d: open called (type=%s)\n", - btv->c.nr, v4l2_type_names[type]); - - /* allocate per filehandle data */ - fh = kmalloc(sizeof(*fh), GFP_KERNEL); - if (unlikely(!fh)) - return -ENOMEM; - btv->users++; - file->private_data = fh; - - *fh = btv->init; - v4l2_fh_init(&fh->fh, vdev); - - fh->type = type; - - videobuf_queue_sg_init(&fh->cap, &bttv_video_qops, - &btv->c.pci->dev, &btv->s_lock, - V4L2_BUF_TYPE_VIDEO_CAPTURE, - V4L2_FIELD_INTERLACED, - sizeof(struct bttv_buffer), - fh, &btv->lock); - videobuf_queue_sg_init(&fh->vbi, &bttv_vbi_qops, - &btv->c.pci->dev, &btv->s_lock, - V4L2_BUF_TYPE_VBI_CAPTURE, - V4L2_FIELD_SEQ_TB, - sizeof(struct bttv_buffer), - fh, &btv->lock); - set_tvnorm(btv,btv->tvnorm); - set_input(btv, btv->input, btv->tvnorm); - audio_mute(btv, btv->mute); - - /* The V4L2 spec requires one global set of cropping parameters - which only change on request. These are stored in btv->crop[1]. - However for compatibility with V4L apps and cropping unaware - V4L2 apps we now reset the cropping parameters as seen through - this fh, which is to say VIDIOC_G_SELECTION and scaling limit checks - will use btv->crop[0], the default cropping parameters for the - current video standard, and VIDIOC_S_FMT will not implicitly - change the cropping parameters until VIDIOC_S_SELECTION has been - called. */ - fh->do_crop = !reset_crop; /* module parameter */ - - /* Likewise there should be one global set of VBI capture - parameters, but for compatibility with V4L apps and earlier - driver versions each fh has its own parameters. */ - bttv_vbi_fmt_reset(&fh->vbi_fmt, btv->tvnorm); - - bttv_field_count(btv); - v4l2_fh_add(&fh->fh); - return 0; -} - -static int bttv_release(struct file *file) -{ - struct bttv_fh *fh = file->private_data; - struct bttv *btv = fh->btv; - - /* stop video capture */ - if (check_btres(fh, RESOURCE_VIDEO_STREAM)) { - videobuf_streamoff(&fh->cap); - free_btres_lock(btv,fh,RESOURCE_VIDEO_STREAM); - } - if (fh->cap.read_buf) { - buffer_release(&fh->cap,fh->cap.read_buf); - kfree(fh->cap.read_buf); - } - if (check_btres(fh, RESOURCE_VIDEO_READ)) { - free_btres_lock(btv, fh, RESOURCE_VIDEO_READ); - } - - /* stop vbi capture */ - if (check_btres(fh, RESOURCE_VBI)) { - videobuf_stop(&fh->vbi); - free_btres_lock(btv,fh,RESOURCE_VBI); - } - - /* free stuff */ - - videobuf_mmap_free(&fh->cap); - videobuf_mmap_free(&fh->vbi); - file->private_data = NULL; - - btv->users--; - bttv_field_count(btv); - - if (!btv->users) - audio_mute(btv, btv->mute); - - v4l2_fh_del(&fh->fh); - v4l2_fh_exit(&fh->fh); - kfree(fh); - return 0; -} - -static int -bttv_mmap(struct file *file, struct vm_area_struct *vma) -{ - struct bttv_fh *fh = file->private_data; - - dprintk("%d: mmap type=%s 0x%lx+%ld\n", - fh->btv->c.nr, v4l2_type_names[fh->type], - vma->vm_start, vma->vm_end - vma->vm_start); - return videobuf_mmap_mapper(bttv_queue(fh),vma); -} - static const struct v4l2_file_operations bttv_fops = { .owner = THIS_MODULE, - .open = bttv_open, - .release = bttv_release, + .open = v4l2_fh_open, + .release = vb2_fop_release, .unlocked_ioctl = video_ioctl2, - .read = bttv_read, - .mmap = bttv_mmap, - .poll = bttv_poll, + .read = vb2_fop_read, + .mmap = vb2_fop_mmap, + .poll = vb2_fop_poll, }; static const struct v4l2_ioctl_ops bttv_ioctl_ops = { @@ -2715,17 +2327,18 @@ static const struct v4l2_ioctl_ops bttv_ioctl_ops = { .vidioc_try_fmt_vbi_cap = bttv_try_fmt_vbi_cap, .vidioc_s_fmt_vbi_cap = bttv_s_fmt_vbi_cap, .vidioc_g_pixelaspect = bttv_g_pixelaspect, - .vidioc_reqbufs = bttv_reqbufs, - .vidioc_querybuf = bttv_querybuf, - .vidioc_qbuf = bttv_qbuf, - .vidioc_dqbuf = bttv_dqbuf, + .vidioc_reqbufs = vb2_ioctl_reqbufs, + .vidioc_create_bufs = vb2_ioctl_create_bufs, + .vidioc_querybuf = vb2_ioctl_querybuf, + .vidioc_qbuf = vb2_ioctl_qbuf, + .vidioc_dqbuf = vb2_ioctl_dqbuf, + .vidioc_streamon = vb2_ioctl_streamon, + .vidioc_streamoff = vb2_ioctl_streamoff, .vidioc_s_std = bttv_s_std, .vidioc_g_std = bttv_g_std, .vidioc_enum_input = bttv_enum_input, .vidioc_g_input = bttv_g_input, .vidioc_s_input = bttv_s_input, - .vidioc_streamon = bttv_streamon, - .vidioc_streamoff = bttv_streamoff, .vidioc_g_tuner = bttv_g_tuner, .vidioc_s_tuner = bttv_s_tuner, .vidioc_g_selection = bttv_g_selection, @@ -2756,52 +2369,40 @@ static int radio_open(struct file *file) { struct video_device *vdev = video_devdata(file); struct bttv *btv = video_drvdata(file); - struct bttv_fh *fh; + int ret = v4l2_fh_open(file); + + if (ret) + return ret; dprintk("open dev=%s\n", video_device_node_name(vdev)); - dprintk("%d: open called (radio)\n", btv->c.nr); - /* allocate per filehandle data */ - fh = kmalloc(sizeof(*fh), GFP_KERNEL); - if (unlikely(!fh)) - return -ENOMEM; - file->private_data = fh; - *fh = btv->init; - v4l2_fh_init(&fh->fh, vdev); - btv->radio_user++; audio_mute(btv, btv->mute); - v4l2_fh_add(&fh->fh); - return 0; } static int radio_release(struct file *file) { - struct bttv_fh *fh = file->private_data; - struct bttv *btv = fh->btv; + struct bttv *btv = video_drvdata(file); struct saa6588_command cmd; - file->private_data = NULL; - v4l2_fh_del(&fh->fh); - v4l2_fh_exit(&fh->fh); - kfree(fh); - btv->radio_user--; bttv_call_all(btv, core, command, SAA6588_CMD_CLOSE, &cmd); if (btv->radio_user == 0) btv->has_radio_tuner = 0; + + v4l2_fh_release(file); + return 0; } static int radio_g_tuner(struct file *file, void *priv, struct v4l2_tuner *t) { - struct bttv_fh *fh = priv; - struct bttv *btv = fh->btv; + struct bttv *btv = video_drvdata(file); if (0 != t->index) return -EINVAL; @@ -2823,8 +2424,7 @@ static int radio_g_tuner(struct file *file, void *priv, struct v4l2_tuner *t) static int radio_s_tuner(struct file *file, void *priv, const struct v4l2_tuner *t) { - struct bttv_fh *fh = priv; - struct bttv *btv = fh->btv; + struct bttv *btv = video_drvdata(file); if (0 != t->index) return -EINVAL; @@ -2837,8 +2437,7 @@ static int radio_s_tuner(struct file *file, void *priv, static int radio_s_hw_freq_seek(struct file *file, void *priv, const struct v4l2_hw_freq_seek *a) { - struct bttv_fh *fh = priv; - struct bttv *btv = fh->btv; + struct bttv *btv = video_drvdata(file); if (btv->has_tea575x) return snd_tea575x_s_hw_freq_seek(file, &btv->tea, a); @@ -2849,8 +2448,7 @@ static int radio_s_hw_freq_seek(struct file *file, void *priv, static int radio_enum_freq_bands(struct file *file, void *priv, struct v4l2_frequency_band *band) { - struct bttv_fh *fh = priv; - struct bttv *btv = fh->btv; + struct bttv *btv = video_drvdata(file); if (btv->has_tea575x) return snd_tea575x_enum_freq_bands(&btv->tea, band); @@ -2861,8 +2459,7 @@ static int radio_enum_freq_bands(struct file *file, void *priv, static ssize_t radio_read(struct file *file, char __user *data, size_t count, loff_t *ppos) { - struct bttv_fh *fh = file->private_data; - struct bttv *btv = fh->btv; + struct bttv *btv = video_drvdata(file); struct saa6588_command cmd; cmd.block_count = count / 3; @@ -2879,23 +2476,17 @@ static ssize_t radio_read(struct file *file, char __user *data, static __poll_t radio_poll(struct file *file, poll_table *wait) { - struct bttv_fh *fh = file->private_data; - struct bttv *btv = fh->btv; - __poll_t req_events = poll_requested_events(wait); + struct bttv *btv = video_drvdata(file); struct saa6588_command cmd; - __poll_t res = 0; + __poll_t rc = v4l2_ctrl_poll(file, wait); - if (v4l2_event_pending(&fh->fh)) - res = EPOLLPRI; - else if (req_events & EPOLLPRI) - poll_wait(file, &fh->fh.wait, wait); radio_enable(btv); cmd.instance = file; cmd.event_list = wait; - cmd.poll_mask = res; + cmd.poll_mask = 0; bttv_call_all(btv, core, command, SAA6588_CMD_POLL, &cmd); - return cmd.poll_mask; + return rc | cmd.poll_mask; } static const struct v4l2_file_operations radio_fops = @@ -3070,17 +2661,19 @@ bttv_irq_next_video(struct bttv *btv, struct bttv_buffer_set *set) /* capture request ? */ if (!list_empty(&btv->capture)) { - set->frame_irq = 1; - item = list_entry(btv->capture.next, struct bttv_buffer, vb.queue); - if (V4L2_FIELD_HAS_TOP(item->vb.field)) + set->frame_irq = BT848_RISC_VIDEO; + item = list_entry(btv->capture.next, struct bttv_buffer, list); + + if (V4L2_FIELD_HAS_TOP(item->vbuf.field)) set->top = item; - if (V4L2_FIELD_HAS_BOTTOM(item->vb.field)) + if (V4L2_FIELD_HAS_BOTTOM(item->vbuf.field)) set->bottom = item; /* capture request for other field ? */ - if (!V4L2_FIELD_HAS_BOTH(item->vb.field) && - (item->vb.queue.next != &btv->capture)) { - item = list_entry(item->vb.queue.next, struct bttv_buffer, vb.queue); + if (!V4L2_FIELD_HAS_BOTH(item->vbuf.field) && + item->list.next != &btv->capture) { + item = list_entry(item->list.next, + struct bttv_buffer, list); /* Mike Isely - Only check * and set up the bottom field in the logic * below. Don't ever do the top field. This @@ -3108,13 +2701,18 @@ bttv_irq_next_video(struct bttv *btv, struct bttv_buffer_set *set) * sync within a single frame time. (Out of * order fields can screw up deinterlacing * algorithms.) */ - if (!V4L2_FIELD_HAS_BOTH(item->vb.field)) { - if (NULL == set->bottom && - V4L2_FIELD_BOTTOM == item->vb.field) { + if (!V4L2_FIELD_HAS_BOTH(item->vbuf.field)) { + if (!set->bottom && + item->vbuf.field == V4L2_FIELD_BOTTOM) set->bottom = item; + if (set->top && set->bottom) { + /* + * The buffer set has a top buffer and + * a bottom buffer and they are not + * copies of each other. + */ + set->top_irq = BT848_RISC_TOP; } - if (NULL != set->top && NULL != set->bottom) - set->top_irq = 2; } } } @@ -3136,44 +2734,68 @@ bttv_irq_wakeup_video(struct bttv *btv, struct bttv_buffer_set *wakeup, if (irq_debug > 1) pr_debug("%d: wakeup: both=%p\n", btv->c.nr, wakeup->top); - wakeup->top->vb.ts = ts; - wakeup->top->vb.field_count = btv->field_count; - wakeup->top->vb.state = state; - wake_up(&wakeup->top->vb.done); + wakeup->top->vbuf.vb2_buf.timestamp = ts; + wakeup->top->vbuf.sequence = btv->field_count >> 1; + vb2_buffer_done(&wakeup->top->vbuf.vb2_buf, state); + if (btv->field_count == 0) + btor(BT848_INT_VSYNC, BT848_INT_MASK); } } else { if (NULL != wakeup->top && curr->top != wakeup->top) { if (irq_debug > 1) pr_debug("%d: wakeup: top=%p\n", btv->c.nr, wakeup->top); - wakeup->top->vb.ts = ts; - wakeup->top->vb.field_count = btv->field_count; - wakeup->top->vb.state = state; - wake_up(&wakeup->top->vb.done); + wakeup->top->vbuf.vb2_buf.timestamp = ts; + wakeup->top->vbuf.sequence = btv->field_count >> 1; + vb2_buffer_done(&wakeup->top->vbuf.vb2_buf, state); + if (btv->field_count == 0) + btor(BT848_INT_VSYNC, BT848_INT_MASK); } if (NULL != wakeup->bottom && curr->bottom != wakeup->bottom) { if (irq_debug > 1) pr_debug("%d: wakeup: bottom=%p\n", btv->c.nr, wakeup->bottom); - wakeup->bottom->vb.ts = ts; - wakeup->bottom->vb.field_count = btv->field_count; - wakeup->bottom->vb.state = state; - wake_up(&wakeup->bottom->vb.done); + wakeup->bottom->vbuf.vb2_buf.timestamp = ts; + wakeup->bottom->vbuf.sequence = btv->field_count >> 1; + vb2_buffer_done(&wakeup->bottom->vbuf.vb2_buf, state); + if (btv->field_count == 0) + btor(BT848_INT_VSYNC, BT848_INT_MASK); } } } static void bttv_irq_wakeup_vbi(struct bttv *btv, struct bttv_buffer *wakeup, - unsigned int state) + unsigned int state) { if (NULL == wakeup) return; + wakeup->vbuf.vb2_buf.timestamp = ktime_get_ns(); + wakeup->vbuf.sequence = btv->field_count >> 1; - wakeup->vb.ts = ktime_get_ns(); - wakeup->vb.field_count = btv->field_count; - wakeup->vb.state = state; - wake_up(&wakeup->vb.done); + /* + * Ugly hack for backwards compatibility. + * Some applications expect that the last 4 bytes of + * the VBI data contains the sequence number. + * + * This makes it possible to associate the VBI data + * with the video frame if you use read() to get the + * VBI data. + */ + if (vb2_fileio_is_active(wakeup->vbuf.vb2_buf.vb2_queue)) { + u32 *vaddr = vb2_plane_vaddr(&wakeup->vbuf.vb2_buf, 0); + unsigned long size = + vb2_get_plane_payload(&wakeup->vbuf.vb2_buf, 0) / 4; + + if (vaddr && size) { + vaddr += size - 1; + *vaddr = wakeup->vbuf.sequence; + } + } + + vb2_buffer_done(&wakeup->vbuf.vb2_buf, state); + if (btv->field_count == 0) + btor(BT848_INT_VSYNC, BT848_INT_MASK); } static void bttv_irq_timeout(struct timer_list *t) @@ -3183,6 +2805,7 @@ static void bttv_irq_timeout(struct timer_list *t) struct bttv_buffer *ovbi; struct bttv_buffer *item; unsigned long flags; + int seqnr = 0; if (bttv_verbose) { pr_info("%d: timeout: drop=%d irq=%d/%d, risc=%08x, ", @@ -3206,21 +2829,25 @@ static void bttv_irq_timeout(struct timer_list *t) bttv_set_dma(btv, 0); /* wake up */ - bttv_irq_wakeup_video(btv, &old, &new, VIDEOBUF_ERROR); - bttv_irq_wakeup_vbi(btv, ovbi, VIDEOBUF_ERROR); + bttv_irq_wakeup_video(btv, &old, &new, VB2_BUF_STATE_DONE); + bttv_irq_wakeup_vbi(btv, ovbi, VB2_BUF_STATE_DONE); /* cancel all outstanding capture / vbi requests */ + if (btv->field_count) + seqnr++; while (!list_empty(&btv->capture)) { - item = list_entry(btv->capture.next, struct bttv_buffer, vb.queue); - list_del(&item->vb.queue); - item->vb.state = VIDEOBUF_ERROR; - wake_up(&item->vb.done); + item = list_entry(btv->capture.next, struct bttv_buffer, list); + list_del(&item->list); + item->vbuf.vb2_buf.timestamp = ktime_get_ns(); + item->vbuf.sequence = (btv->field_count >> 1) + seqnr++; + vb2_buffer_done(&item->vbuf.vb2_buf, VB2_BUF_STATE_ERROR); } while (!list_empty(&btv->vcapture)) { - item = list_entry(btv->vcapture.next, struct bttv_buffer, vb.queue); - list_del(&item->vb.queue); - item->vb.state = VIDEOBUF_ERROR; - wake_up(&item->vb.done); + item = list_entry(btv->vcapture.next, struct bttv_buffer, list); + list_del(&item->list); + item->vbuf.vb2_buf.timestamp = ktime_get_ns(); + item->vbuf.sequence = (btv->field_count >> 1) + seqnr++; + vb2_buffer_done(&item->vbuf.vb2_buf, VB2_BUF_STATE_ERROR); } btv->errors++; @@ -3239,11 +2866,11 @@ bttv_irq_wakeup_top(struct bttv *btv) btv->curr.top_irq = 0; btv->curr.top = NULL; bttv_risc_hook(btv, RISC_SLOT_O_FIELD, NULL, 0); - - wakeup->vb.ts = ktime_get_ns(); - wakeup->vb.field_count = btv->field_count; - wakeup->vb.state = VIDEOBUF_DONE; - wake_up(&wakeup->vb.done); + wakeup->vbuf.vb2_buf.timestamp = ktime_get_ns(); + wakeup->vbuf.sequence = btv->field_count >> 1; + vb2_buffer_done(&wakeup->vbuf.vb2_buf, VB2_BUF_STATE_DONE); + if (btv->field_count == 0) + btor(BT848_INT_VSYNC, BT848_INT_MASK); spin_unlock(&btv->s_lock); } @@ -3280,7 +2907,7 @@ bttv_irq_switch_video(struct bttv *btv) /* switch over */ old = btv->curr; btv->curr = new; - btv->loop_irq &= ~1; + btv->loop_irq &= ~BT848_RISC_VIDEO; bttv_buffer_activate_video(btv, &new); bttv_set_dma(btv, 0); @@ -3291,7 +2918,7 @@ bttv_irq_switch_video(struct bttv *btv) } /* wake up finished buffers */ - bttv_irq_wakeup_video(btv, &old, &new, VIDEOBUF_DONE); + bttv_irq_wakeup_video(btv, &old, &new, VB2_BUF_STATE_DONE); spin_unlock(&btv->s_lock); } @@ -3305,7 +2932,7 @@ bttv_irq_switch_vbi(struct bttv *btv) spin_lock(&btv->s_lock); if (!list_empty(&btv->vcapture)) - new = list_entry(btv->vcapture.next, struct bttv_buffer, vb.queue); + new = list_entry(btv->vcapture.next, struct bttv_buffer, list); old = btv->cvbi; rc = btread(BT848_RISC_COUNT); @@ -3320,11 +2947,11 @@ bttv_irq_switch_vbi(struct bttv *btv) /* switch */ btv->cvbi = new; - btv->loop_irq &= ~4; + btv->loop_irq &= ~BT848_RISC_VBI; bttv_buffer_activate_vbi(btv, new); bttv_set_dma(btv, 0); - bttv_irq_wakeup_vbi(btv, old, VIDEOBUF_DONE); + bttv_irq_wakeup_vbi(btv, old, VB2_BUF_STATE_DONE); spin_unlock(&btv->s_lock); } @@ -3383,13 +3010,13 @@ static irqreturn_t bttv_irq(int irq, void *dev_id) wake_up(&btv->i2c_queue); } - if ((astat & BT848_INT_RISCI) && (stat & (4<<28))) + if ((astat & BT848_INT_RISCI) && (stat & BT848_INT_RISCS_VBI)) bttv_irq_switch_vbi(btv); - if ((astat & BT848_INT_RISCI) && (stat & (2<<28))) + if ((astat & BT848_INT_RISCI) && (stat & BT848_INT_RISCS_TOP)) bttv_irq_wakeup_top(btv); - if ((astat & BT848_INT_RISCI) && (stat & (1<<28))) + if ((astat & BT848_INT_RISCI) && (stat & BT848_INT_RISCS_VIDEO)) bttv_irq_switch_video(btv); if ((astat & BT848_INT_HLOCK) && btv->opt_automute) @@ -3445,11 +3072,12 @@ static irqreturn_t bttv_irq(int irq, void *dev_id) /* ----------------------------------------------------------------------- */ /* initialization */ -static void vdev_init(struct bttv *btv, - struct video_device *vfd, - const struct video_device *template, - const char *type_name) +static int vdev_init(struct bttv *btv, struct video_device *vfd, + const struct video_device *template, + const char *type_name) { + int err; + struct vb2_queue *q; *vfd = *template; vfd->v4l2_dev = &btv->c.v4l2_dev; vfd->release = video_device_release_empty; @@ -3463,6 +3091,36 @@ static void vdev_init(struct bttv *btv, v4l2_disable_ioctl(vfd, VIDIOC_G_TUNER); v4l2_disable_ioctl(vfd, VIDIOC_S_TUNER); } + + if (strcmp(type_name, "radio") == 0) + return 0; + + if (strcmp(type_name, "video") == 0) { + q = &btv->capq; + q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + q->ops = &bttv_video_qops; + } else if (strcmp(type_name, "vbi") == 0) { + q = &btv->vbiq; + q->type = V4L2_BUF_TYPE_VBI_CAPTURE; + q->ops = &bttv_vbi_qops; + } else { + return -EINVAL; + } + q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC; + q->io_modes = VB2_MMAP | VB2_USERPTR | VB2_READ | VB2_DMABUF; + q->mem_ops = &vb2_dma_sg_memops; + q->drv_priv = btv; + q->gfp_flags = __GFP_DMA32; + q->buf_struct_size = sizeof(struct bttv_buffer); + q->lock = &btv->lock; + q->min_buffers_needed = 2; + q->dev = &btv->c.pci->dev; + err = vb2_queue_init(q); + if (err) + return err; + vfd->queue = q; + + return 0; } static void bttv_unregister_video(struct bttv *btv) @@ -3670,11 +3328,16 @@ static int bttv_probe(struct pci_dev *dev, const struct pci_device_id *pci_id) bttv_ctrl_coring.def = coring; /* fill struct bttv with some useful defaults */ - btv->init.btv = btv; - btv->init.fmt = format_by_fourcc(V4L2_PIX_FMT_BGR24); - btv->init.width = 320; - btv->init.height = 240; + btv->fmt = format_by_fourcc(V4L2_PIX_FMT_BGR24); + btv->width = 320; + btv->height = 240; + btv->field = V4L2_FIELD_INTERLACED; btv->input = 0; + btv->tvnorm = 0; /* Index into bttv_tvnorms[] i.e. PAL. */ + bttv_vbi_fmt_reset(&btv->vbi_fmt, btv->tvnorm); + btv->vbi_count[0] = VBI_DEFLINES; + btv->vbi_count[1] = VBI_DEFLINES; + btv->do_crop = 0; v4l2_ctrl_new_std(hdl, &bttv_ctrl_ops, V4L2_CID_BRIGHTNESS, 0, 0xff00, 0x100, 32768); @@ -3749,7 +3412,7 @@ static int bttv_probe(struct pci_dev *dev, const struct pci_device_id *pci_id) result = btv->radio_ctrl_handler.error; goto fail2; } - set_input(btv, 0, btv->tvnorm); + set_input(btv, btv->input, btv->tvnorm); bttv_crop_reset(&btv->crop[0], btv->tvnorm); btv->crop[1] = btv->crop[0]; /* current = default */ disclaim_vbi_lines(btv); @@ -3830,6 +3493,7 @@ static void bttv_remove(struct pci_dev *pci_dev) /* free resources */ free_irq(btv->c.pci->irq,btv); + del_timer_sync(&btv->timeout); iounmap(btv->bt848_mmio); release_mem_region(pci_resource_start(btv->c.pci,0), pci_resource_len(btv->c.pci,0)); diff --git a/drivers/media/pci/bt8xx/bttv-gpio.c b/drivers/media/pci/bt8xx/bttv-gpio.c index a2b18e2bed1b..6b7fea50328c 100644 --- a/drivers/media/pci/bt8xx/bttv-gpio.c +++ b/drivers/media/pci/bt8xx/bttv-gpio.c @@ -55,7 +55,7 @@ static void bttv_sub_remove(struct device *dev) sub->remove(sdev); } -struct bus_type bttv_sub_bus_type = { +const struct bus_type bttv_sub_bus_type = { .name = "bttv-sub", .match = &bttv_sub_bus_match, .probe = bttv_sub_probe, diff --git a/drivers/media/pci/bt8xx/bttv-risc.c b/drivers/media/pci/bt8xx/bttv-risc.c index 4fa4b9da9634..241a696e374a 100644 --- a/drivers/media/pci/bt8xx/bttv-risc.c +++ b/drivers/media/pci/bt8xx/bttv-risc.c @@ -67,8 +67,8 @@ 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) continue; while (offset && offset >= sg_dma_len(sg)) { offset -= sg_dma_len(sg); @@ -106,7 +106,7 @@ bttv_risc_packed(struct bttv *btv, struct btcx_riscmem *risc, /* save pointer to jmp instruction address */ risc->jmp = rp; - BUG_ON((risc->jmp - risc->cpu + 2) * sizeof(*risc->cpu) > risc->size); + WARN_ON((risc->jmp - risc->cpu + 2) * sizeof(*risc->cpu) > risc->size); return 0; } @@ -227,7 +227,7 @@ bttv_risc_planar(struct bttv *btv, struct btcx_riscmem *risc, /* save pointer to jmp instruction address */ risc->jmp = rp; - BUG_ON((risc->jmp - risc->cpu + 2) * sizeof(*risc->cpu) > risc->size); + WARN_ON((risc->jmp - risc->cpu + 2) * sizeof(*risc->cpu) > risc->size); return 0; } @@ -360,21 +360,75 @@ bttv_apply_geo(struct bttv *btv, struct bttv_geometry *geo, int odd) /* ---------------------------------------------------------- */ /* risc group / risc main loop / dma management */ -void -bttv_set_dma(struct bttv *btv, int override) +static void bttv_set_risc_status(struct bttv *btv) { - unsigned long cmd; - int capctl; + unsigned long cmd = BT848_RISC_JUMP; + if (btv->loop_irq) { + cmd |= BT848_RISC_IRQ; + cmd |= (btv->loop_irq & 0x0f) << 16; + cmd |= (~btv->loop_irq & 0x0f) << 20; + } + btv->main.cpu[RISC_SLOT_LOOP] = cpu_to_le32(cmd); +} - btv->cap_ctl = 0; - if (NULL != btv->curr.top) btv->cap_ctl |= 0x02; - if (NULL != btv->curr.bottom) btv->cap_ctl |= 0x01; - if (NULL != btv->cvbi) btv->cap_ctl |= 0x0c; +static void bttv_set_irq_timer(struct bttv *btv) +{ + if (btv->curr.frame_irq || btv->loop_irq || btv->cvbi) + mod_timer(&btv->timeout, jiffies + BTTV_TIMEOUT); + else + del_timer(&btv->timeout); +} - capctl = 0; - capctl |= (btv->cap_ctl & 0x03) ? 0x03 : 0x00; /* capture */ - capctl |= (btv->cap_ctl & 0x0c) ? 0x0c : 0x00; /* vbi data */ - capctl |= override; +static int bttv_set_capture_control(struct bttv *btv, int start_capture) +{ + int capctl = 0; + + if (btv->curr.top || btv->curr.bottom) + capctl = BT848_CAP_CTL_CAPTURE_ODD | + BT848_CAP_CTL_CAPTURE_EVEN; + + if (btv->cvbi) + capctl |= BT848_CAP_CTL_CAPTURE_VBI_ODD | + BT848_CAP_CTL_CAPTURE_VBI_EVEN; + + capctl |= start_capture; + + btaor(capctl, ~0x0f, BT848_CAP_CTL); + + return capctl; +} + +static void bttv_start_dma(struct bttv *btv) +{ + if (btv->dma_on) + return; + btwrite(btv->main.dma, BT848_RISC_STRT_ADD); + btor(BT848_GPIO_DMA_CTL_RISC_ENABLE | BT848_GPIO_DMA_CTL_FIFO_ENABLE, + BT848_GPIO_DMA_CTL); + btv->dma_on = 1; +} + +static void bttv_stop_dma(struct bttv *btv) +{ + if (!btv->dma_on) + return; + btand(~(BT848_GPIO_DMA_CTL_RISC_ENABLE | + BT848_GPIO_DMA_CTL_FIFO_ENABLE), BT848_GPIO_DMA_CTL); + btv->dma_on = 0; +} + +void bttv_set_dma(struct bttv *btv, int start_capture) +{ + int capctl = 0; + + bttv_set_risc_status(btv); + bttv_set_irq_timer(btv); + capctl = bttv_set_capture_control(btv, start_capture); + + if (capctl) + bttv_start_dma(btv); + else + bttv_stop_dma(btv); d2printk("%d: capctl=%x lirq=%d top=%08llx/%08llx even=%08llx/%08llx\n", btv->c.nr,capctl,btv->loop_irq, @@ -382,34 +436,6 @@ bttv_set_dma(struct bttv *btv, int override) btv->curr.top ? (unsigned long long)btv->curr.top->top.dma : 0, btv->cvbi ? (unsigned long long)btv->cvbi->bottom.dma : 0, btv->curr.bottom ? (unsigned long long)btv->curr.bottom->bottom.dma : 0); - - cmd = BT848_RISC_JUMP; - if (btv->loop_irq) { - cmd |= BT848_RISC_IRQ; - cmd |= (btv->loop_irq & 0x0f) << 16; - cmd |= (~btv->loop_irq & 0x0f) << 20; - } - if (btv->curr.frame_irq || btv->loop_irq || btv->cvbi) { - mod_timer(&btv->timeout, jiffies+BTTV_TIMEOUT); - } else { - del_timer(&btv->timeout); - } - btv->main.cpu[RISC_SLOT_LOOP] = cpu_to_le32(cmd); - - btaor(capctl, ~0x0f, BT848_CAP_CTL); - if (capctl) { - if (btv->dma_on) - return; - btwrite(btv->main.dma, BT848_RISC_STRT_ADD); - btor(3, BT848_GPIO_DMA_CTL); - btv->dma_on = 1; - } else { - if (!btv->dma_on) - return; - btand(~3, BT848_GPIO_DMA_CTL); - btv->dma_on = 0; - } - return; } int @@ -478,17 +504,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 @@ -508,8 +567,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); @@ -525,12 +583,12 @@ bttv_buffer_activate_vbi(struct bttv *btv, btwrite(crop, BT848_O_CROP); } - if (vbi->vbi_count[0] > 0) { + if (btv->vbi_count[0] > 0) { top = &vbi->top; top_irq_flags = 4; } - if (vbi->vbi_count[1] > 0) { + if (btv->vbi_count[1] > 0) { top_irq_flags = 0; bottom = &vbi->bottom; bottom_irq_flags = 4; @@ -550,16 +608,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); @@ -572,9 +627,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, @@ -583,9 +637,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); @@ -606,156 +659,146 @@ bttv_buffer_activate_video(struct bttv *btv, int bttv_buffer_risc(struct bttv *btv, struct bttv_buffer *buf) { - const struct bttv_tvnorm *tvnorm = bttv_tvnorms + buf->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], - buf->fmt->fourcc, buf->vb.width, buf->vb.height); + int r = 0; + const struct bttv_tvnorm *tvnorm = bttv_tvnorms + btv->tvnorm; + 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 (buf->fmt->flags & FORMAT_FLAGS_PACKED) { - int bpl = (buf->fmt->depth >> 3) * buf->vb.width; - int bpf = bpl * (buf->vb.height >> 1); + if (btv->fmt->flags & FORMAT_FLAGS_PACKED) { + 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,&buf->crop); - - 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: - BUG(); + WARN_ON(1); + return -EINVAL; } } - /* planar modes */ - if (buf->fmt->flags & FORMAT_FLAGS_PLANAR) { + 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; - if (buf->fmt->flags & FORMAT_FLAGS_CrCb) { + uoffset = btv->width * btv->height; + voffset = btv->width * btv->height; + if (btv->fmt->flags & FORMAT_FLAGS_CrCb) { /* Y-Cr-Cb plane order */ - uoffset >>= buf->fmt->hshift; - uoffset >>= buf->fmt->vshift; + uoffset >>= btv->fmt->hshift; + uoffset >>= btv->fmt->vshift; uoffset += voffset; } else { /* Y-Cb-Cr plane order */ - voffset >>= buf->fmt->hshift; - voffset >>= buf->fmt->vshift; + voffset >>= btv->fmt->hshift; + 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,&buf->crop); - bttv_risc_planar(btv, &buf->top, dma->sglist, - 0,buf->vb.width,0,buf->vb.height, - uoffset,voffset,buf->fmt->hshift, - buf->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,&buf->crop); - bttv_risc_planar(btv, &buf->bottom, dma->sglist, - 0,buf->vb.width,0,buf->vb.height, - uoffset,voffset,buf->fmt->hshift, - buf->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,&buf->crop); - lines = buf->vb.height >> 1; - ypadding = buf->vb.width; - cpadding = buf->vb.width >> buf->fmt->hshift; - bttv_risc_planar(btv,&buf->top, - dma->sglist, - 0,buf->vb.width,ypadding,lines, - uoffset,voffset, - buf->fmt->hshift, - buf->fmt->vshift, - cpadding); - bttv_risc_planar(btv,&buf->bottom, - dma->sglist, - ypadding,buf->vb.width,ypadding,lines, - uoffset+cpadding, - voffset+cpadding, - buf->fmt->hshift, - buf->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,&buf->crop); - lines = buf->vb.height >> 1; - ypadding = buf->vb.width; - cpadding = buf->vb.width >> buf->fmt->hshift; - bttv_risc_planar(btv,&buf->top, - dma->sglist, - 0,buf->vb.width,0,lines, - uoffset >> 1, - voffset >> 1, - buf->fmt->hshift, - buf->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), - buf->fmt->hshift, - buf->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: - BUG(); + WARN_ON(1); + return -EINVAL; } } - /* raw data */ - if (buf->fmt->flags & FORMAT_FLAGS_RAW) { + 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, - 1,tvnorm,&buf->crop); - 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); + 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); + 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 = buf->fmt->btformat; - buf->btswap = buf->fmt->btswap; - return 0; + buf->btformat = btv->fmt->btformat; + buf->btswap = btv->fmt->btswap; + + return r; } diff --git a/drivers/media/pci/bt8xx/bttv-vbi.c b/drivers/media/pci/bt8xx/bttv-vbi.c index ce36a2c0f60b..e489a3acb4b9 100644 --- a/drivers/media/pci/bt8xx/bttv-vbi.c +++ b/drivers/media/pci/bt8xx/bttv-vbi.c @@ -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,121 @@ 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; + return ret; +} - /* 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. */ +static void buf_cleanup_vbi(struct vb2_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); - skip_lines0 = 0; - skip_lines1 = 0; + btcx_riscmem_free(btv->c.pci, &buf->top); + btcx_riscmem_free(btv->c.pci, &buf->bottom); +} - 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])); +static int start_streaming_vbi(struct vb2_queue *q, unsigned int count) +{ + int seqnr = 0; + struct bttv_buffer *buf; + struct bttv *btv = vb2_get_drv_priv(q); - redo_dma_risc = 0; - - if (buf->vbi_skip[0] != skip_lines0 || - buf->vbi_skip[1] != skip_lines1 || - buf->vbi_count[0] != fh->vbi_fmt.fmt.count[0] || - buf->vbi_count[1] != fh->vbi_fmt.fmt.count[1]) { - buf->vbi_skip[0] = skip_lines0; - buf->vbi_skip[1] = skip_lines1; - buf->vbi_count[0] = fh->vbi_fmt.fmt.count[0]; - buf->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; + btv->framedrop = 0; + if (!check_alloc_btres_lock(btv, RESOURCE_VBI)) { + 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 -EBUSY; + } + if (!vb2_is_streaming(&btv->capq)) { + init_irqreg(btv); + btv->field_count = 0; } - - /* 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; } -static void -vbi_buffer_queue(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 = fh->btv; - struct bttv_buffer *buf = container_of(vb,struct bttv_buffer,vb); + struct bttv *btv = vb2_get_drv_priv(q); + unsigned long flags; - 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); + 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); } -static void vbi_buffer_release(struct videobuf_queue *q, struct videobuf_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); - - dprintk("free %p\n",vb); - bttv_dma_free(q,fh->btv,buf); -} - -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, +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, }; /* ----------------------------------------------------------------------- */ @@ -250,7 +196,7 @@ static int try_fmt(struct v4l2_vbi_format *f, const struct bttv_tvnorm *tvnorm, if (min_start > max_start) return -EBUSY; - BUG_ON(max_start >= max_end); + WARN_ON(max_start >= max_end); f->sampling_rate = tvnorm->Fsc; f->samples_per_line = VBI_BPL; @@ -299,8 +245,7 @@ static int try_fmt(struct v4l2_vbi_format *f, const struct bttv_tvnorm *tvnorm, int bttv_try_fmt_vbi_cap(struct file *file, void *f, struct v4l2_format *frt) { - struct bttv_fh *fh = f; - struct bttv *btv = fh->btv; + struct bttv *btv = video_drvdata(file); const struct bttv_tvnorm *tvnorm; __s32 crop_start; @@ -317,8 +262,7 @@ 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 = fh->btv; + struct bttv *btv = video_drvdata(file); const struct bttv_tvnorm *tvnorm; __s32 start1, end; int rc; @@ -326,7 +270,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]; @@ -346,13 +290,9 @@ 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; - - mutex_unlock(&fh->vbi.vb_lock); + btv->vbi_fmt.fmt = frt->fmt.vbi; + btv->vbi_fmt.tvnorm = tvnorm; + btv->vbi_fmt.end = end; rc = 0; @@ -365,14 +305,14 @@ int bttv_s_fmt_vbi_cap(struct file *file, void *f, struct v4l2_format *frt) int bttv_g_fmt_vbi_cap(struct file *file, void *f, struct v4l2_format *frt) { - struct bttv_fh *fh = f; const struct bttv_tvnorm *tvnorm; + struct bttv *btv = video_drvdata(file); - frt->fmt.vbi = fh->vbi_fmt.fmt; + frt->fmt.vbi = btv->vbi_fmt.fmt; - tvnorm = &bttv_tvnorms[fh->btv->tvnorm]; + tvnorm = &bttv_tvnorms[btv->tvnorm]; - if (tvnorm != fh->vbi_fmt.tvnorm) { + if (tvnorm != btv->vbi_fmt.tvnorm) { __s32 max_end; unsigned int i; @@ -388,9 +328,8 @@ int bttv_g_fmt_vbi_cap(struct file *file, void *f, struct v4l2_format *frt) for (i = 0; i < 2; ++i) { __s32 new_start; - new_start = frt->fmt.vbi.start[i] - + tvnorm->vbistart[i] - - fh->vbi_fmt.tvnorm->vbistart[i]; + new_start = frt->fmt.vbi.start[i] + tvnorm->vbistart[i] + - btv->vbi_fmt.tvnorm->vbistart[i]; frt->fmt.vbi.start[i] = min(new_start, max_end - 1); frt->fmt.vbi.count[i] = @@ -430,8 +369,8 @@ void bttv_vbi_fmt_reset(struct bttv_vbi_fmt *f, unsigned int norm) real_count = ((tvnorm->cropcap.defrect.top >> 1) - tvnorm->vbistart[0]); - BUG_ON(real_samples_per_line > VBI_BPL); - BUG_ON(real_count > VBI_DEFLINES); + WARN_ON(real_samples_per_line > VBI_BPL); + WARN_ON(real_count > VBI_DEFLINES); f->tvnorm = tvnorm; diff --git a/drivers/media/pci/bt8xx/bttvp.h b/drivers/media/pci/bt8xx/bttvp.h index 717f002a41df..a534e63b9a37 100644 --- a/drivers/media/pci/bt8xx/bttvp.h +++ b/drivers/media/pci/bt8xx/bttvp.h @@ -26,7 +26,7 @@ #include #include #include -#include +#include #include #include #include @@ -142,19 +142,15 @@ 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 */ - const struct bttv_format *fmt; - unsigned int tvnorm; int btformat; int btswap; struct bttv_geometry geo; struct btcx_riscmem top; struct btcx_riscmem bottom; - struct v4l2_rect crop; - unsigned int vbi_skip[2]; - unsigned int vbi_count[2]; }; struct bttv_buffer_set { @@ -176,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 { @@ -192,31 +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; - - /* Application called VIDIOC_S_SELECTION. */ - int do_crop; - - /* 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 */ @@ -237,24 +210,31 @@ 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 */ -extern struct bus_type bttv_sub_bus_type; +extern const struct bus_type bttv_sub_bus_type; int bttv_sub_add_device(struct bttv_core *core, char *name); int bttv_sub_del_devices(struct bttv_core *core); @@ -275,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, ...) \ @@ -396,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; @@ -436,7 +418,6 @@ struct bttv { int loop_irq; int new_input; - unsigned long cap_ctl; unsigned long dma_on; struct timer_list timeout; struct bttv_suspend_state state; @@ -448,7 +429,25 @@ 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_count[2]; + + /* Application called VIDIOC_S_SELECTION. */ + int do_crop; /* used to make dvb-bt8xx autoloadable */ struct work_struct request_module_wk; @@ -487,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)) diff --git a/drivers/media/pci/bt8xx/dvb-bt8xx.c b/drivers/media/pci/bt8xx/dvb-bt8xx.c index 4cb890b949c3..390cbba6c065 100644 --- a/drivers/media/pci/bt8xx/dvb-bt8xx.c +++ b/drivers/media/pci/bt8xx/dvb-bt8xx.c @@ -190,11 +190,15 @@ static int cx24108_tuner_set_params(struct dvb_frontend *fe) u32 freq = c->frequency; int i, a, n, pump; u32 band, pll; - u32 osci[]={950000,1019000,1075000,1178000,1296000,1432000, - 1576000,1718000,1856000,2036000,2150000}; - u32 bandsel[]={0,0x00020000,0x00040000,0x00100800,0x00101000, - 0x00102000,0x00104000,0x00108000,0x00110000, - 0x00120000,0x00140000}; + static const u32 osci[] = { + 950000, 1019000, 1075000, 1178000, 1296000, 1432000, + 1576000, 1718000, 1856000, 2036000, 2150000 + }; + static const u32 bandsel[] = { + 0, 0x00020000, 0x00040000, 0x00100800, 0x00101000, + 0x00102000, 0x00104000, 0x00108000, 0x00110000, + 0x00120000, 0x00140000 + }; #define XTAL 1011100 /* Hz, really 1.0111 MHz and a /10 prescaler */ dprintk("cx24108 debug: entering SetTunerFreq, freq=%d\n", freq); diff --git a/drivers/media/pci/netup_unidvb/netup_unidvb_i2c.c b/drivers/media/pci/netup_unidvb/netup_unidvb_i2c.c index bd38ce444232..1c885d620b75 100644 --- a/drivers/media/pci/netup_unidvb/netup_unidvb_i2c.c +++ b/drivers/media/pci/netup_unidvb/netup_unidvb_i2c.c @@ -135,7 +135,7 @@ static void netup_i2c_fifo_tx(struct netup_i2c *i2c) (readw(&i2c->regs->tx_fifo.stat_ctrl) & 0x3f); u32 msg_length = i2c->msg->len - i2c->xmit_size; - msg_length = (msg_length < fifo_space ? msg_length : fifo_space); + msg_length = min(msg_length, fifo_space); while (msg_length--) { data = i2c->msg->buf[i2c->xmit_size++]; writeb(data, &i2c->regs->tx_fifo.data8); @@ -289,7 +289,7 @@ static const struct i2c_algorithm netup_i2c_algorithm = { static const struct i2c_adapter netup_i2c_adapter = { .owner = THIS_MODULE, .name = NETUP_UNIDVB_NAME, - .class = I2C_CLASS_HWMON | I2C_CLASS_SPD, + .class = I2C_CLASS_HWMON, .algo = &netup_i2c_algorithm, }; diff --git a/drivers/media/pci/tbsecp3/tbsecp3-cards.c b/drivers/media/pci/tbsecp3/tbsecp3-cards.c index b9a0299f7fff..a160177265a6 100755 --- a/drivers/media/pci/tbsecp3/tbsecp3-cards.c +++ b/drivers/media/pci/tbsecp3/tbsecp3-cards.c @@ -841,6 +841,69 @@ struct tbsecp3_board tbsecp3_boards[] = { .ts_in = 7, .i2c_bus_nr = 0, + } + } + }, + [TBSECP3_BOARD_TBS6312X] = { + .board_id = TBSECP3_BOARD_TBS6312X, + .name = "TurboSight TBS 6312X HDMI Capture", + .adapters = 12, + .i2c_speed = 39, + .eeprom_i2c = 1, + .eeprom_addr = 0x10, + .adap_config = { + { + .ts_in = 0, + .i2c_bus_nr = 0, + }, + { + .ts_in = 1, + .i2c_bus_nr = 0, + }, + { + .ts_in = 2, + .i2c_bus_nr = 0, + }, + { + .ts_in = 3, + .i2c_bus_nr = 0, + }, + { + .ts_in = 4, + .i2c_bus_nr = 0, + }, + { + .ts_in = 5, + .i2c_bus_nr = 0, + }, + { + .ts_in = 6, + .i2c_bus_nr = 0, + }, + { + .ts_in = 7, + .i2c_bus_nr = 0, + + }, + { + .ts_in = 8, + .i2c_bus_nr = 0, + + }, + { + .ts_in = 9, + .i2c_bus_nr = 0, + + }, + { + .ts_in = 10, + .i2c_bus_nr = 0, + + }, + { + .ts_in = 11, + .i2c_bus_nr = 0, + } } }, diff --git a/drivers/media/pci/tbsecp3/tbsecp3-core.c b/drivers/media/pci/tbsecp3/tbsecp3-core.c index a8a192378669..ca9a63efe8a5 100755 --- a/drivers/media/pci/tbsecp3/tbsecp3-core.c +++ b/drivers/media/pci/tbsecp3/tbsecp3-core.c @@ -366,6 +366,7 @@ static const struct pci_device_id tbsecp3_id_table[] = { TBSECP3_ID(TBSECP3_BOARD_TBS6304,0x6304,0x0001), TBSECP3_ID(TBSECP3_BOARD_TBS6308,0x6308,0x0001), TBSECP3_ID(TBSECP3_BOARD_TBS6308X,0x6308,0x0010), + TBSECP3_ID(TBSECP3_BOARD_TBS6312X,0x6312,0x0010), TBSECP3_ID(TBSECP3_BOARD_TBS6909X,0x6909,0x0010), TBSECP3_ID(TBSECP3_BOARD_TBS6909X,0x6909,0x0009), TBSECP3_ID(TBSECP3_BOARD_TBS6909X,0x6909,0x0019), diff --git a/drivers/media/pci/tbsecp3/tbsecp3-dvb.c b/drivers/media/pci/tbsecp3/tbsecp3-dvb.c index 95a1f712fd77..877496fbb4a3 100644 --- a/drivers/media/pci/tbsecp3/tbsecp3-dvb.c +++ b/drivers/media/pci/tbsecp3/tbsecp3-dvb.c @@ -1872,6 +1872,12 @@ static int tbsecp3_frontend_attach(struct tbsecp3_adapter *adapter) if (adapter->fe == NULL) goto frontend_atach_fail; + break; + case TBSECP3_BOARD_TBS6312X: + adapter->fe = dvb_attach(tas2971_attach, &tbs6308_demod_cfg, i2c); + if (adapter->fe == NULL) + goto frontend_atach_fail; + break; case TBSECP3_BOARD_TBS6304: adapter->fe = dvb_attach(tas2971_attach, &tbs6304_demod_cfg[adapter->nr], i2c); diff --git a/drivers/media/pci/tbsecp3/tbsecp3.h b/drivers/media/pci/tbsecp3/tbsecp3.h index d03569f4744e..634d57a4a9f4 100755 --- a/drivers/media/pci/tbsecp3/tbsecp3.h +++ b/drivers/media/pci/tbsecp3/tbsecp3.h @@ -88,7 +88,8 @@ #define TBSECP3_BOARD_TBS6504H 44 #define TBSECP3_BOARD_TBS6590SE 45 #define TBSECP3_BOARD_TBS6308X 46 -#define TBSECP3_BOARD_TBS6916 47 +#define TBSECP3_BOARD_TBS6916 47 +#define TBSECP3_BOARD_TBS6312X 48 #define TBSECP3_MAX_ADAPTERS (16) @@ -221,7 +222,7 @@ struct tbsecp3_dev { bool msi; /* dvb adapters */ - struct tbsecp3_adapter adapter[16]; + struct tbsecp3_adapter adapter[TBSECP3_MAX_ADAPTERS]; /* i2c */ struct tbsecp3_i2c i2c_bus[TBSECP3_MAX_I2C_BUS]; diff --git a/drivers/media/usb/cx231xx/cx231xx-i2c.c b/drivers/media/usb/cx231xx/cx231xx-i2c.c index 8608ec4e88d5..0ff4c7a1f348 100644 --- a/drivers/media/usb/cx231xx/cx231xx-i2c.c +++ b/drivers/media/usb/cx231xx/cx231xx-i2c.c @@ -599,10 +599,7 @@ int cx231xx_i2c_mux_create(struct cx231xx *dev) int cx231xx_i2c_mux_register(struct cx231xx *dev, int mux_no) { - return i2c_mux_add_adapter(dev->muxc, - 0, - mux_no /* chan_id */, - 0 /* class */); + return i2c_mux_add_adapter(dev->muxc, 0, mux_no); } void cx231xx_i2c_mux_unregister(struct cx231xx *dev) diff --git a/drivers/media/v4l2-core/Kconfig b/drivers/media/v4l2-core/Kconfig index 348559bc2468..c57e103fed64 100644 --- a/drivers/media/v4l2-core/Kconfig +++ b/drivers/media/v4l2-core/Kconfig @@ -73,19 +73,3 @@ config V4L2_FWNODE config V4L2_ASYNC tristate - -# Used by drivers that need Videobuf modules -config VIDEOBUF_GEN - tristate - -config VIDEOBUF_DMA_SG - tristate - select VIDEOBUF_GEN - -config VIDEOBUF_VMALLOC - tristate - select VIDEOBUF_GEN - -config VIDEOBUF_DMA_CONTIG - tristate - select VIDEOBUF_GEN diff --git a/drivers/media/v4l2-core/Makefile b/drivers/media/v4l2-core/Makefile index 41d91bd10cf2..a13422fec223 100644 --- a/drivers/media/v4l2-core/Makefile +++ b/drivers/media/v4l2-core/Makefile @@ -32,10 +32,5 @@ obj-$(CONFIG_V4L2_JPEG_HELPER) += v4l2-jpeg.o obj-$(CONFIG_V4L2_MEM2MEM_DEV) += v4l2-mem2mem.o obj-$(CONFIG_V4L2_VP9) += v4l2-vp9.o -obj-$(CONFIG_VIDEOBUF_DMA_CONTIG) += videobuf-dma-contig.o -obj-$(CONFIG_VIDEOBUF_DMA_SG) += videobuf-dma-sg.o -obj-$(CONFIG_VIDEOBUF_GEN) += videobuf-core.o -obj-$(CONFIG_VIDEOBUF_VMALLOC) += videobuf-vmalloc.o - obj-$(CONFIG_VIDEO_TUNER) += tuner.o obj-$(CONFIG_VIDEO_DEV) += v4l2-dv-timings.o videodev.o diff --git a/drivers/media/v4l2-core/videobuf-core.c b/drivers/media/v4l2-core/videobuf-core.c deleted file mode 100644 index 606a271bdd2d..000000000000 --- a/drivers/media/v4l2-core/videobuf-core.c +++ /dev/null @@ -1,1198 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * generic helper functions for handling video4linux capture buffers - * - * (c) 2007 Mauro Carvalho Chehab, - * - * Highly based on video-buf written originally by: - * (c) 2001,02 Gerd Knorr - * (c) 2006 Mauro Carvalho Chehab, - * (c) 2006 Ted Walther and John Sokol - */ - -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#define MAGIC_BUFFER 0x20070728 -#define MAGIC_CHECK(is, should) \ - do { \ - if (unlikely((is) != (should))) { \ - printk(KERN_ERR \ - "magic mismatch: %x (expected %x)\n", \ - is, should); \ - BUG(); \ - } \ - } while (0) - -static int debug; -module_param(debug, int, 0644); - -MODULE_DESCRIPTION("helper module to manage video4linux buffers"); -MODULE_AUTHOR("Mauro Carvalho Chehab "); -MODULE_LICENSE("GPL"); - -#define dprintk(level, fmt, arg...) \ - do { \ - if (debug >= level) \ - printk(KERN_DEBUG "vbuf: " fmt, ## arg); \ - } while (0) - -/* --------------------------------------------------------------------- */ - -#define CALL(q, f, arg...) \ - ((q->int_ops->f) ? q->int_ops->f(arg) : 0) -#define CALLPTR(q, f, arg...) \ - ((q->int_ops->f) ? q->int_ops->f(arg) : NULL) - -struct videobuf_buffer *videobuf_alloc_vb(struct videobuf_queue *q) -{ - struct videobuf_buffer *vb; - - BUG_ON(q->msize < sizeof(*vb)); - - if (!q->int_ops || !q->int_ops->alloc_vb) { - printk(KERN_ERR "No specific ops defined!\n"); - BUG(); - } - - vb = q->int_ops->alloc_vb(q->msize); - if (NULL != vb) { - init_waitqueue_head(&vb->done); - vb->magic = MAGIC_BUFFER; - } - - return vb; -} -EXPORT_SYMBOL_GPL(videobuf_alloc_vb); - -static int state_neither_active_nor_queued(struct videobuf_queue *q, - struct videobuf_buffer *vb) -{ - unsigned long flags; - bool rc; - - spin_lock_irqsave(q->irqlock, flags); - rc = vb->state != VIDEOBUF_ACTIVE && vb->state != VIDEOBUF_QUEUED; - spin_unlock_irqrestore(q->irqlock, flags); - return rc; -}; - -int videobuf_waiton(struct videobuf_queue *q, struct videobuf_buffer *vb, - int non_blocking, int intr) -{ - bool is_ext_locked; - int ret = 0; - - MAGIC_CHECK(vb->magic, MAGIC_BUFFER); - - if (non_blocking) { - if (state_neither_active_nor_queued(q, vb)) - return 0; - return -EAGAIN; - } - - is_ext_locked = q->ext_lock && mutex_is_locked(q->ext_lock); - - /* Release vdev lock to prevent this wait from blocking outside access to - the device. */ - if (is_ext_locked) - mutex_unlock(q->ext_lock); - if (intr) - ret = wait_event_interruptible(vb->done, - state_neither_active_nor_queued(q, vb)); - else - wait_event(vb->done, state_neither_active_nor_queued(q, vb)); - /* Relock */ - if (is_ext_locked) - mutex_lock(q->ext_lock); - - return ret; -} -EXPORT_SYMBOL_GPL(videobuf_waiton); - -int videobuf_iolock(struct videobuf_queue *q, struct videobuf_buffer *vb, - struct v4l2_framebuffer *fbuf) -{ - MAGIC_CHECK(vb->magic, MAGIC_BUFFER); - MAGIC_CHECK(q->int_ops->magic, MAGIC_QTYPE_OPS); - - return CALL(q, iolock, q, vb, fbuf); -} -EXPORT_SYMBOL_GPL(videobuf_iolock); - -void *videobuf_queue_to_vaddr(struct videobuf_queue *q, - struct videobuf_buffer *buf) -{ - if (q->int_ops->vaddr) - return q->int_ops->vaddr(buf); - return NULL; -} -EXPORT_SYMBOL_GPL(videobuf_queue_to_vaddr); - -/* --------------------------------------------------------------------- */ - - -void videobuf_queue_core_init(struct videobuf_queue *q, - const struct videobuf_queue_ops *ops, - struct device *dev, - spinlock_t *irqlock, - enum v4l2_buf_type type, - enum v4l2_field field, - unsigned int msize, - void *priv, - struct videobuf_qtype_ops *int_ops, - struct mutex *ext_lock) -{ - BUG_ON(!q); - memset(q, 0, sizeof(*q)); - q->irqlock = irqlock; - q->ext_lock = ext_lock; - q->dev = dev; - q->type = type; - q->field = field; - q->msize = msize; - q->ops = ops; - q->priv_data = priv; - q->int_ops = int_ops; - - /* All buffer operations are mandatory */ - BUG_ON(!q->ops->buf_setup); - BUG_ON(!q->ops->buf_prepare); - BUG_ON(!q->ops->buf_queue); - BUG_ON(!q->ops->buf_release); - - /* Lock is mandatory for queue_cancel to work */ - BUG_ON(!irqlock); - - /* Having implementations for abstract methods are mandatory */ - BUG_ON(!q->int_ops); - - mutex_init(&q->vb_lock); - init_waitqueue_head(&q->wait); - INIT_LIST_HEAD(&q->stream); -} -EXPORT_SYMBOL_GPL(videobuf_queue_core_init); - -/* Locking: Only usage in bttv unsafe find way to remove */ -int videobuf_queue_is_busy(struct videobuf_queue *q) -{ - int i; - - MAGIC_CHECK(q->int_ops->magic, MAGIC_QTYPE_OPS); - - if (q->streaming) { - dprintk(1, "busy: streaming active\n"); - return 1; - } - if (q->reading) { - dprintk(1, "busy: pending read #1\n"); - return 1; - } - if (q->read_buf) { - dprintk(1, "busy: pending read #2\n"); - return 1; - } - for (i = 0; i < VIDEO_MAX_FRAME; i++) { - if (NULL == q->bufs[i]) - continue; - if (q->bufs[i]->map) { - dprintk(1, "busy: buffer #%d mapped\n", i); - return 1; - } - if (q->bufs[i]->state == VIDEOBUF_QUEUED) { - dprintk(1, "busy: buffer #%d queued\n", i); - return 1; - } - if (q->bufs[i]->state == VIDEOBUF_ACTIVE) { - dprintk(1, "busy: buffer #%d active\n", i); - return 1; - } - } - return 0; -} -EXPORT_SYMBOL_GPL(videobuf_queue_is_busy); - -/* - * __videobuf_free() - free all the buffers and their control structures - * - * This function can only be called if streaming/reading is off, i.e. no buffers - * are under control of the driver. - */ -/* Locking: Caller holds q->vb_lock */ -static int __videobuf_free(struct videobuf_queue *q) -{ - int i; - - dprintk(1, "%s\n", __func__); - if (!q) - return 0; - - if (q->streaming || q->reading) { - dprintk(1, "Cannot free buffers when streaming or reading\n"); - return -EBUSY; - } - - MAGIC_CHECK(q->int_ops->magic, MAGIC_QTYPE_OPS); - - for (i = 0; i < VIDEO_MAX_FRAME; i++) - if (q->bufs[i] && q->bufs[i]->map) { - dprintk(1, "Cannot free mmapped buffers\n"); - return -EBUSY; - } - - for (i = 0; i < VIDEO_MAX_FRAME; i++) { - if (NULL == q->bufs[i]) - continue; - q->ops->buf_release(q, q->bufs[i]); - kfree(q->bufs[i]); - q->bufs[i] = NULL; - } - - return 0; -} - -/* Locking: Caller holds q->vb_lock */ -void videobuf_queue_cancel(struct videobuf_queue *q) -{ - unsigned long flags = 0; - int i; - - q->streaming = 0; - q->reading = 0; - wake_up_interruptible_sync(&q->wait); - - /* remove queued buffers from list */ - spin_lock_irqsave(q->irqlock, flags); - for (i = 0; i < VIDEO_MAX_FRAME; i++) { - if (NULL == q->bufs[i]) - continue; - if (q->bufs[i]->state == VIDEOBUF_QUEUED) { - list_del(&q->bufs[i]->queue); - q->bufs[i]->state = VIDEOBUF_ERROR; - wake_up_all(&q->bufs[i]->done); - } - } - spin_unlock_irqrestore(q->irqlock, flags); - - /* free all buffers + clear queue */ - for (i = 0; i < VIDEO_MAX_FRAME; i++) { - if (NULL == q->bufs[i]) - continue; - q->ops->buf_release(q, q->bufs[i]); - } - INIT_LIST_HEAD(&q->stream); -} -EXPORT_SYMBOL_GPL(videobuf_queue_cancel); - -/* --------------------------------------------------------------------- */ - -/* Locking: Caller holds q->vb_lock */ -enum v4l2_field videobuf_next_field(struct videobuf_queue *q) -{ - enum v4l2_field field = q->field; - - BUG_ON(V4L2_FIELD_ANY == field); - - if (V4L2_FIELD_ALTERNATE == field) { - if (V4L2_FIELD_TOP == q->last) { - field = V4L2_FIELD_BOTTOM; - q->last = V4L2_FIELD_BOTTOM; - } else { - field = V4L2_FIELD_TOP; - q->last = V4L2_FIELD_TOP; - } - } - return field; -} -EXPORT_SYMBOL_GPL(videobuf_next_field); - -/* Locking: Caller holds q->vb_lock */ -static void videobuf_status(struct videobuf_queue *q, struct v4l2_buffer *b, - struct videobuf_buffer *vb, enum v4l2_buf_type type) -{ - MAGIC_CHECK(vb->magic, MAGIC_BUFFER); - MAGIC_CHECK(q->int_ops->magic, MAGIC_QTYPE_OPS); - - b->index = vb->i; - b->type = type; - - b->memory = vb->memory; - switch (b->memory) { - case V4L2_MEMORY_MMAP: - b->m.offset = vb->boff; - b->length = vb->bsize; - break; - case V4L2_MEMORY_USERPTR: - b->m.userptr = vb->baddr; - b->length = vb->bsize; - break; - case V4L2_MEMORY_OVERLAY: - b->m.offset = vb->boff; - break; - case V4L2_MEMORY_DMABUF: - /* DMABUF is not handled in videobuf framework */ - break; - } - - b->flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC; - if (vb->map) - b->flags |= V4L2_BUF_FLAG_MAPPED; - - switch (vb->state) { - case VIDEOBUF_PREPARED: - case VIDEOBUF_QUEUED: - case VIDEOBUF_ACTIVE: - b->flags |= V4L2_BUF_FLAG_QUEUED; - break; - case VIDEOBUF_ERROR: - b->flags |= V4L2_BUF_FLAG_ERROR; - fallthrough; - case VIDEOBUF_DONE: - b->flags |= V4L2_BUF_FLAG_DONE; - break; - case VIDEOBUF_NEEDS_INIT: - case VIDEOBUF_IDLE: - /* nothing */ - break; - } - - b->field = vb->field; - v4l2_buffer_set_timestamp(b, vb->ts); - b->bytesused = vb->size; - b->sequence = vb->field_count >> 1; -} - -int videobuf_mmap_free(struct videobuf_queue *q) -{ - int ret; - videobuf_queue_lock(q); - ret = __videobuf_free(q); - videobuf_queue_unlock(q); - return ret; -} -EXPORT_SYMBOL_GPL(videobuf_mmap_free); - -/* Locking: Caller holds q->vb_lock */ -int __videobuf_mmap_setup(struct videobuf_queue *q, - unsigned int bcount, unsigned int bsize, - enum v4l2_memory memory) -{ - unsigned int i; - int err; - - MAGIC_CHECK(q->int_ops->magic, MAGIC_QTYPE_OPS); - - err = __videobuf_free(q); - if (0 != err) - return err; - - /* Allocate and initialize buffers */ - for (i = 0; i < bcount; i++) { - q->bufs[i] = videobuf_alloc_vb(q); - - if (NULL == q->bufs[i]) - break; - - q->bufs[i]->i = i; - q->bufs[i]->memory = memory; - q->bufs[i]->bsize = bsize; - switch (memory) { - case V4L2_MEMORY_MMAP: - q->bufs[i]->boff = PAGE_ALIGN(bsize) * i; - break; - case V4L2_MEMORY_USERPTR: - case V4L2_MEMORY_OVERLAY: - case V4L2_MEMORY_DMABUF: - /* nothing */ - break; - } - } - - if (!i) - return -ENOMEM; - - dprintk(1, "mmap setup: %d buffers, %d bytes each\n", i, bsize); - - return i; -} -EXPORT_SYMBOL_GPL(__videobuf_mmap_setup); - -int videobuf_mmap_setup(struct videobuf_queue *q, - unsigned int bcount, unsigned int bsize, - enum v4l2_memory memory) -{ - int ret; - videobuf_queue_lock(q); - ret = __videobuf_mmap_setup(q, bcount, bsize, memory); - videobuf_queue_unlock(q); - return ret; -} -EXPORT_SYMBOL_GPL(videobuf_mmap_setup); - -int videobuf_reqbufs(struct videobuf_queue *q, - struct v4l2_requestbuffers *req) -{ - unsigned int size, count; - int retval; - - if (req->memory != V4L2_MEMORY_MMAP && - req->memory != V4L2_MEMORY_USERPTR && - req->memory != V4L2_MEMORY_OVERLAY) { - dprintk(1, "reqbufs: memory type invalid\n"); - return -EINVAL; - } - - videobuf_queue_lock(q); - if (req->type != q->type) { - dprintk(1, "reqbufs: queue type invalid\n"); - retval = -EINVAL; - goto done; - } - - if (q->streaming) { - dprintk(1, "reqbufs: streaming already exists\n"); - retval = -EBUSY; - goto done; - } - if (!list_empty(&q->stream)) { - dprintk(1, "reqbufs: stream running\n"); - retval = -EBUSY; - goto done; - } - - if (req->count == 0) { - dprintk(1, "reqbufs: count invalid (%d)\n", req->count); - retval = __videobuf_free(q); - goto done; - } - - count = req->count; - if (count > VIDEO_MAX_FRAME) - count = VIDEO_MAX_FRAME; - size = 0; - q->ops->buf_setup(q, &count, &size); - dprintk(1, "reqbufs: bufs=%d, size=0x%x [%u pages total]\n", - count, size, - (unsigned int)((count * PAGE_ALIGN(size)) >> PAGE_SHIFT)); - - retval = __videobuf_mmap_setup(q, count, size, req->memory); - if (retval < 0) { - dprintk(1, "reqbufs: mmap setup returned %d\n", retval); - goto done; - } - - req->count = retval; - retval = 0; - - done: - videobuf_queue_unlock(q); - return retval; -} -EXPORT_SYMBOL_GPL(videobuf_reqbufs); - -int videobuf_querybuf(struct videobuf_queue *q, struct v4l2_buffer *b) -{ - int ret = -EINVAL; - - videobuf_queue_lock(q); - if (unlikely(b->type != q->type)) { - dprintk(1, "querybuf: Wrong type.\n"); - goto done; - } - if (unlikely(b->index >= VIDEO_MAX_FRAME)) { - dprintk(1, "querybuf: index out of range.\n"); - goto done; - } - if (unlikely(NULL == q->bufs[b->index])) { - dprintk(1, "querybuf: buffer is null.\n"); - goto done; - } - - videobuf_status(q, b, q->bufs[b->index], q->type); - - ret = 0; -done: - videobuf_queue_unlock(q); - return ret; -} -EXPORT_SYMBOL_GPL(videobuf_querybuf); - -int videobuf_qbuf(struct videobuf_queue *q, struct v4l2_buffer *b) -{ - struct videobuf_buffer *buf; - enum v4l2_field field; - unsigned long flags = 0; - int retval; - - MAGIC_CHECK(q->int_ops->magic, MAGIC_QTYPE_OPS); - - if (b->memory == V4L2_MEMORY_MMAP) - mmap_read_lock(current->mm); - - videobuf_queue_lock(q); - retval = -EBUSY; - if (q->reading) { - dprintk(1, "qbuf: Reading running...\n"); - goto done; - } - retval = -EINVAL; - if (b->type != q->type) { - dprintk(1, "qbuf: Wrong type.\n"); - goto done; - } - if (b->index >= VIDEO_MAX_FRAME) { - dprintk(1, "qbuf: index out of range.\n"); - goto done; - } - buf = q->bufs[b->index]; - if (NULL == buf) { - dprintk(1, "qbuf: buffer is null.\n"); - goto done; - } - MAGIC_CHECK(buf->magic, MAGIC_BUFFER); - if (buf->memory != b->memory) { - dprintk(1, "qbuf: memory type is wrong.\n"); - goto done; - } - if (buf->state != VIDEOBUF_NEEDS_INIT && buf->state != VIDEOBUF_IDLE) { - dprintk(1, "qbuf: buffer is already queued or active.\n"); - goto done; - } - - switch (b->memory) { - case V4L2_MEMORY_MMAP: - if (0 == buf->baddr) { - dprintk(1, "qbuf: mmap requested but buffer addr is zero!\n"); - goto done; - } - if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT - || q->type == V4L2_BUF_TYPE_VBI_OUTPUT - || q->type == V4L2_BUF_TYPE_SLICED_VBI_OUTPUT - || q->type == V4L2_BUF_TYPE_SDR_OUTPUT) { - buf->size = b->bytesused; - buf->field = b->field; - buf->ts = v4l2_buffer_get_timestamp(b); - } - break; - case V4L2_MEMORY_USERPTR: - if (b->length < buf->bsize) { - dprintk(1, "qbuf: buffer length is not enough\n"); - goto done; - } - if (VIDEOBUF_NEEDS_INIT != buf->state && - buf->baddr != b->m.userptr) - q->ops->buf_release(q, buf); - buf->baddr = b->m.userptr; - break; - case V4L2_MEMORY_OVERLAY: - buf->boff = b->m.offset; - break; - default: - dprintk(1, "qbuf: wrong memory type\n"); - goto done; - } - - dprintk(1, "qbuf: requesting next field\n"); - field = videobuf_next_field(q); - retval = q->ops->buf_prepare(q, buf, field); - if (0 != retval) { - dprintk(1, "qbuf: buffer_prepare returned %d\n", retval); - goto done; - } - - list_add_tail(&buf->stream, &q->stream); - if (q->streaming) { - spin_lock_irqsave(q->irqlock, flags); - q->ops->buf_queue(q, buf); - spin_unlock_irqrestore(q->irqlock, flags); - } - dprintk(1, "qbuf: succeeded\n"); - retval = 0; - wake_up_interruptible_sync(&q->wait); - -done: - videobuf_queue_unlock(q); - - if (b->memory == V4L2_MEMORY_MMAP) - mmap_read_unlock(current->mm); - - return retval; -} -EXPORT_SYMBOL_GPL(videobuf_qbuf); - -/* Locking: Caller holds q->vb_lock */ -static int stream_next_buffer_check_queue(struct videobuf_queue *q, int noblock) -{ - int retval; - -checks: - if (!q->streaming) { - dprintk(1, "next_buffer: Not streaming\n"); - retval = -EINVAL; - goto done; - } - - if (list_empty(&q->stream)) { - if (noblock) { - retval = -EAGAIN; - dprintk(2, "next_buffer: no buffers to dequeue\n"); - goto done; - } else { - dprintk(2, "next_buffer: waiting on buffer\n"); - - /* Drop lock to avoid deadlock with qbuf */ - videobuf_queue_unlock(q); - - /* Checking list_empty and streaming is safe without - * locks because we goto checks to validate while - * holding locks before proceeding */ - retval = wait_event_interruptible(q->wait, - !list_empty(&q->stream) || !q->streaming); - videobuf_queue_lock(q); - - if (retval) - goto done; - - goto checks; - } - } - - retval = 0; - -done: - return retval; -} - -/* Locking: Caller holds q->vb_lock */ -static int stream_next_buffer(struct videobuf_queue *q, - struct videobuf_buffer **vb, int nonblocking) -{ - int retval; - struct videobuf_buffer *buf = NULL; - - retval = stream_next_buffer_check_queue(q, nonblocking); - if (retval) - goto done; - - buf = list_entry(q->stream.next, struct videobuf_buffer, stream); - retval = videobuf_waiton(q, buf, nonblocking, 1); - if (retval < 0) - goto done; - - *vb = buf; -done: - return retval; -} - -int videobuf_dqbuf(struct videobuf_queue *q, - struct v4l2_buffer *b, int nonblocking) -{ - struct videobuf_buffer *buf = NULL; - int retval; - - MAGIC_CHECK(q->int_ops->magic, MAGIC_QTYPE_OPS); - - memset(b, 0, sizeof(*b)); - videobuf_queue_lock(q); - - retval = stream_next_buffer(q, &buf, nonblocking); - if (retval < 0) { - dprintk(1, "dqbuf: next_buffer error: %i\n", retval); - goto done; - } - - switch (buf->state) { - case VIDEOBUF_ERROR: - dprintk(1, "dqbuf: state is error\n"); - break; - case VIDEOBUF_DONE: - dprintk(1, "dqbuf: state is done\n"); - break; - default: - dprintk(1, "dqbuf: state invalid\n"); - retval = -EINVAL; - goto done; - } - CALL(q, sync, q, buf); - videobuf_status(q, b, buf, q->type); - list_del(&buf->stream); - buf->state = VIDEOBUF_IDLE; - b->flags &= ~V4L2_BUF_FLAG_DONE; -done: - videobuf_queue_unlock(q); - return retval; -} -EXPORT_SYMBOL_GPL(videobuf_dqbuf); - -int videobuf_streamon(struct videobuf_queue *q) -{ - struct videobuf_buffer *buf; - unsigned long flags = 0; - int retval; - - videobuf_queue_lock(q); - retval = -EBUSY; - if (q->reading) - goto done; - retval = 0; - if (q->streaming) - goto done; - q->streaming = 1; - spin_lock_irqsave(q->irqlock, flags); - list_for_each_entry(buf, &q->stream, stream) - if (buf->state == VIDEOBUF_PREPARED) - q->ops->buf_queue(q, buf); - spin_unlock_irqrestore(q->irqlock, flags); - - wake_up_interruptible_sync(&q->wait); -done: - videobuf_queue_unlock(q); - return retval; -} -EXPORT_SYMBOL_GPL(videobuf_streamon); - -/* Locking: Caller holds q->vb_lock */ -static int __videobuf_streamoff(struct videobuf_queue *q) -{ - if (!q->streaming) - return -EINVAL; - - videobuf_queue_cancel(q); - - return 0; -} - -int videobuf_streamoff(struct videobuf_queue *q) -{ - int retval; - - videobuf_queue_lock(q); - retval = __videobuf_streamoff(q); - videobuf_queue_unlock(q); - - return retval; -} -EXPORT_SYMBOL_GPL(videobuf_streamoff); - -/* Locking: Caller holds q->vb_lock */ -static ssize_t videobuf_read_zerocopy(struct videobuf_queue *q, - char __user *data, - size_t count, loff_t *ppos) -{ - enum v4l2_field field; - unsigned long flags = 0; - int retval; - - MAGIC_CHECK(q->int_ops->magic, MAGIC_QTYPE_OPS); - - /* setup stuff */ - q->read_buf = videobuf_alloc_vb(q); - if (NULL == q->read_buf) - return -ENOMEM; - - q->read_buf->memory = V4L2_MEMORY_USERPTR; - q->read_buf->baddr = (unsigned long)data; - q->read_buf->bsize = count; - - field = videobuf_next_field(q); - retval = q->ops->buf_prepare(q, q->read_buf, field); - if (0 != retval) - goto done; - - /* start capture & wait */ - spin_lock_irqsave(q->irqlock, flags); - q->ops->buf_queue(q, q->read_buf); - spin_unlock_irqrestore(q->irqlock, flags); - retval = videobuf_waiton(q, q->read_buf, 0, 0); - if (0 == retval) { - CALL(q, sync, q, q->read_buf); - if (VIDEOBUF_ERROR == q->read_buf->state) - retval = -EIO; - else - retval = q->read_buf->size; - } - -done: - /* cleanup */ - q->ops->buf_release(q, q->read_buf); - kfree(q->read_buf); - q->read_buf = NULL; - return retval; -} - -static int __videobuf_copy_to_user(struct videobuf_queue *q, - struct videobuf_buffer *buf, - char __user *data, size_t count, - int nonblocking) -{ - void *vaddr = CALLPTR(q, vaddr, buf); - - /* copy to userspace */ - if (count > buf->size - q->read_off) - count = buf->size - q->read_off; - - if (copy_to_user(data, vaddr + q->read_off, count)) - return -EFAULT; - - return count; -} - -static int __videobuf_copy_stream(struct videobuf_queue *q, - struct videobuf_buffer *buf, - char __user *data, size_t count, size_t pos, - int vbihack, int nonblocking) -{ - unsigned int *fc = CALLPTR(q, vaddr, buf); - - if (vbihack) { - /* dirty, undocumented hack -- pass the frame counter - * within the last four bytes of each vbi data block. - * We need that one to maintain backward compatibility - * to all vbi decoding software out there ... */ - fc += (buf->size >> 2) - 1; - *fc = buf->field_count >> 1; - dprintk(1, "vbihack: %d\n", *fc); - } - - /* copy stuff using the common method */ - count = __videobuf_copy_to_user(q, buf, data, count, nonblocking); - - if ((count == -EFAULT) && (pos == 0)) - return -EFAULT; - - return count; -} - -ssize_t videobuf_read_one(struct videobuf_queue *q, - char __user *data, size_t count, loff_t *ppos, - int nonblocking) -{ - enum v4l2_field field; - unsigned long flags = 0; - unsigned size = 0, nbufs = 1; - int retval; - - MAGIC_CHECK(q->int_ops->magic, MAGIC_QTYPE_OPS); - - videobuf_queue_lock(q); - - q->ops->buf_setup(q, &nbufs, &size); - - if (NULL == q->read_buf && - count >= size && - !nonblocking) { - retval = videobuf_read_zerocopy(q, data, count, ppos); - if (retval >= 0 || retval == -EIO) - /* ok, all done */ - goto done; - /* fallback to kernel bounce buffer on failures */ - } - - if (NULL == q->read_buf) { - /* need to capture a new frame */ - retval = -ENOMEM; - q->read_buf = videobuf_alloc_vb(q); - - dprintk(1, "video alloc=0x%p\n", q->read_buf); - if (NULL == q->read_buf) - goto done; - q->read_buf->memory = V4L2_MEMORY_USERPTR; - q->read_buf->bsize = count; /* preferred size */ - field = videobuf_next_field(q); - retval = q->ops->buf_prepare(q, q->read_buf, field); - - if (0 != retval) { - kfree(q->read_buf); - q->read_buf = NULL; - goto done; - } - - spin_lock_irqsave(q->irqlock, flags); - q->ops->buf_queue(q, q->read_buf); - spin_unlock_irqrestore(q->irqlock, flags); - - q->read_off = 0; - } - - /* wait until capture is done */ - retval = videobuf_waiton(q, q->read_buf, nonblocking, 1); - if (0 != retval) - goto done; - - CALL(q, sync, q, q->read_buf); - - if (VIDEOBUF_ERROR == q->read_buf->state) { - /* catch I/O errors */ - q->ops->buf_release(q, q->read_buf); - kfree(q->read_buf); - q->read_buf = NULL; - retval = -EIO; - goto done; - } - - /* Copy to userspace */ - retval = __videobuf_copy_to_user(q, q->read_buf, data, count, nonblocking); - if (retval < 0) - goto done; - - q->read_off += retval; - if (q->read_off == q->read_buf->size) { - /* all data copied, cleanup */ - q->ops->buf_release(q, q->read_buf); - kfree(q->read_buf); - q->read_buf = NULL; - } - -done: - videobuf_queue_unlock(q); - return retval; -} -EXPORT_SYMBOL_GPL(videobuf_read_one); - -/* Locking: Caller holds q->vb_lock */ -static int __videobuf_read_start(struct videobuf_queue *q) -{ - enum v4l2_field field; - unsigned long flags = 0; - unsigned int count = 0, size = 0; - int err, i; - - q->ops->buf_setup(q, &count, &size); - if (count < 2) - count = 2; - if (count > VIDEO_MAX_FRAME) - count = VIDEO_MAX_FRAME; - size = PAGE_ALIGN(size); - - err = __videobuf_mmap_setup(q, count, size, V4L2_MEMORY_USERPTR); - if (err < 0) - return err; - - count = err; - - for (i = 0; i < count; i++) { - field = videobuf_next_field(q); - err = q->ops->buf_prepare(q, q->bufs[i], field); - if (err) - return err; - list_add_tail(&q->bufs[i]->stream, &q->stream); - } - spin_lock_irqsave(q->irqlock, flags); - for (i = 0; i < count; i++) - q->ops->buf_queue(q, q->bufs[i]); - spin_unlock_irqrestore(q->irqlock, flags); - q->reading = 1; - return 0; -} - -static void __videobuf_read_stop(struct videobuf_queue *q) -{ - int i; - - videobuf_queue_cancel(q); - __videobuf_free(q); - INIT_LIST_HEAD(&q->stream); - for (i = 0; i < VIDEO_MAX_FRAME; i++) { - if (NULL == q->bufs[i]) - continue; - kfree(q->bufs[i]); - q->bufs[i] = NULL; - } - q->read_buf = NULL; -} - -int videobuf_read_start(struct videobuf_queue *q) -{ - int rc; - - videobuf_queue_lock(q); - rc = __videobuf_read_start(q); - videobuf_queue_unlock(q); - - return rc; -} -EXPORT_SYMBOL_GPL(videobuf_read_start); - -void videobuf_read_stop(struct videobuf_queue *q) -{ - videobuf_queue_lock(q); - __videobuf_read_stop(q); - videobuf_queue_unlock(q); -} -EXPORT_SYMBOL_GPL(videobuf_read_stop); - -void videobuf_stop(struct videobuf_queue *q) -{ - videobuf_queue_lock(q); - - if (q->streaming) - __videobuf_streamoff(q); - - if (q->reading) - __videobuf_read_stop(q); - - videobuf_queue_unlock(q); -} -EXPORT_SYMBOL_GPL(videobuf_stop); - -ssize_t videobuf_read_stream(struct videobuf_queue *q, - char __user *data, size_t count, loff_t *ppos, - int vbihack, int nonblocking) -{ - int rc, retval; - unsigned long flags = 0; - - MAGIC_CHECK(q->int_ops->magic, MAGIC_QTYPE_OPS); - - dprintk(2, "%s\n", __func__); - videobuf_queue_lock(q); - retval = -EBUSY; - if (q->streaming) - goto done; - if (!q->reading) { - retval = __videobuf_read_start(q); - if (retval < 0) - goto done; - } - - retval = 0; - while (count > 0) { - /* get / wait for data */ - if (NULL == q->read_buf) { - q->read_buf = list_entry(q->stream.next, - struct videobuf_buffer, - stream); - list_del(&q->read_buf->stream); - q->read_off = 0; - } - rc = videobuf_waiton(q, q->read_buf, nonblocking, 1); - if (rc < 0) { - if (0 == retval) - retval = rc; - break; - } - - if (q->read_buf->state == VIDEOBUF_DONE) { - rc = __videobuf_copy_stream(q, q->read_buf, data + retval, count, - retval, vbihack, nonblocking); - if (rc < 0) { - retval = rc; - break; - } - retval += rc; - count -= rc; - q->read_off += rc; - } else { - /* some error */ - q->read_off = q->read_buf->size; - if (0 == retval) - retval = -EIO; - } - - /* requeue buffer when done with copying */ - if (q->read_off == q->read_buf->size) { - list_add_tail(&q->read_buf->stream, - &q->stream); - spin_lock_irqsave(q->irqlock, flags); - q->ops->buf_queue(q, q->read_buf); - spin_unlock_irqrestore(q->irqlock, flags); - q->read_buf = NULL; - } - if (retval < 0) - break; - } - -done: - videobuf_queue_unlock(q); - return retval; -} -EXPORT_SYMBOL_GPL(videobuf_read_stream); - -__poll_t videobuf_poll_stream(struct file *file, - struct videobuf_queue *q, - poll_table *wait) -{ - __poll_t req_events = poll_requested_events(wait); - struct videobuf_buffer *buf = NULL; - __poll_t rc = 0; - - videobuf_queue_lock(q); - if (q->streaming) { - if (!list_empty(&q->stream)) - buf = list_entry(q->stream.next, - struct videobuf_buffer, stream); - } else if (req_events & (EPOLLIN | EPOLLRDNORM)) { - if (!q->reading) - __videobuf_read_start(q); - if (!q->reading) { - rc = EPOLLERR; - } else if (NULL == q->read_buf) { - q->read_buf = list_entry(q->stream.next, - struct videobuf_buffer, - stream); - list_del(&q->read_buf->stream); - q->read_off = 0; - } - buf = q->read_buf; - } - if (buf) - poll_wait(file, &buf->done, wait); - else - rc = EPOLLERR; - - if (0 == rc) { - if (buf->state == VIDEOBUF_DONE || - buf->state == VIDEOBUF_ERROR) { - switch (q->type) { - case V4L2_BUF_TYPE_VIDEO_OUTPUT: - case V4L2_BUF_TYPE_VBI_OUTPUT: - case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT: - case V4L2_BUF_TYPE_SDR_OUTPUT: - rc = EPOLLOUT | EPOLLWRNORM; - break; - default: - rc = EPOLLIN | EPOLLRDNORM; - break; - } - } - } - videobuf_queue_unlock(q); - return rc; -} -EXPORT_SYMBOL_GPL(videobuf_poll_stream); - -int videobuf_mmap_mapper(struct videobuf_queue *q, struct vm_area_struct *vma) -{ - int rc = -EINVAL; - int i; - - MAGIC_CHECK(q->int_ops->magic, MAGIC_QTYPE_OPS); - - if (!(vma->vm_flags & VM_WRITE) || !(vma->vm_flags & VM_SHARED)) { - dprintk(1, "mmap appl bug: PROT_WRITE and MAP_SHARED are required\n"); - return -EINVAL; - } - - videobuf_queue_lock(q); - for (i = 0; i < VIDEO_MAX_FRAME; i++) { - struct videobuf_buffer *buf = q->bufs[i]; - - if (buf && buf->memory == V4L2_MEMORY_MMAP && - buf->boff == (vma->vm_pgoff << PAGE_SHIFT)) { - rc = CALL(q, mmap_mapper, q, buf, vma); - break; - } - } - videobuf_queue_unlock(q); - - return rc; -} -EXPORT_SYMBOL_GPL(videobuf_mmap_mapper); diff --git a/drivers/media/v4l2-core/videobuf-dma-contig.c b/drivers/media/v4l2-core/videobuf-dma-contig.c deleted file mode 100644 index 4c2ec7a0d804..000000000000 --- a/drivers/media/v4l2-core/videobuf-dma-contig.c +++ /dev/null @@ -1,402 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * helper functions for physically contiguous capture buffers - * - * The functions support hardware lacking scatter gather support - * (i.e. the buffers must be linear in physical memory) - * - * Copyright (c) 2008 Magnus Damm - * - * Based on videobuf-vmalloc.c, - * (c) 2007 Mauro Carvalho Chehab, - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -struct videobuf_dma_contig_memory { - u32 magic; - void *vaddr; - dma_addr_t dma_handle; - unsigned long size; -}; - -#define MAGIC_DC_MEM 0x0733ac61 -#define MAGIC_CHECK(is, should) \ - if (unlikely((is) != (should))) { \ - pr_err("magic mismatch: %x expected %x\n", (is), (should)); \ - BUG(); \ - } - -static int __videobuf_dc_alloc(struct device *dev, - struct videobuf_dma_contig_memory *mem, - unsigned long size) -{ - mem->size = size; - mem->vaddr = dma_alloc_coherent(dev, mem->size, &mem->dma_handle, - GFP_KERNEL); - if (!mem->vaddr) { - dev_err(dev, "memory alloc size %ld failed\n", mem->size); - return -ENOMEM; - } - - dev_dbg(dev, "dma mapped data is at %p (%ld)\n", mem->vaddr, mem->size); - - return 0; -} - -static void __videobuf_dc_free(struct device *dev, - struct videobuf_dma_contig_memory *mem) -{ - dma_free_coherent(dev, mem->size, mem->vaddr, mem->dma_handle); - - mem->vaddr = NULL; -} - -static void videobuf_vm_open(struct vm_area_struct *vma) -{ - struct videobuf_mapping *map = vma->vm_private_data; - - dev_dbg(map->q->dev, "vm_open %p [count=%u,vma=%08lx-%08lx]\n", - map, map->count, vma->vm_start, vma->vm_end); - - map->count++; -} - -static void videobuf_vm_close(struct vm_area_struct *vma) -{ - struct videobuf_mapping *map = vma->vm_private_data; - struct videobuf_queue *q = map->q; - int i; - - dev_dbg(q->dev, "vm_close %p [count=%u,vma=%08lx-%08lx]\n", - map, map->count, vma->vm_start, vma->vm_end); - - map->count--; - if (0 == map->count) { - struct videobuf_dma_contig_memory *mem; - - dev_dbg(q->dev, "munmap %p q=%p\n", map, q); - videobuf_queue_lock(q); - - /* We need first to cancel streams, before unmapping */ - if (q->streaming) - videobuf_queue_cancel(q); - - for (i = 0; i < VIDEO_MAX_FRAME; i++) { - if (NULL == q->bufs[i]) - continue; - - if (q->bufs[i]->map != map) - continue; - - mem = q->bufs[i]->priv; - if (mem) { - /* This callback is called only if kernel has - allocated memory and this memory is mmapped. - In this case, memory should be freed, - in order to do memory unmap. - */ - - MAGIC_CHECK(mem->magic, MAGIC_DC_MEM); - - /* vfree is not atomic - can't be - called with IRQ's disabled - */ - dev_dbg(q->dev, "buf[%d] freeing %p\n", - i, mem->vaddr); - - __videobuf_dc_free(q->dev, mem); - mem->vaddr = NULL; - } - - q->bufs[i]->map = NULL; - q->bufs[i]->baddr = 0; - } - - kfree(map); - - videobuf_queue_unlock(q); - } -} - -static const struct vm_operations_struct videobuf_vm_ops = { - .open = videobuf_vm_open, - .close = videobuf_vm_close, -}; - -/** - * videobuf_dma_contig_user_put() - reset pointer to user space buffer - * @mem: per-buffer private videobuf-dma-contig data - * - * This function resets the user space pointer - */ -static void videobuf_dma_contig_user_put(struct videobuf_dma_contig_memory *mem) -{ - mem->dma_handle = 0; - mem->size = 0; -} - -/** - * videobuf_dma_contig_user_get() - setup user space memory pointer - * @mem: per-buffer private videobuf-dma-contig data - * @vb: video buffer to map - * - * This function validates and sets up a pointer to user space memory. - * Only physically contiguous pfn-mapped memory is accepted. - * - * Returns 0 if successful. - */ -static int videobuf_dma_contig_user_get(struct videobuf_dma_contig_memory *mem, - struct videobuf_buffer *vb) -{ - unsigned long untagged_baddr = untagged_addr(vb->baddr); - struct mm_struct *mm = current->mm; - struct vm_area_struct *vma; - unsigned long prev_pfn, this_pfn; - unsigned long pages_done, user_address; - unsigned int offset; - int ret; - - offset = untagged_baddr & ~PAGE_MASK; - mem->size = PAGE_ALIGN(vb->size + offset); - ret = -EINVAL; - - mmap_read_lock(mm); - - vma = find_vma(mm, untagged_baddr); - if (!vma) - goto out_up; - - if ((untagged_baddr + mem->size) > vma->vm_end) - goto out_up; - - pages_done = 0; - prev_pfn = 0; /* kill warning */ - user_address = untagged_baddr; - - while (pages_done < (mem->size >> PAGE_SHIFT)) { - ret = follow_pfn(vma, user_address, &this_pfn); - if (ret) - break; - - if (pages_done == 0) - mem->dma_handle = (this_pfn << PAGE_SHIFT) + offset; - else if (this_pfn != (prev_pfn + 1)) - ret = -EFAULT; - - if (ret) - break; - - prev_pfn = this_pfn; - user_address += PAGE_SIZE; - pages_done++; - } - -out_up: - mmap_read_unlock(current->mm); - - return ret; -} - -static struct videobuf_buffer *__videobuf_alloc(size_t size) -{ - struct videobuf_dma_contig_memory *mem; - struct videobuf_buffer *vb; - - vb = kzalloc(size + sizeof(*mem), GFP_KERNEL); - if (vb) { - vb->priv = ((char *)vb) + size; - mem = vb->priv; - mem->magic = MAGIC_DC_MEM; - } - - return vb; -} - -static void *__videobuf_to_vaddr(struct videobuf_buffer *buf) -{ - struct videobuf_dma_contig_memory *mem = buf->priv; - - BUG_ON(!mem); - MAGIC_CHECK(mem->magic, MAGIC_DC_MEM); - - return mem->vaddr; -} - -static int __videobuf_iolock(struct videobuf_queue *q, - struct videobuf_buffer *vb, - struct v4l2_framebuffer *fbuf) -{ - struct videobuf_dma_contig_memory *mem = vb->priv; - - BUG_ON(!mem); - MAGIC_CHECK(mem->magic, MAGIC_DC_MEM); - - switch (vb->memory) { - case V4L2_MEMORY_MMAP: - dev_dbg(q->dev, "%s memory method MMAP\n", __func__); - - /* All handling should be done by __videobuf_mmap_mapper() */ - if (!mem->vaddr) { - dev_err(q->dev, "memory is not allocated/mmapped.\n"); - return -EINVAL; - } - break; - case V4L2_MEMORY_USERPTR: - dev_dbg(q->dev, "%s memory method USERPTR\n", __func__); - - /* handle pointer from user space */ - if (vb->baddr) - return videobuf_dma_contig_user_get(mem, vb); - - /* allocate memory for the read() method */ - if (__videobuf_dc_alloc(q->dev, mem, PAGE_ALIGN(vb->size))) - return -ENOMEM; - break; - case V4L2_MEMORY_OVERLAY: - default: - dev_dbg(q->dev, "%s memory method OVERLAY/unknown\n", __func__); - return -EINVAL; - } - - return 0; -} - -static int __videobuf_mmap_mapper(struct videobuf_queue *q, - struct videobuf_buffer *buf, - struct vm_area_struct *vma) -{ - struct videobuf_dma_contig_memory *mem; - struct videobuf_mapping *map; - int retval; - - dev_dbg(q->dev, "%s\n", __func__); - - /* create mapping + update buffer list */ - map = kzalloc(sizeof(struct videobuf_mapping), GFP_KERNEL); - if (!map) - return -ENOMEM; - - buf->map = map; - map->q = q; - - buf->baddr = vma->vm_start; - - mem = buf->priv; - BUG_ON(!mem); - MAGIC_CHECK(mem->magic, MAGIC_DC_MEM); - - if (__videobuf_dc_alloc(q->dev, mem, PAGE_ALIGN(buf->bsize))) - goto error; - - /* the "vm_pgoff" is just used in v4l2 to find the - * corresponding buffer data structure which is allocated - * earlier and it does not mean the offset from the physical - * buffer start address as usual. So set it to 0 to pass - * the sanity check in dma_mmap_coherent(). - */ - vma->vm_pgoff = 0; - retval = dma_mmap_coherent(q->dev, vma, mem->vaddr, mem->dma_handle, - mem->size); - if (retval) { - dev_err(q->dev, "mmap: remap failed with error %d. ", - retval); - dma_free_coherent(q->dev, mem->size, - mem->vaddr, mem->dma_handle); - goto error; - } - - vma->vm_ops = &videobuf_vm_ops; - vm_flags_set(vma, VM_DONTEXPAND); - vma->vm_private_data = map; - - dev_dbg(q->dev, "mmap %p: q=%p %08lx-%08lx (%lx) pgoff %08lx buf %d\n", - map, q, vma->vm_start, vma->vm_end, - (long int)buf->bsize, vma->vm_pgoff, buf->i); - - videobuf_vm_open(vma); - - return 0; - -error: - kfree(map); - return -ENOMEM; -} - -static struct videobuf_qtype_ops qops = { - .magic = MAGIC_QTYPE_OPS, - .alloc_vb = __videobuf_alloc, - .iolock = __videobuf_iolock, - .mmap_mapper = __videobuf_mmap_mapper, - .vaddr = __videobuf_to_vaddr, -}; - -void videobuf_queue_dma_contig_init(struct videobuf_queue *q, - const struct videobuf_queue_ops *ops, - struct device *dev, - spinlock_t *irqlock, - enum v4l2_buf_type type, - enum v4l2_field field, - unsigned int msize, - void *priv, - struct mutex *ext_lock) -{ - videobuf_queue_core_init(q, ops, dev, irqlock, type, field, msize, - priv, &qops, ext_lock); -} -EXPORT_SYMBOL_GPL(videobuf_queue_dma_contig_init); - -dma_addr_t videobuf_to_dma_contig(struct videobuf_buffer *buf) -{ - struct videobuf_dma_contig_memory *mem = buf->priv; - - BUG_ON(!mem); - MAGIC_CHECK(mem->magic, MAGIC_DC_MEM); - - return mem->dma_handle; -} -EXPORT_SYMBOL_GPL(videobuf_to_dma_contig); - -void videobuf_dma_contig_free(struct videobuf_queue *q, - struct videobuf_buffer *buf) -{ - struct videobuf_dma_contig_memory *mem = buf->priv; - - /* mmapped memory can't be freed here, otherwise mmapped region - would be released, while still needed. In this case, the memory - release should happen inside videobuf_vm_close(). - So, it should free memory only if the memory were allocated for - read() operation. - */ - if (buf->memory != V4L2_MEMORY_USERPTR) - return; - - if (!mem) - return; - - MAGIC_CHECK(mem->magic, MAGIC_DC_MEM); - - /* handle user space pointer case */ - if (buf->baddr) { - videobuf_dma_contig_user_put(mem); - return; - } - - /* read() method */ - if (mem->vaddr) { - __videobuf_dc_free(q->dev, mem); - mem->vaddr = NULL; - } -} -EXPORT_SYMBOL_GPL(videobuf_dma_contig_free); - -MODULE_DESCRIPTION("helper module to manage video4linux dma contig buffers"); -MODULE_AUTHOR("Magnus Damm"); -MODULE_LICENSE("GPL"); diff --git a/drivers/media/v4l2-core/videobuf-dma-sg.c b/drivers/media/v4l2-core/videobuf-dma-sg.c deleted file mode 100644 index 405b89ea1054..000000000000 --- a/drivers/media/v4l2-core/videobuf-dma-sg.c +++ /dev/null @@ -1,681 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * helper functions for SG DMA video4linux capture buffers - * - * The functions expect the hardware being able to scatter gather - * (i.e. the buffers are not linear in physical memory, but fragmented - * into PAGE_SIZE chunks). They also assume the driver does not need - * to touch the video data. - * - * (c) 2007 Mauro Carvalho Chehab, - * - * Highly based on video-buf written originally by: - * (c) 2001,02 Gerd Knorr - * (c) 2006 Mauro Carvalho Chehab, - * (c) 2006 Ted Walther and John Sokol - */ - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include - -#define MAGIC_DMABUF 0x19721112 -#define MAGIC_SG_MEM 0x17890714 - -#define MAGIC_CHECK(is, should) \ - if (unlikely((is) != (should))) { \ - printk(KERN_ERR "magic mismatch: %x (expected %x)\n", \ - is, should); \ - BUG(); \ - } - -static int debug; -module_param(debug, int, 0644); - -MODULE_DESCRIPTION("helper module to manage video4linux dma sg buffers"); -MODULE_AUTHOR("Mauro Carvalho Chehab "); -MODULE_LICENSE("GPL"); - -#define dprintk(level, fmt, arg...) \ - if (debug >= level) \ - printk(KERN_DEBUG "vbuf-sg: " fmt , ## arg) - -/* --------------------------------------------------------------------- */ - -/* - * Return a scatterlist for some page-aligned vmalloc()'ed memory - * block (NULL on errors). Memory for the scatterlist is allocated - * using kmalloc. The caller must free the memory. - */ -static struct scatterlist *videobuf_vmalloc_to_sg(unsigned char *virt, - int nr_pages) -{ - struct scatterlist *sglist; - struct page *pg; - int i; - - sglist = vzalloc(array_size(nr_pages, sizeof(*sglist))); - if (NULL == sglist) - return NULL; - sg_init_table(sglist, nr_pages); - for (i = 0; i < nr_pages; i++, virt += PAGE_SIZE) { - pg = vmalloc_to_page(virt); - if (NULL == pg) - goto err; - BUG_ON(PageHighMem(pg)); - sg_set_page(&sglist[i], pg, PAGE_SIZE, 0); - } - return sglist; - -err: - vfree(sglist); - return NULL; -} - -/* - * Return a scatterlist for a an array of userpages (NULL on errors). - * Memory for the scatterlist is allocated using kmalloc. The caller - * must free the memory. - */ -static struct scatterlist *videobuf_pages_to_sg(struct page **pages, - int nr_pages, int offset, size_t size) -{ - struct scatterlist *sglist; - int i; - - if (NULL == pages[0]) - return NULL; - sglist = vmalloc(array_size(nr_pages, sizeof(*sglist))); - if (NULL == sglist) - return NULL; - sg_init_table(sglist, nr_pages); - - if (PageHighMem(pages[0])) - /* DMA to highmem pages might not work */ - goto highmem; - sg_set_page(&sglist[0], pages[0], - min_t(size_t, PAGE_SIZE - offset, size), offset); - size -= min_t(size_t, PAGE_SIZE - offset, size); - for (i = 1; i < nr_pages; i++) { - if (NULL == pages[i]) - goto nopage; - if (PageHighMem(pages[i])) - goto highmem; - sg_set_page(&sglist[i], pages[i], min_t(size_t, PAGE_SIZE, size), 0); - size -= min_t(size_t, PAGE_SIZE, size); - } - return sglist; - -nopage: - dprintk(2, "sgl: oops - no page\n"); - vfree(sglist); - return NULL; - -highmem: - dprintk(2, "sgl: oops - highmem page\n"); - vfree(sglist); - return NULL; -} - -/* --------------------------------------------------------------------- */ - -struct videobuf_dmabuf *videobuf_to_dma(struct videobuf_buffer *buf) -{ - struct videobuf_dma_sg_memory *mem = buf->priv; - BUG_ON(!mem); - - MAGIC_CHECK(mem->magic, MAGIC_SG_MEM); - - return &mem->dma; -} -EXPORT_SYMBOL_GPL(videobuf_to_dma); - -static void videobuf_dma_init(struct videobuf_dmabuf *dma) -{ - memset(dma, 0, sizeof(*dma)); - dma->magic = MAGIC_DMABUF; -} - -static int videobuf_dma_init_user_locked(struct videobuf_dmabuf *dma, - int direction, unsigned long data, unsigned long size) -{ - unsigned int gup_flags = FOLL_LONGTERM; - unsigned long first, last; - int err; - - dma->direction = direction; - switch (dma->direction) { - case DMA_FROM_DEVICE: - gup_flags |= FOLL_WRITE; - break; - case DMA_TO_DEVICE: - break; - default: - BUG(); - } - - first = (data & PAGE_MASK) >> PAGE_SHIFT; - last = ((data+size-1) & PAGE_MASK) >> PAGE_SHIFT; - dma->offset = data & ~PAGE_MASK; - dma->size = size; - dma->nr_pages = last-first+1; - dma->pages = kmalloc_array(dma->nr_pages, sizeof(struct page *), - GFP_KERNEL); - if (NULL == dma->pages) - return -ENOMEM; - - dprintk(1, "init user [0x%lx+0x%lx => %lu pages]\n", - data, size, dma->nr_pages); - - err = pin_user_pages(data & PAGE_MASK, dma->nr_pages, gup_flags, - dma->pages); - - if (err != dma->nr_pages) { - dma->nr_pages = (err >= 0) ? err : 0; - dprintk(1, "pin_user_pages: err=%d [%lu]\n", err, - dma->nr_pages); - return err < 0 ? err : -EINVAL; - } - return 0; -} - -static int videobuf_dma_init_user(struct videobuf_dmabuf *dma, int direction, - unsigned long data, unsigned long size) -{ - int ret; - - mmap_read_lock(current->mm); - ret = videobuf_dma_init_user_locked(dma, direction, data, size); - mmap_read_unlock(current->mm); - - return ret; -} - -static int videobuf_dma_init_kernel(struct videobuf_dmabuf *dma, int direction, - unsigned long nr_pages) -{ - int i; - - dprintk(1, "init kernel [%lu pages]\n", nr_pages); - - dma->direction = direction; - dma->vaddr_pages = kcalloc(nr_pages, sizeof(*dma->vaddr_pages), - GFP_KERNEL); - if (!dma->vaddr_pages) - return -ENOMEM; - - dma->dma_addr = kcalloc(nr_pages, sizeof(*dma->dma_addr), GFP_KERNEL); - if (!dma->dma_addr) { - kfree(dma->vaddr_pages); - return -ENOMEM; - } - for (i = 0; i < nr_pages; i++) { - void *addr; - - addr = dma_alloc_coherent(dma->dev, PAGE_SIZE, - &(dma->dma_addr[i]), GFP_KERNEL); - if (addr == NULL) - goto out_free_pages; - - dma->vaddr_pages[i] = virt_to_page(addr); - } - dma->vaddr = vmap(dma->vaddr_pages, nr_pages, VM_MAP | VM_IOREMAP, - PAGE_KERNEL); - if (NULL == dma->vaddr) { - dprintk(1, "vmalloc_32(%lu pages) failed\n", nr_pages); - goto out_free_pages; - } - - dprintk(1, "vmalloc is at addr %p, size=%lu\n", - dma->vaddr, nr_pages << PAGE_SHIFT); - - memset(dma->vaddr, 0, nr_pages << PAGE_SHIFT); - dma->nr_pages = nr_pages; - - return 0; -out_free_pages: - while (i > 0) { - void *addr; - - i--; - addr = page_address(dma->vaddr_pages[i]); - dma_free_coherent(dma->dev, PAGE_SIZE, addr, dma->dma_addr[i]); - } - kfree(dma->dma_addr); - dma->dma_addr = NULL; - kfree(dma->vaddr_pages); - dma->vaddr_pages = NULL; - - return -ENOMEM; - -} - -static int videobuf_dma_init_overlay(struct videobuf_dmabuf *dma, int direction, - dma_addr_t addr, unsigned long nr_pages) -{ - dprintk(1, "init overlay [%lu pages @ bus 0x%lx]\n", - nr_pages, (unsigned long)addr); - dma->direction = direction; - - if (0 == addr) - return -EINVAL; - - dma->bus_addr = addr; - dma->nr_pages = nr_pages; - - return 0; -} - -static int videobuf_dma_map(struct device *dev, struct videobuf_dmabuf *dma) -{ - MAGIC_CHECK(dma->magic, MAGIC_DMABUF); - BUG_ON(0 == dma->nr_pages); - - if (dma->pages) { - dma->sglist = videobuf_pages_to_sg(dma->pages, dma->nr_pages, - dma->offset, dma->size); - } - if (dma->vaddr) { - dma->sglist = videobuf_vmalloc_to_sg(dma->vaddr, - dma->nr_pages); - } - if (dma->bus_addr) { - dma->sglist = vmalloc(sizeof(*dma->sglist)); - if (NULL != dma->sglist) { - dma->sglen = 1; - sg_dma_address(&dma->sglist[0]) = dma->bus_addr - & PAGE_MASK; - dma->sglist[0].offset = dma->bus_addr & ~PAGE_MASK; - sg_dma_len(&dma->sglist[0]) = dma->nr_pages * PAGE_SIZE; - } - } - if (NULL == dma->sglist) { - dprintk(1, "scatterlist is NULL\n"); - return -ENOMEM; - } - if (!dma->bus_addr) { - dma->sglen = dma_map_sg(dev, dma->sglist, - dma->nr_pages, dma->direction); - if (0 == dma->sglen) { - printk(KERN_WARNING - "%s: videobuf_map_sg failed\n", __func__); - vfree(dma->sglist); - dma->sglist = NULL; - dma->sglen = 0; - return -ENOMEM; - } - } - - return 0; -} - -int videobuf_dma_unmap(struct device *dev, struct videobuf_dmabuf *dma) -{ - MAGIC_CHECK(dma->magic, MAGIC_DMABUF); - - if (!dma->sglen) - return 0; - - dma_unmap_sg(dev, dma->sglist, dma->nr_pages, dma->direction); - - vfree(dma->sglist); - dma->sglist = NULL; - dma->sglen = 0; - - return 0; -} -EXPORT_SYMBOL_GPL(videobuf_dma_unmap); - -int videobuf_dma_free(struct videobuf_dmabuf *dma) -{ - int i; - MAGIC_CHECK(dma->magic, MAGIC_DMABUF); - BUG_ON(dma->sglen); - - if (dma->pages) { - unpin_user_pages_dirty_lock(dma->pages, dma->nr_pages, - dma->direction == DMA_FROM_DEVICE); - kfree(dma->pages); - dma->pages = NULL; - } - - if (dma->dma_addr) { - for (i = 0; i < dma->nr_pages; i++) { - void *addr; - - addr = page_address(dma->vaddr_pages[i]); - dma_free_coherent(dma->dev, PAGE_SIZE, addr, - dma->dma_addr[i]); - } - kfree(dma->dma_addr); - dma->dma_addr = NULL; - kfree(dma->vaddr_pages); - dma->vaddr_pages = NULL; - vunmap(dma->vaddr); - dma->vaddr = NULL; - } - - if (dma->bus_addr) - dma->bus_addr = 0; - dma->direction = DMA_NONE; - - return 0; -} -EXPORT_SYMBOL_GPL(videobuf_dma_free); - -/* --------------------------------------------------------------------- */ - -static void videobuf_vm_open(struct vm_area_struct *vma) -{ - struct videobuf_mapping *map = vma->vm_private_data; - - dprintk(2, "vm_open %p [count=%d,vma=%08lx-%08lx]\n", map, - map->count, vma->vm_start, vma->vm_end); - - map->count++; -} - -static void videobuf_vm_close(struct vm_area_struct *vma) -{ - struct videobuf_mapping *map = vma->vm_private_data; - struct videobuf_queue *q = map->q; - struct videobuf_dma_sg_memory *mem; - int i; - - dprintk(2, "vm_close %p [count=%d,vma=%08lx-%08lx]\n", map, - map->count, vma->vm_start, vma->vm_end); - - map->count--; - if (0 == map->count) { - dprintk(1, "munmap %p q=%p\n", map, q); - videobuf_queue_lock(q); - for (i = 0; i < VIDEO_MAX_FRAME; i++) { - if (NULL == q->bufs[i]) - continue; - mem = q->bufs[i]->priv; - if (!mem) - continue; - - MAGIC_CHECK(mem->magic, MAGIC_SG_MEM); - - if (q->bufs[i]->map != map) - continue; - q->bufs[i]->map = NULL; - q->bufs[i]->baddr = 0; - q->ops->buf_release(q, q->bufs[i]); - } - videobuf_queue_unlock(q); - kfree(map); - } -} - -/* - * Get a anonymous page for the mapping. Make sure we can DMA to that - * memory location with 32bit PCI devices (i.e. don't use highmem for - * now ...). Bounce buffers don't work very well for the data rates - * video capture has. - */ -static vm_fault_t videobuf_vm_fault(struct vm_fault *vmf) -{ - struct vm_area_struct *vma = vmf->vma; - struct page *page; - - dprintk(3, "fault: fault @ %08lx [vma %08lx-%08lx]\n", - vmf->address, vma->vm_start, vma->vm_end); - - page = alloc_page(GFP_USER | __GFP_DMA32); - if (!page) - return VM_FAULT_OOM; - clear_user_highpage(page, vmf->address); - vmf->page = page; - - return 0; -} - -static const struct vm_operations_struct videobuf_vm_ops = { - .open = videobuf_vm_open, - .close = videobuf_vm_close, - .fault = videobuf_vm_fault, -}; - -/* --------------------------------------------------------------------- - * SG handlers for the generic methods - */ - -/* Allocated area consists on 3 parts: - struct video_buffer - struct _buffer (cx88_buffer, saa7134_buf, ...) - struct videobuf_dma_sg_memory - */ - -static struct videobuf_buffer *__videobuf_alloc_vb(size_t size) -{ - struct videobuf_dma_sg_memory *mem; - struct videobuf_buffer *vb; - - vb = kzalloc(size + sizeof(*mem), GFP_KERNEL); - if (!vb) - return vb; - - mem = vb->priv = ((char *)vb) + size; - mem->magic = MAGIC_SG_MEM; - - videobuf_dma_init(&mem->dma); - - dprintk(1, "%s: allocated at %p(%ld+%ld) & %p(%ld)\n", - __func__, vb, (long)sizeof(*vb), (long)size - sizeof(*vb), - mem, (long)sizeof(*mem)); - - return vb; -} - -static void *__videobuf_to_vaddr(struct videobuf_buffer *buf) -{ - struct videobuf_dma_sg_memory *mem = buf->priv; - BUG_ON(!mem); - - MAGIC_CHECK(mem->magic, MAGIC_SG_MEM); - - return mem->dma.vaddr; -} - -static int __videobuf_iolock(struct videobuf_queue *q, - struct videobuf_buffer *vb, - struct v4l2_framebuffer *fbuf) -{ - struct videobuf_dma_sg_memory *mem = vb->priv; - unsigned long pages; - dma_addr_t bus; - int err; - - BUG_ON(!mem); - - MAGIC_CHECK(mem->magic, MAGIC_SG_MEM); - - if (!mem->dma.dev) - mem->dma.dev = q->dev; - else - WARN_ON(mem->dma.dev != q->dev); - - switch (vb->memory) { - case V4L2_MEMORY_MMAP: - case V4L2_MEMORY_USERPTR: - if (0 == vb->baddr) { - /* no userspace addr -- kernel bounce buffer */ - pages = PAGE_ALIGN(vb->size) >> PAGE_SHIFT; - err = videobuf_dma_init_kernel(&mem->dma, - DMA_FROM_DEVICE, - pages); - if (0 != err) - return err; - } else if (vb->memory == V4L2_MEMORY_USERPTR) { - /* dma directly to userspace */ - err = videobuf_dma_init_user(&mem->dma, - DMA_FROM_DEVICE, - vb->baddr, vb->bsize); - if (0 != err) - return err; - } else { - /* NOTE: HACK: videobuf_iolock on V4L2_MEMORY_MMAP - buffers can only be called from videobuf_qbuf - we take current->mm->mmap_lock there, to prevent - locking inversion, so don't take it here */ - - err = videobuf_dma_init_user_locked(&mem->dma, - DMA_FROM_DEVICE, - vb->baddr, vb->bsize); - if (0 != err) - return err; - } - break; - case V4L2_MEMORY_OVERLAY: - if (NULL == fbuf) - return -EINVAL; - /* FIXME: need sanity checks for vb->boff */ - /* - * Using a double cast to avoid compiler warnings when - * building for PAE. Compiler doesn't like direct casting - * of a 32 bit ptr to 64 bit integer. - */ - bus = (dma_addr_t)(unsigned long)fbuf->base + vb->boff; - pages = PAGE_ALIGN(vb->size) >> PAGE_SHIFT; - err = videobuf_dma_init_overlay(&mem->dma, DMA_FROM_DEVICE, - bus, pages); - if (0 != err) - return err; - break; - default: - BUG(); - } - err = videobuf_dma_map(q->dev, &mem->dma); - if (0 != err) - return err; - - return 0; -} - -static int __videobuf_sync(struct videobuf_queue *q, - struct videobuf_buffer *buf) -{ - struct videobuf_dma_sg_memory *mem = buf->priv; - BUG_ON(!mem || !mem->dma.sglen); - - MAGIC_CHECK(mem->magic, MAGIC_SG_MEM); - MAGIC_CHECK(mem->dma.magic, MAGIC_DMABUF); - - dma_sync_sg_for_cpu(q->dev, mem->dma.sglist, - mem->dma.nr_pages, mem->dma.direction); - - return 0; -} - -static int __videobuf_mmap_mapper(struct videobuf_queue *q, - struct videobuf_buffer *buf, - struct vm_area_struct *vma) -{ - struct videobuf_dma_sg_memory *mem = buf->priv; - struct videobuf_mapping *map; - unsigned int first, last, size = 0, i; - int retval; - - retval = -EINVAL; - - BUG_ON(!mem); - MAGIC_CHECK(mem->magic, MAGIC_SG_MEM); - - /* look for first buffer to map */ - for (first = 0; first < VIDEO_MAX_FRAME; first++) { - if (buf == q->bufs[first]) { - size = PAGE_ALIGN(q->bufs[first]->bsize); - break; - } - } - - /* paranoia, should never happen since buf is always valid. */ - if (!size) { - dprintk(1, "mmap app bug: offset invalid [offset=0x%lx]\n", - (vma->vm_pgoff << PAGE_SHIFT)); - goto done; - } - - last = first; - - /* create mapping + update buffer list */ - retval = -ENOMEM; - map = kmalloc(sizeof(struct videobuf_mapping), GFP_KERNEL); - if (NULL == map) - goto done; - - size = 0; - for (i = first; i <= last; i++) { - if (NULL == q->bufs[i]) - continue; - q->bufs[i]->map = map; - q->bufs[i]->baddr = vma->vm_start + size; - size += PAGE_ALIGN(q->bufs[i]->bsize); - } - - map->count = 1; - map->q = q; - vma->vm_ops = &videobuf_vm_ops; - /* using shared anonymous pages */ - vm_flags_mod(vma, VM_DONTEXPAND | VM_DONTDUMP, VM_IO); - vma->vm_private_data = map; - dprintk(1, "mmap %p: q=%p %08lx-%08lx pgoff %08lx bufs %d-%d\n", - map, q, vma->vm_start, vma->vm_end, vma->vm_pgoff, first, last); - retval = 0; - -done: - return retval; -} - -static struct videobuf_qtype_ops sg_ops = { - .magic = MAGIC_QTYPE_OPS, - - .alloc_vb = __videobuf_alloc_vb, - .iolock = __videobuf_iolock, - .sync = __videobuf_sync, - .mmap_mapper = __videobuf_mmap_mapper, - .vaddr = __videobuf_to_vaddr, -}; - -void *videobuf_sg_alloc(size_t size) -{ - struct videobuf_queue q; - - /* Required to make generic handler to call __videobuf_alloc */ - q.int_ops = &sg_ops; - - q.msize = size; - - return videobuf_alloc_vb(&q); -} -EXPORT_SYMBOL_GPL(videobuf_sg_alloc); - -void videobuf_queue_sg_init(struct videobuf_queue *q, - const struct videobuf_queue_ops *ops, - struct device *dev, - spinlock_t *irqlock, - enum v4l2_buf_type type, - enum v4l2_field field, - unsigned int msize, - void *priv, - struct mutex *ext_lock) -{ - videobuf_queue_core_init(q, ops, dev, irqlock, type, field, msize, - priv, &sg_ops, ext_lock); -} -EXPORT_SYMBOL_GPL(videobuf_queue_sg_init); - diff --git a/drivers/media/v4l2-core/videobuf-vmalloc.c b/drivers/media/v4l2-core/videobuf-vmalloc.c deleted file mode 100644 index 85c7090606d6..000000000000 --- a/drivers/media/v4l2-core/videobuf-vmalloc.c +++ /dev/null @@ -1,326 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * helper functions for vmalloc video4linux capture buffers - * - * The functions expect the hardware being able to scatter gather - * (i.e. the buffers are not linear in physical memory, but fragmented - * into PAGE_SIZE chunks). They also assume the driver does not need - * to touch the video data. - * - * (c) 2007 Mauro Carvalho Chehab - */ - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include - -#define MAGIC_DMABUF 0x17760309 -#define MAGIC_VMAL_MEM 0x18221223 - -#define MAGIC_CHECK(is, should) \ - if (unlikely((is) != (should))) { \ - printk(KERN_ERR "magic mismatch: %x (expected %x)\n", \ - is, should); \ - BUG(); \ - } - -static int debug; -module_param(debug, int, 0644); - -MODULE_DESCRIPTION("helper module to manage video4linux vmalloc buffers"); -MODULE_AUTHOR("Mauro Carvalho Chehab "); -MODULE_LICENSE("GPL"); - -#define dprintk(level, fmt, arg...) \ - if (debug >= level) \ - printk(KERN_DEBUG "vbuf-vmalloc: " fmt , ## arg) - - -/***************************************************************************/ - -static void videobuf_vm_open(struct vm_area_struct *vma) -{ - struct videobuf_mapping *map = vma->vm_private_data; - - dprintk(2, "vm_open %p [count=%u,vma=%08lx-%08lx]\n", map, - map->count, vma->vm_start, vma->vm_end); - - map->count++; -} - -static void videobuf_vm_close(struct vm_area_struct *vma) -{ - struct videobuf_mapping *map = vma->vm_private_data; - struct videobuf_queue *q = map->q; - int i; - - dprintk(2, "vm_close %p [count=%u,vma=%08lx-%08lx]\n", map, - map->count, vma->vm_start, vma->vm_end); - - map->count--; - if (0 == map->count) { - struct videobuf_vmalloc_memory *mem; - - dprintk(1, "munmap %p q=%p\n", map, q); - videobuf_queue_lock(q); - - /* We need first to cancel streams, before unmapping */ - if (q->streaming) - videobuf_queue_cancel(q); - - for (i = 0; i < VIDEO_MAX_FRAME; i++) { - if (NULL == q->bufs[i]) - continue; - - if (q->bufs[i]->map != map) - continue; - - mem = q->bufs[i]->priv; - if (mem) { - /* This callback is called only if kernel has - allocated memory and this memory is mmapped. - In this case, memory should be freed, - in order to do memory unmap. - */ - - MAGIC_CHECK(mem->magic, MAGIC_VMAL_MEM); - - /* vfree is not atomic - can't be - called with IRQ's disabled - */ - dprintk(1, "%s: buf[%d] freeing (%p)\n", - __func__, i, mem->vaddr); - - vfree(mem->vaddr); - mem->vaddr = NULL; - } - - q->bufs[i]->map = NULL; - q->bufs[i]->baddr = 0; - } - - kfree(map); - - videobuf_queue_unlock(q); - } - - return; -} - -static const struct vm_operations_struct videobuf_vm_ops = { - .open = videobuf_vm_open, - .close = videobuf_vm_close, -}; - -/* --------------------------------------------------------------------- - * vmalloc handlers for the generic methods - */ - -/* Allocated area consists on 3 parts: - struct video_buffer - struct _buffer (cx88_buffer, saa7134_buf, ...) - struct videobuf_dma_sg_memory - */ - -static struct videobuf_buffer *__videobuf_alloc_vb(size_t size) -{ - struct videobuf_vmalloc_memory *mem; - struct videobuf_buffer *vb; - - vb = kzalloc(size + sizeof(*mem), GFP_KERNEL); - if (!vb) - return vb; - - mem = vb->priv = ((char *)vb) + size; - mem->magic = MAGIC_VMAL_MEM; - - dprintk(1, "%s: allocated at %p(%ld+%ld) & %p(%ld)\n", - __func__, vb, (long)sizeof(*vb), (long)size - sizeof(*vb), - mem, (long)sizeof(*mem)); - - return vb; -} - -static int __videobuf_iolock(struct videobuf_queue *q, - struct videobuf_buffer *vb, - struct v4l2_framebuffer *fbuf) -{ - struct videobuf_vmalloc_memory *mem = vb->priv; - int pages; - - BUG_ON(!mem); - - MAGIC_CHECK(mem->magic, MAGIC_VMAL_MEM); - - switch (vb->memory) { - case V4L2_MEMORY_MMAP: - dprintk(1, "%s memory method MMAP\n", __func__); - - /* All handling should be done by __videobuf_mmap_mapper() */ - if (!mem->vaddr) { - printk(KERN_ERR "memory is not allocated/mmapped.\n"); - return -EINVAL; - } - break; - case V4L2_MEMORY_USERPTR: - pages = PAGE_ALIGN(vb->size); - - dprintk(1, "%s memory method USERPTR\n", __func__); - - if (vb->baddr) { - printk(KERN_ERR "USERPTR is currently not supported\n"); - return -EINVAL; - } - - /* The only USERPTR currently supported is the one needed for - * read() method. - */ - - mem->vaddr = vmalloc_user(pages); - if (!mem->vaddr) { - printk(KERN_ERR "vmalloc (%d pages) failed\n", pages); - return -ENOMEM; - } - dprintk(1, "vmalloc is at addr %p (%d pages)\n", - mem->vaddr, pages); - break; - case V4L2_MEMORY_OVERLAY: - default: - dprintk(1, "%s memory method OVERLAY/unknown\n", __func__); - - /* Currently, doesn't support V4L2_MEMORY_OVERLAY */ - printk(KERN_ERR "Memory method currently unsupported.\n"); - return -EINVAL; - } - - return 0; -} - -static int __videobuf_mmap_mapper(struct videobuf_queue *q, - struct videobuf_buffer *buf, - struct vm_area_struct *vma) -{ - struct videobuf_vmalloc_memory *mem; - struct videobuf_mapping *map; - int retval, pages; - - dprintk(1, "%s\n", __func__); - - /* create mapping + update buffer list */ - map = kzalloc(sizeof(struct videobuf_mapping), GFP_KERNEL); - if (NULL == map) - return -ENOMEM; - - buf->map = map; - map->q = q; - - buf->baddr = vma->vm_start; - - mem = buf->priv; - BUG_ON(!mem); - MAGIC_CHECK(mem->magic, MAGIC_VMAL_MEM); - - pages = PAGE_ALIGN(vma->vm_end - vma->vm_start); - mem->vaddr = vmalloc_user(pages); - if (!mem->vaddr) { - printk(KERN_ERR "vmalloc (%d pages) failed\n", pages); - goto error; - } - dprintk(1, "vmalloc is at addr %p (%d pages)\n", mem->vaddr, pages); - - /* Try to remap memory */ - retval = remap_vmalloc_range(vma, mem->vaddr, 0); - if (retval < 0) { - printk(KERN_ERR "mmap: remap failed with error %d. ", retval); - vfree(mem->vaddr); - goto error; - } - - vma->vm_ops = &videobuf_vm_ops; - vm_flags_set(vma, VM_DONTEXPAND | VM_DONTDUMP); - vma->vm_private_data = map; - - dprintk(1, "mmap %p: q=%p %08lx-%08lx (%lx) pgoff %08lx buf %d\n", - map, q, vma->vm_start, vma->vm_end, - (long int)buf->bsize, - vma->vm_pgoff, buf->i); - - videobuf_vm_open(vma); - - return 0; - -error: - mem = NULL; - kfree(map); - return -ENOMEM; -} - -static struct videobuf_qtype_ops qops = { - .magic = MAGIC_QTYPE_OPS, - - .alloc_vb = __videobuf_alloc_vb, - .iolock = __videobuf_iolock, - .mmap_mapper = __videobuf_mmap_mapper, - .vaddr = videobuf_to_vmalloc, -}; - -void videobuf_queue_vmalloc_init(struct videobuf_queue *q, - const struct videobuf_queue_ops *ops, - struct device *dev, - spinlock_t *irqlock, - enum v4l2_buf_type type, - enum v4l2_field field, - unsigned int msize, - void *priv, - struct mutex *ext_lock) -{ - videobuf_queue_core_init(q, ops, dev, irqlock, type, field, msize, - priv, &qops, ext_lock); -} -EXPORT_SYMBOL_GPL(videobuf_queue_vmalloc_init); - -void *videobuf_to_vmalloc(struct videobuf_buffer *buf) -{ - struct videobuf_vmalloc_memory *mem = buf->priv; - BUG_ON(!mem); - MAGIC_CHECK(mem->magic, MAGIC_VMAL_MEM); - - return mem->vaddr; -} -EXPORT_SYMBOL_GPL(videobuf_to_vmalloc); - -void videobuf_vmalloc_free(struct videobuf_buffer *buf) -{ - struct videobuf_vmalloc_memory *mem = buf->priv; - - /* mmapped memory can't be freed here, otherwise mmapped region - would be released, while still needed. In this case, the memory - release should happen inside videobuf_vm_close(). - So, it should free memory only if the memory were allocated for - read() operation. - */ - if ((buf->memory != V4L2_MEMORY_USERPTR) || buf->baddr) - return; - - if (!mem) - return; - - MAGIC_CHECK(mem->magic, MAGIC_VMAL_MEM); - - vfree(mem->vaddr); - mem->vaddr = NULL; - - return; -} -EXPORT_SYMBOL_GPL(videobuf_vmalloc_free); - diff --git a/include/trace/events/pwc.h b/include/trace/events/pwc.h index a2da764a3b41..0543702542d9 100644 --- a/include/trace/events/pwc.h +++ b/include/trace/events/pwc.h @@ -26,7 +26,7 @@ TRACE_EVENT(pwc_handler_enter, __entry->urb__actual_length = urb->actual_length; __entry->fbuf__filled = (pdev->fill_buf ? pdev->fill_buf->filled : 0); - __assign_str(name, pdev->v4l2_dev.name); + __assign_str(name); ), TP_printk("dev=%s (fbuf=%p filled=%d) urb=%p (status=%d actual_length=%u)", __get_str(name), @@ -50,7 +50,7 @@ TRACE_EVENT(pwc_handler_exit, __entry->urb = urb; __entry->fbuf = pdev->fill_buf; __entry->fbuf__filled = pdev->fill_buf->filled; - __assign_str(name, pdev->v4l2_dev.name); + __assign_str(name); ), TP_printk(" dev=%s (fbuf=%p filled=%d) urb=%p", __get_str(name),