Add support for the Rockchip RK3568 video capture (VICAP) block. Signed-off-by: Michael Riesch <michael.riesch@xxxxxxxxxxxxxx> --- drivers/media/platform/rockchip/cif/cif-capture.c | 6 + drivers/media/platform/rockchip/cif/cif-dev.c | 247 ++++++++++++++++++++++ drivers/media/platform/rockchip/cif/cif-regs.h | 9 + 3 files changed, 262 insertions(+) diff --git a/drivers/media/platform/rockchip/cif/cif-capture.c b/drivers/media/platform/rockchip/cif/cif-capture.c index dd5c45f28cdd..d0e8f3b49d38 100644 --- a/drivers/media/platform/rockchip/cif/cif-capture.c +++ b/drivers/media/platform/rockchip/cif/cif-capture.c @@ -340,6 +340,7 @@ static int cif_stream_start(struct cif_stream *stream) u32 val, fmt_type, xfer_mode = 0; struct cif_device *cif_dev = stream->cifdev; struct cif_remote *remote_info = &cif_dev->remote; + struct v4l2_mbus_config_parallel *parallel; int ret; u32 input_mode; @@ -351,6 +352,11 @@ static int cif_stream_start(struct cif_stream *stream) CIF_FORMAT_INPUT_MODE_NTSC : CIF_FORMAT_INPUT_MODE_PAL; + parallel = &cif_dev->vep.bus.parallel; + if ((parallel->bus_width == 16) && + (parallel->flags & V4L2_MBUS_PCLK_SAMPLE_DUALEDGE)) + xfer_mode |= CIF_FORMAT_BT1120_CLOCK_DOUBLE_EDGES; + val = input_mode | stream->cif_fmt_out->fmt_val | stream->cif_fmt_in->dvp_fmt_val | xfer_mode; cif_write(cif_dev, CIF_FOR, val); diff --git a/drivers/media/platform/rockchip/cif/cif-dev.c b/drivers/media/platform/rockchip/cif/cif-dev.c index 929ea39dd832..3b895b496c45 100644 --- a/drivers/media/platform/rockchip/cif/cif-dev.c +++ b/drivers/media/platform/rockchip/cif/cif-dev.c @@ -302,11 +302,258 @@ static const struct cif_match_data px30_cif_match_data = { }, }; +static const struct cif_input_fmt rk3568_in_fmts[] = { + { + .mbus_code = MEDIA_BUS_FMT_YUYV8_2X8, + .dvp_fmt_val = CIF_FORMAT_YUV_INPUT_422 | + CIF_FORMAT_YUV_INPUT_ORDER_YUYV, + .fmt_type = CIF_FMT_TYPE_YUV, + .field = V4L2_FIELD_NONE, + }, { + .mbus_code = MEDIA_BUS_FMT_YUYV8_2X8, + .dvp_fmt_val = CIF_FORMAT_YUV_INPUT_422 | + CIF_FORMAT_YUV_INPUT_ORDER_YUYV, + .fmt_type = CIF_FMT_TYPE_YUV, + .field = V4L2_FIELD_INTERLACED, + }, { + .mbus_code = MEDIA_BUS_FMT_YVYU8_2X8, + .dvp_fmt_val = CIF_FORMAT_YUV_INPUT_422 | + CIF_FORMAT_YUV_INPUT_ORDER_YVYU, + .fmt_type = CIF_FMT_TYPE_YUV, + .field = V4L2_FIELD_NONE, + }, { + .mbus_code = MEDIA_BUS_FMT_YVYU8_2X8, + .dvp_fmt_val = CIF_FORMAT_YUV_INPUT_422 | + CIF_FORMAT_YUV_INPUT_ORDER_YVYU, + .fmt_type = CIF_FMT_TYPE_YUV, + .field = V4L2_FIELD_INTERLACED, + }, { + .mbus_code = MEDIA_BUS_FMT_UYVY8_2X8, + .dvp_fmt_val = CIF_FORMAT_YUV_INPUT_422 | + CIF_FORMAT_YUV_INPUT_ORDER_UYVY, + .fmt_type = CIF_FMT_TYPE_YUV, + .field = V4L2_FIELD_NONE, + }, { + .mbus_code = MEDIA_BUS_FMT_UYVY8_2X8, + .dvp_fmt_val = CIF_FORMAT_YUV_INPUT_422 | + CIF_FORMAT_YUV_INPUT_ORDER_UYVY, + .fmt_type = CIF_FMT_TYPE_YUV, + .field = V4L2_FIELD_INTERLACED, + }, { + .mbus_code = MEDIA_BUS_FMT_VYUY8_2X8, + .dvp_fmt_val = CIF_FORMAT_YUV_INPUT_422 | + CIF_FORMAT_YUV_INPUT_ORDER_VYUY, + .fmt_type = CIF_FMT_TYPE_YUV, + .field = V4L2_FIELD_NONE, + }, { + .mbus_code = MEDIA_BUS_FMT_VYUY8_2X8, + .dvp_fmt_val = CIF_FORMAT_YUV_INPUT_422 | + CIF_FORMAT_YUV_INPUT_ORDER_VYUY, + .fmt_type = CIF_FMT_TYPE_YUV, + .field = V4L2_FIELD_INTERLACED, + }, { + .mbus_code = MEDIA_BUS_FMT_YUYV8_1X16, + .dvp_fmt_val = CIF_FORMAT_YUV_INPUT_422 | + CIF_FORMAT_YUV_INPUT_ORDER_YUYV | + CIF_FORMAT_INPUT_MODE_BT1120 | + CIF_FORMAT_BT1120_TRANSMIT_PROGRESS, + .field = V4L2_FIELD_NONE, + }, { + .mbus_code = MEDIA_BUS_FMT_YUYV8_1X16, + .dvp_fmt_val = CIF_FORMAT_YUV_INPUT_422 | + CIF_FORMAT_YUV_INPUT_ORDER_YUYV | + CIF_FORMAT_INPUT_MODE_BT1120, + .field = V4L2_FIELD_INTERLACED, + }, { + .mbus_code = MEDIA_BUS_FMT_YVYU8_1X16, + .dvp_fmt_val = CIF_FORMAT_YUV_INPUT_422 | + CIF_FORMAT_YUV_INPUT_ORDER_YVYU | + CIF_FORMAT_INPUT_MODE_BT1120 | + CIF_FORMAT_BT1120_TRANSMIT_PROGRESS, + .field = V4L2_FIELD_NONE, + }, { + .mbus_code = MEDIA_BUS_FMT_YVYU8_1X16, + .dvp_fmt_val = CIF_FORMAT_YUV_INPUT_422 | + CIF_FORMAT_YUV_INPUT_ORDER_YVYU | + CIF_FORMAT_INPUT_MODE_BT1120, + .field = V4L2_FIELD_INTERLACED, + }, { + .mbus_code = MEDIA_BUS_FMT_UYVY8_1X16, + .dvp_fmt_val = CIF_FORMAT_YUV_INPUT_422 | + CIF_FORMAT_YUV_INPUT_ORDER_YUYV | + CIF_FORMAT_INPUT_MODE_BT1120 | + CIF_FORMAT_BT1120_YC_SWAP | + CIF_FORMAT_BT1120_TRANSMIT_PROGRESS, + .field = V4L2_FIELD_NONE, + }, { + .mbus_code = MEDIA_BUS_FMT_UYVY8_1X16, + .dvp_fmt_val = CIF_FORMAT_YUV_INPUT_422 | + CIF_FORMAT_YUV_INPUT_ORDER_YUYV | + CIF_FORMAT_BT1120_YC_SWAP | + CIF_FORMAT_INPUT_MODE_BT1120, + .field = V4L2_FIELD_INTERLACED, + }, { + .mbus_code = MEDIA_BUS_FMT_VYUY8_1X16, + .dvp_fmt_val = CIF_FORMAT_YUV_INPUT_422 | + CIF_FORMAT_YUV_INPUT_ORDER_YVYU | + CIF_FORMAT_INPUT_MODE_BT1120 | + CIF_FORMAT_BT1120_YC_SWAP | + CIF_FORMAT_BT1120_TRANSMIT_PROGRESS, + .field = V4L2_FIELD_NONE, + }, { + .mbus_code = MEDIA_BUS_FMT_VYUY8_1X16, + .dvp_fmt_val = CIF_FORMAT_YUV_INPUT_422 | + CIF_FORMAT_YUV_INPUT_ORDER_YVYU | + CIF_FORMAT_BT1120_YC_SWAP | + CIF_FORMAT_INPUT_MODE_BT1120, + .field = V4L2_FIELD_INTERLACED, + }, { + .mbus_code = MEDIA_BUS_FMT_SBGGR8_1X8, + .dvp_fmt_val = CIF_FORMAT_INPUT_MODE_RAW | + CIF_FORMAT_RAW_DATA_WIDTH_8, + .fmt_type = CIF_FMT_TYPE_RAW, + .field = V4L2_FIELD_NONE, + }, { + .mbus_code = MEDIA_BUS_FMT_SGBRG8_1X8, + .dvp_fmt_val = CIF_FORMAT_INPUT_MODE_RAW | + CIF_FORMAT_RAW_DATA_WIDTH_8, + .fmt_type = CIF_FMT_TYPE_RAW, + .field = V4L2_FIELD_NONE, + }, { + .mbus_code = MEDIA_BUS_FMT_SGRBG8_1X8, + .dvp_fmt_val = CIF_FORMAT_INPUT_MODE_RAW | + CIF_FORMAT_RAW_DATA_WIDTH_8, + .fmt_type = CIF_FMT_TYPE_RAW, + .field = V4L2_FIELD_NONE, + }, { + .mbus_code = MEDIA_BUS_FMT_SRGGB8_1X8, + .dvp_fmt_val = CIF_FORMAT_INPUT_MODE_RAW | + CIF_FORMAT_RAW_DATA_WIDTH_8, + .fmt_type = CIF_FMT_TYPE_RAW, + .field = V4L2_FIELD_NONE, + }, { + .mbus_code = MEDIA_BUS_FMT_SBGGR10_1X10, + .dvp_fmt_val = CIF_FORMAT_INPUT_MODE_RAW | + CIF_FORMAT_RAW_DATA_WIDTH_10, + .fmt_type = CIF_FMT_TYPE_RAW, + .field = V4L2_FIELD_NONE, + }, { + .mbus_code = MEDIA_BUS_FMT_SGBRG10_1X10, + .dvp_fmt_val = CIF_FORMAT_INPUT_MODE_RAW | + CIF_FORMAT_RAW_DATA_WIDTH_10, + .fmt_type = CIF_FMT_TYPE_RAW, + .field = V4L2_FIELD_NONE, + }, { + .mbus_code = MEDIA_BUS_FMT_SGRBG10_1X10, + .dvp_fmt_val = CIF_FORMAT_INPUT_MODE_RAW | + CIF_FORMAT_RAW_DATA_WIDTH_10, + .fmt_type = CIF_FMT_TYPE_RAW, + .field = V4L2_FIELD_NONE, + }, { + .mbus_code = MEDIA_BUS_FMT_SRGGB10_1X10, + .dvp_fmt_val = CIF_FORMAT_INPUT_MODE_RAW | + CIF_FORMAT_RAW_DATA_WIDTH_10, + .fmt_type = CIF_FMT_TYPE_RAW, + .field = V4L2_FIELD_NONE, + }, { + .mbus_code = MEDIA_BUS_FMT_SBGGR12_1X12, + .dvp_fmt_val = CIF_FORMAT_INPUT_MODE_RAW | + CIF_FORMAT_RAW_DATA_WIDTH_12, + .fmt_type = CIF_FMT_TYPE_RAW, + .field = V4L2_FIELD_NONE, + }, { + .mbus_code = MEDIA_BUS_FMT_SGBRG12_1X12, + .dvp_fmt_val = CIF_FORMAT_INPUT_MODE_RAW | + CIF_FORMAT_RAW_DATA_WIDTH_12, + .fmt_type = CIF_FMT_TYPE_RAW, + .field = V4L2_FIELD_NONE, + }, { + .mbus_code = MEDIA_BUS_FMT_SGRBG12_1X12, + .dvp_fmt_val = CIF_FORMAT_INPUT_MODE_RAW | + CIF_FORMAT_RAW_DATA_WIDTH_12, + .fmt_type = CIF_FMT_TYPE_RAW, + .field = V4L2_FIELD_NONE, + }, { + .mbus_code = MEDIA_BUS_FMT_SRGGB12_1X12, + .dvp_fmt_val = CIF_FORMAT_INPUT_MODE_RAW | + CIF_FORMAT_RAW_DATA_WIDTH_12, + .fmt_type = CIF_FMT_TYPE_RAW, + .field = V4L2_FIELD_NONE, + }, { + .mbus_code = MEDIA_BUS_FMT_RGB888_1X24, + .field = V4L2_FIELD_NONE, + }, { + .mbus_code = MEDIA_BUS_FMT_Y8_1X8, + .dvp_fmt_val = CIF_FORMAT_INPUT_MODE_RAW | + CIF_FORMAT_RAW_DATA_WIDTH_8, + .fmt_type = CIF_FMT_TYPE_RAW, + .field = V4L2_FIELD_NONE, + }, { + .mbus_code = MEDIA_BUS_FMT_Y10_1X10, + .dvp_fmt_val = CIF_FORMAT_INPUT_MODE_RAW | + CIF_FORMAT_RAW_DATA_WIDTH_10, + .fmt_type = CIF_FMT_TYPE_RAW, + .field = V4L2_FIELD_NONE, + }, { + .mbus_code = MEDIA_BUS_FMT_Y12_1X12, + .dvp_fmt_val = CIF_FORMAT_INPUT_MODE_RAW | + CIF_FORMAT_RAW_DATA_WIDTH_12, + .fmt_type = CIF_FMT_TYPE_RAW, + .field = V4L2_FIELD_NONE, + }, +}; + +static struct clk_bulk_data rk3568_cif_clks[] = { + { .id = "aclk", }, + { .id = "hclk", }, + { .id = "dclk", }, + { .id = "iclk", }, +}; + +static void rk3568_grf_dvp_setup(struct cif_device *cif_dev) +{ + u32 con1 = RK3568_GRF_WRITE_ENABLE(RK3568_GRF_VI_CON1_CIF_DATAPATH); + + if (cif_dev->vep.bus.parallel.flags & V4L2_MBUS_PCLK_SAMPLE_DUALEDGE) + con1 |= RK3568_GRF_VI_CON1_CIF_DATAPATH; + + regmap_write(cif_dev->grf, RK3568_GRF_VI_CON1, con1); +} + +static const struct cif_match_data rk3568_cif_match_data = { + .clks = rk3568_cif_clks, + .clks_num = ARRAY_SIZE(rk3568_cif_clks), + .grf_dvp_setup = rk3568_grf_dvp_setup, + .in_fmts = rk3568_in_fmts, + .in_fmts_num = ARRAY_SIZE(rk3568_in_fmts), + .has_scaler = false, + .regs = { + [CIF_CTRL] = 0x00, + [CIF_INTEN] = 0x04, + [CIF_INTSTAT] = 0x08, + [CIF_FOR] = 0x0c, + [CIF_LINE_NUM_ADDR] = 0x2c, + [CIF_FRM0_ADDR_Y] = 0x14, + [CIF_FRM0_ADDR_UV] = 0x18, + [CIF_FRM1_ADDR_Y] = 0x1c, + [CIF_FRM1_ADDR_UV] = 0x20, + [CIF_VIR_LINE_WIDTH] = 0x24, + [CIF_SET_SIZE] = 0x28, + [CIF_FRAME_STATUS] = 0x3c, + [CIF_LAST_LINE] = 0x44, + [CIF_LAST_PIX] = 0x48, + }, +}; + static const struct of_device_id cif_plat_of_match[] = { { .compatible = "rockchip,px30-vip", .data = &px30_cif_match_data, }, + { + .compatible = "rockchip,rk3568-vicap", + .data = &rk3568_cif_match_data, + }, {}, }; diff --git a/drivers/media/platform/rockchip/cif/cif-regs.h b/drivers/media/platform/rockchip/cif/cif-regs.h index 2ce756fde204..261bc71240f2 100644 --- a/drivers/media/platform/rockchip/cif/cif-regs.h +++ b/drivers/media/platform/rockchip/cif/cif-regs.h @@ -117,4 +117,13 @@ enum cif_register { #define CIF_CROP_Y_SHIFT 16 #define CIF_CROP_X_SHIFT 0 +/* GRF register offsets */ +#define RK3568_GRF_VI_CON0 0x340 +#define RK3568_GRF_VI_CON1 0x344 +#define RK3568_GRF_VI_STATUS0 0x348 + +#define RK3568_GRF_VI_CON1_CIF_DATAPATH BIT(9) + +#define RK3568_GRF_WRITE_ENABLE(x) ((x) << 16) + #endif -- 2.30.2