diff --git a/drivers/media/platform/rockchip/isp/Makefile b/drivers/media/platform/rockchip/isp/Makefile index 425d81d7489c..033dd2cc48db 100644 --- a/drivers/media/platform/rockchip/isp/Makefile +++ b/drivers/media/platform/rockchip/isp/Makefile @@ -44,4 +44,7 @@ video_rkisp-$(CONFIG_VIDEO_ROCKCHIP_ISP_VERSION_V32) += \ isp_params_v32.o \ isp_stats_v32.o +video_rkisp-$(CONFIG_ROCKCHIP_DVBM) += \ + isp_dvbm.o + video_rkisp-$(CONFIG_VIDEO_ROCKCHIP_THUNDER_BOOT_ISP) += rkisp_tb_helper.o diff --git a/drivers/media/platform/rockchip/isp/capture.c b/drivers/media/platform/rockchip/isp/capture.c index e8984145dd5f..73c7e1ae244c 100644 --- a/drivers/media/platform/rockchip/isp/capture.c +++ b/drivers/media/platform/rockchip/isp/capture.c @@ -438,8 +438,10 @@ int rkisp_stream_frame_start(struct rkisp_device *dev, u32 isp_mis) struct rkisp_stream *stream; int i; - if (isp_mis) + if (isp_mis) { + rkisp_dvbm_event(dev, CIF_ISP_V_START); rkisp_bridge_update_mi(dev, isp_mis); + } for (i = 0; i < RKISP_MAX_STREAM; i++) { if (i == RKISP_STREAM_VIR || i == RKISP_STREAM_LUMA) @@ -1422,6 +1424,33 @@ static int rkisp_set_mirror_flip(struct rkisp_stream *stream, return 0; } +static int rkisp_get_wrap_line(struct rkisp_stream *stream, int *line) +{ + struct rkisp_device *dev = stream->ispdev; + + if (dev->isp_ver != ISP_V32 && stream->id != RKISP_STREAM_MP) + return -EINVAL; + + *line = dev->cap_dev.wrap_line; + return 0; +} + +static int rkisp_set_wrap_line(struct rkisp_stream *stream, int *line) +{ + struct rkisp_device *dev = stream->ispdev; + + if (dev->isp_ver != ISP_V32) + return -EINVAL; + + if (dev->hw_dev->dev_link_num > 1 || stream->id != RKISP_STREAM_MP) { + v4l2_err(&dev->v4l2_dev, + "wrap only support for single sensor and mainpath\n"); + return -EINVAL; + } + dev->cap_dev.wrap_line = *line; + return 0; +} + static long rkisp_ioctl_default(struct file *file, void *fh, bool valid_prio, unsigned int cmd, void *arg) { @@ -1474,6 +1503,12 @@ static long rkisp_ioctl_default(struct file *file, void *fh, case RKISP_CMD_SET_MIRROR_FLIP: ret = rkisp_set_mirror_flip(stream, arg); break; + case RKISP_CMD_GET_WRAP_LINE: + ret = rkisp_get_wrap_line(stream, arg); + break; + case RKISP_CMD_SET_WRAP_LINE: + ret = rkisp_set_wrap_line(stream, arg); + break; default: ret = -EINVAL; } diff --git a/drivers/media/platform/rockchip/isp/capture_v32.c b/drivers/media/platform/rockchip/isp/capture_v32.c index 2b3262d5e992..48df3720850a 100644 --- a/drivers/media/platform/rockchip/isp/capture_v32.c +++ b/drivers/media/platform/rockchip/isp/capture_v32.c @@ -1251,6 +1251,7 @@ static int rkisp_create_dummy_buf(struct rkisp_stream *stream) { struct rkisp_device *dev = stream->ispdev; struct rkisp_dummy_buffer *buf = &stream->dummy_buf; + int ret; /* mainpath for warp default */ if (!dev->cap_dev.wrap_line || stream->id != RKISP_STREAM_MP) @@ -1258,7 +1259,14 @@ static int rkisp_create_dummy_buf(struct rkisp_stream *stream) buf->size = stream->out_fmt.plane_fmt[0].sizeimage; buf->is_need_dbuf = true; - return rkisp_alloc_buffer(stream->ispdev, buf); + ret = rkisp_alloc_buffer(stream->ispdev, buf); + if (ret == 0) { + ret = rkisp_dvbm_init(stream); + if (ret < 0) + rkisp_free_buffer(dev, buf); + } + + return ret; } static void rkisp_destroy_dummy_buf(struct rkisp_stream *stream) @@ -1267,7 +1275,8 @@ static void rkisp_destroy_dummy_buf(struct rkisp_stream *stream) if (!dev->cap_dev.wrap_line || stream->id != RKISP_STREAM_MP) return; - rkisp_free_buffer(stream->ispdev, &stream->dummy_buf); + rkisp_dvbm_deinit(); + rkisp_free_buffer(dev, &stream->dummy_buf); } static void destroy_buf_queue(struct rkisp_stream *stream, @@ -1604,6 +1613,8 @@ int rkisp_register_stream_v32(struct rkisp_device *dev) struct rkisp_capture_device *cap_dev = &dev->cap_dev; int ret; + rkisp_dvbm_get(dev); + ret = rkisp_stream_init(dev, RKISP_STREAM_MP); if (ret < 0) goto err; @@ -1674,6 +1685,9 @@ void rkisp_mi_v32_isr(u32 mis_val, struct rkisp_device *dev) mi_frame_end_int_clear(stream); + if (i == RKISP_STREAM_MP) + rkisp_dvbm_event(dev, CIF_MI_MP_FRAME); + if (stream->stopping) { /* * Make sure stream is actually stopped, whose state diff --git a/drivers/media/platform/rockchip/isp/capture_v3x.h b/drivers/media/platform/rockchip/isp/capture_v3x.h index 62e15905a664..fc82a7699990 100644 --- a/drivers/media/platform/rockchip/isp/capture_v3x.h +++ b/drivers/media/platform/rockchip/isp/capture_v3x.h @@ -32,4 +32,16 @@ static inline void rkisp_mi_v32_isr(u32 mis_val, struct rkisp_device *dev) {} static inline void rkisp_mipi_v32_isr(u32 phy, u32 packet, u32 overflow, u32 state, struct rkisp_device *dev) {} #endif +#if IS_ENABLED(CONFIG_ROCKCHIP_DVBM) +int rkisp_dvbm_get(struct rkisp_device *dev); +int rkisp_dvbm_init(struct rkisp_stream *stream); +void rkisp_dvbm_deinit(void); +int rkisp_dvbm_event(struct rkisp_device *dev, u32 event); +#else +static inline int rkisp_dvbm_get(struct rkisp_device *dev) { return -EINVAL; } +static inline int rkisp_dvbm_init(struct rkisp_stream *stream) { return -EINVAL; } +static inline void rkisp_dvbm_deinit(void) {} +static inline int rkisp_dvbm_event(struct rkisp_device *dev, u32 event) { return -EINVAL; } +#endif + #endif diff --git a/drivers/media/platform/rockchip/isp/dev.c b/drivers/media/platform/rockchip/isp/dev.c index 631e08e94451..f2b9c689b6f3 100644 --- a/drivers/media/platform/rockchip/isp/dev.c +++ b/drivers/media/platform/rockchip/isp/dev.c @@ -79,6 +79,10 @@ 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 unsigned int rkisp_wrap_line; +module_param_named(wrap_line, rkisp_wrap_line, uint, 0644); +MODULE_PARM_DESC(wrap_line, "rkisp wrap line for mpp"); + static DEFINE_MUTEX(rkisp_dev_mutex); static LIST_HEAD(rkisp_device_list); @@ -912,6 +916,7 @@ static int __maybe_unused rkisp_runtime_resume(struct device *dev) int ret; isp_dev->cap_dev.wait_line = rkisp_wait_line; + isp_dev->cap_dev.wrap_line = rkisp_wrap_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); diff --git a/drivers/media/platform/rockchip/isp/isp_dvbm.c b/drivers/media/platform/rockchip/isp/isp_dvbm.c new file mode 100644 index 000000000000..fe597add1f64 --- /dev/null +++ b/drivers/media/platform/rockchip/isp/isp_dvbm.c @@ -0,0 +1,93 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright (C) 2022 Rockchip Electronics Co., Ltd */ + +#include +#include +#include + +#include "dev.h" +#include "regs.h" + +static struct dvbm_port *g_dvbm; + +int rkisp_dvbm_get(struct rkisp_device *dev) +{ + struct device_node *np = dev->dev->of_node; + struct device_node *np_dvbm = of_parse_phandle(np, "dvbm", 0); + int ret = -EINVAL; + + g_dvbm = NULL; + if (dev->isp_ver != ISP_V32) + goto end; + + if (!np_dvbm || !of_device_is_available(np_dvbm)) { + dev_warn(dev->dev, "failed to get dvbm node\n"); + } else { + struct platform_device *p_dvbm = of_find_device_by_node(np_dvbm); + + g_dvbm = rk_dvbm_get_port(p_dvbm, DVBM_ISP_PORT); + of_node_put(np_dvbm); + } + +end: + return ret; +} + +int rkisp_dvbm_init(struct rkisp_stream *stream) +{ + struct rkisp_device *dev = stream->ispdev; + struct rkisp_dummy_buffer *buf = &stream->dummy_buf; + struct dvbm_isp_cfg_t dvbm_cfg; + u32 width, height, wrap_line; + + if (!g_dvbm) + return -EINVAL; + + width = stream->out_fmt.plane_fmt[0].bytesperline; + height = stream->out_fmt.height; + wrap_line = dev->cap_dev.wrap_line; + dvbm_cfg.dma_addr = buf->dma_addr; + dvbm_cfg.ybuf_bot = 0; + dvbm_cfg.ybuf_top = width * wrap_line; + dvbm_cfg.ybuf_lstd = width; + dvbm_cfg.ybuf_fstd = width * height; + dvbm_cfg.cbuf_bot = dvbm_cfg.ybuf_top; + dvbm_cfg.cbuf_top = dvbm_cfg.cbuf_bot + (width * wrap_line / 2); + dvbm_cfg.cbuf_lstd = width; + dvbm_cfg.cbuf_fstd = dvbm_cfg.ybuf_fstd / 2; + + rk_dvbm_ctrl(g_dvbm, DVBM_ISP_SET_CFG, &dvbm_cfg); + rk_dvbm_link(g_dvbm); + return 0; +} + +void rkisp_dvbm_deinit(void) +{ + if (g_dvbm) + rk_dvbm_unlink(g_dvbm); +} + +int rkisp_dvbm_event(struct rkisp_device *dev, u32 event) +{ + enum dvbm_cmd cmd; + u32 seq; + + if (!g_dvbm || dev->isp_ver != ISP_V32 || + !dev->cap_dev.wrap_line) + return -EINVAL; + + rkisp_dmarx_get_frame(dev, &seq, NULL, NULL, true); + + switch (event) { + case CIF_ISP_V_START: + cmd = DVBM_ISP_FRM_START; + break; + case CIF_MI_MP_FRAME: + cmd = DVBM_ISP_FRM_END; + break; + default: + return -EINVAL; + } + + return rk_dvbm_ctrl(g_dvbm, cmd, &seq); +} diff --git a/include/uapi/linux/rkisp2-config.h b/include/uapi/linux/rkisp2-config.h index 83c98e7f9811..1b073655575e 100644 --- a/include/uapi/linux/rkisp2-config.h +++ b/include/uapi/linux/rkisp2-config.h @@ -67,6 +67,12 @@ #define RKISP_CMD_SET_MIRROR_FLIP \ _IOW('V', BASE_VIDIOC_PRIVATE + 106, struct rkisp_mirror_flip) +#define RKISP_CMD_GET_WRAP_LINE \ + _IOR('V', BASE_VIDIOC_PRIVATE + 107, int) +/* set wrap line before VIDIOC_S_FMT */ +#define RKISP_CMD_SET_WRAP_LINE \ + _IOW('V', BASE_VIDIOC_PRIVATE + 108, int) + /*************************************************************/ #define ISP2X_ID_DPCC (0)