mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-07 03:15:31 +09:00
media: rockchip: isp: bridge v30 connect to ispp
Change-Id: I4dc870e46127133639d131194276da91da3ac023 Signed-off-by: Cai YiWei <cyw@rock-chips.com>
This commit is contained in:
@@ -24,6 +24,7 @@ video_rkisp-$(CONFIG_VIDEO_ROCKCHIP_ISP_VERSION_V20) += \
|
||||
isp_params_v2x.o \
|
||||
capture_v20.o \
|
||||
bridge.o \
|
||||
bridge_v20.o \
|
||||
isp_mipi_luma.o
|
||||
|
||||
video_rkisp-$(CONFIG_VIDEO_ROCKCHIP_ISP_VERSION_V21) += \
|
||||
@@ -34,6 +35,8 @@ video_rkisp-$(CONFIG_VIDEO_ROCKCHIP_ISP_VERSION_V21) += \
|
||||
video_rkisp-$(CONFIG_VIDEO_ROCKCHIP_ISP_VERSION_V30) += \
|
||||
capture_v30.o \
|
||||
isp_stats_v3x.o \
|
||||
isp_params_v3x.o
|
||||
isp_params_v3x.o \
|
||||
bridge.o \
|
||||
bridge_v30.o
|
||||
|
||||
video_rkisp-$(CONFIG_VIDEO_ROCKCHIP_THUNDER_BOOT_ISP) += rkisp_tb_helper.o
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -17,6 +17,10 @@ struct rkisp_bridge_ops {
|
||||
int (*config)(struct rkisp_bridge_device *dev);
|
||||
void (*disable)(struct rkisp_bridge_device *dev);
|
||||
bool (*is_stopped)(struct rkisp_bridge_device *dev);
|
||||
int (*start)(struct rkisp_bridge_device *dev);
|
||||
int (*stop)(struct rkisp_bridge_device *dev);
|
||||
void (*update_mi)(struct rkisp_bridge_device *dev);
|
||||
int (*frame_end)(struct rkisp_bridge_device *dev, u32 state);
|
||||
};
|
||||
|
||||
struct rkisp_bridge_config {
|
||||
@@ -68,22 +72,34 @@ struct rkisp_bridge_device {
|
||||
bool frame_early;
|
||||
};
|
||||
|
||||
#if IS_ENABLED(CONFIG_VIDEO_ROCKCHIP_ISP_VERSION_V20)
|
||||
#if IS_ENABLED(CONFIG_VIDEO_ROCKCHIP_ISP_VERSION_V20) || IS_ENABLED(CONFIG_VIDEO_ROCKCHIP_ISP_VERSION_V30)
|
||||
int rkisp_register_bridge_subdev(struct rkisp_device *dev,
|
||||
struct v4l2_device *v4l2_dev);
|
||||
void rkisp_unregister_bridge_subdev(struct rkisp_device *dev);
|
||||
int rkisp_bridge_get_fbcbuf_fd(struct rkisp_device *dev, struct isp2x_buf_idxfd *idxfd);
|
||||
void rkisp_bridge_isr(u32 *mis_val, struct rkisp_device *dev);
|
||||
void rkisp_bridge_sendtopp_buffer(struct rkisp_device *dev, u32 dev_id, u32 buf_idx);
|
||||
void rkisp_bridge_save_spbuf(struct rkisp_device *dev, struct rkisp_buffer *sp_buf);
|
||||
void rkisp_bridge_stop_spstream(struct rkisp_device *dev);
|
||||
void rkisp_bridge_update_mi(struct rkisp_device *dev, u32 isp_mis);
|
||||
void rkisp_get_bridge_sd(struct platform_device *dev, struct v4l2_subdev **sd);
|
||||
#else
|
||||
static inline int rkisp_register_bridge_subdev(struct rkisp_device *dev, struct v4l2_device *v4l2_dev) { return 0; }
|
||||
static inline void rkisp_unregister_bridge_subdev(struct rkisp_device *dev) {}
|
||||
static inline int rkisp_bridge_get_fbcbuf_fd(struct rkisp_device *dev, struct isp2x_buf_idxfd *idxfd) { return 0; }
|
||||
static inline void rkisp_bridge_update_mi(struct rkisp_device *dev, u32 isp_mis) {}
|
||||
#endif
|
||||
|
||||
#if IS_ENABLED(CONFIG_VIDEO_ROCKCHIP_ISP_VERSION_V20)
|
||||
int rkisp_bridge_get_fbcbuf_fd(struct rkisp_device *dev, struct isp2x_buf_idxfd *idxfd);
|
||||
void rkisp_bridge_sendtopp_buffer(struct rkisp_device *dev, u32 dev_id, u32 buf_idx);
|
||||
void rkisp_bridge_save_spbuf(struct rkisp_device *dev, struct rkisp_buffer *sp_buf);
|
||||
void rkisp_bridge_stop_spstream(struct rkisp_device *dev);
|
||||
void rkisp_bridge_init_ops_v20(struct rkisp_bridge_device *dev);
|
||||
#else
|
||||
static inline int rkisp_bridge_get_fbcbuf_fd(struct rkisp_device *dev, struct isp2x_buf_idxfd *idxfd) { return 0; }
|
||||
static inline void rkisp_bridge_init_ops_v20(struct rkisp_bridge_device *dev) {}
|
||||
#endif
|
||||
|
||||
#if IS_ENABLED(CONFIG_VIDEO_ROCKCHIP_ISP_VERSION_V30)
|
||||
void rkisp_bridge_init_ops_v30(struct rkisp_bridge_device *dev);
|
||||
#else
|
||||
static inline void rkisp_bridge_init_ops_v30(struct rkisp_bridge_device *dev) {}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
1094
drivers/media/platform/rockchip/isp/bridge_v20.c
Normal file
1094
drivers/media/platform/rockchip/isp/bridge_v20.c
Normal file
File diff suppressed because it is too large
Load Diff
236
drivers/media/platform/rockchip/isp/bridge_v30.c
Normal file
236
drivers/media/platform/rockchip/isp/bridge_v30.c
Normal file
@@ -0,0 +1,236 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/* Copyright (c) 2019 Fuzhou Rockchip Electronics Co., Ltd. */
|
||||
|
||||
#include <linux/delay.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <media/v4l2-common.h>
|
||||
#include <media/v4l2-event.h>
|
||||
#include <media/v4l2-fh.h>
|
||||
#include <media/v4l2-ioctl.h>
|
||||
#include <media/v4l2-subdev.h>
|
||||
#include <media/videobuf2-dma-contig.h>
|
||||
#include <linux/dma-iommu.h>
|
||||
#include <linux/rk-camera-module.h>
|
||||
#include "dev.h"
|
||||
#include "regs.h"
|
||||
|
||||
static inline
|
||||
struct rkisp_bridge_buf *to_bridge_buf(struct rkisp_ispp_buf *dbufs)
|
||||
{
|
||||
return container_of(dbufs, struct rkisp_bridge_buf, dbufs);
|
||||
}
|
||||
|
||||
static void crop_on(struct rkisp_bridge_device *dev)
|
||||
{
|
||||
struct rkisp_device *ispdev = dev->ispdev;
|
||||
u32 src_w = ispdev->isp_sdev.out_crop.width;
|
||||
u32 src_h = ispdev->isp_sdev.out_crop.height;
|
||||
u32 dest_w = dev->crop.width;
|
||||
u32 dest_h = dev->crop.height;
|
||||
u32 left = dev->crop.left;
|
||||
u32 top = dev->crop.top;
|
||||
u32 ctrl = CIF_DUAL_CROP_CFG_UPD;
|
||||
|
||||
rkisp_write(ispdev, CIF_DUAL_CROP_M_H_OFFS, left, false);
|
||||
rkisp_write(ispdev, CIF_DUAL_CROP_M_V_OFFS, top, false);
|
||||
rkisp_write(ispdev, CIF_DUAL_CROP_M_H_SIZE, dest_w, false);
|
||||
rkisp_write(ispdev, CIF_DUAL_CROP_M_V_SIZE, dest_h, false);
|
||||
ctrl |= rkisp_read(ispdev, CIF_DUAL_CROP_CTRL, true);
|
||||
if (src_w == dest_w && src_h == dest_h)
|
||||
ctrl &= ~(CIF_DUAL_CROP_MP_MODE_YUV | CIF_DUAL_CROP_MP_MODE_RAW);
|
||||
else
|
||||
ctrl |= CIF_DUAL_CROP_MP_MODE_YUV;
|
||||
rkisp_write(ispdev, CIF_DUAL_CROP_CTRL, ctrl, false);
|
||||
}
|
||||
|
||||
static void crop_off(struct rkisp_bridge_device *dev)
|
||||
{
|
||||
struct rkisp_device *ispdev = dev->ispdev;
|
||||
u32 ctrl = CIF_DUAL_CROP_GEN_CFG_UPD;
|
||||
|
||||
ctrl = rkisp_read(ispdev, CIF_DUAL_CROP_CTRL, true);
|
||||
ctrl &= ~(CIF_DUAL_CROP_MP_MODE_YUV | CIF_DUAL_CROP_MP_MODE_RAW);
|
||||
rkisp_write(ispdev, CIF_DUAL_CROP_CTRL, ctrl, false);
|
||||
}
|
||||
|
||||
static int bridge_start(struct rkisp_bridge_device *dev)
|
||||
{
|
||||
crop_on(dev);
|
||||
dev->ops->config(dev);
|
||||
|
||||
rkisp_stats_first_ddr_config(&dev->ispdev->stats_vdev);
|
||||
if (!dev->ispdev->hw_dev->is_mi_update)
|
||||
force_cfg_update(dev->ispdev);
|
||||
|
||||
dev->ispdev->skip_frame = 0;
|
||||
dev->en = true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int bridge_stop(struct rkisp_bridge_device *dev)
|
||||
{
|
||||
int ret;
|
||||
|
||||
dev->stopping = true;
|
||||
if (dev->ispdev->hw_dev->is_single)
|
||||
dev->ops->disable(dev);
|
||||
ret = wait_event_timeout(dev->done, !dev->en,
|
||||
msecs_to_jiffies(1000));
|
||||
if (!ret)
|
||||
v4l2_warn(&dev->sd,
|
||||
"%s timeout ret:%d\n", __func__, ret);
|
||||
crop_off(dev);
|
||||
dev->stopping = false;
|
||||
dev->en = false;
|
||||
dev->ops->disable(dev);
|
||||
dev->ispdev->irq_ends_mask &= ~ISP_FRAME_MP;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void bridge_update_mi(struct rkisp_bridge_device *br)
|
||||
{
|
||||
struct rkisp_device *dev = br->ispdev;
|
||||
struct rkisp_hw_dev *hw = dev->hw_dev;
|
||||
struct rkisp_bridge_buf *buf;
|
||||
u32 val;
|
||||
|
||||
if (hw->nxt_buf) {
|
||||
buf = to_bridge_buf(hw->nxt_buf);
|
||||
val = buf->dummy[GROUP_BUF_PIC].dma_addr;
|
||||
rkisp_write(dev, br->cfg->reg.y0_base, val, true);
|
||||
val += br->cfg->offset;
|
||||
rkisp_write(dev, br->cfg->reg.uv0_base, val, true);
|
||||
}
|
||||
|
||||
v4l2_dbg(2, rkisp_debug, &br->sd,
|
||||
"update pic(shd:0x%x base:0x%x)\n",
|
||||
rkisp_read(dev, br->cfg->reg.y0_base_shd, true),
|
||||
rkisp_read(dev, br->cfg->reg.y0_base, true));
|
||||
}
|
||||
|
||||
static int bridge_frame_end(struct rkisp_bridge_device *dev, u32 state)
|
||||
{
|
||||
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();
|
||||
|
||||
if (dev->stopping) {
|
||||
if (!hw->is_single) {
|
||||
dev->en = false;
|
||||
dev->stopping = false;
|
||||
dev->ops->disable(dev);
|
||||
wake_up(&dev->done);
|
||||
} else if (dev->ops->is_stopped(dev)) {
|
||||
dev->en = false;
|
||||
dev->stopping = false;
|
||||
wake_up(&dev->done);
|
||||
}
|
||||
}
|
||||
|
||||
if (!dev->en) {
|
||||
ispdev->irq_ends_mask &= ~ISP_FRAME_MP;
|
||||
return 0;
|
||||
}
|
||||
|
||||
rkisp_dmarx_get_frame(ispdev, &dev->dbg.id, NULL, NULL, true);
|
||||
dev->dbg.interval = ns - dev->dbg.timestamp;
|
||||
dev->dbg.timestamp = ns;
|
||||
if (hw->cur_buf && hw->nxt_buf) {
|
||||
if (ispdev->skip_frame > 0) {
|
||||
ispdev->skip_frame--;
|
||||
spin_lock_irqsave(&hw->buf_lock, lock_flags);
|
||||
list_add_tail(&hw->cur_buf->list, &hw->list);
|
||||
spin_unlock_irqrestore(&hw->buf_lock, lock_flags);
|
||||
} else {
|
||||
ns = 0;
|
||||
rkisp_dmarx_get_frame(ispdev, &hw->cur_buf->frame_id,
|
||||
NULL, &ns, true);
|
||||
if (!ns)
|
||||
ns = ktime_get_ns();
|
||||
hw->cur_buf->frame_timestamp = ns;
|
||||
hw->cur_buf->index = ispdev->dev_id;
|
||||
v4l2_subdev_call(sd, video, s_rx_buffer, hw->cur_buf, NULL);
|
||||
}
|
||||
hw->cur_buf = NULL;
|
||||
} else {
|
||||
v4l2_dbg(1, rkisp_debug, &dev->sd, "lost frm_id %d\n", dev->dbg.id);
|
||||
dev->dbg.frameloss++;
|
||||
}
|
||||
|
||||
if (hw->nxt_buf) {
|
||||
hw->cur_buf = hw->nxt_buf;
|
||||
hw->nxt_buf = NULL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int config_mp(struct rkisp_bridge_device *dev)
|
||||
{
|
||||
u32 w = dev->crop.width;
|
||||
u32 h = dev->crop.height;
|
||||
u32 val;
|
||||
|
||||
val = w * h;
|
||||
rkisp_write(dev->ispdev, CIF_MI_MP_Y_SIZE_INIT, val, false);
|
||||
val = (dev->work_mode & ISP_ISPP_422) ? val : val / 2;
|
||||
rkisp_write(dev->ispdev, CIF_MI_MP_CB_SIZE_INIT, val, false);
|
||||
rkisp_write(dev->ispdev, CIF_MI_MP_CR_SIZE_INIT, 0, false);
|
||||
rkisp_write(dev->ispdev, CIF_MI_MP_Y_OFFS_CNT_INIT, 0, false);
|
||||
rkisp_write(dev->ispdev, CIF_MI_MP_CB_OFFS_CNT_INIT, 0, false);
|
||||
rkisp_write(dev->ispdev, CIF_MI_MP_CR_OFFS_CNT_INIT, 0, false);
|
||||
|
||||
rkisp_write(dev->ispdev, ISP_MPFBC_BASE,
|
||||
dev->work_mode & ISP_ISPP_422, false);
|
||||
rkisp_set_bits(dev->ispdev, CIF_MI_CTRL, MI_CTRL_MP_FMT_MASK,
|
||||
MI_CTRL_MP_WRITE_YUV_SPLA | CIF_MI_CTRL_MP_ENABLE |
|
||||
CIF_MI_MP_AUTOUPDATE_ENABLE, false);
|
||||
dev->ispdev->irq_ends_mask |= ISP_FRAME_MP;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void disable_mp(struct rkisp_bridge_device *dev)
|
||||
{
|
||||
rkisp_clear_bits(dev->ispdev, CIF_MI_CTRL,
|
||||
CIF_MI_CTRL_MP_ENABLE | CIF_MI_CTRL_RAW_ENABLE, false);
|
||||
}
|
||||
|
||||
static bool is_stopped_mp(struct rkisp_bridge_device *dev)
|
||||
{
|
||||
bool en = true;
|
||||
|
||||
if (dev->ispdev->hw_dev->is_single)
|
||||
en = mp_is_stream_stopped(dev->ispdev->base_addr);
|
||||
return en;
|
||||
}
|
||||
|
||||
static struct rkisp_bridge_ops mp_ops = {
|
||||
.config = config_mp,
|
||||
.disable = disable_mp,
|
||||
.is_stopped = is_stopped_mp,
|
||||
.frame_end = bridge_frame_end,
|
||||
.update_mi = bridge_update_mi,
|
||||
.start = bridge_start,
|
||||
.stop = bridge_stop,
|
||||
};
|
||||
|
||||
static struct rkisp_bridge_config mp_cfg = {
|
||||
.frame_end_id = MI_MP_FRAME,
|
||||
.reg = {
|
||||
.y0_base = MI_MP_WR_Y_BASE,
|
||||
.uv0_base = MI_MP_WR_CB_BASE,
|
||||
.y1_base = MI_MP_WR_Y_BASE2,
|
||||
.uv1_base = MI_MP_WR_CB_BASE2,
|
||||
|
||||
.y0_base_shd = MI_MP_WR_Y_BASE_SHD,
|
||||
.uv0_base_shd = MI_MP_WR_CB_BASE_SHD,
|
||||
},
|
||||
};
|
||||
|
||||
void rkisp_bridge_init_ops_v30(struct rkisp_bridge_device *dev)
|
||||
{
|
||||
dev->ops = &mp_ops;
|
||||
dev->cfg = &mp_cfg;
|
||||
}
|
||||
@@ -1080,6 +1080,8 @@ static int rkisp_stream_init(struct rkisp_device *dev, u32 id)
|
||||
strscpy(vdev->name, MP_VDEV_NAME, sizeof(vdev->name));
|
||||
stream->ops = &rkisp_mp_streams_ops;
|
||||
stream->config = &rkisp_mp_stream_config;
|
||||
if (dev->br_dev.linked)
|
||||
stream->linked = false;
|
||||
}
|
||||
|
||||
node = vdev_to_node(vdev);
|
||||
@@ -1157,6 +1159,8 @@ void rkisp_mi_v30_isr(u32 mis_val, struct rkisp_device *dev)
|
||||
v4l2_dbg(3, rkisp_debug, &dev->v4l2_dev,
|
||||
"mi isr:0x%x\n", mis_val);
|
||||
|
||||
rkisp_bridge_isr(&mis_val, dev);
|
||||
|
||||
for (i = 0; i < RKISP_MAX_STREAM; ++i) {
|
||||
stream = &dev->cap_dev.stream[i];
|
||||
|
||||
|
||||
@@ -122,7 +122,7 @@ struct rkisp_ispp_buf {
|
||||
|
||||
int __init rkispp_hw_drv_init(void);
|
||||
|
||||
#if IS_ENABLED(CONFIG_VIDEO_ROCKCHIP_ISP_VERSION_V20)
|
||||
#if IS_ENABLED(CONFIG_VIDEO_ROCKCHIP_ISP_VERSION_V20) || IS_ENABLED(CONFIG_VIDEO_ROCKCHIP_ISP_VERSION_V30)
|
||||
void rkisp_get_bridge_sd(struct platform_device *dev,
|
||||
struct v4l2_subdev **sd);
|
||||
#else
|
||||
|
||||
Reference in New Issue
Block a user