diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2018-08-15 18:29:14 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2018-08-15 18:29:14 -0700 |
commit | 71f3a82fab1b631ae9cb1feb677f498d4ca5007d (patch) | |
tree | f3b7fd0a62658d60b491c65cf8ab93378e322024 /drivers/staging/media | |
parent | 54dbe75bbf1e189982516de179147208e90b5e45 (diff) | |
parent | da2048b7348a0be92f706ac019e022139e29495e (diff) |
Merge tag 'media/v4.19-1' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media
Pull media updates from Mauro Carvalho Chehab:
- new Socionext MN88443x ISDB-S/T demodulator driver: mn88443x
- new sensor drivers: ak7375, ov2680 and rj54n1cb0c
- an old soc-camera sensor driver converted to the V4L2 framework:
mt9v111
- a new Voice-Coil Motor (VCM) driver: dw9807-vcm
- some cleanups at cx25821, removing legacy unused code
- some improvements at ddbridge driver
- new platform driver: vicodec
- some DVB API cleanups, removing ioctls and compat code for old
out-of-tree drivers that were never merged upstream
- improvements at DVB core to support frontents that support both
Satellite and non-satellite delivery systems
- got rid of the unused VIDIOC_RESERVED V4L2 ioctl
- some cleanups/improvements at gl861 ISDB driver
- several improvements on ov772x, ov7670 and ov5640, imx274, ov5645,
and smiapp sensor drivers
- fixes at em28xx to support dual TS devices
- some cleanups at V4L2/VB2 locking logic
- some API improvements at media controller
- some cec core and drivers improvements
- some uvcvideo improvements
- some improvements at platform drivers: stm32-dcmi, rcar-vin, coda,
reneseas-ceu, imx, vsp1, venus, camss
- lots of other cleanups and fixes
* tag 'media/v4.19-1' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media: (406 commits)
Revert "media: vivid: shut up warnings due to a non-trivial logic"
siano: get rid of an unused return code for debugfs register
media: isp: fix a warning about a wrong struct initializer
media: radio-wl1273: fix return code for the polling routine
media: s3c-camif: fix return code for the polling routine
media: saa7164: fix return codes for the polling routine
media: exynos-gsc: fix return code if mutex was interrupted
media: mt9v111: Fix build error with no VIDEO_V4L2_SUBDEV_API
media: xc4000: get rid of uneeded casts
media: drxj: get rid of uneeded casts
media: tuner-xc2028: don't use casts for printing sizes
media: cleanup fall-through comments
media: vivid: shut up warnings due to a non-trivial logic
media: rtl28xxu: be sure that it won't go past the array size
media: mt9v111: avoid going past the buffer
media: vsp1_dl: add a description for cmdpool field
media: sta2x11: add a missing parameter description
media: v4l2-mem2mem: add descriptions to MC fields
media: i2c: fix warning in Aptina MT9V111
media: imx: shut up a false positive warning
...
Diffstat (limited to 'drivers/staging/media')
-rw-r--r-- | drivers/staging/media/bcm2048/radio-bcm2048.c | 2 | ||||
-rw-r--r-- | drivers/staging/media/davinci_vpfe/vpfe_video.c | 6 | ||||
-rw-r--r-- | drivers/staging/media/davinci_vpfe/vpfe_video.h | 2 | ||||
-rw-r--r-- | drivers/staging/media/imx/imx-ic-prpencvf.c | 5 | ||||
-rw-r--r-- | drivers/staging/media/imx/imx-media-capture.c | 38 | ||||
-rw-r--r-- | drivers/staging/media/imx/imx-media-csi.c | 112 | ||||
-rw-r--r-- | drivers/staging/media/imx/imx-media-utils.c | 1 | ||||
-rw-r--r-- | drivers/staging/media/imx/imx-media.h | 2 |
8 files changed, 110 insertions, 58 deletions
diff --git a/drivers/staging/media/bcm2048/radio-bcm2048.c b/drivers/staging/media/bcm2048/radio-bcm2048.c index 06d1920150da..a90b2eb112f9 100644 --- a/drivers/staging/media/bcm2048/radio-bcm2048.c +++ b/drivers/staging/media/bcm2048/radio-bcm2048.c @@ -2175,7 +2175,7 @@ static int bcm2048_fops_release(struct file *file) } static __poll_t bcm2048_fops_poll(struct file *file, - struct poll_table_struct *pts) + struct poll_table_struct *pts) { struct bcm2048_device *bdev = video_drvdata(file); __poll_t retval = 0; diff --git a/drivers/staging/media/davinci_vpfe/vpfe_video.c b/drivers/staging/media/davinci_vpfe/vpfe_video.c index 390fc98d07dd..1269a983455e 100644 --- a/drivers/staging/media/davinci_vpfe/vpfe_video.c +++ b/drivers/staging/media/davinci_vpfe/vpfe_video.c @@ -1312,6 +1312,8 @@ static const struct vb2_ops video_qops = { .stop_streaming = vpfe_stop_streaming, .buf_cleanup = vpfe_buf_cleanup, .buf_queue = vpfe_buffer_queue, + .wait_prepare = vb2_ops_wait_prepare, + .wait_finish = vb2_ops_wait_finish, }; /* @@ -1357,6 +1359,7 @@ static int vpfe_reqbufs(struct file *file, void *priv, q->buf_struct_size = sizeof(struct vpfe_cap_buffer); q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC; q->dev = vpfe_dev->pdev; + q->lock = &video->lock; ret = vb2_queue_init(q); if (ret) { @@ -1598,17 +1601,18 @@ int vpfe_video_init(struct vpfe_video_device *video, const char *name) return -EINVAL; } /* Initialize field of video device */ + mutex_init(&video->lock); video->video_dev.release = video_device_release; video->video_dev.fops = &vpfe_fops; video->video_dev.ioctl_ops = &vpfe_ioctl_ops; video->video_dev.minor = -1; video->video_dev.tvnorms = 0; + video->video_dev.lock = &video->lock; snprintf(video->video_dev.name, sizeof(video->video_dev.name), "DAVINCI VIDEO %s %s", name, direction); spin_lock_init(&video->irqlock); spin_lock_init(&video->dma_queue_lock); - mutex_init(&video->lock); ret = media_entity_pads_init(&video->video_dev.entity, 1, &video->pad); if (ret < 0) diff --git a/drivers/staging/media/davinci_vpfe/vpfe_video.h b/drivers/staging/media/davinci_vpfe/vpfe_video.h index 22136d3dadcb..4bbd219e8329 100644 --- a/drivers/staging/media/davinci_vpfe/vpfe_video.h +++ b/drivers/staging/media/davinci_vpfe/vpfe_video.h @@ -128,7 +128,7 @@ struct vpfe_video_device { spinlock_t irqlock; /* IRQ lock for DMA queue */ spinlock_t dma_queue_lock; - /* lock used to access this structure */ + /* lock used to serialize all video4linux ioctls */ struct mutex lock; /* number of users performing IO */ u32 io_usrs; diff --git a/drivers/staging/media/imx/imx-ic-prpencvf.c b/drivers/staging/media/imx/imx-ic-prpencvf.c index ae453fd422f0..28f41caba05d 100644 --- a/drivers/staging/media/imx/imx-ic-prpencvf.c +++ b/drivers/staging/media/imx/imx-ic-prpencvf.c @@ -103,6 +103,7 @@ struct prp_priv { int nfb4eof_irq; int stream_count; + u32 frame_sequence; /* frame sequence counter */ bool last_eof; /* waiting for last EOF at stream off */ bool nfb4eof; /* NFB4EOF encountered during streaming */ struct completion last_eof_comp; @@ -210,12 +211,15 @@ static void prp_vb2_buf_done(struct prp_priv *priv, struct ipuv3_channel *ch) done = priv->active_vb2_buf[priv->ipu_buf_num]; if (done) { + done->vbuf.field = vdev->fmt.fmt.pix.field; + done->vbuf.sequence = priv->frame_sequence; vb = &done->vbuf.vb2_buf; vb->timestamp = ktime_get_ns(); vb2_buffer_done(vb, priv->nfb4eof ? VB2_BUF_STATE_ERROR : VB2_BUF_STATE_DONE); } + priv->frame_sequence++; priv->nfb4eof = false; /* get next queued buffer */ @@ -637,6 +641,7 @@ static int prp_start(struct prp_priv *priv) /* init EOF completion waitq */ init_completion(&priv->last_eof_comp); + priv->frame_sequence = 0; priv->last_eof = false; priv->nfb4eof = false; diff --git a/drivers/staging/media/imx/imx-media-capture.c b/drivers/staging/media/imx/imx-media-capture.c index 4e3fdf8aeef5..256039ce561e 100644 --- a/drivers/staging/media/imx/imx-media-capture.c +++ b/drivers/staging/media/imx/imx-media-capture.c @@ -170,23 +170,22 @@ static int capture_enum_fmt_vid_cap(struct file *file, void *fh, } cc_src = imx_media_find_ipu_format(fmt_src.format.code, CS_SEL_ANY); - if (!cc_src) - cc_src = imx_media_find_mbus_format(fmt_src.format.code, - CS_SEL_ANY, true); - if (!cc_src) - return -EINVAL; - - if (cc_src->bayer) { - if (f->index != 0) - return -EINVAL; - fourcc = cc_src->fourcc; - } else { + if (cc_src) { u32 cs_sel = (cc_src->cs == IPUV3_COLORSPACE_YUV) ? CS_SEL_YUV : CS_SEL_RGB; ret = imx_media_enum_format(&fourcc, f->index, cs_sel); if (ret) return ret; + } else { + cc_src = imx_media_find_mbus_format(fmt_src.format.code, + CS_SEL_ANY, true); + if (WARN_ON(!cc_src)) + return -EINVAL; + + if (f->index != 0) + return -EINVAL; + fourcc = cc_src->fourcc; } f->pixelformat = fourcc; @@ -219,15 +218,7 @@ static int capture_try_fmt_vid_cap(struct file *file, void *fh, return ret; cc_src = imx_media_find_ipu_format(fmt_src.format.code, CS_SEL_ANY); - if (!cc_src) - cc_src = imx_media_find_mbus_format(fmt_src.format.code, - CS_SEL_ANY, true); - if (!cc_src) - return -EINVAL; - - if (cc_src->bayer) { - cc = cc_src; - } else { + if (cc_src) { u32 fourcc, cs_sel; cs_sel = (cc_src->cs == IPUV3_COLORSPACE_YUV) ? @@ -239,6 +230,13 @@ static int capture_try_fmt_vid_cap(struct file *file, void *fh, imx_media_enum_format(&fourcc, 0, cs_sel); cc = imx_media_find_format(fourcc, cs_sel, false); } + } else { + cc_src = imx_media_find_mbus_format(fmt_src.format.code, + CS_SEL_ANY, true); + if (WARN_ON(!cc_src)) + return -EINVAL; + + cc = cc_src; } imx_media_mbus_fmt_to_pix_fmt(&f->fmt.pix, &fmt_src.format, cc); diff --git a/drivers/staging/media/imx/imx-media-csi.c b/drivers/staging/media/imx/imx-media-csi.c index 95d7805f3485..cd2c291e1e94 100644 --- a/drivers/staging/media/imx/imx-media-csi.c +++ b/drivers/staging/media/imx/imx-media-csi.c @@ -111,6 +111,7 @@ struct csi_priv { struct v4l2_ctrl_handler ctrl_hdlr; int stream_count; /* streaming counter */ + u32 frame_sequence; /* frame sequence counter */ bool last_eof; /* waiting for last EOF at stream off */ bool nfb4eof; /* NFB4EOF encountered during streaming */ struct completion last_eof_comp; @@ -121,10 +122,32 @@ static inline struct csi_priv *sd_to_dev(struct v4l2_subdev *sdev) return container_of(sdev, struct csi_priv, sd); } +static inline bool is_parallel_bus(struct v4l2_fwnode_endpoint *ep) +{ + return ep->bus_type != V4L2_MBUS_CSI2; +} + static inline bool is_parallel_16bit_bus(struct v4l2_fwnode_endpoint *ep) { - return ep->bus_type != V4L2_MBUS_CSI2 && - ep->bus.parallel.bus_width >= 16; + return is_parallel_bus(ep) && ep->bus.parallel.bus_width >= 16; +} + +/* + * Check for conditions that require the IPU to handle the + * data internally as generic data, aka passthrough mode: + * - raw bayer media bus formats, or + * - the CSI is receiving from a 16-bit parallel bus, or + * - the CSI is receiving from an 8-bit parallel bus and the incoming + * media bus format is other than UYVY8_2X8/YUYV8_2X8. + */ +static inline bool requires_passthrough(struct v4l2_fwnode_endpoint *ep, + struct v4l2_mbus_framefmt *infmt, + const struct imx_media_pixfmt *incc) +{ + return incc->bayer || is_parallel_16bit_bus(ep) || + (is_parallel_bus(ep) && + infmt->code != MEDIA_BUS_FMT_UYVY8_2X8 && + infmt->code != MEDIA_BUS_FMT_YUYV8_2X8); } /* @@ -236,12 +259,15 @@ static void csi_vb2_buf_done(struct csi_priv *priv) done = priv->active_vb2_buf[priv->ipu_buf_num]; if (done) { + done->vbuf.field = vdev->fmt.fmt.pix.field; + done->vbuf.sequence = priv->frame_sequence; vb = &done->vbuf.vb2_buf; vb->timestamp = ktime_get_ns(); vb2_buffer_done(vb, priv->nfb4eof ? VB2_BUF_STATE_ERROR : VB2_BUF_STATE_DONE); } + priv->frame_sequence++; priv->nfb4eof = false; /* get next queued buffer */ @@ -367,15 +393,18 @@ static void csi_idmac_unsetup_vb2_buf(struct csi_priv *priv, static int csi_idmac_setup_channel(struct csi_priv *priv) { struct imx_media_video_dev *vdev = priv->vdev; + const struct imx_media_pixfmt *incc; struct v4l2_mbus_framefmt *infmt; struct ipu_image image; u32 passthrough_bits; + u32 passthrough_cycles; dma_addr_t phys[2]; bool passthrough; u32 burst_size; int ret; infmt = &priv->format_mbus[CSI_SINK_PAD]; + incc = priv->cc[CSI_SINK_PAD]; ipu_cpmem_zero(priv->idmac_ch); @@ -389,12 +418,9 @@ static int csi_idmac_setup_channel(struct csi_priv *priv) image.phys0 = phys[0]; image.phys1 = phys[1]; - /* - * Check for conditions that require the IPU to handle the - * data internally as generic data, aka passthrough mode: - * - raw bayer formats - * - the CSI is receiving from a 16-bit parallel bus - */ + passthrough = requires_passthrough(&priv->upstream_ep, infmt, incc); + passthrough_cycles = 1; + switch (image.pix.pixelformat) { case V4L2_PIX_FMT_SBGGR8: case V4L2_PIX_FMT_SGBRG8: @@ -402,7 +428,6 @@ static int csi_idmac_setup_channel(struct csi_priv *priv) case V4L2_PIX_FMT_SRGGB8: case V4L2_PIX_FMT_GREY: burst_size = 16; - passthrough = true; passthrough_bits = 8; break; case V4L2_PIX_FMT_SBGGR16: @@ -411,7 +436,6 @@ static int csi_idmac_setup_channel(struct csi_priv *priv) case V4L2_PIX_FMT_SRGGB16: case V4L2_PIX_FMT_Y16: burst_size = 8; - passthrough = true; passthrough_bits = 16; break; case V4L2_PIX_FMT_YUV420: @@ -419,7 +443,6 @@ static int csi_idmac_setup_channel(struct csi_priv *priv) burst_size = (image.pix.width & 0x3f) ? ((image.pix.width & 0x1f) ? ((image.pix.width & 0xf) ? 8 : 16) : 32) : 64; - passthrough = is_parallel_16bit_bus(&priv->upstream_ep); passthrough_bits = 16; /* Skip writing U and V components to odd rows */ ipu_cpmem_skip_odd_chroma_rows(priv->idmac_ch); @@ -428,18 +451,25 @@ static int csi_idmac_setup_channel(struct csi_priv *priv) case V4L2_PIX_FMT_UYVY: burst_size = (image.pix.width & 0x1f) ? ((image.pix.width & 0xf) ? 8 : 16) : 32; - passthrough = is_parallel_16bit_bus(&priv->upstream_ep); passthrough_bits = 16; break; + case V4L2_PIX_FMT_RGB565: + if (passthrough) { + burst_size = 16; + passthrough_bits = 8; + passthrough_cycles = incc->cycles; + break; + } + /* fallthrough - non-passthrough RGB565 (CSI-2 bus) */ default: burst_size = (image.pix.width & 0xf) ? 8 : 16; - passthrough = is_parallel_16bit_bus(&priv->upstream_ep); passthrough_bits = 16; break; } if (passthrough) { - ipu_cpmem_set_resolution(priv->idmac_ch, image.rect.width, + ipu_cpmem_set_resolution(priv->idmac_ch, + image.rect.width * passthrough_cycles, image.rect.height); ipu_cpmem_set_stride(priv->idmac_ch, image.pix.bytesperline); ipu_cpmem_set_buffer(priv->idmac_ch, 0, image.phys0); @@ -545,6 +575,7 @@ static int csi_idmac_start(struct csi_priv *priv) /* init EOF completion waitq */ init_completion(&priv->last_eof_comp); + priv->frame_sequence = 0; priv->last_eof = false; priv->nfb4eof = false; @@ -630,17 +661,20 @@ static void csi_idmac_stop(struct csi_priv *priv) static int csi_setup(struct csi_priv *priv) { struct v4l2_mbus_framefmt *infmt, *outfmt; + const struct imx_media_pixfmt *incc; struct v4l2_mbus_config mbus_cfg; struct v4l2_mbus_framefmt if_fmt; + struct v4l2_rect crop; infmt = &priv->format_mbus[CSI_SINK_PAD]; + incc = priv->cc[CSI_SINK_PAD]; outfmt = &priv->format_mbus[priv->active_output_pad]; /* compose mbus_config from the upstream endpoint */ mbus_cfg.type = priv->upstream_ep.bus_type; - mbus_cfg.flags = (priv->upstream_ep.bus_type == V4L2_MBUS_CSI2) ? - priv->upstream_ep.bus.mipi_csi2.flags : - priv->upstream_ep.bus.parallel.flags; + mbus_cfg.flags = is_parallel_bus(&priv->upstream_ep) ? + priv->upstream_ep.bus.parallel.flags : + priv->upstream_ep.bus.mipi_csi2.flags; /* * we need to pass input frame to CSI interface, but @@ -648,8 +682,18 @@ static int csi_setup(struct csi_priv *priv) */ if_fmt = *infmt; if_fmt.field = outfmt->field; + crop = priv->crop; - ipu_csi_set_window(priv->csi, &priv->crop); + /* + * if cycles is set, we need to handle this over multiple cycles as + * generic/bayer data + */ + if (is_parallel_bus(&priv->upstream_ep) && incc->cycles) { + if_fmt.width *= incc->cycles; + crop.width *= incc->cycles; + } + + ipu_csi_set_window(priv->csi, &crop); ipu_csi_set_downsize(priv->csi, priv->crop.width == 2 * priv->compose.width, @@ -1007,7 +1051,6 @@ static int csi_link_validate(struct v4l2_subdev *sd, { struct csi_priv *priv = v4l2_get_subdevdata(sd); struct v4l2_fwnode_endpoint upstream_ep = {}; - const struct imx_media_pixfmt *incc; bool is_csi2; int ret; @@ -1025,17 +1068,7 @@ static int csi_link_validate(struct v4l2_subdev *sd, mutex_lock(&priv->lock); priv->upstream_ep = upstream_ep; - is_csi2 = (upstream_ep.bus_type == V4L2_MBUS_CSI2); - incc = priv->cc[CSI_SINK_PAD]; - - if (priv->dest != IPU_CSI_DEST_IDMAC && - (incc->bayer || is_parallel_16bit_bus(&upstream_ep))) { - v4l2_err(&priv->sd, - "bayer/16-bit parallel buses must go to IDMAC pad\n"); - ret = -EINVAL; - goto out; - } - + is_csi2 = !is_parallel_bus(&upstream_ep); if (is_csi2) { int vc_num = 0; /* @@ -1059,7 +1092,7 @@ static int csi_link_validate(struct v4l2_subdev *sd, /* select either parallel or MIPI-CSI2 as input to CSI */ ipu_set_csi_src_mux(priv->ipu, priv->csi_id, is_csi2); -out: + mutex_unlock(&priv->lock); return ret; } @@ -1131,6 +1164,7 @@ static int csi_enum_mbus_code(struct v4l2_subdev *sd, struct v4l2_subdev_mbus_code_enum *code) { struct csi_priv *priv = v4l2_get_subdevdata(sd); + struct v4l2_fwnode_endpoint upstream_ep; const struct imx_media_pixfmt *incc; struct v4l2_mbus_framefmt *infmt; int ret = 0; @@ -1147,7 +1181,13 @@ static int csi_enum_mbus_code(struct v4l2_subdev *sd, break; case CSI_SRC_PAD_DIRECT: case CSI_SRC_PAD_IDMAC: - if (incc->bayer) { + ret = csi_get_upstream_endpoint(priv, &upstream_ep); + if (ret) { + v4l2_err(&priv->sd, "failed to find upstream endpoint\n"); + goto out; + } + + if (requires_passthrough(&upstream_ep, infmt, incc)) { if (code->index != 0) { ret = -EINVAL; goto out; @@ -1192,10 +1232,12 @@ static int csi_enum_frame_size(struct v4l2_subdev *sd, } else { crop = __csi_get_crop(priv, cfg, fse->which); - fse->min_width = fse->max_width = fse->index & 1 ? + fse->min_width = fse->index & 1 ? crop->width / 2 : crop->width; - fse->min_height = fse->max_height = fse->index & 2 ? + fse->max_width = fse->min_width; + fse->min_height = fse->index & 2 ? crop->height / 2 : crop->height; + fse->max_height = fse->min_height; } mutex_unlock(&priv->lock); @@ -1286,7 +1328,7 @@ static void csi_try_fmt(struct csi_priv *priv, sdformat->format.width = compose->width; sdformat->format.height = compose->height; - if (incc->bayer) { + if (requires_passthrough(upstream_ep, infmt, incc)) { sdformat->format.code = infmt->code; *cc = incc; } else { diff --git a/drivers/staging/media/imx/imx-media-utils.c b/drivers/staging/media/imx/imx-media-utils.c index 7ec2db84451c..8aa13403b09d 100644 --- a/drivers/staging/media/imx/imx-media-utils.c +++ b/drivers/staging/media/imx/imx-media-utils.c @@ -78,6 +78,7 @@ static const struct imx_media_pixfmt rgb_formats[] = { .codes = {MEDIA_BUS_FMT_RGB565_2X8_LE}, .cs = IPUV3_COLORSPACE_RGB, .bpp = 16, + .cycles = 2, }, { .fourcc = V4L2_PIX_FMT_RGB24, .codes = { diff --git a/drivers/staging/media/imx/imx-media.h b/drivers/staging/media/imx/imx-media.h index e945e0ed6dd6..57bd094cf765 100644 --- a/drivers/staging/media/imx/imx-media.h +++ b/drivers/staging/media/imx/imx-media.h @@ -62,6 +62,8 @@ struct imx_media_pixfmt { u32 fourcc; u32 codes[4]; int bpp; /* total bpp */ + /* cycles per pixel for generic (bayer) formats for the parallel bus */ + int cycles; enum ipu_color_space cs; bool planar; /* is a planar format */ bool bayer; /* is a raw bayer format */ |