media: rockchip: vicap support to check group sync state

Signed-off-by: Zefa Chen <zefa.chen@rock-chips.com>
Change-Id: Iff14c0108ba1a1e913177d307e47c0b97c27f7f5
This commit is contained in:
Zefa Chen
2022-02-09 18:13:15 +08:00
committed by Tao Huang
parent d10dfe46c2
commit 1b1ec94d63
5 changed files with 102 additions and 7 deletions

View File

@@ -3102,6 +3102,8 @@ void rkcif_do_stop_stream(struct rkcif_stream *stream,
vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
}
stream->dma_en &= ~RKCIF_DMAEN_BY_VICAP;
if (dev->sync_type != RKCIF_NOSYNC_MODE)
dev->hw_dev->is_in_group_sync = false;
}
if (mode == stream->cur_stream_mode) {
@@ -6166,7 +6168,7 @@ static void rkcif_buf_done_prepare(struct rkcif_stream *stream,
if (active_buf) {
vb_done = &active_buf->vb;
vb_done->vb2_buf.timestamp = ktime_get_ns();
vb_done->vb2_buf.timestamp = stream->readout.fs_timestamp;
vb_done->sequence = stream->frame_idx;
if (stream->is_line_wake_up) {
spin_lock_irqsave(&stream->fps_lock, flags);
@@ -7192,12 +7194,51 @@ void rkcif_irq_handle_toisp(struct rkcif_device *cif_dev, unsigned int intstat_g
}
}
static void rkcif_deal_sof(struct rkcif_device *cif_dev)
static int rkcif_check_group_sync_state(struct rkcif_device *cif_dev)
{
struct rkcif_stream *detect_stream = &cif_dev->stream[0];
struct rkcif_stream *next_stream = NULL;
struct rkcif_hw *hw = cif_dev->hw_dev;
u64 fs_interval = 0;
int i = 0;
int ret = 0;
for (i = 0; i < hw->sync_config.dev_cnt; i++) {
if (hw->sync_config.mode == RKCIF_MASTER_MASTER) {
if (i < hw->sync_config.ext_master.count)
next_stream = &hw->sync_config.ext_master.cif_dev[i]->stream
[0];
else
next_stream = &hw->sync_config.int_master.cif_dev[0]->stream
[0];
} else if (hw->sync_config.mode == RKCIF_MASTER_SLAVE) {
if (i < hw->sync_config.slave.count)
next_stream = &hw->sync_config.slave.cif_dev[i]->stream
[0];
else
next_stream = &hw->sync_config.int_master.cif_dev[0]->stream
[0];
} else {
v4l2_err(&cif_dev->v4l2_dev,
"ERROR: invalid group sync mode\n");
ret = -EINVAL;
break;
}
if (detect_stream == next_stream)
continue;
fs_interval = abs(detect_stream->readout.fs_timestamp - next_stream->readout.fs_timestamp);
if (fs_interval > RKCIF_MAX_INTERVAL_NS) {
ret = -EINVAL;
break;
}
}
return ret;
}
static void rkcif_send_sof(struct rkcif_device *cif_dev)
{
struct v4l2_mbus_config *mbus = &cif_dev->active_sensor->mbus;
struct csi2_dev *csi;
unsigned long flags;
if (mbus->type == V4L2_MBUS_CSI2_DPHY ||
mbus->type == V4L2_MBUS_CSI2_CPHY) {
@@ -7208,11 +7249,55 @@ static void rkcif_deal_sof(struct rkcif_device *cif_dev)
} else {
rkcif_dvp_event_inc_sof(cif_dev);
}
}
static void rkcif_deal_sof(struct rkcif_device *cif_dev)
{
struct rkcif_stream *detect_stream = &cif_dev->stream[0];
struct rkcif_hw *hw = cif_dev->hw_dev;
struct rkcif_device *tmp_dev = NULL;
unsigned long flags;
unsigned int frame_idx = 0;
int i = 0;
int ret = 0;
detect_stream->fs_cnt_in_single_frame++;
spin_lock_irqsave(&detect_stream->fps_lock, flags);
detect_stream->readout.fs_timestamp = ktime_get_ns();
spin_unlock_irqrestore(&detect_stream->fps_lock, flags);
if (cif_dev->sync_type != RKCIF_NOSYNC_MODE && !hw->is_in_group_sync) {
ret = rkcif_check_group_sync_state(cif_dev);
if (!ret) {
hw->is_in_group_sync = true;
for (i = 0; i < hw->sync_config.dev_cnt; i++) {
if (hw->sync_config.mode == RKCIF_MASTER_MASTER) {
if (i < hw->sync_config.ext_master.count)
tmp_dev = hw->sync_config.ext_master.cif_dev[i];
else
tmp_dev = hw->sync_config.int_master.cif_dev[0];
} else if (hw->sync_config.mode == RKCIF_MASTER_SLAVE) {
if (i < hw->sync_config.slave.count)
tmp_dev = hw->sync_config.slave.cif_dev[i];
else
tmp_dev = hw->sync_config.int_master.cif_dev[0];
} else {
v4l2_err(&cif_dev->v4l2_dev,
"ERROR: invalid group sync mode\n");
}
if (tmp_dev) {
rkcif_send_sof(tmp_dev);
frame_idx = rkcif_get_sof(tmp_dev);
tmp_dev->stream[0].frame_idx = frame_idx;
tmp_dev->stream[1].frame_idx = frame_idx;
tmp_dev->stream[2].frame_idx = frame_idx;
tmp_dev->stream[3].frame_idx = frame_idx;
}
}
}
} else {
rkcif_send_sof(cif_dev);
}
}
unsigned int rkcif_irq_global(struct rkcif_device *cif_dev)
@@ -7367,10 +7452,16 @@ void rkcif_irq_pingpong_v1(struct rkcif_device *cif_dev)
if (stream->crop_dyn_en)
rkcif_dynamic_crop(stream);
if (stream->dma_en & RKCIF_DMAEN_BY_VICAP)
rkcif_update_stream(cif_dev, stream, mipi_id);
else if (stream->dma_en & RKCIF_DMAEN_BY_ISP)
if (stream->dma_en & RKCIF_DMAEN_BY_VICAP) {
if (cif_dev->sync_type == RKCIF_NOSYNC_MODE) {
rkcif_update_stream(cif_dev, stream, mipi_id);
} else {
if (cif_dev->hw_dev->is_in_group_sync)
rkcif_update_stream(cif_dev, stream, mipi_id);
}
} else if (stream->dma_en & RKCIF_DMAEN_BY_ISP) {
rkcif_update_stream_toisp(cif_dev, stream, mipi_id);
}
if (stream->to_en_dma)
rkcif_enable_dma_capture(stream);
@@ -7393,6 +7484,7 @@ void rkcif_irq_pingpong_v1(struct rkcif_device *cif_dev)
detect_stream->fs_cnt_in_single_frame);
detect_stream->is_fs_fe_not_paired = true;
detect_stream->fs_cnt_in_single_frame = 0;
cif_dev->hw_dev->is_in_group_sync = false;
} else {
detect_stream->fs_cnt_in_single_frame--;
}

View File

@@ -839,7 +839,7 @@ static void rkcif_set_sensor_streamon_in_sync_mode(struct rkcif_device *cif_dev)
if (!is_streaming) {
ret = v4l2_subdev_call(dev->terminal_sensor.sd, core, ioctl,
RKMODULE_SET_QUICK_STREAM, &on);
if (!ret)
if (ret)
dev_info(dev->dev,
"set RKMODULE_SET_QUICK_STREAM failed\n");
hw->sync_config.slave.is_streaming[i] = true;

View File

@@ -75,6 +75,7 @@
#define RKCIF_RX_BUF_MAX 8
#define RKCIF_MAX_INTERVAL_NS 5000000
/*
* for HDR mode sync buf
*/

View File

@@ -997,6 +997,7 @@ static int rkcif_plat_hw_probe(struct platform_device *pdev)
cif_hw->chip_id = data->chip_id;
cif_hw->sync_config.is_attach = false;
cif_hw->sync_config.mode = RKCIF_NOSYNC_MODE;
cif_hw->is_in_group_sync = false;
if (data->chip_id >= CHIP_RK1808_CIF) {
res = platform_get_resource_byname(pdev,
IORESOURCE_MEM,

View File

@@ -121,6 +121,7 @@ struct rkcif_hw {
const struct rkcif_hw_match_data *match_data;
struct mutex dev_lock;
struct rkcif_multi_sync_config sync_config;
bool is_in_group_sync;
};
void rkcif_hw_soft_reset(struct rkcif_hw *cif_hw, bool is_rst_iommu);