media: rockchip: vicap fixes suspend/resume

Signed-off-by: Zefa Chen <zefa.chen@rock-chips.com>
Change-Id: I1d7e7d8f521fca3bda4f3599a7b34233e1a94bc2
Signed-off-by: Mingwei Yan <mingwei.yan@rock-chips.com>
This commit is contained in:
Zefa Chen
2023-07-21 10:55:50 +08:00
committed by Tao Huang
parent f331648b74
commit af37f2152d
7 changed files with 451 additions and 33 deletions
+328 -31
View File
@@ -1913,6 +1913,9 @@ static void rkcif_assign_new_buffer_init_toisp(struct rkcif_stream *stream,
} else {
rkcif_write_register(dev, frm0_addr_y, buff_addr_y);
}
} else {
if (stream->lack_buf_cnt < 2)
stream->lack_buf_cnt++;
}
if (!stream->next_buf_toisp) {
@@ -1938,6 +1941,9 @@ static void rkcif_assign_new_buffer_init_toisp(struct rkcif_stream *stream,
} else {
rkcif_write_register(dev, frm1_addr_y, buff_addr_y);
}
} else {
if (stream->lack_buf_cnt < 2)
stream->lack_buf_cnt++;
}
spin_unlock_irqrestore(&stream->vbq_lock, flags);
@@ -1970,10 +1976,7 @@ static int rkcif_assign_new_buffer_update_toisp(struct rkcif_stream *stream,
spin_lock_irqsave(&stream->vbq_lock, flags);
if (!list_empty(&stream->rx_buf_head)) {
if (stream->frame_phase == CIF_CSI_FRAME0_READY) {
if (stream->curr_buf_toisp == stream->next_buf_toisp)
active_buf = NULL;
else
active_buf = stream->curr_buf_toisp;
active_buf = stream->curr_buf_toisp;
buffer = list_first_entry(&stream->rx_buf_head,
struct rkcif_rx_buffer, list);
@@ -1999,15 +2002,13 @@ static int rkcif_assign_new_buffer_update_toisp(struct rkcif_stream *stream,
rkcif_rdbk_frame_end_toisp(stream, active_buf);
}
} else {
rkcif_s_rx_buffer(dev, &active_buf->dbufs);
if (active_buf)
rkcif_s_rx_buffer(dev, &active_buf->dbufs);
if (dev->is_support_tools && stream->tools_vdev)
rkcif_rdbk_with_tools(stream, active_buf);
}
} else if (stream->frame_phase == CIF_CSI_FRAME1_READY) {
if (stream->curr_buf_toisp == stream->next_buf_toisp)
active_buf = NULL;
else
active_buf = stream->next_buf_toisp;
active_buf = stream->next_buf_toisp;
buffer = list_first_entry(&stream->rx_buf_head,
struct rkcif_rx_buffer, list);
if (buffer) {
@@ -2032,7 +2033,8 @@ static int rkcif_assign_new_buffer_update_toisp(struct rkcif_stream *stream,
rkcif_rdbk_frame_end_toisp(stream, active_buf);
}
} else {
rkcif_s_rx_buffer(dev, &active_buf->dbufs);
if (active_buf)
rkcif_s_rx_buffer(dev, &active_buf->dbufs);
if (dev->is_support_tools && stream->tools_vdev)
rkcif_rdbk_with_tools(stream, active_buf);
}
@@ -2068,6 +2070,18 @@ static int rkcif_assign_new_buffer_update_toisp(struct rkcif_stream *stream,
"stream[%d] hold buf %x\n",
stream->id,
(u32)stream->next_buf_toisp->dummy.dma_addr);
} else {
if (stream->curr_buf_toisp)
active_buf = stream->curr_buf_toisp;
else if (stream->next_buf_toisp)
active_buf = stream->next_buf_toisp;
stream->next_buf_toisp = NULL;
stream->curr_buf_toisp = NULL;
}
if (stream->lack_buf_cnt == 2) {
stream->to_stop_dma = RKCIF_DMAEN_BY_ISP;
rkcif_stop_dma_capture(stream);
}
if (active_buf) {
if (stream->frame_idx == 1)
@@ -2078,8 +2092,6 @@ static int rkcif_assign_new_buffer_update_toisp(struct rkcif_stream *stream,
stream->last_frame_idx = stream->frame_idx;
if (dev->hdr.hdr_mode == NO_HDR) {
rkcif_s_rx_buffer(dev, &active_buf->dbufs);
if (dev->is_support_tools && stream->tools_vdev)
rkcif_rdbk_with_tools(stream, active_buf);
atomic_dec(&stream->buf_cnt);
} else {
rkcif_rdbk_frame_end_toisp(stream, active_buf);
@@ -2091,8 +2103,8 @@ static int rkcif_assign_new_buffer_update_toisp(struct rkcif_stream *stream,
stream->id,
stream->frame_idx - 1);
}
if (dev->is_support_tools && stream->tools_vdev && stream->curr_buf_toisp)
rkcif_rdbk_with_tools(stream, stream->curr_buf_toisp);
if (dev->is_support_tools && stream->tools_vdev && active_buf)
rkcif_rdbk_with_tools(stream, active_buf);
}
out_get_buf:
@@ -2152,6 +2164,7 @@ void rkcif_assign_check_buffer_update_toisp(struct rkcif_stream *stream)
int frame_phase = 0;
int frame_phase_next = 0;
bool is_early_update = false;
bool is_dual_update = false;
if (stream->curr_buf_toisp != stream->next_buf_toisp) {
if (dev->rdbk_debug > 2 &&
@@ -2169,19 +2182,19 @@ void rkcif_assign_check_buffer_update_toisp(struct rkcif_stream *stream)
vblank_ns = vblank * dev->sensor_linetime;
cur_time = ktime_get_ns();
frame_phase = stream->frame_phase & CIF_CSI_FRAME0_READY ?
CIF_CSI_FRAME0_READY : CIF_CSI_FRAME1_READY;
frame_phase_next = stream->frame_phase & CIF_CSI_FRAME0_READY ?
CIF_CSI_FRAME1_READY : CIF_CSI_FRAME0_READY;
if (dev->chip_id > CHIP_RK3568_CIF &&
dev->hdr.hdr_mode == NO_HDR &&
cur_time - stream->readout.fe_timestamp < (vblank_ns - 500000) &&
stream->lack_buf_cnt == 2 &&
stream->frame_idx > stream->last_frame_idx) {
stream->frame_idx > stream->last_frame_idx)
is_early_update = true;
frame_phase = stream->frame_phase & CIF_CSI_FRAME0_READY ?
CIF_CSI_FRAME1_READY : CIF_CSI_FRAME0_READY;
frame_phase_next = stream->frame_phase & CIF_CSI_FRAME0_READY ?
CIF_CSI_FRAME0_READY : CIF_CSI_FRAME1_READY;
} else {
frame_phase = stream->frame_phase;
}
else if (!stream->dma_en)
is_dual_update = true;
if (dev->rdbk_debug > 2 &&
stream->frame_idx < 15)
v4l2_info(&dev->v4l2_dev,
@@ -2295,6 +2308,29 @@ void rkcif_assign_check_buffer_update_toisp(struct rkcif_stream *stream)
} else {
rkcif_write_register(dev, frm_addr_y, buff_addr_y);
}
} else if (is_dual_update) {
if (mbus_cfg->type == V4L2_MBUS_CSI2_DPHY ||
mbus_cfg->type == V4L2_MBUS_CSI2_CPHY ||
mbus_cfg->type == V4L2_MBUS_CCP2) {
frm_addr_y = frame_phase_next & CIF_CSI_FRAME0_READY ?
get_reg_index_of_frm0_y_addr(stream->id) :
get_reg_index_of_frm1_y_addr(stream->id);
} else {
frm_addr_y = frame_phase_next & CIF_CSI_FRAME0_READY ?
get_dvp_reg_index_of_frm0_y_addr(stream->id) :
get_dvp_reg_index_of_frm1_y_addr(stream->id);
}
if (frame_phase == CIF_CSI_FRAME0_READY)
stream->next_buf_toisp = stream->curr_buf_toisp;
else
stream->curr_buf_toisp = stream->next_buf_toisp;
buff_addr_y = stream->curr_buf_toisp->dummy.dma_addr;
if (capture_info->mode == RKMODULE_MULTI_DEV_COMBINE_ONE) {
rkcif_write_buff_addr_multi_dev_combine(stream, frm_addr_y, 0,
buff_addr_y, 0, false);
} else {
rkcif_write_register(dev, frm_addr_y, buff_addr_y);
}
}
}
@@ -2675,7 +2711,8 @@ static int rkcif_assign_new_buffer_update(struct rkcif_stream *stream,
} else {
dbufs = &stream->curr_buf_toisp->dbufs;
}
rkcif_s_rx_buffer(dev, dbufs);
if (dbufs)
rkcif_s_rx_buffer(dev, dbufs);
if (stream->curr_buf && stream->frame_phase == CIF_CSI_FRAME0_READY) {
stream->curr_buf = NULL;
if (stream->buf_replace_cnt)
@@ -4690,12 +4727,14 @@ int rkcif_init_rx_buf(struct rkcif_stream *stream, int buf_num)
buf->dbufs.is_uncompact = false;
else
buf->dbufs.is_uncompact = true;
if (priv && priv->mode.rdbk_mode == RKISP_VICAP_ONLINE && i == 0) {
if (priv && i == 0) {
buf->dbufs.is_first = true;
rkcif_s_rx_buffer(dev, &buf->dbufs);
if (priv->mode.rdbk_mode == RKISP_VICAP_ONLINE)
rkcif_s_rx_buffer(dev, &buf->dbufs);
}
i++;
if (!dev->is_thunderboot && i >= buf_num) {
priv->buf_num = buf_num;
break;
} else if (i >= RKISP_VICAP_BUF_CNT_MAX) {
priv->buf_num = i;
@@ -10263,6 +10302,247 @@ static bool rkcif_check_buffer_prepare(struct rkcif_stream *stream)
return is_update;
}
static int rkcif_subdevs_set_power(struct rkcif_device *cif_dev, int on)
{
struct sditf_priv *priv = cif_dev->sditf[0];
int ret = 0;
int i = 0;
if (cif_dev->terminal_sensor.sd)
ret = v4l2_subdev_call(cif_dev->terminal_sensor.sd,
core, s_power, on);
if (priv && priv->is_combine_mode && cif_dev->sditf_cnt <= RKCIF_MAX_SDITF) {
for (i = 0; i < cif_dev->sditf_cnt; i++) {
if (cif_dev->sditf[i] && cif_dev->sditf[i]->sensor_sd)
v4l2_subdev_call(cif_dev->sditf[i]->sensor_sd, core,
s_power, on);
}
}
return ret;
}
static int rkcif_subdevs_set_stream(struct rkcif_device *cif_dev, int on)
{
struct rkcif_pipeline *p = &cif_dev->pipe;
struct sditf_priv *priv = cif_dev->sditf[0];
int i = 0;
int ret = 0;
for (i = 0; i < p->num_subdevs; i++) {
ret = v4l2_subdev_call(p->subdevs[i], video, s_stream, on);
if (ret)
v4l2_dbg(1, rkcif_debug, &cif_dev->v4l2_dev,
"%s:stream %s subdev:%s failed\n",
__func__, on ? "on" : "off", p->subdevs[i]->name);
}
if (priv && priv->is_combine_mode && cif_dev->sditf_cnt <= RKCIF_MAX_SDITF) {
for (i = 0; i < cif_dev->sditf_cnt; i++) {
if (cif_dev->sditf[i] && cif_dev->sditf[i]->sensor_sd) {
ret = v4l2_subdev_call(cif_dev->sditf[i]->sensor_sd, video, s_stream, on);
if (ret)
v4l2_dbg(1, rkcif_debug, &cif_dev->v4l2_dev,
"%s:stream %s subdev:%s failed\n",
__func__, on ? "on" : "off",
cif_dev->sditf[i]->sensor_sd->name);
}
}
}
return ret;
}
int rkcif_stream_suspend(struct rkcif_device *cif_dev, int mode)
{
struct rkcif_stream *stream = NULL;
struct rkcif_resume_info *resume_info = &cif_dev->reset_work.resume_info;
struct sditf_priv *priv = cif_dev->sditf[0];
int ret = 0;
int i = 0;
int sof_cnt = 0;
int on = 0;
int suspend_cnt = 0;
mutex_lock(&cif_dev->stream_lock);
if (priv && priv->mode.rdbk_mode == RKISP_VICAP_ONLINE && mode == RKCIF_RESUME_CIF)
goto out_suspend;
for (i = 0; i < RKCIF_MAX_STREAM_MIPI; i++) {
stream = &cif_dev->stream[i];
if (stream->state == RKCIF_STATE_STREAMING) {
suspend_cnt++;
v4l2_dbg(1, rkcif_debug, &cif_dev->v4l2_dev,
"stream[%d] stopping\n", stream->id);
if (stream->dma_en) {
stream->stopping = true;
ret = wait_event_timeout(stream->wq_stopped,
stream->state != RKCIF_STATE_STREAMING,
msecs_to_jiffies(500));
if (!ret) {
rkcif_stream_stop(stream);
stream->stopping = false;
}
} else {
rkcif_stream_stop(stream);
}
if (stream->id == RKCIF_STREAM_MIPI_ID0) {
sof_cnt = rkcif_get_sof(cif_dev);
v4l2_dbg(1, rkcif_debug, &cif_dev->v4l2_dev,
"%s: stream[%d] sync frmid & csi_sof, frm_id:%d, csi_sof:%d\n",
__func__,
stream->id,
stream->frame_idx,
sof_cnt);
resume_info->frm_sync_seq = stream->frame_idx;
}
stream->state = RKCIF_STATE_RESET_IN_STREAMING;
stream->is_fs_fe_not_paired = false;
stream->fs_cnt_in_single_frame = 0;
v4l2_dbg(1, rkcif_debug, &cif_dev->v4l2_dev,
"%s stop stream[%d] in streaming, frm_id:%d, csi_sof:%d\n",
__func__, stream->id, stream->frame_idx, rkcif_get_sof(cif_dev));
}
}
rkcif_subdevs_set_power(cif_dev, on);
if (suspend_cnt == 0)
goto out_suspend;
rkcif_subdevs_set_stream(cif_dev, on);
out_suspend:
mutex_unlock(&cif_dev->stream_lock);
return 0;
}
int rkcif_stream_resume(struct rkcif_device *cif_dev, int mode)
{
struct rkcif_stream *stream = NULL;
struct sditf_priv *priv = cif_dev->sditf[0];
int ret = 0;
int i = 0;
u32 capture_mode = 0;
int on = 0;
int resume_cnt = 0;
unsigned long flags;
mutex_lock(&cif_dev->stream_lock);
if (priv && priv->mode.rdbk_mode == RKISP_VICAP_ONLINE)
capture_mode = RKCIF_STREAM_MODE_TOISP;
else if (priv && priv->mode.rdbk_mode == RKISP_VICAP_RDBK_AUTO)
capture_mode = RKCIF_STREAM_MODE_TOISP_RDBK;
else
capture_mode = RKCIF_STREAM_MODE_CAPTURE;
if (priv && priv->mode.rdbk_mode == RKISP_VICAP_ONLINE && mode == RKCIF_RESUME_CIF)
goto out_resume;
for (i = 0; i < RKCIF_MAX_STREAM_MIPI; i++) {
stream = &cif_dev->stream[i];
if (stream->state != RKCIF_STATE_RESET_IN_STREAMING)
continue;
stream->fs_cnt_in_single_frame = 0;
spin_lock_irqsave(&stream->vbq_lock, flags);
if (!priv || priv->mode.rdbk_mode == RKISP_VICAP_RDBK_AIQ) {
if (stream->cif_fmt_in->field == V4L2_FIELD_INTERLACED) {
if (stream->curr_buf == stream->next_buf) {
if (stream->curr_buf)
list_add_tail(&stream->curr_buf->queue, &stream->buf_head);
} else {
if (stream->curr_buf)
list_add_tail(&stream->curr_buf->queue, &stream->buf_head);
if (stream->next_buf)
list_add_tail(&stream->next_buf->queue, &stream->buf_head);
}
stream->curr_buf = NULL;
stream->next_buf = NULL;
}
} else {
if (priv->mode.rdbk_mode == RKISP_VICAP_ONLINE) {
if (stream->curr_buf_toisp == stream->next_buf_toisp) {
if (stream->curr_buf_toisp)
list_add_tail(&stream->curr_buf_toisp->list, &stream->rx_buf_head);
} else {
if (stream->curr_buf_toisp)
list_add_tail(&stream->curr_buf_toisp->list, &stream->rx_buf_head);
if (stream->next_buf_toisp)
list_add_tail(&stream->next_buf_toisp->list, &stream->rx_buf_head);
}
stream->curr_buf_toisp = NULL;
stream->next_buf_toisp = NULL;
} else {
if (stream->curr_buf_toisp == stream->next_buf_toisp) {
if (stream->curr_buf_toisp)
list_add_tail(&stream->curr_buf_toisp->list, &stream->rx_buf_head);
} else {
if (stream->curr_buf_toisp)
list_add_tail(&stream->curr_buf_toisp->list, &stream->rx_buf_head);
if (stream->next_buf_toisp)
list_add_tail(&stream->next_buf_toisp->list, &stream->rx_buf_head);
}
stream->curr_buf_toisp = NULL;
stream->next_buf_toisp = NULL;
}
}
spin_unlock_irqrestore(&stream->vbq_lock, flags);
if (capture_mode == RKCIF_STREAM_MODE_TOISP)
sditf_change_to_online(priv);
else
sditf_disable_immediately(priv);
if (!stream->total_buf_num && priv &&
(capture_mode == RKCIF_STREAM_MODE_TOISP_RDBK ||
(capture_mode == RKCIF_STREAM_MODE_TOISP &&
((priv->hdr_cfg.hdr_mode == HDR_X2 && stream->id == 0) ||
(priv->hdr_cfg.hdr_mode == HDR_X3 && (stream->id == 0 || stream->id == 1))))))
rkcif_init_rx_buf(stream, 1);
stream->lack_buf_cnt = 0;
if (cif_dev->active_sensor &&
(cif_dev->active_sensor->mbus.type == V4L2_MBUS_CSI2_DPHY ||
cif_dev->active_sensor->mbus.type == V4L2_MBUS_CSI2_CPHY ||
cif_dev->active_sensor->mbus.type == V4L2_MBUS_CCP2))
ret = rkcif_csi_stream_start(stream, capture_mode);
else
ret = rkcif_stream_start(stream, capture_mode);
if (ret)
v4l2_err(&cif_dev->v4l2_dev, "%s:resume stream[%d] failed\n",
__func__, stream->id);
resume_cnt++;
v4l2_dbg(1, rkcif_debug, &cif_dev->v4l2_dev,
"resume stream[%d], frm_idx:%d, csi_sof:%d\n",
stream->id, stream->frame_idx,
rkcif_get_sof(cif_dev));
}
on = 1;
rkcif_subdevs_set_power(cif_dev, on);
if (resume_cnt == 0)
goto out_resume;
rkcif_subdevs_set_stream(cif_dev, on);
if (cif_dev->chip_id < CHIP_RK3588_CIF)
rkcif_start_luma(&cif_dev->luma_vdev,
cif_dev->stream[RKCIF_STREAM_MIPI_ID0].cif_fmt_in);
out_resume:
mutex_unlock(&cif_dev->stream_lock);
return 0;
}
void rkcif_err_print_work(struct work_struct *work)
{
struct rkcif_err_state_work *err_state_work = container_of(work,
@@ -10322,10 +10602,18 @@ void rkcif_err_print_work(struct work_struct *work)
v4l2_err(&dev->v4l2_dev,
"stream[3], frm0/frm1 end simultaneously,frm id:%d, cnt %llu\n",
dev->stream[3].frame_idx, dev->irq_stats.trig_simult_cnt[3]);
if (err_state & RKCIF_ERR_SIZE)
v4l2_err(&dev->v4l2_dev,
"ERROR: csi size err, intstat:0x%x, lastline:0x%x, cnt %llu\n",
intstat, lastline, dev->irq_stats.csi_size_err_cnt);
if (err_state & RKCIF_ERR_SIZE) {
if (dev->chip_id >= CHIP_RK3588_CIF)
v4l2_err(&dev->v4l2_dev,
"ERROR: csi size err, intstat:0x%x, size:0x%x,0x%x,0x%x,0x%x, cnt %llu\n",
intstat, err_state_work->size_id0, err_state_work->size_id1,
err_state_work->size_id2, err_state_work->size_id3,
dev->irq_stats.csi_size_err_cnt);
else
v4l2_err(&dev->v4l2_dev,
"ERROR: csi size err, intstat:0x%x, lastline:0x%x, cnt %llu\n",
intstat, lastline, dev->irq_stats.csi_size_err_cnt);
}
if (err_state & RKCIF_ERR_OVERFLOW)
v4l2_err(&dev->v4l2_dev,
"ERROR: csi fifo overflow, intstat:0x%x, lastline:0x%x, cnt %llu\n",
@@ -10379,13 +10667,22 @@ void rkcif_irq_pingpong_v1(struct rkcif_device *cif_dev)
if (intstat) {
rkcif_write_register(cif_dev, CIF_REG_MIPI_LVDS_INTSTAT, intstat);
v4l2_dbg(2, rkcif_debug, &cif_dev->v4l2_dev,
"intstat 0x%x\n",
intstat);
"intstat 0x%x\n", intstat);
} else {
return;
}
if (intstat & CSI_SIZE_ERR) {
if (cif_dev->chip_id >= CHIP_RK3588_CIF) {
cif_dev->err_state_work.size_id0 = rkcif_read_register(cif_dev,
CIF_REG_MIPI_FRAME_SIZE_ID0);
cif_dev->err_state_work.size_id1 = rkcif_read_register(cif_dev,
CIF_REG_MIPI_FRAME_SIZE_ID1);
cif_dev->err_state_work.size_id2 = rkcif_read_register(cif_dev,
CIF_REG_MIPI_FRAME_SIZE_ID2);
cif_dev->err_state_work.size_id3 = rkcif_read_register(cif_dev,
CIF_REG_MIPI_FRAME_SIZE_ID3);
}
cif_dev->irq_stats.csi_size_err_cnt++;
cif_dev->err_state |= RKCIF_ERR_SIZE;
rkcif_write_register_or(cif_dev, CIF_REG_MIPI_LVDS_CTRL, 0x000A0000);
+17 -2
View File
@@ -2211,6 +2211,21 @@ static int rkcif_plat_remove(struct platform_device *pdev)
return 0;
}
static int __maybe_unused rkcif_runtime_prepare(struct device *dev)
{
struct rkcif_device *cif_dev = dev_get_drvdata(dev);
rkcif_stream_suspend(cif_dev, RKCIF_RESUME_CIF);
return 0;
}
static void __maybe_unused rkcif_runtime_complete(struct device *dev)
{
struct rkcif_device *cif_dev = dev_get_drvdata(dev);
rkcif_stream_resume(cif_dev, RKCIF_RESUME_CIF);
}
static int __maybe_unused rkcif_runtime_suspend(struct device *dev)
{
struct rkcif_device *cif_dev = dev_get_drvdata(dev);
@@ -2281,8 +2296,8 @@ late_initcall(rkcif_clr_unready_dev);
#endif
static const struct dev_pm_ops rkcif_plat_pm_ops = {
SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
pm_runtime_force_resume)
.prepare = rkcif_runtime_prepare,
.complete = rkcif_runtime_complete,
SET_RUNTIME_PM_OPS(rkcif_runtime_suspend, rkcif_runtime_resume, NULL)
};
+11
View File
@@ -792,6 +792,15 @@ struct rkcif_err_state_work {
u32 intstat;
u32 lastline;
u32 lastpixel;
u32 size_id0;
u32 size_id1;
u32 size_id2;
u32 size_id3;
};
enum rkcif_resume_user {
RKCIF_RESUME_CIF,
RKCIF_RESUME_ISP,
};
/*
@@ -968,5 +977,7 @@ void rkcif_rockit_dev_init(struct rkcif_device *dev);
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);
#endif
+37
View File
@@ -699,6 +699,10 @@ static const struct cif_reg rk3588_cif_regs[] = {
[CIF_REG_MIPI_EFFECT_CODE_ID1] = CIF_REG(CSI_MIPI0_EFFECT_CODE_ID1),
[CIF_REG_MIPI_EFFECT_CODE_ID2] = CIF_REG(CSI_MIPI0_EFFECT_CODE_ID2),
[CIF_REG_MIPI_EFFECT_CODE_ID3] = CIF_REG(CSI_MIPI0_EFFECT_CODE_ID3),
[CIF_REG_MIPI_FRAME_SIZE_ID0] = CIF_REG(CSI_MIPI0_FRAME_SIZE_ID0),
[CIF_REG_MIPI_FRAME_SIZE_ID1] = CIF_REG(CSI_MIPI0_FRAME_SIZE_ID1),
[CIF_REG_MIPI_FRAME_SIZE_ID2] = CIF_REG(CSI_MIPI0_FRAME_SIZE_ID2),
[CIF_REG_MIPI_FRAME_SIZE_ID3] = CIF_REG(CSI_MIPI0_FRAME_SIZE_ID3),
[CIF_REG_MIPI_ON_PAD] = CIF_REG(CSI_MIPI0_ON_PAD),
[CIF_REG_GLB_CTRL] = CIF_REG(GLB_CTRL),
@@ -823,6 +827,10 @@ static const struct cif_reg rv1106_cif_regs[] = {
[CIF_REG_MIPI_EFFECT_CODE_ID1] = CIF_REG(CSI_MIPI0_EFFECT_CODE_ID1),
[CIF_REG_MIPI_EFFECT_CODE_ID2] = CIF_REG(CSI_MIPI0_EFFECT_CODE_ID2),
[CIF_REG_MIPI_EFFECT_CODE_ID3] = CIF_REG(CSI_MIPI0_EFFECT_CODE_ID3),
[CIF_REG_MIPI_FRAME_SIZE_ID0] = CIF_REG(CSI_MIPI0_FRAME_SIZE_ID0),
[CIF_REG_MIPI_FRAME_SIZE_ID1] = CIF_REG(CSI_MIPI0_FRAME_SIZE_ID1),
[CIF_REG_MIPI_FRAME_SIZE_ID2] = CIF_REG(CSI_MIPI0_FRAME_SIZE_ID2),
[CIF_REG_MIPI_FRAME_SIZE_ID3] = CIF_REG(CSI_MIPI0_FRAME_SIZE_ID3),
[CIF_REG_MIPI_ON_PAD] = CIF_REG(CSI_MIPI0_ON_PAD),
[CIF_REG_LVDS_ID0_CTRL0] = CIF_REG(CIF_LVDS0_ID0_CTRL0),
[CIF_REG_LVDS_ID1_CTRL0] = CIF_REG(CIF_LVDS0_ID1_CTRL0),
@@ -942,6 +950,10 @@ static const struct cif_reg rk3562_cif_regs[] = {
[CIF_REG_MIPI_EFFECT_CODE_ID1] = CIF_REG(CSI_MIPI0_EFFECT_CODE_ID1),
[CIF_REG_MIPI_EFFECT_CODE_ID2] = CIF_REG(CSI_MIPI0_EFFECT_CODE_ID2),
[CIF_REG_MIPI_EFFECT_CODE_ID3] = CIF_REG(CSI_MIPI0_EFFECT_CODE_ID3),
[CIF_REG_MIPI_FRAME_SIZE_ID0] = CIF_REG(CSI_MIPI0_FRAME_SIZE_ID0),
[CIF_REG_MIPI_FRAME_SIZE_ID1] = CIF_REG(CSI_MIPI0_FRAME_SIZE_ID1),
[CIF_REG_MIPI_FRAME_SIZE_ID2] = CIF_REG(CSI_MIPI0_FRAME_SIZE_ID2),
[CIF_REG_MIPI_FRAME_SIZE_ID3] = CIF_REG(CSI_MIPI0_FRAME_SIZE_ID3),
[CIF_REG_MIPI_ON_PAD] = CIF_REG(CSI_MIPI0_ON_PAD),
[CIF_REG_GLB_CTRL] = CIF_REG(GLB_CTRL),
@@ -1538,7 +1550,32 @@ static int __maybe_unused rkcif_runtime_resume(struct device *dev)
return 0;
}
static int __maybe_unused rkcif_sleep_suspend(struct device *dev)
{
struct rkcif_hw *cif_hw = dev_get_drvdata(dev);
rkcif_disable_sys_clk(cif_hw);
return pinctrl_pm_select_sleep_state(dev);
}
static int __maybe_unused rkcif_sleep_resume(struct device *dev)
{
struct rkcif_hw *cif_hw = dev_get_drvdata(dev);
int ret;
ret = pinctrl_pm_select_default_state(dev);
if (ret < 0)
return ret;
rkcif_enable_sys_clk(cif_hw);
rkcif_hw_soft_reset(cif_hw, true);
return 0;
}
static const struct dev_pm_ops rkcif_plat_pm_ops = {
SET_SYSTEM_SLEEP_PM_OPS(rkcif_sleep_suspend,
rkcif_sleep_resume)
SET_RUNTIME_PM_OPS(rkcif_runtime_suspend, rkcif_runtime_resume, NULL)
};
@@ -145,6 +145,10 @@ enum cif_reg_index {
CIF_REG_LVDS_ID1_CTRL0,
CIF_REG_LVDS_ID2_CTRL0,
CIF_REG_LVDS_ID3_CTRL0,
CIF_REG_MIPI_FRAME_SIZE_ID0,
CIF_REG_MIPI_FRAME_SIZE_ID1,
CIF_REG_MIPI_FRAME_SIZE_ID2,
CIF_REG_MIPI_FRAME_SIZE_ID3,
CIF_REG_MIPI_ON_PAD,
CIF_REG_Y_STAT_CONTROL,
@@ -421,6 +425,11 @@ enum cif_reg_index {
#define CSI_MIPI0_EFFECT_CODE_ID3 0x1B8
#define CSI_MIPI0_ON_PAD 0x1BC
#define CSI_MIPI0_FRAME_SIZE_ID0 0x1C0
#define CSI_MIPI0_FRAME_SIZE_ID1 0x1C4
#define CSI_MIPI0_FRAME_SIZE_ID2 0x1C8
#define CSI_MIPI0_FRAME_SIZE_ID3 0x1CC
/* RV1106 CONTROL Registers Offset */
#define CIF_LVDS0_ID0_CTRL0 0x1D0
#define CIF_LVDS0_ID1_CTRL0 0x1D4
@@ -327,6 +327,7 @@ static void sditf_reinit_mode(struct sditf_priv *priv, struct rkisp_vicap_mode *
__func__, mode->rdbk_mode, mode->name, priv->toisp_inf.link_mode);
}
static void sditf_channel_disable(struct sditf_priv *priv, int user);
static long sditf_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
{
struct sditf_priv *priv = to_sditf_priv(sd);
@@ -336,11 +337,14 @@ static long sditf_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
struct v4l2_subdev *sensor_sd;
int *pbuf_num = NULL;
int ret = 0;
int *on = NULL;
switch (cmd) {
case RKISP_VICAP_CMD_MODE:
mode = (struct rkisp_vicap_mode *)arg;
mutex_lock(&cif_dev->stream_lock);
memcpy(&priv->mode, mode, sizeof(*mode));
mutex_unlock(&cif_dev->stream_lock);
sditf_reinit_mode(priv, &priv->mode);
if (priv->is_combine_mode)
mode->input.merge_num = cif_dev->sditf_cnt;
@@ -363,6 +367,22 @@ static long sditf_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
return v4l2_subdev_call(sensor_sd, core, ioctl, cmd, arg);
}
break;
case RKISP_VICAP_CMD_QUICK_STREAM:
on = (int *)arg;
if (*on) {
rkcif_stream_resume(cif_dev, RKCIF_RESUME_ISP);
} else {
if (priv->toisp_inf.link_mode == TOISP0) {
sditf_channel_disable(priv, 0);
} else if (priv->toisp_inf.link_mode == TOISP1) {
sditf_channel_disable(priv, 1);
} else if (priv->toisp_inf.link_mode == TOISP_UNITE) {
sditf_channel_disable(priv, 0);
sditf_channel_disable(priv, 1);
}
rkcif_stream_suspend(cif_dev, RKCIF_RESUME_ISP);
}
break;
default:
break;
}
@@ -382,6 +402,7 @@ static long sditf_compat_ioctl32(struct v4l2_subdev *sd,
struct rkmodule_hdr_cfg *hdr_cfg;
int buf_num;
int ret = 0;
int on;
switch (cmd) {
case RKISP_VICAP_CMD_MODE:
@@ -414,6 +435,11 @@ static long sditf_compat_ioctl32(struct v4l2_subdev *sd,
}
ret = sditf_ioctl(sd, cmd, hdr_cfg);
return ret;
case RKISP_VICAP_CMD_QUICK_STREAM:
if (copy_from_user(&on, up, sizeof(int)))
return -EFAULT;
ret = sditf_ioctl(sd, cmd, &on);
return ret;
default:
break;
}
@@ -605,6 +631,21 @@ void sditf_change_to_online(struct sditf_priv *priv)
cif_dev->wait_line_bak = 0;
}
void sditf_disable_immediately(struct sditf_priv *priv)
{
struct rkcif_device *cif_dev = priv->cif_dev;
u32 ctrl_val = 0x10101;
if (priv->toisp_inf.link_mode == TOISP0) {
rkcif_write_register_and(cif_dev, CIF_REG_TOISP0_CTRL, ~ctrl_val);
} else if (priv->toisp_inf.link_mode == TOISP1) {
rkcif_write_register_and(cif_dev, CIF_REG_TOISP1_CTRL, ~ctrl_val);
} else if (priv->toisp_inf.link_mode == TOISP_UNITE) {
rkcif_write_register_and(cif_dev, CIF_REG_TOISP0_CTRL, ~ctrl_val);
rkcif_write_register_and(cif_dev, CIF_REG_TOISP1_CTRL, ~ctrl_val);
}
}
static void sditf_check_capture_mode(struct rkcif_device *cif_dev)
{
struct rkcif_device *dev = NULL;
@@ -828,6 +869,10 @@ static int sditf_s_rx_buffer(struct v4l2_subdev *sd,
if (!is_free && (!dbufs->is_switch)) {
list_add_tail(&rx_buf->list, &stream->rx_buf_head);
rkcif_assign_check_buffer_update_toisp(stream);
if (!stream->dma_en) {
stream->to_en_dma = RKCIF_DMAEN_BY_ISP;
rkcif_enable_dma_capture(stream, true);
}
if (cif_dev->rdbk_debug) {
u32 offset = 0;
@@ -855,6 +900,9 @@ static int sditf_s_rx_buffer(struct v4l2_subdev *sd,
}
spin_unlock_irqrestore(&stream->vbq_lock, flags);
if (!cif_dev->is_thunderboot)
return 0;
if (dbufs->runtime_us && cif_dev->early_line == 0) {
if (!cif_dev->sensor_linetime)
cif_dev->sensor_linetime = rkcif_get_linetime(stream);
@@ -84,5 +84,6 @@ struct sditf_priv {
extern struct platform_driver rkcif_subdev_driver;
void sditf_change_to_online(struct sditf_priv *priv);
void sditf_disable_immediately(struct sditf_priv *priv);
#endif