Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

media: iris: introduce host firmware interface with necessary hooks

The Host firmware interface (HFI) is a well defined set of interfaces
for the communication between the host driver and the firmware. The
commands and responses are exchanged in form of packets. One or multiple
packets are grouped under the packet header. Each packet has a packet
type which describes the specific HFI and the payload, which holds the
corresponding value for that HFI.

Tested-by: Stefan Schmidt <stefan.schmidt@linaro.org> # x1e80100 (Dell XPS 13 9345)
Reviewed-by: Stefan 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: Dikshita Agarwal <quic_dikshita@quicinc.com>
Signed-off-by: Hans Verkuil <hverkuil@xs4all.nl>

authored by

Dikshita Agarwal and committed by
Hans Verkuil
fb583a21 abf5bac6

+1341 -1
+4
drivers/media/platform/qcom/iris/Makefile
··· 1 1 iris-objs += iris_core.o \ 2 2 iris_firmware.o \ 3 + iris_hfi_common.o \ 3 4 iris_hfi_gen1_command.o \ 5 + iris_hfi_gen1_response.o \ 4 6 iris_hfi_gen2_command.o \ 7 + iris_hfi_gen2_packet.o \ 8 + iris_hfi_gen2_response.o \ 5 9 iris_hfi_queue.o \ 6 10 iris_platform_sm8550.o \ 7 11 iris_probe.o \
+23 -1
drivers/media/platform/qcom/iris/iris_core.c
··· 17 17 mutex_unlock(&core->lock); 18 18 } 19 19 20 + static int iris_wait_for_system_response(struct iris_core *core) 21 + { 22 + u32 hw_response_timeout_val = core->iris_platform_data->hw_response_timeout; 23 + int ret; 24 + 25 + if (core->state == IRIS_CORE_ERROR) 26 + return -EIO; 27 + 28 + ret = wait_for_completion_timeout(&core->core_init_done, 29 + msecs_to_jiffies(hw_response_timeout_val)); 30 + if (!ret) { 31 + core->state = IRIS_CORE_ERROR; 32 + return -ETIMEDOUT; 33 + } 34 + 35 + return 0; 36 + } 37 + 20 38 int iris_core_init(struct iris_core *core) 21 39 { 22 40 int ret; ··· 62 44 if (ret) 63 45 goto error_unload_fw; 64 46 47 + ret = iris_hfi_core_init(core); 48 + if (ret) 49 + goto error_unload_fw; 50 + 65 51 mutex_unlock(&core->lock); 66 52 67 - return 0; 53 + return iris_wait_for_system_response(core); 68 54 69 55 error_unload_fw: 70 56 iris_fw_unload(core);
+20
drivers/media/platform/qcom/iris/iris_core.h
··· 9 9 #include <linux/types.h> 10 10 #include <media/v4l2-device.h> 11 11 12 + #include "iris_hfi_common.h" 12 13 #include "iris_hfi_queue.h" 13 14 #include "iris_platform_common.h" 14 15 #include "iris_state.h" ··· 19 18 u32 bw_min_kbps; 20 19 u32 bw_max_kbps; 21 20 }; 21 + 22 + #define IRIS_FW_VERSION_LENGTH 128 23 + #define IFACEQ_CORE_PKT_SIZE (1024 * 4) 22 24 23 25 /** 24 26 * struct iris_core - holds core parameters valid for all instances ··· 49 45 * @message_queue: shared interface queue to receive responses from firmware 50 46 * @debug_queue: shared interface queue to receive debug info from firmware 51 47 * @lock: a lock for this strucure 48 + * @response_packet: a pointer to response packet from fw to driver 49 + * @header_id: id of packet header 50 + * @packet_id: id of packet 51 + * @hfi_ops: iris hfi command ops 52 + * @hfi_response_ops: iris hfi response ops 53 + * @core_init_done: structure of signal completion for system response 54 + * @intr_status: interrupt status 55 + * @sys_error_handler: a delayed work for handling system fatal error 52 56 */ 53 57 54 58 struct iris_core { ··· 83 71 struct iris_iface_q_info message_queue; 84 72 struct iris_iface_q_info debug_queue; 85 73 struct mutex lock; /* lock for core related operations */ 74 + u8 *response_packet; 75 + u32 header_id; 76 + u32 packet_id; 77 + const struct iris_hfi_command_ops *hfi_ops; 78 + const struct iris_hfi_response_ops *hfi_response_ops; 79 + struct completion core_init_done; 80 + u32 intr_status; 81 + struct delayed_work sys_error_handler; 86 82 }; 87 83 88 84 int iris_core_init(struct iris_core *core);
+50
drivers/media/platform/qcom/iris/iris_hfi_common.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + /* 3 + * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved. 4 + */ 5 + 6 + #include "iris_core.h" 7 + #include "iris_hfi_common.h" 8 + #include "iris_vpu_common.h" 9 + 10 + int iris_hfi_core_init(struct iris_core *core) 11 + { 12 + const struct iris_hfi_command_ops *hfi_ops = core->hfi_ops; 13 + int ret; 14 + 15 + ret = hfi_ops->sys_init(core); 16 + if (ret) 17 + return ret; 18 + 19 + ret = hfi_ops->sys_image_version(core); 20 + if (ret) 21 + return ret; 22 + 23 + return hfi_ops->sys_interframe_powercollapse(core); 24 + } 25 + 26 + irqreturn_t iris_hfi_isr(int irq, void *data) 27 + { 28 + disable_irq_nosync(irq); 29 + 30 + return IRQ_WAKE_THREAD; 31 + } 32 + 33 + irqreturn_t iris_hfi_isr_handler(int irq, void *data) 34 + { 35 + struct iris_core *core = data; 36 + 37 + if (!core) 38 + return IRQ_NONE; 39 + 40 + mutex_lock(&core->lock); 41 + iris_vpu_clear_interrupt(core); 42 + mutex_unlock(&core->lock); 43 + 44 + core->hfi_response_ops->hfi_response_handler(core); 45 + 46 + if (!iris_vpu_watchdog(core, core->intr_status)) 47 + enable_irq(irq); 48 + 49 + return IRQ_HANDLED; 50 + }
+60
drivers/media/platform/qcom/iris/iris_hfi_common.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0-only */ 2 + /* 3 + * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved. 4 + */ 5 + 6 + #ifndef __IRIS_HFI_COMMON_H__ 7 + #define __IRIS_HFI_COMMON_H__ 8 + 9 + #include <linux/types.h> 10 + #include <media/v4l2-device.h> 11 + 12 + struct iris_core; 13 + 14 + enum hfi_packet_port_type { 15 + HFI_PORT_NONE = 0x00000000, 16 + HFI_PORT_BITSTREAM = 0x00000001, 17 + HFI_PORT_RAW = 0x00000002, 18 + }; 19 + 20 + enum hfi_packet_payload_info { 21 + HFI_PAYLOAD_NONE = 0x00000000, 22 + HFI_PAYLOAD_U32 = 0x00000001, 23 + HFI_PAYLOAD_S32 = 0x00000002, 24 + HFI_PAYLOAD_U64 = 0x00000003, 25 + HFI_PAYLOAD_S64 = 0x00000004, 26 + HFI_PAYLOAD_STRUCTURE = 0x00000005, 27 + HFI_PAYLOAD_BLOB = 0x00000006, 28 + HFI_PAYLOAD_STRING = 0x00000007, 29 + HFI_PAYLOAD_Q16 = 0x00000008, 30 + HFI_PAYLOAD_U32_ENUM = 0x00000009, 31 + HFI_PAYLOAD_32_PACKED = 0x0000000a, 32 + HFI_PAYLOAD_U32_ARRAY = 0x0000000b, 33 + HFI_PAYLOAD_S32_ARRAY = 0x0000000c, 34 + HFI_PAYLOAD_64_PACKED = 0x0000000d, 35 + }; 36 + 37 + enum hfi_packet_host_flags { 38 + HFI_HOST_FLAGS_NONE = 0x00000000, 39 + HFI_HOST_FLAGS_INTR_REQUIRED = 0x00000001, 40 + HFI_HOST_FLAGS_RESPONSE_REQUIRED = 0x00000002, 41 + HFI_HOST_FLAGS_NON_DISCARDABLE = 0x00000004, 42 + HFI_HOST_FLAGS_GET_PROPERTY = 0x00000008, 43 + }; 44 + 45 + struct iris_hfi_command_ops { 46 + int (*sys_init)(struct iris_core *core); 47 + int (*sys_image_version)(struct iris_core *core); 48 + int (*sys_interframe_powercollapse)(struct iris_core *core); 49 + }; 50 + 51 + struct iris_hfi_response_ops { 52 + void (*hfi_response_handler)(struct iris_core *core); 53 + }; 54 + 55 + int iris_hfi_core_init(struct iris_core *core); 56 + 57 + irqreturn_t iris_hfi_isr(int irq, void *data); 58 + irqreturn_t iris_hfi_isr_handler(int irq, void *data); 59 + 60 + #endif
+3
drivers/media/platform/qcom/iris/iris_hfi_gen1.h
··· 6 6 #ifndef __IRIS_HFI_GEN1_H__ 7 7 #define __IRIS_HFI_GEN1_H__ 8 8 9 + struct iris_core; 9 10 struct iris_inst; 10 11 12 + void iris_hfi_gen1_command_ops_init(struct iris_core *core); 13 + void iris_hfi_gen1_response_ops_init(struct iris_core *core); 11 14 struct iris_inst *iris_hfi_gen1_get_instance(void); 12 15 13 16 #endif
+61
drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c
··· 4 4 */ 5 5 6 6 #include "iris_hfi_gen1.h" 7 + #include "iris_hfi_gen1_defines.h" 7 8 #include "iris_instance.h" 9 + 10 + static int iris_hfi_gen1_sys_init(struct iris_core *core) 11 + { 12 + struct hfi_sys_init_pkt sys_init_pkt; 13 + 14 + sys_init_pkt.hdr.size = sizeof(sys_init_pkt); 15 + sys_init_pkt.hdr.pkt_type = HFI_CMD_SYS_INIT; 16 + sys_init_pkt.arch_type = HFI_VIDEO_ARCH_OX; 17 + 18 + return iris_hfi_queue_cmd_write_locked(core, &sys_init_pkt, sys_init_pkt.hdr.size); 19 + } 20 + 21 + static int iris_hfi_gen1_sys_image_version(struct iris_core *core) 22 + { 23 + struct hfi_sys_get_property_pkt packet; 24 + 25 + packet.hdr.size = sizeof(packet); 26 + packet.hdr.pkt_type = HFI_CMD_SYS_GET_PROPERTY; 27 + packet.num_properties = 1; 28 + packet.data = HFI_PROPERTY_SYS_IMAGE_VERSION; 29 + 30 + return iris_hfi_queue_cmd_write_locked(core, &packet, packet.hdr.size); 31 + } 32 + 33 + static int iris_hfi_gen1_sys_interframe_powercollapse(struct iris_core *core) 34 + { 35 + struct hfi_sys_set_property_pkt *pkt; 36 + struct hfi_enable *hfi; 37 + u32 packet_size; 38 + int ret; 39 + 40 + packet_size = struct_size(pkt, data, 1) + sizeof(*hfi); 41 + pkt = kzalloc(packet_size, GFP_KERNEL); 42 + if (!pkt) 43 + return -ENOMEM; 44 + 45 + hfi = (struct hfi_enable *)&pkt->data[1]; 46 + 47 + pkt->hdr.size = packet_size; 48 + pkt->hdr.pkt_type = HFI_CMD_SYS_SET_PROPERTY; 49 + pkt->num_properties = 1; 50 + pkt->data[0] = HFI_PROPERTY_SYS_CODEC_POWER_PLANE_CTRL; 51 + hfi->enable = true; 52 + 53 + ret = iris_hfi_queue_cmd_write_locked(core, pkt, pkt->hdr.size); 54 + kfree(pkt); 55 + 56 + return ret; 57 + } 58 + 59 + static const struct iris_hfi_command_ops iris_hfi_gen1_command_ops = { 60 + .sys_init = iris_hfi_gen1_sys_init, 61 + .sys_image_version = iris_hfi_gen1_sys_image_version, 62 + .sys_interframe_powercollapse = iris_hfi_gen1_sys_interframe_powercollapse, 63 + }; 64 + 65 + void iris_hfi_gen1_command_ops_init(struct iris_core *core) 66 + { 67 + core->hfi_ops = &iris_hfi_gen1_command_ops; 68 + } 8 69 9 70 struct iris_inst *iris_hfi_gen1_get_instance(void) 10 71 {
+94
drivers/media/platform/qcom/iris/iris_hfi_gen1_defines.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0-only */ 2 + /* 3 + * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved. 4 + */ 5 + 6 + #ifndef __IRIS_HFI_GEN1_DEFINES_H__ 7 + #define __IRIS_HFI_GEN1_DEFINES_H__ 8 + 9 + #include <linux/types.h> 10 + 11 + #define HFI_VIDEO_ARCH_OX 0x1 12 + #define HFI_ERR_NONE 0x0 13 + 14 + #define HFI_CMD_SYS_INIT 0x10001 15 + #define HFI_CMD_SYS_SET_PROPERTY 0x10005 16 + #define HFI_CMD_SYS_GET_PROPERTY 0x10006 17 + 18 + #define HFI_PROPERTY_SYS_CODEC_POWER_PLANE_CTRL 0x5 19 + #define HFI_PROPERTY_SYS_IMAGE_VERSION 0x6 20 + 21 + #define HFI_EVENT_SYS_ERROR 0x1 22 + 23 + #define HFI_MSG_SYS_INIT 0x20001 24 + #define HFI_MSG_SYS_COV 0x20009 25 + #define HFI_MSG_SYS_PROPERTY_INFO 0x2000a 26 + 27 + #define HFI_MSG_EVENT_NOTIFY 0x21001 28 + 29 + struct hfi_pkt_hdr { 30 + u32 size; 31 + u32 pkt_type; 32 + }; 33 + 34 + struct hfi_sys_init_pkt { 35 + struct hfi_pkt_hdr hdr; 36 + u32 arch_type; 37 + }; 38 + 39 + struct hfi_sys_set_property_pkt { 40 + struct hfi_pkt_hdr hdr; 41 + u32 num_properties; 42 + u32 data[]; 43 + }; 44 + 45 + struct hfi_sys_get_property_pkt { 46 + struct hfi_pkt_hdr hdr; 47 + u32 num_properties; 48 + u32 data; 49 + }; 50 + 51 + struct hfi_msg_event_notify_pkt { 52 + struct hfi_pkt_hdr hdr; 53 + u32 event_id; 54 + u32 event_data1; 55 + u32 event_data2; 56 + u32 ext_event_data[]; 57 + }; 58 + 59 + struct hfi_msg_sys_init_done_pkt { 60 + struct hfi_pkt_hdr hdr; 61 + u32 error_type; 62 + u32 num_properties; 63 + u32 data[]; 64 + }; 65 + 66 + struct hfi_msg_sys_property_info_pkt { 67 + struct hfi_pkt_hdr hdr; 68 + u32 num_properties; 69 + u32 property; 70 + u8 data[]; 71 + }; 72 + 73 + struct hfi_enable { 74 + u32 enable; 75 + }; 76 + 77 + struct hfi_msg_sys_debug_pkt { 78 + struct hfi_pkt_hdr hdr; 79 + u32 msg_type; 80 + u32 msg_size; 81 + u32 time_stamp_hi; 82 + u32 time_stamp_lo; 83 + u8 msg_data[]; 84 + }; 85 + 86 + struct hfi_msg_sys_coverage_pkt { 87 + struct hfi_pkt_hdr hdr; 88 + u32 msg_size; 89 + u32 time_stamp_hi; 90 + u32 time_stamp_lo; 91 + u8 msg_data[]; 92 + }; 93 + 94 + #endif
+176
drivers/media/platform/qcom/iris/iris_hfi_gen1_response.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + /* 3 + * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved. 4 + */ 5 + 6 + #include "iris_hfi_gen1.h" 7 + #include "iris_hfi_gen1_defines.h" 8 + #include "iris_instance.h" 9 + 10 + static void 11 + iris_hfi_gen1_sys_event_notify(struct iris_core *core, void *packet) 12 + { 13 + struct hfi_msg_event_notify_pkt *pkt = packet; 14 + 15 + if (pkt->event_id == HFI_EVENT_SYS_ERROR) 16 + dev_err(core->dev, "sys error (type: %x, data1:%x, data2:%x)\n", 17 + pkt->event_id, pkt->event_data1, pkt->event_data2); 18 + 19 + core->state = IRIS_CORE_ERROR; 20 + schedule_delayed_work(&core->sys_error_handler, msecs_to_jiffies(10)); 21 + } 22 + 23 + static void iris_hfi_gen1_sys_init_done(struct iris_core *core, void *packet) 24 + { 25 + struct hfi_msg_sys_init_done_pkt *pkt = packet; 26 + 27 + if (pkt->error_type != HFI_ERR_NONE) { 28 + core->state = IRIS_CORE_ERROR; 29 + return; 30 + } 31 + 32 + complete(&core->core_init_done); 33 + } 34 + 35 + static void 36 + iris_hfi_gen1_sys_get_prop_image_version(struct iris_core *core, 37 + struct hfi_msg_sys_property_info_pkt *pkt) 38 + { 39 + int req_bytes = pkt->hdr.size - sizeof(*pkt); 40 + char fw_version[IRIS_FW_VERSION_LENGTH]; 41 + u8 *str_image_version; 42 + u32 i; 43 + 44 + if (req_bytes < IRIS_FW_VERSION_LENGTH - 1 || !pkt->data[0] || pkt->num_properties > 1) { 45 + dev_err(core->dev, "bad packet\n"); 46 + return; 47 + } 48 + 49 + str_image_version = pkt->data; 50 + if (!str_image_version) { 51 + dev_err(core->dev, "firmware version not available\n"); 52 + return; 53 + } 54 + 55 + for (i = 0; i < IRIS_FW_VERSION_LENGTH - 1; i++) { 56 + if (str_image_version[i] != '\0') 57 + fw_version[i] = str_image_version[i]; 58 + else 59 + fw_version[i] = ' '; 60 + } 61 + fw_version[i] = '\0'; 62 + dev_dbg(core->dev, "firmware version: %s\n", fw_version); 63 + } 64 + 65 + static void iris_hfi_gen1_sys_property_info(struct iris_core *core, void *packet) 66 + { 67 + struct hfi_msg_sys_property_info_pkt *pkt = packet; 68 + 69 + if (!pkt->num_properties) { 70 + dev_dbg(core->dev, "no properties\n"); 71 + return; 72 + } 73 + 74 + switch (pkt->property) { 75 + case HFI_PROPERTY_SYS_IMAGE_VERSION: 76 + iris_hfi_gen1_sys_get_prop_image_version(core, pkt); 77 + break; 78 + default: 79 + dev_dbg(core->dev, "unknown property data\n"); 80 + break; 81 + } 82 + } 83 + 84 + struct iris_hfi_gen1_response_pkt_info { 85 + u32 pkt; 86 + u32 pkt_sz; 87 + }; 88 + 89 + static const struct iris_hfi_gen1_response_pkt_info pkt_infos[] = { 90 + { 91 + .pkt = HFI_MSG_EVENT_NOTIFY, 92 + .pkt_sz = sizeof(struct hfi_msg_event_notify_pkt), 93 + }, 94 + { 95 + .pkt = HFI_MSG_SYS_INIT, 96 + .pkt_sz = sizeof(struct hfi_msg_sys_init_done_pkt), 97 + }, 98 + { 99 + .pkt = HFI_MSG_SYS_PROPERTY_INFO, 100 + .pkt_sz = sizeof(struct hfi_msg_sys_property_info_pkt), 101 + }, 102 + }; 103 + 104 + static void iris_hfi_gen1_handle_response(struct iris_core *core, void *response) 105 + { 106 + struct hfi_pkt_hdr *hdr = (struct hfi_pkt_hdr *)response; 107 + const struct iris_hfi_gen1_response_pkt_info *pkt_info; 108 + struct device *dev = core->dev; 109 + bool found = false; 110 + u32 i; 111 + 112 + for (i = 0; i < ARRAY_SIZE(pkt_infos); i++) { 113 + pkt_info = &pkt_infos[i]; 114 + if (pkt_info->pkt != hdr->pkt_type) 115 + continue; 116 + found = true; 117 + break; 118 + } 119 + 120 + if (!found || hdr->size < pkt_info->pkt_sz) { 121 + dev_err(dev, "bad packet size (%d should be %d, pkt type:%x, found %d)\n", 122 + hdr->size, pkt_info->pkt_sz, hdr->pkt_type, found); 123 + 124 + return; 125 + } 126 + 127 + switch (hdr->pkt_type) { 128 + case HFI_MSG_SYS_INIT: 129 + iris_hfi_gen1_sys_init_done(core, hdr); 130 + break; 131 + case HFI_MSG_SYS_PROPERTY_INFO: 132 + iris_hfi_gen1_sys_property_info(core, hdr); 133 + break; 134 + case HFI_MSG_EVENT_NOTIFY: 135 + iris_hfi_gen1_sys_event_notify(core, hdr); 136 + break; 137 + default: 138 + break; 139 + } 140 + } 141 + 142 + static void iris_hfi_gen1_flush_debug_queue(struct iris_core *core, u8 *packet) 143 + { 144 + struct hfi_msg_sys_coverage_pkt *pkt; 145 + 146 + while (!iris_hfi_queue_dbg_read(core, packet)) { 147 + pkt = (struct hfi_msg_sys_coverage_pkt *)packet; 148 + 149 + if (pkt->hdr.pkt_type != HFI_MSG_SYS_COV) { 150 + struct hfi_msg_sys_debug_pkt *pkt = 151 + (struct hfi_msg_sys_debug_pkt *)packet; 152 + 153 + dev_dbg(core->dev, "%s", pkt->msg_data); 154 + } 155 + } 156 + } 157 + 158 + static void iris_hfi_gen1_response_handler(struct iris_core *core) 159 + { 160 + memset(core->response_packet, 0, sizeof(struct hfi_pkt_hdr)); 161 + while (!iris_hfi_queue_msg_read(core, core->response_packet)) { 162 + iris_hfi_gen1_handle_response(core, core->response_packet); 163 + memset(core->response_packet, 0, sizeof(struct hfi_pkt_hdr)); 164 + } 165 + 166 + iris_hfi_gen1_flush_debug_queue(core, core->response_packet); 167 + } 168 + 169 + static const struct iris_hfi_response_ops iris_hfi_gen1_response_ops = { 170 + .hfi_response_handler = iris_hfi_gen1_response_handler, 171 + }; 172 + 173 + void iris_hfi_gen1_response_ops_init(struct iris_core *core) 174 + { 175 + core->hfi_response_ops = &iris_hfi_gen1_response_ops; 176 + }
+4
drivers/media/platform/qcom/iris/iris_hfi_gen2.h
··· 8 8 9 9 #include "iris_instance.h" 10 10 11 + struct iris_core; 12 + 11 13 /** 12 14 * struct iris_inst_hfi_gen2 - holds per video instance parameters for hfi_gen2 13 15 * ··· 19 17 struct iris_inst inst; 20 18 }; 21 19 20 + void iris_hfi_gen2_command_ops_init(struct iris_core *core); 21 + void iris_hfi_gen2_response_ops_init(struct iris_core *core); 22 22 struct iris_inst *iris_hfi_gen2_get_instance(void); 23 23 24 24 #endif
+74
drivers/media/platform/qcom/iris/iris_hfi_gen2_command.c
··· 4 4 */ 5 5 6 6 #include "iris_hfi_gen2.h" 7 + #include "iris_hfi_gen2_packet.h" 8 + 9 + #define NUM_SYS_INIT_PACKETS 8 10 + 11 + #define SYS_INIT_PKT_SIZE (sizeof(struct iris_hfi_header) + \ 12 + NUM_SYS_INIT_PACKETS * (sizeof(struct iris_hfi_packet) + sizeof(u32))) 13 + 14 + #define SYS_IFPC_PKT_SIZE (sizeof(struct iris_hfi_header) + \ 15 + sizeof(struct iris_hfi_packet) + sizeof(u32)) 16 + 17 + #define SYS_NO_PAYLOAD_PKT_SIZE (sizeof(struct iris_hfi_header) + \ 18 + sizeof(struct iris_hfi_packet)) 19 + 20 + static int iris_hfi_gen2_sys_init(struct iris_core *core) 21 + { 22 + struct iris_hfi_header *hdr; 23 + int ret; 24 + 25 + hdr = kzalloc(SYS_INIT_PKT_SIZE, GFP_KERNEL); 26 + if (!hdr) 27 + return -ENOMEM; 28 + 29 + iris_hfi_gen2_packet_sys_init(core, hdr); 30 + ret = iris_hfi_queue_cmd_write_locked(core, hdr, hdr->size); 31 + 32 + kfree(hdr); 33 + 34 + return ret; 35 + } 36 + 37 + static int iris_hfi_gen2_sys_image_version(struct iris_core *core) 38 + { 39 + struct iris_hfi_header *hdr; 40 + int ret; 41 + 42 + hdr = kzalloc(SYS_NO_PAYLOAD_PKT_SIZE, GFP_KERNEL); 43 + if (!hdr) 44 + return -ENOMEM; 45 + 46 + iris_hfi_gen2_packet_image_version(core, hdr); 47 + ret = iris_hfi_queue_cmd_write_locked(core, hdr, hdr->size); 48 + 49 + kfree(hdr); 50 + 51 + return ret; 52 + } 53 + 54 + static int iris_hfi_gen2_sys_interframe_powercollapse(struct iris_core *core) 55 + { 56 + struct iris_hfi_header *hdr; 57 + int ret; 58 + 59 + hdr = kzalloc(SYS_IFPC_PKT_SIZE, GFP_KERNEL); 60 + if (!hdr) 61 + return -ENOMEM; 62 + 63 + iris_hfi_gen2_packet_sys_interframe_powercollapse(core, hdr); 64 + ret = iris_hfi_queue_cmd_write_locked(core, hdr, hdr->size); 65 + 66 + kfree(hdr); 67 + 68 + return ret; 69 + } 70 + 71 + static const struct iris_hfi_command_ops iris_hfi_gen2_command_ops = { 72 + .sys_init = iris_hfi_gen2_sys_init, 73 + .sys_image_version = iris_hfi_gen2_sys_image_version, 74 + .sys_interframe_powercollapse = iris_hfi_gen2_sys_interframe_powercollapse, 75 + }; 76 + 77 + void iris_hfi_gen2_command_ops_init(struct iris_core *core) 78 + { 79 + core->hfi_ops = &iris_hfi_gen2_command_ops; 80 + } 7 81 8 82 struct iris_inst *iris_hfi_gen2_get_instance(void) 9 83 {
+46
drivers/media/platform/qcom/iris/iris_hfi_gen2_defines.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0-only */ 2 + /* 3 + * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved. 4 + */ 5 + 6 + #ifndef __IRIS_HFI_GEN2_DEFINES_H__ 7 + #define __IRIS_HFI_GEN2_DEFINES_H__ 8 + 9 + #include <linux/types.h> 10 + 11 + #define HFI_VIDEO_ARCH_LX 0x1 12 + 13 + #define HFI_CMD_BEGIN 0x01000000 14 + #define HFI_CMD_INIT 0x01000001 15 + #define HFI_CMD_END 0x01FFFFFF 16 + 17 + #define HFI_PROP_BEGIN 0x03000000 18 + #define HFI_PROP_IMAGE_VERSION 0x03000001 19 + #define HFI_PROP_INTRA_FRAME_POWER_COLLAPSE 0x03000002 20 + #define HFI_PROP_UBWC_MAX_CHANNELS 0x03000003 21 + #define HFI_PROP_UBWC_MAL_LENGTH 0x03000004 22 + #define HFI_PROP_UBWC_HBB 0x03000005 23 + #define HFI_PROP_UBWC_BANK_SWZL_LEVEL1 0x03000006 24 + #define HFI_PROP_UBWC_BANK_SWZL_LEVEL2 0x03000007 25 + #define HFI_PROP_UBWC_BANK_SWZL_LEVEL3 0x03000008 26 + #define HFI_PROP_UBWC_BANK_SPREADING 0x03000009 27 + #define HFI_PROP_END 0x03FFFFFF 28 + 29 + #define HFI_SYSTEM_ERROR_BEGIN 0x05000000 30 + #define HFI_SYS_ERROR_WD_TIMEOUT 0x05000001 31 + #define HFI_SYSTEM_ERROR_END 0x05FFFFFF 32 + 33 + enum hfi_packet_firmware_flags { 34 + HFI_FW_FLAGS_SUCCESS = 0x00000001, 35 + HFI_FW_FLAGS_INFORMATION = 0x00000002, 36 + HFI_FW_FLAGS_SESSION_ERROR = 0x00000004, 37 + HFI_FW_FLAGS_SYSTEM_ERROR = 0x00000008, 38 + }; 39 + 40 + struct hfi_debug_header { 41 + u32 size; 42 + u32 debug_level; 43 + u32 reserved[2]; 44 + }; 45 + 46 + #endif
+161
drivers/media/platform/qcom/iris/iris_hfi_gen2_packet.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + /* 3 + * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved. 4 + */ 5 + 6 + #include "iris_hfi_common.h" 7 + #include "iris_hfi_gen2.h" 8 + #include "iris_hfi_gen2_packet.h" 9 + 10 + static void iris_hfi_gen2_create_header(struct iris_hfi_header *hdr, 11 + u32 session_id, u32 header_id) 12 + { 13 + memset(hdr, 0, sizeof(*hdr)); 14 + 15 + hdr->size = sizeof(*hdr); 16 + hdr->session_id = session_id; 17 + hdr->header_id = header_id; 18 + hdr->num_packets = 0; 19 + } 20 + 21 + static void iris_hfi_gen2_create_packet(struct iris_hfi_header *hdr, u32 pkt_type, 22 + u32 pkt_flags, u32 payload_type, u32 port, 23 + u32 packet_id, void *payload, u32 payload_size) 24 + { 25 + struct iris_hfi_packet *pkt = (struct iris_hfi_packet *)((u8 *)hdr + hdr->size); 26 + u32 pkt_size = sizeof(*pkt) + payload_size; 27 + 28 + memset(pkt, 0, pkt_size); 29 + pkt->size = pkt_size; 30 + pkt->type = pkt_type; 31 + pkt->flags = pkt_flags; 32 + pkt->payload_info = payload_type; 33 + pkt->port = port; 34 + pkt->packet_id = packet_id; 35 + if (payload_size) 36 + memcpy(&pkt->payload[0], payload, payload_size); 37 + 38 + hdr->num_packets++; 39 + hdr->size += pkt->size; 40 + } 41 + 42 + void iris_hfi_gen2_packet_sys_init(struct iris_core *core, struct iris_hfi_header *hdr) 43 + { 44 + u32 payload = 0; 45 + 46 + iris_hfi_gen2_create_header(hdr, 0, core->header_id++); 47 + 48 + payload = HFI_VIDEO_ARCH_LX; 49 + iris_hfi_gen2_create_packet(hdr, 50 + HFI_CMD_INIT, 51 + (HFI_HOST_FLAGS_RESPONSE_REQUIRED | 52 + HFI_HOST_FLAGS_INTR_REQUIRED | 53 + HFI_HOST_FLAGS_NON_DISCARDABLE), 54 + HFI_PAYLOAD_U32, 55 + HFI_PORT_NONE, 56 + core->packet_id++, 57 + &payload, 58 + sizeof(u32)); 59 + 60 + payload = core->iris_platform_data->ubwc_config->max_channels; 61 + iris_hfi_gen2_create_packet(hdr, 62 + HFI_PROP_UBWC_MAX_CHANNELS, 63 + HFI_HOST_FLAGS_NONE, 64 + HFI_PAYLOAD_U32, 65 + HFI_PORT_NONE, 66 + core->packet_id++, 67 + &payload, 68 + sizeof(u32)); 69 + 70 + payload = core->iris_platform_data->ubwc_config->mal_length; 71 + iris_hfi_gen2_create_packet(hdr, 72 + HFI_PROP_UBWC_MAL_LENGTH, 73 + HFI_HOST_FLAGS_NONE, 74 + HFI_PAYLOAD_U32, 75 + HFI_PORT_NONE, 76 + core->packet_id++, 77 + &payload, 78 + sizeof(u32)); 79 + 80 + payload = core->iris_platform_data->ubwc_config->highest_bank_bit; 81 + iris_hfi_gen2_create_packet(hdr, 82 + HFI_PROP_UBWC_HBB, 83 + HFI_HOST_FLAGS_NONE, 84 + HFI_PAYLOAD_U32, 85 + HFI_PORT_NONE, 86 + core->packet_id++, 87 + &payload, 88 + sizeof(u32)); 89 + 90 + payload = core->iris_platform_data->ubwc_config->bank_swzl_level; 91 + iris_hfi_gen2_create_packet(hdr, 92 + HFI_PROP_UBWC_BANK_SWZL_LEVEL1, 93 + HFI_HOST_FLAGS_NONE, 94 + HFI_PAYLOAD_U32, 95 + HFI_PORT_NONE, 96 + core->packet_id++, 97 + &payload, 98 + sizeof(u32)); 99 + 100 + payload = core->iris_platform_data->ubwc_config->bank_swz2_level; 101 + iris_hfi_gen2_create_packet(hdr, 102 + HFI_PROP_UBWC_BANK_SWZL_LEVEL2, 103 + HFI_HOST_FLAGS_NONE, 104 + HFI_PAYLOAD_U32, 105 + HFI_PORT_NONE, 106 + core->packet_id++, 107 + &payload, 108 + sizeof(u32)); 109 + 110 + payload = core->iris_platform_data->ubwc_config->bank_swz3_level; 111 + iris_hfi_gen2_create_packet(hdr, 112 + HFI_PROP_UBWC_BANK_SWZL_LEVEL3, 113 + HFI_HOST_FLAGS_NONE, 114 + HFI_PAYLOAD_U32, 115 + HFI_PORT_NONE, 116 + core->packet_id++, 117 + &payload, 118 + sizeof(u32)); 119 + 120 + payload = core->iris_platform_data->ubwc_config->bank_spreading; 121 + iris_hfi_gen2_create_packet(hdr, 122 + HFI_PROP_UBWC_BANK_SPREADING, 123 + HFI_HOST_FLAGS_NONE, 124 + HFI_PAYLOAD_U32, 125 + HFI_PORT_NONE, 126 + core->packet_id++, 127 + &payload, 128 + sizeof(u32)); 129 + } 130 + 131 + void iris_hfi_gen2_packet_image_version(struct iris_core *core, struct iris_hfi_header *hdr) 132 + { 133 + iris_hfi_gen2_create_header(hdr, 0, core->header_id++); 134 + 135 + iris_hfi_gen2_create_packet(hdr, 136 + HFI_PROP_IMAGE_VERSION, 137 + (HFI_HOST_FLAGS_RESPONSE_REQUIRED | 138 + HFI_HOST_FLAGS_INTR_REQUIRED | 139 + HFI_HOST_FLAGS_GET_PROPERTY), 140 + HFI_PAYLOAD_NONE, 141 + HFI_PORT_NONE, 142 + core->packet_id++, 143 + NULL, 0); 144 + } 145 + 146 + void iris_hfi_gen2_packet_sys_interframe_powercollapse(struct iris_core *core, 147 + struct iris_hfi_header *hdr) 148 + { 149 + u32 payload = 1; /* HFI_TRUE */ 150 + 151 + iris_hfi_gen2_create_header(hdr, 0 /*session_id*/, core->header_id++); 152 + 153 + iris_hfi_gen2_create_packet(hdr, 154 + HFI_PROP_INTRA_FRAME_POWER_COLLAPSE, 155 + HFI_HOST_FLAGS_NONE, 156 + HFI_PAYLOAD_U32, 157 + HFI_PORT_NONE, 158 + core->packet_id++, 159 + &payload, 160 + sizeof(u32)); 161 + }
+69
drivers/media/platform/qcom/iris/iris_hfi_gen2_packet.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0-only */ 2 + /* 3 + * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved. 4 + */ 5 + 6 + #ifndef __IRIS_HFI_GEN2_PACKET_H__ 7 + #define __IRIS_HFI_GEN2_PACKET_H__ 8 + 9 + #include "iris_hfi_gen2_defines.h" 10 + 11 + struct iris_core; 12 + 13 + /** 14 + * struct iris_hfi_header 15 + * 16 + * @size: size of the total packet in bytes including hfi_header 17 + * @session_id: For session level hfi_header session_id is non-zero. 18 + * For system level hfi_header session_id is zero. 19 + * @header_id: unique header id for each hfi_header 20 + * @reserved: reserved for future use 21 + * @num_packets: number of hfi_packet that are included with the hfi_header 22 + */ 23 + struct iris_hfi_header { 24 + u32 size; 25 + u32 session_id; 26 + u32 header_id; 27 + u32 reserved[4]; 28 + u32 num_packets; 29 + }; 30 + 31 + /** 32 + * struct iris_hfi_packet 33 + * 34 + * @size: size of the hfi_packet in bytes including payload 35 + * @type: one of the below hfi_packet types: 36 + * HFI_CMD_*, 37 + * HFI_PROP_*, 38 + * HFI_ERROR_*, 39 + * HFI_INFO_*, 40 + * HFI_SYS_ERROR_* 41 + * @flags: hfi_packet flags. It is represented as bit masks. 42 + * host packet flags are "enum hfi_packet_host_flags" 43 + * firmware packet flags are "enum hfi_packet_firmware_flags" 44 + * @payload_info: payload information indicated by "enum hfi_packet_payload_info" 45 + * @port: hfi_packet port type indicated by "enum hfi_packet_port_type" 46 + * This is bitmask and may be applicable to multiple ports. 47 + * @packet_id: host hfi_packet contains unique packet id. 48 + * firmware returns host packet id in response packet 49 + * wherever applicable. If not applicable firmware sets it to zero. 50 + * @reserved: reserved for future use. 51 + * @payload: flexible array of payload having additional packet information. 52 + */ 53 + struct iris_hfi_packet { 54 + u32 size; 55 + u32 type; 56 + u32 flags; 57 + u32 payload_info; 58 + u32 port; 59 + u32 packet_id; 60 + u32 reserved[2]; 61 + u32 payload[]; 62 + }; 63 + 64 + void iris_hfi_gen2_packet_sys_init(struct iris_core *core, struct iris_hfi_header *hdr); 65 + void iris_hfi_gen2_packet_image_version(struct iris_core *core, struct iris_hfi_header *hdr); 66 + void iris_hfi_gen2_packet_sys_interframe_powercollapse(struct iris_core *core, 67 + struct iris_hfi_header *hdr); 68 + 69 + #endif
+215
drivers/media/platform/qcom/iris/iris_hfi_gen2_response.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + /* 3 + * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved. 4 + */ 5 + 6 + #include "iris_hfi_gen2.h" 7 + #include "iris_hfi_gen2_defines.h" 8 + #include "iris_hfi_gen2_packet.h" 9 + #include "iris_vpu_common.h" 10 + 11 + struct iris_hfi_gen2_core_hfi_range { 12 + u32 begin; 13 + u32 end; 14 + int (*handle)(struct iris_core *core, struct iris_hfi_packet *pkt); 15 + }; 16 + 17 + static int iris_hfi_gen2_validate_packet(u8 *response_pkt, u8 *core_resp_pkt) 18 + { 19 + u8 *response_limit = core_resp_pkt + IFACEQ_CORE_PKT_SIZE; 20 + u32 response_pkt_size = *(u32 *)response_pkt; 21 + 22 + if (!response_pkt_size) 23 + return -EINVAL; 24 + 25 + if (response_pkt_size < sizeof(struct iris_hfi_packet)) 26 + return -EINVAL; 27 + 28 + if (response_pkt + response_pkt_size > response_limit) 29 + return -EINVAL; 30 + 31 + return 0; 32 + } 33 + 34 + static int iris_hfi_gen2_validate_hdr_packet(struct iris_core *core, struct iris_hfi_header *hdr) 35 + { 36 + struct iris_hfi_packet *packet; 37 + int ret; 38 + u8 *pkt; 39 + u32 i; 40 + 41 + if (hdr->size < sizeof(*hdr) + sizeof(*packet)) 42 + return -EINVAL; 43 + 44 + pkt = (u8 *)((u8 *)hdr + sizeof(*hdr)); 45 + 46 + for (i = 0; i < hdr->num_packets; i++) { 47 + packet = (struct iris_hfi_packet *)pkt; 48 + ret = iris_hfi_gen2_validate_packet(pkt, core->response_packet); 49 + if (ret) 50 + return ret; 51 + 52 + pkt += packet->size; 53 + } 54 + 55 + return 0; 56 + } 57 + 58 + static int iris_hfi_gen2_handle_system_error(struct iris_core *core, 59 + struct iris_hfi_packet *pkt) 60 + { 61 + dev_err(core->dev, "received system error of type %#x\n", pkt->type); 62 + 63 + core->state = IRIS_CORE_ERROR; 64 + schedule_delayed_work(&core->sys_error_handler, msecs_to_jiffies(10)); 65 + 66 + return 0; 67 + } 68 + 69 + static int iris_hfi_gen2_handle_system_init(struct iris_core *core, 70 + struct iris_hfi_packet *pkt) 71 + { 72 + if (!(pkt->flags & HFI_FW_FLAGS_SUCCESS)) { 73 + core->state = IRIS_CORE_ERROR; 74 + return 0; 75 + } 76 + 77 + complete(&core->core_init_done); 78 + 79 + return 0; 80 + } 81 + 82 + static int iris_hfi_gen2_handle_image_version_property(struct iris_core *core, 83 + struct iris_hfi_packet *pkt) 84 + { 85 + u8 *str_image_version = (u8 *)pkt + sizeof(*pkt); 86 + u32 req_bytes = pkt->size - sizeof(*pkt); 87 + char fw_version[IRIS_FW_VERSION_LENGTH]; 88 + u32 i; 89 + 90 + if (req_bytes < IRIS_FW_VERSION_LENGTH - 1) 91 + return -EINVAL; 92 + 93 + for (i = 0; i < IRIS_FW_VERSION_LENGTH - 1; i++) { 94 + if (str_image_version[i] != '\0') 95 + fw_version[i] = str_image_version[i]; 96 + else 97 + fw_version[i] = ' '; 98 + } 99 + fw_version[i] = '\0'; 100 + dev_dbg(core->dev, "firmware version: %s\n", fw_version); 101 + 102 + return 0; 103 + } 104 + 105 + static int iris_hfi_gen2_handle_system_property(struct iris_core *core, 106 + struct iris_hfi_packet *pkt) 107 + { 108 + switch (pkt->type) { 109 + case HFI_PROP_IMAGE_VERSION: 110 + return iris_hfi_gen2_handle_image_version_property(core, pkt); 111 + default: 112 + return 0; 113 + } 114 + } 115 + 116 + static int iris_hfi_gen2_handle_system_response(struct iris_core *core, 117 + struct iris_hfi_header *hdr) 118 + { 119 + u8 *start_pkt = (u8 *)((u8 *)hdr + sizeof(*hdr)); 120 + struct iris_hfi_packet *packet; 121 + u32 i, j; 122 + u8 *pkt; 123 + int ret; 124 + static const struct iris_hfi_gen2_core_hfi_range range[] = { 125 + {HFI_SYSTEM_ERROR_BEGIN, HFI_SYSTEM_ERROR_END, iris_hfi_gen2_handle_system_error }, 126 + {HFI_PROP_BEGIN, HFI_PROP_END, iris_hfi_gen2_handle_system_property }, 127 + {HFI_CMD_BEGIN, HFI_CMD_END, iris_hfi_gen2_handle_system_init }, 128 + }; 129 + 130 + for (i = 0; i < ARRAY_SIZE(range); i++) { 131 + pkt = start_pkt; 132 + for (j = 0; j < hdr->num_packets; j++) { 133 + packet = (struct iris_hfi_packet *)pkt; 134 + if (packet->flags & HFI_FW_FLAGS_SYSTEM_ERROR) { 135 + ret = iris_hfi_gen2_handle_system_error(core, packet); 136 + return ret; 137 + } 138 + 139 + if (packet->type > range[i].begin && packet->type < range[i].end) { 140 + ret = range[i].handle(core, packet); 141 + if (ret) 142 + return ret; 143 + 144 + if (packet->type > HFI_SYSTEM_ERROR_BEGIN && 145 + packet->type < HFI_SYSTEM_ERROR_END) 146 + return 0; 147 + } 148 + pkt += packet->size; 149 + } 150 + } 151 + 152 + return 0; 153 + } 154 + 155 + static int iris_hfi_gen2_handle_response(struct iris_core *core, void *response) 156 + { 157 + struct iris_hfi_header *hdr = (struct iris_hfi_header *)response; 158 + int ret; 159 + 160 + ret = iris_hfi_gen2_validate_hdr_packet(core, hdr); 161 + if (ret) 162 + return iris_hfi_gen2_handle_system_error(core, NULL); 163 + 164 + return iris_hfi_gen2_handle_system_response(core, hdr); 165 + } 166 + 167 + static void iris_hfi_gen2_flush_debug_queue(struct iris_core *core, u8 *packet) 168 + { 169 + struct hfi_debug_header *pkt; 170 + u8 *log; 171 + 172 + while (!iris_hfi_queue_dbg_read(core, packet)) { 173 + pkt = (struct hfi_debug_header *)packet; 174 + 175 + if (pkt->size < sizeof(*pkt)) 176 + continue; 177 + 178 + if (pkt->size >= IFACEQ_CORE_PKT_SIZE) 179 + continue; 180 + 181 + packet[pkt->size] = '\0'; 182 + log = (u8 *)packet + sizeof(*pkt) + 1; 183 + dev_dbg(core->dev, "%s", log); 184 + } 185 + } 186 + 187 + static void iris_hfi_gen2_response_handler(struct iris_core *core) 188 + { 189 + if (iris_vpu_watchdog(core, core->intr_status)) { 190 + struct iris_hfi_packet pkt = {.type = HFI_SYS_ERROR_WD_TIMEOUT}; 191 + 192 + dev_err(core->dev, "cpu watchdog error received\n"); 193 + core->state = IRIS_CORE_ERROR; 194 + iris_hfi_gen2_handle_system_error(core, &pkt); 195 + 196 + return; 197 + } 198 + 199 + memset(core->response_packet, 0, sizeof(struct iris_hfi_header)); 200 + while (!iris_hfi_queue_msg_read(core, core->response_packet)) { 201 + iris_hfi_gen2_handle_response(core, core->response_packet); 202 + memset(core->response_packet, 0, sizeof(struct iris_hfi_header)); 203 + } 204 + 205 + iris_hfi_gen2_flush_debug_queue(core, core->response_packet); 206 + } 207 + 208 + static const struct iris_hfi_response_ops iris_hfi_gen2_response_ops = { 209 + .hfi_response_handler = iris_hfi_gen2_response_handler, 210 + }; 211 + 212 + void iris_hfi_gen2_response_ops_init(struct iris_core *core) 213 + { 214 + core->hfi_response_ops = &iris_hfi_gen2_response_ops; 215 + }
+173
drivers/media/platform/qcom/iris/iris_hfi_queue.c
··· 5 5 6 6 #include "iris_core.h" 7 7 #include "iris_hfi_queue.h" 8 + #include "iris_vpu_common.h" 9 + 10 + static int iris_hfi_queue_write(struct iris_iface_q_info *qinfo, void *packet, u32 packet_size) 11 + { 12 + struct iris_hfi_queue_header *queue = qinfo->qhdr; 13 + u32 write_idx = queue->write_idx * sizeof(u32); 14 + u32 read_idx = queue->read_idx * sizeof(u32); 15 + u32 empty_space, new_write_idx, residue; 16 + u32 *write_ptr; 17 + 18 + if (write_idx < read_idx) 19 + empty_space = read_idx - write_idx; 20 + else 21 + empty_space = IFACEQ_QUEUE_SIZE - (write_idx - read_idx); 22 + if (empty_space < packet_size) 23 + return -ENOSPC; 24 + 25 + queue->tx_req = 0; 26 + 27 + new_write_idx = write_idx + packet_size; 28 + write_ptr = (u32 *)((u8 *)qinfo->kernel_vaddr + write_idx); 29 + 30 + if (write_ptr < (u32 *)qinfo->kernel_vaddr || 31 + write_ptr > (u32 *)(qinfo->kernel_vaddr + 32 + IFACEQ_QUEUE_SIZE)) 33 + return -EINVAL; 34 + 35 + if (new_write_idx < IFACEQ_QUEUE_SIZE) { 36 + memcpy(write_ptr, packet, packet_size); 37 + } else { 38 + residue = new_write_idx - IFACEQ_QUEUE_SIZE; 39 + memcpy(write_ptr, packet, (packet_size - residue)); 40 + memcpy(qinfo->kernel_vaddr, 41 + packet + (packet_size - residue), residue); 42 + new_write_idx = residue; 43 + } 44 + 45 + /* Make sure packet is written before updating the write index */ 46 + mb(); 47 + queue->write_idx = new_write_idx / sizeof(u32); 48 + 49 + /* Make sure write index is updated before an interrupt is raised */ 50 + mb(); 51 + 52 + return 0; 53 + } 54 + 55 + static int iris_hfi_queue_read(struct iris_iface_q_info *qinfo, void *packet) 56 + { 57 + struct iris_hfi_queue_header *queue = qinfo->qhdr; 58 + u32 write_idx = queue->write_idx * sizeof(u32); 59 + u32 read_idx = queue->read_idx * sizeof(u32); 60 + u32 packet_size, receive_request = 0; 61 + u32 new_read_idx, residue; 62 + u32 *read_ptr; 63 + int ret = 0; 64 + 65 + if (queue->queue_type == IFACEQ_MSGQ_ID) 66 + receive_request = 1; 67 + 68 + if (read_idx == write_idx) { 69 + queue->rx_req = receive_request; 70 + /* Ensure qhdr is updated in main memory */ 71 + mb(); 72 + return -ENODATA; 73 + } 74 + 75 + read_ptr = qinfo->kernel_vaddr + read_idx; 76 + if (read_ptr < (u32 *)qinfo->kernel_vaddr || 77 + read_ptr > (u32 *)(qinfo->kernel_vaddr + 78 + IFACEQ_QUEUE_SIZE - sizeof(*read_ptr))) 79 + return -ENODATA; 80 + 81 + packet_size = *read_ptr; 82 + if (!packet_size) 83 + return -EINVAL; 84 + 85 + new_read_idx = read_idx + packet_size; 86 + if (packet_size <= IFACEQ_CORE_PKT_SIZE) { 87 + if (new_read_idx < IFACEQ_QUEUE_SIZE) { 88 + memcpy(packet, read_ptr, packet_size); 89 + } else { 90 + residue = new_read_idx - IFACEQ_QUEUE_SIZE; 91 + memcpy(packet, read_ptr, (packet_size - residue)); 92 + memcpy((packet + (packet_size - residue)), 93 + qinfo->kernel_vaddr, residue); 94 + new_read_idx = residue; 95 + } 96 + } else { 97 + new_read_idx = write_idx; 98 + ret = -EBADMSG; 99 + } 100 + 101 + queue->rx_req = receive_request; 102 + 103 + queue->read_idx = new_read_idx / sizeof(u32); 104 + /* Ensure qhdr is updated in main memory */ 105 + mb(); 106 + 107 + return ret; 108 + } 109 + 110 + int iris_hfi_queue_cmd_write_locked(struct iris_core *core, void *pkt, u32 pkt_size) 111 + { 112 + struct iris_iface_q_info *q_info = &core->command_queue; 113 + 114 + if (core->state == IRIS_CORE_ERROR) 115 + return -EINVAL; 116 + 117 + if (!iris_hfi_queue_write(q_info, pkt, pkt_size)) { 118 + iris_vpu_raise_interrupt(core); 119 + } else { 120 + dev_err(core->dev, "queue full\n"); 121 + return -ENODATA; 122 + } 123 + 124 + return 0; 125 + } 126 + 127 + int iris_hfi_queue_cmd_write(struct iris_core *core, void *pkt, u32 pkt_size) 128 + { 129 + int ret; 130 + 131 + mutex_lock(&core->lock); 132 + ret = iris_hfi_queue_cmd_write_locked(core, pkt, pkt_size); 133 + mutex_unlock(&core->lock); 134 + 135 + return ret; 136 + } 137 + 138 + int iris_hfi_queue_msg_read(struct iris_core *core, void *pkt) 139 + { 140 + struct iris_iface_q_info *q_info = &core->message_queue; 141 + int ret = 0; 142 + 143 + mutex_lock(&core->lock); 144 + if (core->state != IRIS_CORE_INIT) { 145 + ret = -EINVAL; 146 + goto unlock; 147 + } 148 + 149 + if (iris_hfi_queue_read(q_info, pkt)) { 150 + ret = -ENODATA; 151 + goto unlock; 152 + } 153 + 154 + unlock: 155 + mutex_unlock(&core->lock); 156 + 157 + return ret; 158 + } 159 + 160 + int iris_hfi_queue_dbg_read(struct iris_core *core, void *pkt) 161 + { 162 + struct iris_iface_q_info *q_info = &core->debug_queue; 163 + int ret = 0; 164 + 165 + mutex_lock(&core->lock); 166 + if (core->state != IRIS_CORE_INIT) { 167 + ret = -EINVAL; 168 + goto unlock; 169 + } 170 + 171 + if (iris_hfi_queue_read(q_info, pkt)) { 172 + ret = -ENODATA; 173 + goto unlock; 174 + } 175 + 176 + unlock: 177 + mutex_unlock(&core->lock); 178 + 179 + return ret; 180 + } 8 181 9 182 static void iris_hfi_queue_set_header(struct iris_core *core, u32 queue_id, 10 183 struct iris_iface_q_info *iface_q)
+5
drivers/media/platform/qcom/iris/iris_hfi_queue.h
··· 174 174 int iris_hfi_queues_init(struct iris_core *core); 175 175 void iris_hfi_queues_deinit(struct iris_core *core); 176 176 177 + int iris_hfi_queue_cmd_write_locked(struct iris_core *core, void *pkt, u32 pkt_size); 178 + int iris_hfi_queue_cmd_write(struct iris_core *core, void *pkt, u32 pkt_size); 179 + int iris_hfi_queue_msg_read(struct iris_core *core, void *pkt); 180 + int iris_hfi_queue_dbg_read(struct iris_core *core, void *pkt); 181 + 177 182 #endif
+17
drivers/media/platform/qcom/iris/iris_platform_common.h
··· 6 6 #ifndef __IRIS_PLATFORM_COMMON_H__ 7 7 #define __IRIS_PLATFORM_COMMON_H__ 8 8 9 + struct iris_core; 10 + 9 11 #define IRIS_PAS_ID 9 12 + #define HW_RESPONSE_TIMEOUT_VALUE (1000) /* milliseconds */ 10 13 11 14 extern struct iris_platform_data sm8550_data; 12 15 ··· 31 28 u32 cp_nonpixel_size; 32 29 }; 33 30 31 + struct ubwc_config_data { 32 + u32 max_channels; 33 + u32 mal_length; 34 + u32 highest_bank_bit; 35 + u32 bank_swzl_level; 36 + u32 bank_swz2_level; 37 + u32 bank_swz3_level; 38 + u32 bank_spreading; 39 + }; 40 + 34 41 struct iris_platform_data { 42 + void (*init_hfi_command_ops)(struct iris_core *core); 43 + void (*init_hfi_response_ops)(struct iris_core *core); 35 44 struct iris_inst *(*get_instance)(void); 36 45 const struct icc_info *icc_tbl; 37 46 unsigned int icc_tbl_size; ··· 60 45 u32 pas_id; 61 46 struct tz_cp_config *tz_cp_config_data; 62 47 u32 core_arch; 48 + u32 hw_response_timeout; 49 + struct ubwc_config_data *ubwc_config; 63 50 }; 64 51 65 52 #endif
+14
drivers/media/platform/qcom/iris/iris_platform_sm8550.c
··· 26 26 {IRIS_HW_CLK, "vcodec0_core" }, 27 27 }; 28 28 29 + static struct ubwc_config_data ubwc_config_sm8550 = { 30 + .max_channels = 8, 31 + .mal_length = 32, 32 + .highest_bank_bit = 16, 33 + .bank_swzl_level = 0, 34 + .bank_swz2_level = 1, 35 + .bank_swz3_level = 1, 36 + .bank_spreading = 1, 37 + }; 38 + 29 39 static struct tz_cp_config tz_cp_config_sm8550 = { 30 40 .cp_start = 0, 31 41 .cp_size = 0x25800000, ··· 45 35 46 36 struct iris_platform_data sm8550_data = { 47 37 .get_instance = iris_hfi_gen2_get_instance, 38 + .init_hfi_command_ops = iris_hfi_gen2_command_ops_init, 39 + .init_hfi_response_ops = iris_hfi_gen2_response_ops_init, 48 40 .icc_tbl = sm8550_icc_table, 49 41 .icc_tbl_size = ARRAY_SIZE(sm8550_icc_table), 50 42 .clk_rst_tbl = sm8550_clk_reset_table, ··· 63 51 .pas_id = IRIS_PAS_ID, 64 52 .tz_cp_config_data = &tz_cp_config_sm8550, 65 53 .core_arch = VIDEO_ARCH_LX, 54 + .hw_response_timeout = HW_RESPONSE_TIMEOUT_VALUE, 55 + .ubwc_config = &ubwc_config_sm8550, 66 56 };
+26
drivers/media/platform/qcom/iris/iris_probe.c
··· 177 177 mutex_destroy(&core->lock); 178 178 } 179 179 180 + static void iris_sys_error_handler(struct work_struct *work) 181 + { 182 + struct iris_core *core = 183 + container_of(work, struct iris_core, sys_error_handler.work); 184 + 185 + iris_core_deinit(core); 186 + iris_core_init(core); 187 + } 188 + 180 189 static int iris_probe(struct platform_device *pdev) 181 190 { 182 191 struct device *dev = &pdev->dev; ··· 200 191 201 192 core->state = IRIS_CORE_DEINIT; 202 193 mutex_init(&core->lock); 194 + init_completion(&core->core_init_done); 195 + 196 + core->response_packet = devm_kzalloc(core->dev, IFACEQ_CORE_PKT_SIZE, GFP_KERNEL); 197 + if (!core->response_packet) 198 + return -ENOMEM; 199 + 200 + INIT_DELAYED_WORK(&core->sys_error_handler, iris_sys_error_handler); 203 201 204 202 core->reg_base = devm_platform_ioremap_resource(pdev, 0); 205 203 if (IS_ERR(core->reg_base)) ··· 218 202 219 203 core->iris_platform_data = of_device_get_match_data(core->dev); 220 204 205 + ret = devm_request_threaded_irq(core->dev, core->irq, iris_hfi_isr, 206 + iris_hfi_isr_handler, IRQF_TRIGGER_HIGH, "iris", core); 207 + if (ret) 208 + return ret; 209 + 210 + disable_irq_nosync(core->irq); 211 + 221 212 iris_init_ops(core); 213 + core->iris_platform_data->init_hfi_command_ops(core); 214 + core->iris_platform_data->init_hfi_response_ops(core); 215 + 222 216 ret = iris_init_resources(core); 223 217 if (ret) 224 218 return ret;
+43
drivers/media/platform/qcom/iris/iris_vpu_common.c
··· 11 11 #define CPU_BASE_OFFS 0x000A0000 12 12 13 13 #define CPU_CS_BASE_OFFS (CPU_BASE_OFFS) 14 + #define CPU_IC_BASE_OFFS (CPU_BASE_OFFS) 15 + 16 + #define CPU_CS_A2HSOFTINTCLR (CPU_CS_BASE_OFFS + 0x1C) 17 + #define CLEAR_XTENSA2HOST_INTR BIT(0) 14 18 15 19 #define CTRL_INIT (CPU_CS_BASE_OFFS + 0x48) 16 20 #define CTRL_STATUS (CPU_CS_BASE_OFFS + 0x4C) 17 21 22 + #define CTRL_INIT_IDLE_MSG_BMSK 0x40000000 18 23 #define CTRL_ERROR_STATUS__M 0xfe 19 24 20 25 #define QTBL_INFO (CPU_CS_BASE_OFFS + 0x50) ··· 35 30 #define HOST2XTENSA_INTR_ENABLE BIT(0) 36 31 37 32 #define CPU_CS_X2RPMH (CPU_CS_BASE_OFFS + 0x168) 33 + 34 + #define CPU_IC_SOFTINT (CPU_IC_BASE_OFFS + 0x150) 35 + #define CPU_IC_SOFTINT_H2A_SHFT 0x0 36 + 37 + #define WRAPPER_BASE_OFFS 0x000B0000 38 + #define WRAPPER_INTR_STATUS (WRAPPER_BASE_OFFS + 0x0C) 39 + #define WRAPPER_INTR_STATUS_A2HWD_BMSK BIT(3) 40 + #define WRAPPER_INTR_STATUS_A2H_BMSK BIT(2) 38 41 39 42 static void iris_vpu_setup_ucregion_memory_map(struct iris_core *core) 40 43 { ··· 97 84 98 85 writel(HOST2XTENSA_INTR_ENABLE, core->reg_base + CPU_CS_H2XSOFTINTEN); 99 86 writel(0x0, core->reg_base + CPU_CS_X2RPMH); 87 + 88 + return 0; 89 + } 90 + 91 + void iris_vpu_raise_interrupt(struct iris_core *core) 92 + { 93 + writel(1 << CPU_IC_SOFTINT_H2A_SHFT, core->reg_base + CPU_IC_SOFTINT); 94 + } 95 + 96 + void iris_vpu_clear_interrupt(struct iris_core *core) 97 + { 98 + u32 intr_status, mask; 99 + 100 + intr_status = readl(core->reg_base + WRAPPER_INTR_STATUS); 101 + mask = (WRAPPER_INTR_STATUS_A2H_BMSK | 102 + WRAPPER_INTR_STATUS_A2HWD_BMSK | 103 + CTRL_INIT_IDLE_MSG_BMSK); 104 + 105 + if (intr_status & mask) 106 + core->intr_status |= intr_status; 107 + 108 + writel(CLEAR_XTENSA2HOST_INTR, core->reg_base + CPU_CS_A2HSOFTINTCLR); 109 + } 110 + 111 + int iris_vpu_watchdog(struct iris_core *core, u32 intr_status) 112 + { 113 + if (intr_status & WRAPPER_INTR_STATUS_A2HWD_BMSK) { 114 + dev_err(core->dev, "received watchdog interrupt\n"); 115 + return -ETIME; 116 + } 100 117 101 118 return 0; 102 119 }
+3
drivers/media/platform/qcom/iris/iris_vpu_common.h
··· 9 9 struct iris_core; 10 10 11 11 int iris_vpu_boot_firmware(struct iris_core *core); 12 + void iris_vpu_raise_interrupt(struct iris_core *core); 13 + void iris_vpu_clear_interrupt(struct iris_core *core); 14 + int iris_vpu_watchdog(struct iris_core *core, u32 intr_status); 12 15 13 16 #endif