diff options
author | Dikshita Agarwal <quic_dikshita@quicinc.com> | 2025-02-07 10:54:44 +0300 |
---|---|---|
committer | Hans Verkuil <hverkuil@xs4all.nl> | 2025-02-07 13:51:04 +0300 |
commit | d7378f84e94e14998b3469dcc0d8ce609d049ccc (patch) | |
tree | ac8c1d11da4adeaee4f5ad245ff9323053ba8b4b /drivers/media/platform/qcom/iris/iris_hfi_queue.c | |
parent | fa186c97e3d293c924c36780f721201f0ec73661 (diff) | |
download | linux-d7378f84e94e14998b3469dcc0d8ce609d049ccc.tar.xz |
media: iris: introduce iris core state management with shared queues
Introduce a core state management for iris driver with the necessary
queues needed for the host firmware communication.
There are 3 types of queues:
Command queue - driver to write any command to firmware.
Message queue - firmware to send any response to the driver.
Debug queue - for the firmware to write debug messages.
Initialize and configure the shared queues during probe.
Different states for core:
IRIS_CORE_DEINIT - default state.
IRIS_CORE_INIT - core state with core initialized. FW loaded and HW
brought out of reset, shared queues established
between host driver and firmware.
IRIS_CORE_ERROR - error state.
-----------
|
V
-----------
| DEINIT |
-----------
^
/ \
/ \
/ \
/ \
v v
----------- ----------.
| INIT |-->| ERROR |
----------- ----------.
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>
Diffstat (limited to 'drivers/media/platform/qcom/iris/iris_hfi_queue.c')
-rw-r--r-- | drivers/media/platform/qcom/iris/iris_hfi_queue.c | 127 |
1 files changed, 127 insertions, 0 deletions
diff --git a/drivers/media/platform/qcom/iris/iris_hfi_queue.c b/drivers/media/platform/qcom/iris/iris_hfi_queue.c new file mode 100644 index 000000000000..494ef205133d --- /dev/null +++ b/drivers/media/platform/qcom/iris/iris_hfi_queue.c @@ -0,0 +1,127 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved. + */ + +#include "iris_core.h" +#include "iris_hfi_queue.h" + +static void iris_hfi_queue_set_header(struct iris_core *core, u32 queue_id, + struct iris_iface_q_info *iface_q) +{ + iface_q->qhdr->status = 0x1; + iface_q->qhdr->start_addr = iface_q->device_addr; + iface_q->qhdr->header_type = IFACEQ_DFLT_QHDR; + iface_q->qhdr->queue_type = queue_id; + iface_q->qhdr->q_size = IFACEQ_QUEUE_SIZE / sizeof(u32); + iface_q->qhdr->pkt_size = 0; /* variable packet size */ + iface_q->qhdr->rx_wm = 0x1; + iface_q->qhdr->tx_wm = 0x1; + iface_q->qhdr->rx_req = 0x1; + iface_q->qhdr->tx_req = 0x0; + iface_q->qhdr->rx_irq_status = 0x0; + iface_q->qhdr->tx_irq_status = 0x0; + iface_q->qhdr->read_idx = 0x0; + iface_q->qhdr->write_idx = 0x0; + + /* + * Set receive request to zero on debug queue as there is no + * need of interrupt from video hardware for debug messages + */ + if (queue_id == IFACEQ_DBGQ_ID) + iface_q->qhdr->rx_req = 0; +} + +static void +iris_hfi_queue_init(struct iris_core *core, u32 queue_id, struct iris_iface_q_info *iface_q) +{ + struct iris_hfi_queue_table_header *q_tbl_hdr = core->iface_q_table_vaddr; + u32 offset = sizeof(*q_tbl_hdr) + (queue_id * IFACEQ_QUEUE_SIZE); + + iface_q->device_addr = core->iface_q_table_daddr + offset; + iface_q->kernel_vaddr = + (void *)((char *)core->iface_q_table_vaddr + offset); + iface_q->qhdr = &q_tbl_hdr->q_hdr[queue_id]; + + iris_hfi_queue_set_header(core, queue_id, iface_q); +} + +static void iris_hfi_queue_deinit(struct iris_iface_q_info *iface_q) +{ + iface_q->qhdr = NULL; + iface_q->kernel_vaddr = NULL; + iface_q->device_addr = 0; +} + +int iris_hfi_queues_init(struct iris_core *core) +{ + struct iris_hfi_queue_table_header *q_tbl_hdr; + u32 queue_size; + + /* Iris hardware requires 4K queue alignment */ + queue_size = ALIGN((sizeof(*q_tbl_hdr) + (IFACEQ_QUEUE_SIZE * IFACEQ_NUMQ)), SZ_4K); + core->iface_q_table_vaddr = dma_alloc_attrs(core->dev, queue_size, + &core->iface_q_table_daddr, + GFP_KERNEL, DMA_ATTR_WRITE_COMBINE); + if (!core->iface_q_table_vaddr) { + dev_err(core->dev, "queues alloc and map failed\n"); + return -ENOMEM; + } + + core->sfr_vaddr = dma_alloc_attrs(core->dev, SFR_SIZE, + &core->sfr_daddr, + GFP_KERNEL, DMA_ATTR_WRITE_COMBINE); + if (!core->sfr_vaddr) { + dev_err(core->dev, "sfr alloc and map failed\n"); + dma_free_attrs(core->dev, sizeof(*q_tbl_hdr), core->iface_q_table_vaddr, + core->iface_q_table_daddr, DMA_ATTR_WRITE_COMBINE); + return -ENOMEM; + } + + iris_hfi_queue_init(core, IFACEQ_CMDQ_ID, &core->command_queue); + iris_hfi_queue_init(core, IFACEQ_MSGQ_ID, &core->message_queue); + iris_hfi_queue_init(core, IFACEQ_DBGQ_ID, &core->debug_queue); + + q_tbl_hdr = (struct iris_hfi_queue_table_header *)core->iface_q_table_vaddr; + q_tbl_hdr->version = 0; + q_tbl_hdr->device_addr = (void *)core; + strscpy(q_tbl_hdr->name, "iris-hfi-queues", sizeof(q_tbl_hdr->name)); + q_tbl_hdr->size = sizeof(*q_tbl_hdr); + q_tbl_hdr->qhdr0_offset = sizeof(*q_tbl_hdr) - + (IFACEQ_NUMQ * sizeof(struct iris_hfi_queue_header)); + q_tbl_hdr->qhdr_size = sizeof(q_tbl_hdr->q_hdr[0]); + q_tbl_hdr->num_q = IFACEQ_NUMQ; + q_tbl_hdr->num_active_q = IFACEQ_NUMQ; + + /* Write sfr size in first word to be used by firmware */ + *((u32 *)core->sfr_vaddr) = SFR_SIZE; + + return 0; +} + +void iris_hfi_queues_deinit(struct iris_core *core) +{ + u32 queue_size; + + if (!core->iface_q_table_vaddr) + return; + + iris_hfi_queue_deinit(&core->debug_queue); + iris_hfi_queue_deinit(&core->message_queue); + iris_hfi_queue_deinit(&core->command_queue); + + dma_free_attrs(core->dev, SFR_SIZE, core->sfr_vaddr, + core->sfr_daddr, DMA_ATTR_WRITE_COMBINE); + + core->sfr_vaddr = NULL; + core->sfr_daddr = 0; + + queue_size = ALIGN(sizeof(struct iris_hfi_queue_table_header) + + (IFACEQ_QUEUE_SIZE * IFACEQ_NUMQ), SZ_4K); + + dma_free_attrs(core->dev, queue_size, core->iface_q_table_vaddr, + core->iface_q_table_daddr, DMA_ATTR_WRITE_COMBINE); + + core->iface_q_table_vaddr = NULL; + core->iface_q_table_daddr = 0; +} |