media: rockchip: rkcif: add support for rk3588 vicap mipi capture

The RK3588 Video Capture (VICAP) unit features a Digital Video Port (DVP)
and six MIPI CSI-2 capture interfaces. Add initial support for this variant
to the rkcif driver and enable the MIPI CSI-2 capture interfaces.

Reviewed-by: Mehdi Djait <mehdi.djait@linux.intel.com>
Signed-off-by: Michael Riesch <michael.riesch@collabora.com>
Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
This commit is contained in:
Michael Riesch 2026-05-22 23:23:09 +02:00 committed by Sakari Ailus
parent 4a6b7bf1de
commit 2175323fdf
4 changed files with 163 additions and 6 deletions

View File

@ -30,6 +30,14 @@
#define RK3568_MIPI_CTRL0_CROP_EN BIT(5)
#define RK3568_MIPI_CTRL0_WRDDR(type) ((type) << 1)
#define RK3588_MIPI_CTRL0_DMA_EN BIT(28)
#define RK3588_MIPI_CTRL0_HIGH_ALIGN BIT(27)
#define RK3588_MIPI_CTRL0_WRDDR(type) ((type) << 5)
#define RK3588_MIPI_CTRL0_CROP_EN BIT(4)
#define RK3588_MIPI_CTRL0_PARSE(type) ((type) << 1)
#define RK3588_MIPI_CTRL_CAP_EN BIT(0)
#define RKCIF_MIPI_CTRL0_DT_ID(id) ((id) << 10)
#define RKCIF_MIPI_CTRL0_VC_ID(id) ((id) << 8)
#define RKCIF_MIPI_CTRL0_CAP_EN BIT(0)
@ -375,11 +383,8 @@ static u32
rkcif_rk3568_mipi_ctrl0(struct rkcif_stream *stream,
const struct rkcif_output_fmt *active_out_fmt)
{
u32 ctrl0 = 0;
ctrl0 |= RKCIF_MIPI_CTRL0_DT_ID(active_out_fmt->mipi.dt);
ctrl0 |= RKCIF_MIPI_CTRL0_CAP_EN;
ctrl0 |= RK3568_MIPI_CTRL0_CROP_EN;
u32 ctrl0 = RKCIF_MIPI_CTRL0_DT_ID(active_out_fmt->mipi.dt) |
RKCIF_MIPI_CTRL0_CAP_EN | RK3568_MIPI_CTRL0_CROP_EN;
if (active_out_fmt->mipi.compact)
ctrl0 |= RK3568_MIPI_CTRL0_COMPACT_EN;
@ -481,6 +486,132 @@ const struct rkcif_mipi_match_data rkcif_rk3568_vicap_mipi_match_data = {
},
};
static u32
rkcif_rk3588_mipi_ctrl0(struct rkcif_stream *stream,
const struct rkcif_output_fmt *active_out_fmt)
{
u32 ctrl0 = 0;
ctrl0 |= RK3588_MIPI_CTRL0_DMA_EN;
ctrl0 |= RKCIF_MIPI_CTRL0_DT_ID(active_out_fmt->mipi.dt);
ctrl0 |= RK3588_MIPI_CTRL0_CROP_EN;
ctrl0 |= RKCIF_MIPI_CTRL0_CAP_EN;
switch (active_out_fmt->mipi.type) {
case RKCIF_MIPI_TYPE_RAW8:
break;
case RKCIF_MIPI_TYPE_RAW10:
ctrl0 |= RK3588_MIPI_CTRL0_PARSE(0x1);
if (!active_out_fmt->mipi.compact)
ctrl0 |= RK3588_MIPI_CTRL0_WRDDR(0x1);
break;
case RKCIF_MIPI_TYPE_RAW12:
ctrl0 |= RK3588_MIPI_CTRL0_PARSE(0x2);
if (!active_out_fmt->mipi.compact)
ctrl0 |= RK3588_MIPI_CTRL0_WRDDR(0x1);
break;
case RKCIF_MIPI_TYPE_RGB888:
break;
case RKCIF_MIPI_TYPE_YUV422SP:
ctrl0 |= RK3588_MIPI_CTRL0_WRDDR(0x4);
break;
case RKCIF_MIPI_TYPE_YUV420SP:
ctrl0 |= RK3588_MIPI_CTRL0_WRDDR(0x5);
break;
case RKCIF_MIPI_TYPE_YUV400:
ctrl0 |= RK3588_MIPI_CTRL0_WRDDR(0x3);
break;
default:
break;
}
return ctrl0;
}
const struct rkcif_mipi_match_data rkcif_rk3588_vicap_mipi_match_data = {
.mipi_num = 6,
.mipi_ctrl0 = rkcif_rk3588_mipi_ctrl0,
.regs = {
[RKCIF_MIPI_CTRL] = 0x20,
[RKCIF_MIPI_INTEN] = 0x74,
[RKCIF_MIPI_INTSTAT] = 0x78,
},
.regs_id = {
[RKCIF_ID0] = {
[RKCIF_MIPI_CTRL0] = 0x00,
[RKCIF_MIPI_CTRL1] = 0x04,
[RKCIF_MIPI_FRAME0_ADDR_Y] = 0x24,
[RKCIF_MIPI_FRAME0_ADDR_UV] = 0x2c,
[RKCIF_MIPI_FRAME0_VLW_Y] = 0x34,
[RKCIF_MIPI_FRAME0_VLW_UV] = RKCIF_REGISTER_NOTSUPPORTED,
[RKCIF_MIPI_FRAME1_ADDR_Y] = 0x28,
[RKCIF_MIPI_FRAME1_ADDR_UV] = 0x30,
[RKCIF_MIPI_FRAME1_VLW_Y] = RKCIF_REGISTER_NOTSUPPORTED,
[RKCIF_MIPI_FRAME1_VLW_UV] = RKCIF_REGISTER_NOTSUPPORTED,
[RKCIF_MIPI_CROP_START] = 0x8c,
},
[RKCIF_ID1] = {
[RKCIF_MIPI_CTRL0] = 0x08,
[RKCIF_MIPI_CTRL1] = 0x0c,
[RKCIF_MIPI_FRAME0_ADDR_Y] = 0x38,
[RKCIF_MIPI_FRAME0_ADDR_UV] = 0x40,
[RKCIF_MIPI_FRAME0_VLW_Y] = 0x48,
[RKCIF_MIPI_FRAME0_VLW_UV] = RKCIF_REGISTER_NOTSUPPORTED,
[RKCIF_MIPI_FRAME1_ADDR_Y] = 0x3c,
[RKCIF_MIPI_FRAME1_ADDR_UV] = 0x44,
[RKCIF_MIPI_FRAME1_VLW_Y] = RKCIF_REGISTER_NOTSUPPORTED,
[RKCIF_MIPI_FRAME1_VLW_UV] = RKCIF_REGISTER_NOTSUPPORTED,
[RKCIF_MIPI_CROP_START] = 0x90,
},
[RKCIF_ID2] = {
[RKCIF_MIPI_CTRL0] = 0x10,
[RKCIF_MIPI_CTRL1] = 0x14,
[RKCIF_MIPI_FRAME0_ADDR_Y] = 0x4c,
[RKCIF_MIPI_FRAME0_ADDR_UV] = 0x54,
[RKCIF_MIPI_FRAME0_VLW_Y] = 0x5c,
[RKCIF_MIPI_FRAME0_VLW_UV] = RKCIF_REGISTER_NOTSUPPORTED,
[RKCIF_MIPI_FRAME1_ADDR_Y] = 0x50,
[RKCIF_MIPI_FRAME1_ADDR_UV] = 0x58,
[RKCIF_MIPI_FRAME1_VLW_Y] = RKCIF_REGISTER_NOTSUPPORTED,
[RKCIF_MIPI_FRAME1_VLW_UV] = RKCIF_REGISTER_NOTSUPPORTED,
[RKCIF_MIPI_CROP_START] = 0x94,
},
[RKCIF_ID3] = {
[RKCIF_MIPI_CTRL0] = 0x18,
[RKCIF_MIPI_CTRL1] = 0x1c,
[RKCIF_MIPI_FRAME0_ADDR_Y] = 0x60,
[RKCIF_MIPI_FRAME0_ADDR_UV] = 0x68,
[RKCIF_MIPI_FRAME0_VLW_Y] = 0x70,
[RKCIF_MIPI_FRAME0_VLW_UV] = RKCIF_REGISTER_NOTSUPPORTED,
[RKCIF_MIPI_FRAME1_ADDR_Y] = 0x64,
[RKCIF_MIPI_FRAME1_ADDR_UV] = 0x6c,
[RKCIF_MIPI_FRAME1_VLW_Y] = RKCIF_REGISTER_NOTSUPPORTED,
[RKCIF_MIPI_FRAME1_VLW_UV] = RKCIF_REGISTER_NOTSUPPORTED,
[RKCIF_MIPI_CROP_START] = 0x98,
},
},
.blocks = {
{
.offset = 0x100,
},
{
.offset = 0x200,
},
{
.offset = 0x300,
},
{
.offset = 0x400,
},
{
.offset = 0x500,
},
{
.offset = 0x600,
},
},
};
static inline unsigned int rkcif_mipi_get_reg(struct rkcif_interface *interface,
unsigned int index)
{
@ -631,6 +762,13 @@ static int rkcif_mipi_start_streaming(struct rkcif_stream *stream)
rkcif_mipi_stream_write(stream, RKCIF_MIPI_CTRL1, ctrl1);
rkcif_mipi_stream_write(stream, RKCIF_MIPI_CTRL0, ctrl0);
/*
* TODO: This bit has a different meaning on the RK3568, but it is
* set there by default anyway. While correct, this is not exactly
* nice and shall be reworked during the next refactoring.
*/
rkcif_mipi_write(interface, RKCIF_MIPI_CTRL, RK3588_MIPI_CTRL_CAP_EN);
ret = 0;
out:

View File

@ -13,6 +13,7 @@
#include "rkcif-common.h"
extern const struct rkcif_mipi_match_data rkcif_rk3568_vicap_mipi_match_data;
extern const struct rkcif_mipi_match_data rkcif_rk3588_vicap_mipi_match_data;
int rkcif_mipi_register(struct rkcif_device *rkcif);

View File

@ -27,7 +27,7 @@
#include "rkcif-regs.h"
#define RKCIF_DRIVER_NAME "rockchip-cif"
#define RKCIF_CLK_MAX 4
#define RKCIF_CLK_MAX 5
enum rkcif_format_type {
RKCIF_FMT_TYPE_INVALID,

View File

@ -53,6 +53,20 @@ static const struct rkcif_match_data rk3568_vicap_match_data = {
.mipi = &rkcif_rk3568_vicap_mipi_match_data,
};
static const char *const rk3588_vicap_clks[] = {
"aclk",
"hclk",
"dclk",
"iclk",
"iclk1",
};
static const struct rkcif_match_data rk3588_vicap_match_data = {
.clks = rk3588_vicap_clks,
.clks_num = ARRAY_SIZE(rk3588_vicap_clks),
.mipi = &rkcif_rk3588_vicap_mipi_match_data,
};
static const struct of_device_id rkcif_plat_of_match[] = {
{
.compatible = "rockchip,px30-vip",
@ -62,6 +76,10 @@ static const struct of_device_id rkcif_plat_of_match[] = {
.compatible = "rockchip,rk3568-vicap",
.data = &rk3568_vicap_match_data,
},
{
.compatible = "rockchip,rk3588-vicap",
.data = &rk3588_vicap_match_data,
},
{}
};
MODULE_DEVICE_TABLE(of, rkcif_plat_of_match);