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>
This commit is contained in:
fraunak
2025-07-14 18:03:10 -07:00
committed by mobile promotions
parent 7313487650
commit 59fa283238
4 changed files with 628 additions and 35 deletions

View File

@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (c) 2017-2022 NVIDIA Corporation. All rights reserved.
* Copyright (c) 2017-2025 NVIDIA Corporation. All rights reserved.
*/
/**
@@ -157,6 +157,19 @@ struct isp_buffer_req {
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).
*
@@ -374,4 +387,20 @@ 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__ */

View File

@@ -321,7 +321,7 @@ struct CAPTURE_MSG_HEADER {
* @par Response
* - @ref CAPTURE_COE_CHANNEL_RESET_RESP
*/
#define CAPTURE_COE_CHANNEL_RESET_REQ MK_U32(0x26)
#define CAPTURE_COE_CHANNEL_RESET_REQ MK_U32(0x28)
/**
* @brief CoE capture channel reset response.
@@ -341,7 +341,7 @@ struct CAPTURE_MSG_HEADER {
* @par Payload
* - @ref CAPTURE_COE_CHANNEL_RESET_RESP_MSG
*/
#define CAPTURE_COE_CHANNEL_RESET_RESP MK_U32(0x27)
#define CAPTURE_COE_CHANNEL_RESET_RESP MK_U32(0x29)
/**
* @brief CoE capture channel release request.
@@ -365,7 +365,7 @@ struct CAPTURE_MSG_HEADER {
* @par Response
* - @ref CAPTURE_COE_CHANNEL_RELEASE_RESP
*/
#define CAPTURE_COE_CHANNEL_RELEASE_REQ MK_U32(0x28)
#define CAPTURE_COE_CHANNEL_RELEASE_REQ MK_U32(0x2A)
/**
* @brief CoE capture channel release response.
@@ -385,7 +385,7 @@ struct CAPTURE_MSG_HEADER {
* @par Payload
* - @ref CAPTURE_COE_CHANNEL_RELEASE_RESP_MSG
*/
#define CAPTURE_COE_CHANNEL_RELEASE_RESP MK_U32(0x29)
#define CAPTURE_COE_CHANNEL_RELEASE_RESP MK_U32(0x2B)
/** @} */
/**
@@ -530,6 +530,49 @@ struct CAPTURE_MSG_HEADER {
* - @ref CAPTURE_CHANNEL_ISP_RELEASE_RESP_MSG
*/
#define CAPTURE_CHANNEL_ISP_RELEASE_RESP MK_U32(0x25)
/**
* @brief ISP fuse register query request.
*
* This is a @ref CapCtrlMsgType "capture control message" to
* query the ISP fuse register value from RCE firmware. This
* message is used to determine which ISP units are enabled
* or disabled based on hardware fusing.
*
* @pre The capture-control IVC channel has been set up during
* boot using the @ref CAMRTC_HSP_CH_SETUP command.
*
* @par Header
* - @ref CAPTURE_CONTROL_MSG@b::@ref CAPTURE_MSG_HEADER "header"
* - @ref CAPTURE_MSG_HEADER::msg_id "msg_id" = @ref CAPTURE_ISP_FUSE_QUERY_REQ
* - @ref CAPTURE_MSG_HEADER::transaction "transaction" = <em>unique ID</em>
*
* @par Payload
* - @ref CAPTURE_ISP_FUSE_QUERY_REQ_MSG
*
* @par Response
* - @ref CAPTURE_ISP_FUSE_QUERY_RESP
*/
#define CAPTURE_ISP_FUSE_QUERY_REQ MK_U32(0x26)
/**
* @brief ISP fuse register query response.
*
* This is a @ref CapCtrlMsgType "capture control message" received in
* response to a @ref CAPTURE_ISP_FUSE_QUERY_REQ message.
*
* @pre A @ref CAPTURE_ISP_FUSE_QUERY_REQ message has been sent.
*
* @par Header
* - @ref CAPTURE_CONTROL_MSG@b::@ref CAPTURE_MSG_HEADER "header"
* - @ref CAPTURE_MSG_HEADER::msg_id "msg_id" = @ref CAPTURE_ISP_FUSE_QUERY_RESP
* - @ref CAPTURE_MSG_HEADER::transaction "transaction" =
* @ref CAPTURE_ISP_FUSE_QUERY_REQ@b::@ref CAPTURE_MSG_HEADER "header"@b::@ref CAPTURE_MSG_HEADER::transaction "transaction"
*
* @par Payload
* - @ref CAPTURE_ISP_FUSE_QUERY_RESP_MSG
*/
#define CAPTURE_ISP_FUSE_QUERY_RESP MK_U32(0x27)
/** @} */
/** @} */
@@ -1968,6 +2011,32 @@ struct CAPTURE_CHANNEL_ISP_RELEASE_RESP_MSG {
uint32_t pad__;
} CAPTURE_IVC_ALIGN;
/** @brief Message data for @ref CAPTURE_ISP_FUSE_QUERY_REQ message */
struct CAPTURE_ISP_FUSE_QUERY_REQ_MSG {
/** Reserved - no parameters needed for fuse query */
uint32_t pad__;
/** Reserved */
uint32_t pad2__;
} CAPTURE_IVC_ALIGN;
/** @brief Message data for @ref CAPTURE_ISP_FUSE_QUERY_RESP message */
struct CAPTURE_ISP_FUSE_QUERY_RESP_MSG {
/**
* ISP availability mask calculated from fuse register:
* Each bit represents an ISP unit (bit 0 = ISP0, bit 1 = ISP1, etc.)
* 1 = ISP available, 0 = ISP fused off
* Examples:
* 0x3: Both ISP0 and ISP1 available
* 0x2: Only ISP1 available (ISP0 fused off)
* 0x1: Only ISP0 available (ISP1 fused off)
*/
uint32_t isp_available_mask;
/** Request result code. See @ref CapErrorCodes "result codes". */
capture_result result;
} CAPTURE_IVC_ALIGN;
/**
* @brief Message frame for capture-control IVC channel.
*
@@ -2155,6 +2224,13 @@ struct CAPTURE_CONTROL_MSG {
/** @anon_union_member */
/** Message data for @ref CAPTURE_HSM_CHANSEL_ERROR_MASK_RESP message */
struct CAPTURE_HSM_CHANSEL_ERROR_MASK_RESP_MSG hsm_chansel_mask_resp;
/** @anon_union_member */
/** Message data for @ref CAPTURE_ISP_FUSE_QUERY_REQ message */
struct CAPTURE_ISP_FUSE_QUERY_REQ_MSG isp_fuse_query_req;
/** @anon_union_member */
/** Message data for @ref CAPTURE_ISP_FUSE_QUERY_RESP message */
struct CAPTURE_ISP_FUSE_QUERY_RESP_MSG isp_fuse_query_resp;
};
} CAPTURE_IVC_ALIGN;