mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-07 19:30:30 +09:00
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:
@@ -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:
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user