File Index
Files and directories
Sign in
FILE

ipu7-fw-isys.c

File preview with syntax highlighting.

linux-6.19.14/drivers/staging/media/ipu7/ipu7-fw-isys.c C
  1// SPDX-License-Identifier: GPL-2.0-only
  2/*
  3 * Copyright (C) 2013 - 2025 Intel Corporation
  4 */
  5
  6#include <linux/cacheflush.h>
  7#include <linux/device.h>
  8#include <linux/dma-mapping.h>
  9#include <linux/kernel.h>
 10#include <linux/string.h>
 11#include <linux/types.h>
 12
 13#include "abi/ipu7_fw_insys_config_abi.h"
 14#include "abi/ipu7_fw_isys_abi.h"
 15
 16#include "ipu7.h"
 17#include "ipu7-boot.h"
 18#include "ipu7-bus.h"
 19#include "ipu7-dma.h"
 20#include "ipu7-fw-isys.h"
 21#include "ipu7-isys.h"
 22#include "ipu7-platform-regs.h"
 23#include "ipu7-syscom.h"
 24
 25static const char * const send_msg_types[N_IPU_INSYS_SEND_TYPE] = {
 26	"STREAM_OPEN",
 27	"STREAM_START_AND_CAPTURE",
 28	"STREAM_CAPTURE",
 29	"STREAM_ABORT",
 30	"STREAM_FLUSH",
 31	"STREAM_CLOSE"
 32};
 33
 34int ipu7_fw_isys_complex_cmd(struct ipu7_isys *isys,
 35			     const unsigned int stream_handle,
 36			     void *cpu_mapped_buf,
 37			     dma_addr_t dma_mapped_buf,
 38			     size_t size, u16 send_type)
 39{
 40	struct ipu7_syscom_context *ctx = isys->adev->syscom;
 41	struct device *dev = &isys->adev->auxdev.dev;
 42	struct ipu7_insys_send_queue_token *token;
 43
 44	if (send_type >= N_IPU_INSYS_SEND_TYPE)
 45		return -EINVAL;
 46
 47	dev_dbg(dev, "send_token: %s\n", send_msg_types[send_type]);
 48
 49	/*
 50	 * Time to flush cache in case we have some payload. Not all messages
 51	 * have that
 52	 */
 53	if (cpu_mapped_buf)
 54		clflush_cache_range(cpu_mapped_buf, size);
 55
 56	token = ipu7_syscom_get_token(ctx, stream_handle +
 57				      IPU_INSYS_INPUT_MSG_QUEUE);
 58	if (!token)
 59		return -EBUSY;
 60
 61	token->addr = dma_mapped_buf;
 62	token->buf_handle = (unsigned long)cpu_mapped_buf;
 63	token->send_type = send_type;
 64	token->stream_id = stream_handle;
 65	token->flag = IPU_INSYS_SEND_QUEUE_TOKEN_FLAG_NONE;
 66
 67	ipu7_syscom_put_token(ctx, stream_handle + IPU_INSYS_INPUT_MSG_QUEUE);
 68	/* now wakeup FW */
 69	ipu_buttress_wakeup_is_uc(isys->adev->isp);
 70
 71	return 0;
 72}
 73
 74int ipu7_fw_isys_simple_cmd(struct ipu7_isys *isys,
 75			    const unsigned int stream_handle, u16 send_type)
 76{
 77	return ipu7_fw_isys_complex_cmd(isys, stream_handle, NULL, 0, 0,
 78					send_type);
 79}
 80
 81int ipu7_fw_isys_init(struct ipu7_isys *isys)
 82{
 83	struct syscom_queue_config *queue_configs;
 84	struct ipu7_bus_device *adev = isys->adev;
 85	struct device *dev = &adev->auxdev.dev;
 86	struct ipu7_insys_config *isys_config;
 87	struct ipu7_syscom_context *syscom;
 88	dma_addr_t isys_config_dma_addr;
 89	unsigned int i, num_queues;
 90	u32 freq;
 91	u8 major;
 92	int ret;
 93
 94	/* Allocate and init syscom context. */
 95	syscom = devm_kzalloc(dev, sizeof(struct ipu7_syscom_context),
 96			      GFP_KERNEL);
 97	if (!syscom)
 98		return -ENOMEM;
 99
100	adev->syscom = syscom;
101	syscom->num_input_queues = IPU_INSYS_MAX_INPUT_QUEUES;
102	syscom->num_output_queues = IPU_INSYS_MAX_OUTPUT_QUEUES;
103	num_queues = syscom->num_input_queues + syscom->num_output_queues;
104	queue_configs = devm_kzalloc(dev, FW_QUEUE_CONFIG_SIZE(num_queues),
105				     GFP_KERNEL);
106	if (!queue_configs) {
107		ipu7_fw_isys_release(isys);
108		return -ENOMEM;
109	}
110	syscom->queue_configs = queue_configs;
111	queue_configs[IPU_INSYS_OUTPUT_MSG_QUEUE].max_capacity =
112		IPU_ISYS_SIZE_RECV_QUEUE;
113	queue_configs[IPU_INSYS_OUTPUT_MSG_QUEUE].token_size_in_bytes =
114		sizeof(struct ipu7_insys_resp);
115	queue_configs[IPU_INSYS_OUTPUT_LOG_QUEUE].max_capacity =
116		IPU_ISYS_SIZE_LOG_QUEUE;
117	queue_configs[IPU_INSYS_OUTPUT_LOG_QUEUE].token_size_in_bytes =
118		sizeof(struct ipu7_insys_resp);
119	queue_configs[IPU_INSYS_OUTPUT_RESERVED_QUEUE].max_capacity = 0;
120	queue_configs[IPU_INSYS_OUTPUT_RESERVED_QUEUE].token_size_in_bytes = 0;
121
122	queue_configs[IPU_INSYS_INPUT_DEV_QUEUE].max_capacity =
123		IPU_ISYS_MAX_STREAMS;
124	queue_configs[IPU_INSYS_INPUT_DEV_QUEUE].token_size_in_bytes =
125		sizeof(struct ipu7_insys_send_queue_token);
126
127	for (i = IPU_INSYS_INPUT_MSG_QUEUE; i < num_queues; i++) {
128		queue_configs[i].max_capacity = IPU_ISYS_SIZE_SEND_QUEUE;
129		queue_configs[i].token_size_in_bytes =
130			sizeof(struct ipu7_insys_send_queue_token);
131	}
132
133	/* Allocate ISYS subsys config. */
134	isys_config = ipu7_dma_alloc(adev, sizeof(struct ipu7_insys_config),
135				     &isys_config_dma_addr, GFP_KERNEL, 0);
136	if (!isys_config) {
137		dev_err(dev, "Failed to allocate isys subsys config.\n");
138		ipu7_fw_isys_release(isys);
139		return -ENOMEM;
140	}
141	isys->subsys_config = isys_config;
142	isys->subsys_config_dma_addr = isys_config_dma_addr;
143	memset(isys_config, 0, sizeof(struct ipu7_insys_config));
144	isys_config->logger_config.use_source_severity = 0;
145	isys_config->logger_config.use_channels_enable_bitmask = 1;
146	isys_config->logger_config.channels_enable_bitmask =
147		LOGGER_CONFIG_CHANNEL_ENABLE_SYSCOM_BITMASK;
148	isys_config->logger_config.hw_printf_buffer_base_addr = 0U;
149	isys_config->logger_config.hw_printf_buffer_size_bytes = 0U;
150	isys_config->wdt_config.wdt_timer1_us = 0;
151	isys_config->wdt_config.wdt_timer2_us = 0;
152	ret = ipu_buttress_get_isys_freq(adev->isp, &freq);
153	if (ret) {
154		dev_err(dev, "Failed to get ISYS frequency.\n");
155		ipu7_fw_isys_release(isys);
156		return ret;
157	}
158
159	ipu7_dma_sync_single(adev, isys_config_dma_addr,
160			     sizeof(struct ipu7_insys_config));
161
162	major = is_ipu8(adev->isp->hw_ver) ? 2U : 1U;
163	ret = ipu7_boot_init_boot_config(adev, queue_configs, num_queues,
164					 freq, isys_config_dma_addr, major);
165	if (ret)
166		ipu7_fw_isys_release(isys);
167
168	return ret;
169}
170
171void ipu7_fw_isys_release(struct ipu7_isys *isys)
172{
173	struct ipu7_bus_device *adev = isys->adev;
174
175	ipu7_boot_release_boot_config(adev);
176	if (isys->subsys_config) {
177		ipu7_dma_free(adev,
178			      sizeof(struct ipu7_insys_config),
179			      isys->subsys_config,
180			      isys->subsys_config_dma_addr, 0);
181		isys->subsys_config = NULL;
182		isys->subsys_config_dma_addr = 0;
183	}
184}
185
186int ipu7_fw_isys_open(struct ipu7_isys *isys)
187{
188	return ipu7_boot_start_fw(isys->adev);
189}
190
191int ipu7_fw_isys_close(struct ipu7_isys *isys)
192{
193	return ipu7_boot_stop_fw(isys->adev);
194}
195
196struct ipu7_insys_resp *ipu7_fw_isys_get_resp(struct ipu7_isys *isys)
197{
198	return (struct ipu7_insys_resp *)
199		ipu7_syscom_get_token(isys->adev->syscom,
200				      IPU_INSYS_OUTPUT_MSG_QUEUE);
201}
202
203void ipu7_fw_isys_put_resp(struct ipu7_isys *isys)
204{
205	ipu7_syscom_put_token(isys->adev->syscom, IPU_INSYS_OUTPUT_MSG_QUEUE);
206}
207
208void ipu7_fw_isys_dump_stream_cfg(struct device *dev,
209				  struct ipu7_insys_stream_cfg *cfg)
210{
211	unsigned int i;
212
213	dev_dbg(dev, "---------------------------\n");
214	dev_dbg(dev, "IPU_FW_ISYS_STREAM_CFG_DATA\n");
215
216	dev_dbg(dev, ".port id %d\n", cfg->port_id);
217	dev_dbg(dev, ".vc %d\n", cfg->vc);
218	dev_dbg(dev, ".nof_input_pins = %d\n", cfg->nof_input_pins);
219	dev_dbg(dev, ".nof_output_pins = %d\n", cfg->nof_output_pins);
220	dev_dbg(dev, ".stream_msg_map = 0x%x\n", cfg->stream_msg_map);
221
222	for (i = 0; i < cfg->nof_input_pins; i++) {
223		dev_dbg(dev, ".input_pin[%d]:\n", i);
224		dev_dbg(dev, "\t.dt = 0x%0x\n",
225			cfg->input_pins[i].dt);
226		dev_dbg(dev, "\t.disable_mipi_unpacking = %d\n",
227			cfg->input_pins[i].disable_mipi_unpacking);
228		dev_dbg(dev, "\t.dt_rename_mode = %d\n",
229			cfg->input_pins[i].dt_rename_mode);
230		dev_dbg(dev, "\t.mapped_dt = 0x%0x\n",
231			cfg->input_pins[i].mapped_dt);
232		dev_dbg(dev, "\t.input_res = %d x %d\n",
233			cfg->input_pins[i].input_res.width,
234			cfg->input_pins[i].input_res.height);
235		dev_dbg(dev, "\t.sync_msg_map = 0x%x\n",
236			cfg->input_pins[i].sync_msg_map);
237	}
238
239	for (i = 0; i < cfg->nof_output_pins; i++) {
240		dev_dbg(dev, ".output_pin[%d]:\n", i);
241		dev_dbg(dev, "\t.input_pin_id = %d\n",
242			cfg->output_pins[i].input_pin_id);
243		dev_dbg(dev, "\t.stride = %d\n", cfg->output_pins[i].stride);
244		dev_dbg(dev, "\t.send_irq = %d\n",
245			cfg->output_pins[i].send_irq);
246		dev_dbg(dev, "\t.ft = %d\n", cfg->output_pins[i].ft);
247
248		dev_dbg(dev, "\t.link.buffer_lines = %d\n",
249			cfg->output_pins[i].link.buffer_lines);
250		dev_dbg(dev, "\t.link.foreign_key = %d\n",
251			cfg->output_pins[i].link.foreign_key);
252		dev_dbg(dev, "\t.link.granularity_pointer_update = %d\n",
253			cfg->output_pins[i].link.granularity_pointer_update);
254		dev_dbg(dev, "\t.link.msg_link_streaming_mode = %d\n",
255			cfg->output_pins[i].link.msg_link_streaming_mode);
256		dev_dbg(dev, "\t.link.pbk_id = %d\n",
257			cfg->output_pins[i].link.pbk_id);
258		dev_dbg(dev, "\t.link.pbk_slot_id = %d\n",
259			cfg->output_pins[i].link.pbk_slot_id);
260		dev_dbg(dev, "\t.link.dest = %d\n",
261			cfg->output_pins[i].link.dest);
262		dev_dbg(dev, "\t.link.use_sw_managed = %d\n",
263			cfg->output_pins[i].link.use_sw_managed);
264		dev_dbg(dev, "\t.link.is_snoop = %d\n",
265			cfg->output_pins[i].link.is_snoop);
266
267		dev_dbg(dev, "\t.crop.line_top = %d\n",
268			cfg->output_pins[i].crop.line_top);
269		dev_dbg(dev, "\t.crop.line_bottom = %d\n",
270			cfg->output_pins[i].crop.line_bottom);
271
272		dev_dbg(dev, "\t.dpcm_enable = %d\n",
273			cfg->output_pins[i].dpcm.enable);
274		dev_dbg(dev, "\t.dpcm.type = %d\n",
275			cfg->output_pins[i].dpcm.type);
276		dev_dbg(dev, "\t.dpcm.predictor = %d\n",
277			cfg->output_pins[i].dpcm.predictor);
278	}
279	dev_dbg(dev, "---------------------------\n");
280}
281
282void ipu7_fw_isys_dump_frame_buff_set(struct device *dev,
283				      struct ipu7_insys_buffset *buf,
284				      unsigned int outputs)
285{
286	unsigned int i;
287
288	dev_dbg(dev, "--------------------------\n");
289	dev_dbg(dev, "IPU_ISYS_BUFF_SET\n");
290	dev_dbg(dev, ".capture_msg_map = %d\n", buf->capture_msg_map);
291	dev_dbg(dev, ".frame_id = %d\n", buf->frame_id);
292	dev_dbg(dev, ".skip_frame = %d\n", buf->skip_frame);
293
294	for (i = 0; i < outputs; i++) {
295		dev_dbg(dev, ".output_pin[%d]:\n", i);
296		dev_dbg(dev, "\t.user_token = %llx\n",
297			buf->output_pins[i].user_token);
298		dev_dbg(dev, "\t.addr = 0x%x\n", buf->output_pins[i].addr);
299	}
300	dev_dbg(dev, "---------------------------\n");
301}
~/ Read-only file preview.