media: rockchip: isp: frame buffer done early

config wait-line to isp virtual device dts node,
or echo value to debug node before open isp video.
/sys/module/video_rkisp/parameters/wait_line

Change-Id: I5c73c90117455663620b4c025e78aa6233ca40b9
Signed-off-by: Cai YiWei <cyw@rock-chips.com>
This commit is contained in:
Cai YiWei
2021-07-08 18:16:32 +08:00
committed by Tao Huang
parent b0a19c2d18
commit 70dc5c1037
5 changed files with 79 additions and 7 deletions

View File

@@ -511,14 +511,18 @@ static void rkisp_bridge_work(struct work_struct *work)
kfree(br_wk);
}
static int frame_end(struct rkisp_bridge_device *dev, bool en)
static int frame_end(struct rkisp_bridge_device *dev, bool en, u32 state)
{
struct rkisp_hw_dev *hw = dev->ispdev->hw_dev;
struct rkisp_device *ispdev = dev->ispdev;
struct rkisp_hw_dev *hw = ispdev->hw_dev;
struct v4l2_subdev *sd = v4l2_get_subdev_hostdata(&dev->sd);
unsigned long lock_flags = 0;
u64 ns = ktime_get_ns();
struct rkisp_bridge_buf *buf;
if (state == FRAME_IRQ && ispdev->cap_dev.is_done_early)
return 0;
rkisp_dmarx_get_frame(dev->ispdev, &dev->dbg.id, NULL, NULL, true);
dev->dbg.interval = ns - dev->dbg.timestamp;
dev->dbg.timestamp = ns;
@@ -591,9 +595,8 @@ static int frame_end(struct rkisp_bridge_device *dev, bool en)
}
}
hw->cur_buf = NULL;
} else if (dev->ispdev->send_fbcgain) {
v4l2_dbg(1, rkisp_debug, &dev->sd,
"use dummy buffer, lost fbcgain data, frm_id %d\n", dev->dbg.id);
} else {
v4l2_dbg(1, rkisp_debug, &dev->sd, "no buf, lost frame:%d\n", dev->dbg.id);
}
if (hw->nxt_buf) {
@@ -604,6 +607,41 @@ static int frame_end(struct rkisp_bridge_device *dev, bool en)
return 0;
}
static enum hrtimer_restart rkisp_bridge_frame_done_early(struct hrtimer *timer)
{
struct rkisp_bridge_device *br =
container_of(timer, struct rkisp_bridge_device, frame_qst);
struct rkisp_device *dev = br->ispdev;
enum hrtimer_restart ret = HRTIMER_NORESTART;
u32 ycnt, line = dev->cap_dev.wait_line;
u32 seq, time, max_time = 1000000;
u64 ns = ktime_get_ns();
time = (u32)(ns - br->fs_ns);
ycnt = rkisp_read(dev, ISP_MPFBC_ENC_POS, true) & 0x3ff;
ycnt *= 8;
rkisp_dmarx_get_frame(dev, &seq, NULL, NULL, true);
if (!br->en || dev->isp_state == ISP_STOP) {
goto end;
} else if (ycnt < line) {
if (!ycnt)
ns = max_time;
else
ns = time * (line - ycnt) / ycnt;
if (ns > max_time)
ns = max_time;
hrtimer_forward(timer, timer->base->get_time(), ns_to_ktime(ns));
ret = HRTIMER_RESTART;
} else {
v4l2_dbg(3, rkisp_debug, &dev->v4l2_dev,
"%s seq:%d line:%d ycnt:%d time:%dus\n",
__func__, seq, line, ycnt, time / 1000);
frame_end(br, br->en, FRAME_WORK);
}
end:
return ret;
}
static int config_gain(struct rkisp_bridge_device *dev)
{
u32 w = dev->crop.width;
@@ -1002,6 +1040,7 @@ static void crop_off(struct rkisp_bridge_device *dev)
static int bridge_start(struct rkisp_bridge_device *dev)
{
struct rkisp_device *ispdev = dev->ispdev;
struct rkisp_stream *sp_stream;
sp_stream = &dev->ispdev->cap_dev.stream[RKISP_STREAM_SP];
@@ -1019,6 +1058,15 @@ static int bridge_start(struct rkisp_bridge_device *dev)
dev->ispdev->skip_frame = 0;
rkisp_stats_first_ddr_config(&dev->ispdev->stats_vdev);
dev->en = true;
ispdev->cap_dev.is_done_early = false;
if (ispdev->send_fbcgain)
ispdev->cap_dev.wait_line = 0;
if (ispdev->cap_dev.wait_line) {
if (ispdev->cap_dev.wait_line < dev->crop.height / 4)
ispdev->cap_dev.wait_line = dev->crop.height / 4;
ispdev->cap_dev.is_done_early = true;
}
return 0;
}
@@ -1455,6 +1503,7 @@ void rkisp_bridge_update_mi(struct rkisp_device *dev)
br->work_mode & ISP_ISPP_QUICK)
return;
br->fs_ns = ktime_get_ns();
spin_lock_irqsave(&hw->buf_lock, lock_flags);
if (!hw->nxt_buf && !list_empty(&hw->list)) {
hw->nxt_buf = list_first_entry(&hw->list,
@@ -1473,6 +1522,9 @@ void rkisp_bridge_update_mi(struct rkisp_device *dev)
rkisp_write(dev, br->cfg->reg.g0_base, val, true);
}
if (dev->cap_dev.is_done_early)
hrtimer_start(&br->frame_qst, ns_to_ktime(1000000), HRTIMER_MODE_REL);
v4l2_dbg(2, rkisp_debug, &br->sd,
"update pic(shd:0x%x base:0x%x) gain(shd:0x%x base:0x%x)\n",
rkisp_read(dev, br->cfg->reg.y0_base_shd, true),
@@ -1509,7 +1561,7 @@ void rkisp_bridge_isr(u32 *mis_val, struct rkisp_device *dev)
irq = (irq == MI_MPFBC_FRAME) ? ISP_FRAME_MPFBC : ISP_FRAME_MP;
if (!(bridge->work_mode & ISP_ISPP_QUICK)) {
frame_end(bridge, bridge->en);
frame_end(bridge, bridge->en, FRAME_IRQ);
if (!bridge->en)
dev->irq_ends_mask &= ~irq;
}
@@ -1556,6 +1608,8 @@ int rkisp_register_bridge_subdev(struct rkisp_device *dev,
init_waitqueue_head(&bridge->done);
bridge->wq = alloc_workqueue("rkisp bridge workqueue",
WQ_UNBOUND | WQ_MEM_RECLAIM, 1);
hrtimer_init(&bridge->frame_qst, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
bridge->frame_qst.function = rkisp_bridge_frame_done_early;
return ret;
free_media:

View File

@@ -56,13 +56,15 @@ struct rkisp_bridge_device {
struct rkisp_bridge_ops *ops;
struct rkisp_bridge_config *cfg;
struct frame_debug_info dbg;
struct workqueue_struct *wq;
struct hrtimer frame_qst;
u64 fs_ns;
u8 work_mode;
u8 buf_num;
bool pingpong;
bool stopping;
bool linked;
bool en;
struct workqueue_struct *wq;
};
int rkisp_register_bridge_subdev(struct rkisp_device *dev,

View File

@@ -238,6 +238,8 @@ struct rkisp_capture_device {
struct rkisp_stream stream[RKISP_MAX_STREAM];
struct rkisp_buffer *rdbk_buf[RDBK_MAX];
atomic_t refcnt;
u32 wait_line;
bool is_done_early;
};
extern struct stream_config rkisp_mp_stream_config;

View File

@@ -75,6 +75,10 @@ u64 rkisp_debug_reg = 0xFFFFFFFFFLL;
module_param_named(debug_reg, rkisp_debug_reg, ullong, 0644);
MODULE_PARM_DESC(debug_reg, "rkisp debug register");
static unsigned int rkisp_wait_line;
module_param_named(wait_line, rkisp_wait_line, uint, 0644);
MODULE_PARM_DESC(wait_line, "rkisp wait line to buf done early");
static DEFINE_MUTEX(rkisp_dev_mutex);
static LIST_HEAD(rkisp_device_list);
@@ -776,6 +780,9 @@ static int rkisp_plat_probe(struct platform_device *pdev)
if (ret < 0)
goto err_unreg_media_dev;
rkisp_wait_line = 0;
of_property_read_u32(dev->of_node, "wait-line", &rkisp_wait_line);
rkisp_proc_init(isp_dev);
mutex_lock(&rkisp_dev_mutex);
@@ -828,6 +835,7 @@ static int __maybe_unused rkisp_runtime_resume(struct device *dev)
struct rkisp_device *isp_dev = dev_get_drvdata(dev);
int ret;
isp_dev->cap_dev.wait_line = rkisp_wait_line;
mutex_lock(&isp_dev->hw_dev->dev_lock);
ret = pm_runtime_get_sync(isp_dev->hw_dev->dev);
mutex_unlock(&isp_dev->hw_dev->dev_lock);

View File

@@ -29,6 +29,12 @@
#define RKISP_ISPP_CMD_GET_REG_WITHSTREAM \
_IOW('V', BASE_VIDIOC_PRIVATE + 3, bool)
enum frame_end_state {
FRAME_INIT,
FRAME_IRQ,
FRAME_WORK,
};
enum rkisp_ispp_dev {
DEV_ID0 = 0,
DEV_ID1,