Commit 11712ce7 authored by Dikshita Agarwal's avatar Dikshita Agarwal Committed by Hans Verkuil
Browse files

media: iris: implement vb2 streaming ops



During the stream on operation, send HFI_CMD_START on the capture and
output planes to start processing on the respective planes.

During the stream off operation, send HFI_CMD_STOP to the firmware,
which is a synchronous command. After the response is received by the
firmware, the session is closed on the firmware.

Introduce different states for the instance and state transitions.

IRIS_INST_INIT - video instance is opened.
IRIS_INST_INPUT_STREAMING - stream on is completed on output plane.
IRIS_INST_OUTPUT_STREAMING - stream on is completed on capture plane.
IRIS_INST_STREAMING - stream on is completed on both output and capture
planes.
IRIS_INST_DEINIT - video instance is closed.
IRIS_INST_ERROR - error state.

                   |
                   v
            -------------
  +---------|   INIT    |---------  +
  |         -------------           |
  |            ^    ^               |
  |           /      \              |
  |          /        \             |
  |         v          v            |
  |    -----------    -----------   |
  |   |   INPUT         OUTPUT  |   |
  |---| STREAMING     STREAMING |---|
  |    -----------    -----------   |
  |        ^            ^           |
  |         \          /            |
  |          \        /             |
  |           v      v              |
  |         -------------           |
  |--------|  STREAMING |-----------|
  |         -------------           |
  |               |                 |
  |               |                 |
  |               v                 |
  |          -----------            |
  +-------->|  DEINIT   |<----------+
  |          -----------            |
  |               |                 |
  |               |                 |
  |               v                 |
  |          ----------             |
  +-------->|   ERROR  |<-----------+
             ----------.

Reviewed-by: default avatarHans Verkuil <hverkuil@xs4all.nl>
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 1dc5c970
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -12,6 +12,7 @@ iris-objs += iris_buffer.o \
             iris_platform_sm8550.o \
             iris_probe.o \
             iris_resources.o \
             iris_state.o \
             iris_utils.o \
             iris_vidc.o \
             iris_vb2.o \
+2 −0
Original line number Diff line number Diff line
@@ -49,6 +49,8 @@ struct iris_hfi_command_ops {
	int (*sys_interframe_powercollapse)(struct iris_core *core);
	int (*sys_pc_prep)(struct iris_core *core);
	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);
	int (*session_close)(struct iris_inst *inst);
};

+81 −1
Original line number Diff line number Diff line
@@ -71,6 +71,9 @@ static int iris_hfi_gen1_session_open(struct iris_inst *inst)
	struct hfi_session_open_pkt packet;
	int ret;

	if (inst->state != IRIS_INST_DEINIT)
		return -EALREADY;

	packet.shdr.hdr.size = sizeof(struct hfi_session_open_pkt);
	packet.shdr.hdr.pkt_type = HFI_CMD_SYS_SESSION_INIT;
	packet.shdr.session_id = inst->session_id;
@@ -83,7 +86,7 @@ static int iris_hfi_gen1_session_open(struct iris_inst *inst)
	if (ret)
		return ret;

	return iris_wait_for_session_response(inst);
	return iris_wait_for_session_response(inst, false);
}

static void iris_hfi_gen1_packet_session_cmd(struct iris_inst *inst,
@@ -104,12 +107,89 @@ static int iris_hfi_gen1_session_close(struct iris_inst *inst)
	return iris_hfi_queue_cmd_write(inst->core, &packet, packet.shdr.hdr.size);
}

static int iris_hfi_gen1_session_start(struct iris_inst *inst, u32 plane)
{
	struct iris_core *core = inst->core;
	struct hfi_session_pkt packet;
	int ret;

	if (!V4L2_TYPE_IS_OUTPUT(plane))
		return 0;

	reinit_completion(&inst->completion);
	iris_hfi_gen1_packet_session_cmd(inst, &packet, HFI_CMD_SESSION_LOAD_RESOURCES);

	ret = iris_hfi_queue_cmd_write(core, &packet, packet.shdr.hdr.size);
	if (ret)
		return ret;

	ret = iris_wait_for_session_response(inst, false);
	if (ret)
		return ret;

	reinit_completion(&inst->completion);
	iris_hfi_gen1_packet_session_cmd(inst, &packet, HFI_CMD_SESSION_START);

	ret = iris_hfi_queue_cmd_write(core, &packet, packet.shdr.hdr.size);
	if (ret)
		return ret;

	return iris_wait_for_session_response(inst, false);
}

static int iris_hfi_gen1_session_stop(struct iris_inst *inst, u32 plane)
{
	struct hfi_session_flush_pkt flush_pkt;
	struct iris_core *core = inst->core;
	struct hfi_session_pkt pkt;
	u32 flush_type = 0;
	int ret = 0;

	if ((V4L2_TYPE_IS_OUTPUT(plane) &&
	     inst->state == IRIS_INST_INPUT_STREAMING) ||
	    (V4L2_TYPE_IS_CAPTURE(plane) &&
	     inst->state == IRIS_INST_OUTPUT_STREAMING) ||
	    inst->state == IRIS_INST_ERROR) {
		reinit_completion(&inst->completion);
		iris_hfi_gen1_packet_session_cmd(inst, &pkt, HFI_CMD_SESSION_STOP);
		ret = iris_hfi_queue_cmd_write(core, &pkt, pkt.shdr.hdr.size);
		if (!ret)
			ret = iris_wait_for_session_response(inst, false);

		reinit_completion(&inst->completion);
		iris_hfi_gen1_packet_session_cmd(inst, &pkt, HFI_CMD_SESSION_RELEASE_RESOURCES);
		ret = iris_hfi_queue_cmd_write(core, &pkt, pkt.shdr.hdr.size);
		if (!ret)
			ret = iris_wait_for_session_response(inst, false);
	} else if (inst->state == IRIS_INST_STREAMING) {
		if (V4L2_TYPE_IS_OUTPUT(plane))
			flush_type = HFI_FLUSH_ALL;
		else if (V4L2_TYPE_IS_CAPTURE(plane))
			flush_type = HFI_FLUSH_OUTPUT;

		reinit_completion(&inst->flush_completion);

		flush_pkt.shdr.hdr.size = sizeof(struct hfi_session_flush_pkt);
		flush_pkt.shdr.hdr.pkt_type = HFI_CMD_SESSION_FLUSH;
		flush_pkt.shdr.session_id = inst->session_id;
		flush_pkt.flush_type = flush_type;

		ret = iris_hfi_queue_cmd_write(core, &flush_pkt, flush_pkt.shdr.hdr.size);
		if (!ret)
			ret = iris_wait_for_session_response(inst, true);
	}

	return ret;
}

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_start = iris_hfi_gen1_session_start,
	.session_stop = iris_hfi_gen1_session_stop,
	.session_close = iris_hfi_gen1_session_close,
};

+24 −0
Original line number Diff line number Diff line
@@ -23,6 +23,12 @@
#define HFI_CMD_SYS_SESSION_INIT			0x10007
#define HFI_CMD_SYS_SESSION_END				0x10008

#define HFI_CMD_SESSION_LOAD_RESOURCES			0x211001
#define HFI_CMD_SESSION_START				0x211002
#define HFI_CMD_SESSION_STOP				0x211003
#define HFI_CMD_SESSION_FLUSH				0x211008
#define HFI_CMD_SESSION_RELEASE_RESOURCES		0x21100c

#define HFI_ERR_SESSION_UNSUPPORTED_SETTING		0x1008
#define HFI_ERR_SESSION_UNSUPPORT_BUFFERTYPE		0x1010
#define HFI_ERR_SESSION_INVALID_SCALE_FACTOR		0x1012
@@ -31,6 +37,9 @@
#define HFI_EVENT_SYS_ERROR				0x1
#define HFI_EVENT_SESSION_ERROR				0x2

#define HFI_FLUSH_OUTPUT				0x1000002
#define HFI_FLUSH_OUTPUT2				0x1000003
#define HFI_FLUSH_ALL					0x1000004
#define HFI_PROPERTY_SYS_CODEC_POWER_PLANE_CTRL		0x5
#define HFI_PROPERTY_SYS_IMAGE_VERSION			0x6

@@ -41,6 +50,11 @@
#define HFI_MSG_SYS_PROPERTY_INFO			0x2000a

#define HFI_MSG_EVENT_NOTIFY				0x21001
#define HFI_MSG_SESSION_LOAD_RESOURCES			0x221001
#define HFI_MSG_SESSION_START				0x221002
#define HFI_MSG_SESSION_STOP				0x221003
#define HFI_MSG_SESSION_FLUSH				0x221006
#define HFI_MSG_SESSION_RELEASE_RESOURCES		0x22100a

struct hfi_pkt_hdr {
	u32 size;
@@ -83,6 +97,11 @@ struct hfi_sys_pc_prep_pkt {
	struct hfi_pkt_hdr hdr;
};

struct hfi_session_flush_pkt {
	struct hfi_session_hdr_pkt shdr;
	u32 flush_type;
};

struct hfi_msg_event_notify_pkt {
	struct hfi_session_hdr_pkt shdr;
	u32 event_id;
@@ -116,6 +135,11 @@ struct hfi_msg_sys_property_info_pkt {
	u8 data[];
};

struct hfi_msg_session_flush_done_pkt {
	struct hfi_msg_session_hdr_pkt shdr;
	u32 flush_type;
};

struct hfi_enable {
	u32 enable;
};
+38 −1
Original line number Diff line number Diff line
@@ -11,6 +11,7 @@ static void
iris_hfi_gen1_sys_event_notify(struct iris_core *core, void *packet)
{
	struct hfi_msg_event_notify_pkt *pkt = packet;
	struct iris_inst *instance;

	if (pkt->event_id == HFI_EVENT_SYS_ERROR)
		dev_err(core->dev, "sys error (type: %x, session id:%x, data1:%x, data2:%x)\n",
@@ -18,6 +19,12 @@ iris_hfi_gen1_sys_event_notify(struct iris_core *core, void *packet)
			pkt->event_data2);

	core->state = IRIS_CORE_ERROR;

	mutex_lock(&core->lock);
	list_for_each_entry(instance, &core->instances, list)
		iris_inst_change_state(instance, IRIS_INST_ERROR);
	mutex_unlock(&core->lock);

	schedule_delayed_work(&core->sys_error_handler, msecs_to_jiffies(10));
}

@@ -44,6 +51,7 @@ iris_hfi_gen1_event_session_error(struct iris_inst *inst, struct hfi_msg_event_n
			pkt->event_data2, pkt->event_data1,
			pkt->shdr.session_id);
		iris_vb2_queue_error(inst);
		iris_inst_change_state(inst, IRIS_INST_ERROR);
		break;
	}
}
@@ -148,6 +156,26 @@ static const struct iris_hfi_gen1_response_pkt_info pkt_infos[] = {
	 .pkt = HFI_MSG_SYS_SESSION_END,
	 .pkt_sz = sizeof(struct hfi_msg_session_hdr_pkt),
	},
	{
	 .pkt = HFI_MSG_SESSION_LOAD_RESOURCES,
	 .pkt_sz = sizeof(struct hfi_msg_session_hdr_pkt),
	},
	{
	 .pkt = HFI_MSG_SESSION_START,
	 .pkt_sz = sizeof(struct hfi_msg_session_hdr_pkt),
	},
	{
	 .pkt = HFI_MSG_SESSION_STOP,
	 .pkt_sz = sizeof(struct hfi_msg_session_hdr_pkt),
	},
	{
	 .pkt = HFI_MSG_SESSION_FLUSH,
	 .pkt_sz = sizeof(struct hfi_msg_session_flush_done_pkt),
	},
	{
	 .pkt = HFI_MSG_SESSION_RELEASE_RESOURCES,
	 .pkt_sz = sizeof(struct hfi_msg_session_hdr_pkt),
	},
};

static void iris_hfi_gen1_handle_response(struct iris_core *core, void *response)
@@ -156,6 +184,7 @@ static void iris_hfi_gen1_handle_response(struct iris_core *core, void *response
	const struct iris_hfi_gen1_response_pkt_info *pkt_info;
	struct device *dev = core->dev;
	struct hfi_session_pkt *pkt;
	struct completion *done;
	struct iris_inst *inst;
	bool found = false;
	u32 i;
@@ -205,7 +234,15 @@ static void iris_hfi_gen1_handle_response(struct iris_core *core, void *response
		}

		mutex_lock(&inst->lock);
		complete(&inst->completion);
		struct hfi_msg_session_hdr_pkt *shdr;

		shdr = (struct hfi_msg_session_hdr_pkt *)hdr;
		if (shdr->error_type != HFI_ERR_NONE)
			iris_inst_change_state(inst, IRIS_INST_ERROR);

		done = pkt_info->pkt == HFI_MSG_SESSION_FLUSH ?
			&inst->flush_completion : &inst->completion;
		complete(done);
		mutex_unlock(&inst->lock);

		break;
Loading