diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2014-08-06 03:36:30 +0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-08-06 03:36:30 +0400 |
commit | f4d33337eac4007793ca11fd1ab68d91ce7aa762 (patch) | |
tree | b775ad213179822225a3e1c1a27e4cc16f8aff68 /drivers/media/usb/em28xx/em28xx-video.c | |
parent | 91c2ff7708d4edf73ef1f0abb3ea4a44b4b0cf1d (diff) | |
parent | 0f3bf3dc1ca394a8385079a5653088672b65c5c4 (diff) | |
download | linux-f4d33337eac4007793ca11fd1ab68d91ce7aa762.tar.xz |
Merge branch 'v4l_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media
Pull media updates from Mauro Carvalho Chehab:
- removal of sn9c102. This device driver was replaced a long time ago
by gspca
- solo6x10 and go7007 webcam drivers moved from staging into
mainstream. They were waiting for an API to allow setting the image
detection matrix
- SDR drivers moved from staging into mainstream: sdr-msi3101 (renamed
as msi2500) and rtl2832
- added SDR driver for airspy
- added demux driver: si2165
- rework at several RC subsystem, making the code for RC-5 SZ variant
to be added at the standard RC5 decoder
- added decoder for the XMP IR protocol
- tuner driver moved from staging into mainstream: msi3101 (renamed as
msi001)
- added documentation for some additional SDR pixfmt
- some device tree bindings documented
- added support for exynos3250 at s5p-jpeg
- remove the obsolete, unmaintained and broken mx1_camera driver
- added support for remote controllers at au0828 driver
- added a RC driver: sunxi-cir
- several driver fixes, enhancements and cleanups.
* 'v4l_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media: (455 commits)
[media] cx23885: fix UNSET/TUNER_ABSENT confusion
[media] coda: fix build error by making reset control optional
[media] radio-miropcm20: fix sparse NULL pointer warning
[media] MAINTAINERS: Update go7007 pattern
[media] MAINTAINERS: Update solo6x10 patterns
[media] media: atmel-isi: add primary DT support
[media] media: atmel-isi: convert the pdata from pointer to structure
[media] media: atmel-isi: add v4l2 async probe support
[media] rcar_vin: add devicetree support
[media] media: pxa_camera device-tree support
[media] media: mt9m111: add device-tree suppport
[media] soc_camera: add support for dt binding soc_camera drivers
[media] media: soc_camera: pxa_camera documentation device-tree support
[media] media: mt9m111: add device-tree documentation
[media] s5p-mfc: remove unnecessary calling to function video_devdata()
[media] s5p-jpeg: add chroma subsampling adjustment for Exynos3250
[media] s5p-jpeg: Prevent erroneous downscaling for Exynos3250 SoC
[media] s5p-jpeg: Assure proper crop rectangle initialization
[media] s5p-jpeg: fix g_selection op
[media] s5p-jpeg: Adjust jpeg_bound_align_image to Exynos3250 needs
...
Diffstat (limited to 'drivers/media/usb/em28xx/em28xx-video.c')
-rw-r--r-- | drivers/media/usb/em28xx/em28xx-video.c | 116 |
1 files changed, 46 insertions, 70 deletions
diff --git a/drivers/media/usb/em28xx/em28xx-video.c b/drivers/media/usb/em28xx/em28xx-video.c index f6b49c98e2c9..90dec2955f1c 100644 --- a/drivers/media/usb/em28xx/em28xx-video.c +++ b/drivers/media/usb/em28xx/em28xx-video.c @@ -1227,8 +1227,7 @@ static void scale_to_size(struct em28xx *dev, static int vidioc_g_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *f) { - struct em28xx_fh *fh = priv; - struct em28xx *dev = fh->dev; + struct em28xx *dev = video_drvdata(file); struct em28xx_v4l2 *v4l2 = dev->v4l2; f->fmt.pix.width = v4l2->width; @@ -1261,8 +1260,7 @@ static struct em28xx_fmt *format_by_fourcc(unsigned int fourcc) static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *f) { - struct em28xx_fh *fh = priv; - struct em28xx *dev = fh->dev; + struct em28xx *dev = video_drvdata(file); struct em28xx_v4l2 *v4l2 = dev->v4l2; unsigned int width = f->fmt.pix.width; unsigned int height = f->fmt.pix.height; @@ -1355,8 +1353,7 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, static int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *norm) { - struct em28xx_fh *fh = priv; - struct em28xx *dev = fh->dev; + struct em28xx *dev = video_drvdata(file); *norm = dev->v4l2->norm; @@ -1365,8 +1362,7 @@ static int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *norm) static int vidioc_querystd(struct file *file, void *priv, v4l2_std_id *norm) { - struct em28xx_fh *fh = priv; - struct em28xx *dev = fh->dev; + struct em28xx *dev = video_drvdata(file); v4l2_device_call_all(&dev->v4l2->v4l2_dev, 0, video, querystd, norm); @@ -1375,8 +1371,7 @@ static int vidioc_querystd(struct file *file, void *priv, v4l2_std_id *norm) static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id norm) { - struct em28xx_fh *fh = priv; - struct em28xx *dev = fh->dev; + struct em28xx *dev = video_drvdata(file); struct em28xx_v4l2 *v4l2 = dev->v4l2; struct v4l2_format f; @@ -1408,8 +1403,7 @@ static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id norm) static int vidioc_g_parm(struct file *file, void *priv, struct v4l2_streamparm *p) { - struct em28xx_fh *fh = priv; - struct em28xx *dev = fh->dev; + struct em28xx *dev = video_drvdata(file); struct em28xx_v4l2 *v4l2 = dev->v4l2; int rc = 0; @@ -1427,8 +1421,7 @@ static int vidioc_g_parm(struct file *file, void *priv, static int vidioc_s_parm(struct file *file, void *priv, struct v4l2_streamparm *p) { - struct em28xx_fh *fh = priv; - struct em28xx *dev = fh->dev; + struct em28xx *dev = video_drvdata(file); p->parm.capture.readbuffers = EM28XX_MIN_BUF; return v4l2_device_call_until_err(&dev->v4l2->v4l2_dev, @@ -1450,8 +1443,7 @@ static const char *iname[] = { static int vidioc_enum_input(struct file *file, void *priv, struct v4l2_input *i) { - struct em28xx_fh *fh = priv; - struct em28xx *dev = fh->dev; + struct em28xx *dev = video_drvdata(file); unsigned int n; n = i->index; @@ -1479,8 +1471,7 @@ static int vidioc_enum_input(struct file *file, void *priv, static int vidioc_g_input(struct file *file, void *priv, unsigned int *i) { - struct em28xx_fh *fh = priv; - struct em28xx *dev = fh->dev; + struct em28xx *dev = video_drvdata(file); *i = dev->ctl_input; @@ -1489,8 +1480,7 @@ static int vidioc_g_input(struct file *file, void *priv, unsigned int *i) static int vidioc_s_input(struct file *file, void *priv, unsigned int i) { - struct em28xx_fh *fh = priv; - struct em28xx *dev = fh->dev; + struct em28xx *dev = video_drvdata(file); if (i >= MAX_EM28XX_INPUT) return -EINVAL; @@ -1503,8 +1493,7 @@ static int vidioc_s_input(struct file *file, void *priv, unsigned int i) static int vidioc_g_audio(struct file *file, void *priv, struct v4l2_audio *a) { - struct em28xx_fh *fh = priv; - struct em28xx *dev = fh->dev; + struct em28xx *dev = video_drvdata(file); switch (a->index) { case EM28XX_AMUX_VIDEO: @@ -1543,8 +1532,7 @@ static int vidioc_g_audio(struct file *file, void *priv, struct v4l2_audio *a) static int vidioc_s_audio(struct file *file, void *priv, const struct v4l2_audio *a) { - struct em28xx_fh *fh = priv; - struct em28xx *dev = fh->dev; + struct em28xx *dev = video_drvdata(file); if (a->index >= MAX_EM28XX_INPUT) return -EINVAL; @@ -1563,8 +1551,7 @@ static int vidioc_s_audio(struct file *file, void *priv, const struct v4l2_audio static int vidioc_g_tuner(struct file *file, void *priv, struct v4l2_tuner *t) { - struct em28xx_fh *fh = priv; - struct em28xx *dev = fh->dev; + struct em28xx *dev = video_drvdata(file); if (0 != t->index) return -EINVAL; @@ -1578,8 +1565,7 @@ static int vidioc_g_tuner(struct file *file, void *priv, static int vidioc_s_tuner(struct file *file, void *priv, const struct v4l2_tuner *t) { - struct em28xx_fh *fh = priv; - struct em28xx *dev = fh->dev; + struct em28xx *dev = video_drvdata(file); if (0 != t->index) return -EINVAL; @@ -1591,8 +1577,7 @@ static int vidioc_s_tuner(struct file *file, void *priv, static int vidioc_g_frequency(struct file *file, void *priv, struct v4l2_frequency *f) { - struct em28xx_fh *fh = priv; - struct em28xx *dev = fh->dev; + struct em28xx *dev = video_drvdata(file); struct em28xx_v4l2 *v4l2 = dev->v4l2; if (0 != f->tuner) @@ -1606,8 +1591,7 @@ static int vidioc_s_frequency(struct file *file, void *priv, const struct v4l2_frequency *f) { struct v4l2_frequency new_freq = *f; - struct em28xx_fh *fh = priv; - struct em28xx *dev = fh->dev; + struct em28xx *dev = video_drvdata(file); struct em28xx_v4l2 *v4l2 = dev->v4l2; if (0 != f->tuner) @@ -1624,8 +1608,7 @@ static int vidioc_s_frequency(struct file *file, void *priv, static int vidioc_g_chip_info(struct file *file, void *priv, struct v4l2_dbg_chip_info *chip) { - struct em28xx_fh *fh = priv; - struct em28xx *dev = fh->dev; + struct em28xx *dev = video_drvdata(file); if (chip->match.addr > 1) return -EINVAL; @@ -1652,8 +1635,7 @@ static int em28xx_reg_len(int reg) static int vidioc_g_register(struct file *file, void *priv, struct v4l2_dbg_register *reg) { - struct em28xx_fh *fh = priv; - struct em28xx *dev = fh->dev; + struct em28xx *dev = video_drvdata(file); int ret; if (reg->match.addr > 1) @@ -1693,8 +1675,7 @@ static int vidioc_g_register(struct file *file, void *priv, static int vidioc_s_register(struct file *file, void *priv, const struct v4l2_dbg_register *reg) { - struct em28xx_fh *fh = priv; - struct em28xx *dev = fh->dev; + struct em28xx *dev = video_drvdata(file); __le16 buf; if (reg->match.addr > 1) @@ -1715,8 +1696,7 @@ static int vidioc_querycap(struct file *file, void *priv, struct v4l2_capability *cap) { struct video_device *vdev = video_devdata(file); - struct em28xx_fh *fh = priv; - struct em28xx *dev = fh->dev; + struct em28xx *dev = video_drvdata(file); struct em28xx_v4l2 *v4l2 = dev->v4l2; strlcpy(cap->driver, "em28xx", sizeof(cap->driver)); @@ -1761,8 +1741,7 @@ static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv, static int vidioc_enum_framesizes(struct file *file, void *priv, struct v4l2_frmsizeenum *fsize) { - struct em28xx_fh *fh = priv; - struct em28xx *dev = fh->dev; + struct em28xx *dev = video_drvdata(file); struct em28xx_fmt *fmt; unsigned int maxw = norm_maxw(dev); unsigned int maxh = norm_maxh(dev); @@ -1806,8 +1785,7 @@ static int vidioc_enum_framesizes(struct file *file, void *priv, static int vidioc_g_fmt_vbi_cap(struct file *file, void *priv, struct v4l2_format *format) { - struct em28xx_fh *fh = priv; - struct em28xx *dev = fh->dev; + struct em28xx *dev = video_drvdata(file); struct em28xx_v4l2 *v4l2 = dev->v4l2; format->fmt.vbi.samples_per_line = v4l2->vbi_width; @@ -1840,7 +1818,7 @@ static int vidioc_g_fmt_vbi_cap(struct file *file, void *priv, static int radio_g_tuner(struct file *file, void *priv, struct v4l2_tuner *t) { - struct em28xx *dev = ((struct em28xx_fh *)priv)->dev; + struct em28xx *dev = video_drvdata(file); if (unlikely(t->index > 0)) return -EINVAL; @@ -1855,7 +1833,7 @@ static int radio_g_tuner(struct file *file, void *priv, static int radio_s_tuner(struct file *file, void *priv, const struct v4l2_tuner *t) { - struct em28xx *dev = ((struct em28xx_fh *)priv)->dev; + struct em28xx *dev = video_drvdata(file); if (0 != t->index) return -EINVAL; @@ -1890,7 +1868,7 @@ static int em28xx_v4l2_open(struct file *filp) struct em28xx *dev = video_drvdata(filp); struct em28xx_v4l2 *v4l2 = dev->v4l2; enum v4l2_buf_type fh_type = 0; - struct em28xx_fh *fh; + int ret; switch (vdev->vfl_type) { case VFL_TYPE_GRABBER: @@ -1905,24 +1883,23 @@ static int em28xx_v4l2_open(struct file *filp) return -EINVAL; } - em28xx_videodbg("open dev=%s type=%s users=%d\n", - video_device_node_name(vdev), v4l2_type_names[fh_type], - v4l2->users); + em28xx_videodbg("open dev=%s type=%s\n", + video_device_node_name(vdev), v4l2_type_names[fh_type]); if (mutex_lock_interruptible(&dev->lock)) return -ERESTARTSYS; - fh = kzalloc(sizeof(struct em28xx_fh), GFP_KERNEL); - if (!fh) { - em28xx_errdev("em28xx-video.c: Out of memory?!\n"); + + ret = v4l2_fh_open(filp); + if (ret) { + em28xx_errdev("%s: v4l2_fh_open() returned error %d\n", + __func__, ret); mutex_unlock(&dev->lock); - return -ENOMEM; + return ret; } - v4l2_fh_init(&fh->fh, vdev); - fh->dev = dev; - fh->type = fh_type; - filp->private_data = fh; - if (v4l2->users == 0) { + if (v4l2_fh_is_singular_file(filp)) { + em28xx_videodbg("first opened filehandle, initializing device\n"); + em28xx_set_mode(dev, EM28XX_ANALOG_MODE); if (vdev->vfl_type != VFL_TYPE_RADIO) @@ -1933,6 +1910,8 @@ static int em28xx_v4l2_open(struct file *filp) * of some i2c devices */ em28xx_wake_i2c(dev); + } else { + em28xx_videodbg("further filehandles are already opened\n"); } if (vdev->vfl_type == VFL_TYPE_RADIO) { @@ -1942,10 +1921,8 @@ static int em28xx_v4l2_open(struct file *filp) kref_get(&dev->ref); kref_get(&v4l2->ref); - v4l2->users++; mutex_unlock(&dev->lock); - v4l2_fh_add(&fh->fh); return 0; } @@ -2046,17 +2023,15 @@ static int em28xx_v4l2_resume(struct em28xx *dev) */ static int em28xx_v4l2_close(struct file *filp) { - struct em28xx_fh *fh = filp->private_data; - struct em28xx *dev = fh->dev; + struct em28xx *dev = video_drvdata(filp); struct em28xx_v4l2 *v4l2 = dev->v4l2; int errCode; - em28xx_videodbg("users=%d\n", v4l2->users); - - vb2_fop_release(filp); mutex_lock(&dev->lock); - if (v4l2->users == 1) { + if (v4l2_fh_is_singular_file(filp)) { + em28xx_videodbg("last opened filehandle, shutting down device\n"); + /* No sense to try to write to the device */ if (dev->disconnected) goto exit; @@ -2075,10 +2050,12 @@ static int em28xx_v4l2_close(struct file *filp) em28xx_errdev("cannot change alternate number to " "0 (error=%i)\n", errCode); } + } else { + em28xx_videodbg("further opened filehandles left\n"); } exit: - v4l2->users--; + vb2_fop_release(filp); kref_put(&v4l2->ref, em28xx_free_v4l2); mutex_unlock(&dev->lock); kref_put(&dev->ref, em28xx_free_device); @@ -2208,7 +2185,6 @@ static struct video_device *em28xx_vdev_init(struct em28xx *dev, vfd->v4l2_dev = &dev->v4l2->v4l2_dev; vfd->debug = video_debug; vfd->lock = &dev->lock; - set_bit(V4L2_FL_USE_FH_PRIO, &vfd->flags); if (dev->board.is_webcam) vfd->tvnorms = 0; @@ -2552,7 +2528,7 @@ static int em28xx_v4l2_init(struct em28xx *dev) v4l2->vbi_dev->queue->lock = &v4l2->vb_vbi_queue_lock; /* disable inapplicable ioctls */ - v4l2_disable_ioctl(v4l2->vdev, VIDIOC_S_PARM); + v4l2_disable_ioctl(v4l2->vbi_dev, VIDIOC_S_PARM); if (dev->tuner_type == TUNER_ABSENT) { v4l2_disable_ioctl(v4l2->vbi_dev, VIDIOC_G_TUNER); v4l2_disable_ioctl(v4l2->vbi_dev, VIDIOC_S_TUNER); |