diff mbox series

[v3,16/29] media: iris: implement iris v4l2_ctrl_ops and prepare capabilities

Message ID 20240827-iris_v3-v3-16-c5fdbbe65e70@quicinc.com (mailing list archive)
State New
Headers show
Series Qualcomm iris video decoder driver | expand

Commit Message

Dikshita Agarwal via B4 Relay Aug. 27, 2024, 10:05 a.m. UTC
From: Vedang Nagar <quic_vnagar@quicinc.com>

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@quicinc.com>
Signed-off-by: Dikshita Agarwal <quic_dikshita@quicinc.com>
---
 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(-)

Comments

Dmitry Baryshkov Aug. 29, 2024, 9:33 a.m. UTC | #1
On Tue, Aug 27, 2024 at 03:35:41PM GMT, Dikshita Agarwal via B4 Relay wrote:
> From: Vedang Nagar <quic_vnagar@quicinc.com>
> 
> 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@quicinc.com>
> Signed-off-by: Dikshita Agarwal <quic_dikshita@quicinc.com>
> ---
>  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++) {

Drop the second condition

> +		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;

This isn't related to the s_ctrl and g_volatile_ctrl. Please split this
commit into the chunk that is actually related to that API and the rest
of the changes.

>  	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,
> +};

Please use C structures for platform caps. You have introduced a
wrapping that 1:1 maps to C code, which is not iterated or otherwise
accessed via a generic ID aside from the driver code.

> +
> +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,
> +};

I have mixed feelings towards fw caps. Let's see how the code evolves
after you split the commit into V4L2 CTRL code and the rest of the
changes.

> +
> +enum platform_inst_cap_flags {
> +	CAP_FLAG_NONE			= 0,

No need to define NONE, just skip the setting.

> +	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;
> +};
> +
Vedang Nagar Oct. 1, 2024, 1:01 p.m. UTC | #2
Hi Dmitry,

On 8/29/2024 3:03 PM, Dmitry Baryshkov wrote:
> On Tue, Aug 27, 2024 at 03:35:41PM GMT, Dikshita Agarwal via B4 Relay wrote:
>> From: Vedang Nagar <quic_vnagar@quicinc.com>
>>
>> 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@quicinc.com>
>> Signed-off-by: Dikshita Agarwal <quic_dikshita@quicinc.com>
>> ---
>>  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(-)

[Skipped]

>> 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;
> 
> This isn't related to the s_ctrl and g_volatile_ctrl. Please split this
> commit into the chunk that is actually related to that API and the rest
> of the changes.
Could you please help to provide more details on how are you expecting the
split of the patches?

Do you expect to split V4L2 ctrls_init/s_ctrl/g_ctrl in one patch and the
introduction of all the capabilities into another patch? We are not finding
it feasible to split the patch that way as in ctrl_init we read the
capability from platform data to initialize the respective control.

Regards,
Vedang Nagar
> 
>>  	iris_hfi_gen2_packet_session_property(inst,
>>  					      HFI_PROP_DEC_DEFAULT_HEADER,
>>  					      HFI_HOST_FLAGS_NONE,
> 
>
Dmitry Baryshkov Oct. 6, 2024, 4:46 p.m. UTC | #3
On Tue, Oct 01, 2024 at 06:31:16PM GMT, Vedang Nagar wrote:
> Hi Dmitry,
> 
> On 8/29/2024 3:03 PM, Dmitry Baryshkov wrote:
> > On Tue, Aug 27, 2024 at 03:35:41PM GMT, Dikshita Agarwal via B4 Relay wrote:
> >> From: Vedang Nagar <quic_vnagar@quicinc.com>
> >>
> >> 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@quicinc.com>
> >> Signed-off-by: Dikshita Agarwal <quic_dikshita@quicinc.com>
> >> ---
> >>  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(-)
> 
> [Skipped]
> 
> >> 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;
> > 
> > This isn't related to the s_ctrl and g_volatile_ctrl. Please split this
> > commit into the chunk that is actually related to that API and the rest
> > of the changes.
> Could you please help to provide more details on how are you expecting the
> split of the patches?
> 
> Do you expect to split V4L2 ctrls_init/s_ctrl/g_ctrl in one patch and the
> introduction of all the capabilities into another patch? We are not finding
> it feasible to split the patch that way as in ctrl_init we read the
> capability from platform data to initialize the respective control.

Please split all caps and all the structs that are not related to the
V4L2 ctrls implementation. In this patch please keep only those defines,
structs and fields that are required to implement V4L2 ctrl API.

> > 
> >>  	iris_hfi_gen2_packet_session_property(inst,
> >>  					      HFI_PROP_DEC_DEFAULT_HEADER,
> >>  					      HFI_HOST_FLAGS_NONE,
> > 
> >
diff mbox series

Patch

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: