drivers/media/pci/intel/ipu6/ipu6-isys.c

Source file repositories/reference/linux-study-clean/drivers/media/pci/intel/ipu6/ipu6-isys.c

File Facts

System
Linux kernel
Corpus path
drivers/media/pci/intel/ipu6/ipu6-isys.c
Extension
.c
Size
37209 bytes
Lines
1366
Domain
Driver Families
Bucket
drivers/media
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

struct fwmsg {
	int type;
	char *msg;
	bool valid_ts;
};

static const struct fwmsg fw_msg[] = {
	{IPU6_FW_ISYS_RESP_TYPE_STREAM_OPEN_DONE, "STREAM_OPEN_DONE", 0},
	{IPU6_FW_ISYS_RESP_TYPE_STREAM_CLOSE_ACK, "STREAM_CLOSE_ACK", 0},
	{IPU6_FW_ISYS_RESP_TYPE_STREAM_START_ACK, "STREAM_START_ACK", 0},
	{IPU6_FW_ISYS_RESP_TYPE_STREAM_START_AND_CAPTURE_ACK,
	 "STREAM_START_AND_CAPTURE_ACK", 0},
	{IPU6_FW_ISYS_RESP_TYPE_STREAM_STOP_ACK, "STREAM_STOP_ACK", 0},
	{IPU6_FW_ISYS_RESP_TYPE_STREAM_FLUSH_ACK, "STREAM_FLUSH_ACK", 0},
	{IPU6_FW_ISYS_RESP_TYPE_PIN_DATA_READY, "PIN_DATA_READY", 1},
	{IPU6_FW_ISYS_RESP_TYPE_STREAM_CAPTURE_ACK, "STREAM_CAPTURE_ACK", 0},
	{IPU6_FW_ISYS_RESP_TYPE_STREAM_START_AND_CAPTURE_DONE,
	 "STREAM_START_AND_CAPTURE_DONE", 1},
	{IPU6_FW_ISYS_RESP_TYPE_STREAM_CAPTURE_DONE, "STREAM_CAPTURE_DONE", 1},
	{IPU6_FW_ISYS_RESP_TYPE_FRAME_SOF, "FRAME_SOF", 1},
	{IPU6_FW_ISYS_RESP_TYPE_FRAME_EOF, "FRAME_EOF", 1},
	{IPU6_FW_ISYS_RESP_TYPE_STATS_DATA_READY, "STATS_READY", 1},
	{-1, "UNKNOWN MESSAGE", 0}
};

static u32 resp_type_to_index(int type)
{
	unsigned int i;

	for (i = 0; i < ARRAY_SIZE(fw_msg); i++)
		if (fw_msg[i].type == type)
			return i;

	return  ARRAY_SIZE(fw_msg) - 1;
}

static int isys_isr_one(struct ipu6_bus_device *adev)
{
	struct ipu6_isys *isys = ipu6_bus_get_drvdata(adev);
	struct ipu6_fw_isys_resp_info_abi *resp;
	struct ipu6_isys_stream *stream;
	struct ipu6_isys_csi2 *csi2 = NULL;
	u32 index;
	u64 ts;

	if (!isys->fwcom)
		return 1;

	resp = ipu6_fw_isys_get_resp(isys->fwcom, IPU6_BASE_MSG_RECV_QUEUES);
	if (!resp)
		return 1;

	ts = (u64)resp->timestamp[1] << 32 | resp->timestamp[0];

	index = resp_type_to_index(resp->type);
	dev_dbg(&adev->auxdev.dev,
		"FW resp %02d %s, stream %u, ts 0x%16.16llx, pin %d\n",
		resp->type, fw_msg[index].msg, resp->stream_handle,
		fw_msg[index].valid_ts ? ts : 0, resp->pin_id);

	if (resp->error_info.error == IPU6_FW_ISYS_ERROR_STREAM_IN_SUSPENSION)
		/* Suspension is kind of special case: not enough buffers */
		dev_dbg(&adev->auxdev.dev,
			"FW error resp SUSPENSION, details %d\n",
			resp->error_info.error_details);
	else if (resp->error_info.error)
		dev_dbg(&adev->auxdev.dev,
			"FW error resp error %d, details %d\n",
			resp->error_info.error, resp->error_info.error_details);

	if (resp->stream_handle >= IPU6_ISYS_MAX_STREAMS) {
		dev_err(&adev->auxdev.dev, "bad stream handle %u\n",
			resp->stream_handle);
		goto leave;
	}

	stream = ipu6_isys_query_stream_by_handle(isys, resp->stream_handle);
	if (!stream) {
		dev_err(&adev->auxdev.dev, "stream of stream_handle %u is unused\n",
			resp->stream_handle);
		goto leave;
	}
	stream->error = resp->error_info.error;

	csi2 = ipu6_isys_subdev_to_csi2(stream->asd);

	switch (resp->type) {
	case IPU6_FW_ISYS_RESP_TYPE_STREAM_OPEN_DONE:
		complete(&stream->stream_open_completion);
		break;

Annotation

Implementation Notes