Commit 025398e9 authored by Vedang Nagar's avatar Vedang Nagar Committed by Hans Verkuil
Browse files

media: iris: subscribe parameters and properties to firmware for hfi_gen2



For hfi_gen2, subscribe different bitstream parameters on to firmware,
to get notified of a change in any of the subscribed parameters.

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 3a19d7b9
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -18,12 +18,18 @@ struct iris_core;
 *
 * @inst: pointer to iris_instance structure
 * @packet: HFI packet
 * @ipsc_properties_set: boolean to set ipsc properties to fw
 * @opsc_properties_set: boolean to set opsc properties to fw
 * @src_subcr_params: subscription params to fw on input port
 * @dst_subcr_params: subscription params to fw on output port
 */
struct iris_inst_hfi_gen2 {
	struct iris_inst		inst;
	struct iris_hfi_header		*packet;
	bool				ipsc_properties_set;
	bool				opsc_properties_set;
	struct hfi_subscription_params	src_subcr_params;
	struct hfi_subscription_params	dst_subcr_params;
};

void iris_hfi_gen2_command_ops_init(struct iris_core *core);
+174 −0
Original line number Diff line number Diff line
@@ -437,6 +437,9 @@ static int iris_hfi_gen2_session_open(struct iris_inst *inst)
	if (inst->state != IRIS_INST_DEINIT)
		return -EALREADY;

	inst_hfi_gen2->ipsc_properties_set = false;
	inst_hfi_gen2->opsc_properties_set = false;

	inst_hfi_gen2->packet = kzalloc(4096, GFP_KERNEL);
	if (!inst_hfi_gen2->packet)
		return -ENOMEM;
@@ -501,9 +504,180 @@ static int iris_hfi_gen2_session_close(struct iris_inst *inst)
	return ret;
}

static int iris_hfi_gen2_session_subscribe_mode(struct iris_inst *inst,
						u32 cmd, u32 plane, u32 payload_type,
						void *payload, u32 payload_size)
{
	struct iris_inst_hfi_gen2 *inst_hfi_gen2 = to_iris_inst_hfi_gen2(inst);

	iris_hfi_gen2_packet_session_command(inst,
					     cmd,
					     (HFI_HOST_FLAGS_RESPONSE_REQUIRED |
					     HFI_HOST_FLAGS_INTR_REQUIRED),
					     iris_hfi_gen2_get_port(plane),
					     inst->session_id,
					     payload_type,
					     payload,
					     payload_size);

	return iris_hfi_queue_cmd_write(inst->core, inst_hfi_gen2->packet,
					inst_hfi_gen2->packet->size);
}

static int iris_hfi_gen2_subscribe_change_param(struct iris_inst *inst, u32 plane)
{
	struct iris_inst_hfi_gen2 *inst_hfi_gen2 = to_iris_inst_hfi_gen2(inst);
	struct hfi_subscription_params subsc_params;
	u32 prop_type, payload_size, payload_type;
	struct iris_core *core = inst->core;
	const u32 *change_param;
	u32 change_param_size;
	u32 payload[32] = {0};
	u32 hfi_port = 0, i;
	int ret;

	if ((V4L2_TYPE_IS_OUTPUT(plane) && inst_hfi_gen2->ipsc_properties_set) ||
	    (V4L2_TYPE_IS_CAPTURE(plane) && inst_hfi_gen2->opsc_properties_set)) {
		dev_err(core->dev, "invalid plane\n");
		return 0;
	}

	change_param = core->iris_platform_data->input_config_params;
	change_param_size = core->iris_platform_data->input_config_params_size;

	payload[0] = HFI_MODE_PORT_SETTINGS_CHANGE;

	for (i = 0; i < change_param_size; i++)
		payload[i + 1] = change_param[i];

	ret = iris_hfi_gen2_session_subscribe_mode(inst,
						   HFI_CMD_SUBSCRIBE_MODE,
						   plane,
						   HFI_PAYLOAD_U32_ARRAY,
						   &payload[0],
						   ((change_param_size + 1) * sizeof(u32)));
	if (ret)
		return ret;

	if (V4L2_TYPE_IS_OUTPUT(plane)) {
		inst_hfi_gen2->ipsc_properties_set = true;
	} else {
		hfi_port = iris_hfi_gen2_get_port(V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
		memcpy(&inst_hfi_gen2->dst_subcr_params,
		       &inst_hfi_gen2->src_subcr_params,
		       sizeof(inst_hfi_gen2->src_subcr_params));
		subsc_params = inst_hfi_gen2->dst_subcr_params;
		for (i = 0; i < change_param_size; i++) {
			payload[0] = 0;
			payload[1] = 0;
			payload_size = 0;
			payload_type = 0;
			prop_type = change_param[i];
			switch (prop_type) {
			case HFI_PROP_BITSTREAM_RESOLUTION:
				payload[0] = subsc_params.bitstream_resolution;
				payload_size = sizeof(u32);
				payload_type = HFI_PAYLOAD_U32;
				break;
			case HFI_PROP_CROP_OFFSETS:
				payload[0] = subsc_params.crop_offsets[0];
				payload[1] = subsc_params.crop_offsets[1];
				payload_size = sizeof(u64);
				payload_type = HFI_PAYLOAD_64_PACKED;
				break;
			case HFI_PROP_CODED_FRAMES:
				payload[0] = subsc_params.coded_frames;
				payload_size = sizeof(u32);
				payload_type = HFI_PAYLOAD_U32;
				break;
			case HFI_PROP_BUFFER_FW_MIN_OUTPUT_COUNT:
				payload[0] = subsc_params.fw_min_count;
				payload_size = sizeof(u32);
				payload_type = HFI_PAYLOAD_U32;
				break;
			case HFI_PROP_PIC_ORDER_CNT_TYPE:
				payload[0] = subsc_params.pic_order_cnt;
				payload_size = sizeof(u32);
				payload_type = HFI_PAYLOAD_U32;
				break;
			case HFI_PROP_SIGNAL_COLOR_INFO:
				payload[0] = subsc_params.color_info;
				payload_size = sizeof(u32);
				payload_type = HFI_PAYLOAD_U32;
				break;
			case HFI_PROP_PROFILE:
				payload[0] = subsc_params.profile;
				payload_size = sizeof(u32);
				payload_type = HFI_PAYLOAD_U32;
				break;
			case HFI_PROP_LEVEL:
				payload[0] = subsc_params.level;
				payload_size = sizeof(u32);
				payload_type = HFI_PAYLOAD_U32;
				break;
			default:
				prop_type = 0;
				ret = -EINVAL;
				break;
			}
			if (prop_type) {
				ret = iris_hfi_gen2_session_set_property(inst,
									 prop_type,
									 HFI_HOST_FLAGS_NONE,
									 hfi_port,
									 payload_type,
									 &payload,
									 payload_size);
				if (ret)
					return ret;
			}
		}
		inst_hfi_gen2->opsc_properties_set = true;
	}

	return 0;
}

static int iris_hfi_gen2_subscribe_property(struct iris_inst *inst, u32 plane)
{
	struct iris_core *core = inst->core;
	u32 subscribe_prop_size, i;
	const u32 *subcribe_prop;
	u32 payload[32] = {0};

	payload[0] = HFI_MODE_PROPERTY;

	if (V4L2_TYPE_IS_OUTPUT(plane)) {
		subscribe_prop_size = core->iris_platform_data->dec_input_prop_size;
		subcribe_prop = core->iris_platform_data->dec_input_prop;
	} else {
		subscribe_prop_size = core->iris_platform_data->dec_output_prop_size;
		subcribe_prop = core->iris_platform_data->dec_output_prop;
	}

	for (i = 0; i < subscribe_prop_size; i++)
		payload[i + 1] = subcribe_prop[i];

	return iris_hfi_gen2_session_subscribe_mode(inst,
						    HFI_CMD_SUBSCRIBE_MODE,
						    plane,
						    HFI_PAYLOAD_U32_ARRAY,
						    &payload[0],
						    (subscribe_prop_size + 1) * sizeof(u32));
}

static int iris_hfi_gen2_session_start(struct iris_inst *inst, u32 plane)
{
	struct iris_inst_hfi_gen2 *inst_hfi_gen2 = to_iris_inst_hfi_gen2(inst);
	int ret = 0;

	ret = iris_hfi_gen2_subscribe_change_param(inst, plane);
	if (ret)
		return ret;

	ret = iris_hfi_gen2_subscribe_property(inst, plane);
	if (ret)
		return ret;

	iris_hfi_gen2_packet_session_command(inst,
					     HFI_CMD_START,
+9 −0
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
#define HFI_CMD_CLOSE				0x01000004
#define HFI_CMD_START				0x01000005
#define HFI_CMD_STOP				0x01000006
#define HFI_CMD_SUBSCRIBE_MODE			0x0100000B
#define HFI_CMD_END				0x01FFFFFF

#define HFI_BITMASK_FRAME_MBS_ONLY_FLAG		0x00000001
@@ -42,13 +43,16 @@
#define HFI_PROP_PIPE				0x0300010b
#define HFI_PROP_LUMA_CHROMA_BIT_DEPTH		0x0300010f
#define HFI_PROP_CODED_FRAMES			0x03000120
#define HFI_PROP_CABAC_SESSION			0x03000121
#define HFI_PROP_BUFFER_HOST_MAX_COUNT		0x03000123
#define HFI_PROP_BUFFER_FW_MIN_OUTPUT_COUNT	0x03000124
#define HFI_PROP_PIC_ORDER_CNT_TYPE		0x03000128
#define HFI_PROP_QUALITY_MODE			0x03000148
#define HFI_PROP_SIGNAL_COLOR_INFO		0x03000155
#define HFI_PROP_PICTURE_TYPE			0x03000162
#define HFI_PROP_DEC_DEFAULT_HEADER		0x03000168
#define HFI_PROP_DEC_START_FROM_RAP_FRAME	0x03000169
#define HFI_PROP_NO_OUTPUT			0x0300016a
#define HFI_PROP_END				0x03FFFFFF

#define HFI_SESSION_ERROR_BEGIN			0x04000000
@@ -65,6 +69,11 @@
#define HFI_SYS_ERROR_WD_TIMEOUT		0x05000001
#define HFI_SYSTEM_ERROR_END			0x05FFFFFF

enum hfi_property_mode_type {
	HFI_MODE_PORT_SETTINGS_CHANGE		= 0x00000001,
	HFI_MODE_PROPERTY			= 0x00000002,
};

enum hfi_color_format {
	HFI_COLOR_FMT_OPAQUE			= 0,
	HFI_COLOR_FMT_NV12			= 1,
+4 −0
Original line number Diff line number Diff line
@@ -147,6 +147,10 @@ struct iris_platform_data {
	unsigned int input_config_params_size;
	const u32 *output_config_params;
	unsigned int output_config_params_size;
	const u32 *dec_input_prop;
	unsigned int dec_input_prop_size;
	const u32 *dec_output_prop;
	unsigned int dec_output_prop_size;
};

#endif
+13 −0
Original line number Diff line number Diff line
@@ -183,6 +183,15 @@ static const u32 sm8550_vdec_output_config_params[] = {
	HFI_PROP_LINEAR_STRIDE_SCANLINE,
};

static const u32 sm8550_vdec_subscribe_input_properties[] = {
	HFI_PROP_NO_OUTPUT,
};

static const u32 sm8550_vdec_subscribe_output_properties[] = {
	HFI_PROP_PICTURE_TYPE,
	HFI_PROP_CABAC_SESSION,
};

struct iris_platform_data sm8550_data = {
	.get_instance = iris_hfi_gen2_get_instance,
	.init_hfi_command_ops = iris_hfi_gen2_command_ops_init,
@@ -220,4 +229,8 @@ struct iris_platform_data sm8550_data = {
		sm8550_vdec_output_config_params,
	.output_config_params_size =
		ARRAY_SIZE(sm8550_vdec_output_config_params),
	.dec_input_prop = sm8550_vdec_subscribe_input_properties,
	.dec_input_prop_size = ARRAY_SIZE(sm8550_vdec_subscribe_input_properties),
	.dec_output_prop = sm8550_vdec_subscribe_output_properties,
	.dec_output_prop_size = ARRAY_SIZE(sm8550_vdec_subscribe_output_properties),
};