mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git
synced 2025-01-06 05:02:31 +00:00
Tag branch
-----BEGIN PGP SIGNATURE----- iHUEABYIAB0WIQRSrcquik9wuZrNjXJrQl33mxwedgUCYhSuNQAKCRBrQl33mxwe dqOzAQCYc0iOPhTap9q7thsa5KYbyOU1A45u2jeETEz80La8mwEA4GjXUWMi2Scs e0BMW+hej/kjPnFHNqz4UBBXoDG0Egg= =TDr2 -----END PGP SIGNATURE----- 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>
This commit is contained in:
commit
8268d06750
@ -76,7 +76,7 @@ All components are stored with the same number of bits per component.
|
||||
- 'NV21'
|
||||
- 8
|
||||
- 4:2:0
|
||||
- Cr, Cr
|
||||
- Cr, Cb
|
||||
- Yes
|
||||
- Linear
|
||||
* - V4L2_PIX_FMT_NV12M
|
||||
@ -90,7 +90,7 @@ All components are stored with the same number of bits per component.
|
||||
- 'NM21'
|
||||
- 8
|
||||
- 4:2:0
|
||||
- Cr, Cr
|
||||
- Cr, Cb
|
||||
- No
|
||||
- Linear
|
||||
* - V4L2_PIX_FMT_NV12MT
|
||||
@ -120,7 +120,7 @@ All components are stored with the same number of bits per component.
|
||||
- 'NV61'
|
||||
- 8
|
||||
- 4:2:2
|
||||
- Cr, Cr
|
||||
- Cr, Cb
|
||||
- Yes
|
||||
- Linear
|
||||
* - V4L2_PIX_FMT_NV16M
|
||||
@ -134,7 +134,7 @@ All components are stored with the same number of bits per component.
|
||||
- 'NM61'
|
||||
- 8
|
||||
- 4:2:2
|
||||
- Cr, Cr
|
||||
- Cr, Cb
|
||||
- No
|
||||
- Linear
|
||||
* - V4L2_PIX_FMT_NV24
|
||||
@ -148,7 +148,7 @@ All components are stored with the same number of bits per component.
|
||||
- 'NV42'
|
||||
- 8
|
||||
- 4:4:4
|
||||
- Cr, Cr
|
||||
- Cr, Cb
|
||||
- Yes
|
||||
- Linear
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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 */
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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 @@ static void mxc_jpeg_device_run(void *priv)
|
||||
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;
|
||||
}
|
||||
|
@ -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;
|
||||
};
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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:
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
mutex_lock(&group->lock);
|
||||
|
||||
/* 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);
|
||||
}
|
||||
|
||||
/* 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;
|
||||
|
||||
master_id = rvin_group_id_to_master(vin->id);
|
||||
|
||||
if (WARN_ON(!group->vin[master_id])) {
|
||||
ret = -ENODEV;
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
if (!mask_new) {
|
||||
ret = -EMLINK;
|
||||
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;
|
||||
|
||||
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_setup_links(struct rvin_dev *vin)
|
||||
static int rvin_csi2_create_link(struct rvin_group *group, unsigned int id,
|
||||
const struct rvin_group_route *route)
|
||||
|
||||
{
|
||||
const struct rvin_group_route *route;
|
||||
int ret = -EINVAL;
|
||||
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;
|
||||
|
||||
/* 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;
|
||||
|
||||
/* Check that VIN' master is part of the group. */
|
||||
if (!vin->group->vin[rvin_group_id_to_master(route->vin)])
|
||||
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];
|
||||
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) {
|
||||
vin_err(vin, "Error adding link from %s to %s\n",
|
||||
source->name, sink->name);
|
||||
break;
|
||||
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->chsel; route++) {
|
||||
/* Check that VIN' master is part of the group. */
|
||||
if (!vin->group->vin[route->master])
|
||||
continue;
|
||||
|
||||
/* Check that CSI-2 is part of the group. */
|
||||
if (!vin->group->remotes[route->csi].subdev)
|
||||
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 = 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 */ }
|
||||
};
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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.
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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);
|
||||
|
||||
/*
|
||||
|
@ -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 @@ static int s2250_probe(struct i2c_client *client,
|
||||
i2c_unregister_device(audio);
|
||||
v4l2_ctrl_handler_free(&state->hdl);
|
||||
kfree(state);
|
||||
return -EIO;
|
||||
return err;
|
||||
}
|
||||
|
||||
static int s2250_remove(struct i2c_client *client)
|
||||
|
@ -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,
|
||||
};
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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")
|
||||
}
|
||||
},
|
||||
{}
|
||||
};
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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,
|
||||
|
@ -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");
|
||||
|
@ -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;
|
||||
|
@ -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));
|
||||
}
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user