diff options
author | Mauro Carvalho Chehab <mchehab@kernel.org> | 2022-03-07 16:24:56 +0100 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@kernel.org> | 2022-03-07 16:25:17 +0100 |
commit | 8268d067508b0fb9988b5423a8539a21caba5f44 (patch) | |
tree | 8f4f14c72770488b070d2b62ed37d01d07c36c4c /drivers | |
parent | 8bd4aaf438e39f88e4321e0cad2d42284c2269af (diff) | |
parent | d8ebe298d008ccbae3011cbeb139707f01a730c8 (diff) |
Merge tag 'br-v5.18l' of git://linuxtv.org/hverkuil/media_tree into media_stage
Tag branch
* tag 'br-v5.18l' of git://linuxtv.org/hverkuil/media_tree: (39 commits)
media: imx-jpeg: Set V4L2_BUF_FLAG_LAST at eos
media: meson-ir-tx: remove incorrect doc comment
media: vivid: use time_is_after_jiffies() instead of open coding it
media: wl128x: use time_is_before_jiffies() instead of open coding it
media: tda8083: use time_is_after_jiffies() instead of open coding it
media: stv0299: use time_is_before_jiffies() instead of open coding it
media: si21xx: use time_is_before_jiffies() instead of open coding it
media: cedrus: h264: Fix neighbour info buffer size
media: cx88-mpeg: clear interrupt status register before streaming video
media: cedrus: H265: Fix neighbour info buffer size
media: fsl-viu: use GFP_KERNEL
media: cx18: use GFP_KERNEL
drivers: meson: vdec: add VP9 support to GXM
stkwebcam: add new Asus laptop to upside_down table
media: imx-jpeg: fix a bug of accessing array out of bounds
media: sun6i-csi: fix colorspace in sun6i_video_try_fmt()
media: usb: go7007: s2250-board: fix leak in probe()
media: cedrus: Add watchdog for job completion
pixfmt-yuv-planar.rst: fix typo: 'Cr, Cr' -> 'Cr, Cb'
media: imx-jpeg: Remove unnecessary print function dev_err()
...
Signed-off-by: Mauro Carvalho Chehab <mchehab@kernel.org>
Diffstat (limited to 'drivers')
41 files changed, 400 insertions, 358 deletions
diff --git a/drivers/media/dvb-frontends/si21xx.c b/drivers/media/dvb-frontends/si21xx.c index 001b23588389..2d29d2c4d434 100644 --- a/drivers/media/dvb-frontends/si21xx.c +++ b/drivers/media/dvb-frontends/si21xx.c @@ -336,7 +336,7 @@ static int si21xx_wait_diseqc_idle(struct si21xx_state *state, int timeout) dprintk("%s\n", __func__); while ((si21_readreg(state, LNB_CTRL_REG_1) & 0x8) == 8) { - if (jiffies - start > timeout) { + if (time_is_before_jiffies(start + timeout)) { dprintk("%s: timeout!!\n", __func__); return -ETIMEDOUT; } diff --git a/drivers/media/dvb-frontends/stv0299.c b/drivers/media/dvb-frontends/stv0299.c index 10e7cc8ffc43..b5263a0ee5aa 100644 --- a/drivers/media/dvb-frontends/stv0299.c +++ b/drivers/media/dvb-frontends/stv0299.c @@ -184,7 +184,7 @@ static int stv0299_wait_diseqc_fifo (struct stv0299_state* state, int timeout) dprintk ("%s\n", __func__); while (stv0299_readreg(state, 0x0a) & 1) { - if (jiffies - start > timeout) { + if (time_is_before_jiffies(start + timeout)) { dprintk ("%s: timeout!!\n", __func__); return -ETIMEDOUT; } @@ -201,7 +201,7 @@ static int stv0299_wait_diseqc_idle (struct stv0299_state* state, int timeout) dprintk ("%s\n", __func__); while ((stv0299_readreg(state, 0x0a) & 3) != 2 ) { - if (jiffies - start > timeout) { + if (time_is_before_jiffies(start + timeout)) { dprintk ("%s: timeout!!\n", __func__); return -ETIMEDOUT; } diff --git a/drivers/media/dvb-frontends/tda8083.c b/drivers/media/dvb-frontends/tda8083.c index 5be11fd65e3b..e3e1c3db2c85 100644 --- a/drivers/media/dvb-frontends/tda8083.c +++ b/drivers/media/dvb-frontends/tda8083.c @@ -162,7 +162,7 @@ static void tda8083_wait_diseqc_fifo (struct tda8083_state* state, int timeout) { unsigned long start = jiffies; - while (jiffies - start < timeout && + while (time_is_after_jiffies(start + timeout) && !(tda8083_readreg(state, 0x02) & 0x80)) { msleep(50); diff --git a/drivers/media/i2c/saa7115.c b/drivers/media/i2c/saa7115.c index a958bbc2c33d..15ff80e6301e 100644 --- a/drivers/media/i2c/saa7115.c +++ b/drivers/media/i2c/saa7115.c @@ -1129,7 +1129,7 @@ static void saa711x_set_lcr(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_forma static int saa711x_g_sliced_fmt(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_format *sliced) { - static u16 lcr2vbi[] = { + static const u16 lcr2vbi[] = { 0, V4L2_SLICED_TELETEXT_B, 0, /* 1 */ 0, V4L2_SLICED_CAPTION_525, /* 4 */ V4L2_SLICED_WSS_625, 0, /* 5 */ diff --git a/drivers/media/pci/cx18/cx18-driver.c b/drivers/media/pci/cx18/cx18-driver.c index 59497ba6bf1f..1be9672ae9d4 100644 --- a/drivers/media/pci/cx18/cx18-driver.c +++ b/drivers/media/pci/cx18/cx18-driver.c @@ -899,7 +899,7 @@ static int cx18_probe(struct pci_dev *pci_dev, return -ENOMEM; } - cx = kzalloc(sizeof(*cx), GFP_ATOMIC); + cx = kzalloc(sizeof(*cx), GFP_KERNEL); if (!cx) return -ENOMEM; diff --git a/drivers/media/pci/cx88/cx88-mpeg.c b/drivers/media/pci/cx88/cx88-mpeg.c index 680e1e3fe89b..2c1d5137ac47 100644 --- a/drivers/media/pci/cx88/cx88-mpeg.c +++ b/drivers/media/pci/cx88/cx88-mpeg.c @@ -162,6 +162,9 @@ int cx8802_start_dma(struct cx8802_dev *dev, cx_write(MO_TS_GPCNTRL, GP_COUNT_CONTROL_RESET); q->count = 0; + /* clear interrupt status register */ + cx_write(MO_TS_INTSTAT, 0x1f1111); + /* enable irqs */ dprintk(1, "setting the interrupt mask\n"); cx_set(MO_PCI_INTMSK, core->pci_irqmask | PCI_INT_TSINT); diff --git a/drivers/media/pci/saa7134/saa7134-video.c b/drivers/media/pci/saa7134/saa7134-video.c index 7bc4c7709f4d..48543ad3d595 100644 --- a/drivers/media/pci/saa7134/saa7134-video.c +++ b/drivers/media/pci/saa7134/saa7134-video.c @@ -1535,8 +1535,6 @@ int saa7134_s_std(struct file *file, void *priv, v4l2_std_id id) return -EINVAL; } - id = tvnorms[i].id; - if (!is_empress(file) && fh == dev->overlay_owner) { spin_lock_irqsave(&dev->slock, flags); stop_preview(dev); diff --git a/drivers/media/pci/saa7164/saa7164-cmd.c b/drivers/media/pci/saa7164/saa7164-cmd.c index a65d810ce212..42bd8e76005b 100644 --- a/drivers/media/pci/saa7164/saa7164-cmd.c +++ b/drivers/media/pci/saa7164/saa7164-cmd.c @@ -187,7 +187,6 @@ static int saa7164_cmd_set(struct saa7164_dev *dev, struct tmComResInfo *msg, mutex_lock(&dev->cmds[msg->id].lock); size = msg->size; - idx = 0; cmds = size / bus->m_wMaxReqSize; if (size % bus->m_wMaxReqSize == 0) cmds -= 1; diff --git a/drivers/media/platform/aspeed-video.c b/drivers/media/platform/aspeed-video.c index 51fb18453b81..b937dbcbe9e0 100644 --- a/drivers/media/platform/aspeed-video.c +++ b/drivers/media/platform/aspeed-video.c @@ -13,6 +13,7 @@ #include <linux/module.h> #include <linux/mutex.h> #include <linux/of.h> +#include <linux/of_device.h> #include <linux/of_irq.h> #include <linux/of_reserved_mem.h> #include <linux/platform_device.h> @@ -32,7 +33,8 @@ #include <media/v4l2-event.h> #include <media/v4l2-ioctl.h> #include <media/videobuf2-dma-contig.h> -#include <linux/videodev2.h> + +#define ASPEED_VIDEO_V4L2_MIN_BUF_REQ 3 #define DEVICE_NAME "aspeed-video" @@ -86,8 +88,6 @@ #define VE_CTRL_SOURCE BIT(2) #define VE_CTRL_INT_DE BIT(4) #define VE_CTRL_DIRECT_FETCH BIT(5) -#define VE_CTRL_YUV BIT(6) -#define VE_CTRL_RGB BIT(7) #define VE_CTRL_CAPTURE_FMT GENMASK(7, 6) #define VE_CTRL_AUTO_OR_CURSOR BIT(8) #define VE_CTRL_CLK_INVERSE BIT(11) @@ -153,9 +153,14 @@ #define VE_MODE_DETECT_STATUS 0x098 #define VE_MODE_DETECT_H_PERIOD GENMASK(11, 0) +#define VE_MODE_DETECT_EXTSRC_ADC BIT(12) +#define VE_MODE_DETECT_H_STABLE BIT(13) +#define VE_MODE_DETECT_V_STABLE BIT(14) #define VE_MODE_DETECT_V_LINES GENMASK(27, 16) #define VE_MODE_DETECT_STATUS_VSYNC BIT(28) #define VE_MODE_DETECT_STATUS_HSYNC BIT(29) +#define VE_MODE_DETECT_VSYNC_RDY BIT(30) +#define VE_MODE_DETECT_HSYNC_RDY BIT(31) #define VE_SYNC_STATUS 0x09c #define VE_SYNC_STATUS_HSYNC GENMASK(11, 0) @@ -178,9 +183,24 @@ #define VE_INTERRUPT_VSYNC_DESC BIT(11) #define VE_MODE_DETECT 0x30c +#define VE_MODE_DT_HOR_TOLER GENMASK(31, 28) +#define VE_MODE_DT_VER_TOLER GENMASK(27, 24) +#define VE_MODE_DT_HOR_STABLE GENMASK(23, 20) +#define VE_MODE_DT_VER_STABLE GENMASK(19, 16) +#define VE_MODE_DT_EDG_THROD GENMASK(15, 8) + #define VE_MEM_RESTRICT_START 0x310 #define VE_MEM_RESTRICT_END 0x314 +/* + * VIDEO_MODE_DETECT_DONE: a flag raised if signal lock + * VIDEO_RES_CHANGE: a flag raised if res_change work on-going + * VIDEO_RES_DETECT: a flag raised if res. detection on-going + * VIDEO_STREAMING: a flag raised if user requires stream-on + * VIDEO_FRAME_INPRG: a flag raised if hw working on a frame + * VIDEO_STOPPED: a flag raised if device release + * VIDEO_CLOCKS_ON: a flag raised if clk is on + */ enum { VIDEO_MODE_DETECT_DONE, VIDEO_RES_CHANGE, @@ -191,6 +211,15 @@ enum { VIDEO_CLOCKS_ON, }; +// for VE_CTRL_CAPTURE_FMT +enum aspeed_video_capture_format { + VIDEO_CAP_FMT_YUV_STUDIO_SWING = 0, + VIDEO_CAP_FMT_YUV_FULL_SWING, + VIDEO_CAP_FMT_RGB, + VIDEO_CAP_FMT_GRAY, + VIDEO_CAP_FMT_MAX +}; + struct aspeed_video_addr { unsigned int size; dma_addr_t dma; @@ -213,6 +242,25 @@ struct aspeed_video_perf { #define to_aspeed_video_buffer(x) \ container_of((x), struct aspeed_video_buffer, vb) +/* + * struct aspeed_video - driver data + * + * res_work: holds the delayed_work for res-detection if unlock + * buffers: holds the list of buffer queued from user + * flags: holds the state of video + * sequence: holds the last number of frame completed + * max_compressed_size: holds max compressed stream's size + * srcs: holds the buffer information for srcs + * jpeg: holds the buffer information for jpeg header + * yuv420: a flag raised if JPEG subsampling is 420 + * frame_rate: holds the frame_rate + * jpeg_quality: holds jpeq's quality (0~11) + * frame_bottom: end position of video data in vertical direction + * frame_left: start position of video data in horizontal direction + * frame_right: end position of video data in horizontal direction + * frame_top: start position of video data in vertical direction + * perf: holds the statistics primary for debugfs + */ struct aspeed_video { void __iomem *base; struct clk *eclk; @@ -903,6 +951,7 @@ static void aspeed_video_get_resolution(struct aspeed_video *video) bool invalid_resolution = true; int rc; int tries = 0; + u32 mds; u32 src_lr_edge; u32 src_tb_edge; struct v4l2_bt_timings *det = &video->detected_timings; @@ -933,6 +982,13 @@ static void aspeed_video_get_resolution(struct aspeed_video *video) return; } + mds = aspeed_video_read(video, VE_MODE_DETECT_STATUS); + // try detection again if current signal isn't stable + if (!(mds & VE_MODE_DETECT_H_STABLE) || + !(mds & VE_MODE_DETECT_V_STABLE) || + (mds & VE_MODE_DETECT_EXTSRC_ADC)) + continue; + aspeed_video_check_and_set_polarity(video); aspeed_video_enable_mode_detect(video); @@ -1070,7 +1126,8 @@ static void aspeed_video_init_regs(struct aspeed_video *video) u32 comp_ctrl = VE_COMP_CTRL_RSVD | FIELD_PREP(VE_COMP_CTRL_DCT_LUM, video->jpeg_quality) | FIELD_PREP(VE_COMP_CTRL_DCT_CHR, video->jpeg_quality | 0x10); - u32 ctrl = VE_CTRL_AUTO_OR_CURSOR; + u32 ctrl = VE_CTRL_AUTO_OR_CURSOR | + FIELD_PREP(VE_CTRL_CAPTURE_FMT, VIDEO_CAP_FMT_YUV_FULL_SWING); u32 seq_ctrl = video->jpeg_mode; if (video->frame_rate) @@ -1105,7 +1162,12 @@ static void aspeed_video_init_regs(struct aspeed_video *video) aspeed_video_write(video, VE_SCALING_FILTER3, 0x00200000); /* Set mode detection defaults */ - aspeed_video_write(video, VE_MODE_DETECT, 0x22666500); + aspeed_video_write(video, VE_MODE_DETECT, + FIELD_PREP(VE_MODE_DT_HOR_TOLER, 2) | + FIELD_PREP(VE_MODE_DT_VER_TOLER, 2) | + FIELD_PREP(VE_MODE_DT_HOR_STABLE, 6) | + FIELD_PREP(VE_MODE_DT_VER_STABLE, 6) | + FIELD_PREP(VE_MODE_DT_EDG_THROD, 0x65)); } static void aspeed_video_start(struct aspeed_video *video) @@ -1212,7 +1274,7 @@ static int aspeed_video_get_parm(struct file *file, void *fh, struct aspeed_video *video = video_drvdata(file); a->parm.capture.capability = V4L2_CAP_TIMEPERFRAME; - a->parm.capture.readbuffers = 3; + a->parm.capture.readbuffers = ASPEED_VIDEO_V4L2_MIN_BUF_REQ; a->parm.capture.timeperframe.numerator = 1; if (!video->frame_rate) a->parm.capture.timeperframe.denominator = MAX_FRAME_RATE; @@ -1229,7 +1291,7 @@ static int aspeed_video_set_parm(struct file *file, void *fh, struct aspeed_video *video = video_drvdata(file); a->parm.capture.capability = V4L2_CAP_TIMEPERFRAME; - a->parm.capture.readbuffers = 3; + a->parm.capture.readbuffers = ASPEED_VIDEO_V4L2_MIN_BUF_REQ; if (a->parm.capture.timeperframe.numerator) frame_rate = a->parm.capture.timeperframe.denominator / @@ -1781,7 +1843,7 @@ static int aspeed_video_setup_video(struct aspeed_video *video) vbq->drv_priv = video; vbq->buf_struct_size = sizeof(struct aspeed_video_buffer); vbq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC; - vbq->min_buffers_needed = 3; + vbq->min_buffers_needed = ASPEED_VIDEO_V4L2_MIN_BUF_REQ; rc = vb2_queue_init(vbq); if (rc) { @@ -1899,7 +1961,6 @@ MODULE_DEVICE_TABLE(of, aspeed_video_of_match); static int aspeed_video_probe(struct platform_device *pdev) { const struct aspeed_video_config *config; - const struct of_device_id *match; struct aspeed_video *video; int rc; @@ -1911,11 +1972,10 @@ static int aspeed_video_probe(struct platform_device *pdev) if (IS_ERR(video->base)) return PTR_ERR(video->base); - match = of_match_node(aspeed_video_of_match, pdev->dev.of_node); - if (!match) - return -EINVAL; + config = of_device_get_match_data(&pdev->dev); + if (!config) + return -ENODEV; - config = match->data; video->jpeg_mode = config->jpeg_mode; video->comp_size_read = config->comp_size_read; diff --git a/drivers/media/platform/fsl-viu.c b/drivers/media/platform/fsl-viu.c index a4bfa70b49b2..afc96f6db2a1 100644 --- a/drivers/media/platform/fsl-viu.c +++ b/drivers/media/platform/fsl-viu.c @@ -1407,7 +1407,7 @@ static int viu_of_probe(struct platform_device *op) } /* Prepare our private structure */ - viu_dev = devm_kzalloc(&op->dev, sizeof(struct viu_dev), GFP_ATOMIC); + viu_dev = devm_kzalloc(&op->dev, sizeof(struct viu_dev), GFP_KERNEL); if (!viu_dev) { dev_err(&op->dev, "Can't allocate private structure\n"); ret = -ENOMEM; diff --git a/drivers/media/platform/imx-jpeg/mxc-jpeg.c b/drivers/media/platform/imx-jpeg/mxc-jpeg.c index fed762491379..3b892c5792b4 100644 --- a/drivers/media/platform/imx-jpeg/mxc-jpeg.c +++ b/drivers/media/platform/imx-jpeg/mxc-jpeg.c @@ -954,7 +954,6 @@ static void mxc_jpeg_device_run(void *priv) jpeg_src_buf->jpeg_parse_error = true; } if (jpeg_src_buf->jpeg_parse_error) { - jpeg->slot_data[ctx->slot].used = false; v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx); v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx); v4l2_m2m_buf_done(src_buf, VB2_BUF_STATE_ERROR); @@ -998,6 +997,20 @@ end: spin_unlock_irqrestore(&ctx->mxc_jpeg->hw_lock, flags); } +static void mxc_jpeg_set_last_buffer_dequeued(struct mxc_jpeg_ctx *ctx) +{ + struct vb2_queue *q; + + ctx->stopped = 1; + q = v4l2_m2m_get_dst_vq(ctx->fh.m2m_ctx); + if (!list_empty(&q->done_list)) + return; + + q->last_buffer_dequeued = true; + wake_up(&q->done_wq); + ctx->stopped = 0; +} + static int mxc_jpeg_decoder_cmd(struct file *file, void *priv, struct v4l2_decoder_cmd *cmd) { @@ -1015,6 +1028,7 @@ static int mxc_jpeg_decoder_cmd(struct file *file, void *priv, if (v4l2_m2m_num_src_bufs_ready(fh->m2m_ctx) == 0) { /* No more src bufs, notify app EOS */ notify_eos(ctx); + mxc_jpeg_set_last_buffer_dequeued(ctx); } else { /* will send EOS later*/ ctx->stopping = 1; @@ -1041,6 +1055,7 @@ static int mxc_jpeg_encoder_cmd(struct file *file, void *priv, if (v4l2_m2m_num_src_bufs_ready(fh->m2m_ctx) == 0) { /* No more src bufs, notify app EOS */ notify_eos(ctx); + mxc_jpeg_set_last_buffer_dequeued(ctx); } else { /* will send EOS later*/ ctx->stopping = 1; @@ -1117,6 +1132,10 @@ static void mxc_jpeg_stop_streaming(struct vb2_queue *q) v4l2_m2m_buf_done(vbuf, VB2_BUF_STATE_ERROR); } pm_runtime_put_sync(&ctx->mxc_jpeg->pdev->dev); + if (V4L2_TYPE_IS_OUTPUT(q->type)) { + ctx->stopping = 0; + ctx->stopped = 0; + } } static int mxc_jpeg_valid_comp_id(struct device *dev, @@ -1408,12 +1427,29 @@ static int mxc_jpeg_buf_prepare(struct vb2_buffer *vb) return 0; } +static void mxc_jpeg_buf_finish(struct vb2_buffer *vb) +{ + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); + struct mxc_jpeg_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue); + struct vb2_queue *q = vb->vb2_queue; + + if (V4L2_TYPE_IS_OUTPUT(vb->type)) + return; + if (!ctx->stopped) + return; + if (list_empty(&q->done_list)) { + vbuf->flags |= V4L2_BUF_FLAG_LAST; + ctx->stopped = 0; + } +} + static const struct vb2_ops mxc_jpeg_qops = { .queue_setup = mxc_jpeg_queue_setup, .wait_prepare = vb2_ops_wait_prepare, .wait_finish = vb2_ops_wait_finish, .buf_out_validate = mxc_jpeg_buf_out_validate, .buf_prepare = mxc_jpeg_buf_prepare, + .buf_finish = mxc_jpeg_buf_finish, .start_streaming = mxc_jpeg_start_streaming, .stop_streaming = mxc_jpeg_stop_streaming, .buf_queue = mxc_jpeg_buf_queue, @@ -1849,14 +1885,14 @@ static int mxc_jpeg_dqbuf(struct file *file, void *priv, int ret; dev_dbg(dev, "DQBUF type=%d, index=%d", buf->type, buf->index); - if (ctx->stopping == 1 && num_src_ready == 0) { + if (ctx->stopping == 1 && num_src_ready == 0) { /* No more src bufs, notify app EOS */ notify_eos(ctx); ctx->stopping = 0; + mxc_jpeg_set_last_buffer_dequeued(ctx); } ret = v4l2_m2m_dqbuf(file, fh->m2m_ctx, buf); - return ret; } @@ -2022,7 +2058,6 @@ static int mxc_jpeg_probe(struct platform_device *pdev) for (slot = 0; slot < MXC_MAX_SLOTS; slot++) { dec_irq = platform_get_irq(pdev, slot); if (dec_irq < 0) { - dev_err(&pdev->dev, "Failed to get irq %d\n", dec_irq); ret = dec_irq; goto err_irq; } diff --git a/drivers/media/platform/imx-jpeg/mxc-jpeg.h b/drivers/media/platform/imx-jpeg/mxc-jpeg.h index 9fb2a5aaa941..f53f004ba851 100644 --- a/drivers/media/platform/imx-jpeg/mxc-jpeg.h +++ b/drivers/media/platform/imx-jpeg/mxc-jpeg.h @@ -91,6 +91,7 @@ struct mxc_jpeg_ctx { struct v4l2_fh fh; enum mxc_jpeg_enc_state enc_state; unsigned int stopping; + unsigned int stopped; unsigned int slot; }; diff --git a/drivers/media/platform/mtk-jpeg/mtk_jpeg_core.c b/drivers/media/platform/mtk-jpeg/mtk_jpeg_core.c index d532f86e826e..ab5485dfc20c 100644 --- a/drivers/media/platform/mtk-jpeg/mtk_jpeg_core.c +++ b/drivers/media/platform/mtk-jpeg/mtk_jpeg_core.c @@ -680,7 +680,7 @@ static int mtk_jpeg_buf_prepare(struct vb2_buffer *vb) { struct mtk_jpeg_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue); struct mtk_jpeg_q_data *q_data = NULL; - struct v4l2_plane_pix_format plane_fmt = {}; + struct v4l2_plane_pix_format plane_fmt; int i; q_data = mtk_jpeg_get_q_data(ctx, vb->vb2_queue->type); diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_drv.c b/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_drv.c index 8d11510e441e..48dad9bb13d2 100644 --- a/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_drv.c +++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_drv.c @@ -374,7 +374,7 @@ static int mtk_vcodec_probe(struct platform_device *pdev) if (IS_ERR((__force void *)dev->m2m_dev_dec)) { mtk_v4l2_err("Failed to init mem2mem dec device"); ret = PTR_ERR((__force void *)dev->m2m_dev_dec); - goto err_dec_mem_init; + goto err_dec_alloc; } dev->decode_workqueue = @@ -391,10 +391,16 @@ static int mtk_vcodec_probe(struct platform_device *pdev) &pdev->dev); if (ret) { mtk_v4l2_err("Main device of_platform_populate failed."); - goto err_event_workq; + goto err_reg_cont; } } + ret = video_register_device(vfd_dec, VFL_TYPE_VIDEO, -1); + if (ret) { + mtk_v4l2_err("Failed to register video device"); + goto err_reg_cont; + } + if (dev->vdec_pdata->uses_stateless_api) { dev->mdev_dec.dev = &pdev->dev; strscpy(dev->mdev_dec.model, MTK_VCODEC_DEC_NAME, @@ -408,7 +414,7 @@ static int mtk_vcodec_probe(struct platform_device *pdev) MEDIA_ENT_F_PROC_VIDEO_DECODER); if (ret) { mtk_v4l2_err("Failed to register media controller"); - goto err_reg_cont; + goto err_dec_mem_init; } ret = media_device_register(&dev->mdev_dec); @@ -419,30 +425,21 @@ static int mtk_vcodec_probe(struct platform_device *pdev) mtk_v4l2_debug(0, "media registered as /dev/media%d", vfd_dec->minor); } - ret = video_register_device(vfd_dec, VFL_TYPE_VIDEO, 0); - if (ret) { - mtk_v4l2_err("Failed to register video device"); - goto err_dec_reg; - } mtk_v4l2_debug(0, "decoder registered as /dev/video%d", vfd_dec->minor); return 0; -err_dec_reg: - if (dev->vdec_pdata->uses_stateless_api) - media_device_unregister(&dev->mdev_dec); err_media_reg: - if (dev->vdec_pdata->uses_stateless_api) - v4l2_m2m_unregister_media_controller(dev->m2m_dev_dec); + v4l2_m2m_unregister_media_controller(dev->m2m_dev_dec); +err_dec_mem_init: + video_unregister_device(vfd_dec); err_reg_cont: if (dev->vdec_pdata->uses_stateless_api) media_device_cleanup(&dev->mdev_dec); destroy_workqueue(dev->decode_workqueue); err_event_workq: v4l2_m2m_release(dev->m2m_dev_dec); -err_dec_mem_init: - video_unregister_device(vfd_dec); err_dec_alloc: v4l2_device_unregister(&dev->v4l2_dev); err_core_workq: diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_drv.c b/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_drv.c index 326ee151298c..5172cfe0db4a 100644 --- a/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_drv.c +++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_drv.c @@ -349,7 +349,7 @@ static int mtk_vcodec_probe(struct platform_device *pdev) if (of_get_property(pdev->dev.of_node, "dma-ranges", NULL)) dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(34)); - ret = video_register_device(vfd_enc, VFL_TYPE_VIDEO, 1); + ret = video_register_device(vfd_enc, VFL_TYPE_VIDEO, -1); if (ret) { mtk_v4l2_err("Failed to register video device"); goto err_enc_reg; diff --git a/drivers/media/platform/rcar-vin/rcar-core.c b/drivers/media/platform/rcar-vin/rcar-core.c index 0186ae235113..58b002693b7d 100644 --- a/drivers/media/platform/rcar-vin/rcar-core.c +++ b/drivers/media/platform/rcar-vin/rcar-core.c @@ -743,27 +743,6 @@ static int rvin_parallel_init(struct rvin_dev *vin) * CSI-2 */ -static unsigned int rvin_csi2_get_mask(struct rvin_dev *vin, - enum rvin_csi_id csi_id, - unsigned char channel) -{ - const struct rvin_group_route *route; - unsigned int mask = 0; - - for (route = vin->info->routes; route->mask; route++) { - if (route->vin == vin->id && - route->csi == csi_id && - route->channel == channel) { - vin_dbg(vin, - "Adding route: vin: %d csi: %d channel: %d\n", - route->vin, route->csi, route->channel); - mask |= route->mask; - } - } - - return mask; -} - /* * Link setup for the links between a VIN and a CSI-2 receiver is a bit * complex. The reason for this is that the register controlling routing @@ -793,12 +772,10 @@ static int rvin_csi2_link_notify(struct media_link *link, u32 flags, { struct rvin_group *group = container_of(link->graph_obj.mdev, struct rvin_group, mdev); - unsigned int master_id, channel, mask_new, i; - unsigned int mask = ~0; struct media_entity *entity; struct video_device *vdev; - struct media_pad *csi_pad; - struct rvin_dev *vin = NULL; + struct rvin_dev *vin; + unsigned int i; int csi_id, ret; ret = v4l2_pipeline_link_notify(link, flags, notification); @@ -819,38 +796,13 @@ static int rvin_csi2_link_notify(struct media_link *link, u32 flags, if (entity->stream_count) return -EBUSY; - mutex_lock(&group->lock); - /* Find the master VIN that controls the routes. */ vdev = media_entity_to_video_device(link->sink->entity); vin = container_of(vdev, struct rvin_dev, vdev); - master_id = rvin_group_id_to_master(vin->id); - if (WARN_ON(!group->vin[master_id])) { - ret = -ENODEV; - goto out; - } - - /* Build a mask for already enabled links. */ - for (i = master_id; i < master_id + 4; i++) { - if (!group->vin[i]) - continue; - - /* Get remote CSI-2, if any. */ - csi_pad = media_entity_remote_pad( - &group->vin[i]->vdev.entity.pads[0]); - if (!csi_pad) - continue; - - csi_id = rvin_group_entity_to_remote_id(group, csi_pad->entity); - channel = rvin_group_csi_pad_to_channel(csi_pad->index); - - mask &= rvin_csi2_get_mask(group->vin[i], csi_id, channel); - } + mutex_lock(&group->lock); - /* Add the new link to the existing mask and check if it works. */ csi_id = rvin_group_entity_to_remote_id(group, link->source->entity); - if (csi_id == -ENODEV) { struct v4l2_subdev *sd; @@ -875,25 +827,58 @@ static int rvin_csi2_link_notify(struct media_link *link, u32 flags, vin_err(vin, "Subdevice %s not registered to any VIN\n", link->source->entity->name); ret = -ENODEV; - goto out; - } + } else { + const struct rvin_group_route *route; + unsigned int chsel = UINT_MAX; + unsigned int master_id; - channel = rvin_group_csi_pad_to_channel(link->source->index); - mask_new = mask & rvin_csi2_get_mask(vin, csi_id, channel); - vin_dbg(vin, "Try link change mask: 0x%x new: 0x%x\n", mask, mask_new); + master_id = rvin_group_id_to_master(vin->id); - if (!mask_new) { - ret = -EMLINK; - goto out; - } + if (WARN_ON(!group->vin[master_id])) { + ret = -ENODEV; + goto out; + } - /* New valid CHSEL found, set the new value. */ - ret = rvin_set_channel_routing(group->vin[master_id], __ffs(mask_new)); - if (ret) - goto out; + /* Make sure group is connected to same CSI-2 */ + for (i = master_id; i < master_id + 4; i++) { + struct media_pad *csi_pad; + + if (!group->vin[i]) + continue; + + /* Get remote CSI-2, if any. */ + csi_pad = media_entity_remote_pad( + &group->vin[i]->vdev.entity.pads[0]); + if (!csi_pad) + continue; + + if (csi_pad->entity != link->source->entity) { + vin_dbg(vin, "Already attached to %s\n", + csi_pad->entity->name); + ret = -EBUSY; + goto out; + } + } + + for (route = vin->info->routes; route->chsel; route++) { + if (route->master == master_id && route->csi == csi_id) { + chsel = route->chsel; + break; + } + } - vin->is_csi = true; + if (chsel == UINT_MAX) { + vin_err(vin, "No CHSEL value found\n"); + ret = -EINVAL; + goto out; + } + + ret = rvin_set_channel_routing(group->vin[master_id], chsel); + if (ret) + goto out; + vin->is_csi = true; + } out: mutex_unlock(&group->lock); @@ -904,48 +889,60 @@ static const struct media_device_ops rvin_csi2_media_ops = { .link_notify = rvin_csi2_link_notify, }; +static int rvin_csi2_create_link(struct rvin_group *group, unsigned int id, + const struct rvin_group_route *route) + +{ + struct media_entity *source = &group->remotes[route->csi].subdev->entity; + struct media_entity *sink = &group->vin[id]->vdev.entity; + struct media_pad *sink_pad = &sink->pads[0]; + unsigned int channel; + int ret; + + for (channel = 0; channel < 4; channel++) { + unsigned int source_idx = rvin_group_csi_channel_to_pad(channel); + struct media_pad *source_pad = &source->pads[source_idx]; + + /* Skip if link already exists. */ + if (media_entity_find_link(source_pad, sink_pad)) + continue; + + ret = media_create_pad_link(source, source_idx, sink, 0, 0); + if (ret) + return ret; + } + + return 0; +} + static int rvin_csi2_setup_links(struct rvin_dev *vin) { const struct rvin_group_route *route; + unsigned int id; int ret = -EINVAL; /* Create all media device links between VINs and CSI-2's. */ mutex_lock(&vin->group->lock); - for (route = vin->info->routes; route->mask; route++) { - struct media_pad *source_pad, *sink_pad; - struct media_entity *source, *sink; - unsigned int source_idx; - - /* Check that VIN is part of the group. */ - if (!vin->group->vin[route->vin]) - continue; - + for (route = vin->info->routes; route->chsel; route++) { /* Check that VIN' master is part of the group. */ - if (!vin->group->vin[rvin_group_id_to_master(route->vin)]) + if (!vin->group->vin[route->master]) continue; /* Check that CSI-2 is part of the group. */ if (!vin->group->remotes[route->csi].subdev) continue; - source = &vin->group->remotes[route->csi].subdev->entity; - source_idx = rvin_group_csi_channel_to_pad(route->channel); - source_pad = &source->pads[source_idx]; - - sink = &vin->group->vin[route->vin]->vdev.entity; - sink_pad = &sink->pads[0]; - - /* Skip if link already exists. */ - if (media_entity_find_link(source_pad, sink_pad)) - continue; + for (id = route->master; id < route->master + 4; id++) { + /* Check that VIN is part of the group. */ + if (!vin->group->vin[id]) + continue; - ret = media_create_pad_link(source, source_idx, sink, 0, 0); - if (ret) { - vin_err(vin, "Error adding link from %s to %s\n", - source->name, sink->name); - break; + ret = rvin_csi2_create_link(vin->group, id, route); + if (ret) + goto out; } } +out: mutex_unlock(&vin->group->lock); return ret; @@ -1155,30 +1152,9 @@ static const struct rvin_info rcar_info_gen2 = { }; static const struct rvin_group_route rcar_info_r8a774e1_routes[] = { - { .csi = RVIN_CSI40, .channel = 0, .vin = 0, .mask = BIT(0) | BIT(3) }, - { .csi = RVIN_CSI20, .channel = 0, .vin = 0, .mask = BIT(1) | BIT(4) }, - { .csi = RVIN_CSI40, .channel = 1, .vin = 0, .mask = BIT(2) }, - { .csi = RVIN_CSI20, .channel = 0, .vin = 1, .mask = BIT(0) }, - { .csi = RVIN_CSI40, .channel = 1, .vin = 1, .mask = BIT(1) | BIT(3) }, - { .csi = RVIN_CSI40, .channel = 0, .vin = 1, .mask = BIT(2) }, - { .csi = RVIN_CSI20, .channel = 1, .vin = 1, .mask = BIT(4) }, - { .csi = RVIN_CSI20, .channel = 1, .vin = 2, .mask = BIT(0) }, - { .csi = RVIN_CSI40, .channel = 0, .vin = 2, .mask = BIT(1) }, - { .csi = RVIN_CSI20, .channel = 0, .vin = 2, .mask = BIT(2) }, - { .csi = RVIN_CSI40, .channel = 2, .vin = 2, .mask = BIT(3) }, - { .csi = RVIN_CSI20, .channel = 2, .vin = 2, .mask = BIT(4) }, - { .csi = RVIN_CSI40, .channel = 1, .vin = 3, .mask = BIT(0) }, - { .csi = RVIN_CSI20, .channel = 1, .vin = 3, .mask = BIT(1) | BIT(2) }, - { .csi = RVIN_CSI40, .channel = 3, .vin = 3, .mask = BIT(3) }, - { .csi = RVIN_CSI20, .channel = 3, .vin = 3, .mask = BIT(4) }, - { .csi = RVIN_CSI20, .channel = 0, .vin = 4, .mask = BIT(1) | BIT(4) }, - { .csi = RVIN_CSI20, .channel = 0, .vin = 5, .mask = BIT(0) }, - { .csi = RVIN_CSI20, .channel = 1, .vin = 5, .mask = BIT(4) }, - { .csi = RVIN_CSI20, .channel = 1, .vin = 6, .mask = BIT(0) }, - { .csi = RVIN_CSI20, .channel = 0, .vin = 6, .mask = BIT(2) }, - { .csi = RVIN_CSI20, .channel = 2, .vin = 6, .mask = BIT(4) }, - { .csi = RVIN_CSI20, .channel = 1, .vin = 7, .mask = BIT(1) | BIT(2) }, - { .csi = RVIN_CSI20, .channel = 3, .vin = 7, .mask = BIT(4) }, + { .master = 0, .csi = RVIN_CSI20, .chsel = 0x04 }, + { .master = 0, .csi = RVIN_CSI40, .chsel = 0x03 }, + { .master = 4, .csi = RVIN_CSI20, .chsel = 0x04 }, { /* Sentinel */ } }; @@ -1191,38 +1167,10 @@ static const struct rvin_info rcar_info_r8a774e1 = { }; static const struct rvin_group_route rcar_info_r8a7795_routes[] = { - { .csi = RVIN_CSI40, .channel = 0, .vin = 0, .mask = BIT(0) | BIT(3) }, - { .csi = RVIN_CSI20, .channel = 0, .vin = 0, .mask = BIT(1) | BIT(4) }, - { .csi = RVIN_CSI40, .channel = 1, .vin = 0, .mask = BIT(2) }, - { .csi = RVIN_CSI20, .channel = 0, .vin = 1, .mask = BIT(0) }, - { .csi = RVIN_CSI40, .channel = 1, .vin = 1, .mask = BIT(1) | BIT(3) }, - { .csi = RVIN_CSI40, .channel = 0, .vin = 1, .mask = BIT(2) }, - { .csi = RVIN_CSI20, .channel = 1, .vin = 1, .mask = BIT(4) }, - { .csi = RVIN_CSI20, .channel = 1, .vin = 2, .mask = BIT(0) }, - { .csi = RVIN_CSI40, .channel = 0, .vin = 2, .mask = BIT(1) }, - { .csi = RVIN_CSI20, .channel = 0, .vin = 2, .mask = BIT(2) }, - { .csi = RVIN_CSI40, .channel = 2, .vin = 2, .mask = BIT(3) }, - { .csi = RVIN_CSI20, .channel = 2, .vin = 2, .mask = BIT(4) }, - { .csi = RVIN_CSI40, .channel = 1, .vin = 3, .mask = BIT(0) }, - { .csi = RVIN_CSI20, .channel = 1, .vin = 3, .mask = BIT(1) | BIT(2) }, - { .csi = RVIN_CSI40, .channel = 3, .vin = 3, .mask = BIT(3) }, - { .csi = RVIN_CSI20, .channel = 3, .vin = 3, .mask = BIT(4) }, - { .csi = RVIN_CSI41, .channel = 0, .vin = 4, .mask = BIT(0) | BIT(3) }, - { .csi = RVIN_CSI20, .channel = 0, .vin = 4, .mask = BIT(1) | BIT(4) }, - { .csi = RVIN_CSI41, .channel = 1, .vin = 4, .mask = BIT(2) }, - { .csi = RVIN_CSI20, .channel = 0, .vin = 5, .mask = BIT(0) }, - { .csi = RVIN_CSI41, .channel = 1, .vin = 5, .mask = BIT(1) | BIT(3) }, - { .csi = RVIN_CSI41, .channel = 0, .vin = 5, .mask = BIT(2) }, - { .csi = RVIN_CSI20, .channel = 1, .vin = 5, .mask = BIT(4) }, - { .csi = RVIN_CSI20, .channel = 1, .vin = 6, .mask = BIT(0) }, - { .csi = RVIN_CSI41, .channel = 0, .vin = 6, .mask = BIT(1) }, - { .csi = RVIN_CSI20, .channel = 0, .vin = 6, .mask = BIT(2) }, - { .csi = RVIN_CSI41, .channel = 2, .vin = 6, .mask = BIT(3) }, - { .csi = RVIN_CSI20, .channel = 2, .vin = 6, .mask = BIT(4) }, - { .csi = RVIN_CSI41, .channel = 1, .vin = 7, .mask = BIT(0) }, - { .csi = RVIN_CSI20, .channel = 1, .vin = 7, .mask = BIT(1) | BIT(2) }, - { .csi = RVIN_CSI41, .channel = 3, .vin = 7, .mask = BIT(3) }, - { .csi = RVIN_CSI20, .channel = 3, .vin = 7, .mask = BIT(4) }, + { .master = 0, .csi = RVIN_CSI20, .chsel = 0x04 }, + { .master = 0, .csi = RVIN_CSI40, .chsel = 0x03 }, + { .master = 4, .csi = RVIN_CSI20, .chsel = 0x04 }, + { .master = 4, .csi = RVIN_CSI41, .chsel = 0x03 }, { /* Sentinel */ } }; @@ -1236,48 +1184,12 @@ static const struct rvin_info rcar_info_r8a7795 = { }; static const struct rvin_group_route rcar_info_r8a7795es1_routes[] = { - { .csi = RVIN_CSI40, .channel = 0, .vin = 0, .mask = BIT(0) | BIT(3) }, - { .csi = RVIN_CSI20, .channel = 0, .vin = 0, .mask = BIT(1) | BIT(4) }, - { .csi = RVIN_CSI21, .channel = 0, .vin = 0, .mask = BIT(2) | BIT(5) }, - { .csi = RVIN_CSI20, .channel = 0, .vin = 1, .mask = BIT(0) }, - { .csi = RVIN_CSI21, .channel = 0, .vin = 1, .mask = BIT(1) }, - { .csi = RVIN_CSI40, .channel = 0, .vin = 1, .mask = BIT(2) }, - { .csi = RVIN_CSI40, .channel = 1, .vin = 1, .mask = BIT(3) }, - { .csi = RVIN_CSI20, .channel = 1, .vin = 1, .mask = BIT(4) }, - { .csi = RVIN_CSI21, .channel = 1, .vin = 1, .mask = BIT(5) }, - { .csi = RVIN_CSI21, .channel = 0, .vin = 2, .mask = BIT(0) }, - { .csi = RVIN_CSI40, .channel = 0, .vin = 2, .mask = BIT(1) }, - { .csi = RVIN_CSI20, .channel = 0, .vin = 2, .mask = BIT(2) }, - { .csi = RVIN_CSI40, .channel = 2, .vin = 2, .mask = BIT(3) }, - { .csi = RVIN_CSI20, .channel = 2, .vin = 2, .mask = BIT(4) }, - { .csi = RVIN_CSI21, .channel = 2, .vin = 2, .mask = BIT(5) }, - { .csi = RVIN_CSI40, .channel = 1, .vin = 3, .mask = BIT(0) }, - { .csi = RVIN_CSI20, .channel = 1, .vin = 3, .mask = BIT(1) }, - { .csi = RVIN_CSI21, .channel = 1, .vin = 3, .mask = BIT(2) }, - { .csi = RVIN_CSI40, .channel = 3, .vin = 3, .mask = BIT(3) }, - { .csi = RVIN_CSI20, .channel = 3, .vin = 3, .mask = BIT(4) }, - { .csi = RVIN_CSI21, .channel = 3, .vin = 3, .mask = BIT(5) }, - { .csi = RVIN_CSI41, .channel = 0, .vin = 4, .mask = BIT(0) | BIT(3) }, - { .csi = RVIN_CSI20, .channel = 0, .vin = 4, .mask = BIT(1) | BIT(4) }, - { .csi = RVIN_CSI21, .channel = 0, .vin = 4, .mask = BIT(2) | BIT(5) }, - { .csi = RVIN_CSI20, .channel = 0, .vin = 5, .mask = BIT(0) }, - { .csi = RVIN_CSI21, .channel = 0, .vin = 5, .mask = BIT(1) }, - { .csi = RVIN_CSI41, .channel = 0, .vin = 5, .mask = BIT(2) }, - { .csi = RVIN_CSI41, .channel = 1, .vin = 5, .mask = BIT(3) }, - { .csi = RVIN_CSI20, .channel = 1, .vin = 5, .mask = BIT(4) }, - { .csi = RVIN_CSI21, .channel = 1, .vin = 5, .mask = BIT(5) }, - { .csi = RVIN_CSI21, .channel = 0, .vin = 6, .mask = BIT(0) }, - { .csi = RVIN_CSI41, .channel = 0, .vin = 6, .mask = BIT(1) }, - { .csi = RVIN_CSI20, .channel = 0, .vin = 6, .mask = BIT(2) }, - { .csi = RVIN_CSI41, .channel = 2, .vin = 6, .mask = BIT(3) }, - { .csi = RVIN_CSI20, .channel = 2, .vin = 6, .mask = BIT(4) }, - { .csi = RVIN_CSI21, .channel = 2, .vin = 6, .mask = BIT(5) }, - { .csi = RVIN_CSI41, .channel = 1, .vin = 7, .mask = BIT(0) }, - { .csi = RVIN_CSI20, .channel = 1, .vin = 7, .mask = BIT(1) }, - { .csi = RVIN_CSI21, .channel = 1, .vin = 7, .mask = BIT(2) }, - { .csi = RVIN_CSI41, .channel = 3, .vin = 7, .mask = BIT(3) }, - { .csi = RVIN_CSI20, .channel = 3, .vin = 7, .mask = BIT(4) }, - { .csi = RVIN_CSI21, .channel = 3, .vin = 7, .mask = BIT(5) }, + { .master = 0, .csi = RVIN_CSI20, .chsel = 0x04 }, + { .master = 0, .csi = RVIN_CSI21, .chsel = 0x05 }, + { .master = 0, .csi = RVIN_CSI40, .chsel = 0x03 }, + { .master = 4, .csi = RVIN_CSI20, .chsel = 0x04 }, + { .master = 4, .csi = RVIN_CSI21, .chsel = 0x05 }, + { .master = 4, .csi = RVIN_CSI41, .chsel = 0x03 }, { /* Sentinel */ } }; @@ -1290,34 +1202,10 @@ static const struct rvin_info rcar_info_r8a7795es1 = { }; static const struct rvin_group_route rcar_info_r8a7796_routes[] = { - { .csi = RVIN_CSI40, .channel = 0, .vin = 0, .mask = BIT(0) | BIT(3) }, - { .csi = RVIN_CSI20, .channel = 0, .vin = 0, .mask = BIT(1) | BIT(4) }, - { .csi = RVIN_CSI20, .channel = 0, .vin = 1, .mask = BIT(0) }, - { .csi = RVIN_CSI40, .channel = 0, .vin = 1, .mask = BIT(2) }, - { .csi = RVIN_CSI40, .channel = 1, .vin = 1, .mask = BIT(3) }, - { .csi = RVIN_CSI20, .channel = 1, .vin = 1, .mask = BIT(4) }, - { .csi = RVIN_CSI40, .channel = 0, .vin = 2, .mask = BIT(1) }, - { .csi = RVIN_CSI20, .channel = 0, .vin = 2, .mask = BIT(2) }, - { .csi = RVIN_CSI40, .channel = 2, .vin = 2, .mask = BIT(3) }, - { .csi = RVIN_CSI20, .channel = 2, .vin = 2, .mask = BIT(4) }, - { .csi = RVIN_CSI40, .channel = 1, .vin = 3, .mask = BIT(0) }, - { .csi = RVIN_CSI20, .channel = 1, .vin = 3, .mask = BIT(1) }, - { .csi = RVIN_CSI40, .channel = 3, .vin = 3, .mask = BIT(3) }, - { .csi = RVIN_CSI20, .channel = 3, .vin = 3, .mask = BIT(4) }, - { .csi = RVIN_CSI40, .channel = 0, .vin = 4, .mask = BIT(0) | BIT(3) }, - { .csi = RVIN_CSI20, .channel = 0, .vin = 4, .mask = BIT(1) | BIT(4) }, - { .csi = RVIN_CSI20, .channel = 0, .vin = 5, .mask = BIT(0) }, - { .csi = RVIN_CSI40, .channel = 0, .vin = 5, .mask = BIT(2) }, - { .csi = RVIN_CSI40, .channel = 1, .vin = 5, .mask = BIT(3) }, - { .csi = RVIN_CSI20, .channel = 1, .vin = 5, .mask = BIT(4) }, - { .csi = RVIN_CSI40, .channel = 0, .vin = 6, .mask = BIT(1) }, - { .csi = RVIN_CSI20, .channel = 0, .vin = 6, .mask = BIT(2) }, - { .csi = RVIN_CSI40, .channel = 2, .vin = 6, .mask = BIT(3) }, - { .csi = RVIN_CSI20, .channel = 2, .vin = 6, .mask = BIT(4) }, - { .csi = RVIN_CSI40, .channel = 1, .vin = 7, .mask = BIT(0) }, - { .csi = RVIN_CSI20, .channel = 1, .vin = 7, .mask = BIT(1) }, - { .csi = RVIN_CSI40, .channel = 3, .vin = 7, .mask = BIT(3) }, - { .csi = RVIN_CSI20, .channel = 3, .vin = 7, .mask = BIT(4) }, + { .master = 0, .csi = RVIN_CSI20, .chsel = 0x04 }, + { .master = 0, .csi = RVIN_CSI40, .chsel = 0x03 }, + { .master = 4, .csi = RVIN_CSI20, .chsel = 0x04 }, + { .master = 4, .csi = RVIN_CSI40, .chsel = 0x03 }, { /* Sentinel */ } }; @@ -1331,38 +1219,10 @@ static const struct rvin_info rcar_info_r8a7796 = { }; static const struct rvin_group_route rcar_info_r8a77965_routes[] = { - { .csi = RVIN_CSI40, .channel = 0, .vin = 0, .mask = BIT(0) | BIT(3) }, - { .csi = RVIN_CSI20, .channel = 0, .vin = 0, .mask = BIT(1) | BIT(4) }, - { .csi = RVIN_CSI40, .channel = 1, .vin = 0, .mask = BIT(2) }, - { .csi = RVIN_CSI20, .channel = 0, .vin = 1, .mask = BIT(0) }, - { .csi = RVIN_CSI40, .channel = 1, .vin = 1, .mask = BIT(1) | BIT(3) }, - { .csi = RVIN_CSI40, .channel = 0, .vin = 1, .mask = BIT(2) }, - { .csi = RVIN_CSI20, .channel = 1, .vin = 1, .mask = BIT(4) }, - { .csi = RVIN_CSI20, .channel = 1, .vin = 2, .mask = BIT(0) }, - { .csi = RVIN_CSI40, .channel = 0, .vin = 2, .mask = BIT(1) }, - { .csi = RVIN_CSI20, .channel = 0, .vin = 2, .mask = BIT(2) }, - { .csi = RVIN_CSI40, .channel = 2, .vin = 2, .mask = BIT(3) }, - { .csi = RVIN_CSI20, .channel = 2, .vin = 2, .mask = BIT(4) }, - { .csi = RVIN_CSI40, .channel = 1, .vin = 3, .mask = BIT(0) }, - { .csi = RVIN_CSI20, .channel = 1, .vin = 3, .mask = BIT(1) | BIT(2) }, - { .csi = RVIN_CSI40, .channel = 3, .vin = 3, .mask = BIT(3) }, - { .csi = RVIN_CSI20, .channel = 3, .vin = 3, .mask = BIT(4) }, - { .csi = RVIN_CSI40, .channel = 0, .vin = 4, .mask = BIT(0) | BIT(3) }, - { .csi = RVIN_CSI20, .channel = 0, .vin = 4, .mask = BIT(1) | BIT(4) }, - { .csi = RVIN_CSI40, .channel = 1, .vin = 4, .mask = BIT(2) }, - { .csi = RVIN_CSI20, .channel = 0, .vin = 5, .mask = BIT(0) }, - { .csi = RVIN_CSI40, .channel = 1, .vin = 5, .mask = BIT(1) | BIT(3) }, - { .csi = RVIN_CSI40, .channel = 0, .vin = 5, .mask = BIT(2) }, - { .csi = RVIN_CSI20, .channel = 1, .vin = 5, .mask = BIT(4) }, - { .csi = RVIN_CSI20, .channel = 1, .vin = 6, .mask = BIT(0) }, - { .csi = RVIN_CSI40, .channel = 0, .vin = 6, .mask = BIT(1) }, - { .csi = RVIN_CSI20, .channel = 0, .vin = 6, .mask = BIT(2) }, - { .csi = RVIN_CSI40, .channel = 2, .vin = 6, .mask = BIT(3) }, - { .csi = RVIN_CSI20, .channel = 2, .vin = 6, .mask = BIT(4) }, - { .csi = RVIN_CSI40, .channel = 1, .vin = 7, .mask = BIT(0) }, - { .csi = RVIN_CSI20, .channel = 1, .vin = 7, .mask = BIT(1) | BIT(2) }, - { .csi = RVIN_CSI40, .channel = 3, .vin = 7, .mask = BIT(3) }, - { .csi = RVIN_CSI20, .channel = 3, .vin = 7, .mask = BIT(4) }, + { .master = 0, .csi = RVIN_CSI20, .chsel = 0x04 }, + { .master = 0, .csi = RVIN_CSI40, .chsel = 0x03 }, + { .master = 4, .csi = RVIN_CSI20, .chsel = 0x04 }, + { .master = 4, .csi = RVIN_CSI40, .chsel = 0x03 }, { /* Sentinel */ } }; @@ -1376,13 +1236,7 @@ static const struct rvin_info rcar_info_r8a77965 = { }; static const struct rvin_group_route rcar_info_r8a77970_routes[] = { - { .csi = RVIN_CSI40, .channel = 0, .vin = 0, .mask = BIT(0) | BIT(3) }, - { .csi = RVIN_CSI40, .channel = 0, .vin = 1, .mask = BIT(2) }, - { .csi = RVIN_CSI40, .channel = 1, .vin = 1, .mask = BIT(3) }, - { .csi = RVIN_CSI40, .channel = 0, .vin = 2, .mask = BIT(1) }, - { .csi = RVIN_CSI40, .channel = 2, .vin = 2, .mask = BIT(3) }, - { .csi = RVIN_CSI40, .channel = 1, .vin = 3, .mask = BIT(0) }, - { .csi = RVIN_CSI40, .channel = 3, .vin = 3, .mask = BIT(3) }, + { .master = 0, .csi = RVIN_CSI40, .chsel = 0x03 }, { /* Sentinel */ } }; @@ -1395,22 +1249,8 @@ static const struct rvin_info rcar_info_r8a77970 = { }; static const struct rvin_group_route rcar_info_r8a77980_routes[] = { - { .csi = RVIN_CSI40, .channel = 0, .vin = 0, .mask = BIT(0) | BIT(3) }, - { .csi = RVIN_CSI40, .channel = 1, .vin = 0, .mask = BIT(2) }, - { .csi = RVIN_CSI40, .channel = 0, .vin = 1, .mask = BIT(2) }, - { .csi = RVIN_CSI40, .channel = 1, .vin = 1, .mask = BIT(1) | BIT(3) }, - { .csi = RVIN_CSI40, .channel = 0, .vin = 2, .mask = BIT(1) }, - { .csi = RVIN_CSI40, .channel = 2, .vin = 2, .mask = BIT(3) }, - { .csi = RVIN_CSI40, .channel = 1, .vin = 3, .mask = BIT(0) }, - { .csi = RVIN_CSI40, .channel = 3, .vin = 3, .mask = BIT(3) }, - { .csi = RVIN_CSI41, .channel = 0, .vin = 4, .mask = BIT(0) | BIT(3) }, - { .csi = RVIN_CSI41, .channel = 1, .vin = 4, .mask = BIT(2) }, - { .csi = RVIN_CSI41, .channel = 0, .vin = 5, .mask = BIT(2) }, - { .csi = RVIN_CSI41, .channel = 1, .vin = 5, .mask = BIT(1) | BIT(3) }, - { .csi = RVIN_CSI41, .channel = 0, .vin = 6, .mask = BIT(1) }, - { .csi = RVIN_CSI41, .channel = 2, .vin = 6, .mask = BIT(3) }, - { .csi = RVIN_CSI41, .channel = 1, .vin = 7, .mask = BIT(0) }, - { .csi = RVIN_CSI41, .channel = 3, .vin = 7, .mask = BIT(3) }, + { .master = 0, .csi = RVIN_CSI40, .chsel = 0x03 }, + { .master = 4, .csi = RVIN_CSI41, .chsel = 0x03 }, { /* Sentinel */ } }; @@ -1424,10 +1264,7 @@ static const struct rvin_info rcar_info_r8a77980 = { }; static const struct rvin_group_route rcar_info_r8a77990_routes[] = { - { .csi = RVIN_CSI40, .channel = 0, .vin = 4, .mask = BIT(0) | BIT(3) }, - { .csi = RVIN_CSI40, .channel = 0, .vin = 5, .mask = BIT(2) }, - { .csi = RVIN_CSI40, .channel = 1, .vin = 4, .mask = BIT(2) }, - { .csi = RVIN_CSI40, .channel = 1, .vin = 5, .mask = BIT(1) | BIT(3) }, + { .master = 0, .csi = RVIN_CSI40, .chsel = 0x03 }, { /* Sentinel */ } }; diff --git a/drivers/media/platform/rcar-vin/rcar-csi2.c b/drivers/media/platform/rcar-vin/rcar-csi2.c index 2f097792525f..2fe179e389d2 100644 --- a/drivers/media/platform/rcar-vin/rcar-csi2.c +++ b/drivers/media/platform/rcar-vin/rcar-csi2.c @@ -503,6 +503,8 @@ struct rcar_csi2 { struct v4l2_subdev *remote; unsigned int remote_pad; + int channel_vc[4]; + struct mutex lock; /* Protects mf and stream_count. */ struct v4l2_mbus_framefmt mf; int stream_count; @@ -700,8 +702,11 @@ static int rcsi2_start_receiver(struct rcar_csi2 *priv) for (i = 0; i < priv->info->num_channels; i++) { u32 vcdt_part; - vcdt_part = VCDT_SEL_VC(i) | VCDT_VCDTN_EN | VCDT_SEL_DTN_ON | - VCDT_SEL_DT(format->datatype); + if (priv->channel_vc[i] < 0) + continue; + + vcdt_part = VCDT_SEL_VC(priv->channel_vc[i]) | VCDT_VCDTN_EN | + VCDT_SEL_DTN_ON | VCDT_SEL_DT(format->datatype); /* Store in correct reg and offset. */ if (i < 2) @@ -1283,7 +1288,52 @@ static int rcsi2_init_phtw_v3u(struct rcar_csi2 *priv, * Platform Device Driver. */ +static int rcsi2_link_setup(struct media_entity *entity, + const struct media_pad *local, + const struct media_pad *remote, u32 flags) +{ + struct v4l2_subdev *sd = media_entity_to_v4l2_subdev(entity); + struct rcar_csi2 *priv = sd_to_csi2(sd); + struct video_device *vdev; + int channel, vc; + u32 id; + + if (!is_media_entity_v4l2_video_device(remote->entity)) { + dev_err(priv->dev, "Remote is not a video device\n"); + return -EINVAL; + } + + vdev = media_entity_to_video_device(remote->entity); + + if (of_property_read_u32(vdev->dev_parent->of_node, "renesas,id", &id)) { + dev_err(priv->dev, "No renesas,id, can't configure routing\n"); + return -EINVAL; + } + + channel = id % 4; + + if (flags & MEDIA_LNK_FL_ENABLED) { + if (media_entity_remote_pad(local)) { + dev_dbg(priv->dev, + "Each VC can only be routed to one output channel\n"); + return -EINVAL; + } + + vc = local->index - 1; + + dev_dbg(priv->dev, "Route VC%d to VIN%u on output channel %d\n", + vc, id, channel); + } else { + vc = -1; + } + + priv->channel_vc[channel] = vc; + + return 0; +} + static const struct media_entity_operations rcar_csi2_entity_ops = { + .link_setup = rcsi2_link_setup, .link_validate = v4l2_subdev_link_validate, }; @@ -1502,6 +1552,9 @@ static int rcsi2_probe(struct platform_device *pdev) if (ret) goto error_async; + for (i = 0; i < ARRAY_SIZE(priv->channel_vc); i++) + priv->channel_vc[i] = -1; + pm_runtime_enable(&pdev->dev); ret = v4l2_async_register_subdev(&priv->subdev); diff --git a/drivers/media/platform/rcar-vin/rcar-dma.c b/drivers/media/platform/rcar-vin/rcar-dma.c index 8136bc75e7c4..2272f1c96aaf 100644 --- a/drivers/media/platform/rcar-vin/rcar-dma.c +++ b/drivers/media/platform/rcar-vin/rcar-dma.c @@ -1507,7 +1507,7 @@ int rvin_set_channel_routing(struct rvin_dev *vin, u8 chsel) * register. IFMD_DES1 controls data expansion mode for CSI20/21, * IFMD_DES0 controls data expansion mode for CSI40/41. */ - for (route = vin->info->routes; route->mask; route++) { + for (route = vin->info->routes; route->chsel; route++) { if (route->csi == RVIN_CSI20 || route->csi == RVIN_CSI21) ifmd |= VNCSI_IFMD_DES1; else diff --git a/drivers/media/platform/rcar-vin/rcar-vin.h b/drivers/media/platform/rcar-vin/rcar-vin.h index 7e86e35ca42b..1f94589d9ef1 100644 --- a/drivers/media/platform/rcar-vin/rcar-vin.h +++ b/drivers/media/platform/rcar-vin/rcar-vin.h @@ -128,11 +128,9 @@ struct rvin_parallel_entity { * struct rvin_group_route - describes a route from a channel of a * CSI-2 receiver to a VIN * + * @master: VIN group master ID. * @csi: CSI-2 receiver ID. - * @channel: Output channel of the CSI-2 receiver. - * @vin: VIN ID. - * @mask: Bitmask of the different CHSEL register values that - * allow for a route from @csi + @chan to @vin. + * @chsel: CHSEL register values that connects VIN group to CSI-2. * * .. note:: * Each R-Car CSI-2 receiver has four output channels facing the VIN @@ -140,19 +138,11 @@ struct rvin_parallel_entity { * There is no correlation between channel number and CSI-2 VC. It's * up to the CSI-2 receiver driver to configure which VC is output * on which channel, the VIN devices only care about output channels. - * - * There are in some cases multiple CHSEL register settings which would - * allow for the same route from @csi + @channel to @vin. For example - * on R-Car H3 both the CHSEL values 0 and 3 allow for a route from - * CSI40/VC0 to VIN0. All possible CHSEL values for a route need to be - * recorded as a bitmask in @mask, in this example bit 0 and 3 should - * be set. */ struct rvin_group_route { + unsigned int master; enum rvin_csi_id csi; - unsigned int channel; - unsigned int vin; - unsigned int mask; + unsigned int chsel; }; /** diff --git a/drivers/media/platform/sunxi/sun6i-csi/sun6i_video.c b/drivers/media/platform/sunxi/sun6i-csi/sun6i_video.c index 607a8d39fbe2..682c26536034 100644 --- a/drivers/media/platform/sunxi/sun6i-csi/sun6i_video.c +++ b/drivers/media/platform/sunxi/sun6i-csi/sun6i_video.c @@ -368,7 +368,11 @@ static int sun6i_video_try_fmt(struct sun6i_video *video, if (pixfmt->field == V4L2_FIELD_ANY) pixfmt->field = V4L2_FIELD_NONE; - pixfmt->colorspace = V4L2_COLORSPACE_RAW; + if (pixfmt->pixelformat == V4L2_PIX_FMT_JPEG) + pixfmt->colorspace = V4L2_COLORSPACE_JPEG; + else + pixfmt->colorspace = V4L2_COLORSPACE_SRGB; + pixfmt->ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT; pixfmt->quantization = V4L2_QUANTIZATION_DEFAULT; pixfmt->xfer_func = V4L2_XFER_FUNC_DEFAULT; diff --git a/drivers/media/radio/wl128x/fmdrv_common.c b/drivers/media/radio/wl128x/fmdrv_common.c index 6142484d5cb4..8a316de70e6c 100644 --- a/drivers/media/radio/wl128x/fmdrv_common.c +++ b/drivers/media/radio/wl128x/fmdrv_common.c @@ -23,6 +23,7 @@ #include <linux/firmware.h> #include <linux/module.h> #include <linux/nospec.h> +#include <linux/jiffies.h> #include "fmdrv.h" #include "fmdrv_v4l2.h" @@ -342,7 +343,7 @@ static void send_tasklet(struct tasklet_struct *t) return; /* Check, is there any timeout happened to last transmitted packet */ - if ((jiffies - fmdev->last_tx_jiffies) > FM_DRV_TX_TIMEOUT) { + if (time_is_before_jiffies(fmdev->last_tx_jiffies + FM_DRV_TX_TIMEOUT)) { fmerr("TX timeout occurred\n"); atomic_set(&fmdev->tx_cnt, 1); } diff --git a/drivers/media/rc/meson-ir-tx.c b/drivers/media/rc/meson-ir-tx.c index c22cd26a5c07..63e1dbf0a4e9 100644 --- a/drivers/media/rc/meson-ir-tx.c +++ b/drivers/media/rc/meson-ir-tx.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-2.0-only -/** +/* * meson-ir-tx.c - Amlogic Meson IR TX driver * * Copyright (c) 2021, SberDevices. All Rights Reserved. diff --git a/drivers/media/test-drivers/vivid/vivid-kthread-cap.c b/drivers/media/test-drivers/vivid/vivid-kthread-cap.c index 6baa046c1ae3..690daada7db4 100644 --- a/drivers/media/test-drivers/vivid/vivid-kthread-cap.c +++ b/drivers/media/test-drivers/vivid/vivid-kthread-cap.c @@ -18,6 +18,7 @@ #include <linux/freezer.h> #include <linux/random.h> #include <linux/v4l2-dv-timings.h> +#include <linux/jiffies.h> #include <asm/div64.h> #include <media/videobuf2-vmalloc.h> #include <media/v4l2-dv-timings.h> @@ -893,7 +894,7 @@ static int vivid_thread_vid_cap(void *data) next_jiffies_since_start = jiffies_since_start; wait_jiffies = next_jiffies_since_start - jiffies_since_start; - while (jiffies - cur_jiffies < wait_jiffies && + while (time_is_after_jiffies(cur_jiffies + wait_jiffies) && !kthread_should_stop()) schedule(); } diff --git a/drivers/media/test-drivers/vivid/vivid-kthread-out.c b/drivers/media/test-drivers/vivid/vivid-kthread-out.c index b6d43169e970..0833e021bb11 100644 --- a/drivers/media/test-drivers/vivid/vivid-kthread-out.c +++ b/drivers/media/test-drivers/vivid/vivid-kthread-out.c @@ -18,6 +18,7 @@ #include <linux/freezer.h> #include <linux/random.h> #include <linux/v4l2-dv-timings.h> +#include <linux/jiffies.h> #include <asm/div64.h> #include <media/videobuf2-vmalloc.h> #include <media/v4l2-dv-timings.h> @@ -234,7 +235,7 @@ static int vivid_thread_vid_out(void *data) next_jiffies_since_start = jiffies_since_start; wait_jiffies = next_jiffies_since_start - jiffies_since_start; - while (jiffies - cur_jiffies < wait_jiffies && + while (time_is_after_jiffies(cur_jiffies + wait_jiffies) && !kthread_should_stop()) schedule(); } diff --git a/drivers/media/test-drivers/vivid/vivid-kthread-touch.c b/drivers/media/test-drivers/vivid/vivid-kthread-touch.c index f065faae4988..fa711ee36a3f 100644 --- a/drivers/media/test-drivers/vivid/vivid-kthread-touch.c +++ b/drivers/media/test-drivers/vivid/vivid-kthread-touch.c @@ -5,6 +5,7 @@ */ #include <linux/freezer.h> +#include <linux/jiffies.h> #include "vivid-core.h" #include "vivid-kthread-touch.h" #include "vivid-touch-cap.h" @@ -134,7 +135,7 @@ static int vivid_thread_touch_cap(void *data) next_jiffies_since_start = jiffies_since_start; wait_jiffies = next_jiffies_since_start - jiffies_since_start; - while (jiffies - cur_jiffies < wait_jiffies && + while (time_is_after_jiffies(cur_jiffies + wait_jiffies) && !kthread_should_stop()) schedule(); } diff --git a/drivers/media/test-drivers/vivid/vivid-sdr-cap.c b/drivers/media/test-drivers/vivid/vivid-sdr-cap.c index 59fd508e27c8..0ae5628b86c9 100644 --- a/drivers/media/test-drivers/vivid/vivid-sdr-cap.c +++ b/drivers/media/test-drivers/vivid/vivid-sdr-cap.c @@ -17,6 +17,7 @@ #include <media/v4l2-event.h> #include <media/v4l2-dv-timings.h> #include <linux/fixp-arith.h> +#include <linux/jiffies.h> #include "vivid-core.h" #include "vivid-ctrls.h" @@ -205,7 +206,7 @@ static int vivid_thread_sdr_cap(void *data) next_jiffies_since_start = jiffies_since_start; wait_jiffies = next_jiffies_since_start - jiffies_since_start; - while (jiffies - cur_jiffies < wait_jiffies && + while (time_is_after_jiffies(cur_jiffies + wait_jiffies) && !kthread_should_stop()) schedule(); } diff --git a/drivers/media/usb/em28xx/em28xx-cards.c b/drivers/media/usb/em28xx/em28xx-cards.c index 4a46ef50baf9..ae25d2cbfdfe 100644 --- a/drivers/media/usb/em28xx/em28xx-cards.c +++ b/drivers/media/usb/em28xx/em28xx-cards.c @@ -3936,6 +3936,8 @@ static int em28xx_usb_probe(struct usb_interface *intf, goto err_free; } + kref_init(&dev->ref); + dev->devno = nr; dev->model = id->driver_info; dev->alt = -1; @@ -4036,6 +4038,8 @@ static int em28xx_usb_probe(struct usb_interface *intf, } if (dev->board.has_dual_ts && em28xx_duplicate_dev(dev) == 0) { + kref_init(&dev->dev_next->ref); + dev->dev_next->ts = SECONDARY_TS; dev->dev_next->alt = -1; dev->dev_next->is_audio_only = has_vendor_audio && @@ -4090,12 +4094,8 @@ static int em28xx_usb_probe(struct usb_interface *intf, em28xx_write_reg(dev, 0x0b, 0x82); mdelay(100); } - - kref_init(&dev->dev_next->ref); } - kref_init(&dev->ref); - request_modules(dev); /* diff --git a/drivers/media/usb/go7007/s2250-board.c b/drivers/media/usb/go7007/s2250-board.c index c742cc88fac5..1fa6f10ee157 100644 --- a/drivers/media/usb/go7007/s2250-board.c +++ b/drivers/media/usb/go7007/s2250-board.c @@ -504,6 +504,7 @@ static int s2250_probe(struct i2c_client *client, u8 *data; struct go7007 *go = i2c_get_adapdata(adapter); struct go7007_usb *usb = go->hpi_context; + int err = -EIO; audio = i2c_new_dummy_device(adapter, TLV320_ADDRESS >> 1); if (IS_ERR(audio)) @@ -532,11 +533,8 @@ static int s2250_probe(struct i2c_client *client, V4L2_CID_HUE, -512, 511, 1, 0); sd->ctrl_handler = &state->hdl; if (state->hdl.error) { - int err = state->hdl.error; - - v4l2_ctrl_handler_free(&state->hdl); - kfree(state); - return err; + err = state->hdl.error; + goto fail; } state->std = V4L2_STD_NTSC; @@ -600,7 +598,7 @@ fail: i2c_unregister_device(audio); v4l2_ctrl_handler_free(&state->hdl); kfree(state); - return -EIO; + return err; } static int s2250_remove(struct i2c_client *client) diff --git a/drivers/media/usb/go7007/snd-go7007.c b/drivers/media/usb/go7007/snd-go7007.c index 2ce85ab38db5..9a6bd87fce03 100644 --- a/drivers/media/usb/go7007/snd-go7007.c +++ b/drivers/media/usb/go7007/snd-go7007.c @@ -191,7 +191,7 @@ static int go7007_snd_free(struct snd_device *device) return 0; } -static struct snd_device_ops go7007_snd_device_ops = { +static const struct snd_device_ops go7007_snd_device_ops = { .dev_free = go7007_snd_free, }; diff --git a/drivers/media/usb/gspca/pac7302.c b/drivers/media/usb/gspca/pac7302.c index 2e8c3ef51ca3..608be0d64f94 100644 --- a/drivers/media/usb/gspca/pac7302.c +++ b/drivers/media/usb/gspca/pac7302.c @@ -794,7 +794,6 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, n = (sof - data) - (footer_length + sizeof pac_sof_marker); if (n < 0) { gspca_dev->image_len += n; - n = 0; } else { gspca_frame_add(gspca_dev, INTER_PACKET, data, n); } diff --git a/drivers/media/usb/pwc/pwc-uncompress.c b/drivers/media/usb/pwc/pwc-uncompress.c index 68bc3829c6b3..faf44cdeb268 100644 --- a/drivers/media/usb/pwc/pwc-uncompress.c +++ b/drivers/media/usb/pwc/pwc-uncompress.c @@ -41,7 +41,7 @@ int pwc_decompress(struct pwc_device *pdev, struct pwc_frame_buf *fbuf) memcpy(raw_frame->cmd, pdev->cmd_buf, 4); memcpy(raw_frame+1, yuv, pdev->frame_size); vb2_set_plane_payload(&fbuf->vb.vb2_buf, 0, - pdev->frame_size + sizeof(struct pwc_raw_frame)); + struct_size(raw_frame, rawframe, pdev->frame_size)); return 0; } diff --git a/drivers/media/usb/stkwebcam/stk-webcam.c b/drivers/media/usb/stkwebcam/stk-webcam.c index 9f445e6ab5fa..5b822214ccc5 100644 --- a/drivers/media/usb/stkwebcam/stk-webcam.c +++ b/drivers/media/usb/stkwebcam/stk-webcam.c @@ -114,6 +114,13 @@ static const struct dmi_system_id stk_upside_down_dmi_table[] = { DMI_MATCH(DMI_PRODUCT_NAME, "A6VM") } }, + { + .ident = "ASUS A6JC", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."), + DMI_MATCH(DMI_PRODUCT_NAME, "A6JC") + } + }, {} }; diff --git a/drivers/media/v4l2-core/v4l2-ctrls-core.c b/drivers/media/v4l2-core/v4l2-ctrls-core.c index 85c2d3f39d96..c2147509b7cd 100644 --- a/drivers/media/v4l2-core/v4l2-ctrls-core.c +++ b/drivers/media/v4l2-core/v4l2-ctrls-core.c @@ -112,6 +112,7 @@ static void std_init_compound(const struct v4l2_ctrl *ctrl, u32 idx, struct v4l2_ctrl_mpeg2_picture *p_mpeg2_picture; struct v4l2_ctrl_mpeg2_quantisation *p_mpeg2_quant; struct v4l2_ctrl_vp8_frame *p_vp8_frame; + struct v4l2_ctrl_vp9_frame *p_vp9_frame; struct v4l2_ctrl_fwht_params *p_fwht_params; void *p = ptr.p + idx * ctrl->elem_size; @@ -152,6 +153,13 @@ static void std_init_compound(const struct v4l2_ctrl *ctrl, u32 idx, p_vp8_frame = p; p_vp8_frame->num_dct_parts = 1; break; + case V4L2_CTRL_TYPE_VP9_FRAME: + p_vp9_frame = p; + p_vp9_frame->profile = 0; + p_vp9_frame->bit_depth = 8; + p_vp9_frame->flags |= V4L2_VP9_FRAME_FLAG_X_SUBSAMPLING | + V4L2_VP9_FRAME_FLAG_Y_SUBSAMPLING; + break; case V4L2_CTRL_TYPE_FWHT_PARAMS: p_fwht_params = p; p_fwht_params->version = V4L2_FWHT_VERSION; diff --git a/drivers/staging/media/meson/vdec/vdec_platform.c b/drivers/staging/media/meson/vdec/vdec_platform.c index eabbebab2da2..88c9d72e1c83 100644 --- a/drivers/staging/media/meson/vdec/vdec_platform.c +++ b/drivers/staging/media/meson/vdec/vdec_platform.c @@ -103,6 +103,18 @@ static const struct amvdec_format vdec_formats_gxl[] = { static const struct amvdec_format vdec_formats_gxm[] = { { + .pixfmt = V4L2_PIX_FMT_VP9, + .min_buffers = 16, + .max_buffers = 24, + .max_width = 3840, + .max_height = 2160, + .vdec_ops = &vdec_hevc_ops, + .codec_ops = &codec_vp9_ops, + .firmware_path = "meson/vdec/gxl_vp9.bin", + .pixfmts_cap = { V4L2_PIX_FMT_NV12M, 0 }, + .flags = V4L2_FMT_FLAG_COMPRESSED | + V4L2_FMT_FLAG_DYN_RESOLUTION, + }, { .pixfmt = V4L2_PIX_FMT_H264, .min_buffers = 2, .max_buffers = 24, diff --git a/drivers/staging/media/sunxi/cedrus/cedrus.c b/drivers/staging/media/sunxi/cedrus/cedrus.c index 4a4b714b0f26..68b3dcdb5df3 100644 --- a/drivers/staging/media/sunxi/cedrus/cedrus.c +++ b/drivers/staging/media/sunxi/cedrus/cedrus.c @@ -439,6 +439,8 @@ static int cedrus_probe(struct platform_device *pdev) mutex_init(&dev->dev_mutex); + INIT_DELAYED_WORK(&dev->watchdog_work, cedrus_watchdog); + ret = v4l2_device_register(&pdev->dev, &dev->v4l2_dev); if (ret) { dev_err(&pdev->dev, "Failed to register V4L2 device\n"); diff --git a/drivers/staging/media/sunxi/cedrus/cedrus.h b/drivers/staging/media/sunxi/cedrus/cedrus.h index c345f2984041..3bc094eb497f 100644 --- a/drivers/staging/media/sunxi/cedrus/cedrus.h +++ b/drivers/staging/media/sunxi/cedrus/cedrus.h @@ -24,6 +24,7 @@ #include <linux/iopoll.h> #include <linux/platform_device.h> +#include <linux/workqueue.h> #define CEDRUS_NAME "cedrus" @@ -194,6 +195,8 @@ struct cedrus_dev { struct reset_control *rstc; unsigned int capabilities; + + struct delayed_work watchdog_work; }; extern struct cedrus_dec_ops cedrus_dec_ops_mpeg2; diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_dec.c b/drivers/staging/media/sunxi/cedrus/cedrus_dec.c index a16c1422558f..9c7200299465 100644 --- a/drivers/staging/media/sunxi/cedrus/cedrus_dec.c +++ b/drivers/staging/media/sunxi/cedrus/cedrus_dec.c @@ -97,4 +97,8 @@ void cedrus_device_run(void *priv) v4l2_ctrl_request_complete(src_req, &ctx->hdl); dev->dec_ops[ctx->current_codec]->trigger(ctx); + + /* Start the watchdog timer. */ + schedule_delayed_work(&dev->watchdog_work, + msecs_to_jiffies(2000)); } diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_h264.c b/drivers/staging/media/sunxi/cedrus/cedrus_h264.c index b4173a8926d6..d8fb93035470 100644 --- a/drivers/staging/media/sunxi/cedrus/cedrus_h264.c +++ b/drivers/staging/media/sunxi/cedrus/cedrus_h264.c @@ -38,7 +38,7 @@ struct cedrus_h264_sram_ref_pic { #define CEDRUS_H264_FRAME_NUM 18 -#define CEDRUS_NEIGHBOR_INFO_BUF_SIZE (16 * SZ_1K) +#define CEDRUS_NEIGHBOR_INFO_BUF_SIZE (32 * SZ_1K) #define CEDRUS_MIN_PIC_INFO_BUF_SIZE (130 * SZ_1K) static void cedrus_h264_write_sram(struct cedrus_dev *dev, diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_h265.c b/drivers/staging/media/sunxi/cedrus/cedrus_h265.c index 8ab2d9c6f048..44f385be9f6c 100644 --- a/drivers/staging/media/sunxi/cedrus/cedrus_h265.c +++ b/drivers/staging/media/sunxi/cedrus/cedrus_h265.c @@ -23,7 +23,7 @@ * Subsequent BSP implementations seem to double the neighbor info buffer size * for the H6 SoC, which may be related to 10 bit H265 support. */ -#define CEDRUS_H265_NEIGHBOR_INFO_BUF_SIZE (397 * SZ_1K) +#define CEDRUS_H265_NEIGHBOR_INFO_BUF_SIZE (794 * SZ_1K) #define CEDRUS_H265_ENTRY_POINTS_BUF_SIZE (4 * SZ_1K) #define CEDRUS_H265_MV_COL_BUF_UNIT_CTB_SIZE 160 diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_hw.c b/drivers/staging/media/sunxi/cedrus/cedrus_hw.c index 2d7663726467..a6470a89851e 100644 --- a/drivers/staging/media/sunxi/cedrus/cedrus_hw.c +++ b/drivers/staging/media/sunxi/cedrus/cedrus_hw.c @@ -118,6 +118,13 @@ static irqreturn_t cedrus_irq(int irq, void *data) enum vb2_buffer_state state; enum cedrus_irq_status status; + /* + * If cancel_delayed_work returns false it means watchdog already + * executed and finished the job. + */ + if (!cancel_delayed_work(&dev->watchdog_work)) + return IRQ_HANDLED; + ctx = v4l2_m2m_get_curr_priv(dev->m2m_dev); if (!ctx) { v4l2_err(&dev->v4l2_dev, @@ -143,6 +150,24 @@ static irqreturn_t cedrus_irq(int irq, void *data) return IRQ_HANDLED; } +void cedrus_watchdog(struct work_struct *work) +{ + struct cedrus_dev *dev; + struct cedrus_ctx *ctx; + + dev = container_of(to_delayed_work(work), + struct cedrus_dev, watchdog_work); + + ctx = v4l2_m2m_get_curr_priv(dev->m2m_dev); + if (!ctx) + return; + + v4l2_err(&dev->v4l2_dev, "frame processing timed out!\n"); + reset_control_reset(dev->rstc); + v4l2_m2m_buf_done_and_job_finish(ctx->dev->m2m_dev, ctx->fh.m2m_ctx, + VB2_BUF_STATE_ERROR); +} + int cedrus_hw_suspend(struct device *device) { struct cedrus_dev *dev = dev_get_drvdata(device); diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_hw.h b/drivers/staging/media/sunxi/cedrus/cedrus_hw.h index 45f641f0bfa2..7c92f00e36da 100644 --- a/drivers/staging/media/sunxi/cedrus/cedrus_hw.h +++ b/drivers/staging/media/sunxi/cedrus/cedrus_hw.h @@ -28,4 +28,6 @@ int cedrus_hw_resume(struct device *device); int cedrus_hw_probe(struct cedrus_dev *dev); void cedrus_hw_remove(struct cedrus_dev *dev); +void cedrus_watchdog(struct work_struct *work); + #endif |