media: rockchip: vicap support one camera separate to multi camera

Signed-off-by: Zefa Chen <zefa.chen@rock-chips.com>
Change-Id: I39170a161636ec9bf9b1b8069736aa5e54af023d
This commit is contained in:
Zefa Chen
2022-10-03 20:45:08 +08:00
committed by Tao Huang
parent 25ef1c071c
commit 35559e36f5
5 changed files with 1025 additions and 64 deletions

View File

@@ -1018,9 +1018,8 @@ cif_input_fmt *rkcif_get_input_fmt(struct rkcif_device *dev, struct v4l2_rect *r
}
}
csi_info->capture_info = capture_info;
} else {
csi_info->capture_info.mode = RKMODULE_CAPTURE_MODE_NONE;
}
for (i = 0; i < ARRAY_SIZE(in_fmts); i++)
if (fmt.format.code == in_fmts[i].mbus_code &&
fmt.format.field == in_fmts[i].field)
@@ -2502,6 +2501,7 @@ static void rkcif_assign_new_buffer_init(struct rkcif_stream *stream,
unsigned long flags;
struct rkcif_dummy_buffer *dummy_buf = &dev->hw_dev->dummy_buf;
struct csi_channel_info *channel = &dev->channels[channel_id];
struct rkcif_stream *buf_stream = stream;
stream->lack_buf_cnt = 0;
if (mbus_cfg->type == V4L2_MBUS_CSI2_DPHY ||
@@ -2521,13 +2521,14 @@ static void rkcif_assign_new_buffer_init(struct rkcif_stream *stream,
spin_lock_irqsave(&stream->vbq_lock, flags);
if (!stream->curr_buf) {
if (!list_empty(&stream->buf_head)) {
stream->curr_buf = list_first_entry(&stream->buf_head,
if (!list_empty(&buf_stream->buf_head)) {
stream->curr_buf = list_first_entry(&buf_stream->buf_head,
struct rkcif_buffer,
queue);
v4l2_dbg(4, rkcif_debug, &dev->v4l2_dev, "%s %d, stream[%d] buf idx %d\n",
__func__, __LINE__, stream->id, stream->curr_buf->vb.vb2_buf.index);
list_del(&stream->curr_buf->queue);
atomic_inc(&buf_stream->sub_stream_buf_cnt);
}
}
@@ -2591,13 +2592,17 @@ static void rkcif_assign_new_buffer_init(struct rkcif_stream *stream,
}
}
} else {
if (channel->capture_info.mode == RKMODULE_ONE_CH_TO_MULTI_ISP &&
channel->capture_info.one_to_multi.frame_pattern[0] == 1)
buf_stream = &dev->stream[dev->sditf[1]->connect_id];
if (!stream->next_buf) {
if (!list_empty(&stream->buf_head)) {
stream->next_buf = list_first_entry(&stream->buf_head,
if (!list_empty(&buf_stream->buf_head)) {
stream->next_buf = list_first_entry(&buf_stream->buf_head,
struct rkcif_buffer, queue);
v4l2_dbg(4, rkcif_debug, &dev->v4l2_dev, "%s %d, stream[%d] buf idx %d\n",
__func__, __LINE__, stream->id, stream->next_buf->vb.vb2_buf.index);
list_del(&stream->next_buf->queue);
atomic_inc(&buf_stream->sub_stream_buf_cnt);
} else if (stream->curr_buf) {
stream->next_buf = stream->curr_buf;
}
@@ -2673,6 +2678,38 @@ static void rkcif_assign_new_buffer_init(struct rkcif_stream *stream,
stream->buf_owner = RKCIF_DMAEN_BY_VICAP;
}
static struct rkcif_stream *rkcif_get_update_buffer_stream(struct rkcif_stream *stream)
{
struct rkcif_device *dev = stream->cifdev;
struct rkcif_stream *buf_stream = NULL;
u32 i = 0, pattern_cnt = 0, tmp = 0;
for (i = 0; i < dev->channels[0].capture_info.one_to_multi.isp_num; i++)
pattern_cnt += dev->channels[0].capture_info.one_to_multi.frame_pattern[i];
if (pattern_cnt == 0) {
v4l2_info(&dev->v4l2_dev,
"stream[%d] pattern_cnt is %d, pls check it\n",
stream->id, pattern_cnt);
return NULL;
}
tmp = (stream->frame_idx + 1) % pattern_cnt;
pattern_cnt = 0;
for (i = 0; i < dev->channels[0].capture_info.one_to_multi.isp_num; i++) {
pattern_cnt += dev->channels[0].capture_info.one_to_multi.frame_pattern[i];
if (tmp < pattern_cnt) {
buf_stream = &dev->stream[i];
break;
}
}
if (buf_stream == NULL)
buf_stream = stream;
if (dev->exp_dbg)
v4l2_info(&dev->v4l2_dev,
"stream[%d] update buffer\n", buf_stream->id);
return buf_stream;
}
static int rkcif_assign_new_buffer_update(struct rkcif_stream *stream,
int channel_id)
{
@@ -2684,8 +2721,9 @@ static int rkcif_assign_new_buffer_update(struct rkcif_stream *stream,
struct csi_channel_info *channel = &dev->channels[channel_id];
struct rkisp_rx_buf *dbufs = NULL;
struct dma_buf *dbuf = NULL;
struct rkcif_stream *buf_stream = stream;
int ret = 0;
u32 buff_addr_y, buff_addr_cbcr;
u32 buff_addr_y = 0, buff_addr_cbcr = 0;
unsigned long flags;
if (mbus_cfg->type == V4L2_MBUS_CSI2_DPHY ||
@@ -2711,8 +2749,18 @@ static int rkcif_assign_new_buffer_update(struct rkcif_stream *stream,
goto stop_dma;
}
if (dev->channels[0].capture_info.mode == RKMODULE_ONE_CH_TO_MULTI_ISP)
buf_stream = rkcif_get_update_buffer_stream(stream);
spin_lock_irqsave(&stream->vbq_lock, flags);
if (!list_empty(&stream->buf_head)) {
if (dev->channels[0].capture_info.mode == RKMODULE_ONE_CH_TO_MULTI_ISP &&
(buf_stream->state != RKCIF_STATE_STREAMING || buf_stream->stopping)) {
buffer = NULL;
if (stream->frame_phase == CIF_CSI_FRAME0_READY)
stream->curr_buf = NULL;
else
stream->next_buf = NULL;
} else if (!list_empty(&buf_stream->buf_head)) {
if (!dummy_buf->vaddr &&
stream->curr_buf == stream->next_buf &&
@@ -2722,7 +2770,7 @@ static int rkcif_assign_new_buffer_update(struct rkcif_stream *stream,
if (stream->frame_phase == CIF_CSI_FRAME0_READY) {
if (!stream->curr_buf)
ret = -EINVAL;
stream->curr_buf = list_first_entry(&stream->buf_head,
stream->curr_buf = list_first_entry(&buf_stream->buf_head,
struct rkcif_buffer, queue);
if (stream->curr_buf) {
list_del(&stream->curr_buf->queue);
@@ -2743,7 +2791,7 @@ static int rkcif_assign_new_buffer_update(struct rkcif_stream *stream,
}
} else {
stream->next_buf = list_first_entry(&stream->buf_head,
stream->next_buf = list_first_entry(&buf_stream->buf_head,
struct rkcif_buffer, queue);
if (stream->next_buf) {
list_del(&stream->next_buf->queue);
@@ -2789,6 +2837,30 @@ static int rkcif_assign_new_buffer_update(struct rkcif_stream *stream,
if (buffer) {
buff_addr_y = buffer->buff_addr[RKCIF_PLANE_Y];
buff_addr_cbcr = buffer->buff_addr[RKCIF_PLANE_CBCR];
if (stream->dma_en & RKCIF_DMAEN_BY_ISP) {
if (stream->buf_replace_cnt < 2)
stream->buf_replace_cnt++;
if (stream->frame_phase == CIF_CSI_FRAME0_READY &&
stream->next_buf)
dbuf = stream->next_buf->dbuf;
else if (stream->frame_phase == CIF_CSI_FRAME1_READY &&
stream->curr_buf)
dbuf = stream->curr_buf->dbuf;
if (dbuf) {
list_for_each_entry(dbufs, &stream->rx_buf_head_vicap, list) {
if (dbufs->dbuf == dbuf)
break;
}
}
if (dbufs)
rkcif_s_rx_buffer(stream, dbufs);
}
} else if (dummy_buf) {
buff_addr_y = dummy_buf->dma_addr;
buff_addr_cbcr = dummy_buf->dma_addr;
}
if (buff_addr_y) {
if (rkcif_get_interlace_mode(stream) == RKCIF_INTERLACE_SOFT &&
stream->frame_phase == CIF_CSI_FRAME1_READY) {
if (channel->capture_info.mode == RKMODULE_MULTI_DEV_COMBINE_ONE) {
@@ -2819,25 +2891,6 @@ static int rkcif_assign_new_buffer_update(struct rkcif_stream *stream,
rkcif_write_register(dev, frm_addr_uv, buff_addr_cbcr);
}
}
if (stream->dma_en & RKCIF_DMAEN_BY_ISP) {
if (stream->buf_replace_cnt < 2)
stream->buf_replace_cnt++;
if (stream->frame_phase == CIF_CSI_FRAME0_READY &&
stream->next_buf)
dbuf = stream->next_buf->dbuf;
else if (stream->frame_phase == CIF_CSI_FRAME1_READY &&
stream->curr_buf)
dbuf = stream->curr_buf->dbuf;
if (dbuf) {
list_for_each_entry(dbufs, &stream->rx_buf_head_vicap, list) {
if (dbufs->dbuf == dbuf)
break;
}
}
if (dbufs)
rkcif_s_rx_buffer(stream, dbufs);
}
}
spin_unlock_irqrestore(&stream->vbq_lock, flags);
return ret;
@@ -4476,6 +4529,8 @@ static int rkcif_csi_stream_start(struct rkcif_stream *stream, unsigned int mode
struct rkcif_sensor_info *active_sensor = dev->active_sensor;
enum v4l2_mbus_type mbus_type = active_sensor->mbus.type;
struct csi_channel_info *channel;
int isp_num = dev->channels[0].capture_info.one_to_multi.isp_num;
struct rkcif_pipeline *p = &dev->pipe;
u32 ret = 0;
int i;
@@ -4503,6 +4558,14 @@ static int rkcif_csi_stream_start(struct rkcif_stream *stream, unsigned int mode
}
}
rkcif_csi_channel_init(stream, channel);
if (dev->channels[0].capture_info.mode == RKMODULE_ONE_CH_TO_MULTI_ISP) {
if (atomic_read(&p->stream_cnt) < isp_num - 1)
goto one_to_multi_skip;
else
*channel = dev->channels[0];
}
if (stream->state != RKCIF_STATE_STREAMING) {
if (mode == RKCIF_STREAM_MODE_CAPTURE) {
stream->dma_en |= RKCIF_DMAEN_BY_VICAP;
@@ -4549,6 +4612,7 @@ static int rkcif_csi_stream_start(struct rkcif_stream *stream, unsigned int mode
}
}
}
one_to_multi_skip:
if (stream->state != RKCIF_STATE_STREAMING) {
stream->line_int_cnt = 0;
if (stream->is_line_wake_up)
@@ -4990,7 +5054,9 @@ void rkcif_buf_queue(struct vb2_buffer *vb)
}
spin_lock_irqsave(&stream->vbq_lock, flags);
list_add_tail(&cifbuf->queue, &stream->buf_head);
cifbuf->id = stream->id;
spin_unlock_irqrestore(&stream->vbq_lock, flags);
if (stream->dma_en & RKCIF_DMAEN_BY_ISP && (!cifbuf->dbuf)) {
struct rkisp_rx_buf *dbufs = NULL;
@@ -5010,12 +5076,14 @@ void rkcif_buf_queue(struct vb2_buffer *vb)
}
if (stream->cifdev->workmode == RKCIF_WORKMODE_PINGPONG &&
stream->lack_buf_cnt &&
stream->cur_stream_mode & RKCIF_STREAM_MODE_CAPTURE)
stream->cur_stream_mode & RKCIF_STREAM_MODE_CAPTURE &&
stream->cifdev->channels[0].capture_info.mode != RKMODULE_ONE_CH_TO_MULTI_ISP)
rkcif_check_buffer_update_pingpong(stream, stream->id);
v4l2_dbg(3, rkcif_debug, &stream->cifdev->v4l2_dev,
"stream[%d] buf queue, index: %d, dma_addr 0x%x\n",
stream->id, vb->index, cifbuf->buff_addr[0]);
atomic_inc(&stream->buf_cnt);
v4l2_dbg(3, rkcif_debug, &stream->cifdev->v4l2_dev,
"stream[%d] buf queue, index: %d, dma_addr 0x%x, dbuf %p, mem_priv %p\n",
stream->id, vb->index, cifbuf->buff_addr[0], cifbuf->vb.vb2_buf.planes[0].dbuf,
cifbuf->vb.vb2_buf.planes[0].mem_priv);
}
void rkcif_free_rx_buf(struct rkcif_stream *stream, int buf_num)
@@ -5466,6 +5534,78 @@ static void rkcif_detach_sync_mode(struct rkcif_device *cif_dev)
mutex_unlock(&hw->dev_lock);
}
static void rkcif_clean_state_one_to_multi_mode(struct rkcif_device *dev)
{
struct sditf_priv *priv = NULL;
struct sditf_effect_exp *effect_exp;
struct sditf_effect_time *effect_time;
struct sditf_effect_gain *effect_gain;
struct sditf_time *time;
struct sditf_gain *gain;
int i = 0;
while (work_busy(&dev->exp_work)) {
usleep_range(2000, 3000);
i++;
if (i > 5)
break;
}
for (i = 0; i < dev->sditf_cnt; i++) {
priv = dev->sditf[i];
if (priv) {
atomic_set(&priv->frm_sync_seq, 0);
priv->frame_idx.cur_frame_idx = 0;
priv->frame_idx.total_frame_idx = 0;
while (!list_empty(&priv->effect_exp_head)) {
effect_exp = list_first_entry(&priv->effect_exp_head,
struct sditf_effect_exp, list);
if (effect_exp) {
list_del(&effect_exp->list);
kfree(effect_exp);
effect_exp = NULL;
}
}
while (!list_empty(&priv->time_head)) {
time = list_first_entry(&priv->time_head,
struct sditf_time, list);
if (time) {
list_del(&time->list);
kfree(time);
time = NULL;
}
}
while (!list_empty(&priv->time_head)) {
gain = list_first_entry(&priv->gain_head,
struct sditf_gain, list);
if (gain) {
list_del(&gain->list);
kfree(gain);
gain = NULL;
}
}
}
}
while (!list_empty(&dev->effect_time_head)) {
effect_time = list_first_entry(&dev->effect_time_head,
struct sditf_effect_time, list);
if (effect_time) {
list_del(&effect_time->list);
kfree(effect_time);
effect_time = NULL;
}
}
while (!list_empty(&dev->effect_gain_head)) {
effect_gain = list_first_entry(&dev->effect_gain_head,
struct sditf_effect_gain, list);
if (effect_gain) {
list_del(&effect_gain->list);
kfree(effect_gain);
effect_gain = NULL;
}
}
}
void rkcif_do_stop_stream(struct rkcif_stream *stream,
enum rkcif_stream_mode mode)
{
@@ -5501,8 +5641,10 @@ void rkcif_do_stop_stream(struct rkcif_stream *stream,
fs_time = stream->readout.fs_timestamp;
spin_unlock_irqrestore(&stream->fps_lock, flags);
cur_time = rkcif_time_get_ns(dev);
if (cur_time > fs_time &&
cur_time - fs_time < (frame_time_ns - 10000000)) {
if ((cur_time > fs_time &&
cur_time - fs_time < (frame_time_ns - 10000000)) ||
(dev->channels[0].capture_info.mode == RKMODULE_ONE_CH_TO_MULTI_ISP &&
stream->id != 0)) {
spin_lock_irqsave(&stream->vbq_lock, flags);
if (stream->dma_en & RKCIF_DMAEN_BY_VICAP)
stream->to_stop_dma = RKCIF_DMAEN_BY_VICAP;
@@ -5554,6 +5696,11 @@ void rkcif_do_stop_stream(struct rkcif_stream *stream,
!stream->is_wait_dma_stop,
msecs_to_jiffies(1000));
}
if (!atomic_read(&dev->pipe.stream_cnt) &&
dev->channels[0].capture_info.mode == RKMODULE_ONE_CH_TO_MULTI_ISP)
rkcif_clean_state_one_to_multi_mode(dev);
if ((mode & RKCIF_STREAM_MODE_CAPTURE) == RKCIF_STREAM_MODE_CAPTURE) {
/* release buffers */
spin_lock_irqsave(&stream->vbq_lock, flags);
@@ -5578,6 +5725,14 @@ void rkcif_do_stop_stream(struct rkcif_stream *stream,
stream->id, buf->buff_addr[0]);
vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
}
while (!list_empty(&stream->buf_head_multi_cache)) {
buf = list_first_entry(&stream->buf_head_multi_cache,
struct rkcif_buffer, queue);
if (buf) {
list_del(&buf->queue);
vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
}
}
INIT_LIST_HEAD(&stream->buf_head);
while (!list_empty(&stream->vb_done_list)) {
buf = list_first_entry(&stream->vb_done_list,
@@ -5635,6 +5790,8 @@ void rkcif_do_stop_stream(struct rkcif_stream *stream,
dev->wait_line = 0;
stream->is_line_wake_up = false;
}
if (atomic_read(&dev->pipe.stream_cnt) == 0)
atomic_set(&stream->sub_stream_buf_cnt, 0);
if (can_reset && hw_dev->dummy_buf.vaddr)
rkcif_destroy_dummy_buf(stream);
}
@@ -5645,6 +5802,8 @@ void rkcif_do_stop_stream(struct rkcif_stream *stream,
if (mode == stream->cur_stream_mode)
rkcif_detach_sync_mode(dev);
if (!atomic_read(&dev->pipe.stream_cnt) && dev->is_alloc_buf_user)
rkcif_free_buf_by_user_require(dev);
stream->cur_stream_mode &= ~mode;
v4l2_info(&dev->v4l2_dev, "stream[%d] stopping finished, dma_en 0x%x\n", stream->id, stream->dma_en);
mutex_unlock(&dev->stream_lock);
@@ -6715,10 +6874,13 @@ static void rkcif_attach_sync_mode(struct rkcif_device *cifdev)
sync_cfg.group = 0;
} else {
for (j = 0; j < cifdev->sditf_cnt; j++) {
ret |= v4l2_subdev_call(cifdev->sditf[j]->sensor_sd,
core, ioctl,
RKMODULE_GET_SYNC_MODE,
&sync_type);
if (cifdev->sditf[j]->sensor_sd)
ret |= v4l2_subdev_call(cifdev->sditf[j]->sensor_sd,
core, ioctl,
RKMODULE_GET_SYNC_MODE,
&sync_type);
else
ret = -EINVAL;
if (!ret && sync_type)
break;
}
@@ -6726,10 +6888,13 @@ static void rkcif_attach_sync_mode(struct rkcif_device *cifdev)
sync_cfg.type = sync_type;
else
sync_cfg.type = NO_SYNC_MODE;
ret = v4l2_subdev_call(cifdev->sditf[j]->sensor_sd,
core, ioctl,
RKMODULE_GET_GROUP_ID,
&sync_group);
if (cifdev->sditf[0]->sensor_sd)
ret = v4l2_subdev_call(cifdev->sditf[0]->sensor_sd,
core, ioctl,
RKMODULE_GET_GROUP_ID,
&sync_group);
else
ret = -EINVAL;
if (!ret && sync_group < RKCIF_MAX_GROUP)
sync_cfg.group = sync_group;
else
@@ -6767,10 +6932,13 @@ static void rkcif_attach_sync_mode(struct rkcif_device *cifdev)
priv = dev->sditf[0];
if (priv && priv->is_combine_mode && dev->sditf_cnt <= RKCIF_MAX_SDITF) {
for (j = 0; j < dev->sditf_cnt; j++) {
ret |= v4l2_subdev_call(dev->sditf[j]->sensor_sd,
core, ioctl,
RKMODULE_GET_SYNC_MODE,
&sync_type);
if (dev->sditf[j]->sensor_sd)
ret |= v4l2_subdev_call(dev->sditf[j]->sensor_sd,
core, ioctl,
RKMODULE_GET_SYNC_MODE,
&sync_type);
else
ret = -EINVAL;
if (!ret && sync_type) {
priv = dev->sditf[j];
break;
@@ -6780,10 +6948,13 @@ static void rkcif_attach_sync_mode(struct rkcif_device *cifdev)
sync_cfg.type = sync_type;
else
sync_cfg.type = NO_SYNC_MODE;
ret = v4l2_subdev_call(priv->sensor_sd,
core, ioctl,
RKMODULE_GET_GROUP_ID,
&sync_group);
if (priv->sensor_sd)
ret = v4l2_subdev_call(priv->sensor_sd,
core, ioctl,
RKMODULE_GET_GROUP_ID,
&sync_group);
else
ret = -EINVAL;
if (!ret && sync_group < RKCIF_MAX_GROUP)
sync_cfg.group = sync_group;
else
@@ -7004,9 +7175,15 @@ int rkcif_do_start_stream(struct rkcif_stream *stream, enum rkcif_stream_mode mo
} else {
ret = rkcif_stream_start(stream, mode);
}
if (ret < 0)
goto destroy_buf;
if (stream->cur_stream_mode == RKCIF_STREAM_MODE_NONE &&
dev->channels[0].capture_info.mode == RKMODULE_ONE_CH_TO_MULTI_ISP &&
stream->id == 0) {
for (i = 0; i < dev->sditf_cnt; i++)
sditf_get_default_exp(dev->sditf[i]);
schedule_work(&dev->exp_work);
}
if (stream->cur_stream_mode == RKCIF_STREAM_MODE_NONE) {
ret = video_device_pipeline_start(&node->vdev, &dev->pipe.pipe);
@@ -7311,6 +7488,7 @@ void rkcif_stream_init(struct rkcif_device *dev, u32 id)
stream->cifdev = dev;
INIT_LIST_HEAD(&stream->buf_head);
INIT_LIST_HEAD(&stream->buf_head_multi_cache);
INIT_LIST_HEAD(&stream->rx_buf_head);
INIT_LIST_HEAD(&stream->rx_buf_head_vicap);
INIT_LIST_HEAD(&stream->rockit_buf_head);
@@ -7384,6 +7562,7 @@ void rkcif_stream_init(struct rkcif_device *dev, u32 id)
init_completion(&stream->stop_complete);
stream->is_wait_stop_complete = false;
stream->thunderboot_skip_interval = get_rk_cam_skip_frame_interval();
atomic_set(&stream->sub_stream_buf_cnt, 0);
}
static int rkcif_fh_open(struct file *filp)
@@ -7987,6 +8166,77 @@ static bool rkcif_check_can_be_online(struct rkcif_device *cif_dev)
return true;
}
static void rkcif_alloc_buf_by_user_require(struct rkcif_device *dev,
struct rkcif_buffer_info *buf_info)
{
struct rkcif_stream *detect_stream = &dev->stream[0];
struct v4l2_pix_format_mplane *pixm = &detect_stream->pixm;
struct rkcif_extend_info *extend_line = &detect_stream->extend_line;
const struct v4l2_plane_pix_format *plane_fmt;
int ret = 0;
int i = 0;
int height = 0;
int h = 0;
u32 size = 0;
bool is_extended = false;
is_extended = rkcif_is_extending_line_for_height(dev,
detect_stream,
detect_stream->cif_fmt_in);
if (detect_stream->crop_enable)
height = detect_stream->crop[CROP_SRC_ACT].height;
else
height = pixm->height;
if (is_extended && extend_line->is_extended) {
height = extend_line->pixm.height;
pixm = &extend_line->pixm;
}
h = round_up(height, MEMORY_ALIGN_ROUND_UP_HEIGHT);
plane_fmt = &pixm->plane_fmt[0];
size = plane_fmt->sizeimage / height * h;
for (i = 0; i < buf_info->buf_num; i++) {
if (!dev->buf_user[i]) {
dev->buf_user[i] = kzalloc(sizeof(*dev->buf_user[i]), GFP_KERNEL);
if (!dev->buf_user[i]) {
buf_info->buf_num = i;
break;
}
}
dev->buf_user[i]->is_need_dbuf = true;
dev->buf_user[i]->is_need_dmafd = true;
dev->buf_user[i]->is_need_vaddr = true;
dev->buf_user[i]->size = size;
ret = rkcif_alloc_buffer(dev, dev->buf_user[i]);
if (ret) {
buf_info->buf_num = i;
kfree(dev->buf_user[i]);
dev->buf_user[i] = NULL;
break;
}
buf_info->dma_fd[i] = dev->buf_user[i]->dma_fd;
}
if (buf_info->buf_num > 0)
dev->is_alloc_buf_user = true;
}
void rkcif_free_buf_by_user_require(struct rkcif_device *dev)
{
int i = 0;
while (i < VB2_MAX_FRAME) {
if (dev->buf_user[i]) {
rkcif_free_buffer(dev, dev->buf_user[i]);
kfree(dev->buf_user[i]);
dev->buf_user[i] = NULL;
} else {
break;
}
i++;
}
dev->is_alloc_buf_user = false;
}
static int rkcif_do_reset_work(struct rkcif_device *cif_dev,
enum rkmodule_reset_src reset_src);
static long rkcif_ioctl_default(struct file *file, void *fh,
@@ -7998,11 +8248,13 @@ static long rkcif_ioctl_default(struct file *file, void *fh,
struct v4l2_rect rect;
struct csi_channel_info csi_info;
struct rkcif_fps fps;
struct rkcif_buffer_info *buf_info = NULL;
struct rkmodule_capture_info *capture_info;
int reset_src;
struct rkcif_quick_stream_param *stream_param;
bool is_single_dev = false;
struct v4l2_subdev *sd;
int ret = -EINVAL;
int ret = 0;
int i = 0;
int stream_num = 0;
bool is_can_be_online = false;
@@ -8176,11 +8428,48 @@ static long rkcif_ioctl_default(struct file *file, void *fh,
v4l2_subdev_call(dev->terminal_sensor.sd, core, ioctl,
RKMODULE_SET_QUICK_STREAM, &on);
break;
case RKCIF_CMD_ALLOC_BUF:
buf_info = (struct rkcif_buffer_info *)arg;
if (buf_info == NULL)
return -ENOMEM;
if (buf_info->buf_num > VIDEO_MAX_FRAME) {
v4l2_err(&dev->v4l2_dev, "alloc buf fail, max buf num %d\n",
VIDEO_MAX_FRAME);
return -EINVAL;
}
mutex_lock(&dev->stream_lock);
if (dev->is_alloc_buf_user) {
v4l2_err(&dev->v4l2_dev, "it's already alloc buf, release buf before alloc new buf\n");
mutex_unlock(&dev->stream_lock);
return -EINVAL;
}
rkcif_alloc_buf_by_user_require(dev, buf_info);
mutex_unlock(&dev->stream_lock);
break;
case RKCIF_CMD_FREE_BUF:
mutex_lock(&dev->stream_lock);
if (dev->is_alloc_buf_user)
rkcif_free_buf_by_user_require(dev);
mutex_unlock(&dev->stream_lock);
break;
case RKMODULE_SET_CAPTURE_MODE:
capture_info = (struct rkmodule_capture_info *)arg;
if (capture_info->mode == RKMODULE_ONE_CH_TO_MULTI_ISP) {
for (i = 0; i < capture_info->one_to_multi.isp_num; i++) {
if (capture_info->one_to_multi.frame_pattern[i] == 0 ||
capture_info->one_to_multi.frame_pattern[i] > 32)
return -EINVAL;
}
}
dev->channels[0].capture_info = *capture_info;
v4l2_info(&dev->v4l2_dev,
"set capture mode %d\n", dev->channels[0].capture_info.mode);
break;
default:
return -EINVAL;
}
return 0;
return ret;
}
static const struct v4l2_ioctl_ops rkcif_v4l2_ioctl_ops = {
@@ -8225,6 +8514,16 @@ void rkcif_vb_done_oneframe(struct rkcif_stream *stream,
atomic_dec(&stream->buf_cnt);
}
static void rkcif_vb_done_one_to_multi(struct rkcif_device *dev,
struct rkcif_buffer *active_buf)
{
struct rkcif_stream *stream = &dev->stream[active_buf->id];
struct sditf_priv *priv = dev->sditf[stream->id];
active_buf->vb.sequence = priv->frame_idx.cur_frame_idx - 1;
rkcif_vb_done_oneframe(stream, &active_buf->vb);
}
static void rkcif_tasklet_handle(unsigned long data)
{
struct rkcif_stream *stream = (struct rkcif_stream *)data;
@@ -8240,7 +8539,11 @@ static void rkcif_tasklet_handle(unsigned long data)
buf = list_first_entry(&local_list,
struct rkcif_buffer, queue);
list_del(&buf->queue);
rkcif_vb_done_oneframe(stream, &buf->vb);
atomic_dec(&stream->cifdev->stream[buf->id].sub_stream_buf_cnt);
if (stream->cifdev->channels[0].capture_info.mode == RKMODULE_ONE_CH_TO_MULTI_ISP)
rkcif_vb_done_one_to_multi(stream->cifdev, buf);
else
rkcif_vb_done_oneframe(stream, &buf->vb);
}
}
@@ -9498,6 +9801,8 @@ static void rkcif_buf_done_prepare(struct rkcif_stream *stream,
rkcif_buf_queue(&active_buf->vb.vb2_buf);
return;
}
if (cif_dev->channels[0].capture_info.mode == RKMODULE_ONE_CH_TO_MULTI_ISP)
vb_done->sequence /= cif_dev->channels[0].capture_info.one_to_multi.isp_num;
} else if (cif_dev->rdbk_buf[stream->id]) {
vb_done = &cif_dev->rdbk_buf[stream->id]->vb;
if (cif_dev->chip_id < CHIP_RK3588_CIF &&
@@ -11373,7 +11678,10 @@ static void rkcif_deal_sof(struct rkcif_device *cif_dev)
if (!detect_stream->thunderboot_skip_interval ||
(detect_stream->thunderboot_skip_interval &&
(detect_stream->frame_idx % detect_stream->thunderboot_skip_interval) == 0)) {
rkcif_send_sof(cif_dev);
if (cif_dev->channels[0].capture_info.mode == RKMODULE_ONE_CH_TO_MULTI_ISP)
schedule_work(&cif_dev->exp_work);
else
rkcif_send_sof(cif_dev);
if (detect_stream->cifdev->rdbk_debug &&
detect_stream->frame_idx < 15)
v4l2_info(&cif_dev->v4l2_dev,
@@ -12130,6 +12438,24 @@ static void rkcif_save_other_intstat_with_combine_mode(struct rkcif_device *cif_
}
}
static void rkcif_check_one_to_multi_sub_stream_stop_state(struct rkcif_device *cif_dev)
{
struct rkcif_stream *stream = NULL;
struct csi_channel_info *channel = &cif_dev->channels[0];
int i = 0;
if (channel->capture_info.mode != RKMODULE_ONE_CH_TO_MULTI_ISP)
return;
for (i = 1; i < channel->capture_info.one_to_multi.isp_num; i++) {
stream = &cif_dev->stream[i];
if (stream->stopping && atomic_read(&stream->sub_stream_buf_cnt) == 0) {
stream->stopping = false;
wake_up(&stream->wq_stopped);
}
}
}
/* pingpong irq for rk3588 and next */
void rkcif_irq_pingpong_v1(struct rkcif_device *cif_dev)
{
@@ -12367,6 +12693,7 @@ void rkcif_irq_pingpong_v1(struct rkcif_device *cif_dev)
}
rkcif_monitor_reset_event(cif_dev);
cif_dev->irq_stats.frm_end_cnt[stream->id]++;
rkcif_check_one_to_multi_sub_stream_stop_state(cif_dev);
}
for (i = 0; i < RKCIF_MAX_STREAM_MIPI; i++) {
@@ -12646,6 +12973,7 @@ void rkcif_irq_pingpong(struct rkcif_device *cif_dev)
}
}
cif_dev->irq_stats.frm_end_cnt[stream->id]++;
rkcif_check_one_to_multi_sub_stream_stop_state(cif_dev);
}
for (i = 0; i < RKCIF_MAX_STREAM_MIPI; i++) {
if (intstat & CSI_START_INTSTAT(i)) {

View File

@@ -1457,8 +1457,72 @@ static int rkcif_pipeline_set_stream(struct rkcif_pipeline *p, bool on)
struct rkcif_device *cif_dev = container_of(p, struct rkcif_device, pipe);
bool can_be_set = false;
int i, ret = 0;
u32 isp_num = 0;
if (cif_dev->hdr.hdr_mode == NO_HDR || cif_dev->hdr.hdr_mode == HDR_COMPR) {
if (cif_dev->channels[0].capture_info.mode == RKMODULE_ONE_CH_TO_MULTI_ISP) {
if (!on && atomic_dec_return(&p->stream_cnt) > 0)
return 0;
if (on) {
atomic_inc(&p->stream_cnt);
isp_num = cif_dev->channels[0].capture_info.one_to_multi.isp_num;
if (atomic_read(&p->stream_cnt) == 1) {
rockchip_set_system_status(SYS_STATUS_CIF0);
can_be_set = false;
} else if (atomic_read(&p->stream_cnt) == isp_num) {
can_be_set = true;
}
}
if ((on && can_be_set) || !on) {
if (on) {
cif_dev->irq_stats.csi_overflow_cnt = 0;
cif_dev->irq_stats.csi_bwidth_lack_cnt = 0;
cif_dev->irq_stats.dvp_bus_err_cnt = 0;
cif_dev->irq_stats.dvp_line_err_cnt = 0;
cif_dev->irq_stats.dvp_overflow_cnt = 0;
cif_dev->irq_stats.dvp_pix_err_cnt = 0;
cif_dev->irq_stats.all_err_cnt = 0;
cif_dev->irq_stats.csi_size_err_cnt = 0;
cif_dev->irq_stats.dvp_size_err_cnt = 0;
cif_dev->irq_stats.dvp_bwidth_lack_cnt = 0;
cif_dev->irq_stats.frm_end_cnt[0] = 0;
cif_dev->irq_stats.frm_end_cnt[1] = 0;
cif_dev->irq_stats.frm_end_cnt[2] = 0;
cif_dev->irq_stats.frm_end_cnt[3] = 0;
cif_dev->irq_stats.not_active_buf_cnt[0] = 0;
cif_dev->irq_stats.not_active_buf_cnt[1] = 0;
cif_dev->irq_stats.not_active_buf_cnt[2] = 0;
cif_dev->irq_stats.not_active_buf_cnt[3] = 0;
cif_dev->irq_stats.trig_simult_cnt[0] = 0;
cif_dev->irq_stats.trig_simult_cnt[1] = 0;
cif_dev->irq_stats.trig_simult_cnt[2] = 0;
cif_dev->irq_stats.trig_simult_cnt[3] = 0;
cif_dev->reset_watchdog_timer.is_triggered = false;
cif_dev->reset_watchdog_timer.is_running = false;
cif_dev->err_state_work.last_timestamp = 0;
cif_dev->is_toisp_reset = false;
for (i = 0; i < cif_dev->num_channels; i++)
cif_dev->reset_watchdog_timer.last_buf_wakeup_cnt[i] = 0;
cif_dev->reset_watchdog_timer.run_cnt = 0;
}
/* phy -> sensor */
for (i = 0; i < p->num_subdevs; i++) {
if (p->subdevs[i] == cif_dev->terminal_sensor.sd &&
on &&
cif_dev->is_thunderboot &&
!rk_tb_mcu_is_done()) {
cif_dev->tb_client.data = p->subdevs[i];
cif_dev->tb_client.cb = rkcif_sensor_streaming_cb;
rk_tb_client_register_cb(&cif_dev->tb_client);
} else {
ret = v4l2_subdev_call(p->subdevs[i], video, s_stream, on);
}
if (on && ret < 0 && ret != -ENOIOCTLCMD && ret != -ENODEV)
goto err_stream_off;
}
}
} else if (cif_dev->hdr.hdr_mode == NO_HDR || cif_dev->hdr.hdr_mode == HDR_COMPR) {
if ((on && atomic_inc_return(&p->stream_cnt) > 1) ||
(!on && atomic_dec_return(&p->stream_cnt) > 0))
return 0;
@@ -1824,6 +1888,7 @@ static int _set_pipeline_default_fmt(struct rkcif_device *dev)
static int subdev_asyn_register_itf(struct rkcif_device *dev)
{
struct sditf_priv *sditf = NULL;
int i = 0;
int ret = 0;
if (IS_ENABLED(CONFIG_NO_GKI)) {
@@ -1834,9 +1899,13 @@ static int subdev_asyn_register_itf(struct rkcif_device *dev)
return 0;
}
}
sditf = dev->sditf[0];
if (sditf && (!sditf->is_combine_mode) && (!dev->is_notifier_isp)) {
ret = v4l2_async_register_subdev_sensor(&sditf->sd);
if (!dev->is_notifier_isp) {
for (i = 0; i < dev->sditf_cnt; i++) {
sditf = dev->sditf[i];
if (sditf && (!sditf->is_combine_mode))
ret = v4l2_async_register_subdev_sensor(&sditf->sd);
}
dev->is_notifier_isp = true;
}
@@ -2264,6 +2333,320 @@ static void rkcif_deal_err_intr(struct work_struct *work)
rkcif_write_register_or(cif_dev, CIF_REG_MIPI_LVDS_INTEN, CSI_BANDWIDTH_LACK_V1);
}
static void rkcif_exposure_effect_sequeue_match(struct rkcif_device *dev,
struct sditf_effect_time *effect_time,
struct sditf_effect_gain *effect_gain)
{
struct sditf_effect_time *new_effect_time = NULL;
struct sditf_effect_gain *new_effect_gain = NULL;
if (effect_time->sequence < effect_gain->sequence) {
if (!list_empty(&dev->effect_time_head)) {
new_effect_time = list_first_entry(&dev->effect_time_head,
struct sditf_effect_time,
list);
if (new_effect_time) {
list_del(&new_effect_time->list);
kfree(effect_time);
effect_time = new_effect_time;
rkcif_exposure_effect_sequeue_match(dev, effect_time, effect_gain);
} else {
return;
}
} else {
return;
}
} else if (effect_time->sequence > effect_gain->sequence) {
if (!list_empty(&dev->effect_gain_head)) {
new_effect_gain = list_first_entry(&dev->effect_gain_head,
struct sditf_effect_gain,
list);
if (new_effect_gain) {
list_del(&new_effect_gain->list);
kfree(effect_gain);
effect_gain = new_effect_gain;
rkcif_exposure_effect_sequeue_match(dev, effect_time, effect_gain);
} else {
return;
}
} else {
return;
}
}
}
static void rkcif_get_cur_effect_sequeue(struct rkcif_device *dev,
u32 total_sequeue,
u32 *cur_sequeue,
u32 *cur_id)
{
u32 i = 0, pattern_cnt = 0, tmp = 0;
u32 tmp_pattern_cnt = 0, offset = 0;
for (i = 0; i < dev->channels[0].capture_info.one_to_multi.isp_num; i++)
pattern_cnt += dev->channels[0].capture_info.one_to_multi.frame_pattern[i];
if (pattern_cnt == 0) {
v4l2_err(&dev->v4l2_dev, "pattern_cnt is %d, pls check it\n", pattern_cnt);
return;
}
*cur_sequeue = total_sequeue / pattern_cnt;
tmp = total_sequeue % pattern_cnt;
pattern_cnt = 0;
for (i = 0; i < dev->channels[0].capture_info.one_to_multi.isp_num; i++) {
pattern_cnt += dev->channels[0].capture_info.one_to_multi.frame_pattern[i];
if (i > 0)
tmp_pattern_cnt += dev->channels[0].capture_info.one_to_multi.frame_pattern[i - 1];
if (tmp < pattern_cnt) {
*cur_id = i;
offset = tmp - tmp_pattern_cnt;
break;
}
}
*cur_sequeue *= dev->channels[0].capture_info.one_to_multi.frame_pattern[*cur_id];
*cur_sequeue += offset;
}
static void rkcif_update_effect_exposure(struct rkcif_device *dev)
{
struct sditf_priv *priv = NULL;
struct sditf_effect_exp *effect_exp = NULL;
struct sditf_effect_time *effect_time = NULL;
struct sditf_effect_gain *effect_gain = NULL;
u32 cur_sequeue = 0;
u32 cur_id = 0;
if (!list_empty(&dev->effect_time_head) && (!list_empty(&dev->effect_gain_head))) {
effect_time = list_first_entry(&dev->effect_time_head,
struct sditf_effect_time,
list);
if (effect_time)
list_del(&effect_time->list);
effect_gain = list_first_entry(&dev->effect_gain_head,
struct sditf_effect_gain,
list);
if (effect_gain)
list_del(&effect_gain->list);
}
if (effect_time && effect_gain) {
rkcif_exposure_effect_sequeue_match(dev, effect_time, effect_gain);
effect_exp = kzalloc(sizeof(*effect_exp), GFP_KERNEL);
if (effect_exp && effect_time && effect_gain) {
rkcif_get_cur_effect_sequeue(dev, effect_time->sequence, &cur_sequeue, &cur_id);
priv = dev->sditf[cur_id];
effect_exp->exp.sequence = cur_sequeue;
effect_exp->exp.time = effect_time->time;
effect_exp->exp.gain = effect_gain->gain;
mutex_lock(&priv->mutex);
list_add_tail(&effect_exp->list, &priv->effect_exp_head);
mutex_unlock(&priv->mutex);
sditf_event_exposure_notifier(priv, effect_exp);
} else {
v4l2_err(&dev->v4l2_dev, "Failed to alloc struct sditf_effect_exp\n");
}
if (effect_time) {
kfree(effect_time);
effect_time = NULL;
}
if (effect_gain) {
kfree(effect_gain);
effect_gain = NULL;
}
} else {
if (effect_time) {
kfree(effect_time);
effect_time = NULL;
}
if (effect_gain) {
kfree(effect_gain);
effect_gain = NULL;
}
v4l2_err(&dev->v4l2_dev, "Failed to get effect time or gain\n");
}
}
static int rkcif_get_exp_effect_stream_id(struct rkcif_device *dev, u32 effect_frame)
{
u32 i = 0, pattern_cnt = 0, tmp = 0;
int id = 0;
for (i = 0; i < dev->channels[0].capture_info.one_to_multi.isp_num; i++)
pattern_cnt += dev->channels[0].capture_info.one_to_multi.frame_pattern[i];
if (pattern_cnt == 0)
return -EINVAL;
tmp = effect_frame % pattern_cnt;
pattern_cnt = 0;
for (i = 0; i < dev->channels[0].capture_info.one_to_multi.isp_num; i++) {
pattern_cnt += dev->channels[0].capture_info.one_to_multi.frame_pattern[i];
if (tmp < pattern_cnt) {
id = i;
break;
}
}
return id;
}
static void rkcif_exp_work(struct work_struct *exp_work)
{
struct rkcif_device *dev = container_of(exp_work,
struct rkcif_device,
exp_work);
struct sditf_priv *priv = NULL;
struct rkcif_stream *stream = &dev->stream[0];
struct sditf_time *time;
struct sditf_gain *gain;
struct sditf_effect_time *effect_time;
struct sditf_effect_gain *effect_gain;
struct v4l2_ctrl *ctrl;
u32 cur_time = 0;
u32 cur_gain = 0;
int i = 0;
int id = 0;
int min_delay = 0;
int effect_frame = 0;
id = rkcif_get_exp_effect_stream_id(dev, stream->frame_idx - 1);
if (id < 0) {
dev_err(dev->dev, "%s %d get exp_effect stream failed\n",
__func__, __LINE__);
return;
}
priv = dev->sditf[id];
if (stream->frame_idx != 0)
sditf_event_inc_sof(priv);
if (stream->frame_idx == 0) {
cur_time = priv->cur_time;
} else {
effect_frame = stream->frame_idx + dev->exp_delay.time_delay - 1;
id = rkcif_get_exp_effect_stream_id(dev, effect_frame);
if (id < 0) {
dev_err(dev->dev, "%s %d get exp_effect stream failed\n",
__func__, __LINE__);
return;
}
priv = dev->sditf[id];
if (!list_empty(&priv->time_head)) {
time = list_first_entry(&priv->time_head,
struct sditf_time,
list);
if (time) {
mutex_lock(&priv->mutex);
list_del(&time->list);
mutex_unlock(&priv->mutex);
cur_time = time->time;
kfree(time);
}
} else {
cur_time = priv->cur_time;
}
if (dev->exp_dbg)
dev_info(priv->dev, "exp set id %d, val 0x%x\n",
priv->connect_id, cur_time);
}
ctrl = v4l2_ctrl_find(dev->terminal_sensor.sd->ctrl_handler,
V4L2_CID_EXPOSURE);
v4l2_ctrl_s_ctrl(ctrl, cur_time);
priv->cur_time = cur_time;
if (stream->frame_idx == 0) {
cur_gain = priv->cur_gain;
} else {
effect_frame = stream->frame_idx + dev->exp_delay.gain_delay - 1;
id = rkcif_get_exp_effect_stream_id(dev, effect_frame);
if (id < 0) {
dev_err(dev->dev, "%s %d get exp_effect stream failed\n",
__func__, __LINE__);
return;
}
priv = dev->sditf[id];
if (!list_empty(&priv->gain_head)) {
gain = list_first_entry(&priv->gain_head,
struct sditf_gain,
list);
if (gain) {
mutex_lock(&priv->mutex);
list_del(&gain->list);
mutex_unlock(&priv->mutex);
cur_gain = gain->gain;
kfree(gain);
}
} else {
cur_gain = priv->cur_gain;
}
if (dev->exp_dbg)
dev_info(priv->dev, "gain set id %d, val 0x%x\n",
priv->connect_id, cur_gain);
}
ctrl = v4l2_ctrl_find(dev->terminal_sensor.sd->ctrl_handler,
V4L2_CID_ANALOGUE_GAIN);
v4l2_ctrl_s_ctrl(ctrl, cur_gain);
priv->cur_gain = cur_gain;
id = rkcif_get_exp_effect_stream_id(dev, stream->frame_idx - 1);
if (id < 0) {
dev_err(dev->dev, "%s %d get exp_effect stream failed\n",
__func__, __LINE__);
return;
}
priv = dev->sditf[id];
if (stream->frame_idx == 0) {
for (i = 0; i < dev->exp_delay.time_delay; i++) {
effect_time = kzalloc(sizeof(*effect_time), GFP_KERNEL);
if (effect_time) {
effect_time->sequence = i;
effect_time->time = priv->cur_time;
list_add_tail(&effect_time->list, &dev->effect_time_head);
effect_time = NULL;
} else {
v4l2_err(&dev->v4l2_dev, "Failed to alloc struct sditf_effect_time\n");
}
}
for (i = 0; i < dev->exp_delay.gain_delay; i++) {
effect_gain = kzalloc(sizeof(*effect_gain), GFP_KERNEL);
if (effect_gain) {
effect_gain->sequence = i;
effect_gain->gain = priv->cur_gain;
list_add_tail(&effect_gain->list, &dev->effect_gain_head);
effect_gain = NULL;
} else {
v4l2_err(&dev->v4l2_dev, "Failed to alloc struct sditf_effect_gain\n");
}
}
if (dev->exp_delay.time_delay >= dev->exp_delay.gain_delay)
min_delay = dev->exp_delay.gain_delay;
else
min_delay = dev->exp_delay.time_delay;
for (i = 0; i < min_delay; i++)
rkcif_update_effect_exposure(dev);
return;
}
effect_time = kzalloc(sizeof(*effect_time), GFP_KERNEL);
if (effect_time) {
effect_time->sequence = stream->frame_idx + dev->exp_delay.time_delay - 1;
effect_time->time = cur_time;
list_add_tail(&effect_time->list, &dev->effect_time_head);
effect_time = NULL;
} else {
v4l2_err(&dev->v4l2_dev, "Failed to alloc struct sditf_effect_time\n");
}
effect_gain = kzalloc(sizeof(*effect_gain), GFP_KERNEL);
if (effect_gain) {
effect_gain->sequence = stream->frame_idx + dev->exp_delay.gain_delay - 1;
effect_gain->gain = cur_gain;
list_add_tail(&effect_gain->list, &dev->effect_gain_head);
effect_gain = NULL;
} else {
v4l2_err(&dev->v4l2_dev, "Failed to alloc struct sditf_effect_gain\n");
}
rkcif_update_effect_exposure(dev);
priv->frame_idx.cur_frame_idx++;
priv->frame_idx.total_frame_idx = stream->frame_idx;
}
int rkcif_plat_init(struct rkcif_device *cif_dev, struct device_node *node, int inf_id)
{
struct device *dev = cif_dev->dev;
@@ -2299,6 +2682,7 @@ int rkcif_plat_init(struct rkcif_device *cif_dev, struct device_node *node, int
cif_dev->rdbk_debug = 0;
cif_dev->is_stop_skip = false;
cif_dev->is_sensor_off = false;
cif_dev->exp_dbg = 0;
cif_dev->resume_mode = 0;
memset(&cif_dev->channels[0].capture_info, 0, sizeof(cif_dev->channels[0].capture_info));
@@ -2308,6 +2692,12 @@ int rkcif_plat_init(struct rkcif_device *cif_dev, struct device_node *node, int
INIT_WORK(&cif_dev->err_state_work.work, rkcif_err_print_work);
INIT_WORK(&cif_dev->sensor_work.work, rkcif_set_sensor_stream);
INIT_DELAYED_WORK(&cif_dev->work_deal_err, rkcif_deal_err_intr);
INIT_WORK(&cif_dev->exp_work, rkcif_exp_work);
cif_dev->exp_delay.time_delay = 2;
cif_dev->exp_delay.gain_delay = 2;
cif_dev->is_alloc_buf_user = false;
INIT_LIST_HEAD(&cif_dev->effect_time_head);
INIT_LIST_HEAD(&cif_dev->effect_gain_head);
if (cif_dev->inf_id == RKCIF_MIPI_LVDS && cif_dev->chip_id <= CHIP_RK3562_CIF)
cif_dev->use_hw_interlace = false;

View File

@@ -197,6 +197,7 @@ struct rkcif_buffer {
};
struct dma_buf *dbuf;
u64 fe_timestamp;
int id;
};
struct rkcif_tools_buffer {
@@ -523,6 +524,7 @@ struct rkcif_stream {
unsigned int crop_mask;
/* lock between irq and buf_queue */
struct list_head buf_head;
struct list_head buf_head_multi_cache;
struct rkcif_buffer *curr_buf;
struct rkcif_buffer *next_buf;
struct rkcif_rx_buffer *curr_buf_toisp;
@@ -575,6 +577,7 @@ struct rkcif_stream {
u32 cur_skip_frame;
int thunderboot_skip_interval;
int sequence;
atomic_t sub_stream_buf_cnt;
bool stopping;
bool crop_enable;
bool crop_dyn_en;
@@ -855,6 +858,12 @@ enum rkcif_interlace_mode {
RKCIF_INTERLACE_HW,
};
struct rkcif_stream_info {
u32 id;
u32 frame_idx_end;
struct sditf_priv *priv;
};
/*
* struct rkcif_device - ISP platform device
* @base_addr: base register address
@@ -919,6 +928,12 @@ struct rkcif_device {
dma_addr_t resmem_addr;
size_t resmem_size;
struct rk_tb_client tb_client;
struct rkcif_stream_info cur_stream;
struct rkcif_exp_delay exp_delay;
struct work_struct exp_work;
struct rkcif_dummy_buffer *buf_user[VIDEO_MAX_FRAME];
struct list_head effect_time_head;
struct list_head effect_gain_head;
bool is_start_hdr;
bool reset_work_cancel;
bool iommu_en;
@@ -934,6 +949,7 @@ struct rkcif_device {
bool use_hw_interlace;
bool is_stop_skip;
bool is_sensor_off;
bool is_alloc_buf_user;
int rdbk_debug;
struct rkcif_sync_cfg sync_cfg;
int sditf_cnt;
@@ -952,6 +968,7 @@ struct rkcif_device {
struct delayed_work work_deal_err;
u32 other_intstat[RKMODULE_MULTI_DEV_NUM];
u32 fb_res_bufs;
int exp_dbg;
};
extern struct platform_driver rkcif_plat_drv;
@@ -1050,6 +1067,7 @@ void rkcif_rockit_dev_deinit(void);
void rkcif_err_print_work(struct work_struct *work);
int rkcif_stream_suspend(struct rkcif_device *cif_dev, int mode);
int rkcif_stream_resume(struct rkcif_device *cif_dev, int mode);
void rkcif_free_buf_by_user_require(struct rkcif_device *dev);
static inline u64 rkcif_time_get_ns(struct rkcif_device *dev)
{

View File

@@ -29,6 +29,54 @@ static inline struct sditf_priv *to_sditf_priv(struct v4l2_subdev *subdev)
return container_of(subdev, struct sditf_priv, sd);
}
void sditf_event_inc_sof(struct sditf_priv *priv)
{
if (priv) {
struct v4l2_event event = {
.type = V4L2_EVENT_FRAME_SYNC,
.u.frame_sync.frame_sequence =
atomic_inc_return(&priv->frm_sync_seq) - 1,
};
v4l2_event_queue(priv->sd.devnode, &event);
if (priv->cif_dev->exp_dbg)
dev_info(priv->dev, "sof %d\n", atomic_read(&priv->frm_sync_seq) - 1);
}
}
void sditf_event_exposure_notifier(struct sditf_priv *priv,
struct sditf_effect_exp *effect_exp)
{
if (priv) {
struct v4l2_event event = {
.type = V4L2_EVENT_EXPOSURE,
};
v4l2_event_queue(priv->sd.devnode, &event);
}
}
u32 sditf_get_sof(struct sditf_priv *priv)
{
if (priv)
return atomic_read(&priv->frm_sync_seq) - 1;
return 0;
}
void sditf_set_sof(struct sditf_priv *priv, u32 seq)
{
if (priv)
atomic_set(&priv->frm_sync_seq, seq);
}
static int sditf_subscribe_event(struct v4l2_subdev *sd, struct v4l2_fh *fh,
struct v4l2_event_subscription *sub)
{
if (sub->type == V4L2_EVENT_FRAME_SYNC || sub->type == V4L2_EVENT_EXPOSURE)
return v4l2_event_subscribe(fh, sub, RKCIF_V4L2_EVENT_ELEMS, NULL);
else
return -EINVAL;
}
static void sditf_buffree_work(struct work_struct *work)
{
struct sditf_work_struct *buffree_work = container_of(work,
@@ -330,9 +378,15 @@ static long sditf_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
struct v4l2_subdev_format fmt;
struct rkcif_device *cif_dev = priv->cif_dev;
struct v4l2_subdev *sensor_sd;
struct rkcif_exp *exp;
struct rkcif_effect_exp *effect_exposure;
struct sditf_time *time;
struct sditf_gain *gain;
struct sditf_effect_exp *effect_exp;
int *pbuf_num = NULL;
int ret = 0;
int *on = NULL;
int *connect_id = NULL;
switch (cmd) {
case RKISP_VICAP_CMD_MODE:
@@ -384,6 +438,53 @@ static long sditf_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
return 0;
}
break;
case RKCIF_CMD_SET_EXPOSURE:
exp = (struct rkcif_exp *)arg;
time = kzalloc(sizeof(*time), GFP_KERNEL);
if (!time) {
ret = -ENOMEM;
return ret;
}
gain = kzalloc(sizeof(*gain), GFP_KERNEL);
if (!gain) {
ret = -ENOMEM;
kfree(time);
return ret;
}
time->time = exp->time;
gain->gain = exp->gain;
mutex_lock(&priv->mutex);
list_add_tail(&time->list, &priv->time_head);
list_add_tail(&gain->list, &priv->gain_head);
mutex_unlock(&priv->mutex);
if (cif_dev->exp_dbg)
dev_info(priv->dev, "RKCIF_CMD_SET_EXPOSURE %d\n", ret);
return ret;
case RKCIF_CMD_GET_EFFECT_EXPOSURE:
if (!list_empty(&priv->effect_exp_head)) {
effect_exp = list_first_entry(&priv->effect_exp_head,
struct sditf_effect_exp,
list);
if (effect_exp) {
effect_exposure = (struct rkcif_effect_exp *)arg;
mutex_lock(&priv->mutex);
list_del(&effect_exp->list);
mutex_unlock(&priv->mutex);
*effect_exposure = effect_exp->exp;
kfree(effect_exp);
effect_exp = NULL;
if (cif_dev->exp_dbg)
dev_info(priv->dev, "RKCIF_CMD_GET_EFFECT_EXPOSURE seq %d, time 0x%x, gain 0x%x\n",
effect_exposure->sequence, effect_exposure->time, effect_exposure->gain);
}
} else {
ret = -EINVAL;
}
return ret;
case RKCIF_CMD_GET_CONNECT_ID:
connect_id = (int *)arg;
*connect_id = priv->connect_id;
return ret;
default:
break;
}
@@ -401,9 +502,12 @@ static long sditf_compat_ioctl32(struct v4l2_subdev *sd,
struct v4l2_subdev *sensor_sd;
struct rkisp_vicap_mode *mode;
struct rkmodule_hdr_cfg *hdr_cfg;
struct rkcif_exp *exp;
struct rkcif_effect_exp *effect_expsure;
int buf_num;
int ret = 0;
int on;
int connect_id = 0;
switch (cmd) {
case RKISP_VICAP_CMD_MODE:
@@ -430,11 +534,48 @@ static long sditf_compat_ioctl32(struct v4l2_subdev *sd,
ret = -ENOMEM;
return ret;
}
if (copy_from_user(hdr_cfg, up, sizeof(*hdr_cfg))) {
kfree(hdr_cfg);
ret = sditf_ioctl(sd, cmd, hdr_cfg);
if (!ret) {
ret = copy_to_user(up, hdr_cfg, sizeof(*hdr_cfg));
if (ret)
ret = -EFAULT;
}
kfree(hdr_cfg);
return ret;
case RKCIF_CMD_SET_EXPOSURE:
exp = kzalloc(sizeof(*exp), GFP_KERNEL);
if (!exp) {
ret = -ENOMEM;
return ret;
}
if (copy_from_user(exp, up, sizeof(*exp))) {
kfree(exp);
return -EFAULT;
}
ret = sditf_ioctl(sd, cmd, hdr_cfg);
ret = sditf_ioctl(sd, cmd, exp);
kfree(exp);
return ret;
case RKCIF_CMD_GET_EFFECT_EXPOSURE:
effect_expsure = kzalloc(sizeof(*effect_expsure), GFP_KERNEL);
if (!effect_expsure) {
ret = -ENOMEM;
return ret;
}
ret = sditf_ioctl(sd, cmd, effect_expsure);
if (!ret) {
ret = copy_to_user(up, effect_expsure, sizeof(*effect_expsure));
if (ret)
ret = -EFAULT;
}
kfree(effect_expsure);
return ret;
case RKCIF_CMD_GET_CONNECT_ID:
ret = sditf_ioctl(sd, cmd, &connect_id);
if (!ret) {
ret = copy_to_user(up, &connect_id, sizeof(int));
if (ret)
ret = -EFAULT;
}
return ret;
case RKISP_VICAP_CMD_QUICK_STREAM:
if (copy_from_user(&on, up, sizeof(int)))
@@ -1018,6 +1159,8 @@ static const struct v4l2_subdev_video_ops sditf_video_ops = {
};
static const struct v4l2_subdev_core_ops sditf_core_ops = {
.subscribe_event = sditf_subscribe_event,
.unsubscribe_event = v4l2_event_subdev_unsubscribe,
.ioctl = sditf_ioctl,
#ifdef CONFIG_COMPAT
.compat_ioctl32 = sditf_compat_ioctl32,
@@ -1058,6 +1201,7 @@ static int rkcif_sditf_attach_cifdev(struct sditf_priv *sditf)
cif_dev->sditf[cif_dev->sditf_cnt] = sditf;
sditf->cif_dev = cif_dev;
sditf->connect_id = cif_dev->sditf_cnt;
cif_dev->sditf_cnt++;
return 0;
@@ -1130,6 +1274,32 @@ static const struct v4l2_ctrl_ops rkcif_sditf_ctrl_ops = {
.g_volatile_ctrl = rkcif_sditf_get_ctrl,
};
void sditf_get_default_exp(struct sditf_priv *sditf)
{
struct v4l2_ctrl *ctrl = NULL;
struct rkcif_device *dev = sditf->cif_dev;
if (dev->terminal_sensor.sd == NULL)
return;
ctrl = v4l2_ctrl_find(dev->terminal_sensor.sd->ctrl_handler,
V4L2_CID_EXPOSURE);
if (ctrl)
sditf->cur_time = ctrl->default_value;
else
sditf->cur_time = 16;
ctrl = v4l2_ctrl_find(dev->terminal_sensor.sd->ctrl_handler,
V4L2_CID_ANALOGUE_GAIN);
if (ctrl)
sditf->cur_gain = ctrl->default_value;
else
sditf->cur_gain = 16;
if (dev->exp_dbg)
dev_info(sditf->dev, "get default time 0x%x gain 0x%x\n",
sditf->cur_time, sditf->cur_gain);
}
static int sditf_notifier_bound(struct v4l2_async_notifier *notifier,
struct v4l2_subdev *subdev,
struct v4l2_async_subdev *asd)
@@ -1264,6 +1434,12 @@ static int rkcif_subdev_media_init(struct sditf_priv *priv)
atomic_set(&priv->stream_cnt, 0);
INIT_WORK(&priv->buffree_work.work, sditf_buffree_work);
INIT_LIST_HEAD(&priv->buf_free_list);
INIT_LIST_HEAD(&priv->time_head);
INIT_LIST_HEAD(&priv->gain_head);
INIT_LIST_HEAD(&priv->effect_exp_head);
priv->frame_idx.cur_frame_idx = 0;
atomic_set(&priv->frm_sync_seq, 0);
mutex_init(&priv->mutex);
return 0;
}
@@ -1282,7 +1458,8 @@ static int rkcif_subdev_probe(struct platform_device *pdev)
sd = &priv->sd;
v4l2_subdev_init(sd, &sditf_subdev_ops);
sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
sd->owner = THIS_MODULE;
sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE | V4L2_SUBDEV_FL_HAS_EVENTS;
snprintf(sd->name, sizeof(sd->name), "rockchip-cif-sditf");
sd->dev = dev;

View File

@@ -59,6 +59,38 @@ struct sditf_work_struct {
struct rkisp_rx_buffer *buf;
};
struct sditf_frame_idx {
u32 cur_frame_idx;
u32 total_frame_idx;
};
struct sditf_time {
struct list_head list;
u32 time;
};
struct sditf_gain {
struct list_head list;
u32 gain;
};
struct sditf_effect_time {
struct list_head list;
u32 sequence;
u32 time;
};
struct sditf_effect_gain {
struct list_head list;
u32 sequence;
u32 gain;
};
struct sditf_effect_exp {
struct list_head list;
struct rkcif_effect_exp exp;
};
struct sditf_priv {
struct device *dev;
struct v4l2_async_notifier notifier;
@@ -74,16 +106,32 @@ struct sditf_priv {
struct v4l2_subdev *sensor_sd;
struct sditf_work_struct buffree_work;
struct list_head buf_free_list;
struct sditf_frame_idx frame_idx;
struct mutex mutex;
atomic_t frm_sync_seq;
int buf_num;
int num_sensors;
int combine_index;
int connect_id;
bool is_combine_mode;
atomic_t power_cnt;
atomic_t stream_cnt;
struct list_head time_head;
struct list_head gain_head;
struct list_head effect_exp_head;
u32 cur_time;
u32 cur_gain;
int one_to_multi_id;
};
extern struct platform_driver rkcif_subdev_driver;
void sditf_change_to_online(struct sditf_priv *priv);
void sditf_disable_immediately(struct sditf_priv *priv);
void sditf_event_exposure_notifier(struct sditf_priv *priv,
struct sditf_effect_exp *effect_exp);
void sditf_event_inc_sof(struct sditf_priv *priv);
u32 sditf_get_sof(struct sditf_priv *priv);
void sditf_set_sof(struct sditf_priv *priv, u32 seq);
void sditf_get_default_exp(struct sditf_priv *sditf);
#endif