From: Vedang Nagar <quic_vnagar@xxxxxxxxxxx> Implement s_ctrl and g_volatile_ctrl ctrl ops. Introduce platform specific driver and firmware capabilities. Capabilities are set of video specifications and features supported by a specific platform (SOC). Each capability is defined with min, max, range, default value and corresponding HFI. Signed-off-by: Vedang Nagar <quic_vnagar@xxxxxxxxxxx> Signed-off-by: Dikshita Agarwal <quic_dikshita@xxxxxxxxxxx> --- drivers/media/platform/qcom/iris/Makefile | 1 + drivers/media/platform/qcom/iris/iris_buffer.c | 3 +- drivers/media/platform/qcom/iris/iris_core.h | 2 + drivers/media/platform/qcom/iris/iris_ctrls.c | 194 +++++++++++++++++++++ drivers/media/platform/qcom/iris/iris_ctrls.h | 15 ++ .../platform/qcom/iris/iris_hfi_gen1_defines.h | 4 + .../platform/qcom/iris/iris_hfi_gen2_command.c | 1 + .../platform/qcom/iris/iris_hfi_gen2_defines.h | 9 + drivers/media/platform/qcom/iris/iris_instance.h | 6 + .../platform/qcom/iris/iris_platform_common.h | 71 ++++++++ .../platform/qcom/iris/iris_platform_sm8250.c | 56 ++++++ .../platform/qcom/iris/iris_platform_sm8550.c | 138 +++++++++++++++ drivers/media/platform/qcom/iris/iris_probe.c | 7 + drivers/media/platform/qcom/iris/iris_vdec.c | 24 ++- drivers/media/platform/qcom/iris/iris_vdec.h | 2 +- drivers/media/platform/qcom/iris/iris_vidc.c | 16 +- 16 files changed, 536 insertions(+), 13 deletions(-) diff --git a/drivers/media/platform/qcom/iris/Makefile b/drivers/media/platform/qcom/iris/Makefile index 9c50e29db41e..a746681e03cd 100644 --- a/drivers/media/platform/qcom/iris/Makefile +++ b/drivers/media/platform/qcom/iris/Makefile @@ -1,5 +1,6 @@ iris-objs += iris_buffer.o \ iris_core.o \ + iris_ctrls.o \ iris_firmware.o \ iris_hfi_common.o \ iris_hfi_gen1_command.o \ diff --git a/drivers/media/platform/qcom/iris/iris_buffer.c b/drivers/media/platform/qcom/iris/iris_buffer.c index a1017ceede7d..652117a19b45 100644 --- a/drivers/media/platform/qcom/iris/iris_buffer.c +++ b/drivers/media/platform/qcom/iris/iris_buffer.c @@ -12,7 +12,6 @@ #define MAX_WIDTH 4096 #define MAX_HEIGHT 2304 #define NUM_MBS_4K (DIV_ROUND_UP(MAX_WIDTH, 16) * DIV_ROUND_UP(MAX_HEIGHT, 16)) -#define BASE_RES_MB_MAX 138240 /* * NV12: @@ -74,7 +73,7 @@ static u32 iris_input_buffer_size(struct iris_inst *inst) num_mbs = iris_get_mbpf(inst); if (num_mbs > NUM_MBS_4K) { div_factor = 4; - base_res_mbs = BASE_RES_MB_MAX; + base_res_mbs = inst->driver_cap[MBPF].value; } else { base_res_mbs = NUM_MBS_4K; div_factor = 2; diff --git a/drivers/media/platform/qcom/iris/iris_core.h b/drivers/media/platform/qcom/iris/iris_core.h index 1f6eca31928d..657d26a0fa2e 100644 --- a/drivers/media/platform/qcom/iris/iris_core.h +++ b/drivers/media/platform/qcom/iris/iris_core.h @@ -58,6 +58,7 @@ * @intr_status: interrupt status * @sys_error_handler: a delayed work for handling system fatal error * @instances: a list_head of all instances + * @inst_fw_cap: an array of supported instance capabilities */ struct iris_core { @@ -97,6 +98,7 @@ struct iris_core { u32 intr_status; struct delayed_work sys_error_handler; struct list_head instances; + struct platform_inst_fw_cap inst_fw_cap[INST_FW_CAP_MAX]; }; int iris_core_init(struct iris_core *core); diff --git a/drivers/media/platform/qcom/iris/iris_ctrls.c b/drivers/media/platform/qcom/iris/iris_ctrls.c new file mode 100644 index 000000000000..868306d68a87 --- /dev/null +++ b/drivers/media/platform/qcom/iris/iris_ctrls.c @@ -0,0 +1,194 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved. + */ + +#include "iris_ctrls.h" +#include "iris_instance.h" + +static bool iris_valid_cap_id(enum platform_inst_fw_cap_type cap_id) +{ + return cap_id >= 1 && cap_id < INST_FW_CAP_MAX; +} + +static enum platform_inst_fw_cap_type iris_get_cap_id(u32 id) +{ + switch (id) { + case V4L2_CID_MPEG_VIDEO_DECODER_MPEG4_DEBLOCK_FILTER: + return DEBLOCK; + case V4L2_CID_MPEG_VIDEO_H264_PROFILE: + return PROFILE; + case V4L2_CID_MPEG_VIDEO_H264_LEVEL: + return LEVEL; + default: + return INST_FW_CAP_MAX; + } +} + +static u32 iris_get_v4l2_id(enum platform_inst_fw_cap_type cap_id) +{ + if (!iris_valid_cap_id(cap_id)) + return 0; + + switch (cap_id) { + case DEBLOCK: + return V4L2_CID_MPEG_VIDEO_DECODER_MPEG4_DEBLOCK_FILTER; + case PROFILE: + return V4L2_CID_MPEG_VIDEO_H264_PROFILE; + case LEVEL: + return V4L2_CID_MPEG_VIDEO_H264_LEVEL; + default: + return 0; + } +} + +static int iris_vdec_op_g_volatile_ctrl(struct v4l2_ctrl *ctrl) +{ + enum platform_inst_fw_cap_type cap_id; + struct iris_inst *inst = NULL; + + inst = container_of(ctrl->handler, struct iris_inst, ctrl_handler); + switch (ctrl->id) { + case V4L2_CID_MIN_BUFFERS_FOR_CAPTURE: + ctrl->val = inst->buffers[BUF_OUTPUT].min_count; + break; + case V4L2_CID_MIN_BUFFERS_FOR_OUTPUT: + ctrl->val = inst->buffers[BUF_INPUT].min_count; + break; + default: + cap_id = iris_get_cap_id(ctrl->id); + if (iris_valid_cap_id(cap_id)) + ctrl->val = inst->fw_cap[cap_id].value; + else + return -EINVAL; + } + + return 0; +} + +static int iris_vdec_op_s_ctrl(struct v4l2_ctrl *ctrl) +{ + enum platform_inst_fw_cap_type cap_id; + struct platform_inst_fw_cap *cap; + struct iris_inst *inst; + + inst = container_of(ctrl->handler, struct iris_inst, ctrl_handler); + cap = &inst->fw_cap[0]; + + cap_id = iris_get_cap_id(ctrl->id); + if (!iris_valid_cap_id(cap_id)) + return -EINVAL; + + cap[cap_id].flags |= CAP_FLAG_CLIENT_SET; + + inst->fw_cap[cap_id].value = ctrl->val; + + return 0; +} + +static const struct v4l2_ctrl_ops iris_ctrl_ops = { + .s_ctrl = iris_vdec_op_s_ctrl, + .g_volatile_ctrl = iris_vdec_op_g_volatile_ctrl, +}; + +int iris_ctrls_init(struct iris_inst *inst) +{ + struct platform_inst_fw_cap *cap; + int num_ctrls = 0, ctrl_idx = 0; + int idx = 0, ret; + u32 v4l2_id; + + cap = &inst->fw_cap[0]; + + for (idx = 1; idx < INST_FW_CAP_MAX; idx++) { + if (iris_get_v4l2_id(cap[idx].cap_id)) + num_ctrls++; + } + if (!num_ctrls) + return -EINVAL; + + ret = v4l2_ctrl_handler_init(&inst->ctrl_handler, num_ctrls); + if (ret) + return ret; + + for (idx = 1; idx < INST_FW_CAP_MAX; idx++) { + struct v4l2_ctrl *ctrl; + + v4l2_id = iris_get_v4l2_id(cap[idx].cap_id); + if (!v4l2_id) + continue; + + if (ctrl_idx >= num_ctrls) { + ret = -EINVAL; + goto error; + } + + if (cap[idx].flags & CAP_FLAG_MENU) { + ctrl = v4l2_ctrl_new_std_menu(&inst->ctrl_handler, + &iris_ctrl_ops, + v4l2_id, + cap[idx].max, + ~(cap[idx].step_or_mask), + cap[idx].value); + } else { + ctrl = v4l2_ctrl_new_std(&inst->ctrl_handler, + &iris_ctrl_ops, + v4l2_id, + cap[idx].min, + cap[idx].max, + cap[idx].step_or_mask, + cap[idx].value); + } + if (!ctrl) { + ret = -EINVAL; + goto error; + } + + ret = inst->ctrl_handler.error; + if (ret) + goto error; + + if ((cap[idx].flags & CAP_FLAG_VOLATILE) || + (ctrl->id == V4L2_CID_MIN_BUFFERS_FOR_CAPTURE || + ctrl->id == V4L2_CID_MIN_BUFFERS_FOR_OUTPUT)) + ctrl->flags |= V4L2_CTRL_FLAG_VOLATILE; + + ctrl->flags |= V4L2_CTRL_FLAG_EXECUTE_ON_WRITE; + ctrl_idx++; + } + + return 0; +error: + v4l2_ctrl_handler_free(&inst->ctrl_handler); + + return ret; +} + +int iris_session_init_caps(struct iris_core *core) +{ + struct platform_inst_fw_cap *inst_plat_cap_data; + int i, num_inst_cap; + u32 cap_id; + + inst_plat_cap_data = core->iris_platform_data->inst_fw_cap_data; + if (!inst_plat_cap_data) + return -EINVAL; + + num_inst_cap = core->iris_platform_data->inst_fw_cap_data_size; + + for (i = 0; i < num_inst_cap && i < INST_FW_CAP_MAX - 1; i++) { + cap_id = inst_plat_cap_data[i].cap_id; + if (!iris_valid_cap_id(cap_id)) + continue; + + core->inst_fw_cap[cap_id].cap_id = inst_plat_cap_data[i].cap_id; + core->inst_fw_cap[cap_id].min = inst_plat_cap_data[i].min; + core->inst_fw_cap[cap_id].max = inst_plat_cap_data[i].max; + core->inst_fw_cap[cap_id].step_or_mask = inst_plat_cap_data[i].step_or_mask; + core->inst_fw_cap[cap_id].value = inst_plat_cap_data[i].value; + core->inst_fw_cap[cap_id].flags = inst_plat_cap_data[i].flags; + core->inst_fw_cap[cap_id].hfi_id = inst_plat_cap_data[i].hfi_id; + } + + return 0; +} diff --git a/drivers/media/platform/qcom/iris/iris_ctrls.h b/drivers/media/platform/qcom/iris/iris_ctrls.h new file mode 100644 index 000000000000..46e1da847aa8 --- /dev/null +++ b/drivers/media/platform/qcom/iris/iris_ctrls.h @@ -0,0 +1,15 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved. + */ + +#ifndef _IRIS_CTRLS_H_ +#define _IRIS_CTRLS_H_ + +struct iris_core; +struct iris_inst; + +int iris_ctrls_init(struct iris_inst *inst); +int iris_session_init_caps(struct iris_core *core); + +#endif diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen1_defines.h b/drivers/media/platform/qcom/iris/iris_hfi_gen1_defines.h index da52e497b74a..9dc050063924 100644 --- a/drivers/media/platform/qcom/iris/iris_hfi_gen1_defines.h +++ b/drivers/media/platform/qcom/iris/iris_hfi_gen1_defines.h @@ -31,9 +31,13 @@ #define HFI_EVENT_SYS_ERROR 0x1 #define HFI_EVENT_SESSION_ERROR 0x2 +#define HFI_PROPERTY_CONFIG_VDEC_POST_LOOP_DEBLOCKER 0x1200001 + #define HFI_PROPERTY_SYS_CODEC_POWER_PLANE_CTRL 0x5 #define HFI_PROPERTY_SYS_IMAGE_VERSION 0x6 +#define HFI_PROPERTY_PARAM_WORK_MODE 0x1015 +#define HFI_PROPERTY_PARAM_WORK_ROUTE 0x1017 #define HFI_MSG_SYS_INIT 0x20001 #define HFI_MSG_SYS_SESSION_INIT 0x20006 #define HFI_MSG_SYS_SESSION_END 0x20007 diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen2_command.c b/drivers/media/platform/qcom/iris/iris_hfi_gen2_command.c index a74114b0761a..6ad2ca7be0f0 100644 --- a/drivers/media/platform/qcom/iris/iris_hfi_gen2_command.c +++ b/drivers/media/platform/qcom/iris/iris_hfi_gen2_command.c @@ -108,6 +108,7 @@ static int iris_hfi_gen2_session_set_default_header(struct iris_inst *inst) struct iris_inst_hfi_gen2 *inst_hfi_gen2 = to_iris_inst_hfi_gen2(inst); u32 default_header = false; + default_header = inst->fw_cap[DEFAULT_HEADER].value; iris_hfi_gen2_packet_session_property(inst, HFI_PROP_DEC_DEFAULT_HEADER, HFI_HOST_FLAGS_NONE, diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen2_defines.h b/drivers/media/platform/qcom/iris/iris_hfi_gen2_defines.h index 18cc9365ab75..401df7b4e976 100644 --- a/drivers/media/platform/qcom/iris/iris_hfi_gen2_defines.h +++ b/drivers/media/platform/qcom/iris/iris_hfi_gen2_defines.h @@ -28,7 +28,16 @@ #define HFI_PROP_UBWC_BANK_SWZL_LEVEL3 0x03000008 #define HFI_PROP_UBWC_BANK_SPREADING 0x03000009 #define HFI_PROP_CODEC 0x03000100 +#define HFI_PROP_PROFILE 0x03000107 +#define HFI_PROP_LEVEL 0x03000108 +#define HFI_PROP_STAGE 0x0300010a +#define HFI_PROP_PIPE 0x0300010b +#define HFI_PROP_LUMA_CHROMA_BIT_DEPTH 0x0300010f +#define HFI_PROP_CODED_FRAMES 0x03000120 +#define HFI_PROP_BUFFER_HOST_MAX_COUNT 0x03000123 +#define HFI_PROP_PIC_ORDER_CNT_TYPE 0x03000128 #define HFI_PROP_DEC_DEFAULT_HEADER 0x03000168 +#define HFI_PROP_DEC_START_FROM_RAP_FRAME 0x03000169 #define HFI_PROP_END 0x03FFFFFF #define HFI_SESSION_ERROR_BEGIN 0x04000000 diff --git a/drivers/media/platform/qcom/iris/iris_instance.h b/drivers/media/platform/qcom/iris/iris_instance.h index d28b8fd7ec2f..2429b9860789 100644 --- a/drivers/media/platform/qcom/iris/iris_instance.h +++ b/drivers/media/platform/qcom/iris/iris_instance.h @@ -23,8 +23,11 @@ * @fh: reference of v4l2 file handler * @fmt_src: structure of v4l2_format for source * @fmt_dst: structure of v4l2_format for destination + * @ctrl_handler: reference of v4l2 ctrl handler * @crop: structure of crop info * @completions: structure of signal completions + * @driver_cap: array of supported instance driver capabilities + * @fw_cap: array of supported instance firmware capabilities * @buffers: array of different iris buffers * @fw_min_count: minimnum count of buffers needed by fw * @once_per_session_set: boolean to set once per session property @@ -42,8 +45,11 @@ struct iris_inst { struct v4l2_fh fh; struct v4l2_format *fmt_src; struct v4l2_format *fmt_dst; + struct v4l2_ctrl_handler ctrl_handler; struct iris_hfi_rect_desc crop; struct completion completion; + struct platform_inst_driver_cap driver_cap[INST_DRIVER_CAP_MAX]; + struct platform_inst_fw_cap fw_cap[INST_FW_CAP_MAX]; struct iris_buffers buffers[BUF_TYPE_MAX]; u32 fw_min_count; bool once_per_session_set; diff --git a/drivers/media/platform/qcom/iris/iris_platform_common.h b/drivers/media/platform/qcom/iris/iris_platform_common.h index 754cccc638a5..2935b769abb7 100644 --- a/drivers/media/platform/qcom/iris/iris_platform_common.h +++ b/drivers/media/platform/qcom/iris/iris_platform_common.h @@ -10,6 +10,23 @@ #define HW_RESPONSE_TIMEOUT_VALUE (1000) /* milliseconds */ #define AUTOSUSPEND_DELAY_VALUE (HW_RESPONSE_TIMEOUT_VALUE + 500) /* milliseconds */ +#define REGISTER_BIT_DEPTH(luma, chroma) ((luma) << 16 | (chroma)) +#define BIT_DEPTH_8 REGISTER_BIT_DEPTH(8, 8) +#define CODED_FRAMES_PROGRESSIVE 0x0 +#define DEFAULT_MAX_HOST_BUF_COUNT 64 +#define DEFAULT_MAX_HOST_BURST_BUF_COUNT 256 + +enum stage_type { + STAGE_1 = 1, + STAGE_2 = 2, +}; + +enum pipe_type { + PIPE_1 = 1, + PIPE_2 = 2, + PIPE_4 = 4, +}; + extern struct iris_platform_data sm8550_data; extern struct iris_platform_data sm8250_data; @@ -41,6 +58,56 @@ struct ubwc_config_data { u32 bank_spreading; }; +enum platform_inst_driver_cap_type { + FRAME_WIDTH = 1, + FRAME_HEIGHT, + MBPF, + INST_DRIVER_CAP_MAX, +}; + +enum platform_inst_fw_cap_type { + PROFILE = 1, + LEVEL, + INPUT_BUF_HOST_MAX_COUNT, + STAGE, + PIPE, + POC, + CODED_FRAMES, + BIT_DEPTH, + DEFAULT_HEADER, + RAP_FRAME, + DEBLOCK, + INST_FW_CAP_MAX, +}; + +enum platform_inst_cap_flags { + CAP_FLAG_NONE = 0, + CAP_FLAG_DYNAMIC_ALLOWED = BIT(0), + CAP_FLAG_MENU = BIT(1), + CAP_FLAG_INPUT_PORT = BIT(2), + CAP_FLAG_OUTPUT_PORT = BIT(3), + CAP_FLAG_CLIENT_SET = BIT(4), + CAP_FLAG_BITMASK = BIT(5), + CAP_FLAG_VOLATILE = BIT(6), +}; + +struct platform_inst_driver_cap { + enum platform_inst_driver_cap_type cap_id; + u32 min; + u32 max; + u32 value; +}; + +struct platform_inst_fw_cap { + enum platform_inst_fw_cap_type cap_id; + s64 min; + s64 max; + s64 step_or_mask; + s64 value; + u32 hfi_id; + enum platform_inst_cap_flags flags; +}; + struct iris_core_power { u64 clk_freq; u64 icc_bw; @@ -70,6 +137,10 @@ struct iris_platform_data { u64 dma_mask; const char *fwname; u32 pas_id; + struct platform_inst_driver_cap *inst_driver_cap_data; + u32 inst_driver_cap_data_size; + struct platform_inst_fw_cap *inst_fw_cap_data; + u32 inst_fw_cap_data_size; struct tz_cp_config *tz_cp_config_data; u32 core_arch; u32 hw_response_timeout; diff --git a/drivers/media/platform/qcom/iris/iris_platform_sm8250.c b/drivers/media/platform/qcom/iris/iris_platform_sm8250.c index cbc5e84641f6..ac9f720aff8e 100644 --- a/drivers/media/platform/qcom/iris/iris_platform_sm8250.c +++ b/drivers/media/platform/qcom/iris/iris_platform_sm8250.c @@ -7,8 +7,60 @@ #include "iris_platform_common.h" #include "iris_resources.h" #include "iris_hfi_gen1.h" +#include "iris_hfi_gen1_defines.h" #include "iris_vpu_common.h" +static struct platform_inst_driver_cap instance_driver_cap_data_sm8250[] = { + { + .cap_id = FRAME_WIDTH, + .min = 128, + .max = 8192, + .value = 1920, + }, + { + .cap_id = FRAME_HEIGHT, + .min = 128, + .max = 8192, + .value = 1920, + }, + { + .cap_id = MBPF, + .min = 64, + .max = 138240, + .value = 138240, + }, +}; + +static struct platform_inst_fw_cap instance_fw_cap_data_sm8250[] = { + { + .cap_id = PIPE, + .min = PIPE_1, + .max = PIPE_4, + .step_or_mask = 1, + .value = PIPE_4, + .hfi_id = HFI_PROPERTY_PARAM_WORK_ROUTE, + .flags = CAP_FLAG_NONE, + }, + { + .cap_id = STAGE, + .min = STAGE_1, + .max = STAGE_2, + .step_or_mask = 1, + .value = STAGE_2, + .hfi_id = HFI_PROPERTY_PARAM_WORK_MODE, + .flags = CAP_FLAG_NONE, + }, + { + .cap_id = DEBLOCK, + .min = 0, + .max = 1, + .step_or_mask = 1, + .value = 0, + .hfi_id = HFI_PROPERTY_CONFIG_VDEC_POST_LOOP_DEBLOCKER, + .flags = CAP_FLAG_NONE, + }, +}; + static void iris_set_sm8250_preset_registers(struct iris_core *core) { writel(0x0, core->reg_base + 0xB0088); @@ -57,6 +109,10 @@ struct iris_platform_data sm8250_data = { .dma_mask = GENMASK(31, 29) - 1, .fwname = "qcom/vpu/vpu20_p4.mbn", .pas_id = IRIS_PAS_ID, + .inst_driver_cap_data = instance_driver_cap_data_sm8250, + .inst_driver_cap_data_size = ARRAY_SIZE(instance_driver_cap_data_sm8250), + .inst_fw_cap_data = instance_fw_cap_data_sm8250, + .inst_fw_cap_data_size = ARRAY_SIZE(instance_fw_cap_data_sm8250), .tz_cp_config_data = &tz_cp_config_sm8250, .hw_response_timeout = HW_RESPONSE_TIMEOUT_VALUE, .num_vpp_pipe = 4, diff --git a/drivers/media/platform/qcom/iris/iris_platform_sm8550.c b/drivers/media/platform/qcom/iris/iris_platform_sm8550.c index 57fe9986b8cf..42e44b454896 100644 --- a/drivers/media/platform/qcom/iris/iris_platform_sm8550.c +++ b/drivers/media/platform/qcom/iris/iris_platform_sm8550.c @@ -5,12 +5,146 @@ #include "iris_core.h" #include "iris_hfi_gen2.h" +#include "iris_hfi_gen2_defines.h" #include "iris_platform_common.h" #include "iris_resources.h" #include "iris_vpu_common.h" #define VIDEO_ARCH_LX 1 +static struct platform_inst_driver_cap instance_driver_cap_data_sm8550[] = { + { + .cap_id = FRAME_WIDTH, + .min = 96, + .max = 8192, + .value = 1920, + }, + { + .cap_id = FRAME_HEIGHT, + .min = 96, + .max = 8192, + .value = 1920, + }, + { + .cap_id = MBPF, + .min = 36, + .max = 138240, + .value = 138240, + }, +}; + +static struct platform_inst_fw_cap instance_fw_cap_data_sm8550[] = { + { + .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, + }, + { + .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, + }, + { + .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, + }, + { + .cap_id = STAGE, + .min = STAGE_1, + .max = STAGE_2, + .step_or_mask = 1, + .value = STAGE_2, + .hfi_id = HFI_PROP_STAGE, + .flags = CAP_FLAG_NONE, + }, + { + .cap_id = PIPE, + .min = PIPE_1, + .max = PIPE_4, + .step_or_mask = 1, + .value = PIPE_4, + .hfi_id = HFI_PROP_PIPE, + .flags = CAP_FLAG_NONE, + }, + { + .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 = DEFAULT_HEADER, + .min = 0, + .max = 1, + .step_or_mask = 1, + .value = 0, + .hfi_id = HFI_PROP_DEC_DEFAULT_HEADER, + }, + { + .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, + }, +}; + static void iris_set_sm8550_preset_registers(struct iris_core *core) { writel(0x0, core->reg_base + 0xB0088); @@ -69,6 +203,10 @@ struct iris_platform_data sm8550_data = { .dma_mask = GENMASK(31, 29) - 1, .fwname = "qcom/vpu/vpu30_p4.mbn", .pas_id = IRIS_PAS_ID, + .inst_driver_cap_data = instance_driver_cap_data_sm8550, + .inst_driver_cap_data_size = ARRAY_SIZE(instance_driver_cap_data_sm8550), + .inst_fw_cap_data = instance_fw_cap_data_sm8550, + .inst_fw_cap_data_size = ARRAY_SIZE(instance_fw_cap_data_sm8550), .tz_cp_config_data = &tz_cp_config_sm8550, .core_arch = VIDEO_ARCH_LX, .hw_response_timeout = HW_RESPONSE_TIMEOUT_VALUE, diff --git a/drivers/media/platform/qcom/iris/iris_probe.c b/drivers/media/platform/qcom/iris/iris_probe.c index 5d492b3919cc..319851c50ccd 100644 --- a/drivers/media/platform/qcom/iris/iris_probe.c +++ b/drivers/media/platform/qcom/iris/iris_probe.c @@ -7,6 +7,7 @@ #include <linux/pm_runtime.h> #include "iris_core.h" +#include "iris_ctrls.h" #include "iris_vidc.h" static inline int iris_init_isr(struct iris_core *core) @@ -145,6 +146,12 @@ static int iris_probe(struct platform_device *pdev) goto err_runtime_disable; } + ret = iris_session_init_caps(core); + if (ret) { + dev_err_probe(core->dev, ret, "init inst caps failed\n"); + goto err_runtime_disable; + } + ret = v4l2_device_register(dev, &core->v4l2_dev); if (ret) goto err_runtime_disable; diff --git a/drivers/media/platform/qcom/iris/iris_vdec.c b/drivers/media/platform/qcom/iris/iris_vdec.c index 29c7e229c148..f82a337b8f43 100644 --- a/drivers/media/platform/qcom/iris/iris_vdec.c +++ b/drivers/media/platform/qcom/iris/iris_vdec.c @@ -7,6 +7,7 @@ #include <media/v4l2-mem2mem.h> #include "iris_buffer.h" +#include "iris_ctrls.h" #include "iris_instance.h" #include "iris_vdec.h" #include "iris_vpu_buffer.h" @@ -16,9 +17,13 @@ #define DEFAULT_CODEC_ALIGNMENT 16 #define MAX_EVENTS 30 -void iris_vdec_inst_init(struct iris_inst *inst) +int iris_vdec_inst_init(struct iris_inst *inst) { + struct platform_inst_driver_cap *inst_plat_cap_data; + struct iris_core *core = inst->core; struct v4l2_format *f; + int i, num_inst_cap; + u32 cap_id; inst->fmt_src = kzalloc(sizeof(*inst->fmt_src), GFP_KERNEL); inst->fmt_dst = kzalloc(sizeof(*inst->fmt_dst), GFP_KERNEL); @@ -54,6 +59,23 @@ void iris_vdec_inst_init(struct iris_inst *inst) inst->buffers[BUF_OUTPUT].min_count = iris_vpu_buf_count(inst, BUF_OUTPUT); inst->buffers[BUF_OUTPUT].actual_count = inst->buffers[BUF_OUTPUT].min_count; inst->buffers[BUF_OUTPUT].size = f->fmt.pix_mp.plane_fmt[0].sizeimage; + + memcpy(&inst->fw_cap[0], &core->inst_fw_cap[0], + INST_FW_CAP_MAX * sizeof(struct platform_inst_fw_cap)); + + inst_plat_cap_data = core->iris_platform_data->inst_driver_cap_data; + num_inst_cap = core->iris_platform_data->inst_driver_cap_data_size; + + for (i = 0; i < num_inst_cap && i < INST_DRIVER_CAP_MAX - 1; i++) { + cap_id = inst_plat_cap_data[i].cap_id; + + inst->driver_cap[cap_id].cap_id = inst_plat_cap_data[i].cap_id; + inst->driver_cap[cap_id].min = inst_plat_cap_data[i].min; + inst->driver_cap[cap_id].max = inst_plat_cap_data[i].max; + inst->driver_cap[cap_id].value = inst_plat_cap_data[i].value; + } + + return iris_ctrls_init(inst); } void iris_vdec_inst_deinit(struct iris_inst *inst) diff --git a/drivers/media/platform/qcom/iris/iris_vdec.h b/drivers/media/platform/qcom/iris/iris_vdec.h index 707fff34bf4d..d7b8a0ad6fa8 100644 --- a/drivers/media/platform/qcom/iris/iris_vdec.h +++ b/drivers/media/platform/qcom/iris/iris_vdec.h @@ -8,7 +8,7 @@ struct iris_inst; -void iris_vdec_inst_init(struct iris_inst *inst); +int iris_vdec_inst_init(struct iris_inst *inst); void iris_vdec_inst_deinit(struct iris_inst *inst); int iris_vdec_enum_fmt(struct iris_inst *inst, struct v4l2_fmtdesc *f); int iris_vdec_try_fmt(struct iris_inst *inst, struct v4l2_format *f); diff --git a/drivers/media/platform/qcom/iris/iris_vidc.c b/drivers/media/platform/qcom/iris/iris_vidc.c index 141704512b3c..7d5da30cb1d1 100644 --- a/drivers/media/platform/qcom/iris/iris_vidc.c +++ b/drivers/media/platform/qcom/iris/iris_vidc.c @@ -16,10 +16,6 @@ #define IRIS_DRV_NAME "iris_driver" #define IRIS_BUS_NAME "platform:iris_icc" -#define MIN_FRAME_WIDTH 128 -#define MAX_FRAME_WIDTH 8192 -#define MIN_FRAME_HEIGHT 128 -#define MAX_FRAME_HEIGHT 8192 #define STEP_WIDTH 1 #define STEP_HEIGHT 1 @@ -31,6 +27,7 @@ static int iris_v4l2_fh_init(struct iris_inst *inst) return -EINVAL; v4l2_fh_init(&inst->fh, core->vdev_dec); + inst->fh.ctrl_handler = &inst->ctrl_handler; v4l2_fh_add(&inst->fh); return 0; @@ -188,7 +185,7 @@ int iris_open(struct file *filp) goto fail_m2m_release; } - iris_vdec_inst_init(inst); + ret = iris_vdec_inst_init(inst); if (ret) goto fail_m2m_ctx_release; @@ -244,6 +241,7 @@ int iris_close(struct file *filp) if (!inst) return -EINVAL; + v4l2_ctrl_handler_free(&inst->ctrl_handler); v4l2_m2m_ctx_release(inst->m2m_ctx); v4l2_m2m_release(inst->m2m_dev); mutex_lock(&inst->lock); @@ -351,11 +349,11 @@ static int iris_enum_framesizes(struct file *filp, void *fh, } fsize->type = V4L2_FRMSIZE_TYPE_STEPWISE; - fsize->stepwise.min_width = MIN_FRAME_WIDTH; - fsize->stepwise.max_width = MAX_FRAME_WIDTH; + fsize->stepwise.min_width = inst->driver_cap[FRAME_WIDTH].min; + fsize->stepwise.max_width = inst->driver_cap[FRAME_WIDTH].max; fsize->stepwise.step_width = STEP_WIDTH; - fsize->stepwise.min_height = MIN_FRAME_HEIGHT; - fsize->stepwise.max_height = MAX_FRAME_HEIGHT; + fsize->stepwise.min_height = inst->driver_cap[FRAME_HEIGHT].min; + fsize->stepwise.max_height = inst->driver_cap[FRAME_HEIGHT].max; fsize->stepwise.step_height = STEP_HEIGHT; unlock: -- 2.34.1