Files
linux-nv-oot/include/media/fusa-capture/capture-isp.h
fraunak 59fa283238 camera: Add ISP floorsweeping support to Linux
This commit implements T264 ISP floorsweeping functionality in the Linux
kernel driver, extending the existing RCE firmware implementation to
provide transparent ISP unit redirection at the kernel level.

Changes:
- Add isp_capture_query_availability_mask_probe() function to query ISP
  availability mask from RCE firmware during driver probe via IVC
- Add isp_capture_find_first_available() helper function to find the
  first available ISP unit from a bitmask for HW assignment
- Integrate floorsweeping logic into isp_get_nvhost_device() to handle
  SW-to-HW ISP unit mapping with thread-safe assignment
- Add isp_capture_get_capabilities() function to expose ISP availability
  to userspace via new IOCTL (ISP_CAPTURE_GET_CAPABILITIES)
- Add probe-time caching of ISP availability mask to avoid repeated IVC
  queries during runtime
- Add comprehensive error handling and safety mechanisms for unknown
  configurations

Implementation details:
- Uses CAPTURE_ISP_FUSE_QUERY_REQ/RESP IVC messages for querying RCE
- Maintains SW-to-HW ISP unit mapping array protected by mutex
- The SW-to-HW mappings persist for the driver's lifetime, given that
  multiple channels make use of the same SW unit ID's and we do not
  have tracking of all open channels during runtime
- Integrates with existing ISP setup flow before buffer allocation
- Maintains backward compatibility with non-T264 hardware
- Conservative approach: blocks requests when no ISP units are available

Floorsweeping logic (handled by RCE firmware, exposed as bitmask):
- Mask bit N set = ISP N available (not fused off)
- Mask bit N clear = ISP N fused off (unavailable)
- Examples:
  - 0x3 (0b11): Both ISP0/ISP1 available (no floorsweeping)
  - 0x1 (0b01): Only ISP0 available → all requests map to ISP0
  - 0x2 (0b10): Only ISP1 available → all requests map to ISP1
  - 0x0: No ISP units available (block all requests)

Benefits:
- Transparent operation for applications using fusacapture library
- Automatic ISP unit redirection without API changes
- Improved hardware yield by supporting single-ISP configurations
- Robust error handling and safety mechanisms
- Minimal performance overhead with probe-time caching

The implementation complements the existing RCE firmware floorsweeping
support and provides a complete end-to-end solution for T264 ISP
floorsweeping across all software layers.

Bug 5640706

Change-Id: If85ee3178e857394300479dd42e636f5f5d3bd23
Signed-off-by: fraunak <fraunak@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3491180
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
Reviewed-by: Evgeny Kornev <ekornev@nvidia.com>
Reviewed-by: Kalle Jokiniemi <kjokiniemi@nvidia.com>
Reviewed-by: Semi Malinen <smalinen@nvidia.com>
Tested-by: Akihiro Mizusawa <amizusawa@nvidia.com>
2025-11-25 13:12:39 -08:00

407 lines
12 KiB
C

/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (c) 2017-2025 NVIDIA Corporation. All rights reserved.
*/
/**
* @file include/media/fusa-capture/capture-isp.h
*
* @brief ISP channel operations header for the T186/T194 Camera RTCPU platform.
*/
#ifndef __FUSA_CAPTURE_ISP_H__
#define __FUSA_CAPTURE_ISP_H__
#if defined(__KERNEL__)
#include <linux/compiler.h>
#include <linux/types.h>
#else
#include <stdint.h>
#endif
#include <linux/ioctl.h>
#define __ISP_CAPTURE_ALIGN __aligned(8)
struct tegra_isp_channel;
/**
* @brief ISP descriptor relocs config.
*/
struct capture_isp_reloc {
uint32_t num_relocs; /**< No. of buffers to pin/reloc */
uint32_t __pad;
uint64_t reloc_relatives;
/**< Offsets buffer addresses to patch in descriptor */
} __ISP_CAPTURE_ALIGN;
/**
* @brief ISP channel setup config (IOCTL payload).
*
* These fields are used to set up the ISP channel and capture contexts, and
* will be copied verbatim in the IVC capture_channel_isp_config struct to
* allocate ISP resources in the RCE subsystem.
*/
struct isp_capture_setup {
uint32_t channel_flags;
/**<
* Bitmask for channel flags, see @ref CAPTURE_ISP_CHANNEL_FLAGS
*/
/* ISP unit index */
uint8_t isp_unit;
uint8_t __pad[3];
/* ISP process capture descriptor queue (ring buffer) */
uint32_t queue_depth;
/**< No. of process capture descriptors in queue */
uint32_t request_size;
/**< Size of a single process capture descriptor [byte] */
uint32_t mem; /**< Process capture descriptors queue NvRm handle */
/* ISP process program descriptor queue (ring buffer) */
uint32_t isp_program_queue_depth;
/**< No. of process program descriptors in queue */
uint32_t isp_program_request_size;
/**< Size of a single process program descriptor [byte] */
uint32_t isp_program_mem;
/**< Process program descriptors queue NvRm handle */
uint32_t error_mask_correctable;
/**<
* Bitmask for correctable channel errors. See
* @ref CAPTURE_ISP_CHANNEL_ERRORS
*/
uint32_t error_mask_uncorrectable;
/**<
* Bitmask for uncorrectable channel errors. See
* @ref CAPTURE_ISP_CHANNEL_ERRORS
*/
} __ISP_CAPTURE_ALIGN;
/**
* @brief ISP capture info (resp. to query).
*/
struct isp_capture_info {
struct isp_capture_syncpts {
uint32_t progress_syncpt; /**< Progress syncpoint id */
uint32_t progress_syncpt_val; /**< Progress syncpoint value */
uint32_t stats_progress_syncpt;
/**< Stats progress syncpoint id */
uint32_t stats_progress_syncpt_val;
/**< Stats progress syncpoint value */
} syncpts;
uint32_t channel_id; /**< RCE-assigned ISP FW channel id */
} __ISP_CAPTURE_ALIGN;
/**
* @brief ISP process capture request (IOCTL payload).
*/
struct isp_capture_req {
uint32_t buffer_index; /**< Process descriptor index */
uint32_t __pad;
struct capture_isp_reloc isp_relocs;
/**<
* Surface buffers pin/reloc config. See @ref capture_isp_reloc
*/
struct capture_isp_reloc inputfences_relocs;
/**<
* Inputfences to pin/reloc. config. See @ref capture_isp_reloc
*/
uint32_t gos_relative; /* GoS offset [byte] */
uint32_t sp_relative; /* Syncpt offset [byte] */
struct capture_isp_reloc prefences_relocs;
/**<
* Prefences to pin/reloc. config. See @ref capture_isp_reloc
*/
} __ISP_CAPTURE_ALIGN;
/**
* @brief ISP process program request (IOCTL payload).
*/
struct isp_program_req {
uint32_t buffer_index; /**< Program descriptor index. */
uint32_t __pad;
struct capture_isp_reloc isp_program_relocs;
/**<
* Push buffers to pin/reloc. config. See
* @ref capture_isp_reloc
*/
} __ISP_CAPTURE_ALIGN;
/**
* @brief ISP joint capture+program request (IOCTL payload).
*/
struct isp_capture_req_ex {
struct isp_capture_req capture_req; /**< ISP capture process request */
struct isp_program_req program_req; /**< ISP program process request */
uint32_t __pad[4];
} __ISP_CAPTURE_ALIGN;
/**
* @brief ISP capture progress status setup config (IOCTL payload).
*/
struct isp_capture_progress_status_req {
uint32_t mem; /**< NvRm handle to buffer region start */
uint32_t mem_offset; /**< Status notifier offset [byte] */
uint32_t process_buffer_depth;
/**< Process capture descriptor queue size [num] */
uint32_t program_buffer_depth;
/**< Process program descriptor queue size [num] */
uint32_t __pad[4];
} __ISP_CAPTURE_ALIGN;
/**
* @brief Add ISP capture buffer to management table (IOCTL payload).
*/
struct isp_buffer_req {
uint32_t mem; /**< NvRm handle to buffer */
uint32_t flag; /**< Buffer @ref CAPTURE_BUFFER_OPS bitmask */
} __ISP_CAPTURE_ALIGN;
/**
* @brief ISP hardware capabilities query response structure
*
* This structure contains dynamic hardware capabilities that can only
* be determined at runtime by querying the actual hardware configuration
* and driver state.
*/
struct isp_capabilities_info {
uint32_t num_isp_units; /**< Number of available ISP units after floorsweeping */
uint32_t isp_unit_mask; /**< Bitmask of available ISP units (bit N set = ISP N available) */
uint32_t reserved[6]; /**< Reserved for future expansion */
} __ISP_CAPTURE_ALIGN;
/**
* @brief Initialize an ISP channel capture context (at channel open).
*
* The ISP channel context is already partially-initialized by the calling
* function, the channel capture context is allocated and linked here.
*
* @param[in,out] chan Allocated ISP channel context,
* partially-initialized
* @returns 0 (success), neg. errno (failure)
*/
int isp_capture_init(
struct tegra_isp_channel *chan);
/**
* @brief De-initialize an ISP capture channel, closing open ISP streams, and
* freeing the buffer management table and channel capture context.
*
* The ISP channel context is not freed in this function, only the capture
* context is.
*
* The ISP channel should have been RESET and RELEASE'd when this function is
* called, but they may still be active due to programming error or client UMD
* crash. In such cases, they will be called automatically by the @em Abort
* functionality.
*
* @param[in,out] chan VI channel context
*/
void isp_capture_shutdown(
struct tegra_isp_channel *chan);
/**
* @brief Select the NvHost ISP client instance platform driver to be
* associated with the channel.
* Only used in the case where ISP standalone driver is used
* to enumerate the ISP channel character drivers
*
* @param[in/out] chan ISP channel context
* @param[in] setup ISP channel setup config
*
*/
void isp_get_nvhost_device(
struct tegra_isp_channel *chan,
struct isp_capture_setup *setup);
/**
* @brief Open an ISP channel in RCE, sending channel configuration to request a
* SW channel allocation. Syncpts are allocated by the KMD in this subroutine.
*
* @param[in,out] chan ISP channel context
* @param[in] setup ISP channel setup config
*
* @returns 0 (success), neg. errno (failure)
*/
int isp_capture_setup(
struct tegra_isp_channel *chan,
struct isp_capture_setup *setup);
/**
* @brief Reset an opened ISP channel, all pending process requests to RCE are
* discarded.
*
* The channel's progress syncpoint is advanced to the threshold of the latest
* capture/program request to unblock any waiting observers.
*
* A reset barrier may be enqueued in the capture IVC channel to flush stale
* capture/program descriptors, in case of abnormal channel termination.
*
* @param[in] chan VI channel context
* @param[in] reset_flags Bitmask for ISP channel reset options
* (CAPTURE_CHANNEL_RESET_FLAG_*)
* @returns 0 (success), neg. errno (failure)
*/
int isp_capture_reset(
struct tegra_isp_channel *chan,
uint32_t reset_flags);
/**
* @brief Release an opened ISP channel; the RCE channel allocation, syncpoints
* and IVC channel callbacks are released.
*
* @param[in] chan ISP channel context
* @param[in] reset_flags Bitmask for ISP channel reset options
* (CAPTURE_CHANNEL_RESET_FLAG_*)
*
* @returns 0 (success), neg. errno (failure)
*/
int isp_capture_release(
struct tegra_isp_channel *chan,
uint32_t reset_flags);
/**
* @brief Query an ISP channel's syncpoint ids and values, and retrieve the
* RCE-assigned ISP FW channel id.
*
* @param[in] chan ISP channel context
* @param[out] info ISP channel info response
*
* @returns 0 (success), neg. errno (failure)
*/
int isp_capture_get_info(
struct tegra_isp_channel *chan,
struct isp_capture_info *info);
/**
* @brief Send a capture (aka. process) request for a frame via the capture IVC
* channel to RCE.
*
* This is a non-blocking call.
*
* @param[in] chan ISP channel context
* @param[in] req ISP process capture request
*
* @returns 0 (success), neg. errno (failure)
*/
int isp_capture_request(
struct tegra_isp_channel *chan,
struct isp_capture_req *req);
/**
* @brief Wait on receipt of the capture status of the head of the capture
* request FIFO queue to RCE. The RCE ISP driver sends a CAPTURE_ISP_STATUS_IND
* notification at frame completion.
*
* This is a blocking call, with the possibility of timeout.
*
* @todo The capture progress status notifier is expected to replace this
* functionality in the future, deprecating it.
*
* @param[in] chan ISP channel context
* @param[in] timeout_ms Time to wait for status completion [ms], set to
* 0 for indefinite
*
* @returns 0 (success), neg. errno (failure)
*/
int isp_capture_status(
struct tegra_isp_channel *chan,
int32_t timeout_ms);
/**
* @brief Send a program request containing an ISP pushbuffer configuration via
* the capture IVC channel to RCE.
*
* This is a non-blocking call.
*
* @param[in] chan ISP channel context
* @param[in] req ISP program request
*
* @returns 0 (success), neg. errno (failure)
*/
int isp_capture_program_request(
struct tegra_isp_channel *chan,
struct isp_program_req *req);
/**
* @brief Wait on receipt of the program status of the head of the program
* request FIFO queue to RCE. The RCE ISP driver sends a
* CAPTURE_ISP_PROGRAM_STATUS_IND notification at completion.
*
* This is a blocking call, with no possibility of timeout; as programs may be
* reused for multiple frames.
*
* @todo The capture progress status notifier is expected to replace this
* functionality in the future, deprecating it.
*
* @param[in] chan ISP channel context
*
* @returns 0 (success), neg. errno (failure)
*/
int isp_capture_program_status(
struct tegra_isp_channel *chan);
/**
* @brief Send an extended capture (aka. process) request for a frame,
* containing the ISP pushbuffer program to execute via the capture IVC channel
* to RCE.
*
* The extended call is equivalent to separately sending a capture and a program
* request for every frame; it is an optimization to reduce the number of
* system context switches from IOCTL and IVC calls.
*
* This is a non-blocking call.
*
* @param[in] chan ISP channel context
* @param[in] req ISP extended process request
*
* @returns 0 (success), neg. errno (failure)
*/
int isp_capture_request_ex(
struct tegra_isp_channel *chan,
struct isp_capture_req_ex *req);
/**
* @brief Setup ISP channel capture status progress notifier
*
* @param[in] chan ISP channel context
* @param[in] req ISP capture progress status setup config
*
* @returns 0 (success), neg. errno (failure)
*/
int isp_capture_set_progress_status_notifier(
struct tegra_isp_channel *chan,
struct isp_capture_progress_status_req *req);
/**
* @brief Perform a buffer management operation on an ISP capture buffer.
*
* @param[in] chan ISP channel context
* @param[in] req ISP capture buffer request
*
* @returns 0 (success), neg. errno (failure)
*/
int isp_capture_buffer_request(
struct tegra_isp_channel *chan,
struct isp_buffer_req *req);
/**
* @brief Query ISP hardware capabilities.
*
* This function queries dynamic ISP hardware capabilities including
* the number of ISP units available, channels per ISP, and hardware
* fusing status.
*
* @param[in] chan ISP channel context
* @param[out] caps ISP capabilities information
*
* @returns 0 (success), neg. errno (failure)
*/
int isp_capture_get_capabilities(
struct tegra_isp_channel *chan,
struct isp_capabilities_info *caps);
#endif /* __FUSA_CAPTURE_ISP_H__ */