media: rockchip: vpss: add v20 for rv1126b

Signed-off-by: Mingwei Yan <mingwei.yan@rock-chips.com>
Change-Id: I60d64e1d8ffb39f199b6a8cd8352f64b3afef344
This commit is contained in:
Mingwei Yan
2025-02-27 10:54:00 +08:00
committed by Tao Huang
parent 3c1a5874b0
commit 05533d40dc
31 changed files with 7413 additions and 20 deletions

View File

@@ -4,7 +4,7 @@ config VIDEO_ROCKCHIP_VPSS
depends on V4L_PLATFORM_DRIVERS
depends on VIDEO_DEV
depends on ARCH_ROCKCHIP || COMPILE_TEST
depends on CPU_RK3576
depends on CPU_RK3576 || CPU_RV1126B
select VIDEO_V4L2_SUBDEV_API
select VIDEOBUF2_CMA_SG
default n
@@ -18,3 +18,11 @@ config VIDEO_ROCKCHIP_VPSS_V10
default y
help
Support for rk3576
config VIDEO_ROCKCHIP_VPSS_V20
bool "vpss2 for rv1126b"
depends on CPU_RV1126B
depends on VIDEO_ROCKCHIP_VPSS
default y
help
Support for rv1126b

View File

@@ -12,3 +12,13 @@ video_rkvpss-objs += hw.o \
video_rkvpss-$(CONFIG_VIDEO_ROCKCHIP_VPSS_V10) += \
stream_v10.o \
vpss_offline_v10.o
video_rkvpss-$(CONFIG_VIDEO_ROCKCHIP_VPSS_V20) += \
stream_v20.o \
vpss_offline_v20.o \
vpss_offline_rockit.o \
vpss_rockit.o
video_rkvpss-$(CONFIG_ROCKCHIP_DVBM) += \
vpss_dvbm.o \
vpss_offline_dvbm.o

View File

@@ -76,6 +76,7 @@ void rkvpss_unite_clear_bits(struct rkvpss_device *dev, u32 reg, u32 mask)
rkvpss_idx_clear_bits(dev, reg, mask, VPSS_UNITE_RIGHT);
}
// 1126b unite or multi sensor todo
void rkvpss_update_regs(struct rkvpss_device *dev, u32 start, u32 end)
{
struct rkvpss_hw_dev *hw = dev->hw_dev;

View File

@@ -26,6 +26,8 @@
#define RKVPSS_DEFAULT_HEIGHT 1080
#define RKVPSS_MAX_WIDTH 4672
#define RKVPSS_MAX_HEIGHT 3504
#define RKVPSS_MAX_WIDTH_V20 4096
#define RKVPSS_MAX_HEIGHT_V20 3072
#define RKVPSS_MIN_WIDTH 32
#define RKVPSS_MIN_HEIGHT 32
#define RKVPSS_UNITE_MAX_WIDTH 8192
@@ -34,13 +36,19 @@
#define RKVPSS_REG_CACHE_SYNC 0xeeeeeeee
#define RKVPSS_REG_CACHE 0xffffffff
#define RKVPSS_SW_REG_SIZE 0x35c0
#define RKVPSS_SW_REG_SIZE 0x37c0
#define RKVPSS_SW_REG_SIZE_MAX (RKVPSS_SW_REG_SIZE * 2)
struct rkvpss_device;
enum rkvpss_ver {
VPSS_V10 = 0x00,
VPSS_V20 = 0x20,
};
enum {
ROCKIT_DVBM_END,
ROCKIT_DVBM_START,
};
enum rkvpss_fmt_pix_type {
@@ -95,6 +103,8 @@ static inline int vpss_outchn_max(int version)
{
if (version == VPSS_V10)
return 4;
else if (version == VPSS_V20)
return 6;
return 0;
}

View File

@@ -372,6 +372,7 @@ static int __maybe_unused rkvpss_dev_runtime_resume(struct device *dev)
struct rkvpss_device *vpss_dev = dev_get_drvdata(dev);
int ret;
vpss_dev->stream_vdev.wrap_line = rkvpss_wrap_line;
mutex_lock(&vpss_dev->hw_dev->dev_lock);
ret = pm_runtime_get_sync(vpss_dev->hw_dev->dev);
mutex_unlock(&vpss_dev->hw_dev->dev_lock);

View File

@@ -24,6 +24,8 @@
#define S1_VDEV_NAME DRIVER_NAME "_scale1"
#define S2_VDEV_NAME DRIVER_NAME "_scale2"
#define S3_VDEV_NAME DRIVER_NAME "_scale3"
#define S4_VDEV_NAME DRIVER_NAME "_scale4"
#define S5_VDEV_NAME DRIVER_NAME "_scale5"
#define RKVPSS_REGFILE_LEN 50
@@ -50,6 +52,11 @@ struct rkvpss_rdbk_info {
u64 seq;
};
struct rkvpss_wrap_buf {
struct dma_buf *dbuf;
dma_addr_t dma_addr;
};
struct rkvpss_device {
char name[128];
struct device *dev;
@@ -64,6 +71,7 @@ struct rkvpss_device {
struct rkvpss_subdev vpss_sdev;
struct rkvpss_stream_vdev stream_vdev;
struct proc_dir_entry *procfs;
struct rkvpss_wrap_buf wrap_buf;
atomic_t pipe_power_cnt;
atomic_t pipe_stream_cnt;

View File

@@ -655,6 +655,10 @@ static irqreturn_t mi_irq_hdl(int irq, void *ctx)
if (mis_val) {
if (mis_val & RKVPSS_MI_BUS_ERR)
dev_err(dev, "axi bus error\n");
if (is_vpss_v20(hw_dev) &&
mis_val & RKVPSS2X_MI_RD_FBCD_ERR)
dev_err(dev, "rd_fbcd_err\n");
rkvpss_hw_write(hw_dev, RKVPSS_MI_ICR, mis_val);
if (vpss)
rkvpss_mi_isr(vpss, mis_val);
@@ -681,12 +685,26 @@ static const struct vpss_match_data rk3576_vpss_match_data = {
.vpss_ver = VPSS_V10,
};
static const struct vpss_match_data rv1126b_vpss_match_data = {
.irqs = vpss_irqs,
.num_irqs = ARRAY_SIZE(vpss_irqs),
.clks = vpss_clks,
.clks_num = ARRAY_SIZE(vpss_clks),
.vpss_ver = VPSS_V20,
};
static const struct of_device_id rkvpss_hw_of_match[] = {
#ifdef CONFIG_VIDEO_ROCKCHIP_VPSS_V10
{
.compatible = "rockchip,rk3576-rkvpss",
.data = &rk3576_vpss_match_data,
},
#endif
#ifdef CONFIG_VIDEO_ROCKCHIP_VPSS_V20
{
.compatible = "rockchip,rv1126b-rkvpss",
.data = &rv1126b_vpss_match_data,
},
#endif
{},
};
@@ -703,7 +721,7 @@ void rkvpss_hw_reg_restore(struct rkvpss_hw_dev *dev)
{
void __iomem *base = dev->base_addr;
void *reg_buf = dev->sw_reg;
u32 val, *reg, i;
u32 val, *reg, i, range;
dev_info(dev->dev, "%s\n", __func__);
@@ -718,7 +736,9 @@ void rkvpss_hw_reg_restore(struct rkvpss_hw_dev *dev)
writel(val, base + RKVPSS_CMSC_UPDATE);
/* crop1 */
for (i = RKVPSS_CROP1_CTRL; i <= RKVPSS_CROP1_3_V_SIZE; i += 4) {
range = is_vpss_v10(dev) ? RKVPSS_CROP1_3_V_SIZE :
RKVPSS2X_CROP1_5_SIZE;
for (i = RKVPSS_CROP1_CTRL; i <= range; i += 4) {
if (i == RKVPSS_CROP1_UPDATE)
continue;
reg = reg_buf + i;
@@ -765,8 +785,30 @@ void rkvpss_hw_reg_restore(struct rkvpss_hw_dev *dev)
val = RKVPSS_SCL_GEN_UPD | RKVPSS_SCL_FORCE_UPD;
writel(val, base + RKVPSS_SCALE3_UPDATE);
if (is_vpss_v20(dev)) {
for (i = RKVPSS2X_SCALE4_BASE; i <= RKVPSS2X_SCALE4_IN_CROP_OFFSET; i += 4) {
if (i == RKVPSS2X_SCALE4_UPDATE)
continue;
reg = reg_buf + i;
writel(*reg, base + i);
}
val = RKVPSS_SCL_GEN_UPD | RKVPSS_SCL_FORCE_UPD;
writel(val, base + RKVPSS2X_SCALE4_UPDATE);
for (i = RKVPSS2X_SCALE5_BASE; i <= RKVPSS2X_SCALE5_IN_CROP_OFFSET; i += 4) {
if (i == RKVPSS2X_SCALE4_UPDATE)
continue;
reg = reg_buf + i;
writel(*reg, base + i);
}
val = RKVPSS_SCL_GEN_UPD | RKVPSS_SCL_FORCE_UPD;
writel(val, base + RKVPSS2X_SCALE5_UPDATE);
}
/* mi */
for (i = RKVPSS_MI_BASE; i <= RKVPSS_MI_CHN3_WR_LINE_CNT; i += 4) {
range = is_vpss_v10(dev) ? RKVPSS_MI_CHN3_WR_LINE_CNT :
RKVPSS2X_MI_CHN5_WR_LINE_CNT;
for (i = RKVPSS_MI_BASE; i <= range; i += 4) {
if (i >= RKVPSS_MI_RD_CTRL && i <= RKVPSS_MI_RD_Y_HEIGHT_SHD)
continue;
if (i == RKVPSS_MI_WR_INIT)
@@ -787,6 +829,8 @@ void rkvpss_hw_reg_restore(struct rkvpss_hw_dev *dev)
}
val = RKVPSS_CFG_FORCE_UPD | RKVPSS_CFG_GEN_UPD | RKVPSS_MIR_GEN_UPD |
RKVPSS_ONLINE2_CHN_FORCE_UPD;
if (is_vpss_v20(dev))
val |= RKVPSS_MIR_FORCE_UPD;
if (!dev->is_ofl_cmsc)
val |= RKVPSS_MIR_FORCE_UPD;
writel(val, base + RKVPSS_VPSS_UPDATE);

View File

@@ -76,6 +76,12 @@ static inline bool is_vpss_v10(const struct rkvpss_hw_dev *hw_dev) { return hw_d
static inline bool is_vpss_v10(const struct rkvpss_hw_dev *hw_dev) { return false; }
#endif
#ifdef CONFIG_VIDEO_ROCKCHIP_VPSS_V20
static inline bool is_vpss_v20(const struct rkvpss_hw_dev *hw_dev) { return hw_dev->vpss_ver == VPSS_V20; }
#else
static inline bool is_vpss_v20(const struct rkvpss_hw_dev *hw_dev) { return false; }
#endif
#define RKVPSS_ZME_TAP_COE(x, y) (((x) & 0x3ff) | (((y) & 0x3ff) << 16))
extern const s16 rkvpss_zme_tap8_coe[11][17][8];
extern const s16 rkvpss_zme_tap6_coe[11][17][8];

View File

@@ -5,5 +5,6 @@
#define _RKVPSS_REGS_H
#include "regs_v10.h"
#include "regs_v20.h"
#endif

View File

@@ -0,0 +1,322 @@
/* SPDX-License-Identifier: GPL-2.0 */
/* Copyright (c) 2025 Rockchip Electronics Co., Ltd. */
#ifndef _RKVPSS_REGS_V20_H
#define _RKVPSS_REGS_V20_H
/* VPSS */
#define RKVPSS2X_VPSS_BASE 0x0000
#define RKVPSS2X_VPSS_PIPE_ACK2 (RKVPSS2X_VPSS_BASE + 0xb8)
/* CMSC identical */
/* CROP */
#define RKVPSS2X_CROP0_BASE 0x0700
#define RKVPSS2X_CROP0_4_OFFS (RKVPSS2X_CROP0_BASE + 0x50)
#define RKVPSS2X_CROP0_4_SIZE (RKVPSS2X_CROP0_BASE + 0x54)
#define RKVPSS2X_CROP0_5_OFFS (RKVPSS2X_CROP0_BASE + 0x58)
#define RKVPSS2X_CROP0_5_SIZE (RKVPSS2X_CROP0_BASE + 0x5c)
#define RKVPSS2X_CROP0_4_OFFS_SHD (RKVPSS2X_CROP0_BASE + 0xb0)
#define RKVPSS2X_CROP0_4_SIZE_SHD (RKVPSS2X_CROP0_BASE + 0xb4)
#define RKVPSS2X_CROP0_5_OFFS_SHD (RKVPSS2X_CROP0_BASE + 0xb8)
#define RKVPSS2X_CROP0_5_SIZE_SHD (RKVPSS2X_CROP0_BASE + 0xbc)
#define RKVPSS2X_CROP1_BASE 0x0800
#define RKVPSS2X_CROP1_4_OFFS (RKVPSS2X_CROP1_BASE + 0x50)
#define RKVPSS2X_CROP1_4_SIZE (RKVPSS2X_CROP1_BASE + 0x54)
#define RKVPSS2X_CROP1_5_OFFS (RKVPSS2X_CROP1_BASE + 0x58)
#define RKVPSS2X_CROP1_5_SIZE (RKVPSS2X_CROP1_BASE + 0x5c)
#define RKVPSS2X_CROP1_4_OFFS_SHD (RKVPSS2X_CROP1_BASE + 0xb0)
#define RKVPSS2X_CROP1_4_SIZE_SHD (RKVPSS2X_CROP1_BASE + 0xb4)
#define RKVPSS2X_CROP1_5_OFFS_SHD (RKVPSS2X_CROP1_BASE + 0xb8)
#define RKVPSS2X_CROP1_5_SIZE_SHD (RKVPSS2X_CROP1_BASE + 0xbc)
/* Bilinear scale channel0 */
#define RKVPSS2X_SCALE0_BASE 0x1000
#define RKVPSS2X_SCALE0_CTRL (RKVPSS2X_SCALE0_BASE + 0x00)
#define RKVPSS2X_SCALE0_UPDATE (RKVPSS2X_SCALE0_BASE + 0x04)
#define RKVPSS2X_SCALE0_SRC_SIZE (RKVPSS2X_SCALE0_BASE + 0x08)
#define RKVPSS2X_SCALE0_DST_SIZE (RKVPSS2X_SCALE0_BASE + 0x0c)
#define RKVPSS2X_SCALE0_HY_FAC (RKVPSS2X_SCALE0_BASE + 0x10)
#define RKVPSS2X_SCALE0_HC_FAC (RKVPSS2X_SCALE0_BASE + 0x14)
#define RKVPSS2X_SCALE0_VY_FAC (RKVPSS2X_SCALE0_BASE + 0x18)
#define RKVPSS2X_SCALE0_VC_FAC (RKVPSS2X_SCALE0_BASE + 0x1c)
#define RKVPSS2X_SCALE0_HY_OFFS (RKVPSS2X_SCALE0_BASE + 0x20)
#define RKVPSS2X_SCALE0_HC_OFFS (RKVPSS2X_SCALE0_BASE + 0x24)
#define RKVPSS2X_SCALE0_VY_OFFS (RKVPSS2X_SCALE0_BASE + 0x28)
#define RKVPSS2X_SCALE0_VC_OFFS (RKVPSS2X_SCALE0_BASE + 0x2c)
#define RKVPSS2X_SCALE0_HY_SIZE (RKVPSS2X_SCALE0_BASE + 0x40)
#define RKVPSS2X_SCALE0_HC_SIZE (RKVPSS2X_SCALE0_BASE + 0x44)
#define RKVPSS2X_SCALE0_HY_OFFS_MI (RKVPSS2X_SCALE0_BASE + 0x48)
#define RKVPSS2X_SCALE0_HC_OFFS_MI (RKVPSS2X_SCALE0_BASE + 0x4c)
#define RKVPSS2X_SCALE0_IN_CROP_OFFSET (RKVPSS2X_SCALE0_BASE + 0x50)
#define RKVPSS2X_SCALE0_CTRL_SHD (RKVPSS2X_SCALE0_BASE + 0x80)
#define RKVPSS2X_SCALE0_SRC_SIZE_SHD (RKVPSS2X_SCALE0_BASE + 0x88)
#define RKVPSS2X_SCALE0_DST_SIZE_SHD (RKVPSS2X_SCALE0_BASE + 0x8c)
#define RKVPSS2X_SCALE0_HY_FAC_SHD (RKVPSS2X_SCALE0_BASE + 0x90)
#define RKVPSS2X_SCALE0_HC_FAC_SHD (RKVPSS2X_SCALE0_BASE + 0x94)
#define RKVPSS2X_SCALE0_VY_FAC_SHD (RKVPSS2X_SCALE0_BASE + 0x98)
#define RKVPSS2X_SCALE0_VC_FAC_SHD (RKVPSS2X_SCALE0_BASE + 0x9c)
#define RKVPSS2X_SCALE0_HY_OFFS_SHD (RKVPSS2X_SCALE0_BASE + 0xa0)
#define RKVPSS2X_SCALE0_HC_OFFS_SHD (RKVPSS2X_SCALE0_BASE + 0xa4)
#define RKVPSS2X_SCALE0_VY_OFFS_SHD (RKVPSS2X_SCALE0_BASE + 0xa8)
#define RKVPSS2X_SCALE0_VC_OFFS_SHD (RKVPSS2X_SCALE0_BASE + 0xac)
#define RKVPSS2X_SCALE0_HY_SIZE_SHD (RKVPSS2X_SCALE0_BASE + 0xc0)
#define RKVPSS2X_SCALE0_HC_SIZE_SHD (RKVPSS2X_SCALE0_BASE + 0xc4)
#define RKVPSS2X_SCALE0_HY_OFFS_MI_SHD (RKVPSS2X_SCALE0_BASE + 0xc8)
#define RKVPSS2X_SCALE0_HC_OFFS_MI_SHD (RKVPSS2X_SCALE0_BASE + 0xcc)
#define RKVPSS2X_SCALE0_IN_CROP_OFFSET_SHD (RKVPSS2X_SCALE0_BASE + 0xd0)
/* Bilinear scale channel4 */
#define RKVPSS2X_SCALE4_BASE 0x0a00
#define RKVPSS2X_SCALE4_CTRL (RKVPSS2X_SCALE4_BASE + 0x00)
#define RKVPSS2X_SCALE4_UPDATE (RKVPSS2X_SCALE4_BASE + 0x04)
#define RKVPSS2X_SCALE4_SRC_SIZE (RKVPSS2X_SCALE4_BASE + 0x08)
#define RKVPSS2X_SCALE4_DST_SIZE (RKVPSS2X_SCALE4_BASE + 0x0c)
#define RKVPSS2X_SCALE4_HY_FAC (RKVPSS2X_SCALE4_BASE + 0x10)
#define RKVPSS2X_SCALE4_HC_FAC (RKVPSS2X_SCALE4_BASE + 0x14)
#define RKVPSS2X_SCALE4_VY_FAC (RKVPSS2X_SCALE4_BASE + 0x18)
#define RKVPSS2X_SCALE4_VC_FAC (RKVPSS2X_SCALE4_BASE + 0x1c)
#define RKVPSS2X_SCALE4_HY_OFFS (RKVPSS2X_SCALE4_BASE + 0x20)
#define RKVPSS2X_SCALE4_HC_OFFS (RKVPSS2X_SCALE4_BASE + 0x24)
#define RKVPSS2X_SCALE4_VY_OFFS (RKVPSS2X_SCALE4_BASE + 0x28)
#define RKVPSS2X_SCALE4_VC_OFFS (RKVPSS2X_SCALE4_BASE + 0x2c)
#define RKVPSS2X_SCALE4_HY_SIZE (RKVPSS2X_SCALE4_BASE + 0x40)
#define RKVPSS2X_SCALE4_HC_SIZE (RKVPSS2X_SCALE4_BASE + 0x44)
#define RKVPSS2X_SCALE4_HY_OFFS_MI (RKVPSS2X_SCALE4_BASE + 0x48)
#define RKVPSS2X_SCALE4_HC_OFFS_MI (RKVPSS2X_SCALE4_BASE + 0x4c)
#define RKVPSS2X_SCALE4_IN_CROP_OFFSET (RKVPSS2X_SCALE4_BASE + 0x50)
#define RKVPSS2X_SCALE4_CTRL_SHD (RKVPSS2X_SCALE4_BASE + 0x80)
#define RKVPSS2X_SCALE4_SRC_SIZE_SHD (RKVPSS2X_SCALE4_BASE + 0x88)
#define RKVPSS2X_SCALE4_DST_SIZE_SHD (RKVPSS2X_SCALE4_BASE + 0x8c)
#define RKVPSS2X_SCALE4_HY_FAC_SHD (RKVPSS2X_SCALE4_BASE + 0x90)
#define RKVPSS2X_SCALE4_HC_FAC_SHD (RKVPSS2X_SCALE4_BASE + 0x94)
#define RKVPSS2X_SCALE4_VY_FAC_SHD (RKVPSS2X_SCALE4_BASE + 0x98)
#define RKVPSS2X_SCALE4_VC_FAC_SHD (RKVPSS2X_SCALE4_BASE + 0x9c)
#define RKVPSS2X_SCALE4_HY_OFFS_SHD (RKVPSS2X_SCALE4_BASE + 0xa0)
#define RKVPSS2X_SCALE4_HC_OFFS_SHD (RKVPSS2X_SCALE4_BASE + 0xa4)
#define RKVPSS2X_SCALE4_VY_OFFS_SHD (RKVPSS2X_SCALE4_BASE + 0xa8)
#define RKVPSS2X_SCALE4_VC_OFFS_SHD (RKVPSS2X_SCALE4_BASE + 0xac)
#define RKVPSS2X_SCALE4_HY_SIZE_SHD (RKVPSS2X_SCALE4_BASE + 0xc0)
#define RKVPSS2X_SCALE4_HC_SIZE_SHD (RKVPSS2X_SCALE4_BASE + 0xc4)
#define RKVPSS2X_SCALE4_HY_OFFS_MI_SHD (RKVPSS2X_SCALE4_BASE + 0xc8)
#define RKVPSS2X_SCALE4_HC_OFFS_MI_SHD (RKVPSS2X_SCALE4_BASE + 0xcc)
#define RKVPSS2X_SCALE4_IN_CROP_OFFSET_SHD (RKVPSS2X_SCALE4_BASE + 0xd0)
/* Bilinear scale channel5 */
#define RKVPSS2X_SCALE5_BASE 0x0c00
#define RKVPSS2X_SCALE5_CTRL (RKVPSS2X_SCALE5_BASE + 0x00)
#define RKVPSS2X_SCALE5_UPDATE (RKVPSS2X_SCALE5_BASE + 0x04)
#define RKVPSS2X_SCALE5_SRC_SIZE (RKVPSS2X_SCALE5_BASE + 0x08)
#define RKVPSS2X_SCALE5_DST_SIZE (RKVPSS2X_SCALE5_BASE + 0x0c)
#define RKVPSS2X_SCALE5_HY_FAC (RKVPSS2X_SCALE5_BASE + 0x10)
#define RKVPSS2X_SCALE5_HC_FAC (RKVPSS2X_SCALE5_BASE + 0x14)
#define RKVPSS2X_SCALE5_VY_FAC (RKVPSS2X_SCALE5_BASE + 0x18)
#define RKVPSS2X_SCALE5_VC_FAC (RKVPSS2X_SCALE5_BASE + 0x1c)
#define RKVPSS2X_SCALE5_HY_OFFS (RKVPSS2X_SCALE5_BASE + 0x20)
#define RKVPSS2X_SCALE5_HC_OFFS (RKVPSS2X_SCALE5_BASE + 0x24)
#define RKVPSS2X_SCALE5_VY_OFFS (RKVPSS2X_SCALE5_BASE + 0x28)
#define RKVPSS2X_SCALE5_VC_OFFS (RKVPSS2X_SCALE5_BASE + 0x2c)
#define RKVPSS2X_SCALE5_HY_SIZE (RKVPSS2X_SCALE5_BASE + 0x40)
#define RKVPSS2X_SCALE5_HC_SIZE (RKVPSS2X_SCALE5_BASE + 0x44)
#define RKVPSS2X_SCALE5_HY_OFFS_MI (RKVPSS2X_SCALE5_BASE + 0x48)
#define RKVPSS2X_SCALE5_HC_OFFS_MI (RKVPSS2X_SCALE5_BASE + 0x4c)
#define RKVPSS2X_SCALE5_IN_CROP_OFFSET (RKVPSS2X_SCALE5_BASE + 0x50)
#define RKVPSS2X_SCALE5_CTRL_SHD (RKVPSS2X_SCALE5_BASE + 0x80)
#define RKVPSS2X_SCALE5_SRC_SIZE_SHD (RKVPSS2X_SCALE5_BASE + 0x88)
#define RKVPSS2X_SCALE5_DST_SIZE_SHD (RKVPSS2X_SCALE5_BASE + 0x8c)
#define RKVPSS2X_SCALE5_HY_FAC_SHD (RKVPSS2X_SCALE5_BASE + 0x90)
#define RKVPSS2X_SCALE5_HC_FAC_SHD (RKVPSS2X_SCALE5_BASE + 0x94)
#define RKVPSS2X_SCALE5_VY_FAC_SHD (RKVPSS2X_SCALE5_BASE + 0x98)
#define RKVPSS2X_SCALE5_VC_FAC_SHD (RKVPSS2X_SCALE5_BASE + 0x9c)
#define RKVPSS2X_SCALE5_HY_OFFS_SHD (RKVPSS2X_SCALE5_BASE + 0xa0)
#define RKVPSS2X_SCALE5_HC_OFFS_SHD (RKVPSS2X_SCALE5_BASE + 0xa4)
#define RKVPSS2X_SCALE5_VY_OFFS_SHD (RKVPSS2X_SCALE5_BASE + 0xa8)
#define RKVPSS2X_SCALE5_VC_OFFS_SHD (RKVPSS2X_SCALE5_BASE + 0xac)
#define RKVPSS2X_SCALE5_HY_SIZE_SHD (RKVPSS2X_SCALE5_BASE + 0xc0)
#define RKVPSS2X_SCALE5_HC_SIZE_SHD (RKVPSS2X_SCALE5_BASE + 0xc4)
#define RKVPSS2X_SCALE5_HY_OFFS_MI_SHD (RKVPSS2X_SCALE5_BASE + 0xc8)
#define RKVPSS2X_SCALE5_HC_OFFS_MI_SHD (RKVPSS2X_SCALE5_BASE + 0xcc)
#define RKVPSS2X_SCALE5_IN_CROP_OFFSET_SHD (RKVPSS2X_SCALE5_BASE + 0xd0)
/* ASPTO4 */
#define RKVPSS2X_RATIO4_BASE 0x0b00
#define RKVPSS2X_RATIO4_CTRL (RKVPSS2X_RATIO4_BASE + 0x00)
#define RKVPSS2X_RATIO4_UPDATE (RKVPSS2X_RATIO4_BASE + 0x04)
#define RKVPSS2X_RATIO4_ACT_SIZE (RKVPSS2X_RATIO4_BASE + 0x10)
#define RKVPSS2X_RATIO4_VIR_SIZE (RKVPSS2X_RATIO4_BASE + 0x14)
#define RKVPSS2X_RATIO4_OFFS (RKVPSS2X_RATIO4_BASE + 0x18)
#define RKVPSS2X_RATIO4_COLOR (RKVPSS2X_RATIO4_BASE + 0x1c)
#define RKVPSS2X_RATIO4_ACT_SIZE_SHD (RKVPSS2X_RATIO4_BASE + 0x30)
#define RKVPSS2X_RATIO4_VIR_SIZE_SHD (RKVPSS2X_RATIO4_BASE + 0x34)
#define RKVPSS2X_RATIO4_OFFS_SHD (RKVPSS2X_RATIO4_BASE + 0x38)
#define RKVPSS2X_RATIO4_COLOR_SHD (RKVPSS2X_RATIO4_BASE + 0x3c)
/* ASPTO5 */
#define RKVPSS2X_RATIO5_BASE 0x0d00
#define RKVPSS2X_RATIO5_CTRL (RKVPSS2X_RATIO5_BASE + 0x00)
#define RKVPSS2X_RATIO5_UPDATE (RKVPSS2X_RATIO5_BASE + 0x04)
#define RKVPSS2X_RATIO5_ACT_SIZE (RKVPSS2X_RATIO5_BASE + 0x10)
#define RKVPSS2X_RATIO5_VIR_SIZE (RKVPSS2X_RATIO5_BASE + 0x14)
#define RKVPSS2X_RATIO5_OFFS (RKVPSS2X_RATIO5_BASE + 0x18)
#define RKVPSS2X_RATIO5_COLOR (RKVPSS2X_RATIO5_BASE + 0x1c)
#define RKVPSS2X_RATIO5_ACT_SIZE_SHD (RKVPSS2X_RATIO5_BASE + 0x30)
#define RKVPSS2X_RATIO5_VIR_SIZE_SHD (RKVPSS2X_RATIO5_BASE + 0x34)
#define RKVPSS2X_RATIO5_OFFS_SHD (RKVPSS2X_RATIO5_BASE + 0x38)
#define RKVPSS2X_RATIO5_COLOR_SHD (RKVPSS2X_RATIO5_BASE + 0x3c)
/* MI */
#define RKVPSS2X_MI_BASE 0x3000
#define RKVPSS2X_MI_WR_FBCE_CTRL (RKVPSS2X_MI_BASE + 0x20)
#define RKVPSS2X_MI_WR_FBCE_SIZE (RKVPSS2X_MI_BASE + 0x24)
#define RKVPSS2X_MI_WR_FBCE_OFFSET (RKVPSS2X_MI_BASE + 0x28)
#define RKVPSS2X_MI_CHN0_WR_CB_STRIDE (RKVPSS2X_MI_BASE + 0x240)
#define RKVPSS2X_MI_CHN0_WR_CB_PIC_SIZE (RKVPSS2X_MI_BASE + 0x24c)
#define RKVPSS2X_MI_CHN0_WR_Y_STRIDE_SHD (RKVPSS2X_MI_BASE + 0x26c)
#define RKVPSS2X_MI_CHN0_WR_CB_STRIDE_SHD (RKVPSS2X_MI_BASE + 0x27c)
#define RKVPSS2X_MI_CHN1_WR_CB_STRIDE (RKVPSS2X_MI_BASE + 0x340)
#define RKVPSS2X_MI_CHN1_WR_CB_PIC_SIZE (RKVPSS2X_MI_BASE + 0x34c)
#define RKVPSS2X_MI_CHN1_WR_Y_STRIDE_SHD (RKVPSS2X_MI_BASE + 0x36c)
#define RKVPSS2X_MI_CHN1_WR_CB_STRIDE_SHD (RKVPSS2X_MI_BASE + 0x37c)
#define RKVPSS2X_MI_CHN2_WR_Y_STRIDE_SHD (RKVPSS2X_MI_BASE + 0x46c)
#define RKVPSS2X_MI_CHN3_WR_Y_STRIDE_SHD (RKVPSS2X_MI_BASE + 0x56c)
#define RKVPSS2X_MI_CHN4_WR_CTRL (RKVPSS2X_MI_BASE + 0x600)
#define RKVPSS2X_MI_CHN4_WR_Y_BASE (RKVPSS2X_MI_BASE + 0x610)
#define RKVPSS2X_MI_CHN4_WR_Y_SIZE (RKVPSS2X_MI_BASE + 0x614)
#define RKVPSS2X_MI_CHN4_WR_Y_OFFS_CNT (RKVPSS2X_MI_BASE + 0x618)
#define RKVPSS2X_MI_CHN4_WR_Y_OFFS_CNT_START (RKVPSS2X_MI_BASE + 0x61c)
#define RKVPSS2X_MI_CHN4_WR_CB_BASE (RKVPSS2X_MI_BASE + 0x620)
#define RKVPSS2X_MI_CHN4_WR_CB_SIZE (RKVPSS2X_MI_BASE + 0x624)
#define RKVPSS2X_MI_CHN4_WR_CB_OFFS_CNT (RKVPSS2X_MI_BASE + 0x628)
#define RKVPSS2X_MI_CHN4_WR_CB_OFFS_CNT_START (RKVPSS2X_MI_BASE + 0x62c)
#define RKVPSS2X_MI_CHN4_WR_Y_STRIDE (RKVPSS2X_MI_BASE + 0x630)
#define RKVPSS2X_MI_CHN4_WR_Y_PIC_WIDTH (RKVPSS2X_MI_BASE + 0x634)
#define RKVPSS2X_MI_CHN4_WR_Y_PIC_SIZE (RKVPSS2X_MI_BASE + 0x63c)
#define RKVPSS2X_MI_CHN4_WR_CTRL_SHD (RKVPSS2X_MI_BASE + 0x650)
#define RKVPSS2X_MI_CHN4_WR_Y_BASE_SHD (RKVPSS2X_MI_BASE + 0x660)
#define RKVPSS2X_MI_CHN4_WR_Y_SIZE_SHD (RKVPSS2X_MI_BASE + 0x664)
#define RKVPSS2X_MI_CHN4_WR_Y_OFFS_CNT_SHD (RKVPSS2X_MI_BASE + 0x668)
#define RKVPSS2X_MI_CHN4_WR_Y_STRDE_SHD (RKVPSS2X_MI_BASE + 0x66c)
#define RKVPSS2X_MI_CHN4_WR_CB_BASE_SHD (RKVPSS2X_MI_BASE + 0x670)
#define RKVPSS2X_MI_CHN4_WR_CB_SIZE_SHD (RKVPSS2X_MI_BASE + 0x674)
#define RKVPSS2X_MI_CHN4_WR_CB_OFFS_CNT_SHD (RKVPSS2X_MI_BASE + 0x678)
#define RKVPSS2X_MI_CHN4_WR_Y_END_ADDR (RKVPSS2X_MI_BASE + 0x680)
#define RKVPSS2X_MI_CHN4_WR_CB_END_ADDR (RKVPSS2X_MI_BASE + 0x684)
#define RKVPSS2X_MI_CHN4_WR_LINE_CNT (RKVPSS2X_MI_BASE + 0x688)
#define RKVPSS2X_MI_CHN5_WR_CTRL (RKVPSS2X_MI_BASE + 0x700)
#define RKVPSS2X_MI_CHN5_WR_Y_BASE (RKVPSS2X_MI_BASE + 0x710)
#define RKVPSS2X_MI_CHN5_WR_Y_SIZE (RKVPSS2X_MI_BASE + 0x714)
#define RKVPSS2X_MI_CHN5_WR_Y_OFFS_CNT (RKVPSS2X_MI_BASE + 0x718)
#define RKVPSS2X_MI_CHN5_WR_Y_OFFS_CNT_START (RKVPSS2X_MI_BASE + 0x71c)
#define RKVPSS2X_MI_CHN5_WR_CB_BASE (RKVPSS2X_MI_BASE + 0x720)
#define RKVPSS2X_MI_CHN5_WR_CB_SIZE (RKVPSS2X_MI_BASE + 0x724)
#define RKVPSS2X_MI_CHN5_WR_CB_OFFS_CNT (RKVPSS2X_MI_BASE + 0x728)
#define RKVPSS2X_MI_CHN5_WR_CB_OFFS_CNT_START (RKVPSS2X_MI_BASE + 0x72c)
#define RKVPSS2X_MI_CHN5_WR_Y_STRIDE (RKVPSS2X_MI_BASE + 0x730)
#define RKVPSS2X_MI_CHN5_WR_Y_PIC_WIDTH (RKVPSS2X_MI_BASE + 0x734)
#define RKVPSS2X_MI_CHN5_WR_Y_PIC_SIZE (RKVPSS2X_MI_BASE + 0x73c)
#define RKVPSS2X_MI_CHN5_WR_CTRL_SHD (RKVPSS2X_MI_BASE + 0x750)
#define RKVPSS2X_MI_CHN5_WR_Y_BASE_SHD (RKVPSS2X_MI_BASE + 0x760)
#define RKVPSS2X_MI_CHN5_WR_Y_SIZE_SHD (RKVPSS2X_MI_BASE + 0x764)
#define RKVPSS2X_MI_CHN5_WR_Y_OFFS_CNT_SHD (RKVPSS2X_MI_BASE + 0x768)
#define RKVPSS2X_MI_CHN5_WR_Y_STRDE_SHD (RKVPSS2X_MI_BASE + 0x76c)
#define RKVPSS2X_MI_CHN5_WR_CB_BASE_SHD (RKVPSS2X_MI_BASE + 0x770)
#define RKVPSS2X_MI_CHN5_WR_CB_SIZE_SHD (RKVPSS2X_MI_BASE + 0x774)
#define RKVPSS2X_MI_CHN5_WR_CB_OFFS_CNT_SHD (RKVPSS2X_MI_BASE + 0x778)
#define RKVPSS2X_MI_CHN5_WR_Y_END_ADDR (RKVPSS2X_MI_BASE + 0x780)
#define RKVPSS2X_MI_CHN5_WR_CB_END_ADDR (RKVPSS2X_MI_BASE + 0x784)
#define RKVPSS2X_MI_CHN5_WR_LINE_CNT (RKVPSS2X_MI_BASE + 0x788)
/********* BIT **********/
/* VPSS_CTRL */
#define RKVPSS2X_VPSS2ENC_PATH_EN BIT(11)
#define RKVPSS2X_SENSOR_ID(x) (((x) & 0x7) << 12)
#define RKVPSS2X_CHN4_CMSC_SEL(x) (((x) & 0x3) << 16)
#define RKVPSS2X_CHN5_CMSC_SEL(x) (((x) & 0x3) << 18)
/* VPSS_ONLINE */
#define RKVPSS2X_ISP2VPSS_CHN4_SEL(x) (((x) & 0x3) << 8)
#define RKVPSS2X_ISP2VPSS_CHN5_SEL(x) (((x) & 0x3) << 10)
/* VPSS_CLK_EN */
#define RKVPSS2X_SCL4_CLK_EN BIT(12)
#define RKVPSS2X_SCL5_CLK_EN BIT(13)
#define RKVPSS2X_RATIO4_CLK_EN BIT(14)
#define RKVPSS2X_RATIO5_CLK_EN BIT(15)
/* VPSS_CLK_GATE */
#define RKVPSS2X_SCL4_CKG_DIS BIT(12)
#define RKVPSS2X_SCL5_CKG_DIS BIT(13)
#define RKVPSS2X_RATIO4_CKG_DIS BIT(14)
#define RKVPSS2X_RATI05_CKG_DIS BIT(15)
#define RKVPSS2X_MI_CHN4_CKG_DIS BIT(20)
#define RKVPSS2X_MI_CHN5_CKG_DIS BIT(21)
/* VPSS_IMSC */
#define RKVPSS2X_SCL4_IN_FRM_END BIT(16)
#define RKVPSS2X_SCL5_IN_FRM_END BIT(17)
#define RKVPSS2X_RATIO4_IN_FRM_END BIT(18)
#define RKVPSS2X_RATIO5_IN_FRM_END BIT(19)
/* VPSS_CTRL_SHD */
#define RKVPSS2X_VPSS2ENC_PATH_EN_SHD BIT(11)
/* VPSS_ONLINE_SHD */
#define RKVPSS2X_CHN4_EN_SHD BIT(8)
#define RKVPSS2X_ISP_CHN4_EN_SHD BIT(9)
#define RKVPSS2X_CHN5_EN_SHD BIT(10)
#define RKVPSS2X_ISP_CHN5_EN_SHD BIT(11)
#define RKVPSS2X_ISP_USE_CMSC_EN_SHD BIT(18)
#define RKVPSS2X_VPSS_USE_CMSC_EN_SHD BIT(19)
/* VPSS_WORKING */
#define RKVPSS2X_SCL4_WORKING BIT(12)
#define RKVPSS2X_SCL5_WORKING BIT(13)
#define RKVPSS2X_RATIO4_WORKING BIT(14)
#define RKVPSS2X_RATIO5_WORKING BIT(15)
/* CMSC_CTRL */
#define RKVPSS2X_CMSC_BLK_SIZE(x) (((x) & 0x7) << 8)
/* CROP_CTRL_SHD */
#define RKVPSS2X_CROP_CHN4_EN_SHD BIT(4)
#define RKVPSS2X_CROP_CHN5_EN_SHD BIT(5)
/* CROP_CH4_5 */
#define RKVPSS2X_CROP_OFFS(v, h) (((v & 0x3fff) << 16) | (h & 0x3fff))
#define RKVPSS2X_CROP_SIZE(v, h) (((v & 0x3fff) << 16) | (h & 0x3fff))
/* SCALE_CTRL */
#define RKVPSS2X_SW_AVG_SCALE_H_EN BIT(8)
#define RKVPSS2X_SW_AVG_SCALE_V_EN BIT(9)
/* MI_FORCE_UPDATE */
#define RKVPSS2X_MI_CHN4_FORCE_UPD BIT(8)
#define RKVPSS2X_MI_CHN5_FORCE_UPD BIT(9)
/* MI_WR_FBCE_SET */
#define RKVPSS2X_MI_WR_FBCE_SEL(x) (BIT(0) << (x))
#define RKVPSS2X_WR_FBCE_FORCE_UN_EN BIT(2)
#define RKVPSS2X_WR_FBCE_PAYL_ALIGN_EN BIT(3)
#define RKVPSS2X_MI_WR_FBCE_SET_SHD(x) (BIT(28) << (x))
/* MI_IMSC */
#define RKVPSS2X_MI_CHN4_FRM_END BIT(16)
#define RKVPSS2X_MI_CHN5_FRM_END BIT(17)
#define RKVPSS2X_MI_RD_FBCD_ERR BIT(29)
/* MI_RD_CTRL */
#define RKVPSS2X_MI_RD_INPUT_UYVY 3
/* MI_CHN1_WR_CTRL */
#define RKVPSS2X_CH1_WR_RGB888_ALPHA(x) ((x & 0xff) << 16)
/* MI_WR_FBCE_CTRL */
#define RKVPSS2X_SW_MI_WR_FBCE_SEL(x) ((x) & 0x3)
/* MI_WR_FBCE_SIZE */
#define RKVPSS2X_SW_WR_FBCE_SIZE(w, h) ((w & 0x7fff) | (h & 0x7fff) << 16)
#endif

View File

@@ -11,11 +11,14 @@
#include "regs.h"
#include "stream_v10.h"
#include "stream_v20.h"
void rkvpss_cmsc_config(struct rkvpss_device *dev, bool sync)
{
if (is_vpss_v10(dev->hw_dev))
rkvpss_cmsc_config_v10(dev, sync);
else if (is_vpss_v20(dev->hw_dev))
rkvpss_cmsc_config_v20(dev, sync);
}
int rkvpss_stream_buf_cnt(struct rkvpss_stream *stream)
@@ -25,6 +28,8 @@ int rkvpss_stream_buf_cnt(struct rkvpss_stream *stream)
if (is_vpss_v10(vpss->hw_dev))
ret = rkvpss_stream_buf_cnt_v10(stream);
else if (is_vpss_v20(vpss->hw_dev))
ret = rkvpss_stream_buf_cnt_v20(stream);
return ret;
}
@@ -35,6 +40,8 @@ int rkvpss_register_stream_vdevs(struct rkvpss_device *dev)
if (is_vpss_v10(dev->hw_dev))
ret = rkvpss_register_stream_vdevs_v10(dev);
else if (is_vpss_v20(dev->hw_dev))
ret = rkvpss_register_stream_vdevs_v20(dev);
return ret;
}
@@ -43,6 +50,8 @@ void rkvpss_unregister_stream_vdevs(struct rkvpss_device *dev)
{
if (is_vpss_v10(dev->hw_dev))
rkvpss_unregister_stream_vdevs_v10(dev);
else if (is_vpss_v20(dev->hw_dev))
rkvpss_unregister_stream_vdevs_v20(dev);
}
void rkvpss_stream_default_fmt(struct rkvpss_device *dev, u32 id,
@@ -50,16 +59,22 @@ void rkvpss_stream_default_fmt(struct rkvpss_device *dev, u32 id,
{
if (is_vpss_v10(dev->hw_dev))
rkvpss_stream_default_fmt_v10(dev, id, width, height, pixelformat);
else if (is_vpss_v20(dev->hw_dev))
rkvpss_stream_default_fmt_v20(dev, id, width, height, pixelformat);
}
void rkvpss_isr(struct rkvpss_device *dev, u32 mis_val)
{
if (is_vpss_v10(dev->hw_dev))
rkvpss_isr_v10(dev, mis_val);
else if (is_vpss_v20(dev->hw_dev))
rkvpss_isr_v20(dev, mis_val);
}
void rkvpss_mi_isr(struct rkvpss_device *dev, u32 mis_val)
{
if (is_vpss_v10(dev->hw_dev))
rkvpss_mi_isr_v10(dev, mis_val);
else if (is_vpss_v20(dev->hw_dev))
rkvpss_mi_isr_v20(dev, mis_val);
}

View File

@@ -96,6 +96,10 @@ struct stream_config {
u32 v_offs_shd;
u32 h_size_shd;
u32 v_size_shd;
u32 ch_4_5_offs;
u32 ch_4_5_size;
u32 ch_4_5_offs_shd;
u32 ch_4_5_size_shd;
} crop;
struct {
u32 ctrl;
@@ -162,6 +166,8 @@ struct rkvpss_online_unite_params {
* streaming: stream start flag
* stopping: stream stop flag
* linked: link enable flag
* alpha: argb a value
* avg_scl_down : CH0 and CH2 can use average scale down, 1-16 scale range
*/
struct rkvpss_stream {
struct rkvpss_device *dev;
@@ -186,6 +192,7 @@ struct rkvpss_stream {
struct rkvpss_online_unite_params unite_params;
int id;
u32 alpha;
bool streaming;
bool stopping;
bool linked;
@@ -194,12 +201,15 @@ struct rkvpss_stream {
bool is_mf_upd;
bool is_pause;
bool is_attach_info;
bool rockit_on;
bool avg_scl_down;
};
/* rkvpss stream device */
struct rkvpss_stream_vdev {
struct rkvpss_stream stream[RKVPSS_OUTPUT_MAX];
atomic_t refcnt;
u32 wrap_line;
};
void rkvpss_cmsc_config(struct rkvpss_device *dev, bool sync);

View File

@@ -35,7 +35,7 @@ static inline void rkvpss_stream_default_fmt_v10(struct rkvpss_device *dev, u32
static inline void rkvpss_isr_v10(struct rkvpss_device *dev, u32 mis_val) {}
static inline void rkvpss_mi_isr_v10(struct rkvpss_device *dev, u32 mis_val) {}
static inline void rkvpss_cmsc_config_v10(struct rkvpss_device *dev, bool sync) {}
static inline int rkvpss_stream_buf_cnt_v10(struct rkvpss_stream *stream) {return -EINVAL; }
static inline int rkvpss_stream_buf_cnt_v10(struct rkvpss_stream *stream) {return 0; }
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,58 @@
/* SPDX-License-Identifier: GPL-2.0 */
/* Copyright (c) 2025 Rockchip Electronics Co., Ltd. */
#ifndef _RKVPSS_STREAM_V20_H
#define _RKVPSS_STREAM_V20_H
#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/pm_runtime.h>
#include <linux/slab.h>
#include <media/v4l2-common.h>
#include <media/v4l2-event.h>
#include <media/v4l2-fh.h>
#include <media/v4l2-ioctl.h>
#include <media/v4l2-mc.h>
#include <media/v4l2-subdev.h>
#include <media/videobuf2-dma-contig.h>
#include <media/videobuf2-dma-sg.h>
#include <uapi/linux/rk-video-format.h>
struct rockit_vpss_ops {
int (*rkvpss_stream_start)(struct rkvpss_stream *stream);
void (*rkvpss_stream_stop)(struct rkvpss_stream *stream);
int (*rkvpss_set_fmt)(struct rkvpss_stream *stream,
struct v4l2_pix_format_mplane *pixm,
bool try);
};
int rkvpss_rockit_buf_done(struct rkvpss_stream *stream, int cmd, struct rkvpss_buffer *curr_buf);
int rkvpss_rockit_buf_free(struct rkvpss_stream *stream);
void rkvpss_rockit_buf_state_clear(struct rkvpss_stream *stream);
void rkvpss_rockit_frame_start(struct rkvpss_device *dev);
#if IS_ENABLED(CONFIG_VIDEO_ROCKCHIP_VPSS_V20)
int rkvpss_register_stream_vdevs_v20(struct rkvpss_device *dev);
void rkvpss_unregister_stream_vdevs_v20(struct rkvpss_device *dev);
void rkvpss_stream_default_fmt_v20(struct rkvpss_device *dev, u32 id,
u32 width, u32 height, u32 pixelformat);
void rkvpss_isr_v20(struct rkvpss_device *dev, u32 mis_val);
void rkvpss_mi_isr_v20(struct rkvpss_device *dev, u32 mis_val);
void rkvpss_cmsc_config_v20(struct rkvpss_device *dev, bool sync);
int rkvpss_stream_buf_cnt_v20(struct rkvpss_stream *stream);
#else
static inline int rkvpss_register_stream_vdevs_v20(struct rkvpss_device *dev) {return -EINVAL; }
static inline void rkvpss_unregister_stream_vdevs_v20(struct rkvpss_device *dev) {}
static inline void rkvpss_stream_default_fmt_v20(struct rkvpss_device *dev, u32 id, u32 width, u32 height, u32 pixelformat) {}
static inline void rkvpss_isr_v20(struct rkvpss_device *dev, u32 mis_val) {}
static inline void rkvpss_mi_isr_v20(struct rkvpss_device *dev, u32 mis_val) {}
static inline void rkvpss_cmsc_config_v20(struct rkvpss_device *dev, bool sync) {}
static inline int rkvpss_stream_buf_cnt_v20(struct rkvpss_stream *stream) {return 0; }
#endif
#endif

View File

@@ -28,6 +28,10 @@ static inline const char *s_dev_name(int i)
return S2_VDEV_NAME;
case 3:
return S3_VDEV_NAME;
case 4:
return S4_VDEV_NAME;
case 5:
return S5_VDEV_NAME;
default:
return S0_VDEV_NAME;
}
@@ -185,6 +189,8 @@ static int rkvpss_sd_s_stream(struct v4l2_subdev *sd, int on)
rkvpss_unite_write(dev, RKVPSS_VPSS_ONLINE2_SIZE, h << 16 | w);
val = RKVPSS_CFG_FORCE_UPD | RKVPSS_CFG_GEN_UPD | RKVPSS_MIR_GEN_UPD;
if (dev->hw_dev->vpss_ver == VPSS_V20)
val |= RKVPSS_MIR_FORCE_UPD;
if (!dev->hw_dev->is_ofl_cmsc)
val |= RKVPSS_MIR_FORCE_UPD;
@@ -278,6 +284,7 @@ static int rkvpss_sof(struct rkvpss_subdev *sdev, struct rkisp_vpss_sof *info)
}
if (!info->irq && (!hw->is_single || dev->unite_mode)) {
// 1126b unite or multi sensor todo
hw->cur_dev_id = dev->dev_id;
rkvpss_update_regs(dev, RKVPSS_VPSS_CTRL, RKVPSS_VPSS_ONLINE2_SIZE);
rkvpss_update_regs(dev, RKVPSS_VPSS_IRQ_CFG, RKVPSS_VPSS_IMSC);

View File

@@ -47,9 +47,11 @@ enum rkvpss_state {
VPSS_FRAME_SCL1 = BIT(4),
VPSS_FRAME_SCL2 = BIT(5),
VPSS_FRAME_SCL3 = BIT(6),
VPSS_FRAME_SCL4 = BIT(7),
VPSS_FRAME_SCL5 = BIT(8),
VPSS_START = BIT(8),
VPSS_RX_START = BIT(9),
VPSS_START = BIT(9),
VPSS_RX_START = BIT(10),
};
struct vpsssd_fmt {

View File

@@ -0,0 +1,102 @@
// SPDX-License-Identifier: GPL-2.0
/* Copyright (C) 2025 Rockchip Electronics Co., Ltd. */
#define pr_fmt(fmt) "vpss_dvbm: %s:%d " fmt, __func__, __LINE__
#include "vpss.h"
#include "common.h"
#include "stream.h"
#include "dev.h"
#include "vpss_offline.h"
#include "hw.h"
#include "procfs.h"
#include "regs.h"
#include "vpss_dvbm.h"
#include "stream_v20.h"
static struct dvbm_port *g_dvbm;
int rkvpss_dvbm_get(struct rkvpss_device *vpss_dev)
{
struct device_node *np = vpss_dev->dev->of_node;
struct device_node *np_dvbm = of_parse_phandle(np, "dvbm", 0);
int ret = 0;
g_dvbm = NULL;
if (!np_dvbm || !of_device_is_available(np_dvbm)) {
dev_warn(vpss_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);
put_device(&p_dvbm->dev);
}
of_node_put(np_dvbm);
return ret;
}
int rkvpss_dvbm_init(struct rkvpss_stream *stream)
{
struct rkvpss_device *vpss_dev = stream->dev;
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 = vpss_dev->stream_vdev.wrap_line;
dvbm_cfg.dma_addr = vpss_dev->wrap_buf.dma_addr;
dvbm_cfg.buf = vpss_dev->wrap_buf.dbuf;
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, 0);
return 0;
}
void rkvpss_dvbm_deinit(struct rkvpss_device *vpss_dev)
{
if (!g_dvbm || !vpss_dev) {
pr_err("g_dvbm %p or vpss_dev %p is NULL\n", g_dvbm, vpss_dev);
return;
}
rk_dvbm_unlink(g_dvbm, 0);
}
int rkvpss_dvbm_event(struct rkvpss_device *vpss_dev, u32 event)
{
enum dvbm_cmd cmd;
u32 seq;
if (!g_dvbm || !vpss_dev->stream_vdev.wrap_line)
return -EINVAL;
seq = vpss_dev->vpss_sdev.frame_seq;
switch (event) {
case ROCKIT_DVBM_START:
cmd = DVBM_ISP_FRM_START;
break;
case ROCKIT_DVBM_END:
cmd = DVBM_ISP_FRM_END;
break;
default:
return -EINVAL;
}
return rk_dvbm_ctrl(g_dvbm, cmd, &seq);
}

View File

@@ -0,0 +1,26 @@
/* SPDX-License-Identifier: GPL-2.0 */
/* Copyright (C) 2025 Rockchip Electronics Co., Ltd. */
#ifndef _RKVPSS_DVBM_H
#define _RKVPSS_DVBM_H
#include <linux/of.h>
#include <linux/of_platform.h>
#include <soc/rockchip/rockchip_dvbm.h>
#if IS_ENABLED(CONFIG_ROCKCHIP_DVBM)
int rkvpss_dvbm_get(struct rkvpss_device *vpss_dev);
int rkvpss_dvbm_init(struct rkvpss_stream *stream);
void rkvpss_dvbm_deinit(struct rkvpss_device *vpss_dev);
int rkvpss_dvbm_event(struct rkvpss_device *vpss_dev, u32 event);
#else
static inline int rkvpss_dvbm_get(struct rkvpss_device *vpss_dev) {return -EINVAL; }
static inline int rkvpss_dvbm_init(struct rkvpss_stream *stream) {return -EINVAL; }
static inline void rkvpss_dvbm_deinit(struct rkvpss_device *vpss_dev) {}
static inline int rkvpss_dvbm_event(struct rkvpss_device *vpss_dev, u32 event) {return -EINVAL; }
#endif
#endif

View File

@@ -14,6 +14,7 @@
#include "regs.h"
#include "vpss_offline_v10.h"
#include "vpss_offline_v20.h"
void rkvpss_dump_reg(struct rkvpss_offline_dev *ofl, int sequence, int size)
{
@@ -72,6 +73,8 @@ void rkvpss_offline_irq(struct rkvpss_hw_dev *hw, u32 irq)
{
if (is_vpss_v10(hw))
rkvpss_offline_irq_v10(hw, irq);
else if (is_vpss_v20(hw))
rkvpss_offline_irq_v20(hw, irq);
}
int rkvpss_register_offline(struct rkvpss_hw_dev *hw)
@@ -80,6 +83,8 @@ int rkvpss_register_offline(struct rkvpss_hw_dev *hw)
if (is_vpss_v10(hw))
ret = rkvpss_register_offline_v10(hw);
else if (is_vpss_v20(hw))
ret = rkvpss_register_offline_v20(hw);
return ret;
}
@@ -88,5 +93,7 @@ void rkvpss_unregister_offline(struct rkvpss_hw_dev *hw)
{
if (is_vpss_v10(hw))
rkvpss_unregister_offline_v10(hw);
else if (is_vpss_v20(hw))
rkvpss_unregister_offline_v20(hw);
}

View File

@@ -75,6 +75,9 @@ struct rkvpss_offline_dev {
struct rkvpss_unite_scl_params unite_params[RKVPSS_OUTPUT_MAX];
struct completion pm_cmpl;
u32 unite_right_enlarge;
struct idr file_idr;
struct mutex idr_lock;
struct mutex handle_lock;
bool mode_sel_en;
bool pm_need_wait;
};

View File

@@ -0,0 +1,96 @@
// SPDX-License-Identifier: GPL-2.0
/* Copyright (C) 2025 Rockchip Electronics Co., Ltd. */
#define pr_fmt(fmt) "vpss_dvbm: %s:%d " fmt, __func__, __LINE__
#include "vpss.h"
#include "common.h"
#include "stream.h"
#include "dev.h"
#include "vpss_offline.h"
#include "hw.h"
#include "procfs.h"
#include "regs.h"
#include "vpss_offline_dvbm.h"
static struct dvbm_port *g_ofl_dvbm;
int rkvpss_ofl_dvbm_get(struct rkvpss_offline_dev *ofl)
{
struct device_node *np = ofl->hw->dev->of_node;
struct device_node *np_dvbm = of_parse_phandle(np, "dvbm", 0);
int ret = 0;
g_ofl_dvbm = NULL;
if (!np_dvbm || !of_device_is_available(np_dvbm)) {
dev_warn(ofl->hw->dev, "failed to get dvbm node\n");
} else {
struct platform_device *p_dvbm = of_find_device_by_node(np_dvbm);
g_ofl_dvbm = rk_dvbm_get_port(p_dvbm, DVBM_ISP_PORT);
put_device(&p_dvbm->dev);
}
of_node_put(np_dvbm);
return ret;
}
int rkvpss_ofl_dvbm_init(struct dma_buf *dbuf, u32 dma_addr, u32 wrap_line,
int width, int height, int id)
{
struct dvbm_isp_cfg_t dvbm_cfg;
if (!g_ofl_dvbm)
return -EINVAL;
dvbm_cfg.dma_addr = dma_addr;
dvbm_cfg.buf = dbuf;
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;
dvbm_cfg.chan_id = id;
rk_dvbm_ctrl(g_ofl_dvbm, DVBM_ISP_SET_CFG, &dvbm_cfg);
rk_dvbm_link(g_ofl_dvbm, id);
return 0;
}
void rkvpss_ofl_dvbm_deinit(struct rkvpss_offline_dev *ofl, int id)
{
if (!g_ofl_dvbm || !ofl) {
pr_err("g_dvbm %p or vpss_dev %p is NULL\n", g_ofl_dvbm, ofl);
return;
}
rk_dvbm_unlink(g_ofl_dvbm, id);
}
int rkvpss_ofl_dvbm_event(u32 event, u32 seq)
{
enum dvbm_cmd cmd;
if (!g_ofl_dvbm)
return -EINVAL;
switch (event) {
case ROCKIT_DVBM_START:
cmd = DVBM_ISP_FRM_START;
break;
case ROCKIT_DVBM_END:
cmd = DVBM_ISP_FRM_END;
break;
default:
return -EINVAL;
}
return rk_dvbm_ctrl(g_ofl_dvbm, cmd, &seq);
}

View File

@@ -0,0 +1,26 @@
/* SPDX-License-Identifier: GPL-2.0 */
/* Copyright (C) 2025 Rockchip Electronics Co., Ltd. */
#ifndef _RKVPSS_OFFLINE_DVBM_H
#define _RKVPSS_OFFLINE_DVBM_H
#include <linux/of.h>
#include <linux/of_platform.h>
#include <soc/rockchip/rockchip_dvbm.h>
#if IS_ENABLED(CONFIG_ROCKCHIP_DVBM)
int rkvpss_ofl_dvbm_get(struct rkvpss_offline_dev *ofl);
int rkvpss_ofl_dvbm_init(struct dma_buf *dbuf, u32 dma_addr, u32 wrap_line, int width, int height, int id);
void rkvpss_ofl_dvbm_deinit(struct rkvpss_offline_dev *ofl, int id);
int rkvpss_ofl_dvbm_event(u32 event, u32 seq);
#else
static inline int rkvpss_ofl_dvbm_get(struct rkvpss_offline_dev *ofl) {return -EINVAL; }
static inline int rkvpss_ofl_dvbm_init(struct dma_buf *dbuf, u32 dma_addr, u32 wrap_line, int width, int height, int id) {return -EINVAL; }
static inline void rkvpss_ofl_dvbm_deinit(struct rkvpss_offline_dev *ofl, int id) {}
static inline int rkvpss_ofl_dvbm_event(u32 event, u32 seq) {return -EINVAL; }
#endif
#endif

View File

@@ -0,0 +1,113 @@
// SPDX-License-Identifier: GPL-2.0
/* Copyright (C) 2025 Rockchip Electronics Co., Ltd. */
#include "vpss.h"
#include "common.h"
#include "stream.h"
#include "dev.h"
#include "vpss_offline.h"
#include "hw.h"
#include "procfs.h"
#include "regs.h"
#include "vpss_offline_rockit.h"
#include "vpss_offline_v20.h"
static struct rkvpss_offline_dev *global_ofl;
void rkvpss_ofl_rockit_init(struct rkvpss_offline_dev *ofl)
{
global_ofl = ofl;
}
static long rkvpss_ofl_rockit_open(int *file_id)
{
void *temp_file = kmalloc(sizeof(void *), GFP_KERNEL);
long ret = 0;
*file_id = rkvpss_ofl_add_file_id(global_ofl, temp_file);
if (*file_id <= 0) {
ret = -EINVAL;
kfree(temp_file);
goto out;
}
mutex_lock(&global_ofl->hw->dev_lock);
pm_runtime_get_sync(global_ofl->hw->dev);
mutex_unlock(&global_ofl->hw->dev_lock);
v4l2_dbg(1, rkvpss_debug, &global_ofl->v4l2_dev,
"%s file_id:%d\n", __func__, *file_id);
out:
return ret;
}
static long rkvpss_ofl_rockit_release(int *file_id)
{
void *idr_entity = NULL;
long ret = 0;
rkvpss_ofl_buf_del_by_file(global_ofl, *file_id);
idr_entity = idr_remove(&global_ofl->file_idr, *file_id);
if (!idr_entity)
goto out;
kfree(idr_entity);
mutex_lock(&global_ofl->hw->dev_lock);
pm_runtime_put_sync(global_ofl->hw->dev);
mutex_unlock(&global_ofl->hw->dev_lock);
v4l2_dbg(1, rkvpss_debug, &global_ofl->v4l2_dev,
"%s file_id:%d\n", __func__, *file_id);
out:
return ret;
}
static void *rkvpss_ofl_check_file_id(struct rkvpss_offline_dev *ofl,
int file_id)
{
void *idr_entity = NULL;
mutex_lock(&ofl->idr_lock);
idr_entity = idr_find(&ofl->file_idr, file_id);
mutex_unlock(&ofl->idr_lock);
return idr_entity;
}
long vpss_rockit_action(int *file_id, unsigned int cmd, void *arg)
{
long ret = 0;
switch (cmd) {
case RKVPSS_CMD_OPEN:
ret = rkvpss_ofl_rockit_open(file_id);
break;
case RKVPSS_CMD_RELEASE:
ret = rkvpss_ofl_rockit_release(file_id);
break;
case RKVPSS_CMD_MODULE_SEL:
case RKVPSS_CMD_MODULE_GET:
case RKVPSS_CMD_BUF_ADD:
case RKVPSS_CMD_BUF_DEL:
case RKVPSS_CMD_FRAME_HANDLE:
case RKVPSS_CMD_CHECKPARAMS:
case RKVPSS_CMD_WRAP_DVBM_INIT:
case RKVPSS_CMD_WRAP_DVBM_DEINIT:
if (!rkvpss_ofl_check_file_id(global_ofl, *file_id)) {
v4l2_err(&global_ofl->v4l2_dev, "file_id error\n");
ret = -EINVAL;
goto out;
}
ret = rkvpss_ofl_action(global_ofl, *file_id, cmd, arg);
break;
default:
break;
}
out:
return ret;
}
EXPORT_SYMBOL(vpss_rockit_action);

View File

@@ -0,0 +1,13 @@
/* SPDX-License-Identifier: GPL-2.0 */
/* Copyright (c) 2025 Rockchip Electronics Co., Ltd. */
#ifndef _RKVPSS_OFFLINE_ROCKIT_H
#define _RKVPSS_OFFLINE_ROCKIT_H
#include <linux/pm_runtime.h>
struct rkvpss_offline_dev;
void rkvpss_ofl_rockit_init(struct rkvpss_offline_dev *ofl);
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,40 @@
/* SPDX-License-Identifier: GPL-2.0 */
/* Copyright (c) 2025 Rockchip Electronics Co., Ltd. */
#ifndef _RKVPSS_OFFLINE_V20_H
#define _RKVPSS_OFFLINE_V20_H
struct rkvpss_offline_dev;
//void buf_del(struct rkvpss_offline_dev *ofl,
// struct dma_buf *dmabuf,
// int file_id, int id, int fd, bool is_all,
// bool running);
int rkvpss_module_sel(struct rkvpss_offline_dev *ofl,
struct rkvpss_module_sel *sel);
int rkvpss_module_get(struct rkvpss_offline_dev *ofl,
struct rkvpss_module_sel *get);
int rkvpss_ofl_buf_add(struct rkvpss_offline_dev *ofl, int file_id, struct rkvpss_buf_info *info);
void rkvpss_ofl_buf_del(struct rkvpss_offline_dev *ofl, int file_id, struct rkvpss_buf_info *info);
void rkvpss_ofl_buf_del_by_file(struct rkvpss_offline_dev *ofl, int file_id);
int rkvpss_prepare_run(struct rkvpss_offline_dev *ofl, int file_id, struct rkvpss_frame_cfg *cfg);
int rkvpss_check_params(struct rkvpss_offline_dev *ofl, struct rkvpss_frame_cfg *cfg, bool *unite);
long rkvpss_ofl_action(struct rkvpss_offline_dev *ofl, int file_id, unsigned int cmd, void *arg);
int rkvpss_ofl_add_file_id(struct rkvpss_offline_dev *ofl, void *idr_entity);
void *rkvpss_ofl_del_file_id(struct rkvpss_offline_dev *ofl, struct file *file);
#if IS_ENABLED(CONFIG_VIDEO_ROCKCHIP_VPSS_V20)
int rkvpss_register_offline_v20(struct rkvpss_hw_dev *hw);
void rkvpss_unregister_offline_v20(struct rkvpss_hw_dev *hw);
void rkvpss_offline_irq_v20(struct rkvpss_hw_dev *hw, u32 irq);
#else
static inline int rkvpss_register_offline_v20(struct rkvpss_hw_dev *hw) {return -EINVAL; }
static inline void rkvpss_unregister_offline_v20(struct rkvpss_hw_dev *hw) {}
static inline void rkvpss_offline_irq_v20(struct rkvpss_hw_dev *hw, u32 irq) {}
#endif
#endif

View File

@@ -0,0 +1,617 @@
// SPDX-License-Identifier: GPL-2.0
/* Copyright (C) 2025 Rockchip Electronics Co., Ltd. */
#define pr_fmt(fmt) "vpss_rockit: %s:%d " fmt, __func__, __LINE__
#include "vpss.h"
#include "common.h"
#include "stream.h"
#include "dev.h"
#include "vpss_offline.h"
#include "hw.h"
#include "procfs.h"
#include "regs.h"
#include "stream_v20.h"
#include "vpss_rockit.h"
#include "vpss_dvbm.h"
static struct rockit_rkvpss_cfg *rockit_vpss_cfg;
struct rkvpss_rockit_buffer {
struct rkvpss_buffer vpss_buffer;
struct dma_buf *dmabuf;
struct dma_buf_attachment *dba;
struct sg_table *sgt;
void *mpi_buf;
struct list_head queue;
int buf_id;
u32 buff_addr;
void *vaddr;
};
static struct rkvpss_stream *rkvpss_rockit_get_stream(struct rockit_rkvpss_cfg *input_cfg)
{
struct rkvpss_device *vpss_dev = NULL;
struct rkvpss_stream *stream = NULL;
u8 i;
if (!rockit_vpss_cfg) {
pr_err("rockit_vpss_cfg is null, get stream failed\n");
return NULL;
}
if (!input_cfg) {
pr_err("input_cfg is null, get stream failed\n");
return NULL;
}
for (i = 0; i < rockit_vpss_cfg->vpss_num; i++) {
if (!strcmp(rockit_vpss_cfg->rkvpss_dev_cfg[i].vpss_name,
input_cfg->current_name)) {
vpss_dev = rockit_vpss_cfg->rkvpss_dev_cfg[i].vpss_dev;
break;
}
}
if (vpss_dev == NULL) {
pr_err("can not find vpss_dev!\n");
return NULL;
}
switch (input_cfg->nick_id) {
case 0:
stream = &vpss_dev->stream_vdev.stream[RKVPSS_OUTPUT_CH0];
break;
case 1:
stream = &vpss_dev->stream_vdev.stream[RKVPSS_OUTPUT_CH1];
break;
case 2:
stream = &vpss_dev->stream_vdev.stream[RKVPSS_OUTPUT_CH2];
break;
case 3:
stream = &vpss_dev->stream_vdev.stream[RKVPSS_OUTPUT_CH3];
break;
default:
stream = NULL;
break;
}
return stream;
}
static void rkvpss_rockit_cfg_stream_buffer(struct rkvpss_stream *stream,
struct rkvpss_rockit_buffer *vpssrk_buf,
struct rockit_rkvpss_cfg *input_cfg)
{
u32 y_offs = 0, uv_offs = 0;
u32 dma_addr = vpssrk_buf->buff_addr;
struct capture_fmt *fmt;
fmt = &stream->out_cap_fmt;
if (input_cfg->vir_width) {
stream->out_fmt.plane_fmt[0].bytesperline = input_cfg->vir_width *
DIV_ROUND_UP(fmt->bpp[0], 8);
y_offs = input_cfg->y_offset;
uv_offs = input_cfg->uv_offset;
stream->out_fmt.plane_fmt[1].bytesperline = input_cfg->vir_width *
DIV_ROUND_UP(fmt->bpp[0], 8);
stream->out_fmt.plane_fmt[1].sizeimage = stream->out_fmt.plane_fmt[1].bytesperline *
stream->out_fmt.height;
} else {
y_offs = 0;
if (stream->dev->stream_vdev.wrap_line && stream->id == RKVPSS_OUTPUT_CH0) {
uv_offs = stream->out_fmt.plane_fmt[0].bytesperline *
stream->dev->stream_vdev.wrap_line;
stream->dev->wrap_buf.dbuf = vpssrk_buf->dmabuf;
stream->dev->wrap_buf.dma_addr = dma_addr;
} else {
uv_offs = stream->out_fmt.plane_fmt[0].bytesperline * stream->out_fmt.height;
}
}
vpssrk_buf->vpss_buffer.dma[0] = dma_addr + y_offs;
vpssrk_buf->vpss_buffer.dma[1] = dma_addr + uv_offs;
vpssrk_buf->vpss_buffer.vaddr[0] = NULL;
vpssrk_buf->vpss_buffer.vaddr[1] = NULL;
vpssrk_buf->vpss_buffer.vb.vb2_buf.planes[0].mem_priv = NULL;
if (vpssrk_buf->vaddr) {
vpssrk_buf->vpss_buffer.vaddr[0] = vpssrk_buf->vaddr + y_offs;
vpssrk_buf->vpss_buffer.vaddr[1] = vpssrk_buf->vaddr + uv_offs;
vpssrk_buf->vpss_buffer.vb.vb2_buf.planes[0].mem_priv = vpssrk_buf->sgt;
}
}
int rkvpss_rockit_buf_queue(struct rockit_rkvpss_cfg *input_cfg)
{
struct rkvpss_stream *stream = NULL;
struct rkvpss_rockit_buffer *vpssrk_buf = NULL;
struct rkvpss_device *vpss_dev = NULL;
struct rkvpss_stream_cfg *stream_cfg = NULL;
unsigned long lock_flags = 0;
int dev_id, i;
if (!input_cfg) {
pr_err("input_cfg is null\n");
return -EINVAL;
}
stream = rkvpss_rockit_get_stream(input_cfg);
if (!stream || stream->id >= ROCKIT_STREAM_NUM_MAX) {
pr_err("inval stream");
return -EINVAL;
}
dev_id = stream->dev->dev_id;
vpss_dev = stream->dev;
if (!rockit_vpss_cfg) {
pr_err("rockit_vpss_cfg is null\n");
return -EINVAL;
}
stream_cfg = &rockit_vpss_cfg->rkvpss_dev_cfg[dev_id].rkvpss_stream_cfg[stream->id];
stream_cfg->node = input_cfg->node;
if (!input_cfg->buf)
return -EINVAL;
for (i = 0; i < ROCKIT_BUF_NUM_MAX; i++) {
if (stream_cfg->buff_id[i] == input_cfg->mpi_id) {
input_cfg->is_alloc = 0;
break;
}
}
if (input_cfg->is_alloc) {
struct dma_buf_attachment *dba;
struct sg_table *sgt;
struct iosys_map map;
for (i = 0; i < ROCKIT_BUF_NUM_MAX; i++) {
if (!stream_cfg->buff_id[i] && !stream_cfg->rkvpss_buff[i]) {
stream_cfg->buff_id[i] = input_cfg->mpi_id;
vpssrk_buf = kzalloc(sizeof(struct rkvpss_rockit_buffer),
GFP_KERNEL);
if (!vpssrk_buf) {
stream_cfg->buff_id[i] = 0;
pr_err("vpssrk_buf alloc failed\n");
return -ENOMEM;
}
break;
}
}
if (i == ROCKIT_BUF_NUM_MAX)
return -EINVAL;
dba = dma_buf_attach(input_cfg->buf, vpss_dev->hw_dev->dev);
if (IS_ERR(dba)) {
kfree(vpssrk_buf);
stream_cfg->buff_id[i] = 0;
return PTR_ERR(dba);
}
sgt = dma_buf_map_attachment(dba, DMA_BIDIRECTIONAL);
if (IS_ERR(sgt)) {
dma_buf_detach(input_cfg->buf, dba);
kfree(vpssrk_buf);
stream_cfg->buff_id[i] = 0;
return PTR_ERR(sgt);
}
vpssrk_buf->vaddr = NULL;
if (dma_buf_vmap(input_cfg->buf, &map) == 0)
vpssrk_buf->vaddr = map.vaddr;
vpssrk_buf->buff_addr = sg_dma_address(sgt->sgl);
get_dma_buf(input_cfg->buf);
vpssrk_buf->mpi_buf = input_cfg->mpibuf;
vpssrk_buf->dmabuf = input_cfg->buf;
vpssrk_buf->dba = dba;
vpssrk_buf->sgt = sgt;
stream_cfg->rkvpss_buff[i] = vpssrk_buf;
}
/*no todo, vpss use update config mi addr */
spin_lock_irqsave(&stream->vbq_lock, lock_flags);
vpssrk_buf = NULL;
for (i = 0; i < ROCKIT_BUF_NUM_MAX; i++) {
if (stream_cfg->buff_id[i] == input_cfg->mpi_id) {
vpssrk_buf = stream_cfg->rkvpss_buff[i];
break;
}
}
if (!vpssrk_buf) {
spin_unlock_irqrestore(&stream->vbq_lock, lock_flags);
return -EINVAL;
}
if (stream->out_cap_fmt.mplanes == 1)
rkvpss_rockit_cfg_stream_buffer(stream, vpssrk_buf, input_cfg);
v4l2_dbg(2, rkvpss_debug, &vpss_dev->v4l2_dev,
"stream:%d rockit_queue buf:%p y:0x%x uv:0x%x\n",
stream->id, vpssrk_buf,
vpssrk_buf->vpss_buffer.dma[0], vpssrk_buf->vpss_buffer.dma[1]);
list_add_tail(&vpssrk_buf->vpss_buffer.queue, &stream->buf_queue);
spin_unlock_irqrestore(&stream->vbq_lock, lock_flags);
if (stream->is_pause)
stream->ops->update_mi(stream);
return 0;
}
int rkvpss_rockit_buf_done(struct rkvpss_stream *stream, int cmd, struct rkvpss_buffer *curr_buf)
{
struct rkvpss_device *vpss_dev = stream->dev;
struct rkvpss_rockit_buffer *vpssrk_buf = NULL;
struct rkvpss_stream_cfg *stream_cfg = NULL;
unsigned long lock_flags = 0;
u32 dev_id = vpss_dev->dev_id;
if (!rockit_vpss_cfg ||
!rockit_vpss_cfg->rkvpss_rockit_mpibuf_done ||
stream->id >= ROCKIT_STREAM_NUM_MAX)
return -EINVAL;
v4l2_dbg(4, rkvpss_debug, &vpss_dev->v4l2_dev, "%s enter cmd:%d\n", __func__, cmd);
if (!stream->rockit_on) {
if (!vpss_dev->stream_vdev.wrap_line) {
spin_lock_irqsave(&stream->vbq_lock, lock_flags);
list_add_tail(&curr_buf->queue, &stream->buf_queue);
spin_unlock_irqrestore(&stream->vbq_lock, lock_flags);
}
v4l2_dbg(2, rkvpss_debug, &vpss_dev->v4l2_dev, "%s already stop\n", __func__);
return 0;
}
stream_cfg = &rockit_vpss_cfg->rkvpss_dev_cfg[dev_id].rkvpss_stream_cfg[stream->id];
if (cmd == ROCKIT_DVBM_END) {
vpssrk_buf = container_of(curr_buf, struct rkvpss_rockit_buffer, vpss_buffer);
rockit_vpss_cfg->mpibuf = vpssrk_buf->mpi_buf;
rockit_vpss_cfg->frame.u64PTS = curr_buf->vb.vb2_buf.timestamp;
rockit_vpss_cfg->frame.u32TimeRef = curr_buf->vb.sequence;
v4l2_dbg(2, rkvpss_debug, &vpss_dev->v4l2_dev,
"stream:%d seq:%d rockit buf done:0x%x\n",
stream->id,
curr_buf->vb.sequence,
curr_buf->dma[0]);
} else {
//tosee
if (!(stream->dev->stream_vdev.wrap_line && stream->id == RKVPSS_OUTPUT_CH0))
return 0;
rockit_vpss_cfg->frame.u64PTS = vpss_dev->vpss_sdev.frame_timestamp;
rockit_vpss_cfg->frame.u32TimeRef = vpss_dev->vpss_sdev.frame_seq;
}
rockit_vpss_cfg->frame.u32Height = stream->out_fmt.height;
rockit_vpss_cfg->frame.u32Width = stream->out_fmt.width;
rockit_vpss_cfg->frame.enPixelFormat = stream->out_fmt.pixelformat;
rockit_vpss_cfg->frame.u32VirWidth = stream->out_fmt.width;
rockit_vpss_cfg->frame.u32VirHeight = stream->out_fmt.height;
rockit_vpss_cfg->current_name = vpss_dev->name;
rockit_vpss_cfg->node = stream_cfg->node;
rockit_vpss_cfg->event = cmd;
if (list_empty(&stream->buf_queue))
rockit_vpss_cfg->is_empty = true;
else
rockit_vpss_cfg->is_empty = false;
rockit_vpss_cfg->rkvpss_rockit_mpibuf_done(rockit_vpss_cfg);
return 0;
}
/* dynamic refmt */
int rkvpss_rockit_pause_stream(struct rockit_rkvpss_cfg *input_cfg)
{
struct rkvpss_stream *stream = NULL;
stream = rkvpss_rockit_get_stream(input_cfg);
if (stream == NULL) {
pr_err("the stream is null\n");
return -EINVAL;
}
v4l2_dbg(1, rkvpss_debug, &stream->dev->v4l2_dev,
"%s stream:%d\n", __func__, stream->id);
rockit_vpss_ops.rkvpss_stream_stop(stream);
if (stream->dev->stream_vdev.wrap_line && stream->id == RKVPSS_OUTPUT_CH0)
rkvpss_dvbm_deinit(stream->dev);
return 0;
}
EXPORT_SYMBOL(rkvpss_rockit_pause_stream);
/* dynamic refmt */
int rkvpss_rockit_config_stream(struct rockit_rkvpss_cfg *input_cfg,
int width, int height, int wrap_line)
{
struct rkvpss_stream *stream = NULL;
struct rkvpss_buffer *vpss_buf, *buf_temp;
int ret;
unsigned long lock_flags = 0;
stream = rkvpss_rockit_get_stream(input_cfg);
if (stream == NULL) {
pr_err("the stream is null\n");
return -EINVAL;
}
v4l2_dbg(1, rkvpss_debug, &stream->dev->v4l2_dev,
"%s stream:%d %dx%d wrap_line:%d\n",
__func__, stream->id, width, height, wrap_line);
stream->dev->stream_vdev.wrap_line = wrap_line;
stream->out_fmt.width = width;
stream->out_fmt.height = height;
stream->out_fmt.plane_fmt[0].bytesperline = 0;
ret = rockit_vpss_ops.rkvpss_set_fmt(stream, &stream->out_fmt, false);
if (ret < 0) {
pr_err("stream id %d config failed\n", stream->id);
return -EINVAL;
}
/* wrap mode */
if (stream->dev->stream_vdev.wrap_line && stream->id == RKVPSS_OUTPUT_CH0)
rkvpss_dvbm_init(stream);
spin_lock_irqsave(&stream->vbq_lock, lock_flags);
if (stream->curr_buf) {
list_add_tail(&stream->curr_buf->queue, &stream->buf_queue);
if (stream->curr_buf == stream->next_buf)
stream->next_buf = NULL;
stream->curr_buf = NULL;
}
if (stream->next_buf) {
list_add_tail(&stream->next_buf->queue, &stream->buf_queue);
stream->next_buf = NULL;
}
list_for_each_entry_safe(vpss_buf, buf_temp, &stream->buf_queue, queue) {
struct rkvpss_rockit_buffer *vpssrk_buf = container_of(vpss_buf,
struct rkvpss_rockit_buffer, vpss_buffer);
if (stream->out_cap_fmt.mplanes == 1)
rkvpss_rockit_cfg_stream_buffer(stream, vpssrk_buf, input_cfg);
}
spin_unlock_irqrestore(&stream->vbq_lock, lock_flags);
return 0;
}
EXPORT_SYMBOL(rkvpss_rockit_config_stream);
/* dynamic refmt */
int rkvpss_rockit_resume_stream(struct rockit_rkvpss_cfg *input_cfg)
{
struct rkvpss_stream *stream = NULL;
int ret = 0;
stream = rkvpss_rockit_get_stream(input_cfg);
if (stream == NULL) {
pr_err("the stream is NULL");
return -EINVAL;
}
v4l2_dbg(1, rkvpss_debug, &stream->dev->v4l2_dev,
"%s stream:%d\n", __func__, stream->id);
ret = rockit_vpss_ops.rkvpss_stream_start(stream);
if (ret < 0) {
pr_err("stream id:%d start failed\n", stream->id);
return -EINVAL;
}
//tosee
return 0;
}
EXPORT_SYMBOL(rkvpss_rockit_resume_stream);
void rkvpss_rockit_buf_state_clear(struct rkvpss_stream *stream)
{
struct rkvpss_stream_cfg *stream_cfg;
u32 i = 0, dev_id = stream->dev->dev_id;
if (!rockit_vpss_cfg || stream->id >= ROCKIT_STREAM_NUM_MAX)
return;
stream_cfg = &rockit_vpss_cfg->rkvpss_dev_cfg[dev_id].rkvpss_stream_cfg[stream->id];
for (i = 0; i < ROCKIT_BUF_NUM_MAX; i++)
stream_cfg->buff_id[i] = 0;
}
int rkvpss_rockit_buf_free(struct rkvpss_stream *stream)
{
struct rkvpss_rockit_buffer *vpssrk_buf;
struct rkvpss_stream_cfg *stream_cfg;
u32 i = 0, dev_id = stream->dev->dev_id;
if (!rockit_vpss_cfg || stream->id >= ROCKIT_STREAM_NUM_MAX)
return -EINVAL;
stream_cfg = &rockit_vpss_cfg->rkvpss_dev_cfg[dev_id].rkvpss_stream_cfg[stream->id];
mutex_lock(&stream_cfg->freebuf_lock);
for (i = 0; i < ROCKIT_BUF_NUM_MAX; i++) {
if (!stream_cfg->rkvpss_buff[i])
continue;
vpssrk_buf = (struct rkvpss_rockit_buffer *)stream_cfg->rkvpss_buff[i];
if (vpssrk_buf->dba) {
if (vpssrk_buf->vaddr) {
struct iosys_map map = IOSYS_MAP_INIT_VADDR(vpssrk_buf->vaddr);
dma_buf_vunmap(vpssrk_buf->dmabuf, &map);
vpssrk_buf->vaddr = NULL;
}
if (vpssrk_buf->sgt) {
dma_buf_unmap_attachment(vpssrk_buf->dba,
vpssrk_buf->sgt, DMA_BIDIRECTIONAL);
vpssrk_buf->sgt = NULL;
}
dma_buf_detach(vpssrk_buf->dmabuf, vpssrk_buf->dba);
dma_buf_put(vpssrk_buf->dmabuf);
vpssrk_buf->dba = NULL;
}
kfree(stream_cfg->rkvpss_buff[i]);
stream_cfg->rkvpss_buff[i] = NULL;
}
mutex_unlock(&stream_cfg->freebuf_lock);
return 0;
}
/* when rockit stream off call */
int rkvpss_rockit_free_stream_buf(struct rockit_rkvpss_cfg *input_cfg)
{
struct rkvpss_stream *stream;
struct rkvpss_buffer *buf;
unsigned long lock_flags = 0;
if (!input_cfg)
return -EINVAL;
stream = rkvpss_rockit_get_stream(input_cfg);
if (!stream)
return -EINVAL;
if (stream->streaming)
return 0;
v4l2_dbg(1, rkvpss_debug, &stream->dev->v4l2_dev,
"%s stream:%d\n", __func__, stream->id);
spin_lock_irqsave(&stream->vbq_lock, lock_flags);
if (stream->curr_buf) {
list_add_tail(&stream->curr_buf->queue, &stream->buf_queue);
if (stream->curr_buf == stream->next_buf)
stream->next_buf = NULL;
stream->curr_buf = NULL;
}
if (stream->next_buf) {
list_add_tail(&stream->next_buf->queue, &stream->buf_queue);
stream->next_buf = NULL;
}
while (!list_empty(&stream->buf_queue)) {
buf = list_first_entry(&stream->buf_queue, struct rkvpss_buffer, queue);
list_del(&buf->queue);
}
rkvpss_rockit_buf_state_clear(stream);
spin_unlock_irqrestore(&stream->vbq_lock, lock_flags);
rkvpss_rockit_buf_free(stream);
return 0;
}
EXPORT_SYMBOL(rkvpss_rockit_free_stream_buf);
void rkvpss_rockit_dev_init(struct rkvpss_device *dev)
{
struct rkvpss_stream_cfg *stream_cfg;
int i, j;
if (rockit_vpss_cfg == NULL) {
rockit_vpss_cfg = kzalloc(sizeof(struct rockit_rkvpss_cfg), GFP_KERNEL);
if (rockit_vpss_cfg == NULL)
return;
}
rockit_vpss_cfg->vpss_num = dev->hw_dev->dev_num;
for (i = 0; i < rockit_vpss_cfg->vpss_num; i++) {
if (dev->hw_dev->vpss[i]) {
rockit_vpss_cfg->rkvpss_dev_cfg[i].vpss_name = dev->hw_dev->vpss[i]->name;
rockit_vpss_cfg->rkvpss_dev_cfg[i].vpss_dev = dev->hw_dev->vpss[i];
for (j = 0; j < vpss_outchn_max(dev->hw_dev->vpss_ver); j++) {
stream_cfg = &rockit_vpss_cfg->rkvpss_dev_cfg[i].rkvpss_stream_cfg[j];
mutex_init(&stream_cfg->freebuf_lock);
}
}
}
}
void rkvpss_rockit_dev_deinit(void)
{
kfree(rockit_vpss_cfg);
rockit_vpss_cfg = NULL;
}
void rkvpss_rockit_frame_start(struct rkvpss_device *dev)
{
struct rkvpss_stream *stream;
int i;
if (rockit_vpss_cfg == NULL)
return;
for (i = 0; i <= RKVPSS_OUTPUT_CH1; i++) {
stream = &dev->stream_vdev.stream[i];
if (!stream->streaming)
continue;
rkvpss_rockit_buf_done(stream, ROCKIT_DVBM_START, stream->curr_buf);
}
}
void *rkvpss_rockit_function_register(void *function, int cmd)
{
if (rockit_vpss_cfg == NULL) {
pr_err("rockit_vpss_cfg is null, function register failed\n");
return NULL;
}
switch (cmd) {
case ROCKIT_BUF_QUE:
function = rkvpss_rockit_buf_queue;
break;
case ROCKIT_MPIBUF_DONE:
rockit_vpss_cfg->rkvpss_rockit_mpibuf_done = function;
if (!rockit_vpss_cfg->rkvpss_rockit_mpibuf_done)
pr_err("get rkvpss_rockit_mpibuf_done failed\n");
break;
default:
break;
}
return function;
}
EXPORT_SYMBOL(rkvpss_rockit_function_register);
int rkvpss_rockit_get_vpssdev(char **name)
{
int i = 0;
if (rockit_vpss_cfg == NULL) {
pr_err("rockit_vpss_cfg is null\n");
return -EINVAL;
}
if (name == NULL) {
pr_err("the name is null\n");
return -EINVAL;
}
for (i = 0; i < rockit_vpss_cfg->vpss_num; i++)
name[i] = (char *)rockit_vpss_cfg->rkvpss_dev_cfg[i].vpss_name;
if (name[0] == NULL)
return -EINVAL;
else
return 0;
}
EXPORT_SYMBOL(rkvpss_rockit_get_vpssdev);

View File

@@ -0,0 +1,17 @@
/* SPDX-License-Identifier: GPL-2.0 */
/* Copyright (C) 2025 Rockchip Electronics Co., Ltd. */
#ifndef _RKVPSS_ROCKIT_H
#define _RKVPSS_ROCKIT_H
#include <linux/of.h>
#include <linux/of_platform.h>
#include <soc/rockchip/rockchip_rockit.h>
extern struct rockit_vpss_ops rockit_vpss_ops;
void rkvpss_rockit_dev_init(struct rkvpss_device *dev);
void rkvpss_rockit_dev_deinit(void);
#endif

View File

@@ -13,6 +13,7 @@
#define ROCKIT_STREAM_NUM_MAX 12
#define ROCKIT_VICAP_NUM_MAX 6
#define ROCKIT_VPSS_NUM_MAX 3
enum {
RKISP_NORMAL_ONLINE,
@@ -125,6 +126,46 @@ struct rockit_rkcif_cfg {
int (*rkcif_rockit_mpibuf_done)(struct rockit_rkcif_cfg *rockit_cif_cfg);
};
struct rkvpss_stream_cfg {
struct rkvpss_rockit_buffer *rkvpss_buff[ROCKIT_BUF_NUM_MAX];
int buff_id[ROCKIT_BUF_NUM_MAX];
void *node;
int fps_cnt;
int dst_fps;
int cur_fps;
u64 old_time;
bool is_discard;
struct mutex freebuf_lock;
};
struct rkvpss_dev_cfg {
const char *vpss_name;
void *vpss_dev;
struct rkvpss_stream_cfg rkvpss_stream_cfg[ROCKIT_STREAM_NUM_MAX];
};
struct rockit_rkvpss_cfg {
bool is_alloc;
bool is_empty;
bool is_qbuf;
char *current_name;
int *buff_id;
int mpi_id;
u32 nick_id;
u32 event;
int vpss_num;
u32 y_offset;
u32 uv_offset;
u32 vir_width;
void *node;
void *mpibuf;
void *vvi_dev[ROCKIT_VPSS_NUM_MAX];
struct dma_buf *buf;
struct ISP_VIDEO_FRAMES frame;
struct rkvpss_dev_cfg rkvpss_dev_cfg[ROCKIT_VPSS_NUM_MAX];
int (*rkvpss_rockit_mpibuf_done)(struct rockit_rkvpss_cfg *rockit_vpss_cfg);
};
#if IS_ENABLED(CONFIG_VIDEO_ROCKCHIP_ISP_VERSION_V32) || \
IS_ENABLED(CONFIG_VIDEO_ROCKCHIP_ISP_VERSION_V33) || \
IS_ENABLED(CONFIG_VIDEO_ROCKCHIP_ISP_VERSION_V35)
@@ -191,4 +232,45 @@ static inline int rkisp_rockit_free_stream_buf(struct rockit_cfg *input_rockit_c
#endif
#if IS_ENABLED(CONFIG_VIDEO_ROCKCHIP_VPSS_V20)
void *rkvpss_rockit_function_register(void *function, int cmd);
int rkvpss_rockit_get_vpssdev(char **name);
int rkvpss_rockit_buf_queue(struct rockit_rkvpss_cfg *input_cfg);
int rkvpss_rockit_pause_stream(struct rockit_rkvpss_cfg *input_cfg);
int rkvpss_rockit_config_stream(struct rockit_rkvpss_cfg *input_cfg,
int width, int height, int wrap_line);
int rkvpss_rockit_resume_stream(struct rockit_rkvpss_cfg *input_cfg);
int rkvpss_rockit_free_stream_buf(struct rockit_rkvpss_cfg *input_cfg);
#else
static inline void *rkvpss_rockit_function_register(void *function, int cmd)
{
return NULL;
}
static inline int rkvpss_rockit_get_vpssdev(char **name)
{
return -EINVAL;
}
static inline int rkvpss_rockit_buf_queue(struct rockit_rkvpss_cfg *input_cfg)
{
return -EINVAL;
}
static inline int rkvpss_rockit_pause_stream(struct rockit_rkvpss_cfg *input_cfg)
{
return -EINVAL;
}
static inline int rkvpss_rockit_config_stream(struct rockit_rkvpss_cfg *input_cfg,
int width, int height, int wrap_line)
{
return -EINVAL;
}
static inline int rkvpss_rockit_resume_stream(struct rockit_rkvpss_cfg *input_cfg)
{
return -EINVAL;
}
static inline int rkvpss_rockit_free_stream_buf(struct rockit_rkvpss_cfg *input_cfg)
{
return -EINVAL;
}
#endif
#endif

View File

@@ -28,6 +28,7 @@
*/
#define RKVPSS_OUT_V10_MAX 4
#define RKVPSS_OUT_V20_MAX 6
/******vpss(online mode) v4l2 ioctl***************************/
/* set before VIDIOC_S_FMT if dynamically changing output resolution */
@@ -50,6 +51,20 @@
_IOR('V', BASE_VIDIOC_PRIVATE + 5, struct rkvpss_cmsc_cfg)
#define RKVPSS_CMD_SET_CMSC \
_IOW('V', BASE_VIDIOC_PRIVATE + 6, struct rkvpss_cmsc_cfg)
#define RKVPSS_CMD_GET_WRAP_LINE \
_IOR('V', BASE_VIDIOC_PRIVATE + 7, int *)
#define RKVPSS_CMD_SET_WRAP_LINE \
_IOW('V', BASE_VIDIOC_PRIVATE + 8, int *)
#define RKVPSS_CMD_GET_ALPHA \
_IOR('V', BASE_VIDIOC_PRIVATE + 9, int *)
#define RKVPSS_CMD_SET_ALPHA \
_IOW('V', BASE_VIDIOC_PRIVATE + 10, int *)
#define RKVPSS_CMD_GET_AVG_SCL_DOWN \
_IOR('V', BASE_VIDIOC_PRIVATE + 11, int *)
#define RKVPSS_CMD_SET_AVG_SCL_DOWN \
_IOW('V', BASE_VIDIOC_PRIVATE + 12, int *)
/******vpss(offline mode) independent video ioctl****************/
#define RKVPSS_CMD_MODULE_SEL \
@@ -72,6 +87,20 @@
#define RKVPSS_CMD_STREAM_ATTACH_INFO \
_IOW('V', BASE_VIDIOC_PRIVATE + 56, int)
/****** vpss(offline mode rockit) independent ioctl*************/
#define RKVPSS_CMD_OPEN \
_IOWR('V', BASE_VIDIOC_PRIVATE + 101, int *)
#define RKVPSS_CMD_RELEASE \
_IOWR('V', BASE_VIDIOC_PRIVATE + 102, int *)
#define RKVPSS_CMD_WRAP_DVBM_INIT \
_IOW('V', BASE_VIDIOC_PRIVATE + 103, struct rkvpss_frame_cfg)
#define RKVPSS_CMD_WRAP_DVBM_DEINIT \
_IOW('V', BASE_VIDIOC_PRIVATE + 104, int *)
/********************************************************************/
/* struct rkvpss_mirror_flip
@@ -128,15 +157,19 @@ struct rkvpss_cmsc_win {
/* struct rkvpss_cmsc_cfg
* cover and mosaic configure
* win: priacy mask window
* mosaic_block: Mosaic block size, 0:8x8 1:16x16 2:32x32 3:64x64, share for all windows
* mosaic_block: Mosaic block size, 0:8x8 1:16x16 2:32x32 3:64x64,
* 4: 128x128 (only for rv1126b) share for all windows
* width_ro: vpss full resolution.
* height_ro: vpss full resolution.
* reuse_ch : (only for rv1126b) ch4 and ch5 use ch0 or ch1 or ch2 or ch3 params,
* -1:disable 0:ch0 1:ch1 2:ch23:ch3
*/
struct rkvpss_cmsc_cfg {
struct rkvpss_cmsc_win win[RKVPSS_CMSC_WIN_MAX];
unsigned int mosaic_block;
unsigned int width_ro;
unsigned int height_ro;
int reuse_ch;
} __attribute__ ((packed));
/* struct rkisp_aspt_cfg _____background____
@@ -164,13 +197,30 @@ struct rkvpss_aspt_cfg {
unsigned char enable;
} __attribute__ ((packed));
/* struct rkvpss_wrap_cfg
* vpss to encoder wrap
* only channel0 or channel1 support wrap
* vpss online wrap_line need to bo greater than or equal to 1/4 out height
*/
struct rkvpss_wrap_cfg {
int enable;
int wrap_line;
int buffer_size;
} __attribute__ ((packed));
/********************************************************************/
/*
* V1: ch0 - ch3
* V2: ch0 - ch5
*/
enum {
RKVPSS_OUTPUT_CH0 = 0,
RKVPSS_OUTPUT_CH1,
RKVPSS_OUTPUT_CH2,
RKVPSS_OUTPUT_CH3,
RKVPSS_OUTPUT_CH4,
RKVPSS_OUTPUT_CH5,
RKVPSS_OUTPUT_MAX,
};
@@ -187,16 +237,20 @@ struct rkvpss_module_sel {
/* struct rkvpss_input_cfg
* input configuration of image
*
* width: width of input image, range: 32~4672
* height: height of input image, range: 32~3504
* stride: virtual width of input image, 16 align. auto calculate according to width and format if 0.
* format: V4L2_PIX_FMT_NV12/V4L2_PIX_FMT_NV16/V4L2_PIX_FMT_RGB565/V4L2_PIX_FMT_RGB24/V4L2_PIX_FMT_XBGR32/
* V4L2_PIX_FMT_NV61/V4L2_PIX_FMT_NV21/V4L2_PIX_FMT_RGB565X/V4L2_PIX_FMT_BGR24/V4L2_PIX_FMT_XRGB32/
* V4L2_PIX_FMT_RGBX32/V4L2_PIX_FMT_BGRX32
* width: width of input image, range: 32~4672(rk3576) 32~4096(rv1126b)
* height: height of input image, range: 32~3504(rk3576) 32~3072(rv1126b)
* stride: virtual width of input image, 16 align. auto calculate according to width and
* format if 0.
* format: V4L2_PIX_FMT_NV12/V4L2_PIX_FMT_NV16/V4L2_PIX_FMT_RGB565/V4L2_PIX_FMT_RGB24/
* V4L2_PIX_FMT_XBGR32/
* V4L2_PIX_FMT_NV61/V4L2_PIX_FMT_NV21/V4L2_PIX_FMT_RGB565X/V4L2_PIX_FMT_BGR24/
* V4L2_PIX_FMT_XRGB32/ V4L2_PIX_FMT_RGBX32/V4L2_PIX_FMT_BGRX32
* V4L2_PIX_FMT_FBC0/V4L2_PIX_FMT_FBC2/V4L2_PIX_FMT_FBC4 for rkfbcd
* V4L2_PIX_FMT_TILE420/V4L2_PIX_FMT_TILE422 for tile
* buf_fd: dmabuf fd of input image buf
* rotate: 0:rotate0 1:rotate90 2:rotate180; 3:rotate270, note:only tile input support rotate
* rotate_90: (only for rv1126b) 1:raster rotate90;
* onte: only support input fmt: NV12/NV21/NV16/NV61/UYVY/YUYV
*/
struct rkvpss_input_cfg {
int width;
@@ -205,6 +259,8 @@ struct rkvpss_input_cfg {
int format;
int buf_fd;
int rotate;
int rotate_90;
struct dma_buf *dmabuf;
} __attribute__ ((packed));
/* struct rkvpss_output_cfg __________________
@@ -215,19 +271,24 @@ struct rkvpss_input_cfg {
* crop_v_offs: vertical offset of crop, 2align | | |scl___| | |
* crop_width: crop output width, 2align | |crop______| |
* crop_height: crop output height, 2align |input_____________|
* scl_width: scale width. CH0 1~8 scale range. CH1/CH2/CH3 1~32 scale range. CH2/CH3 max 1080p with scale.
* scl_height: scale height. CH0 1~6 scale range. CH1/CH2/CH3 1~32 scale range. CH2/CH3 max 1080p with scale.
* stride: virtual width of output image, 16 align. auto calculate according to width and format if 0.
* scl_width: scale width. CH0 1~8 scale range. CH1/CH2/CH3 1~32 scale range.
* CH2/CH3 max 1080p with scale.
* scl_height: scale height. CH0 1~6 scale range. CH1/CH2/CH3 1~32 scale range.
* CH2/CH3 max 1080p with scale.
* stride: virtual width of output image, 16 align.
* auto calculate according to width and format if 0.
* format: V4L2_PIX_FMT_NV12/V4L2_PIX_FMT_NV16/V4L2_PIX_FMT_GREY/V4L2_PIX_FMT_UYVY/
* V4L2_PIX_FMT_VYUY/V4L2_PIX_FMT_NV21/V4L2_PIX_FMT_NV61 for all channel.
* NOTE:V,LSB is for all channel
* V4L2_PIX_FMT_RGB565/V4L2_PIX_FMT_RGB24/V4L2_PIX_FMT_XBGR32/V4L2_PIX_FMT_RGB565X/V4L2_PIX_FMT_BGR24/
* V4L2_PIX_FMT_XRGB32 only for RKVPSS_OUTPUT_CH1.
* V4L2_PIX_FMT_RGB565/V4L2_PIX_FMT_RGB24/V4L2_PIX_FMT_XBGR32/V4L2_PIX_FMT_RGB565X/
* V4L2_PIX_FMT_BGR24/V4L2_PIX_FMT_XRGB32 only for RKVPSS_OUTPUT_CH1.
* V4L2_PIX_FMT_TILE420/V4L2_PIX_FMT_TILE422 for tile, ch0 or ch1 support tile
* flip: flip enable
* buf_fd: dmabuf fd of output image buf
* cmsc: cover and mosaic configure
* aspt: aspective ratio for image background color filling
* avg_scl_down: (only for rv1126b) CH0 and CH2 can use average scale down, 1-16 scale range
* alpha: (only for rv1126b) only use for V4L2_PIX_FMT_XBGR32 and V4L2_PIX_FMT_XRGB32 (0-0xff)
*/
struct rkvpss_output_cfg {
int enable;
@@ -243,9 +304,13 @@ struct rkvpss_output_cfg {
int format;
int flip;
int buf_fd;
int avg_scl_down;
unsigned int alpha;
struct rkvpss_cmsc_cfg cmsc;
struct rkvpss_aspt_cfg aspt;
struct dma_buf *dmabuf;
struct rkvpss_wrap_cfg wrap;
} __attribute__ ((packed));
#define RKVPSS_DEV_ID_MAX 128
@@ -284,6 +349,7 @@ struct rkvpss_buf_info {
int buf_cnt;
int buf_size[RKVPSS_BUF_MAX];
int buf_fd[RKVPSS_BUF_MAX];
struct dma_buf *dmabufs[RKVPSS_BUF_MAX];
} __attribute__ ((packed));
struct rkvpss_frame_info {
@@ -309,4 +375,6 @@ struct rkvpss_frame_info {
__u32 isp_reg[6144];
} __attribute__ ((packed));
long vpss_rockit_action(int *file_id, unsigned int cmd, void *arg);
#endif