From 62eea8981471692403dcd505f9f6e486a595568b Mon Sep 17 00:00:00 2001 From: Avinash Kumar Date: Thu, 30 Jul 2026 03:54:41 +0000 Subject: [PATCH] ipu8: Fix firmware ABI handling for IPU8 1.0.14 For ipu8 new fw binary, code changes to isys needed. Adding patch for this change. Signed-off-by: Avinash Kumar --- ...mware-ABI-handling-for-IPU7-8-1.0.14.patch | 876 ++++++++++++++++++ 1 file changed, 876 insertions(+) create mode 100644 0008-ipu8-Fix-firmware-ABI-handling-for-IPU7-8-1.0.14.patch diff --git a/0008-ipu8-Fix-firmware-ABI-handling-for-IPU7-8-1.0.14.patch b/0008-ipu8-Fix-firmware-ABI-handling-for-IPU7-8-1.0.14.patch new file mode 100644 index 0000000..9ebc29e --- /dev/null +++ b/0008-ipu8-Fix-firmware-ABI-handling-for-IPU7-8-1.0.14.patch @@ -0,0 +1,876 @@ +From 5fa3d83fc1548924784bb6727ad50427509dedc4 Mon Sep 17 00:00:00 2001 +From: Avinash Kumar +Date: Thu, 2 Jul 2026 07:21:12 +0000 +Subject: [PATCH] ipu7: Fix firmware ABI handling for IPU7&8 1.0.14 + +For ipu8 new fw binary, code changes to isys needed + +Tracked-On: #JSWBALINUX-155 + +Change-Id: I01091c780ea72868133ae0074bbb8850527493d6 +Signed-off-by: Avinash Kumar +--- + .../staging/media/ipu7/abi/ipu7_fw_isys_abi.h | 122 +++++----- + drivers/staging/media/ipu7/ipu7-fw-isys.c | 220 +++++++++++++----- + drivers/staging/media/ipu7/ipu7-isys.h | 13 +- + 3 files changed, 227 insertions(+), 128 deletions(-) + +diff --git a/drivers/staging/media/ipu7/abi/ipu7_fw_isys_abi.h b/drivers/staging/media/ipu7/abi/ipu7_fw_isys_abi.h +index f32674f081d2..e25ca5f5541f 100644 +--- a/drivers/staging/media/ipu7/abi/ipu7_fw_isys_abi.h ++++ b/drivers/staging/media/ipu7/abi/ipu7_fw_isys_abi.h +@@ -2,16 +2,12 @@ + /* + * Copyright (C) 2020 - 2025 Intel Corporation + */ +- + #ifndef IPU7_FW_ISYS_ABI_H + #define IPU7_FW_ISYS_ABI_H +- + #include "ipu7_fw_common_abi.h" + #include "ipu7_fw_isys_abi.h" +- + #define IPU_INSYS_MAX_OUTPUT_QUEUES (3U) + #define IPU_INSYS_STREAM_ID_MAX (16U) +- + #define IPU_INSYS_MAX_INPUT_QUEUES (IPU_INSYS_STREAM_ID_MAX + 1U) + #define IPU_INSYS_OUTPUT_FIRST_QUEUE (0U) + #define IPU_INSYS_OUTPUT_LAST_QUEUE (IPU_INSYS_MAX_OUTPUT_QUEUES - 1U) +@@ -24,17 +20,12 @@ + #define IPU_INSYS_INPUT_DEV_QUEUE (IPU_INSYS_INPUT_FIRST_QUEUE) + #define IPU_INSYS_INPUT_MSG_QUEUE (IPU_INSYS_INPUT_FIRST_QUEUE + 1U) + #define IPU_INSYS_INPUT_MSG_MAX_QUEUE (IPU_INSYS_MAX_INPUT_QUEUES - 1U) +- + #define MAX_OPINS_FOR_SINGLE_IPINS (3U) + #define DEV_SEND_QUEUE_SIZE (IPU_INSYS_STREAM_ID_MAX) +- + #define PIN_PLANES_MAX (4U) +- + #define INSYS_MSG_ERR_STREAM_INSUFFICIENT_RESOURCES_INPUT \ + INSYS_MSG_ERR_STREAM_INSUFFICIENT_RESOURCES +- + typedef u64 ipu7_insys_return_token; +- + enum ipu7_insys_resp_type { + IPU_INSYS_RESP_TYPE_STREAM_OPEN_DONE = 0, + IPU_INSYS_RESP_TYPE_STREAM_START_AND_CAPTURE_ACK = 1, +@@ -49,7 +40,6 @@ enum ipu7_insys_resp_type { + IPU_INSYS_RESP_TYPE_STREAM_CAPTURE_DONE = 10, + N_IPU_INSYS_RESP_TYPE + }; +- + enum ipu7_insys_send_type { + IPU_INSYS_SEND_TYPE_STREAM_OPEN = 0, + IPU_INSYS_SEND_TYPE_STREAM_START_AND_CAPTURE = 1, +@@ -59,7 +49,6 @@ enum ipu7_insys_send_type { + IPU_INSYS_SEND_TYPE_STREAM_CLOSE = 5, + N_IPU_INSYS_SEND_TYPE + }; +- + enum ipu7_insys_mipi_vc { + IPU_INSYS_MIPI_VC_0 = 0, + IPU_INSYS_MIPI_VC_1 = 1, +@@ -79,7 +68,6 @@ enum ipu7_insys_mipi_vc { + IPU_INSYS_MIPI_VC_15 = 15, + N_IPU_INSYS_MIPI_VC + }; +- + enum ipu7_insys_mipi_port { + IPU_INSYS_MIPI_PORT_0 = 0, + IPU_INSYS_MIPI_PORT_1 = 1, +@@ -89,7 +77,6 @@ enum ipu7_insys_mipi_port { + IPU_INSYS_MIPI_PORT_5 = 5, + NA_IPU_INSYS_MIPI_PORT + }; +- + enum ipu7_insys_frame_format_type { + IPU_INSYS_FRAME_FORMAT_NV11 = 0, + IPU_INSYS_FRAME_FORMAT_NV12 = 1, +@@ -125,21 +112,26 @@ enum ipu7_insys_frame_format_type { + IPU_INSYS_FRAME_FORMAT_ARGB888 = 31, + IPU_INSYS_FRAME_FORMAT_BGRA888 = 32, + IPU_INSYS_FRAME_FORMAT_ABGR888 = 33, ++ IPU_INSYS_FRAME_FORMAT_RGB888 = 34, ++ IPU_INSYS_FRAME_FORMAT_YUV420_LEGACY = 35, ++ IPU_INSYS_FRAME_FORMAT_RAW6 = 36, ++ IPU_INSYS_FRAME_FORMAT_RAW7 = 37, ++ IPU_INSYS_FRAME_FORMAT_RGB444 = 38, ++ IPU_INSYS_FRAME_FORMAT_RGB666 = 39, ++ IPU_INSYS_FRAME_FORMAT_RAW20 = 40, ++ IPU_INSYS_FRAME_FORMAT_P010 = 41, ++ IPU_INSYS_FRAME_FORMAT_RGB555 = 42, + N_IPU_INSYS_FRAME_FORMAT + }; +- + #define IPU_INSYS_FRAME_FORMAT_RAW (IPU_INSYS_FRAME_FORMAT_RAW16) + #define N_IPU_INSYS_MIPI_DATA_TYPE 0x40 +- + enum ipu7_insys_mipi_dt_rename_mode { + IPU_INSYS_MIPI_DT_NO_RENAME = 0, + IPU_INSYS_MIPI_DT_RENAMED_MODE = 1, + N_IPU_INSYS_MIPI_DT_MODE + }; +- + #define IPU_INSYS_SEND_MSG_ENABLED 1U + #define IPU_INSYS_SEND_MSG_DISABLED 0U +- + #define IPU_INSYS_STREAM_SYNC_MSG_SEND_RESP_SOF BIT(0) + #define IPU_INSYS_STREAM_SYNC_MSG_SEND_RESP_EOF BIT(1) + #define IPU_INSYS_STREAM_SYNC_MSG_SEND_IRQ_SOF BIT(2) +@@ -158,7 +150,6 @@ enum ipu7_insys_mipi_dt_rename_mode { + IPU_INSYS_STREAM_SYNC_MSG_SEND_IRQ_EOF | \ + IPU_INSYS_STREAM_SYNC_MSG_SEND_IRQ_SOF_DISCARDED | \ + IPU_INSYS_STREAM_SYNC_MSG_SEND_IRQ_EOF_DISCARDED) +- + #define IPU_INSYS_STREAM_MSG_SEND_RESP_STREAM_OPEN_DONE BIT(0) + #define IPU_INSYS_STREAM_MSG_SEND_IRQ_STREAM_OPEN_DONE BIT(1) + #define IPU_INSYS_STREAM_MSG_SEND_RESP_STREAM_START_ACK BIT(2) +@@ -181,7 +172,6 @@ enum ipu7_insys_mipi_dt_rename_mode { + IPU_INSYS_STREAM_MSG_SEND_IRQ_STREAM_CLOSE_ACK | \ + IPU_INSYS_STREAM_MSG_SEND_IRQ_STREAM_FLUSH_ACK | \ + IPU_INSYS_STREAM_MSG_SEND_IRQ_STREAM_ABORT_ACK) +- + #define IPU_INSYS_FRAME_MSG_SEND_RESP_CAPTURE_ACK BIT(0) + #define IPU_INSYS_FRAME_MSG_SEND_IRQ_CAPTURE_ACK BIT(1) + #define IPU_INSYS_FRAME_MSG_SEND_RESP_CAPTURE_DONE BIT(2) +@@ -196,14 +186,12 @@ enum ipu7_insys_mipi_dt_rename_mode { + IPU_INSYS_FRAME_MSG_SEND_IRQ_CAPTURE_ACK | \ + IPU_INSYS_FRAME_MSG_SEND_IRQ_CAPTURE_DONE | \ + IPU_INSYS_FRAME_MSG_SEND_IRQ_PIN_DATA_READY) +- + enum ipu7_insys_output_link_dest { + IPU_INSYS_OUTPUT_LINK_DEST_MEM = 0, + IPU_INSYS_OUTPUT_LINK_DEST_PSYS = 1, + IPU_INSYS_OUTPUT_LINK_DEST_IPU_EXTERNAL = 2, + N_IPU_INSYS_OUTPUT_LINK_DEST + }; +- + enum ipu7_insys_dpcm_type { + IPU_INSYS_DPCM_TYPE_DISABLED = 0, + IPU_INSYS_DPCM_TYPE_10_8_10 = 1, +@@ -211,33 +199,27 @@ enum ipu7_insys_dpcm_type { + IPU_INSYS_DPCM_TYPE_12_10_12 = 3, + N_IPU_INSYS_DPCM_TYPE + }; +- + enum ipu7_insys_dpcm_predictor { + IPU_INSYS_DPCM_PREDICTOR_1 = 0, + IPU_INSYS_DPCM_PREDICTOR_2 = 1, + N_IPU_INSYS_DPCM_PREDICTOR + }; +- + enum ipu7_insys_send_queue_token_flag { + IPU_INSYS_SEND_QUEUE_TOKEN_FLAG_NONE = 0, + IPU_INSYS_SEND_QUEUE_TOKEN_FLAG_FLUSH_FORCE = 1, + N_IPU_INSYS_SEND_QUEUE_TOKEN_FLAG + }; +- + #define IPU_INSYS_MIPI_FRAME_NUMBER_DONT_CARE UINT16_MAX +- + #pragma pack(push, 1) + struct ipu7_insys_resolution { + u32 width; + u32 height; + }; +- + struct ipu7_insys_capture_output_pin_payload { + u64 user_token; + ia_gofo_addr_t addr; + u8 pad[4]; + }; +- + struct ipu7_insys_output_link { + u32 buffer_lines; + u16 foreign_key; +@@ -250,36 +232,32 @@ struct ipu7_insys_output_link { + u8 is_snoop; + u8 pad[2]; + }; +- ++struct ipu7_insys_output_cropping_v1 { ++ u16 line_top; ++ u16 line_bottom; ++}; + struct ipu7_insys_output_cropping { + u16 line_top; + u16 line_bottom; +-#ifdef IPU8_INSYS_NEW_ABI + u16 column_left; + u16 column_right; +-#endif + }; +- + struct ipu7_insys_output_dpcm { + u8 enable; + u8 type; + u8 predictor; + u8 pad; + }; +- +-#ifdef IPU8_INSYS_NEW_ABI + enum ipu_insys_cfa_dim { + IPU_INSYS_CFA_DIM_2x2 = 0, + IPU_INSYS_CFA_DIM_4x4 = 1, + N_IPU_INSYS_CFA_DIM + }; +- + #define IPU_INSYS_MAX_BINNING_FACTOR (4U) + #define IPU_INSYS_UPIPE_MAX_OUTPUTS (2U) + #define IPU_INSYS_UPIPE_MAX_UOB_FIFO_ALLOC (4U) + #define IPU_INSYS_UPIPE_STREAM_CFG_BUF_SIZE (32U) + #define IPU_INSYS_UPIPE_FRAME_CFG_BUF_SIZE (36U) +- + struct ipu7_insys_upipe_output_pin { + ia_gofo_addr_t opaque_pin_cfg; + u16 plane_offset_1; +@@ -288,36 +266,35 @@ struct ipu7_insys_upipe_output_pin { + u8 shared_uob_fifo; + u8 pad[2]; + }; +- + struct ipu7_insys_capture_output_pin_cfg { + struct ipu7_insys_capture_output_pin_payload pin_payload; + ia_gofo_addr_t upipe_capture_cfg; + }; +- +-#endif ++struct ipu7_insys_output_pin_v1 { ++ struct ipu7_insys_output_link link; ++ struct ipu7_insys_output_cropping_v1 crop; ++ struct ipu7_insys_output_dpcm dpcm; ++ u32 stride; ++ u16 ft; ++ u8 send_irq; ++ u8 input_pin_id; ++ u8 early_ack_en; ++ u8 pad[3]; ++}; + struct ipu7_insys_output_pin { + struct ipu7_insys_output_link link; + struct ipu7_insys_output_cropping crop; + struct ipu7_insys_output_dpcm dpcm; +-#ifdef IPU8_INSYS_NEW_ABI + struct ipu7_insys_upipe_output_pin upipe_pin_cfg; +-#endif + u32 stride; + u16 ft; +-#ifdef IPU8_INSYS_NEW_ABI + u8 upipe_enable; +-#endif + u8 send_irq; + u8 input_pin_id; + u8 early_ack_en; +-#ifdef IPU8_INSYS_NEW_ABI + u8 cfa_dim; + u8 binning_factor; +-#else +- u8 pad[3]; +-#endif + }; +- + struct ipu7_insys_input_pin { + struct ipu7_insys_resolution input_res; + u16 sync_msg_map; +@@ -327,7 +304,16 @@ struct ipu7_insys_input_pin { + u8 mapped_dt; + u8 pad[2]; + }; +- ++struct ipu7_insys_stream_cfg_v1 { ++ struct ipu7_insys_input_pin input_pins[4]; ++ struct ipu7_insys_output_pin_v1 output_pins[4]; ++ u16 stream_msg_map; ++ u8 port_id; ++ u8 vc; ++ u8 nof_input_pins; ++ u8 nof_output_pins; ++ u8 pad[2]; ++}; + struct ipu7_insys_stream_cfg { + struct ipu7_insys_input_pin input_pins[4]; + struct ipu7_insys_output_pin output_pins[4]; +@@ -338,42 +324,49 @@ struct ipu7_insys_stream_cfg { + u8 nof_output_pins; + u8 pad[2]; + }; +- ++struct ipu7_insys_buffset_v1 { ++ struct ipu7_insys_capture_output_pin_payload output_pins[4]; ++ u8 capture_msg_map; ++ u8 frame_id; ++ u8 skip_frame; ++ u8 pad[5]; ++}; + struct ipu7_insys_buffset { +-#ifdef IPU8_INSYS_NEW_ABI + struct ipu7_insys_capture_output_pin_cfg output_pins[4]; +-#else +- struct ipu7_insys_capture_output_pin_payload output_pins[4]; +-#endif + u8 capture_msg_map; + u8 frame_id; + u8 skip_frame; + u8 pad[5]; + }; +- +-struct ipu7_insys_resp { ++struct ipu7_insys_resp_v1 { + u64 buf_id; + struct ipu7_insys_capture_output_pin_payload pin; + struct ia_gofo_msg_err error_info; + u32 timestamp[2]; +-#ifdef IPU8_INSYS_NEW_ABI ++ u8 type; ++ u8 msg_link_streaming_mode; ++ u8 stream_id; ++ u8 pin_id; ++ u8 frame_id; ++ u8 skip_frame; + u16 mipi_fn; +-#endif ++}; ++struct ipu7_insys_resp { ++ u64 buf_id; ++ struct ipu7_insys_capture_output_pin_payload pin; ++ struct ia_gofo_msg_err error_info; ++ u32 timestamp[2]; + u8 type; + u8 msg_link_streaming_mode; + u8 stream_id; + u8 pin_id; + u8 frame_id; + u8 skip_frame; +-#ifndef IPU8_INSYS_NEW_ABI + u16 mipi_fn; +-#endif + }; +- + struct ipu7_insys_resp_queue_token { + struct ipu7_insys_resp resp_info; + }; +- + struct ipu7_insys_send_queue_token { + u64 buf_handle; + ia_gofo_addr_t addr; +@@ -381,9 +374,7 @@ struct ipu7_insys_send_queue_token { + u8 send_type; + u8 flag; + }; +- + #pragma pack(pop) +- + enum insys_msg_err_stream { + INSYS_MSG_ERR_STREAM_OK = IA_GOFO_MSG_ERR_OK, + INSYS_MSG_ERR_STREAM_STREAM_ID = 1, +@@ -424,17 +415,14 @@ enum insys_msg_err_stream { + INSYS_MSG_ERR_STREAM_INSUFFICIENT_RESOURCES_OUTPUT = 36, + INSYS_MSG_ERR_STREAM_WIDTH_OUTPUT_SIZE = 37, + INSYS_MSG_ERR_STREAM_CLOSED = 38, +-#ifdef IPU8_INSYS_NEW_ABI + INSYS_MSG_ERR_STREAM_BINNING_FACTOR_NOT_SUPPORTED = 39, + INSYS_MSG_ERR_STREAM_CFA_DIM_NOT_SUPPORTED = 40, + INSYS_MSG_ERR_STREAM_INVALID_UPIPE_ENABLE = 41, + INSYS_MSG_ERR_STREAM_INVALID_UPIPE_UOB_SINGLE = 42, + INSYS_MSG_ERR_STREAM_INVALID_UPIPE_UOB_SHARED = 43, + INSYS_MSG_ERR_STREAM_INVALID_UPIPE_OPAQUE_PIN_CFG = 44, +-#endif + INSYS_MSG_ERR_STREAM_N + }; +- + enum insys_msg_err_capture { + INSYS_MSG_ERR_CAPTURE_OK = IA_GOFO_MSG_ERR_OK, + INSYS_MSG_ERR_CAPTURE_STREAM_ID = 1, +@@ -463,7 +451,6 @@ enum insys_msg_err_capture { + INSYS_MSG_ERR_CAPTURE_CMD_SUBMIT_TO_HW = 24, + INSYS_MSG_ERR_CAPTURE_N + }; +- + enum insys_msg_err_groups { + INSYS_MSG_ERR_GROUP_RESERVED = IA_GOFO_MSG_ERR_GROUP_RESERVED, + INSYS_MSG_ERR_GROUP_GENERAL = IA_GOFO_MSG_ERR_GROUP_GENERAL, +@@ -471,5 +458,4 @@ enum insys_msg_err_groups { + INSYS_MSG_ERR_GROUP_CAPTURE = 3, + INSYS_MSG_ERR_GROUP_N, + }; +- + #endif +diff --git a/drivers/staging/media/ipu7/ipu7-fw-isys.c b/drivers/staging/media/ipu7/ipu7-fw-isys.c +index c98326bd9fee..b3cafb015f64 100644 +--- a/drivers/staging/media/ipu7/ipu7-fw-isys.c ++++ b/drivers/staging/media/ipu7/ipu7-fw-isys.c +@@ -2,17 +2,14 @@ + /* + * Copyright (C) 2013 - 2025 Intel Corporation + */ +- + #include + #include + #include + #include + #include + #include +- + #include "abi/ipu7_fw_insys_config_abi.h" + #include "abi/ipu7_fw_isys_abi.h" +- + #include "ipu7.h" + #include "ipu7-boot.h" + #include "ipu7-bus.h" +@@ -21,7 +18,6 @@ + #include "ipu7-isys.h" + #include "ipu7-platform-regs.h" + #include "ipu7-syscom.h" +- + static const char * const send_msg_types[N_IPU_INSYS_SEND_TYPE] = { + "STREAM_OPEN", + "STREAM_START_AND_CAPTURE", +@@ -30,7 +26,103 @@ static const char * const send_msg_types[N_IPU_INSYS_SEND_TYPE] = { + "STREAM_FLUSH", + "STREAM_CLOSE" + }; +- ++static void isys_stream_cfg_to_v1(struct ipu7_insys_stream_cfg_v1 *dst, ++ const struct ipu7_insys_stream_cfg *src) ++{ ++ unsigned int i; ++ memset(dst, 0, sizeof(*dst)); ++ memcpy(dst->input_pins, src->input_pins, sizeof(dst->input_pins)); ++ dst->stream_msg_map = src->stream_msg_map; ++ dst->port_id = src->port_id; ++ dst->vc = src->vc; ++ dst->nof_input_pins = src->nof_input_pins; ++ dst->nof_output_pins = src->nof_output_pins; ++ for (i = 0; i < ARRAY_SIZE(dst->output_pins); i++) { ++ dst->output_pins[i].link = src->output_pins[i].link; ++ dst->output_pins[i].crop.line_top = ++ src->output_pins[i].crop.line_top; ++ dst->output_pins[i].crop.line_bottom = ++ src->output_pins[i].crop.line_bottom; ++ dst->output_pins[i].dpcm = src->output_pins[i].dpcm; ++ dst->output_pins[i].stride = src->output_pins[i].stride; ++ dst->output_pins[i].ft = src->output_pins[i].ft; ++ dst->output_pins[i].send_irq = src->output_pins[i].send_irq; ++ dst->output_pins[i].input_pin_id = ++ src->output_pins[i].input_pin_id; ++ dst->output_pins[i].early_ack_en = ++ src->output_pins[i].early_ack_en; ++ } ++} ++static void isys_buffset_to_v1(struct ipu7_insys_buffset_v1 *dst, ++ const struct ipu7_insys_buffset *src) ++{ ++ unsigned int i; ++ memset(dst, 0, sizeof(*dst)); ++ for (i = 0; i < ARRAY_SIZE(dst->output_pins); i++) ++ dst->output_pins[i] = src->output_pins[i].pin_payload; ++ dst->capture_msg_map = src->capture_msg_map; ++ dst->frame_id = src->frame_id; ++ dst->skip_frame = src->skip_frame; ++} ++static size_t isys_prepare_fw_payload_v1(void *cpu_mapped_buf, ++ u16 send_type, size_t size) ++{ ++ if (!cpu_mapped_buf) ++ return 0; ++ switch (send_type) { ++ case IPU_INSYS_SEND_TYPE_STREAM_OPEN: { ++ struct ipu7_insys_stream_cfg cfg; ++ memcpy(&cfg, cpu_mapped_buf, sizeof(cfg)); ++ isys_stream_cfg_to_v1(cpu_mapped_buf, &cfg); ++ return sizeof(struct ipu7_insys_stream_cfg_v1); ++ } ++ case IPU_INSYS_SEND_TYPE_STREAM_START_AND_CAPTURE: ++ case IPU_INSYS_SEND_TYPE_STREAM_CAPTURE: { ++ struct ipu7_insys_buffset set; ++ memcpy(&set, cpu_mapped_buf, sizeof(set)); ++ isys_buffset_to_v1(cpu_mapped_buf, &set); ++ return sizeof(struct ipu7_insys_buffset_v1); ++ } ++ default: ++ return size; ++ } ++} ++static size_t isys_prepare_fw_payload(void *cpu_mapped_buf, ++ u16 send_type, size_t size) ++{ ++ if (!cpu_mapped_buf) ++ return 0; ++ switch (send_type) { ++ case IPU_INSYS_SEND_TYPE_STREAM_OPEN: ++ return sizeof(struct ipu7_insys_stream_cfg); ++ case IPU_INSYS_SEND_TYPE_STREAM_START_AND_CAPTURE: ++ case IPU_INSYS_SEND_TYPE_STREAM_CAPTURE: ++ return sizeof(struct ipu7_insys_buffset); ++ default: ++ return size; ++ } ++} ++static __maybe_unused void isys_decode_resp_v1(struct ipu7_insys_resp *dst, const void *token) ++{ ++ const struct ipu7_insys_resp_v1 *src = token; ++ memset(dst, 0, sizeof(*dst)); ++ dst->buf_id = src->buf_id; ++ dst->pin = src->pin; ++ dst->error_info = src->error_info; ++ dst->timestamp[0] = src->timestamp[0]; ++ dst->timestamp[1] = src->timestamp[1]; ++ dst->type = src->type; ++ dst->msg_link_streaming_mode = src->msg_link_streaming_mode; ++ dst->stream_id = src->stream_id; ++ dst->pin_id = src->pin_id; ++ dst->frame_id = src->frame_id; ++ dst->skip_frame = src->skip_frame; ++ dst->mipi_fn = src->mipi_fn; ++} ++static void isys_decode_resp(struct ipu7_insys_resp *dst, const void *token) ++{ ++ memcpy(dst, token, sizeof(*dst)); ++} + int ipu7_fw_isys_complex_cmd(struct ipu7_isys *isys, + const unsigned int stream_handle, + void *cpu_mapped_buf, +@@ -40,44 +132,38 @@ int ipu7_fw_isys_complex_cmd(struct ipu7_isys *isys, + struct ipu7_syscom_context *ctx = isys->adev->syscom; + struct device *dev = &isys->adev->auxdev.dev; + struct ipu7_insys_send_queue_token *token; +- + if (send_type >= N_IPU_INSYS_SEND_TYPE) + return -EINVAL; +- + dev_dbg(dev, "send_token: %s\n", send_msg_types[send_type]); +- + /* + * Time to flush cache in case we have some payload. Not all messages + * have that + */ +- if (cpu_mapped_buf) ++ if (cpu_mapped_buf) { ++ size = isys->abi_ops.prepare_payload(cpu_mapped_buf, ++ send_type, size); + clflush_cache_range(cpu_mapped_buf, size); +- ++ } + token = ipu7_syscom_get_token(ctx, stream_handle + + IPU_INSYS_INPUT_MSG_QUEUE); + if (!token) + return -EBUSY; +- + token->addr = dma_mapped_buf; + token->buf_handle = (unsigned long)cpu_mapped_buf; + token->send_type = send_type; + token->stream_id = stream_handle; + token->flag = IPU_INSYS_SEND_QUEUE_TOKEN_FLAG_NONE; +- + ipu7_syscom_put_token(ctx, stream_handle + IPU_INSYS_INPUT_MSG_QUEUE); + /* now wakeup FW */ + ipu_buttress_wakeup_is_uc(isys->adev->isp); +- + return 0; + } +- + int ipu7_fw_isys_simple_cmd(struct ipu7_isys *isys, + const unsigned int stream_handle, u16 send_type) + { + return ipu7_fw_isys_complex_cmd(isys, stream_handle, NULL, 0, 0, + send_type); + } +- + int ipu7_fw_isys_init(struct ipu7_isys *isys) + { + struct syscom_queue_config *queue_configs; +@@ -96,7 +182,13 @@ int ipu7_fw_isys_init(struct ipu7_isys *isys) + GFP_KERNEL); + if (!syscom) + return -ENOMEM; +- ++ if (is_ipu8(adev->isp->hw_ver)) ++ isys->abi_ops.prepare_payload = isys_prepare_fw_payload; ++ else ++ isys->abi_ops.prepare_payload = isys_prepare_fw_payload_v1; ++ isys->abi_ops.decode_resp = isys_decode_resp; ++ isys->abi_ops.resp_queue_token_size = ++ sizeof(struct ipu7_insys_resp); + adev->syscom = syscom; + syscom->num_input_queues = IPU_INSYS_MAX_INPUT_QUEUES; + syscom->num_output_queues = IPU_INSYS_MAX_OUTPUT_QUEUES; +@@ -111,25 +203,22 @@ int ipu7_fw_isys_init(struct ipu7_isys *isys) + queue_configs[IPU_INSYS_OUTPUT_MSG_QUEUE].max_capacity = + IPU_ISYS_SIZE_RECV_QUEUE; + queue_configs[IPU_INSYS_OUTPUT_MSG_QUEUE].token_size_in_bytes = +- sizeof(struct ipu7_insys_resp); ++ isys->abi_ops.resp_queue_token_size; + queue_configs[IPU_INSYS_OUTPUT_LOG_QUEUE].max_capacity = + IPU_ISYS_SIZE_LOG_QUEUE; + queue_configs[IPU_INSYS_OUTPUT_LOG_QUEUE].token_size_in_bytes = +- sizeof(struct ipu7_insys_resp); ++ isys->abi_ops.resp_queue_token_size; + queue_configs[IPU_INSYS_OUTPUT_RESERVED_QUEUE].max_capacity = 0; + queue_configs[IPU_INSYS_OUTPUT_RESERVED_QUEUE].token_size_in_bytes = 0; +- + queue_configs[IPU_INSYS_INPUT_DEV_QUEUE].max_capacity = + IPU_ISYS_MAX_STREAMS; + queue_configs[IPU_INSYS_INPUT_DEV_QUEUE].token_size_in_bytes = + sizeof(struct ipu7_insys_send_queue_token); +- + for (i = IPU_INSYS_INPUT_MSG_QUEUE; i < num_queues; i++) { + queue_configs[i].max_capacity = IPU_ISYS_SIZE_SEND_QUEUE; + queue_configs[i].token_size_in_bytes = + sizeof(struct ipu7_insys_send_queue_token); + } +- + /* Allocate ISYS subsys config. */ + isys_config = ipu7_dma_alloc(adev, sizeof(struct ipu7_insys_config), + &isys_config_dma_addr, GFP_KERNEL, 0); +@@ -155,23 +244,19 @@ int ipu7_fw_isys_init(struct ipu7_isys *isys) + ipu7_fw_isys_release(isys); + return ret; + } +- + ipu7_dma_sync_single(adev, isys_config_dma_addr, + sizeof(struct ipu7_insys_config)); +- + major = is_ipu8(adev->isp->hw_ver) ? 2U : 1U; + ret = ipu7_boot_init_boot_config(adev, queue_configs, num_queues, + freq, isys_config_dma_addr, major); + if (ret) + ipu7_fw_isys_release(isys); +- + return ret; + } +- + void ipu7_fw_isys_release(struct ipu7_isys *isys) + { + struct ipu7_bus_device *adev = isys->adev; +- ++ struct device *dev = &isys->adev->auxdev.dev; + ipu7_boot_release_boot_config(adev); + if (isys->subsys_config) { + ipu7_dma_free(adev, +@@ -182,43 +267,85 @@ void ipu7_fw_isys_release(struct ipu7_isys *isys) + isys->subsys_config_dma_addr = 0; + } + } +- + int ipu7_fw_isys_open(struct ipu7_isys *isys) + { + return ipu7_boot_start_fw(isys->adev); + } +- + int ipu7_fw_isys_close(struct ipu7_isys *isys) + { + return ipu7_boot_stop_fw(isys->adev); + } +- + struct ipu7_insys_resp *ipu7_fw_isys_get_resp(struct ipu7_isys *isys) + { +- return (struct ipu7_insys_resp *) +- ipu7_syscom_get_token(isys->adev->syscom, +- IPU_INSYS_OUTPUT_MSG_QUEUE); ++ void *token = ipu7_syscom_get_token(isys->adev->syscom, ++ IPU_INSYS_OUTPUT_MSG_QUEUE); ++ if (!token) ++ return NULL; ++ isys->abi_ops.decode_resp(&isys->resp, token); ++ return &isys->resp; + } +- + void ipu7_fw_isys_put_resp(struct ipu7_isys *isys) + { + ipu7_syscom_put_token(isys->adev->syscom, IPU_INSYS_OUTPUT_MSG_QUEUE); + } +- ++#ifdef ENABLE_FW_OFFLINE_LOGGER ++int ipu7_fw_isys_get_log(struct ipu7_isys *isys) ++{ ++ u32 log_size = sizeof(struct ia_gofo_msg_log_info_ts); ++ struct device *dev = &isys->adev->auxdev.dev; ++ struct isys_fw_log *fw_log = isys->fw_log; ++ struct ia_gofo_msg_log *log_msg; ++ u8 msg_type, msg_len; ++ u32 count, fmt_id; ++ void *token; ++ token = ipu7_syscom_get_token(isys->adev->syscom, ++ IPU_INSYS_OUTPUT_LOG_QUEUE); ++ if (!token) ++ return -ENODATA; ++ while (token) { ++ log_msg = (struct ia_gofo_msg_log *)token; ++ msg_type = log_msg->header.tlv_header.tlv_type; ++ msg_len = log_msg->header.tlv_header.tlv_len32; ++ if (msg_type != IPU_MSG_TYPE_DEV_LOG || !msg_len) ++ dev_warn(dev, "Invalid msg data from Log queue!\n"); ++ count = log_msg->log_info_ts.log_info.log_counter; ++ fmt_id = log_msg->log_info_ts.log_info.fmt_id; ++ if (count > fw_log->count + 1) ++ dev_warn(dev, "log msg lost, count %u+1 != %u!\n", ++ count, fw_log->count); ++ if (fmt_id == IA_GOFO_MSG_LOG_FMT_ID_INVALID) { ++ dev_err(dev, "invalid log msg fmt_id 0x%x!\n", fmt_id); ++ ipu7_syscom_put_token(isys->adev->syscom, ++ IPU_INSYS_OUTPUT_LOG_QUEUE); ++ return -EIO; ++ } ++ if (log_size + fw_log->head - fw_log->addr > ++ FW_LOG_BUF_SIZE) ++ fw_log->head = fw_log->addr; ++ memcpy(fw_log->head, (void *)&log_msg->log_info_ts, ++ sizeof(struct ia_gofo_msg_log_info_ts)); ++ fw_log->count = count; ++ fw_log->head += log_size; ++ fw_log->size += log_size; ++ ipu7_syscom_put_token(isys->adev->syscom, ++ IPU_INSYS_OUTPUT_LOG_QUEUE); ++ token = ipu7_syscom_get_token(isys->adev->syscom, ++ IPU_INSYS_OUTPUT_LOG_QUEUE); ++ }; ++ return 0; ++} ++#endif + void ipu7_fw_isys_dump_stream_cfg(struct device *dev, + struct ipu7_insys_stream_cfg *cfg) + { + unsigned int i; +- + dev_dbg(dev, "---------------------------\n"); + dev_dbg(dev, "IPU_FW_ISYS_STREAM_CFG_DATA\n"); +- + dev_dbg(dev, ".port id %d\n", cfg->port_id); + dev_dbg(dev, ".vc %d\n", cfg->vc); + dev_dbg(dev, ".nof_input_pins = %d\n", cfg->nof_input_pins); + dev_dbg(dev, ".nof_output_pins = %d\n", cfg->nof_output_pins); + dev_dbg(dev, ".stream_msg_map = 0x%x\n", cfg->stream_msg_map); +- + for (i = 0; i < cfg->nof_input_pins; i++) { + dev_dbg(dev, ".input_pin[%d]:\n", i); + dev_dbg(dev, "\t.dt = 0x%0x\n", +@@ -235,7 +362,6 @@ void ipu7_fw_isys_dump_stream_cfg(struct device *dev, + dev_dbg(dev, "\t.sync_msg_map = 0x%x\n", + cfg->input_pins[i].sync_msg_map); + } +- + for (i = 0; i < cfg->nof_output_pins; i++) { + dev_dbg(dev, ".output_pin[%d]:\n", i); + dev_dbg(dev, "\t.input_pin_id = %d\n", +@@ -244,7 +370,6 @@ void ipu7_fw_isys_dump_stream_cfg(struct device *dev, + dev_dbg(dev, "\t.send_irq = %d\n", + cfg->output_pins[i].send_irq); + dev_dbg(dev, "\t.ft = %d\n", cfg->output_pins[i].ft); +- + dev_dbg(dev, "\t.link.buffer_lines = %d\n", + cfg->output_pins[i].link.buffer_lines); + dev_dbg(dev, "\t.link.foreign_key = %d\n", +@@ -263,25 +388,20 @@ void ipu7_fw_isys_dump_stream_cfg(struct device *dev, + cfg->output_pins[i].link.use_sw_managed); + dev_dbg(dev, "\t.link.is_snoop = %d\n", + cfg->output_pins[i].link.is_snoop); +- + dev_dbg(dev, "\t.crop.line_top = %d\n", + cfg->output_pins[i].crop.line_top); + dev_dbg(dev, "\t.crop.line_bottom = %d\n", + cfg->output_pins[i].crop.line_bottom); +-#ifdef IPU8_INSYS_NEW_ABI + dev_dbg(dev, "\t.crop.column_left = %d\n", + cfg->output_pins[i].crop.column_left); +- dev_dbg(dev, "\t.crop.colunm_right = %d\n", ++ dev_dbg(dev, "\t.crop.column_right = %d\n", + cfg->output_pins[i].crop.column_right); +-#endif +- + dev_dbg(dev, "\t.dpcm_enable = %d\n", + cfg->output_pins[i].dpcm.enable); + dev_dbg(dev, "\t.dpcm.type = %d\n", + cfg->output_pins[i].dpcm.type); + dev_dbg(dev, "\t.dpcm.predictor = %d\n", + cfg->output_pins[i].dpcm.predictor); +-#ifdef IPU8_INSYS_NEW_ABI + dev_dbg(dev, "\t.upipe_enable = %d\n", + cfg->output_pins[i].upipe_enable); + dev_dbg(dev, "\t.upipe_pin_cfg.opaque_pin_cfg = %d\n", +@@ -294,37 +414,27 @@ void ipu7_fw_isys_dump_stream_cfg(struct device *dev, + cfg->output_pins[i].upipe_pin_cfg.single_uob_fifo); + dev_dbg(dev, "\t.upipe_pin_cfg.shared_uob_fifo = %d\n", + cfg->output_pins[i].upipe_pin_cfg.shared_uob_fifo); +-#endif + } + dev_dbg(dev, "---------------------------\n"); + } +- + void ipu7_fw_isys_dump_frame_buff_set(struct device *dev, + struct ipu7_insys_buffset *buf, + unsigned int outputs) + { + unsigned int i; +- + dev_dbg(dev, "--------------------------\n"); + dev_dbg(dev, "IPU_ISYS_BUFF_SET\n"); + dev_dbg(dev, ".capture_msg_map = %d\n", buf->capture_msg_map); + dev_dbg(dev, ".frame_id = %d\n", buf->frame_id); + dev_dbg(dev, ".skip_frame = %d\n", buf->skip_frame); +- + for (i = 0; i < outputs; i++) { + dev_dbg(dev, ".output_pin[%d]:\n", i); +-#ifndef IPU8_INSYS_NEW_ABI +- dev_dbg(dev, "\t.user_token = %llx\n", +- buf->output_pins[i].user_token); +- dev_dbg(dev, "\t.addr = 0x%x\n", buf->output_pins[i].addr); +-#else + dev_dbg(dev, "\t.pin_payload.user_token = %llx\n", + buf->output_pins[i].pin_payload.user_token); + dev_dbg(dev, "\t.pin_payload.addr = 0x%x\n", + buf->output_pins[i].pin_payload.addr); + dev_dbg(dev, "\t.pin_payload.upipe_capture_cfg = 0x%x\n", + buf->output_pins[i].upipe_capture_cfg); +-#endif + } + dev_dbg(dev, "---------------------------\n"); + } +diff --git a/drivers/staging/media/ipu7/ipu7-isys.h b/drivers/staging/media/ipu7/ipu7-isys.h +index 2579669c21a9..2d32dc1c2a1d 100644 +--- a/drivers/staging/media/ipu7/ipu7-isys.h ++++ b/drivers/staging/media/ipu7/ipu7-isys.h +@@ -58,7 +58,12 @@ struct isys_fw_log { + u32 count; /* running counter of log */ + u32 size; /* actual size of log content, in bits */ + }; +- ++struct ipu7_isys_abi_ops { ++ size_t (*prepare_payload)(void *cpu_mapped_buf, u16 send_type, ++ size_t size); ++ void (*decode_resp)(struct ipu7_insys_resp *dst, const void *token); ++ size_t resp_queue_token_size; ++}; + /* + * struct ipu7_isys + * +@@ -113,7 +118,8 @@ struct ipu7_isys { + struct list_head framebuflist; + struct list_head framebuflist_fw; + struct v4l2_async_notifier notifier; +- ++ struct ipu7_isys_abi_ops abi_ops; ++ struct ipu7_insys_resp resp; + struct ipu7_insys_config *subsys_config; + dma_addr_t subsys_config_dma_addr; + }; +@@ -127,18 +133,15 @@ struct isys_fw_msgs { + struct list_head head; + dma_addr_t dma_addr; + }; +- + struct ipu7_isys_csi2_config { + unsigned int nlanes; + unsigned int port; + enum v4l2_mbus_type bus_type; + }; +- + struct sensor_async_sd { + struct v4l2_async_connection asc; + struct ipu7_isys_csi2_config csi2; + }; +- + struct isys_fw_msgs *ipu7_get_fw_msg_buf(struct ipu7_isys_stream *stream); + void ipu7_put_fw_msg_buf(struct ipu7_isys *isys, uintptr_t data); + void ipu7_cleanup_fw_msg_bufs(struct ipu7_isys *isys); +-- +2.43.0 +