media: rockchip: isp: add link state for stream

Disable mp/sp link and enable mpfbc default for isp2.0.
Using ispp video to capture image, or disable mpfbc then
to use mp/sp.

Change-Id: I5d21cdaf212cdf77fb3c052e9ad77d1c1166ce0d
Signed-off-by: Cai YiWei <cyw@rock-chips.com>
This commit is contained in:
Cai YiWei
2020-04-08 20:45:02 +08:00
committed by Tao Huang
parent bc261bed10
commit e0e2ec0d31
8 changed files with 79 additions and 27 deletions

View File

@@ -2045,6 +2045,9 @@ static void rkisp_stop_streaming(struct vb2_queue *queue)
v4l2_dbg(1, rkisp_debug, &dev->v4l2_dev,
"%s %d\n", __func__, stream->id);
if (!stream->streaming)
return;
rkisp_stream_stop(stream);
if (stream->id == RKISP_STREAM_MP ||
stream->id == RKISP_STREAM_SP) {
@@ -2116,6 +2119,11 @@ rkisp_start_streaming(struct vb2_queue *queue, unsigned int count)
v4l2_dbg(1, rkisp_debug, &dev->v4l2_dev,
"%s %d\n", __func__, stream->id);
if (!stream->linked) {
v4l2_err(v4l2_dev, "link stream first\n");
return -EINVAL;
}
if (WARN_ON(stream->streaming))
return -EBUSY;
@@ -2727,25 +2735,14 @@ static int rkisp_register_stream_vdev(struct rkisp_stream *stream)
source = &dev->csi_dev.sd.entity;
switch (stream->id) {
case RKISP_STREAM_DMATX0:
pad = CSI_SRC_CH1;
dev->csi_dev.sink[1].linked = true;
dev->csi_dev.sink[1].index = BIT(1);
break;
case RKISP_STREAM_DMATX1:
pad = CSI_SRC_CH2;
dev->csi_dev.sink[2].linked = true;
dev->csi_dev.sink[2].index = BIT(2);
break;
case RKISP_STREAM_DMATX2:
pad = CSI_SRC_CH3;
dev->csi_dev.sink[3].linked = true;
dev->csi_dev.sink[3].index = BIT(3);
break;
case RKISP_STREAM_DMATX3:
pad = CSI_SRC_CH4;
dev->csi_dev.sink[4].linked = true;
dev->csi_dev.sink[4].index = BIT(4);
case RKISP_STREAM_DMATX0://CSI_SRC_CH1
case RKISP_STREAM_DMATX1://CSI_SRC_CH2
case RKISP_STREAM_DMATX2://CSI_SRC_CH3
case RKISP_STREAM_DMATX3://CSI_SRC_CH4
pad = stream->id;
stream->linked = true;
dev->csi_dev.sink[pad - 1].linked = true;
dev->csi_dev.sink[pad - 1].index = BIT(pad - 1);
break;
default:
source = &dev->isp_sdev.sd.entity;
@@ -2753,7 +2750,7 @@ static int rkisp_register_stream_vdev(struct rkisp_stream *stream)
}
sink = &vdev->entity;
ret = media_create_pad_link(source, pad,
sink, 0, MEDIA_LNK_FL_ENABLED);
sink, 0, stream->linked);
if (ret < 0)
goto unreg;
return 0;
@@ -2779,6 +2776,11 @@ static int rkisp_stream_init(struct rkisp_device *dev, u32 id)
init_waitqueue_head(&stream->done);
spin_lock_init(&stream->vbq_lock);
/* isp2 disable MP/SP, enable MPFBC default */
if ((id == RKISP_STREAM_SP || id == RKISP_STREAM_MP) &&
dev->isp_ver == ISP_V20)
stream->linked = false;
switch (id) {
case RKISP_STREAM_SP:
strlcpy(vdev->name, SP_VDEV_NAME,

View File

@@ -187,6 +187,7 @@ struct streams_ops {
* rkisp use shadowsock registers, so it need two buffer at a time
* @curr_buf: the buffer used for current frame
* @next_buf: the buffer used for next frame
* @linked: stream link to isp
* @done: wait frame end event queue
* @burst: burst length for Y and CB/CR
* @sequence: damtx video frame sequence
@@ -209,6 +210,7 @@ struct rkisp_stream {
bool streaming;
bool stopping;
bool frame_end;
bool linked;
wait_queue_head_t done;
unsigned int burst;
atomic_t sequence;

View File

@@ -68,6 +68,7 @@ static int rkisp_csi_link_setup(struct media_entity *entity,
{
struct v4l2_subdev *sd = media_entity_to_v4l2_subdev(entity);
struct rkisp_csi_device *csi;
struct rkisp_stream *stream = NULL;
int ret = 0;
u8 id;
@@ -77,6 +78,8 @@ static int rkisp_csi_link_setup(struct media_entity *entity,
csi = v4l2_get_subdevdata(sd);
if (local->flags & MEDIA_PAD_FL_SOURCE) {
id = local->index - 1;
if (id && id < RKISP_STREAM_DMATX3)
stream = &csi->ispdev->cap_dev.stream[id + 1];
if (flags & MEDIA_LNK_FL_ENABLED) {
if (csi->sink[id].linked) {
ret = -EBUSY;
@@ -88,7 +91,10 @@ static int rkisp_csi_link_setup(struct media_entity *entity,
csi->sink[id].linked = false;
csi->sink[id].index = 0;
}
if (stream)
stream->linked = csi->sink[id].linked;
}
return 0;
out:
v4l2_err(sd, "pad%d is already linked\n", local->index);

View File

@@ -37,7 +37,7 @@ enum hdr_op_mode {
};
enum rkisp_csi_pad {
CSI_SINK,
CSI_SINK = 0,
CSI_SRC_CH0,
CSI_SRC_CH1,
CSI_SRC_CH2,

View File

@@ -523,6 +523,9 @@ static void dmarx_stop_streaming(struct vb2_queue *queue)
{
struct rkisp_stream *stream = queue->drv_priv;
if (!stream->streaming)
return;
dmarx_stop(stream);
destroy_buf_queue(stream, VB2_BUF_STATE_ERROR);
}
@@ -535,6 +538,11 @@ static int dmarx_start_streaming(struct vb2_queue *queue,
struct v4l2_device *v4l2_dev = &dev->v4l2_dev;
int ret = -1;
if (!stream->linked) {
v4l2_err(v4l2_dev, "link stream first\n");
return -EINVAL;
}
if (WARN_ON(stream->streaming))
return -EBUSY;
@@ -872,6 +880,7 @@ static int dmarx_init(struct rkisp_device *dev, u32 id)
stream->id = id;
stream->ispdev = dev;
vdev = &stream->vnode.vdev;
stream->linked = false;
switch (id) {
case RKISP_STREAM_DMARX:
@@ -910,7 +919,7 @@ static int dmarx_init(struct rkisp_device *dev, u32 id)
source = &vdev->entity;
sink = &dev->isp_sdev.sd.entity;
return media_create_pad_link(source, 0, sink,
RKISP_ISP_PAD_SINK, 0);
RKISP_ISP_PAD_SINK, stream->linked);
}
u32 rkisp_dmarx_get_frame_id(struct rkisp_device *dev)

View File

@@ -185,8 +185,13 @@ static int mpfbc_start_stream(struct v4l2_subdev *sd)
struct rkisp_device *dev = mpfbc_dev->ispdev;
int ret;
if (WARN_ON(mpfbc_dev->en) ||
!dev->isp_inp)
if (!mpfbc_dev->linked || !dev->isp_inp) {
v4l2_err(&dev->v4l2_dev,
"mpfbc no linked or isp inval input\n");
return -EINVAL;
}
if (WARN_ON(mpfbc_dev->en))
return -EBUSY;
if (dev->isp_inp & INP_CSI ||
@@ -354,10 +359,11 @@ int rkisp_register_mpfbc_subdev(struct rkisp_device *dev,
}
/* mpfbc links */
mpfbc_dev->linked = true;
source = &dev->isp_sdev.sd.entity;
sink = &sd->entity;
ret = media_create_pad_link(source, RKISP_ISP_PAD_SOURCE_PATH,
sink, 0, MEDIA_LNK_FL_ENABLED);
sink, 0, mpfbc_dev->linked);
init_waitqueue_head(&mpfbc_dev->done);
return ret;

View File

@@ -28,6 +28,7 @@ struct rkisp_mpfbc_device {
u8 pingpong;
u8 stopping;
u8 en;
bool linked;
};
int rkisp_register_mpfbc_subdev(struct rkisp_device *dev,

View File

@@ -1557,12 +1557,14 @@ static int rkisp_subdev_link_setup(struct media_entity *entity,
{
struct v4l2_subdev *sd = media_entity_to_v4l2_subdev(entity);
struct rkisp_device *dev;
struct rkisp_stream *stream = NULL;
u8 rawrd = INP_RAWRD0 | INP_RAWRD1 | INP_RAWRD2;
if (!sd)
return -ENODEV;
dev = sd_to_isp_dev(sd);
if (!strcmp(remote->entity->name, DMA_VDEV_NAME)) {
stream = &dev->dmarx_dev.stream[RKISP_STREAM_DMARX];
if (flags & MEDIA_LNK_FL_ENABLED) {
if (dev->isp_inp)
goto err;
@@ -1581,6 +1583,7 @@ static int rkisp_subdev_link_setup(struct media_entity *entity,
dev->isp_inp &= ~INP_CSI;
}
} else if (!strcmp(remote->entity->name, DMARX0_VDEV_NAME)) {
stream = &dev->dmarx_dev.stream[RKISP_STREAM_RAWRD0];
if (flags & MEDIA_LNK_FL_ENABLED) {
if (dev->isp_inp == INP_DMARX_ISP)
goto err;
@@ -1589,6 +1592,7 @@ static int rkisp_subdev_link_setup(struct media_entity *entity,
dev->isp_inp &= ~INP_RAWRD0;
}
} else if (!strcmp(remote->entity->name, DMARX1_VDEV_NAME)) {
stream = &dev->dmarx_dev.stream[RKISP_STREAM_RAWRD1];
if (flags & MEDIA_LNK_FL_ENABLED) {
if (dev->isp_inp == INP_DMARX_ISP)
goto err;
@@ -1597,6 +1601,7 @@ static int rkisp_subdev_link_setup(struct media_entity *entity,
dev->isp_inp &= ~INP_RAWRD1;
}
} else if (!strcmp(remote->entity->name, DMARX2_VDEV_NAME)) {
stream = &dev->dmarx_dev.stream[RKISP_STREAM_RAWRD2];
if (flags & MEDIA_LNK_FL_ENABLED) {
if (dev->isp_inp == INP_DMARX_ISP)
goto err;
@@ -1604,6 +1609,22 @@ static int rkisp_subdev_link_setup(struct media_entity *entity,
} else {
dev->isp_inp &= ~INP_RAWRD2;
}
} else if (!strcmp(remote->entity->name, SP_VDEV_NAME)) {
stream = &dev->cap_dev.stream[RKISP_STREAM_SP];
if (flags & MEDIA_LNK_FL_ENABLED &&
dev->mpfbc_dev.linked)
goto err;
} else if (!strcmp(remote->entity->name, MP_VDEV_NAME)) {
stream = &dev->cap_dev.stream[RKISP_STREAM_MP];
if (flags & MEDIA_LNK_FL_ENABLED &&
dev->mpfbc_dev.linked)
goto err;
} else if (!strcmp(remote->entity->name, MPFBC_DEV_NAME)) {
if (flags & MEDIA_LNK_FL_ENABLED &&
(dev->cap_dev.stream[RKISP_STREAM_SP].linked ||
dev->cap_dev.stream[RKISP_STREAM_MP].linked))
goto err;
dev->mpfbc_dev.linked = flags & MEDIA_LNK_FL_ENABLED;
} else {
if (flags & MEDIA_LNK_FL_ENABLED) {
if (dev->isp_inp & ~(INP_DVP | rawrd))
@@ -1614,6 +1635,8 @@ static int rkisp_subdev_link_setup(struct media_entity *entity,
}
}
if (stream)
stream->linked = flags & MEDIA_LNK_FL_ENABLED;
if (dev->isp_inp & rawrd)
dev->dmarx_dev.trigger = T_MANUAL;
else
@@ -1623,8 +1646,11 @@ static int rkisp_subdev_link_setup(struct media_entity *entity,
"isp input:0x%x\n", dev->isp_inp);
return 0;
err:
v4l2_err(sd, "dmaread can't work with other input\n"
"csi dvp can't work together\n");
v4l2_err(sd, "link error %s -> %s\n"
"\tdmaread can't work with other input\n"
"\tcsi dvp can't work together\n"
"\tmpfbc can't work with mainpath/selfpath\n",
local->entity->name, remote->entity->name);
return -EINVAL;
}