Commit 3a19d7b9 authored by Vedang Nagar's avatar Vedang Nagar Committed by Hans Verkuil
Browse files

media: iris: implement set properties to firmware during streamon



During the stream on operation, set some mandatory properties on the
firmware to start a session. Set all v4l2 properties, which are set by
the client, on to firmware, which is prepared with the dependency graph.

Signed-off-by: default avatarVedang Nagar <quic_vnagar@quicinc.com>
Tested-by: Stefan Schmidt <stefan.schmidt@linaro.org> # x1e80100 (Dell XPS 13 9345)
Reviewed-by: default avatarStefan Schmidt <stefan.schmidt@linaro.org>
Tested-by: Neil Armstrong <neil.armstrong@linaro.org> # on SM8550-QRD
Tested-by: Neil Armstrong <neil.armstrong@linaro.org> # on SM8550-HDK
Signed-off-by: default avatarDikshita Agarwal <quic_dikshita@quicinc.com>
Signed-off-by: default avatarHans Verkuil <hverkuil@xs4all.nl>
parent 11712ce7
Loading
Loading
Loading
Loading
+121 −0
Original line number Diff line number Diff line
@@ -72,6 +72,125 @@ static u32 iris_yuv_buffer_size_nv12(struct iris_inst *inst)
	return ALIGN(y_plane + uv_plane, PIXELS_4K);
}

/*
 * QC08C:
 * Compressed Macro-tile format for NV12.
 * Contains 4 planes in the following order -
 * (A) Y_Meta_Plane
 * (B) Y_UBWC_Plane
 * (C) UV_Meta_Plane
 * (D) UV_UBWC_Plane
 *
 * Y_Meta_Plane consists of meta information to decode compressed
 * tile data in Y_UBWC_Plane.
 * Y_UBWC_Plane consists of Y data in compressed macro-tile format.
 * UBWC decoder block will use the Y_Meta_Plane data together with
 * Y_UBWC_Plane data to produce loss-less uncompressed 8 bit Y samples.
 *
 * UV_Meta_Plane consists of meta information to decode compressed
 * tile data in UV_UBWC_Plane.
 * UV_UBWC_Plane consists of UV data in compressed macro-tile format.
 * UBWC decoder block will use UV_Meta_Plane data together with
 * UV_UBWC_Plane data to produce loss-less uncompressed 8 bit 2x2
 * subsampled color difference samples.
 *
 * Each tile in Y_UBWC_Plane/UV_UBWC_Plane is independently decodable
 * and randomly accessible. There is no dependency between tiles.
 *
 * <----- y_meta_stride ----> (aligned to 64)
 * <-------- Width ------>
 * M M M M M M M M M M M M . .      ^           ^
 * M M M M M M M M M M M M . .      |           |
 * M M M M M M M M M M M M . .      Height      |
 * M M M M M M M M M M M M . .      |         y_meta_scanlines  (aligned to 16)
 * M M M M M M M M M M M M . .      |           |
 * M M M M M M M M M M M M . .      |           |
 * M M M M M M M M M M M M . .      |           |
 * M M M M M M M M M M M M . .      V           |
 * . . . . . . . . . . . . . .                  |
 * . . . . . . . . . . . . . .                  |
 * . . . . . . . . . . . . . .      -------> Buffer size aligned to 4k
 * . . . . . . . . . . . . . .                  V
 * <--Compressed tile y_stride---> (aligned to 128)
 * <------- Width ------->
 * Y* Y* Y* Y* Y* Y* Y* Y* . . . .  ^           ^
 * Y* Y* Y* Y* Y* Y* Y* Y* . . . .  |           |
 * Y* Y* Y* Y* Y* Y* Y* Y* . . . .  Height      |
 * Y* Y* Y* Y* Y* Y* Y* Y* . . . .  |        Macro_tile y_scanlines (aligned to 32)
 * Y* Y* Y* Y* Y* Y* Y* Y* . . . .  |           |
 * Y* Y* Y* Y* Y* Y* Y* Y* . . . .  |           |
 * Y* Y* Y* Y* Y* Y* Y* Y* . . . .  |           |
 * Y* Y* Y* Y* Y* Y* Y* Y* . . . .  V           |
 * . . . . . . . . . . . . . . . .              |
 * . . . . . . . . . . . . . . . .              |
 * . . . . . . . . . . . . . . . .  -------> Buffer size aligned to 4k
 * . . . . . . . . . . . . . . . .              V
 * <----- uv_meta_stride ---->  (aligned to 64)
 * M M M M M M M M M M M M . .      ^
 * M M M M M M M M M M M M . .      |
 * M M M M M M M M M M M M . .      |
 * M M M M M M M M M M M M . .      uv_meta_scanlines (aligned to 16)
 * . . . . . . . . . . . . . .      |
 * . . . . . . . . . . . . . .      V
 * . . . . . . . . . . . . . .      -------> Buffer size aligned to 4k
 * <--Compressed tile uv_stride---> (aligned to 128)
 * U* V* U* V* U* V* U* V* . . . .  ^
 * U* V* U* V* U* V* U* V* . . . .  |
 * U* V* U* V* U* V* U* V* . . . .  |
 * U* V* U* V* U* V* U* V* . . . .  uv_scanlines (aligned to 32)
 * . . . . . . . . . . . . . . . .  |
 * . . . . . . . . . . . . . . . .  V
 * . . . . . . . . . . . . . . . .  -------> Buffer size aligned to 4k
 *
 * y_stride: width aligned to 128
 * uv_stride: width aligned to 128
 * y_scanlines: height aligned to 32
 * uv_scanlines: height aligned to 32
 * y_plane: buffer size aligned to 4096
 * uv_plane: buffer size aligned to 4096
 * y_meta_stride: width aligned to 64
 * y_meta_scanlines: height aligned to 16
 * y_meta_plane: buffer size aligned to 4096
 * uv_meta_stride: width aligned to 64
 * uv_meta_scanlines: height aligned to 16
 * uv_meta_plane: buffer size aligned to 4096
 *
 * Total size = align( y_plane + uv_plane +
 *           y_meta_plane + uv_meta_plane, 4096)
 *
 * Note: All the alignments are hardware requirements.
 */
static u32 iris_yuv_buffer_size_qc08c(struct iris_inst *inst)
{
	u32 y_plane, uv_plane, y_stride, uv_stride;
	struct v4l2_format *f = inst->fmt_dst;
	u32 uv_meta_stride, uv_meta_plane;
	u32 y_meta_stride, y_meta_plane;

	y_meta_stride = ALIGN(DIV_ROUND_UP(f->fmt.pix_mp.width, META_STRIDE_ALIGNED >> 1),
			      META_STRIDE_ALIGNED);
	y_meta_plane = y_meta_stride * ALIGN(DIV_ROUND_UP(f->fmt.pix_mp.height,
							  META_SCANLINE_ALIGNED >> 1),
					     META_SCANLINE_ALIGNED);
	y_meta_plane = ALIGN(y_meta_plane, PIXELS_4K);

	y_stride = ALIGN(f->fmt.pix_mp.width, Y_STRIDE_ALIGN);
	y_plane = ALIGN(y_stride * ALIGN(f->fmt.pix_mp.height, Y_SCANLINE_ALIGN), PIXELS_4K);

	uv_meta_stride = ALIGN(DIV_ROUND_UP(f->fmt.pix_mp.width / 2, META_STRIDE_ALIGNED >> 2),
			       META_STRIDE_ALIGNED);
	uv_meta_plane = uv_meta_stride * ALIGN(DIV_ROUND_UP(f->fmt.pix_mp.height / 2,
							    META_SCANLINE_ALIGNED >> 1),
					       META_SCANLINE_ALIGNED);
	uv_meta_plane = ALIGN(uv_meta_plane, PIXELS_4K);

	uv_stride = ALIGN(f->fmt.pix_mp.width, UV_STRIDE_ALIGN);
	uv_plane = ALIGN(uv_stride * ALIGN(f->fmt.pix_mp.height / 2, UV_SCANLINE_ALIGN_QC08C),
			 PIXELS_4K);

	return ALIGN(y_meta_plane + y_plane + uv_meta_plane + uv_plane, PIXELS_4K);
}

static u32 iris_bitstream_buffer_size(struct iris_inst *inst)
{
	struct platform_inst_caps *caps = inst->core->iris_platform_data->inst_caps;
@@ -102,6 +221,8 @@ int iris_get_buffer_size(struct iris_inst *inst,
		return iris_bitstream_buffer_size(inst);
	case BUF_OUTPUT:
		return iris_yuv_buffer_size_nv12(inst);
	case BUF_DPB:
		return iris_yuv_buffer_size_qc08c(inst);
	default:
		return 0;
	}
+94 −0
Original line number Diff line number Diff line
@@ -3,7 +3,9 @@
 * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved.
 */

#include <linux/types.h>
#include <media/v4l2-mem2mem.h>

#include "iris_ctrls.h"
#include "iris_instance.h"

@@ -163,3 +165,95 @@ void iris_session_init_caps(struct iris_core *core)
		core->inst_fw_caps[cap_id].hfi_id = caps[i].hfi_id;
	}
}

static u32 iris_get_port_info(struct iris_inst *inst,
			      enum platform_inst_fw_cap_type cap_id)
{
	if (inst->fw_caps[cap_id].flags & CAP_FLAG_INPUT_PORT)
		return HFI_PORT_BITSTREAM;
	else if (inst->fw_caps[cap_id].flags & CAP_FLAG_OUTPUT_PORT)
		return HFI_PORT_RAW;

	return HFI_PORT_NONE;
}

int iris_set_u32_enum(struct iris_inst *inst, enum platform_inst_fw_cap_type cap_id)
{
	const struct iris_hfi_command_ops *hfi_ops = inst->core->hfi_ops;
	u32 hfi_value = inst->fw_caps[cap_id].value;
	u32 hfi_id = inst->fw_caps[cap_id].hfi_id;

	return hfi_ops->session_set_property(inst, hfi_id,
					     HFI_HOST_FLAGS_NONE,
					     iris_get_port_info(inst, cap_id),
					     HFI_PAYLOAD_U32_ENUM,
					     &hfi_value, sizeof(u32));
}

int iris_set_u32(struct iris_inst *inst, enum platform_inst_fw_cap_type cap_id)
{
	const struct iris_hfi_command_ops *hfi_ops = inst->core->hfi_ops;
	u32 hfi_value = inst->fw_caps[cap_id].value;
	u32 hfi_id = inst->fw_caps[cap_id].hfi_id;

	return hfi_ops->session_set_property(inst, hfi_id,
					     HFI_HOST_FLAGS_NONE,
					     iris_get_port_info(inst, cap_id),
					     HFI_PAYLOAD_U32,
					     &hfi_value, sizeof(u32));
}

int iris_set_stage(struct iris_inst *inst, enum platform_inst_fw_cap_type cap_id)
{
	const struct iris_hfi_command_ops *hfi_ops = inst->core->hfi_ops;
	struct v4l2_format *inp_f = inst->fmt_src;
	u32 hfi_id = inst->fw_caps[cap_id].hfi_id;
	u32 height = inp_f->fmt.pix_mp.height;
	u32 width = inp_f->fmt.pix_mp.width;
	u32 work_mode = STAGE_2;

	if (iris_res_is_less_than(width, height, 1280, 720))
		work_mode = STAGE_1;

	return hfi_ops->session_set_property(inst, hfi_id,
					     HFI_HOST_FLAGS_NONE,
					     iris_get_port_info(inst, cap_id),
					     HFI_PAYLOAD_U32,
					     &work_mode, sizeof(u32));
}

int iris_set_pipe(struct iris_inst *inst, enum platform_inst_fw_cap_type cap_id)
{
	const struct iris_hfi_command_ops *hfi_ops = inst->core->hfi_ops;
	u32 work_route = inst->fw_caps[PIPE].value;
	u32 hfi_id = inst->fw_caps[cap_id].hfi_id;

	return hfi_ops->session_set_property(inst, hfi_id,
					     HFI_HOST_FLAGS_NONE,
					     iris_get_port_info(inst, cap_id),
					     HFI_PAYLOAD_U32,
					     &work_route, sizeof(u32));
}

int iris_set_properties(struct iris_inst *inst, u32 plane)
{
	const struct iris_hfi_command_ops *hfi_ops = inst->core->hfi_ops;
	struct platform_inst_fw_cap *cap;
	int ret;
	u32 i;

	ret = hfi_ops->session_set_config_params(inst, plane);
	if (ret)
		return ret;

	for (i = 1; i < INST_FW_CAP_MAX; i++) {
		cap = &inst->fw_caps[i];
		if (!iris_valid_cap_id(cap->cap_id))
			continue;

		if (cap->cap_id && cap->set)
			cap->set(inst, i);
	}

	return 0;
}
+5 −0
Original line number Diff line number Diff line
@@ -13,5 +13,10 @@ struct iris_inst;

int iris_ctrls_init(struct iris_inst *inst);
void iris_session_init_caps(struct iris_core *core);
int iris_set_u32_enum(struct iris_inst *inst, enum platform_inst_fw_cap_type cap_id);
int iris_set_stage(struct iris_inst *inst, enum platform_inst_fw_cap_type cap_id);
int iris_set_pipe(struct iris_inst *inst, enum platform_inst_fw_cap_type cap_id);
int iris_set_u32(struct iris_inst *inst, enum platform_inst_fw_cap_type cap_id);
int iris_set_properties(struct iris_inst *inst, u32 plane);

#endif
+76 −0
Original line number Diff line number Diff line
@@ -43,11 +43,75 @@ enum hfi_packet_host_flags {
	HFI_HOST_FLAGS_GET_PROPERTY		= 0x00000008,
};

enum hfi_color_primaries {
	HFI_PRIMARIES_RESERVED		= 0,
	HFI_PRIMARIES_BT709		= 1,
	HFI_PRIMARIES_UNSPECIFIED	= 2,
	HFI_PRIMARIES_BT470_SYSTEM_M	= 4,
	HFI_PRIMARIES_BT470_SYSTEM_BG	= 5,
	HFI_PRIMARIES_BT601_525		= 6,
	HFI_PRIMARIES_SMPTE_ST240M	= 7,
	HFI_PRIMARIES_GENERIC_FILM	= 8,
	HFI_PRIMARIES_BT2020		= 9,
	HFI_PRIMARIES_SMPTE_ST428_1	= 10,
	HFI_PRIMARIES_SMPTE_RP431_2	= 11,
	HFI_PRIMARIES_SMPTE_EG431_1	= 12,
	HFI_PRIMARIES_SMPTE_EBU_TECH	= 22,
};

enum hfi_transfer_characteristics {
	HFI_TRANSFER_RESERVED		= 0,
	HFI_TRANSFER_BT709		= 1,
	HFI_TRANSFER_UNSPECIFIED	= 2,
	HFI_TRANSFER_BT470_SYSTEM_M	= 4,
	HFI_TRANSFER_BT470_SYSTEM_BG	= 5,
	HFI_TRANSFER_BT601_525_OR_625	= 6,
	HFI_TRANSFER_SMPTE_ST240M	= 7,
	HFI_TRANSFER_LINEAR		= 8,
	HFI_TRANSFER_LOG_100_1		= 9,
	HFI_TRANSFER_LOG_SQRT		= 10,
	HFI_TRANSFER_XVYCC		= 11,
	HFI_TRANSFER_BT1361_0		= 12,
	HFI_TRANSFER_SRGB_SYCC		= 13,
	HFI_TRANSFER_BT2020_14		= 14,
	HFI_TRANSFER_BT2020_15		= 15,
	HFI_TRANSFER_SMPTE_ST2084_PQ	= 16,
	HFI_TRANSFER_SMPTE_ST428_1	= 17,
	HFI_TRANSFER_BT2100_2_HLG	= 18,
};

enum hfi_matrix_coefficients {
	HFI_MATRIX_COEFF_SRGB_SMPTE_ST428_1		= 0,
	HFI_MATRIX_COEFF_BT709				= 1,
	HFI_MATRIX_COEFF_UNSPECIFIED			= 2,
	HFI_MATRIX_COEFF_RESERVED			= 3,
	HFI_MATRIX_COEFF_FCC_TITLE_47			= 4,
	HFI_MATRIX_COEFF_BT470_SYS_BG_OR_BT601_625	= 5,
	HFI_MATRIX_COEFF_BT601_525_BT1358_525_OR_625	= 6,
	HFI_MATRIX_COEFF_SMPTE_ST240			= 7,
	HFI_MATRIX_COEFF_YCGCO				= 8,
	HFI_MATRIX_COEFF_BT2020_NON_CONSTANT		= 9,
	HFI_MATRIX_COEFF_BT2020_CONSTANT		= 10,
	HFI_MATRIX_COEFF_SMPTE_ST2085			= 11,
	HFI_MATRIX_COEFF_SMPTE_CHROM_DERV_NON_CONSTANT	= 12,
	HFI_MATRIX_COEFF_SMPTE_CHROM_DERV_CONSTANT	= 13,
	HFI_MATRIX_COEFF_BT2100				= 14,
};

struct iris_hfi_prop_type_handle {
	u32 type;
	int (*handle)(struct iris_inst *inst);
};

struct iris_hfi_command_ops {
	int (*sys_init)(struct iris_core *core);
	int (*sys_image_version)(struct iris_core *core);
	int (*sys_interframe_powercollapse)(struct iris_core *core);
	int (*sys_pc_prep)(struct iris_core *core);
	int (*session_set_config_params)(struct iris_inst *inst, u32 plane);
	int (*session_set_property)(struct iris_inst *inst,
				    u32 packet_type, u32 flag, u32 plane, u32 payload_type,
				    void *payload, u32 payload_size);
	int (*session_open)(struct iris_inst *inst);
	int (*session_start)(struct iris_inst *inst, u32 plane);
	int (*session_stop)(struct iris_inst *inst, u32 plane);
@@ -58,6 +122,18 @@ struct iris_hfi_response_ops {
	void (*hfi_response_handler)(struct iris_core *core);
};

struct hfi_subscription_params {
	u32	bitstream_resolution;
	u32	crop_offsets[2];
	u32	bit_depth;
	u32	coded_frames;
	u32	fw_min_count;
	u32	pic_order_cnt;
	u32	color_info;
	u32	profile;
	u32	level;
};

int iris_hfi_core_init(struct iris_core *core);
int iris_hfi_pm_suspend(struct iris_core *core);
int iris_hfi_pm_resume(struct iris_core *core);
+411 −0
Original line number Diff line number Diff line
@@ -6,6 +6,7 @@
#include "iris_hfi_gen1.h"
#include "iris_hfi_gen1_defines.h"
#include "iris_instance.h"
#include "iris_vpu_buffer.h"

static int iris_hfi_gen1_sys_init(struct iris_core *core)
{
@@ -182,12 +183,422 @@ static int iris_hfi_gen1_session_stop(struct iris_inst *inst, u32 plane)
	return ret;
}

static int
iris_hfi_gen1_packet_session_set_property(struct hfi_session_set_property_pkt *packet,
					  struct iris_inst *inst, u32 ptype, void *pdata)
{
	void *prop_data = &packet->data[1];

	packet->shdr.hdr.size = sizeof(*packet);
	packet->shdr.hdr.pkt_type = HFI_CMD_SESSION_SET_PROPERTY;
	packet->shdr.session_id = inst->session_id;
	packet->num_properties = 1;
	packet->data[0] = ptype;

	switch (ptype) {
	case HFI_PROPERTY_PARAM_FRAME_SIZE: {
		struct hfi_framesize *in = pdata, *fsize = prop_data;

		fsize->buffer_type = in->buffer_type;
		fsize->height = in->height;
		fsize->width = in->width;
		packet->shdr.hdr.size += sizeof(u32) + sizeof(*fsize);
		break;
	}
	case HFI_PROPERTY_CONFIG_VIDEOCORES_USAGE: {
		struct hfi_videocores_usage_type *in = pdata, *cu = prop_data;

		cu->video_core_enable_mask = in->video_core_enable_mask;
		packet->shdr.hdr.size += sizeof(u32) + sizeof(*cu);
		break;
	}
	case HFI_PROPERTY_PARAM_UNCOMPRESSED_FORMAT_SELECT: {
		struct hfi_uncompressed_format_select *in = pdata;
		struct hfi_uncompressed_format_select *hfi = prop_data;

		hfi->buffer_type = in->buffer_type;
		hfi->format = in->format;
		packet->shdr.hdr.size += sizeof(u32) + sizeof(*hfi);
		break;
	}
	case HFI_PROPERTY_PARAM_UNCOMPRESSED_PLANE_ACTUAL_CONSTRAINTS_INFO: {
		struct hfi_uncompressed_plane_actual_constraints_info *info = prop_data;

		info->buffer_type = HFI_BUFFER_OUTPUT2;
		info->num_planes = 2;
		info->plane_format[0].stride_multiples = 128;
		info->plane_format[0].max_stride = 8192;
		info->plane_format[0].min_plane_buffer_height_multiple = 32;
		info->plane_format[0].buffer_alignment = 256;
		if (info->num_planes > 1) {
			info->plane_format[1].stride_multiples = 128;
			info->plane_format[1].max_stride = 8192;
			info->plane_format[1].min_plane_buffer_height_multiple = 16;
			info->plane_format[1].buffer_alignment = 256;
		}

		packet->shdr.hdr.size += sizeof(u32) + sizeof(*info);
		break;
	}
	case HFI_PROPERTY_PARAM_BUFFER_COUNT_ACTUAL: {
		struct hfi_buffer_count_actual *in = pdata;
		struct hfi_buffer_count_actual *count = prop_data;

		count->type = in->type;
		count->count_actual = in->count_actual;
		count->count_min_host = in->count_min_host;
		packet->shdr.hdr.size += sizeof(u32) + sizeof(*count);
		break;
	}
	case HFI_PROPERTY_PARAM_VDEC_MULTI_STREAM: {
		struct hfi_multi_stream *in = pdata;
		struct hfi_multi_stream *multi = prop_data;

		multi->buffer_type = in->buffer_type;
		multi->enable = in->enable;
		packet->shdr.hdr.size += sizeof(u32) + sizeof(*multi);
		break;
	}
	case HFI_PROPERTY_PARAM_BUFFER_SIZE_ACTUAL: {
		struct hfi_buffer_size_actual *in = pdata, *sz = prop_data;

		sz->size = in->size;
		sz->type = in->type;
		packet->shdr.hdr.size += sizeof(u32) + sizeof(*sz);
		break;
	}
	case HFI_PROPERTY_PARAM_WORK_ROUTE: {
		struct hfi_video_work_route *wr = prop_data;
		u32 *in = pdata;

		wr->video_work_route = *in;
		packet->shdr.hdr.size += sizeof(u32) + sizeof(*wr);
		break;
	}
	case HFI_PROPERTY_PARAM_WORK_MODE: {
		struct hfi_video_work_mode *wm = prop_data;
		u32 *in = pdata;

		wm->video_work_mode = *in;
		packet->shdr.hdr.size += sizeof(u32) + sizeof(*wm);
		break;
	}
	case HFI_PROPERTY_CONFIG_VDEC_POST_LOOP_DEBLOCKER: {
		struct hfi_enable *en = prop_data;
		u32 *in = pdata;

		en->enable = *in;
		packet->shdr.hdr.size += sizeof(u32) + sizeof(*en);
		break;
	}
	default:
		return -EINVAL;
	}

	return 0;
}

static int hfi_gen1_set_property(struct iris_inst *inst, u32 packet_type,
				 void *payload, u32 payload_size)
{
	struct hfi_session_set_property_pkt *pkt;
	u32 packet_size;
	int ret;

	packet_size = sizeof(*pkt) + sizeof(u32) + payload_size;
	pkt = kzalloc(packet_size, GFP_KERNEL);
	if (!pkt)
		return -ENOMEM;

	ret = iris_hfi_gen1_packet_session_set_property(pkt, inst, packet_type, payload);
	if (ret == -EOPNOTSUPP) {
		ret = 0;
		goto exit;
	}
	if (ret)
		goto exit;

	ret = iris_hfi_queue_cmd_write(inst->core, pkt, pkt->shdr.hdr.size);

exit:
	kfree(pkt);

	return ret;
}

static int iris_hfi_gen1_session_set_property(struct iris_inst *inst, u32 packet_type,
					      u32 flag, u32 plane, u32 payload_type,
					      void *payload, u32 payload_size)
{
	return hfi_gen1_set_property(inst, packet_type, payload, payload_size);
}

static int iris_hfi_gen1_set_resolution(struct iris_inst *inst)
{
	u32 ptype = HFI_PROPERTY_PARAM_FRAME_SIZE;
	struct hfi_framesize fs;
	int ret;

	fs.buffer_type = HFI_BUFFER_INPUT;
	fs.width = inst->fmt_src->fmt.pix_mp.width;
	fs.height = inst->fmt_src->fmt.pix_mp.height;

	ret = hfi_gen1_set_property(inst, ptype, &fs, sizeof(fs));
	if (ret)
		return ret;

	fs.buffer_type = HFI_BUFFER_OUTPUT2;
	fs.width = inst->fmt_dst->fmt.pix_mp.width;
	fs.height = inst->fmt_dst->fmt.pix_mp.height;

	return hfi_gen1_set_property(inst, ptype, &fs, sizeof(fs));
}

static int iris_hfi_gen1_decide_core(struct iris_inst *inst)
{
	const u32 ptype = HFI_PROPERTY_CONFIG_VIDEOCORES_USAGE;
	struct hfi_videocores_usage_type cu;

	cu.video_core_enable_mask = HFI_CORE_ID_1;

	return hfi_gen1_set_property(inst, ptype, &cu, sizeof(cu));
}

static int iris_hfi_gen1_set_raw_format(struct iris_inst *inst)
{
	const u32 ptype = HFI_PROPERTY_PARAM_UNCOMPRESSED_FORMAT_SELECT;
	u32 pixelformat = inst->fmt_dst->fmt.pix_mp.pixelformat;
	struct hfi_uncompressed_format_select fmt;
	int ret;

	if (iris_split_mode_enabled(inst)) {
		fmt.buffer_type = HFI_BUFFER_OUTPUT;
		fmt.format = pixelformat == V4L2_PIX_FMT_NV12 ? HFI_COLOR_FORMAT_NV12_UBWC : 0;

		ret = hfi_gen1_set_property(inst, ptype, &fmt, sizeof(fmt));
		if (ret)
			return ret;

		fmt.buffer_type = HFI_BUFFER_OUTPUT2;
		fmt.format = pixelformat == V4L2_PIX_FMT_NV12 ? HFI_COLOR_FORMAT_NV12 : 0;

		ret = hfi_gen1_set_property(inst, ptype, &fmt, sizeof(fmt));
	} else {
		fmt.buffer_type = HFI_BUFFER_OUTPUT;
		fmt.format = pixelformat == V4L2_PIX_FMT_NV12 ? HFI_COLOR_FORMAT_NV12 : 0;

		ret = hfi_gen1_set_property(inst, ptype, &fmt, sizeof(fmt));
	}

	return ret;
}

static int iris_hfi_gen1_set_format_constraints(struct iris_inst *inst)
{
	const u32 ptype = HFI_PROPERTY_PARAM_UNCOMPRESSED_PLANE_ACTUAL_CONSTRAINTS_INFO;
	struct hfi_uncompressed_plane_actual_constraints_info pconstraint;

	pconstraint.buffer_type = HFI_BUFFER_OUTPUT2;
	pconstraint.num_planes = 2;
	pconstraint.plane_format[0].stride_multiples = 128;
	pconstraint.plane_format[0].max_stride = 8192;
	pconstraint.plane_format[0].min_plane_buffer_height_multiple = 32;
	pconstraint.plane_format[0].buffer_alignment = 256;

	pconstraint.plane_format[1].stride_multiples = 128;
	pconstraint.plane_format[1].max_stride = 8192;
	pconstraint.plane_format[1].min_plane_buffer_height_multiple = 16;
	pconstraint.plane_format[1].buffer_alignment = 256;

	return hfi_gen1_set_property(inst, ptype, &pconstraint, sizeof(pconstraint));
}

static int iris_hfi_gen1_set_num_bufs(struct iris_inst *inst)
{
	u32 ptype = HFI_PROPERTY_PARAM_BUFFER_COUNT_ACTUAL;
	struct hfi_buffer_count_actual buf_count;
	int ret;

	buf_count.type = HFI_BUFFER_INPUT;
	buf_count.count_actual = VIDEO_MAX_FRAME;
	buf_count.count_min_host = VIDEO_MAX_FRAME;

	ret = hfi_gen1_set_property(inst, ptype, &buf_count, sizeof(buf_count));
	if (ret)
		return ret;

	if (iris_split_mode_enabled(inst)) {
		buf_count.type = HFI_BUFFER_OUTPUT;
		buf_count.count_actual = VIDEO_MAX_FRAME;
		buf_count.count_min_host = VIDEO_MAX_FRAME;

		ret = hfi_gen1_set_property(inst, ptype, &buf_count, sizeof(buf_count));
		if (ret)
			return ret;

		buf_count.type = HFI_BUFFER_OUTPUT2;
		buf_count.count_actual = iris_vpu_buf_count(inst, BUF_DPB);
		buf_count.count_min_host = iris_vpu_buf_count(inst, BUF_DPB);

		ret = hfi_gen1_set_property(inst, ptype, &buf_count, sizeof(buf_count));
	} else {
		buf_count.type = HFI_BUFFER_OUTPUT;
		buf_count.count_actual = VIDEO_MAX_FRAME;
		buf_count.count_min_host = VIDEO_MAX_FRAME;

		ret = hfi_gen1_set_property(inst, ptype, &buf_count, sizeof(buf_count));
	}

	return ret;
}

static int iris_hfi_gen1_set_multistream(struct iris_inst *inst)
{
	u32 ptype = HFI_PROPERTY_PARAM_VDEC_MULTI_STREAM;
	struct hfi_multi_stream multi = {0};
	int ret;

	if (iris_split_mode_enabled(inst)) {
		multi.buffer_type = HFI_BUFFER_OUTPUT;
		multi.enable = 0;

		ret = hfi_gen1_set_property(inst, ptype, &multi, sizeof(multi));
		if (ret)
			return ret;

		multi.buffer_type = HFI_BUFFER_OUTPUT2;
		multi.enable = 1;

		ret = hfi_gen1_set_property(inst, ptype, &multi, sizeof(multi));
	} else {
		multi.buffer_type = HFI_BUFFER_OUTPUT;
		multi.enable = 1;

		ret = hfi_gen1_set_property(inst, ptype, &multi, sizeof(multi));
		if (ret)
			return ret;

		multi.buffer_type = HFI_BUFFER_OUTPUT2;
		multi.enable = 0;

		ret = hfi_gen1_set_property(inst, ptype, &multi, sizeof(multi));
	}

	return ret;
}

static int iris_hfi_gen1_set_bufsize(struct iris_inst *inst)
{
	const u32 ptype = HFI_PROPERTY_PARAM_BUFFER_SIZE_ACTUAL;
	struct hfi_buffer_size_actual bufsz;
	int ret;

	if (iris_split_mode_enabled(inst)) {
		bufsz.type = HFI_BUFFER_OUTPUT;
		bufsz.size = iris_vpu_dec_dpb_size(inst);

		ret = hfi_gen1_set_property(inst, ptype, &bufsz, sizeof(bufsz));
		if (ret)
			return ret;

		bufsz.type = HFI_BUFFER_OUTPUT2;
		bufsz.size = inst->buffers[BUF_OUTPUT].size;

		ret = hfi_gen1_set_property(inst, ptype, &bufsz, sizeof(bufsz));
	} else {
		bufsz.type = HFI_BUFFER_OUTPUT;
		bufsz.size = inst->buffers[BUF_OUTPUT].size;

		ret = hfi_gen1_set_property(inst, ptype, &bufsz, sizeof(bufsz));
		if (ret)
			return ret;

		bufsz.type = HFI_BUFFER_OUTPUT2;
		bufsz.size = 0;

		ret = hfi_gen1_set_property(inst, ptype, &bufsz, sizeof(bufsz));
	}

	return ret;
}

static int iris_hfi_gen1_session_set_config_params(struct iris_inst *inst, u32 plane)
{
	struct iris_core *core = inst->core;
	u32 config_params_size, i, j;
	const u32 *config_params;
	int ret;

	static const struct iris_hfi_prop_type_handle prop_type_handle_inp_arr[] = {
		{HFI_PROPERTY_PARAM_FRAME_SIZE,
			iris_hfi_gen1_set_resolution},
		{HFI_PROPERTY_CONFIG_VIDEOCORES_USAGE,
			iris_hfi_gen1_decide_core},
		{HFI_PROPERTY_PARAM_UNCOMPRESSED_FORMAT_SELECT,
			iris_hfi_gen1_set_raw_format},
		{HFI_PROPERTY_PARAM_UNCOMPRESSED_PLANE_ACTUAL_CONSTRAINTS_INFO,
			iris_hfi_gen1_set_format_constraints},
		{HFI_PROPERTY_PARAM_BUFFER_COUNT_ACTUAL,
			iris_hfi_gen1_set_num_bufs},
		{HFI_PROPERTY_PARAM_VDEC_MULTI_STREAM,
			iris_hfi_gen1_set_multistream},
		{HFI_PROPERTY_PARAM_BUFFER_SIZE_ACTUAL,
			iris_hfi_gen1_set_bufsize},
	};

	static const struct iris_hfi_prop_type_handle prop_type_handle_out_arr[] = {
		{HFI_PROPERTY_PARAM_FRAME_SIZE,
			iris_hfi_gen1_set_resolution},
		{HFI_PROPERTY_PARAM_UNCOMPRESSED_FORMAT_SELECT,
			iris_hfi_gen1_set_raw_format},
		{HFI_PROPERTY_PARAM_UNCOMPRESSED_PLANE_ACTUAL_CONSTRAINTS_INFO,
			iris_hfi_gen1_set_format_constraints},
		{HFI_PROPERTY_PARAM_BUFFER_COUNT_ACTUAL,
			iris_hfi_gen1_set_num_bufs},
		{HFI_PROPERTY_PARAM_VDEC_MULTI_STREAM,
			iris_hfi_gen1_set_multistream},
		{HFI_PROPERTY_PARAM_BUFFER_SIZE_ACTUAL,
			iris_hfi_gen1_set_bufsize},
	};

	config_params = core->iris_platform_data->input_config_params;
	config_params_size = core->iris_platform_data->input_config_params_size;

	if (V4L2_TYPE_IS_OUTPUT(plane)) {
		for (i = 0; i < config_params_size; i++) {
			for (j = 0; j < ARRAY_SIZE(prop_type_handle_inp_arr); j++) {
				if (prop_type_handle_inp_arr[j].type == config_params[i]) {
					ret = prop_type_handle_inp_arr[j].handle(inst);
					if (ret)
						return ret;
					break;
				}
			}
		}
	} else if (V4L2_TYPE_IS_CAPTURE(plane)) {
		for (i = 0; i < config_params_size; i++) {
			for (j = 0; j < ARRAY_SIZE(prop_type_handle_out_arr); j++) {
				if (prop_type_handle_out_arr[j].type == config_params[i]) {
					ret = prop_type_handle_out_arr[j].handle(inst);
					if (ret)
						return ret;
					break;
				}
			}
		}
	}

	return 0;
}

static const struct iris_hfi_command_ops iris_hfi_gen1_command_ops = {
	.sys_init = iris_hfi_gen1_sys_init,
	.sys_image_version = iris_hfi_gen1_sys_image_version,
	.sys_interframe_powercollapse = iris_hfi_gen1_sys_interframe_powercollapse,
	.sys_pc_prep = iris_hfi_gen1_sys_pc_prep,
	.session_open = iris_hfi_gen1_session_open,
	.session_set_config_params = iris_hfi_gen1_session_set_config_params,
	.session_set_property = iris_hfi_gen1_session_set_property,
	.session_start = iris_hfi_gen1_session_start,
	.session_stop = iris_hfi_gen1_session_stop,
	.session_close = iris_hfi_gen1_session_close,
Loading