From 02083a1e00ae294001faf81ef43f9edfd3952361 Mon Sep 17 00:00:00 2001 From: Neil Armstrong Date: Thu, 17 Apr 2025 16:59:05 +0200 Subject: [PATCH 01/16] media: platform: qcom/iris: add support for vpu33 The IRIS acceleration found in the SM8650 platforms uses the vpu33 hardware version, and requires a slighly different reset and power off sequences in order to properly get out of runtime suspend. Tested-by: Bryan O'Donoghue # x1e Dell Signed-off-by: Neil Armstrong Reviewed-by: Vikash Garodia Signed-off-by: Bryan O'Donoghue Signed-off-by: Hans Verkuil --- drivers/media/platform/qcom/iris/iris_vpu3x.c | 160 +++++++++++++++++- .../platform/qcom/iris/iris_vpu_common.h | 1 + 2 files changed, 157 insertions(+), 4 deletions(-) diff --git a/drivers/media/platform/qcom/iris/iris_vpu3x.c b/drivers/media/platform/qcom/iris/iris_vpu3x.c index 13dab61427b8..9b7c9a1495ee 100644 --- a/drivers/media/platform/qcom/iris/iris_vpu3x.c +++ b/drivers/media/platform/qcom/iris/iris_vpu3x.c @@ -4,20 +4,39 @@ */ #include +#include #include "iris_instance.h" #include "iris_vpu_common.h" #include "iris_vpu_register_defines.h" +#define WRAPPER_TZ_BASE_OFFS 0x000C0000 +#define AON_BASE_OFFS 0x000E0000 #define AON_MVP_NOC_RESET 0x0001F000 +#define WRAPPER_DEBUG_BRIDGE_LPI_CONTROL (WRAPPER_BASE_OFFS + 0x54) +#define WRAPPER_DEBUG_BRIDGE_LPI_STATUS (WRAPPER_BASE_OFFS + 0x58) +#define WRAPPER_IRIS_CPU_NOC_LPI_CONTROL (WRAPPER_BASE_OFFS + 0x5C) +#define REQ_POWER_DOWN_PREP BIT(0) +#define WRAPPER_IRIS_CPU_NOC_LPI_STATUS (WRAPPER_BASE_OFFS + 0x60) #define WRAPPER_CORE_CLOCK_CONFIG (WRAPPER_BASE_OFFS + 0x88) #define CORE_CLK_RUN 0x0 +#define WRAPPER_TZ_CTL_AXI_CLOCK_CONFIG (WRAPPER_TZ_BASE_OFFS + 0x14) +#define CTL_AXI_CLK_HALT BIT(0) +#define CTL_CLK_HALT BIT(1) + +#define WRAPPER_TZ_QNS4PDXFIFO_RESET (WRAPPER_TZ_BASE_OFFS + 0x18) +#define RESET_HIGH BIT(0) + #define CPU_CS_AHB_BRIDGE_SYNC_RESET (CPU_CS_BASE_OFFS + 0x160) #define CORE_BRIDGE_SW_RESET BIT(0) #define CORE_BRIDGE_HW_RESET_DISABLE BIT(1) +#define CPU_CS_X2RPMH (CPU_CS_BASE_OFFS + 0x168) +#define MSK_SIGNAL_FROM_TENSILICA BIT(0) +#define MSK_CORE_POWER_ON BIT(1) + #define AON_WRAPPER_MVP_NOC_RESET_REQ (AON_MVP_NOC_RESET + 0x000) #define VIDEO_NOC_RESET_REQ (BIT(0) | BIT(1)) @@ -25,7 +44,16 @@ #define VCODEC_SS_IDLE_STATUSN (VCODEC_BASE_OFFS + 0x70) -static bool iris_vpu3_hw_power_collapsed(struct iris_core *core) +#define AON_WRAPPER_MVP_NOC_LPI_CONTROL (AON_BASE_OFFS) +#define AON_WRAPPER_MVP_NOC_LPI_STATUS (AON_BASE_OFFS + 0x4) + +#define AON_WRAPPER_MVP_NOC_CORE_SW_RESET (AON_BASE_OFFS + 0x18) +#define SW_RESET BIT(0) +#define AON_WRAPPER_MVP_NOC_CORE_CLK_CONTROL (AON_BASE_OFFS + 0x20) +#define NOC_HALT BIT(0) +#define AON_WRAPPER_SPARE (AON_BASE_OFFS + 0x28) + +static bool iris_vpu3x_hw_power_collapsed(struct iris_core *core) { u32 value, pwr_status; @@ -40,7 +68,7 @@ static void iris_vpu3_power_off_hardware(struct iris_core *core) u32 reg_val = 0, value, i; int ret; - if (iris_vpu3_hw_power_collapsed(core)) + if (iris_vpu3x_hw_power_collapsed(core)) goto disable_power; dev_err(core->dev, "video hw is power on\n"); @@ -79,7 +107,125 @@ disable_power: iris_vpu_power_off_hw(core); } -static u64 iris_vpu3_calculate_frequency(struct iris_inst *inst, size_t data_size) +static void iris_vpu33_power_off_hardware(struct iris_core *core) +{ + u32 reg_val = 0, value, i; + int ret; + + if (iris_vpu3x_hw_power_collapsed(core)) + goto disable_power; + + dev_err(core->dev, "video hw is power on\n"); + + value = readl(core->reg_base + WRAPPER_CORE_CLOCK_CONFIG); + if (value) + writel(CORE_CLK_RUN, core->reg_base + WRAPPER_CORE_CLOCK_CONFIG); + + for (i = 0; i < core->iris_platform_data->num_vpp_pipe; i++) { + ret = readl_poll_timeout(core->reg_base + VCODEC_SS_IDLE_STATUSN + 4 * i, + reg_val, reg_val & 0x400000, 2000, 20000); + if (ret) + goto disable_power; + } + + ret = readl_poll_timeout(core->reg_base + AON_WRAPPER_MVP_NOC_LPI_STATUS, + reg_val, reg_val & BIT(0), 200, 2000); + if (ret) + goto disable_power; + + /* set MNoC to low power, set PD_NOC_QREQ (bit 0) */ + writel(BIT(0), core->reg_base + AON_WRAPPER_MVP_NOC_LPI_CONTROL); + + writel(CORE_BRIDGE_SW_RESET | CORE_BRIDGE_HW_RESET_DISABLE, + core->reg_base + CPU_CS_AHB_BRIDGE_SYNC_RESET); + writel(CORE_BRIDGE_HW_RESET_DISABLE, core->reg_base + CPU_CS_AHB_BRIDGE_SYNC_RESET); + writel(0x0, core->reg_base + CPU_CS_AHB_BRIDGE_SYNC_RESET); + +disable_power: + iris_vpu_power_off_hw(core); +} + +static int iris_vpu33_power_off_controller(struct iris_core *core) +{ + u32 xo_rst_tbl_size = core->iris_platform_data->controller_rst_tbl_size; + u32 clk_rst_tbl_size = core->iris_platform_data->clk_rst_tbl_size; + u32 val = 0; + int ret; + + writel(MSK_SIGNAL_FROM_TENSILICA | MSK_CORE_POWER_ON, core->reg_base + CPU_CS_X2RPMH); + + writel(REQ_POWER_DOWN_PREP, core->reg_base + WRAPPER_IRIS_CPU_NOC_LPI_CONTROL); + + ret = readl_poll_timeout(core->reg_base + WRAPPER_IRIS_CPU_NOC_LPI_STATUS, + val, val & BIT(0), 200, 2000); + if (ret) + goto disable_power; + + writel(0x0, core->reg_base + WRAPPER_DEBUG_BRIDGE_LPI_CONTROL); + + ret = readl_poll_timeout(core->reg_base + WRAPPER_DEBUG_BRIDGE_LPI_STATUS, + val, val == 0, 200, 2000); + if (ret) + goto disable_power; + + writel(CTL_AXI_CLK_HALT | CTL_CLK_HALT, + core->reg_base + WRAPPER_TZ_CTL_AXI_CLOCK_CONFIG); + writel(RESET_HIGH, core->reg_base + WRAPPER_TZ_QNS4PDXFIFO_RESET); + writel(0x0, core->reg_base + WRAPPER_TZ_QNS4PDXFIFO_RESET); + writel(0x0, core->reg_base + WRAPPER_TZ_CTL_AXI_CLOCK_CONFIG); + + reset_control_bulk_reset(clk_rst_tbl_size, core->resets); + + /* Disable MVP NoC clock */ + val = readl(core->reg_base + AON_WRAPPER_MVP_NOC_CORE_CLK_CONTROL); + val |= NOC_HALT; + writel(val, core->reg_base + AON_WRAPPER_MVP_NOC_CORE_CLK_CONTROL); + + /* enable MVP NoC reset */ + val = readl(core->reg_base + AON_WRAPPER_MVP_NOC_CORE_SW_RESET); + val |= SW_RESET; + writel(val, core->reg_base + AON_WRAPPER_MVP_NOC_CORE_SW_RESET); + + /* poll AON spare register bit0 to become zero with 50ms timeout */ + ret = readl_poll_timeout(core->reg_base + AON_WRAPPER_SPARE, + val, (val & BIT(0)) == 0, 1000, 50000); + if (ret) + goto disable_power; + + /* enable bit(1) to avoid cvp noc xo reset */ + val = readl(core->reg_base + AON_WRAPPER_SPARE); + val |= BIT(1); + writel(val, core->reg_base + AON_WRAPPER_SPARE); + + reset_control_bulk_assert(xo_rst_tbl_size, core->controller_resets); + + /* De-assert MVP NoC reset */ + val = readl(core->reg_base + AON_WRAPPER_MVP_NOC_CORE_SW_RESET); + val &= ~SW_RESET; + writel(val, core->reg_base + AON_WRAPPER_MVP_NOC_CORE_SW_RESET); + + usleep_range(80, 100); + + reset_control_bulk_deassert(xo_rst_tbl_size, core->controller_resets); + + /* reset AON spare register */ + writel(0, core->reg_base + AON_WRAPPER_SPARE); + + /* Enable MVP NoC clock */ + val = readl(core->reg_base + AON_WRAPPER_MVP_NOC_CORE_CLK_CONTROL); + val &= ~NOC_HALT; + writel(val, core->reg_base + AON_WRAPPER_MVP_NOC_CORE_CLK_CONTROL); + + iris_disable_unprepare_clock(core, IRIS_CTRL_CLK); + +disable_power: + iris_disable_power_domains(core, core->pmdomain_tbl->pd_devs[IRIS_CTRL_POWER_DOMAIN]); + iris_disable_unprepare_clock(core, IRIS_AXI_CLK); + + return 0; +} + +static u64 iris_vpu3x_calculate_frequency(struct iris_inst *inst, size_t data_size) { struct platform_inst_caps *caps = inst->core->iris_platform_data->inst_caps; struct v4l2_format *inp_f = inst->fmt_src; @@ -119,5 +265,11 @@ static u64 iris_vpu3_calculate_frequency(struct iris_inst *inst, size_t data_siz const struct vpu_ops iris_vpu3_ops = { .power_off_hw = iris_vpu3_power_off_hardware, .power_off_controller = iris_vpu_power_off_controller, - .calc_freq = iris_vpu3_calculate_frequency, + .calc_freq = iris_vpu3x_calculate_frequency, +}; + +const struct vpu_ops iris_vpu33_ops = { + .power_off_hw = iris_vpu33_power_off_hardware, + .power_off_controller = iris_vpu33_power_off_controller, + .calc_freq = iris_vpu3x_calculate_frequency, }; diff --git a/drivers/media/platform/qcom/iris/iris_vpu_common.h b/drivers/media/platform/qcom/iris/iris_vpu_common.h index f8965661c602..93b7fa27be3b 100644 --- a/drivers/media/platform/qcom/iris/iris_vpu_common.h +++ b/drivers/media/platform/qcom/iris/iris_vpu_common.h @@ -10,6 +10,7 @@ struct iris_core; extern const struct vpu_ops iris_vpu2_ops; extern const struct vpu_ops iris_vpu3_ops; +extern const struct vpu_ops iris_vpu33_ops; struct vpu_ops { void (*power_off_hw)(struct iris_core *core); -- 2.51.0 From dc40021c13d412f48e11a5c4aeb9e0a997ff2b95 Mon Sep 17 00:00:00 2001 From: Neil Armstrong Date: Thu, 17 Apr 2025 16:59:06 +0200 Subject: [PATCH 02/16] media: platform: qcom/iris: rename platform_sm8550 to platform_gen2 In order to prepare for supporting the SM8650 SoC, move the iris_platform_sm8550.c file into iris_platform_gen2.c that will contain all the common HFI GEN2x structures. Reviewed-by: Bryan O'Donoghue Tested-by: Bryan O'Donoghue # x1e Dell Signed-off-by: Neil Armstrong Reviewed-by: Vikash Garodia Signed-off-by: Bryan O'Donoghue Signed-off-by: Hans Verkuil --- drivers/media/platform/qcom/iris/Makefile | 2 +- .../qcom/iris/{iris_platform_sm8550.c => iris_platform_gen2.c} | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename drivers/media/platform/qcom/iris/{iris_platform_sm8550.c => iris_platform_gen2.c} (100%) diff --git a/drivers/media/platform/qcom/iris/Makefile b/drivers/media/platform/qcom/iris/Makefile index 473aaf655448..e86d00ee6f15 100644 --- a/drivers/media/platform/qcom/iris/Makefile +++ b/drivers/media/platform/qcom/iris/Makefile @@ -10,7 +10,7 @@ qcom-iris-objs += \ iris_hfi_gen2_packet.o \ iris_hfi_gen2_response.o \ iris_hfi_queue.o \ - iris_platform_sm8550.o \ + iris_platform_gen2.o \ iris_power.o \ iris_probe.o \ iris_resources.o \ diff --git a/drivers/media/platform/qcom/iris/iris_platform_sm8550.c b/drivers/media/platform/qcom/iris/iris_platform_gen2.c similarity index 100% rename from drivers/media/platform/qcom/iris/iris_platform_sm8550.c rename to drivers/media/platform/qcom/iris/iris_platform_gen2.c -- 2.51.0 From cae67e94e46a057e3b3d092db04557acce48b82d Mon Sep 17 00:00:00 2001 From: Neil Armstrong Date: Thu, 17 Apr 2025 16:59:07 +0200 Subject: [PATCH 03/16] media: platform: qcom/iris: add sm8650 support Add support for the SM8650 platform by re-using the SM8550 definitions and using the vpu33 ops. Move the Sm8650 reset tables that differs in a per-SoC platform header, that will contain mode SoC specific data when more codecs are introduced. The SM8650/vpu33 requires more reset lines, but the H.264 decoder capabilities are identical. Tested-by: Bryan O'Donoghue # x1e Dell Reviewed-by: Bryan O'Donoghue Signed-off-by: Neil Armstrong Reviewed-by: Vikash Garodia Signed-off-by: Bryan O'Donoghue Signed-off-by: Hans Verkuil --- .../platform/qcom/iris/iris_platform_common.h | 1 + .../platform/qcom/iris/iris_platform_gen2.c | 62 +++++++++++++++++++ .../platform/qcom/iris/iris_platform_sm8650.h | 13 ++++ drivers/media/platform/qcom/iris/iris_probe.c | 4 ++ 4 files changed, 80 insertions(+) create mode 100644 drivers/media/platform/qcom/iris/iris_platform_sm8650.h diff --git a/drivers/media/platform/qcom/iris/iris_platform_common.h b/drivers/media/platform/qcom/iris/iris_platform_common.h index fdd40fd80178..6bc3a7975b04 100644 --- a/drivers/media/platform/qcom/iris/iris_platform_common.h +++ b/drivers/media/platform/qcom/iris/iris_platform_common.h @@ -35,6 +35,7 @@ enum pipe_type { extern struct iris_platform_data sm8250_data; extern struct iris_platform_data sm8550_data; +extern struct iris_platform_data sm8650_data; enum platform_clk_type { IRIS_AXI_CLK, diff --git a/drivers/media/platform/qcom/iris/iris_platform_gen2.c b/drivers/media/platform/qcom/iris/iris_platform_gen2.c index 35d278996c43..5ff82296ee8e 100644 --- a/drivers/media/platform/qcom/iris/iris_platform_gen2.c +++ b/drivers/media/platform/qcom/iris/iris_platform_gen2.c @@ -10,6 +10,8 @@ #include "iris_platform_common.h" #include "iris_vpu_common.h" +#include "iris_platform_sm8650.h" + #define VIDEO_ARCH_LX 1 static struct platform_inst_fw_cap inst_fw_cap_sm8550[] = { @@ -264,3 +266,63 @@ struct iris_platform_data sm8550_data = { .dec_op_int_buf_tbl = sm8550_dec_op_int_buf_tbl, .dec_op_int_buf_tbl_size = ARRAY_SIZE(sm8550_dec_op_int_buf_tbl), }; + +/* + * Shares most of SM8550 data except: + * - vpu_ops to iris_vpu33_ops + * - clk_rst_tbl to sm8650_clk_reset_table + * - controller_rst_tbl to sm8650_controller_reset_table + * - fwname to "qcom/vpu/vpu33_p4.mbn" + */ +struct iris_platform_data sm8650_data = { + .get_instance = iris_hfi_gen2_get_instance, + .init_hfi_command_ops = iris_hfi_gen2_command_ops_init, + .init_hfi_response_ops = iris_hfi_gen2_response_ops_init, + .vpu_ops = &iris_vpu33_ops, + .set_preset_registers = iris_set_sm8550_preset_registers, + .icc_tbl = sm8550_icc_table, + .icc_tbl_size = ARRAY_SIZE(sm8550_icc_table), + .clk_rst_tbl = sm8650_clk_reset_table, + .clk_rst_tbl_size = ARRAY_SIZE(sm8650_clk_reset_table), + .controller_rst_tbl = sm8650_controller_reset_table, + .controller_rst_tbl_size = ARRAY_SIZE(sm8650_controller_reset_table), + .bw_tbl_dec = sm8550_bw_table_dec, + .bw_tbl_dec_size = ARRAY_SIZE(sm8550_bw_table_dec), + .pmdomain_tbl = sm8550_pmdomain_table, + .pmdomain_tbl_size = ARRAY_SIZE(sm8550_pmdomain_table), + .opp_pd_tbl = sm8550_opp_pd_table, + .opp_pd_tbl_size = ARRAY_SIZE(sm8550_opp_pd_table), + .clk_tbl = sm8550_clk_table, + .clk_tbl_size = ARRAY_SIZE(sm8550_clk_table), + /* Upper bound of DMA address range */ + .dma_mask = 0xe0000000 - 1, + .fwname = "qcom/vpu/vpu33_p4.mbn", + .pas_id = IRIS_PAS_ID, + .inst_caps = &platform_inst_cap_sm8550, + .inst_fw_caps = inst_fw_cap_sm8550, + .inst_fw_caps_size = ARRAY_SIZE(inst_fw_cap_sm8550), + .tz_cp_config_data = &tz_cp_config_sm8550, + .core_arch = VIDEO_ARCH_LX, + .hw_response_timeout = HW_RESPONSE_TIMEOUT_VALUE, + .ubwc_config = &ubwc_config_sm8550, + .num_vpp_pipe = 4, + .max_session_count = 16, + .max_core_mbpf = ((8192 * 4352) / 256) * 2, + .input_config_params = + sm8550_vdec_input_config_params, + .input_config_params_size = + ARRAY_SIZE(sm8550_vdec_input_config_params), + .output_config_params = + sm8550_vdec_output_config_params, + .output_config_params_size = + ARRAY_SIZE(sm8550_vdec_output_config_params), + .dec_input_prop = sm8550_vdec_subscribe_input_properties, + .dec_input_prop_size = ARRAY_SIZE(sm8550_vdec_subscribe_input_properties), + .dec_output_prop = sm8550_vdec_subscribe_output_properties, + .dec_output_prop_size = ARRAY_SIZE(sm8550_vdec_subscribe_output_properties), + + .dec_ip_int_buf_tbl = sm8550_dec_ip_int_buf_tbl, + .dec_ip_int_buf_tbl_size = ARRAY_SIZE(sm8550_dec_ip_int_buf_tbl), + .dec_op_int_buf_tbl = sm8550_dec_op_int_buf_tbl, + .dec_op_int_buf_tbl_size = ARRAY_SIZE(sm8550_dec_op_int_buf_tbl), +}; diff --git a/drivers/media/platform/qcom/iris/iris_platform_sm8650.h b/drivers/media/platform/qcom/iris/iris_platform_sm8650.h new file mode 100644 index 000000000000..75e9d572e788 --- /dev/null +++ b/drivers/media/platform/qcom/iris/iris_platform_sm8650.h @@ -0,0 +1,13 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved. + */ + +#ifndef __IRIS_PLATFORM_SM8650_H__ +#define __IRIS_PLATFORM_SM8650_H__ + +static const char * const sm8650_clk_reset_table[] = { "bus", "core" }; + +static const char * const sm8650_controller_reset_table[] = { "xo" }; + +#endif diff --git a/drivers/media/platform/qcom/iris/iris_probe.c b/drivers/media/platform/qcom/iris/iris_probe.c index 4f8bce6e2002..7cd8650fbe9c 100644 --- a/drivers/media/platform/qcom/iris/iris_probe.c +++ b/drivers/media/platform/qcom/iris/iris_probe.c @@ -345,6 +345,10 @@ static const struct of_device_id iris_dt_match[] = { .data = &sm8250_data, }, #endif + { + .compatible = "qcom,sm8650-iris", + .data = &sm8650_data, + }, { }, }; MODULE_DEVICE_TABLE(of, iris_dt_match); -- 2.51.0 From 6aa5f5887df3b2eaca45ad263acb301540e52802 Mon Sep 17 00:00:00 2001 From: Vikash Garodia Date: Thu, 24 Apr 2025 14:20:45 +0530 Subject: [PATCH 04/16] dt-bindings: media: qcom,sm8550-iris: document QCS8300 IRIS accelerator Document the IRIS video decoder/encoder accelerator found in the QCS8300 platform. It belongs to same iris v3 family as that of SM8550 but is a downscaled version of SM8550. It has 2 frame processing hardware blocks while SM8550 has 4. Thereby QCS8300 have fewer capabilities than those of SM8550. Reviewed-by: Bryan O'Donoghue Signed-off-by: Vikash Garodia Acked-by: Krzysztof Kozlowski Signed-off-by: Bryan O'Donoghue Signed-off-by: Hans Verkuil --- Documentation/devicetree/bindings/media/qcom,sm8550-iris.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/media/qcom,sm8550-iris.yaml b/Documentation/devicetree/bindings/media/qcom,sm8550-iris.yaml index f567f84bd60d..c79bf2101812 100644 --- a/Documentation/devicetree/bindings/media/qcom,sm8550-iris.yaml +++ b/Documentation/devicetree/bindings/media/qcom,sm8550-iris.yaml @@ -22,6 +22,7 @@ properties: - qcom,sa8775p-iris - const: qcom,sm8550-iris - enum: + - qcom,qcs8300-iris - qcom,sm8550-iris - qcom,sm8650-iris -- 2.51.0 From 6490cf1653768a1d4cd9a717a8009785e50495e0 Mon Sep 17 00:00:00 2001 From: Vikash Garodia Date: Thu, 24 Apr 2025 14:20:46 +0530 Subject: [PATCH 05/16] media: iris: fix the order of compat strings Fix the order of compatible strings to make it in alpha numeric order. Reviewed-by: Bryan O'Donoghue Signed-off-by: Vikash Garodia Reviewed-by: Dikshita Agarwal Signed-off-by: Bryan O'Donoghue Signed-off-by: Hans Verkuil --- drivers/media/platform/qcom/iris/iris_probe.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/media/platform/qcom/iris/iris_probe.c b/drivers/media/platform/qcom/iris/iris_probe.c index 7cd8650fbe9c..fa3b9c9b1493 100644 --- a/drivers/media/platform/qcom/iris/iris_probe.c +++ b/drivers/media/platform/qcom/iris/iris_probe.c @@ -335,16 +335,16 @@ static const struct dev_pm_ops iris_pm_ops = { }; static const struct of_device_id iris_dt_match[] = { +#if (!IS_ENABLED(CONFIG_VIDEO_QCOM_VENUS)) + { + .compatible = "qcom,sm8250-venus", + .data = &sm8250_data, + }, +#endif { .compatible = "qcom,sm8550-iris", .data = &sm8550_data, }, -#if (!IS_ENABLED(CONFIG_VIDEO_QCOM_VENUS)) - { - .compatible = "qcom,sm8250-venus", - .data = &sm8250_data, - }, -#endif { .compatible = "qcom,sm8650-iris", .data = &sm8650_data, -- 2.51.0 From 146eadf3d1ef3b13d31e814ab213909c98c0427e Mon Sep 17 00:00:00 2001 From: Vikash Garodia Date: Thu, 24 Apr 2025 14:20:47 +0530 Subject: [PATCH 06/16] media: iris: add qcs8300 platform data Add platform data for QCS8300, which has different capabilities compared to SM8550. Introduce a QCS8300 header that defines these capabilities. Reviewed-by: Bryan O'Donoghue Signed-off-by: Vikash Garodia Reviewed-by: Dikshita Agarwal Signed-off-by: Bryan O'Donoghue Signed-off-by: Hans Verkuil --- .../platform/qcom/iris/iris_platform_common.h | 1 + .../platform/qcom/iris/iris_platform_gen2.c | 57 ++++++++ .../qcom/iris/iris_platform_qcs8300.h | 124 ++++++++++++++++++ drivers/media/platform/qcom/iris/iris_probe.c | 4 + 4 files changed, 186 insertions(+) create mode 100644 drivers/media/platform/qcom/iris/iris_platform_qcs8300.h diff --git a/drivers/media/platform/qcom/iris/iris_platform_common.h b/drivers/media/platform/qcom/iris/iris_platform_common.h index 6bc3a7975b04..ac76d9e1ef9c 100644 --- a/drivers/media/platform/qcom/iris/iris_platform_common.h +++ b/drivers/media/platform/qcom/iris/iris_platform_common.h @@ -33,6 +33,7 @@ enum pipe_type { PIPE_4 = 4, }; +extern struct iris_platform_data qcs8300_data; extern struct iris_platform_data sm8250_data; extern struct iris_platform_data sm8550_data; extern struct iris_platform_data sm8650_data; diff --git a/drivers/media/platform/qcom/iris/iris_platform_gen2.c b/drivers/media/platform/qcom/iris/iris_platform_gen2.c index 5ff82296ee8e..1e69ba15db0f 100644 --- a/drivers/media/platform/qcom/iris/iris_platform_gen2.c +++ b/drivers/media/platform/qcom/iris/iris_platform_gen2.c @@ -10,6 +10,7 @@ #include "iris_platform_common.h" #include "iris_vpu_common.h" +#include "iris_platform_qcs8300.h" #include "iris_platform_sm8650.h" #define VIDEO_ARCH_LX 1 @@ -326,3 +327,59 @@ struct iris_platform_data sm8650_data = { .dec_op_int_buf_tbl = sm8550_dec_op_int_buf_tbl, .dec_op_int_buf_tbl_size = ARRAY_SIZE(sm8550_dec_op_int_buf_tbl), }; + +/* + * Shares most of SM8550 data except: + * - inst_caps to platform_inst_cap_qcs8300 + * - inst_fw_caps to inst_fw_cap_qcs8300 + */ +struct iris_platform_data qcs8300_data = { + .get_instance = iris_hfi_gen2_get_instance, + .init_hfi_command_ops = iris_hfi_gen2_command_ops_init, + .init_hfi_response_ops = iris_hfi_gen2_response_ops_init, + .vpu_ops = &iris_vpu3_ops, + .set_preset_registers = iris_set_sm8550_preset_registers, + .icc_tbl = sm8550_icc_table, + .icc_tbl_size = ARRAY_SIZE(sm8550_icc_table), + .clk_rst_tbl = sm8550_clk_reset_table, + .clk_rst_tbl_size = ARRAY_SIZE(sm8550_clk_reset_table), + .bw_tbl_dec = sm8550_bw_table_dec, + .bw_tbl_dec_size = ARRAY_SIZE(sm8550_bw_table_dec), + .pmdomain_tbl = sm8550_pmdomain_table, + .pmdomain_tbl_size = ARRAY_SIZE(sm8550_pmdomain_table), + .opp_pd_tbl = sm8550_opp_pd_table, + .opp_pd_tbl_size = ARRAY_SIZE(sm8550_opp_pd_table), + .clk_tbl = sm8550_clk_table, + .clk_tbl_size = ARRAY_SIZE(sm8550_clk_table), + /* Upper bound of DMA address range */ + .dma_mask = 0xe0000000 - 1, + .fwname = "qcom/vpu/vpu30_p4_s6.mbn", + .pas_id = IRIS_PAS_ID, + .inst_caps = &platform_inst_cap_qcs8300, + .inst_fw_caps = inst_fw_cap_qcs8300, + .inst_fw_caps_size = ARRAY_SIZE(inst_fw_cap_qcs8300), + .tz_cp_config_data = &tz_cp_config_sm8550, + .core_arch = VIDEO_ARCH_LX, + .hw_response_timeout = HW_RESPONSE_TIMEOUT_VALUE, + .ubwc_config = &ubwc_config_sm8550, + .num_vpp_pipe = 2, + .max_session_count = 16, + .max_core_mbpf = ((4096 * 2176) / 256) * 4, + .input_config_params = + sm8550_vdec_input_config_params, + .input_config_params_size = + ARRAY_SIZE(sm8550_vdec_input_config_params), + .output_config_params = + sm8550_vdec_output_config_params, + .output_config_params_size = + ARRAY_SIZE(sm8550_vdec_output_config_params), + .dec_input_prop = sm8550_vdec_subscribe_input_properties, + .dec_input_prop_size = ARRAY_SIZE(sm8550_vdec_subscribe_input_properties), + .dec_output_prop = sm8550_vdec_subscribe_output_properties, + .dec_output_prop_size = ARRAY_SIZE(sm8550_vdec_subscribe_output_properties), + + .dec_ip_int_buf_tbl = sm8550_dec_ip_int_buf_tbl, + .dec_ip_int_buf_tbl_size = ARRAY_SIZE(sm8550_dec_ip_int_buf_tbl), + .dec_op_int_buf_tbl = sm8550_dec_op_int_buf_tbl, + .dec_op_int_buf_tbl_size = ARRAY_SIZE(sm8550_dec_op_int_buf_tbl), +}; diff --git a/drivers/media/platform/qcom/iris/iris_platform_qcs8300.h b/drivers/media/platform/qcom/iris/iris_platform_qcs8300.h new file mode 100644 index 000000000000..f82355d72fcf --- /dev/null +++ b/drivers/media/platform/qcom/iris/iris_platform_qcs8300.h @@ -0,0 +1,124 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2022-2025 Qualcomm Innovation Center, Inc. All rights reserved. + */ + +static struct platform_inst_fw_cap inst_fw_cap_qcs8300[] = { + { + .cap_id = PROFILE, + .min = V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE, + .max = V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_HIGH, + .step_or_mask = BIT(V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE) | + BIT(V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_HIGH) | + BIT(V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_BASELINE) | + BIT(V4L2_MPEG_VIDEO_H264_PROFILE_MAIN) | + BIT(V4L2_MPEG_VIDEO_H264_PROFILE_HIGH), + .value = V4L2_MPEG_VIDEO_H264_PROFILE_HIGH, + .hfi_id = HFI_PROP_PROFILE, + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU, + .set = iris_set_u32_enum, + }, + { + .cap_id = LEVEL, + .min = V4L2_MPEG_VIDEO_H264_LEVEL_1_0, + .max = V4L2_MPEG_VIDEO_H264_LEVEL_6_2, + .step_or_mask = BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1_0) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1B) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1_1) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1_2) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1_3) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_2_0) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_2_1) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_2_2) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_3_0) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_3_1) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_3_2) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_4_0) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_4_1) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_4_2) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_5_0) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_5_1) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_5_2) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_6_0) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_6_1) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_6_2), + .value = V4L2_MPEG_VIDEO_H264_LEVEL_6_1, + .hfi_id = HFI_PROP_LEVEL, + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU, + .set = iris_set_u32_enum, + }, + { + .cap_id = INPUT_BUF_HOST_MAX_COUNT, + .min = DEFAULT_MAX_HOST_BUF_COUNT, + .max = DEFAULT_MAX_HOST_BURST_BUF_COUNT, + .step_or_mask = 1, + .value = DEFAULT_MAX_HOST_BUF_COUNT, + .hfi_id = HFI_PROP_BUFFER_HOST_MAX_COUNT, + .flags = CAP_FLAG_INPUT_PORT, + .set = iris_set_u32, + }, + { + .cap_id = STAGE, + .min = STAGE_1, + .max = STAGE_2, + .step_or_mask = 1, + .value = STAGE_2, + .hfi_id = HFI_PROP_STAGE, + .set = iris_set_stage, + }, + { + .cap_id = PIPE, + .min = PIPE_1, + .max = PIPE_2, + .step_or_mask = 1, + .value = PIPE_2, + .hfi_id = HFI_PROP_PIPE, + .set = iris_set_pipe, + }, + { + .cap_id = POC, + .min = 0, + .max = 2, + .step_or_mask = 1, + .value = 1, + .hfi_id = HFI_PROP_PIC_ORDER_CNT_TYPE, + }, + { + .cap_id = CODED_FRAMES, + .min = CODED_FRAMES_PROGRESSIVE, + .max = CODED_FRAMES_PROGRESSIVE, + .step_or_mask = 0, + .value = CODED_FRAMES_PROGRESSIVE, + .hfi_id = HFI_PROP_CODED_FRAMES, + }, + { + .cap_id = BIT_DEPTH, + .min = BIT_DEPTH_8, + .max = BIT_DEPTH_8, + .step_or_mask = 1, + .value = BIT_DEPTH_8, + .hfi_id = HFI_PROP_LUMA_CHROMA_BIT_DEPTH, + }, + { + .cap_id = RAP_FRAME, + .min = 0, + .max = 1, + .step_or_mask = 1, + .value = 1, + .hfi_id = HFI_PROP_DEC_START_FROM_RAP_FRAME, + .flags = CAP_FLAG_INPUT_PORT, + .set = iris_set_u32, + }, +}; + +static struct platform_inst_caps platform_inst_cap_qcs8300 = { + .min_frame_width = 96, + .max_frame_width = 4096, + .min_frame_height = 96, + .max_frame_height = 4096, + .max_mbpf = (4096 * 2176) / 256, + .mb_cycles_vpp = 200, + .mb_cycles_fw = 326389, + .mb_cycles_fw_vpp = 44156, + .num_comv = 0, +}; diff --git a/drivers/media/platform/qcom/iris/iris_probe.c b/drivers/media/platform/qcom/iris/iris_probe.c index fa3b9c9b1493..9a7ce142f700 100644 --- a/drivers/media/platform/qcom/iris/iris_probe.c +++ b/drivers/media/platform/qcom/iris/iris_probe.c @@ -335,6 +335,10 @@ static const struct dev_pm_ops iris_pm_ops = { }; static const struct of_device_id iris_dt_match[] = { + { + .compatible = "qcom,qcs8300-iris", + .data = &qcs8300_data, + }, #if (!IS_ENABLED(CONFIG_VIDEO_QCOM_VENUS)) { .compatible = "qcom,sm8250-venus", -- 2.51.0 From d6a0866750bb14e3c0c16677fc45162513f1be1f Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Thu, 24 Apr 2025 10:05:33 +0300 Subject: [PATCH 07/16] media: rcar-vin: Add RCAR_GEN4 model value MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Currently Gen4 VINs are marked as RCAN_GEN3 models. Add a new enum value, RCAR_GEN4, and use it for Gen4 VINs. No functional changes in this patch. Signed-off-by: Tomi Valkeinen Reviewed-by: Niklas Söderlund Tested-by: Niklas Söderlund Link: https://lore.kernel.org/r/20250424-rcar-fix-raw-v2-1-f6afca378124@ideasonboard.com Signed-off-by: Laurent Pinchart Signed-off-by: Hans Verkuil --- drivers/media/platform/renesas/rcar-vin/rcar-core.c | 2 +- drivers/media/platform/renesas/rcar-vin/rcar-dma.c | 8 ++++---- drivers/media/platform/renesas/rcar-vin/rcar-vin.h | 1 + 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/drivers/media/platform/renesas/rcar-vin/rcar-core.c b/drivers/media/platform/renesas/rcar-vin/rcar-core.c index cfbc9ec27706..846ae7989b1d 100644 --- a/drivers/media/platform/renesas/rcar-vin/rcar-core.c +++ b/drivers/media/platform/renesas/rcar-vin/rcar-core.c @@ -1273,7 +1273,7 @@ static const struct rvin_info rcar_info_r8a77995 = { }; static const struct rvin_info rcar_info_gen4 = { - .model = RCAR_GEN3, + .model = RCAR_GEN4, .use_mc = true, .use_isp = true, .nv12 = true, diff --git a/drivers/media/platform/renesas/rcar-vin/rcar-dma.c b/drivers/media/platform/renesas/rcar-vin/rcar-dma.c index f7b80e61a987..374396bcf8b9 100644 --- a/drivers/media/platform/renesas/rcar-vin/rcar-dma.c +++ b/drivers/media/platform/renesas/rcar-vin/rcar-dma.c @@ -783,7 +783,7 @@ static int rvin_setup(struct rvin_dev *vin) } /* Make sure input interface and input format is valid. */ - if (vin->info->model == RCAR_GEN3) { + if (vin->info->model == RCAR_GEN3 || vin->info->model == RCAR_GEN4) { switch (vnmc & VNMC_INF_MASK) { case VNMC_INF_YUV8_BT656: case VNMC_INF_YUV10_BT656: @@ -806,7 +806,7 @@ static int rvin_setup(struct rvin_dev *vin) } /* Enable VSYNC Field Toggle mode after one VSYNC input */ - if (vin->info->model == RCAR_GEN3) + if (vin->info->model == RCAR_GEN3 || vin->info->model == RCAR_GEN4) dmr2 = VNDMR2_FTEV; else dmr2 = VNDMR2_FTEV | VNDMR2_VLV(1); @@ -906,7 +906,7 @@ static int rvin_setup(struct rvin_dev *vin) if (input_is_yuv == output_is_yuv) vnmc |= VNMC_BPS; - if (vin->info->model == RCAR_GEN3) { + if (vin->info->model == RCAR_GEN3 || vin->info->model == RCAR_GEN4) { /* Select between CSI-2 and parallel input */ if (vin->is_csi) vnmc &= ~VNMC_DPINE; @@ -1287,7 +1287,7 @@ static int rvin_mc_validate_format(struct rvin_dev *vin, struct v4l2_subdev *sd, if (rvin_scaler_needed(vin)) { /* Gen3 can't scale NV12 */ - if (vin->info->model == RCAR_GEN3 && + if ((vin->info->model == RCAR_GEN3 || vin->info->model == RCAR_GEN4) && vin->format.pixelformat == V4L2_PIX_FMT_NV12) return -EPIPE; diff --git a/drivers/media/platform/renesas/rcar-vin/rcar-vin.h b/drivers/media/platform/renesas/rcar-vin/rcar-vin.h index 934474d2334a..83d1b2734c41 100644 --- a/drivers/media/platform/renesas/rcar-vin/rcar-vin.h +++ b/drivers/media/platform/renesas/rcar-vin/rcar-vin.h @@ -39,6 +39,7 @@ enum model_id { RCAR_M1, RCAR_GEN2, RCAR_GEN3, + RCAR_GEN4, }; enum rvin_csi_id { -- 2.51.0 From 21cb8227e35ec93c637a2330fc3cb2e63170e7d4 Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Thu, 24 Apr 2025 10:05:34 +0300 Subject: [PATCH 08/16] media: rcar-vin: Remove unnecessary checks MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Remove unnecessary checks wrt. formats and interfaces in rvin_setup(). The validity of the formats has already been checked earlier. Signed-off-by: Tomi Valkeinen Reviewed-by: Niklas Söderlund Tested-by: Niklas Söderlund Link: https://lore.kernel.org/r/20250424-rcar-fix-raw-v2-2-f6afca378124@ideasonboard.com Signed-off-by: Laurent Pinchart Signed-off-by: Hans Verkuil --- .../platform/renesas/rcar-vin/rcar-dma.c | 23 ------------------- 1 file changed, 23 deletions(-) diff --git a/drivers/media/platform/renesas/rcar-vin/rcar-dma.c b/drivers/media/platform/renesas/rcar-vin/rcar-dma.c index 374396bcf8b9..e0464eb49b59 100644 --- a/drivers/media/platform/renesas/rcar-vin/rcar-dma.c +++ b/drivers/media/platform/renesas/rcar-vin/rcar-dma.c @@ -782,29 +782,6 @@ static int rvin_setup(struct rvin_dev *vin) break; } - /* Make sure input interface and input format is valid. */ - if (vin->info->model == RCAR_GEN3 || vin->info->model == RCAR_GEN4) { - switch (vnmc & VNMC_INF_MASK) { - case VNMC_INF_YUV8_BT656: - case VNMC_INF_YUV10_BT656: - case VNMC_INF_YUV16: - case VNMC_INF_RGB666: - if (vin->is_csi) { - vin_err(vin, "Invalid setting in MIPI CSI2\n"); - return -EINVAL; - } - break; - case VNMC_INF_RAW8: - if (!vin->is_csi) { - vin_err(vin, "Invalid setting in Digital Pins\n"); - return -EINVAL; - } - break; - default: - break; - } - } - /* Enable VSYNC Field Toggle mode after one VSYNC input */ if (vin->info->model == RCAR_GEN3 || vin->info->model == RCAR_GEN4) dmr2 = VNDMR2_FTEV; -- 2.51.0 From 17b5496c30709d83a0ca2d11731720a4dc0ef540 Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Thu, 24 Apr 2025 10:05:35 +0300 Subject: [PATCH 09/16] media: rcar-vin: Fix RAW8 MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit On Gen4 we need to set VNMC's EXINF to a different value (1) than in Gen3 (0). Add a define for this, and set the bit for Gen4. Signed-off-by: Tomi Valkeinen Reviewed-by: Niklas Söderlund Tested-by: Niklas Söderlund Link: https://lore.kernel.org/r/20250424-rcar-fix-raw-v2-3-f6afca378124@ideasonboard.com Signed-off-by: Laurent Pinchart Signed-off-by: Hans Verkuil --- drivers/media/platform/renesas/rcar-vin/rcar-dma.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/media/platform/renesas/rcar-vin/rcar-dma.c b/drivers/media/platform/renesas/rcar-vin/rcar-dma.c index e0464eb49b59..65e41c68e627 100644 --- a/drivers/media/platform/renesas/rcar-vin/rcar-dma.c +++ b/drivers/media/platform/renesas/rcar-vin/rcar-dma.c @@ -94,6 +94,7 @@ #define VNMC_INF_YUV16 (5 << 16) #define VNMC_INF_RGB888 (6 << 16) #define VNMC_INF_RGB666 (7 << 16) +#define VNMC_EXINF_RAW8 (1 << 12) /* Gen4 specific */ #define VNMC_VUP (1 << 10) #define VNMC_IM_ODD (0 << 3) #define VNMC_IM_ODD_EVEN (1 << 3) @@ -771,6 +772,8 @@ static int rvin_setup(struct rvin_dev *vin) case MEDIA_BUS_FMT_SRGGB8_1X8: case MEDIA_BUS_FMT_Y8_1X8: vnmc |= VNMC_INF_RAW8; + if (vin->info->model == RCAR_GEN4) + vnmc |= VNMC_EXINF_RAW8; break; case MEDIA_BUS_FMT_SBGGR10_1X10: case MEDIA_BUS_FMT_SGBRG10_1X10: -- 2.51.0 From 94bf847ae5a61e0ab0b971ed186a443688eb793f Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Thu, 24 Apr 2025 10:05:36 +0300 Subject: [PATCH 10/16] media: rcar-vin: Fix RAW10 MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Fix the following to get RAW10 formats working: In rvin_formats, the bpp is set to 4 for RAW10. As VIN unpacks RAW10 to 16-bit containers, the bpp should be 2. Don't set VNDMR_YC_THR to the VNDMR register. The YC_THR is "YC Data Through Mode", used for YUV formats and should not be set for RAW10. Fixes: 1b7e7240eaf3 ("media: rcar-vin: Add support for RAW10") Cc: stable@vger.kernel.org Signed-off-by: Tomi Valkeinen Reviewed-by: Niklas Söderlund Tested-by: Niklas Söderlund Link: https://lore.kernel.org/r/20250424-rcar-fix-raw-v2-4-f6afca378124@ideasonboard.com Signed-off-by: Laurent Pinchart Signed-off-by: Hans Verkuil --- drivers/media/platform/renesas/rcar-vin/rcar-dma.c | 2 +- drivers/media/platform/renesas/rcar-vin/rcar-v4l2.c | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/media/platform/renesas/rcar-vin/rcar-dma.c b/drivers/media/platform/renesas/rcar-vin/rcar-dma.c index 65e41c68e627..5c08ee2c9807 100644 --- a/drivers/media/platform/renesas/rcar-vin/rcar-dma.c +++ b/drivers/media/platform/renesas/rcar-vin/rcar-dma.c @@ -870,7 +870,7 @@ static int rvin_setup(struct rvin_dev *vin) case V4L2_PIX_FMT_SGBRG10: case V4L2_PIX_FMT_SGRBG10: case V4L2_PIX_FMT_SRGGB10: - dmr = VNDMR_RMODE_RAW10 | VNDMR_YC_THR; + dmr = VNDMR_RMODE_RAW10; break; default: vin_err(vin, "Invalid pixelformat (0x%x)\n", diff --git a/drivers/media/platform/renesas/rcar-vin/rcar-v4l2.c b/drivers/media/platform/renesas/rcar-vin/rcar-v4l2.c index ade007a9811f..db091af57c19 100644 --- a/drivers/media/platform/renesas/rcar-vin/rcar-v4l2.c +++ b/drivers/media/platform/renesas/rcar-vin/rcar-v4l2.c @@ -88,19 +88,19 @@ static const struct rvin_video_format rvin_formats[] = { }, { .fourcc = V4L2_PIX_FMT_SBGGR10, - .bpp = 4, + .bpp = 2, }, { .fourcc = V4L2_PIX_FMT_SGBRG10, - .bpp = 4, + .bpp = 2, }, { .fourcc = V4L2_PIX_FMT_SGRBG10, - .bpp = 4, + .bpp = 2, }, { .fourcc = V4L2_PIX_FMT_SRGGB10, - .bpp = 4, + .bpp = 2, }, }; -- 2.51.0 From 63fd40f67283ce7b3ef7414d73ab1cf78fd9c89c Mon Sep 17 00:00:00 2001 From: =?utf8?q?Niklas=20S=C3=B6derlund?= Date: Wed, 23 Apr 2025 18:31:07 +0200 Subject: [PATCH 11/16] dt-bindings: media: renesas,isp: Add ISP core function block MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Some R-Car ISP instances have in addition to the channel selector (CS) an ISP core (CORE) to perform operations on an image stream. The core function is mapped to a different memory region and has a separate interrupt than CS, extend the bindings to allow describing this. On the same SoC different instances of the ISP IP may have, or not have, the CORE functionality. The CS function on all instances on the SoC are the same and the documentation describes the full ISP (CS + CORE) as a single IP block. Where instances not having the CORE function simply lack the functionality to modify the image data. There are dependencies on the CS functionality while operating the CORE functionality. In order for the ISP core to function in memory-to-memory mode it needs to be feed input data from a Streaming Bridge interface. This interface is provided thru the VSP-X device. Add an optional new property "renesas,vspx" to provide a phandle to describe this relationship. While adding mandatory reg-names and interrupt-names breaks existing bindings the driver itself remains backward compatible and provides CS functionality if a single unnamed reg and interrupt property is present. Furthermore all existing users of the bindings are updated in following work to add these new mandatory properties. Signed-off-by: Niklas Söderlund Reviewed-by: Laurent Pinchart Reviewed-by: Geert Uytterhoeven Reviewed-by: Rob Herring (Arm) Link: https://lore.kernel.org/r/20250423163113.2961049-2-niklas.soderlund+renesas@ragnatech.se Signed-off-by: Laurent Pinchart Signed-off-by: Hans Verkuil --- .../bindings/media/renesas,isp.yaml | 63 ++++++++++++++++--- 1 file changed, 55 insertions(+), 8 deletions(-) diff --git a/Documentation/devicetree/bindings/media/renesas,isp.yaml b/Documentation/devicetree/bindings/media/renesas,isp.yaml index c4de4555b753..d25e020f5e5e 100644 --- a/Documentation/devicetree/bindings/media/renesas,isp.yaml +++ b/Documentation/devicetree/bindings/media/renesas,isp.yaml @@ -25,19 +25,55 @@ properties: - renesas,r8a779h0-isp # V4M - const: renesas,rcar-gen4-isp # Generic R-Car Gen4 reg: - maxItems: 1 + minItems: 1 + maxItems: 2 + + reg-names: + minItems: 1 + items: + - const: cs + - const: core interrupts: - maxItems: 1 + minItems: 1 + maxItems: 2 + + interrupt-names: + minItems: 1 + items: + - const: cs + - const: core clocks: - maxItems: 1 + minItems: 1 + maxItems: 2 + + clock-names: + minItems: 1 + items: + - const: cs + - const: core power-domains: maxItems: 1 resets: - maxItems: 1 + minItems: 1 + maxItems: 2 + + reset-names: + minItems: 1 + items: + - const: cs + - const: core + + renesas,vspx: + $ref: /schemas/types.yaml#/definitions/phandle + description: + A phandle to the companion VSPX responsible for the Streaming Bridge + functionality. The Streaming Bridge is responsible for feeding image + and configuration data to the ISP when operating in memory-to-memory + mode. ports: $ref: /schemas/graph.yaml#/properties/ports @@ -103,10 +139,14 @@ properties: required: - compatible - reg + - reg-names - interrupts + - interrupt-names - clocks + - clock-names - power-domains - resets + - reset-names - ports additionalProperties: false @@ -119,11 +159,18 @@ examples: isp1: isp@fed20000 { compatible = "renesas,r8a779a0-isp", "renesas,rcar-gen4-isp"; - reg = <0xfed20000 0x10000>; - interrupts = ; - clocks = <&cpg CPG_MOD 613>; + reg = <0xfed20000 0x10000>, <0xfee00000 0x100000>; + reg-names = "cs", "core"; + interrupts = , + ; + interrupt-names = "cs", "core"; + clocks = <&cpg CPG_MOD 613>, <&cpg CPG_MOD 17>; + clock-names = "cs", "core"; power-domains = <&sysc R8A779A0_PD_A3ISP01>; - resets = <&cpg 613>; + resets = <&cpg 613>, <&cpg 17>; + reset-names = "cs", "core"; + + renesas,vspx = <&vspx1>; ports { #address-cells = <1>; -- 2.51.0 From 9103d33f22b12f9633157d2e853594aabc377eb7 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Niklas=20S=C3=B6derlund?= Date: Wed, 23 Apr 2025 18:31:11 +0200 Subject: [PATCH 12/16] media: rcar-isp: Move driver to own directory MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Before extending the driver with functions from the R-Car ISP core that will span multiple files move the existing driver to a separate directory. While at it rename the single source file to allow future files to be grouped by functions. Signed-off-by: Niklas Söderlund Reviewed-by: Jacopo Mondi Reviewed-by: Laurent Pinchart Link: https://lore.kernel.org/r/20250423163113.2961049-6-niklas.soderlund+renesas@ragnatech.se Signed-off-by: Laurent Pinchart Signed-off-by: Hans Verkuil --- MAINTAINERS | 2 +- drivers/media/platform/renesas/Kconfig | 18 +----------------- drivers/media/platform/renesas/Makefile | 2 +- .../media/platform/renesas/rcar-isp/Kconfig | 18 ++++++++++++++++++ .../media/platform/renesas/rcar-isp/Makefile | 4 ++++ .../renesas/{rcar-isp.c => rcar-isp/csisp.c} | 0 6 files changed, 25 insertions(+), 19 deletions(-) create mode 100644 drivers/media/platform/renesas/rcar-isp/Kconfig create mode 100644 drivers/media/platform/renesas/rcar-isp/Makefile rename drivers/media/platform/renesas/{rcar-isp.c => rcar-isp/csisp.c} (100%) diff --git a/MAINTAINERS b/MAINTAINERS index 1b5e8ec57851..5dee8459a614 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -14897,7 +14897,7 @@ F: Documentation/devicetree/bindings/media/renesas,csi2.yaml F: Documentation/devicetree/bindings/media/renesas,isp.yaml F: Documentation/devicetree/bindings/media/renesas,vin.yaml F: drivers/media/platform/renesas/rcar-csi2.c -F: drivers/media/platform/renesas/rcar-isp.c +F: drivers/media/platform/renesas/rcar-isp/ F: drivers/media/platform/renesas/rcar-vin/ MEDIA DRIVERS FOR RENESAS - VSP1 diff --git a/drivers/media/platform/renesas/Kconfig b/drivers/media/platform/renesas/Kconfig index c7fc718a30a5..27a54fa79083 100644 --- a/drivers/media/platform/renesas/Kconfig +++ b/drivers/media/platform/renesas/Kconfig @@ -30,23 +30,6 @@ config VIDEO_RCAR_CSI2 To compile this driver as a module, choose M here: the module will be called rcar-csi2. -config VIDEO_RCAR_ISP - tristate "R-Car Image Signal Processor (ISP)" - depends on V4L_PLATFORM_DRIVERS - depends on VIDEO_DEV && OF - depends on ARCH_RENESAS || COMPILE_TEST - select MEDIA_CONTROLLER - select VIDEO_V4L2_SUBDEV_API - select RESET_CONTROLLER - select V4L2_FWNODE - help - Support for Renesas R-Car Image Signal Processor (ISP). - Enable this to support the Renesas R-Car Image Signal - Processor (ISP). - - To compile this driver as a module, choose M here: the - module will be called rcar-isp. - config VIDEO_SH_VOU tristate "SuperH VOU video output driver" depends on V4L_PLATFORM_DRIVERS @@ -56,6 +39,7 @@ config VIDEO_SH_VOU help Support for the Video Output Unit (VOU) on SuperH SoCs. +source "drivers/media/platform/renesas/rcar-isp/Kconfig" source "drivers/media/platform/renesas/rcar-vin/Kconfig" source "drivers/media/platform/renesas/rzg2l-cru/Kconfig" diff --git a/drivers/media/platform/renesas/Makefile b/drivers/media/platform/renesas/Makefile index 50774a20330c..1127259c09d6 100644 --- a/drivers/media/platform/renesas/Makefile +++ b/drivers/media/platform/renesas/Makefile @@ -3,13 +3,13 @@ # Makefile for the Renesas capture/playback device drivers. # +obj-y += rcar-isp/ obj-y += rcar-vin/ obj-y += rzg2l-cru/ obj-y += vsp1/ obj-$(CONFIG_VIDEO_RCAR_CSI2) += rcar-csi2.o obj-$(CONFIG_VIDEO_RCAR_DRIF) += rcar_drif.o -obj-$(CONFIG_VIDEO_RCAR_ISP) += rcar-isp.o obj-$(CONFIG_VIDEO_RENESAS_CEU) += renesas-ceu.o obj-$(CONFIG_VIDEO_RENESAS_FCP) += rcar-fcp.o obj-$(CONFIG_VIDEO_RENESAS_FDP1) += rcar_fdp1.o diff --git a/drivers/media/platform/renesas/rcar-isp/Kconfig b/drivers/media/platform/renesas/rcar-isp/Kconfig new file mode 100644 index 000000000000..242f6a23851f --- /dev/null +++ b/drivers/media/platform/renesas/rcar-isp/Kconfig @@ -0,0 +1,18 @@ +# SPDX-License-Identifier: GPL-2.0 + +config VIDEO_RCAR_ISP + tristate "R-Car Image Signal Processor (ISP)" + depends on V4L_PLATFORM_DRIVERS + depends on VIDEO_DEV && OF + depends on ARCH_RENESAS || COMPILE_TEST + select MEDIA_CONTROLLER + select VIDEO_V4L2_SUBDEV_API + select RESET_CONTROLLER + select V4L2_FWNODE + help + Support for Renesas R-Car Image Signal Processor (ISP). + Enable this to support the Renesas R-Car Image Signal + Processor (ISP). + + To compile this driver as a module, choose M here: the + module will be called rcar-isp. diff --git a/drivers/media/platform/renesas/rcar-isp/Makefile b/drivers/media/platform/renesas/rcar-isp/Makefile new file mode 100644 index 000000000000..b542118c831e --- /dev/null +++ b/drivers/media/platform/renesas/rcar-isp/Makefile @@ -0,0 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 +rcar-isp-objs = csisp.o + +obj-$(CONFIG_VIDEO_RCAR_ISP) += rcar-isp.o diff --git a/drivers/media/platform/renesas/rcar-isp.c b/drivers/media/platform/renesas/rcar-isp/csisp.c similarity index 100% rename from drivers/media/platform/renesas/rcar-isp.c rename to drivers/media/platform/renesas/rcar-isp/csisp.c -- 2.51.0 From 7281a7bd5b7b57fb6841f27e95115934ab25f4a4 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Niklas=20S=C3=B6derlund?= Date: Wed, 23 Apr 2025 18:31:12 +0200 Subject: [PATCH 13/16] media: rcar-isp: Rename base register variable MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Prepare for extending the driver to in addition to supporting the channel selector (CS) also support the core ISP. The two different functions have different base addresses so the driver needs to distinguish between them. Prepare for this by marking existing base address variable and read/write functions to make it clear they operate on the CS portion of the driver. There is no functional change. Signed-off-by: Niklas Söderlund Reviewed-by: Jacopo Mondi Reviewed-by: Laurent Pinchart Reviewed-by: Laurent Pinchart Link: https://lore.kernel.org/r/20250423163113.2961049-7-niklas.soderlund+renesas@ragnatech.se Signed-off-by: Laurent Pinchart Signed-off-by: Hans Verkuil --- .../media/platform/renesas/rcar-isp/csisp.c | 46 +++++++++---------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/drivers/media/platform/renesas/rcar-isp/csisp.c b/drivers/media/platform/renesas/rcar-isp/csisp.c index 4bc89d4757fa..f36d43c2e0a2 100644 --- a/drivers/media/platform/renesas/rcar-isp/csisp.c +++ b/drivers/media/platform/renesas/rcar-isp/csisp.c @@ -159,7 +159,7 @@ enum rcar_isp_pads { struct rcar_isp { struct device *dev; - void __iomem *base; + void __iomem *csbase; struct reset_control *rstc; enum rcar_isp_input csi_input; @@ -184,14 +184,14 @@ static inline struct rcar_isp *notifier_to_isp(struct v4l2_async_notifier *n) return container_of(n, struct rcar_isp, notifier); } -static void risp_write(struct rcar_isp *isp, u32 offset, u32 value) +static void risp_write_cs(struct rcar_isp *isp, u32 offset, u32 value) { - iowrite32(value, isp->base + offset); + iowrite32(value, isp->csbase + offset); } -static u32 risp_read(struct rcar_isp *isp, u32 offset) +static u32 risp_read_cs(struct rcar_isp *isp, u32 offset) { - return ioread32(isp->base + offset); + return ioread32(isp->csbase + offset); } static int risp_power_on(struct rcar_isp *isp) @@ -245,31 +245,31 @@ static int risp_start(struct rcar_isp *isp, struct v4l2_subdev_state *state) if (isp->csi_input == RISP_CSI_INPUT1) sel_csi = ISPINPUTSEL0_SEL_CSI0; - risp_write(isp, ISPINPUTSEL0_REG, - risp_read(isp, ISPINPUTSEL0_REG) | sel_csi); + risp_write_cs(isp, ISPINPUTSEL0_REG, + risp_read_cs(isp, ISPINPUTSEL0_REG) | sel_csi); /* Configure Channel Selector. */ for (vc = 0; vc < 4; vc++) { u8 ch = vc + 4; u8 dt = format->datatype; - risp_write(isp, ISPCS_FILTER_ID_CH_REG(ch), BIT(vc)); - risp_write(isp, ISPCS_DT_CODE03_CH_REG(ch), - ISPCS_DT_CODE03_EN3 | ISPCS_DT_CODE03_DT3(dt) | - ISPCS_DT_CODE03_EN2 | ISPCS_DT_CODE03_DT2(dt) | - ISPCS_DT_CODE03_EN1 | ISPCS_DT_CODE03_DT1(dt) | - ISPCS_DT_CODE03_EN0 | ISPCS_DT_CODE03_DT0(dt)); + risp_write_cs(isp, ISPCS_FILTER_ID_CH_REG(ch), BIT(vc)); + risp_write_cs(isp, ISPCS_DT_CODE03_CH_REG(ch), + ISPCS_DT_CODE03_EN3 | ISPCS_DT_CODE03_DT3(dt) | + ISPCS_DT_CODE03_EN2 | ISPCS_DT_CODE03_DT2(dt) | + ISPCS_DT_CODE03_EN1 | ISPCS_DT_CODE03_DT1(dt) | + ISPCS_DT_CODE03_EN0 | ISPCS_DT_CODE03_DT0(dt)); } /* Setup processing method. */ - risp_write(isp, ISPPROCMODE_DT_REG(format->datatype), - ISPPROCMODE_DT_PROC_MODE_VC3(format->procmode) | - ISPPROCMODE_DT_PROC_MODE_VC2(format->procmode) | - ISPPROCMODE_DT_PROC_MODE_VC1(format->procmode) | - ISPPROCMODE_DT_PROC_MODE_VC0(format->procmode)); + risp_write_cs(isp, ISPPROCMODE_DT_REG(format->datatype), + ISPPROCMODE_DT_PROC_MODE_VC3(format->procmode) | + ISPPROCMODE_DT_PROC_MODE_VC2(format->procmode) | + ISPPROCMODE_DT_PROC_MODE_VC1(format->procmode) | + ISPPROCMODE_DT_PROC_MODE_VC0(format->procmode)); /* Start ISP. */ - risp_write(isp, ISPSTART_REG, ISPSTART_START); + risp_write_cs(isp, ISPSTART_REG, ISPSTART_START); ret = v4l2_subdev_enable_streams(isp->remote, isp->remote_pad, BIT_ULL(0)); @@ -284,7 +284,7 @@ static void risp_stop(struct rcar_isp *isp) v4l2_subdev_disable_streams(isp->remote, isp->remote_pad, BIT_ULL(0)); /* Stop ISP. */ - risp_write(isp, ISPSTART_REG, ISPSTART_STOP); + risp_write_cs(isp, ISPSTART_REG, ISPSTART_STOP); risp_power_off(isp); } @@ -465,9 +465,9 @@ static const struct media_entity_operations risp_entity_ops = { static int risp_probe_resources(struct rcar_isp *isp, struct platform_device *pdev) { - isp->base = devm_platform_get_and_ioremap_resource(pdev, 0, NULL); - if (IS_ERR(isp->base)) - return PTR_ERR(isp->base); + isp->csbase = devm_platform_get_and_ioremap_resource(pdev, 0, NULL); + if (IS_ERR(isp->csbase)) + return PTR_ERR(isp->csbase); isp->rstc = devm_reset_control_get(&pdev->dev, NULL); -- 2.51.0 From 09d76b4e83e4911238f74a2ba48d92db6e04f10a Mon Sep 17 00:00:00 2001 From: =?utf8?q?Niklas=20S=C3=B6derlund?= Date: Wed, 23 Apr 2025 18:31:13 +0200 Subject: [PATCH 14/16] media: rcar-isp: Parse named cs memory region MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Extend the device tree parsing to optionally parse the cs memory region by name. The change is backward compatible with the device tree model where a single unnamed region describes only the ISP channel select function. Signed-off-by: Niklas Söderlund Reviewed-by: Jacopo Mondi Reviewed-by: Laurent Pinchart Link: https://lore.kernel.org/r/20250423163113.2961049-8-niklas.soderlund+renesas@ragnatech.se Signed-off-by: Laurent Pinchart Signed-off-by: Hans Verkuil --- drivers/media/platform/renesas/rcar-isp/csisp.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/drivers/media/platform/renesas/rcar-isp/csisp.c b/drivers/media/platform/renesas/rcar-isp/csisp.c index f36d43c2e0a2..1eb29a0b774a 100644 --- a/drivers/media/platform/renesas/rcar-isp/csisp.c +++ b/drivers/media/platform/renesas/rcar-isp/csisp.c @@ -465,7 +465,18 @@ static const struct media_entity_operations risp_entity_ops = { static int risp_probe_resources(struct rcar_isp *isp, struct platform_device *pdev) { - isp->csbase = devm_platform_get_and_ioremap_resource(pdev, 0, NULL); + struct resource *res; + + /* + * For backward compatibility allow cs base to be the only reg if no + * reg-names are set in DT. + */ + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "cs"); + if (!res) + isp->csbase = devm_platform_ioremap_resource(pdev, 0); + else + isp->csbase = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(isp->csbase)) return PTR_ERR(isp->csbase); -- 2.51.0 From 7305ee12b2c9a8fb615319dc96d9aed847c80117 Mon Sep 17 00:00:00 2001 From: Jacopo Mondi Date: Tue, 1 Apr 2025 16:22:01 +0200 Subject: [PATCH 15/16] media: renesas: vsp1: Add support IIF ISP Interface MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit The IIF (ISP InterFace) is a VSP2 function that transfers data to the ISP by reading from external memory through two RPF instances. Add support for it in the vsp1 driver by introducing a new entity type. The sole required operation is to enable the IIF function during configure_stream(). Reviewed-by: Laurent Pinchart Reviewed-by: Niklas Söderlund Tested-by: Niklas Söderlund Signed-off-by: Jacopo Mondi Link: https://lore.kernel.org/r/20250401-v4h-iif-v7-1-cc547c0bddd5@ideasonboard.com Signed-off-by: Laurent Pinchart Signed-off-by: Hans Verkuil --- drivers/media/platform/renesas/vsp1/Makefile | 2 +- drivers/media/platform/renesas/vsp1/vsp1.h | 3 + .../media/platform/renesas/vsp1/vsp1_drv.c | 11 ++ .../media/platform/renesas/vsp1/vsp1_entity.c | 8 ++ .../media/platform/renesas/vsp1/vsp1_entity.h | 1 + .../media/platform/renesas/vsp1/vsp1_iif.c | 121 ++++++++++++++++++ .../media/platform/renesas/vsp1/vsp1_iif.h | 26 ++++ .../media/platform/renesas/vsp1/vsp1_pipe.c | 1 + .../media/platform/renesas/vsp1/vsp1_pipe.h | 1 + .../media/platform/renesas/vsp1/vsp1_regs.h | 8 ++ 10 files changed, 181 insertions(+), 1 deletion(-) create mode 100644 drivers/media/platform/renesas/vsp1/vsp1_iif.c create mode 100644 drivers/media/platform/renesas/vsp1/vsp1_iif.h diff --git a/drivers/media/platform/renesas/vsp1/Makefile b/drivers/media/platform/renesas/vsp1/Makefile index 4bb4dcbef7b5..de8c802e1d1a 100644 --- a/drivers/media/platform/renesas/vsp1/Makefile +++ b/drivers/media/platform/renesas/vsp1/Makefile @@ -5,6 +5,6 @@ vsp1-y += vsp1_rpf.o vsp1_rwpf.o vsp1_wpf.o vsp1-y += vsp1_clu.o vsp1_hsit.o vsp1_lut.o vsp1-y += vsp1_brx.o vsp1_sru.o vsp1_uds.o vsp1-y += vsp1_hgo.o vsp1_hgt.o vsp1_histo.o -vsp1-y += vsp1_lif.o vsp1_uif.o +vsp1-y += vsp1_iif.o vsp1_lif.o vsp1_uif.o obj-$(CONFIG_VIDEO_RENESAS_VSP1) += vsp1.o diff --git a/drivers/media/platform/renesas/vsp1/vsp1.h b/drivers/media/platform/renesas/vsp1/vsp1.h index 2f6f0c6ae555..263024639dd2 100644 --- a/drivers/media/platform/renesas/vsp1/vsp1.h +++ b/drivers/media/platform/renesas/vsp1/vsp1.h @@ -32,6 +32,7 @@ struct vsp1_clu; struct vsp1_hgo; struct vsp1_hgt; struct vsp1_hsit; +struct vsp1_iif; struct vsp1_lif; struct vsp1_lut; struct vsp1_rwpf; @@ -56,6 +57,7 @@ struct vsp1_uif; #define VSP1_HAS_BRS BIT(9) #define VSP1_HAS_EXT_DL BIT(10) #define VSP1_HAS_NON_ZERO_LBA BIT(11) +#define VSP1_HAS_IIF BIT(12) struct vsp1_device_info { u32 version; @@ -91,6 +93,7 @@ struct vsp1_device { struct vsp1_hgt *hgt; struct vsp1_hsit *hsi; struct vsp1_hsit *hst; + struct vsp1_iif *iif; struct vsp1_lif *lif[VSP1_MAX_LIF]; struct vsp1_lut *lut; struct vsp1_rwpf *rpf[VSP1_MAX_RPF]; diff --git a/drivers/media/platform/renesas/vsp1/vsp1_drv.c b/drivers/media/platform/renesas/vsp1/vsp1_drv.c index 9fc6bf624a52..d13e9b31aa7c 100644 --- a/drivers/media/platform/renesas/vsp1/vsp1_drv.c +++ b/drivers/media/platform/renesas/vsp1/vsp1_drv.c @@ -29,6 +29,7 @@ #include "vsp1_hgo.h" #include "vsp1_hgt.h" #include "vsp1_hsit.h" +#include "vsp1_iif.h" #include "vsp1_lif.h" #include "vsp1_lut.h" #include "vsp1_pipe.h" @@ -340,6 +341,16 @@ static int vsp1_create_entities(struct vsp1_device *vsp1) &vsp1->entities); } + if (vsp1_feature(vsp1, VSP1_HAS_IIF)) { + vsp1->iif = vsp1_iif_create(vsp1); + if (IS_ERR(vsp1->iif)) { + ret = PTR_ERR(vsp1->iif); + goto done; + } + + list_add_tail(&vsp1->iif->entity.list_dev, &vsp1->entities); + } + /* * The LIFs are only supported when used in conjunction with the DU, in * which case the userspace API is disabled. If the userspace API is diff --git a/drivers/media/platform/renesas/vsp1/vsp1_entity.c b/drivers/media/platform/renesas/vsp1/vsp1_entity.c index 8b8945bd8f10..2096a09a1278 100644 --- a/drivers/media/platform/renesas/vsp1/vsp1_entity.c +++ b/drivers/media/platform/renesas/vsp1/vsp1_entity.c @@ -63,9 +63,14 @@ void vsp1_entity_route_setup(struct vsp1_entity *entity, /* * The ILV and BRS share the same data path route. The extra BRSSEL bit * selects between the ILV and BRS. + * + * The BRU and IIF share the same data path route. The extra IIFSEL bit + * selects between the IIF and BRU. */ if (source->type == VSP1_ENTITY_BRS) route |= VI6_DPR_ROUTE_BRSSEL; + else if (source->type == VSP1_ENTITY_IIF) + route |= VI6_DPR_ROUTE_IIFSEL; vsp1_dl_body_write(dlb, source->route->reg, route); } @@ -528,6 +533,9 @@ struct media_pad *vsp1_entity_remote_pad(struct media_pad *pad) { VI6_DPR_NODE_WPF(idx) }, VI6_DPR_NODE_WPF(idx) } static const struct vsp1_route vsp1_routes[] = { + { VSP1_ENTITY_IIF, 0, VI6_DPR_BRU_ROUTE, + { VI6_DPR_NODE_BRU_IN(0), VI6_DPR_NODE_BRU_IN(1), + VI6_DPR_NODE_BRU_IN(3) }, VI6_DPR_NODE_WPF(0) }, { VSP1_ENTITY_BRS, 0, VI6_DPR_ILV_BRS_ROUTE, { VI6_DPR_NODE_BRS_IN(0), VI6_DPR_NODE_BRS_IN(1) }, 0 }, { VSP1_ENTITY_BRU, 0, VI6_DPR_BRU_ROUTE, diff --git a/drivers/media/platform/renesas/vsp1/vsp1_entity.h b/drivers/media/platform/renesas/vsp1/vsp1_entity.h index 1bcc9e27dfdc..bdcb780a79da 100644 --- a/drivers/media/platform/renesas/vsp1/vsp1_entity.h +++ b/drivers/media/platform/renesas/vsp1/vsp1_entity.h @@ -28,6 +28,7 @@ enum vsp1_entity_type { VSP1_ENTITY_HGT, VSP1_ENTITY_HSI, VSP1_ENTITY_HST, + VSP1_ENTITY_IIF, VSP1_ENTITY_LIF, VSP1_ENTITY_LUT, VSP1_ENTITY_RPF, diff --git a/drivers/media/platform/renesas/vsp1/vsp1_iif.c b/drivers/media/platform/renesas/vsp1/vsp1_iif.c new file mode 100644 index 000000000000..5dd62bebbe8c --- /dev/null +++ b/drivers/media/platform/renesas/vsp1/vsp1_iif.c @@ -0,0 +1,121 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * vsp1_iif.c -- R-Car VSP1 IIF (ISP Interface) + * + * Copyright (C) 2025 Ideas On Board Oy + * Copyright (C) 2025 Renesas Corporation + */ + +#include "vsp1.h" +#include "vsp1_dl.h" +#include "vsp1_iif.h" + +#define IIF_MIN_WIDTH 128U +#define IIF_MIN_HEIGHT 32U +#define IIF_MAX_WIDTH 5120U +#define IIF_MAX_HEIGHT 4096U + +/* ----------------------------------------------------------------------------- + * Device Access + */ + +static inline void vsp1_iif_write(struct vsp1_dl_body *dlb, u32 reg, u32 data) +{ + vsp1_dl_body_write(dlb, reg, data); +} + +/* ----------------------------------------------------------------------------- + * V4L2 Subdevice Operations + */ + +static const unsigned int iif_codes[] = { + MEDIA_BUS_FMT_Y8_1X8, + MEDIA_BUS_FMT_Y10_1X10, + MEDIA_BUS_FMT_Y12_1X12, + MEDIA_BUS_FMT_Y16_1X16, + MEDIA_BUS_FMT_METADATA_FIXED +}; + +static int iif_enum_mbus_code(struct v4l2_subdev *subdev, + struct v4l2_subdev_state *sd_state, + struct v4l2_subdev_mbus_code_enum *code) +{ + return vsp1_subdev_enum_mbus_code(subdev, sd_state, code, iif_codes, + ARRAY_SIZE(iif_codes)); +} + +static int iif_enum_frame_size(struct v4l2_subdev *subdev, + struct v4l2_subdev_state *sd_state, + struct v4l2_subdev_frame_size_enum *fse) +{ + return vsp1_subdev_enum_frame_size(subdev, sd_state, fse, + IIF_MIN_WIDTH, IIF_MIN_HEIGHT, + IIF_MAX_WIDTH, IIF_MAX_HEIGHT); +} + +static int iif_set_format(struct v4l2_subdev *subdev, + struct v4l2_subdev_state *sd_state, + struct v4l2_subdev_format *fmt) +{ + return vsp1_subdev_set_pad_format(subdev, sd_state, fmt, iif_codes, + ARRAY_SIZE(iif_codes), + IIF_MIN_WIDTH, IIF_MIN_HEIGHT, + IIF_MAX_WIDTH, IIF_MAX_HEIGHT); +} + +static const struct v4l2_subdev_pad_ops iif_pad_ops = { + .enum_mbus_code = iif_enum_mbus_code, + .enum_frame_size = iif_enum_frame_size, + .get_fmt = vsp1_subdev_get_pad_format, + .set_fmt = iif_set_format, +}; + +static const struct v4l2_subdev_ops iif_ops = { + .pad = &iif_pad_ops, +}; + +/* ----------------------------------------------------------------------------- + * VSP1 Entity Operations + */ + +static void iif_configure_stream(struct vsp1_entity *entity, + struct v4l2_subdev_state *state, + struct vsp1_pipeline *pipe, + struct vsp1_dl_list *dl, + struct vsp1_dl_body *dlb) +{ + vsp1_iif_write(dlb, VI6_IIF_CTRL, VI6_IIF_CTRL_CTRL); +} + +static const struct vsp1_entity_operations iif_entity_ops = { + .configure_stream = iif_configure_stream, +}; + +/* ----------------------------------------------------------------------------- + * Initialization and Cleanup + */ + +struct vsp1_iif *vsp1_iif_create(struct vsp1_device *vsp1) +{ + struct vsp1_iif *iif; + int ret; + + iif = devm_kzalloc(vsp1->dev, sizeof(*iif), GFP_KERNEL); + if (!iif) + return ERR_PTR(-ENOMEM); + + iif->entity.ops = &iif_entity_ops; + iif->entity.type = VSP1_ENTITY_IIF; + + /* + * The IIF is never exposed to userspace, but media entity registration + * requires a function to be set. Use PROC_VIDEO_PIXEL_FORMATTER just to + * avoid triggering a WARN_ON(), the value won't be seen anywhere. + */ + ret = vsp1_entity_init(vsp1, &iif->entity, "iif", 3, &iif_ops, + MEDIA_ENT_F_PROC_VIDEO_PIXEL_FORMATTER); + if (ret < 0) + return ERR_PTR(ret); + + return iif; +} diff --git a/drivers/media/platform/renesas/vsp1/vsp1_iif.h b/drivers/media/platform/renesas/vsp1/vsp1_iif.h new file mode 100644 index 000000000000..165996a822c1 --- /dev/null +++ b/drivers/media/platform/renesas/vsp1/vsp1_iif.h @@ -0,0 +1,26 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * vsp1_iif.h -- R-Car VSP1 IIF (ISP Interface) + * + * Copyright (C) 2025 Ideas On Board Oy + * Copyright (C) 2025 Renesas Corporation + */ +#ifndef __VSP1_IIF_H__ +#define __VSP1_IIF_H__ + +#include + +#include "vsp1_entity.h" + +struct vsp1_iif { + struct vsp1_entity entity; +}; + +static inline struct vsp1_iif *to_iif(struct v4l2_subdev *subdev) +{ + return container_of(subdev, struct vsp1_iif, entity.subdev); +} + +struct vsp1_iif *vsp1_iif_create(struct vsp1_device *vsp1); + +#endif /* __VSP1_IIF_H__ */ diff --git a/drivers/media/platform/renesas/vsp1/vsp1_pipe.c b/drivers/media/platform/renesas/vsp1/vsp1_pipe.c index bb0739f684f3..8e9be3ec1b4d 100644 --- a/drivers/media/platform/renesas/vsp1/vsp1_pipe.c +++ b/drivers/media/platform/renesas/vsp1/vsp1_pipe.c @@ -286,6 +286,7 @@ void vsp1_pipeline_reset(struct vsp1_pipeline *pipe) pipe->brx = NULL; pipe->hgo = NULL; pipe->hgt = NULL; + pipe->iif = NULL; pipe->lif = NULL; pipe->uds = NULL; } diff --git a/drivers/media/platform/renesas/vsp1/vsp1_pipe.h b/drivers/media/platform/renesas/vsp1/vsp1_pipe.h index 1ba7bdbad5a8..1655a820da10 100644 --- a/drivers/media/platform/renesas/vsp1/vsp1_pipe.h +++ b/drivers/media/platform/renesas/vsp1/vsp1_pipe.h @@ -119,6 +119,7 @@ struct vsp1_pipeline { struct vsp1_entity *brx; struct vsp1_entity *hgo; struct vsp1_entity *hgt; + struct vsp1_entity *iif; struct vsp1_entity *lif; struct vsp1_entity *uds; struct vsp1_entity *uds_input; diff --git a/drivers/media/platform/renesas/vsp1/vsp1_regs.h b/drivers/media/platform/renesas/vsp1/vsp1_regs.h index 7eca82e0ba7e..86e47c2d991f 100644 --- a/drivers/media/platform/renesas/vsp1/vsp1_regs.h +++ b/drivers/media/platform/renesas/vsp1/vsp1_regs.h @@ -252,6 +252,13 @@ #define VI6_RPF_BRDITH_CTRL_ODE BIT(8) #define VI6_RPF_BRDITH_CTRL_CBRM BIT(0) +/* ----------------------------------------------------------------------------- + * IIF Control Registers + */ + +#define VI6_IIF_CTRL 0x0608 +#define VI6_IIF_CTRL_CTRL 0x13 + /* ----------------------------------------------------------------------------- * WPF Control Registers */ @@ -388,6 +395,7 @@ #define VI6_DPR_HST_ROUTE 0x2044 #define VI6_DPR_HSI_ROUTE 0x2048 #define VI6_DPR_BRU_ROUTE 0x204c +#define VI6_DPR_ROUTE_IIFSEL BIT(28) #define VI6_DPR_ILV_BRS_ROUTE 0x2050 #define VI6_DPR_ROUTE_BRSSEL BIT(28) #define VI6_DPR_ROUTE_FXA_MASK (0xff << 16) -- 2.51.0 From 15b3c76da9e19b24a69c603ec51a965c5be91e26 Mon Sep 17 00:00:00 2001 From: Jacopo Mondi Date: Tue, 1 Apr 2025 16:22:02 +0200 Subject: [PATCH 16/16] media: renesas: vsp1: dl: Use singleshot DL for VSPX MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit The vsp1_dl library allows to program a display list and feed it continuously to the VSP2. As an alternative operation mode, the library allows to program the VSP2 in 'single shot' mode, where a display list is submitted to the VSP on request only. Currently the 'single shot' mode is only available when the VSP2 is controlled by userspace, while it works in continuous mode when driven by DRM, as frames have to be submitted to the display continuously. For the VSPX use case, where there is no uapi support, we should however work in single-shot mode as the ISP driver programs the VSPX on request. Initialize the display lists in single shot mode in case the VSP1 is controlled by userspace or in case the pipeline features an IIF entity, as in the VSPX case. Reviewed-by: Laurent Pinchart Reviewed-by: Niklas Söderlund Tested-by: Niklas Söderlund Signed-off-by: Jacopo Mondi Link: https://lore.kernel.org/r/20250401-v4h-iif-v7-2-cc547c0bddd5@ideasonboard.com Signed-off-by: Laurent Pinchart Signed-off-by: Hans Verkuil --- drivers/media/platform/renesas/vsp1/vsp1_dl.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/media/platform/renesas/vsp1/vsp1_dl.c b/drivers/media/platform/renesas/vsp1/vsp1_dl.c index ad3fa1c9cc73..bb8228b19824 100644 --- a/drivers/media/platform/renesas/vsp1/vsp1_dl.c +++ b/drivers/media/platform/renesas/vsp1/vsp1_dl.c @@ -1099,7 +1099,12 @@ struct vsp1_dl_manager *vsp1_dlm_create(struct vsp1_device *vsp1, return NULL; dlm->index = index; - dlm->singleshot = vsp1->info->uapi; + /* + * uapi = single shot mode; + * DRM = continuous mode; + * VSPX = single shot mode; + */ + dlm->singleshot = vsp1->info->uapi || vsp1->iif; dlm->vsp1 = vsp1; spin_lock_init(&dlm->lock); -- 2.51.0