mirror of
git://nv-tegra.nvidia.com/linux-nv-oot.git
synced 2025-12-22 09:11:26 +03:00
nvidia-oot: CameraSW: KMD SWUD update
+ Use CameraDoxygenWorkflowV1_02182025 to generate SWUD doxygen headers for functions in FusaCap KMD and RTCPU + Use Cursor Agent to generate SWUD doxygen headers for FusaCap capture-vi.c Jira CAMERASW-32271 Change-Id: Ida6b94d6ffea3df593fa793cc4b9a150c87187ba Signed-off-by: kevixie <kevixie@nvidia.com> Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3313956 Reviewed-by: Mohit Ingale <mohiti@nvidia.com> Reviewed-by: Jagadeesh Kinni <jkinni@nvidia.com> Reviewed-by: Frank Chen <frankc@nvidia.com> GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
This commit is contained in:
@@ -62,13 +62,19 @@ struct capture_mapping {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Determine whether all the bits of @a other are set in @a self.
|
* @brief Determines if all flags in @a other are set in @a self.
|
||||||
*
|
*
|
||||||
* @param[in] self Bitmask flag to be compared
|
* This function performs the following operations:
|
||||||
* @param[in] other Bitmask value(s) to compare
|
* - Computes the bitwise AND of @a self and @a other.
|
||||||
|
* - Compares the result with @a other to determine compatibility.
|
||||||
*
|
*
|
||||||
* @retval true compatible
|
* @param[in] self The source flags to be checked.
|
||||||
* @retval false not compatible
|
* Valid range: [0 .. UINT32_MAX].
|
||||||
|
* @param[in] other The flags to verify against @a self.
|
||||||
|
* Valid range: [0 .. UINT32_MAX].
|
||||||
|
*
|
||||||
|
* @retval true All flags in @a other are set in @a self.
|
||||||
|
* @retval false Not all flags in @a other are set in @a self.
|
||||||
*/
|
*/
|
||||||
static inline bool flag_compatible(
|
static inline bool flag_compatible(
|
||||||
unsigned int self,
|
unsigned int self,
|
||||||
@@ -78,12 +84,20 @@ static inline bool flag_compatible(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Determine whether BUFFER_RDWR is set in @a flag.
|
* @brief Extracts the access mode from the provided flag.
|
||||||
*
|
*
|
||||||
* @param[in] flag Bitmask flag to be compared
|
* This function performs the following operations:
|
||||||
|
* - Applies a bitmask to the input flag to isolate the access mode bits using
|
||||||
|
* @ref BUFFER_RDWR.
|
||||||
*
|
*
|
||||||
* @retval true BUFFER_RDWR set
|
* @param[in] flag The input flags containing access mode information.
|
||||||
* @retval false BUFFER_RDWR not set
|
* Valid range: [0 .. UINT32_MAX].
|
||||||
|
*
|
||||||
|
* @retval 0 No access mode flags are set.
|
||||||
|
* @retval @ref BUFFER_READ Read access mode is set.
|
||||||
|
* @retval @ref BUFFER_WRITE Write access mode is set.
|
||||||
|
* @retval (@ref BUFFER_READ | @ref BUFFER_WRITE) Both read and write access
|
||||||
|
* modes are set.
|
||||||
*/
|
*/
|
||||||
static inline unsigned int flag_access_mode(
|
static inline unsigned int flag_access_mode(
|
||||||
unsigned int flag)
|
unsigned int flag)
|
||||||
@@ -92,11 +106,22 @@ static inline unsigned int flag_access_mode(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Map capture common buffer access flag to a Linux dma_data_direction.
|
* @brief Determines the DMA data direction based on the provided flag.
|
||||||
*
|
*
|
||||||
* @param[in] flag Bitmask access flag of capture common buffer
|
* This function performs the following operations:
|
||||||
|
* - Calls @ref flag_access_mode() to determine the access mode from @a flag.
|
||||||
|
* - Uses the access mode to index into a predefined array mapping to the corresponding
|
||||||
|
* @ref dma_data_direction.
|
||||||
*
|
*
|
||||||
* @returns @ref dma_data_direction mapping
|
* @param[in] flag Flag indicating the desired DMA data direction.
|
||||||
|
* Valid range: [0 .. UINT32_MAX].
|
||||||
|
*
|
||||||
|
* @retval DMA_BIDIRECTIONAL Returned when @ref flag_access_mode() indicates
|
||||||
|
* bidirectional access.
|
||||||
|
* @retval DMA_TO_DEVICE Returned when @ref flag_access_mode() indicates
|
||||||
|
* write access.
|
||||||
|
* @retval DMA_FROM_DEVICE Returned when @ref flag_access_mode() indicates
|
||||||
|
* read access.
|
||||||
*/
|
*/
|
||||||
static inline enum dma_data_direction flag_dma_direction(
|
static inline enum dma_data_direction flag_dma_direction(
|
||||||
unsigned int flag)
|
unsigned int flag)
|
||||||
@@ -112,11 +137,36 @@ static inline enum dma_data_direction flag_dma_direction(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Retrieve the scatterlist IOVA address of the capture surface mapping.
|
* @brief Maps a capture mapping and memory offset to a DMA IOVA address.
|
||||||
*
|
*
|
||||||
* @param[in] pin The capture_mapping of the buffer
|
* This inline function calculates the I/O Virtual Address (IOVA) based on a given
|
||||||
|
* capture mapping and a memory offset. The implementation varies depending
|
||||||
|
* on the Linux kernel version:
|
||||||
*
|
*
|
||||||
* @returns Physical address of scatterlist mapping
|
* - **For Linux versions below 5.10.0:**
|
||||||
|
* - Retrieves the DMA address from the scatter-gather table using @ref sg_dma_address().
|
||||||
|
* - If @ref sg_dma_address() returns 0, obtains the physical address using @ref sg_phys().
|
||||||
|
* - Adds the provided @a mem_offset to the obtained address.
|
||||||
|
*
|
||||||
|
* - **For Linux versions 5.10.0 and above:**
|
||||||
|
* - Traverses the scatterlist using @ref for_each_sgtable_dma_sg().
|
||||||
|
* - For each scatterlist entry, obtains the length using @ref sg_dma_len().
|
||||||
|
* - Retrieves the address using @ref sg_dma_address() or @ref sg_phys().
|
||||||
|
* - Checks for overflow using @ref check_add_overflow().
|
||||||
|
* - If an overflow is detected or no suitable scatterlist entry is found, returns 0.
|
||||||
|
*
|
||||||
|
* @param[in] pin Pointer to the @ref capture_mapping structure.
|
||||||
|
* Valid value: non-null.
|
||||||
|
* @param[in] mem_offset Memory offset to be added to the base address.
|
||||||
|
* Valid range: [0 .. UINT64_MAX].
|
||||||
|
*
|
||||||
|
* @retval (dma_addr_t) The calculated IOVA address based on @a pin and @a mem_offset.
|
||||||
|
* @retval 0 Indicates either:
|
||||||
|
* - An overflow occurred during address calculation as detected by
|
||||||
|
* @ref check_add_overflow().
|
||||||
|
* - No suitable scatterlist entry was found using
|
||||||
|
* @ref for_each_sgtable_dma_sg(), @ref sg_phys(), or
|
||||||
|
* @ref sg_dma_address().
|
||||||
*/
|
*/
|
||||||
static inline dma_addr_t mapping_iova(
|
static inline dma_addr_t mapping_iova(
|
||||||
const struct capture_mapping *pin,
|
const struct capture_mapping *pin,
|
||||||
@@ -152,11 +202,16 @@ static inline dma_addr_t mapping_iova(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Retrieve the dma_buf pointer of a capture surface mapping.
|
* @brief Retrieves the DMA buffer from a capture mapping.
|
||||||
*
|
*
|
||||||
* @param[in] pin The capture_mapping of the buffer
|
* This function performs the following operations:
|
||||||
|
* - Accesses the @a buf member of the provided @ref capture_mapping structure.
|
||||||
*
|
*
|
||||||
* @returns Pointer to the capture_mapping @ref dma_buf
|
* @param[in] pin Pointer to the @ref capture_mapping structure.
|
||||||
|
* Valid value: non-null.
|
||||||
|
*
|
||||||
|
* @retval (dma_buf *) Pointer to the @ref dma_buf structure contained in @a pin.
|
||||||
|
* @retval NULL If the @a buf member in @a pin is not set.
|
||||||
*/
|
*/
|
||||||
static inline struct dma_buf *mapping_buf(
|
static inline struct dma_buf *mapping_buf(
|
||||||
const struct capture_mapping *pin)
|
const struct capture_mapping *pin)
|
||||||
@@ -165,13 +220,17 @@ static inline struct dma_buf *mapping_buf(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Determine whether BUFFER_ADD is set in the capture surface mapping's
|
* @brief Checks if the mapping is preserved based on the BUFFER_ADD flag.
|
||||||
* access flag.
|
|
||||||
*
|
*
|
||||||
* @param[in] pin The capture_mapping of the buffer
|
* This function performs the following operations:
|
||||||
|
* - Validates the input parameter.
|
||||||
|
* - Checks if the BUFFER_ADD flag is set in the provided @ref capture_mapping structure.
|
||||||
*
|
*
|
||||||
* @retval true BUFFER_ADD set
|
* @param[in] pin Pointer to the @ref capture_mapping structure.
|
||||||
* @retval false BUFFER_ADD not set
|
* Valid value: non-null.
|
||||||
|
*
|
||||||
|
* @retval true Indicates that the BUFFER_ADD flag is set, preserving the mapping.
|
||||||
|
* @retval false Indicates that the BUFFER_ADD flag is not set, not preserving the mapping.
|
||||||
*/
|
*/
|
||||||
static inline bool mapping_preserved(
|
static inline bool mapping_preserved(
|
||||||
const struct capture_mapping *pin)
|
const struct capture_mapping *pin)
|
||||||
@@ -180,14 +239,24 @@ static inline bool mapping_preserved(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Set or unset the BUFFER_ADD bit in the capture surface mapping's
|
* @brief Sets or clears the BUFFER_ADD flag and updates the reference count.
|
||||||
* access flag, and correspondingly increment or decrement the mapping's refcnt.
|
|
||||||
*
|
*
|
||||||
* @param[in] pin The capture_mapping of the buffer
|
* This inline function modifies the BUFFER_ADD flag within the provided
|
||||||
* @param[in] val The capture_mapping of the buffer
|
* @ref capture_mapping structure based on the boolean value provided. It also
|
||||||
|
* updates the reference count accordingly:
|
||||||
*
|
*
|
||||||
* @retval true BUFFER_ADD set
|
* - If @a val is `true`:
|
||||||
* @retval false BUFFER_ADD not set
|
* - Sets the BUFFER_ADD flag in the @a pin structure.
|
||||||
|
* - Increments the reference count using @ref atomic_inc().
|
||||||
|
*
|
||||||
|
* - If @a val is `false`:
|
||||||
|
* - Clears the BUFFER_ADD flag in the @a pin structure.
|
||||||
|
* - Decrements the reference count using @ref atomic_dec().
|
||||||
|
*
|
||||||
|
* @param[in, out] pin Pointer to the @ref capture_mapping structure.
|
||||||
|
* Valid value: non-null.
|
||||||
|
* @param[in] val lean value indicating whether to preserve mapping.
|
||||||
|
* Valid value: `true` or `false`.
|
||||||
*/
|
*/
|
||||||
static inline void set_mapping_preservation(
|
static inline void set_mapping_preservation(
|
||||||
struct capture_mapping *pin,
|
struct capture_mapping *pin,
|
||||||
@@ -203,16 +272,34 @@ static inline void set_mapping_preservation(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Iteratively search a capture buffer management table to find the entry
|
* @brief Searches for a capture mapping in the buffer table matching the specified buffer and flag.
|
||||||
* with @a buf, and @a flag bits set in the capture mapping.
|
|
||||||
*
|
*
|
||||||
* On success, the capture mapping is incremented by one if it is non-zero.
|
* This function performs the following operations:
|
||||||
|
* - Acquires a read lock on the buffer table using @ref read_lock().
|
||||||
|
* - Iterates over possible hash entries using @ref hash_for_each_possible() to find a
|
||||||
|
* matching @ref capture_mapping.
|
||||||
|
* - For each entry, checks if the buffer matches and the flags are compatible using
|
||||||
|
* @ref flag_compatible().
|
||||||
|
* - If a match is found, attempts to increment the reference count using
|
||||||
|
* @ref atomic_inc_not_zero().
|
||||||
|
* - If the reference count is successfully incremented, releases the read lock using
|
||||||
|
* @ref read_unlock() and returns the matching @ref capture_mapping.
|
||||||
|
* - Releases the read lock using @ref read_unlock() if no matching mapping is found
|
||||||
|
* or the reference count cannot be incremented.
|
||||||
*
|
*
|
||||||
* @param[in] tab The capture buffer management table
|
* @param[in] tab Pointer to the @ref capture_buffer_table structure.
|
||||||
* @param[in] buf The mapping dma_buf pointer to match
|
* Valid value: non-null.
|
||||||
* @param[in] flag The mapping bitmask access flag to compare
|
* @param[in] buf Pointer to the @ref dma_buf structure to search for.
|
||||||
|
* Valid value: non-null.
|
||||||
|
* @param[in] flag Flags to match against the capture mappings.
|
||||||
|
* Valid range: [0 .. UINT32_MAX].
|
||||||
*
|
*
|
||||||
* @returns @ref capture_mapping pointer (success), NULL (failure)
|
* @retval (capture_mapping *) Pointer to the matching @ref capture_mapping structure if found.
|
||||||
|
* @retval NULL No matching capture mapping was found or
|
||||||
|
* @ref atomic_inc_not_zero() failed, influenced by
|
||||||
|
* @ref read_lock(), @ref hash_for_each_possible(),
|
||||||
|
* @ref flag_compatible(), @ref atomic_inc_not_zero() or
|
||||||
|
* @ref read_unlock().
|
||||||
*/
|
*/
|
||||||
static struct capture_mapping *find_mapping(
|
static struct capture_mapping *find_mapping(
|
||||||
struct capture_buffer_table *tab,
|
struct capture_buffer_table *tab,
|
||||||
@@ -243,14 +330,41 @@ static struct capture_mapping *find_mapping(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Add an NvRm buffer to the buffer management table and initialize its
|
* @brief Retrieves or creates a capture mapping for a given file descriptor and flags.
|
||||||
* refcnt to 1.
|
|
||||||
*
|
*
|
||||||
* @param[in] tab The capture buffer management table
|
* This function performs the following operations:
|
||||||
* @param[in] fd The NvRm handle
|
* - Checks if the input parameter @a tab is non-null.
|
||||||
* @param[in] flag The mapping bitmask access flag to set
|
* - Calls @ref dma_buf_get() to obtain a @ref dma_buf structure for the provided file
|
||||||
|
* descriptor @a fd.
|
||||||
|
* - Calls @ref find_mapping() to search for an existing @ref capture_mapping that matches
|
||||||
|
* the buffer @a buf and flags @a flag.
|
||||||
|
* - If a matching mapping is found, calls @ref dma_buf_put() to release the buffer and returns
|
||||||
|
* the existing mapping.
|
||||||
|
* - Allocates a new @ref capture_mapping structure using @ref kmem_cache_alloc().
|
||||||
|
* - Calls @ref dma_buf_attach() to attach the buffer @a buf to the device associated with
|
||||||
|
* @a tab.
|
||||||
|
* - If @ref dma_buf_attach() fails, frees the allocated mapping with @ref kmem_cache_free().
|
||||||
|
* - Determines the DMA data direction by calling @ref flag_dma_direction() with @a flag.
|
||||||
|
* - Calls @ref dma_buf_map_attachment() to map the DMA buffer.
|
||||||
|
* - If @ref dma_buf_map_attachment() fails, detaches the buffer with @ref dma_buf_detach().
|
||||||
|
* - Initializes the @ref capture_mapping structure with the provided flags and buffer.
|
||||||
|
* - Sets the reference count to 1 and initializes the hash node.
|
||||||
|
* - Acquires a write lock on the buffer table using @ref write_lock().
|
||||||
|
* - Adds the new mapping to the buffer table's hash using @ref hash_add().
|
||||||
|
* - Releases the write lock using @ref write_unlock().
|
||||||
*
|
*
|
||||||
* @returns @ref capture_mapping pointer (success), PTR_ERR (failure)
|
* @param[in] tab Pointer to the @ref capture_buffer_table structure.
|
||||||
|
* Valid value: non-null.
|
||||||
|
* @param[in] fd File descriptor associated with the DMA buffer.
|
||||||
|
* Valid range: [0 .. UINT32_MAX].
|
||||||
|
* @param[in] flag Flags indicating the desired DMA data direction.
|
||||||
|
* Valid range: [0 .. UINT32_MAX].
|
||||||
|
*
|
||||||
|
* @retval (capture_mapping *) Pointer to the matching or newly created @ref capture_mapping.
|
||||||
|
* @retval @ref ERR_PTR(-EINVAL) If @a tab is `NULL`.
|
||||||
|
* @retval @ref ERR_CAST(buf) If @ref dma_buf_get() fails.
|
||||||
|
* @retval @ref ERR_PTR(-ENOMEM) If memory allocation via @ref kmem_cache_alloc() fails.
|
||||||
|
* @retval @ref ERR_PTR() If @ref dma_buf_attach() or @ref dma_buf_map_attachment() fails.
|
||||||
*/
|
*/
|
||||||
static struct capture_mapping *get_mapping(
|
static struct capture_mapping *get_mapping(
|
||||||
struct capture_buffer_table *tab,
|
struct capture_buffer_table *tab,
|
||||||
@@ -318,6 +432,24 @@ err0:
|
|||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Creates and initializes a capture buffer table for the specified device.
|
||||||
|
*
|
||||||
|
* This function performs the following operations:
|
||||||
|
* - Allocates memory for a @ref capture_buffer_table structure using @ref kmalloc().
|
||||||
|
* - Initializes a memory cache for @ref capture_mapping structures using @ref KMEM_CACHE().
|
||||||
|
* - If @ref KMEM_CACHE() fails, frees the allocated table using @ref kfree().
|
||||||
|
* - Sets the device pointer within the table to the provided @a dev.
|
||||||
|
* - Initializes the hash table using @ref hash_init().
|
||||||
|
* - Initializes the read-write lock using @ref rwlock_init().
|
||||||
|
*
|
||||||
|
* @param[in] dev Pointer to the @ref device structure.
|
||||||
|
* Valid value: non-null.
|
||||||
|
*
|
||||||
|
* @retval (capture_buffer_table *) Pointer to the newly created @ref capture_buffer_table.
|
||||||
|
* @retval NULL If memory allocation via @ref kmalloc() or cache creation via
|
||||||
|
* @ref KMEM_CACHE() fails.
|
||||||
|
*/
|
||||||
struct capture_buffer_table *create_buffer_table(
|
struct capture_buffer_table *create_buffer_table(
|
||||||
struct device *dev)
|
struct device *dev)
|
||||||
{
|
{
|
||||||
@@ -342,6 +474,28 @@ struct capture_buffer_table *create_buffer_table(
|
|||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(create_buffer_table);
|
EXPORT_SYMBOL_GPL(create_buffer_table);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Destroys and frees the specified capture buffer table.
|
||||||
|
*
|
||||||
|
* This function performs the following operations:
|
||||||
|
* - Checks if the input parameter @a tab is non-null.
|
||||||
|
* - Iterates over all capture mappings in the buffer table using
|
||||||
|
* @ref hash_for_each_safe().
|
||||||
|
* - For each @ref capture_mapping:
|
||||||
|
* - Acquires a write lock on the buffer table using @ref write_lock().
|
||||||
|
* - Removes the mapping from the hash table using @ref hash_del().
|
||||||
|
* - Releases the write lock using @ref write_unlock().
|
||||||
|
* - Unmaps the DMA attachment using @ref dma_buf_unmap_attachment().
|
||||||
|
* - Detaches the DMA buffer using @ref dma_buf_detach().
|
||||||
|
* - Releases the DMA buffer using @ref dma_buf_put().
|
||||||
|
* - Frees the capture mapping structure using @ref kmem_cache_free().
|
||||||
|
* - Destroys the memory cache for capture mappings using
|
||||||
|
* @ref kmem_cache_destroy().
|
||||||
|
* - Frees the buffer table using @ref kfree().
|
||||||
|
*
|
||||||
|
* @param[in] tab Pointer to the @ref capture_buffer_table structure.
|
||||||
|
* Valid value: non-null.
|
||||||
|
*/
|
||||||
void destroy_buffer_table(
|
void destroy_buffer_table(
|
||||||
struct capture_buffer_table *tab)
|
struct capture_buffer_table *tab)
|
||||||
{
|
{
|
||||||
@@ -387,6 +541,43 @@ EXPORT_SYMBOL_GPL(destroy_buffer_table);
|
|||||||
|
|
||||||
static DEFINE_MUTEX(req_lock);
|
static DEFINE_MUTEX(req_lock);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Requests to add or remove a buffer in the capture buffer table.
|
||||||
|
*
|
||||||
|
* This function performs the following operations:
|
||||||
|
* - Validates the input parameters.
|
||||||
|
* - Acquires the request mutex lock using @ref mutex_lock().
|
||||||
|
* - If adding a buffer:
|
||||||
|
* - Calls @ref get_mapping() to retrieve the mapping for the given @a memfd and access
|
||||||
|
* mode obtained from @ref flag_access_mode().
|
||||||
|
* - Checks if @ref get_mapping() returned an error using @ref IS_ERR().
|
||||||
|
* - Checks if the mapping is already preserved using @ref mapping_preserved().
|
||||||
|
* - If removing a buffer:
|
||||||
|
* - Calls @ref dma_buf_get() to obtain the DMA buffer for the given @a memfd.
|
||||||
|
* - Checks if @ref dma_buf_get() returned an error using @ref IS_ERR().
|
||||||
|
* - Calls @ref find_mapping() to find the corresponding capture mapping.
|
||||||
|
* - Calls @ref dma_buf_put() to release the DMA buffer reference.
|
||||||
|
* - Sets the mapping preservation state by calling @ref set_mapping_preservation().
|
||||||
|
* - Releases the capture mapping by calling @ref put_mapping().
|
||||||
|
* - Releases the request mutex lock using @ref mutex_unlock().
|
||||||
|
*
|
||||||
|
* In case of any errors during the operations, the function ensures that the mutex
|
||||||
|
* lock is released before returning the error code.
|
||||||
|
*
|
||||||
|
* @param[in] tab Pointer to the @ref capture_buffer_table structure.
|
||||||
|
* Valid value: non-null.
|
||||||
|
* @param[in] memfd File descriptor associated with the buffer.
|
||||||
|
* Valid range: [0 .. UINT32_MAX].
|
||||||
|
* @param[in] flag Flags indicating the operation to perform.
|
||||||
|
* Valid range: [0 .. UINT32_MAX].
|
||||||
|
*
|
||||||
|
* @retval 0 Operation completed successfully.
|
||||||
|
* @retval -EINVAL If the input buffer table @a tab is NULL.
|
||||||
|
* @retval -EEXIST If attempting to add a buffer that already exists, as determined
|
||||||
|
* by @ref mapping_preserved().
|
||||||
|
* @retval -ENOENT If attempting to remove a buffer that does not exist in the table.
|
||||||
|
* @retval (int) Errors returned by @ref get_mapping() or @ref dma_buf_get().
|
||||||
|
*/
|
||||||
int capture_buffer_request(
|
int capture_buffer_request(
|
||||||
struct capture_buffer_table *tab,
|
struct capture_buffer_table *tab,
|
||||||
uint32_t memfd,
|
uint32_t memfd,
|
||||||
@@ -449,6 +640,22 @@ end:
|
|||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(capture_buffer_request);
|
EXPORT_SYMBOL_GPL(capture_buffer_request);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Adds a buffer to the capture buffer table with read-write permissions.
|
||||||
|
*
|
||||||
|
* This function performs the following operations:
|
||||||
|
* - Calls @ref capture_buffer_request() to request the addition of a buffer identified
|
||||||
|
* by @a fd to the capture buffer table @a t with flags BUFFER_ADD | BUFFER_RDWR.
|
||||||
|
* - The flags indicate that the buffer should be added and have read-write access.
|
||||||
|
*
|
||||||
|
* @param[in] t Pointer to the @ref capture_buffer_table structure.
|
||||||
|
* Valid value: non-null.
|
||||||
|
* @param[in] fd File descriptor representing the buffer to be added.
|
||||||
|
* Valid range: [0 .. UINT32_MAX].
|
||||||
|
*
|
||||||
|
* @retval 0 Buffer added successfully.
|
||||||
|
* @retval (int) Errors returned by @ref capture_buffer_request().
|
||||||
|
*/
|
||||||
int capture_buffer_add(
|
int capture_buffer_add(
|
||||||
struct capture_buffer_table *t,
|
struct capture_buffer_table *t,
|
||||||
uint32_t fd)
|
uint32_t fd)
|
||||||
@@ -457,6 +664,30 @@ int capture_buffer_add(
|
|||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(capture_buffer_add);
|
EXPORT_SYMBOL_GPL(capture_buffer_add);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Releases a capture mapping and cleans up if it is no longer referenced.
|
||||||
|
*
|
||||||
|
* This function performs the following operations:
|
||||||
|
* - Decrements the reference count of the @ref capture_mapping structure using
|
||||||
|
* @ref atomic_dec_and_test().
|
||||||
|
* - If the reference count reaches zero:
|
||||||
|
* - Checks if the mapping is preserved using @ref mapping_preserved().
|
||||||
|
* - If the mapping is preserved, increments the reference count using
|
||||||
|
* @ref atomic_inc().
|
||||||
|
* - Otherwise:
|
||||||
|
* - Acquires a write lock on the buffer table using @ref write_lock().
|
||||||
|
* - Removes the mapping from the hash table using @ref hash_del().
|
||||||
|
* - Releases the write lock using @ref write_unlock().
|
||||||
|
* - Unmaps the DMA attachment using @ref dma_buf_unmap_attachment().
|
||||||
|
* - Detaches the DMA buffer using @ref dma_buf_detach().
|
||||||
|
* - Releases the DMA buffer using @ref dma_buf_put().
|
||||||
|
* - Frees the capture mapping structure using @ref kmem_cache_free().
|
||||||
|
*
|
||||||
|
* @param[in] t Pointer to the @ref capture_buffer_table structure.
|
||||||
|
* Valid value: non-null.
|
||||||
|
* @param[in] pin Pointer to the @ref capture_mapping structure.
|
||||||
|
* Valid value: non-null.
|
||||||
|
*/
|
||||||
void put_mapping(
|
void put_mapping(
|
||||||
struct capture_buffer_table *t,
|
struct capture_buffer_table *t,
|
||||||
struct capture_mapping *pin)
|
struct capture_mapping *pin)
|
||||||
@@ -485,6 +716,46 @@ void put_mapping(
|
|||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(put_mapping);
|
EXPORT_SYMBOL_GPL(put_mapping);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Pins a memory buffer and retrieves its IOVA address based on the handle and offset.
|
||||||
|
*
|
||||||
|
* This function performs the following operations:
|
||||||
|
* - Checks if the memory handle @a mem_handle is zero.
|
||||||
|
* - Validates that the number of unpins in @a unpins does not exceed
|
||||||
|
* @ref MAX_PIN_BUFFER_PER_REQUEST.
|
||||||
|
* - Calls @ref get_mapping() to retrieve or create a @ref capture_mapping based on
|
||||||
|
* the buffer context @a buf_ctx and memory handle @a mem_handle with flags
|
||||||
|
* @ref BUFFER_RDWR.
|
||||||
|
* - Calls @ref mapping_buf() to obtain the @ref dma_buf associated with the mapping.
|
||||||
|
* - Retrieves the size of the DMA buffer.
|
||||||
|
* - Validates that the memory offset @a mem_offset is within the bounds of the buffer size.
|
||||||
|
* - Calls @ref mapping_iova() to compute the IOVA address for the given memory offset.
|
||||||
|
* - Updates the memory information base address and size using @a meminfo_base_address and
|
||||||
|
* @a meminfo_size with the computed IOVA and remaining size.
|
||||||
|
* - Adds the @ref capture_mapping to the @a unpins structure and increments the
|
||||||
|
* unpins count.
|
||||||
|
*
|
||||||
|
* @param[in] buf_ctx Pointer to the @ref capture_buffer_table structure.
|
||||||
|
* Valid value: non-null.
|
||||||
|
* @param[in] mem_handle File descriptor associated with the memory buffer.
|
||||||
|
* Valid range: [1 .. UINT32_MAX].
|
||||||
|
* @param[in] mem_offset Memory offset within the buffer.
|
||||||
|
* Valid range: [0 .. UINT64_MAX].
|
||||||
|
* @param[out] meminfo_base_address Pointer to store the IOVA base address.
|
||||||
|
* Valid value: non-null.
|
||||||
|
* @param[out] meminfo_size Pointer to store the size of the memory region.
|
||||||
|
* Valid value: non-null.
|
||||||
|
* @param[in, out] unpins Pointer to the @ref capture_common_unpins structure.
|
||||||
|
* Valid value: non-null.
|
||||||
|
*
|
||||||
|
* @retval 0 No buffer was processed (mem_handle is zero) or the operation
|
||||||
|
* succeeded.
|
||||||
|
* @retval -ENOMEM The number of unpins exceeded @c MAX_PIN_BUFFER_PER_REQUEST.
|
||||||
|
* Influenced by the check on @p unpins->num_unpins.
|
||||||
|
* @retval -EINVAL Failed to retrieve a valid mapping using @ref get_mapping(),
|
||||||
|
* the memory offset is out of bounds, or an invalid IOVA was
|
||||||
|
* computed using @ref mapping_iova().
|
||||||
|
*/
|
||||||
int capture_common_pin_and_get_iova(struct capture_buffer_table *buf_ctx,
|
int capture_common_pin_and_get_iova(struct capture_buffer_table *buf_ctx,
|
||||||
uint32_t mem_handle, uint64_t mem_offset,
|
uint32_t mem_handle, uint64_t mem_offset,
|
||||||
uint64_t *meminfo_base_address, uint64_t *meminfo_size,
|
uint64_t *meminfo_base_address, uint64_t *meminfo_size,
|
||||||
@@ -534,6 +805,41 @@ int capture_common_pin_and_get_iova(struct capture_buffer_table *buf_ctx,
|
|||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(capture_common_pin_and_get_iova);
|
EXPORT_SYMBOL_GPL(capture_common_pin_and_get_iova);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Sets up a progress status notifier by mapping a DMA buffer and initializing
|
||||||
|
* the notifier structure.
|
||||||
|
*
|
||||||
|
* This function performs the following operations:
|
||||||
|
* - Acquires a DMA buffer reference using @ref dma_buf_get().
|
||||||
|
* - Validates that the combined @a buffer_size and @a mem_offset do not exceed the
|
||||||
|
* maximum allowable size.
|
||||||
|
* - Checks that the sum of @a buffer_size and @a mem_offset does not exceed the size
|
||||||
|
* of the DMA buffer.
|
||||||
|
* - If it does, releases the DMA buffer using @ref dma_buf_put().
|
||||||
|
* - Maps the DMA buffer using @ref dma_buf_vmap().
|
||||||
|
* - If @ref dma_buf_vmap() fails, releases the DMA buffer using @ref dma_buf_put().
|
||||||
|
* - Clears the mapped memory region using @ref memset().
|
||||||
|
* - Initializes the @ref capture_common_status_notifier structure with the DMA buffer,
|
||||||
|
* virtual address, and memory offset.
|
||||||
|
*
|
||||||
|
* In case of any errors during the operations, the function ensures that the DMA buffer
|
||||||
|
* reference is released before returning the error code.
|
||||||
|
*
|
||||||
|
* @param[in, out] status_notifier Pointer to the @ref capture_common_status_notifier structure.
|
||||||
|
* Valid value: non-null.
|
||||||
|
* @param[in] mem Memory handle representing the buffer.
|
||||||
|
* Valid range: [0 .. UINT32_MAX].
|
||||||
|
* @param[in] buffer_size Size of the buffer to be mapped.
|
||||||
|
* Valid range: [0 .. UINT32_MAX - mem_offset].
|
||||||
|
* @param[in] mem_offset Offset within the buffer.
|
||||||
|
* Valid range: [0 .. UINT32_MAX].
|
||||||
|
*
|
||||||
|
* @retval 0 Operation completed successfully.
|
||||||
|
* @retval -EINVAL The combined buffer size and memory offset exceed allowable limits,
|
||||||
|
* or the memory offset is out of bounds.
|
||||||
|
* @retval -ENOMEM Failed to map the DMA buffer using @ref dma_buf_vmap().
|
||||||
|
* @retval (int) Errors returned by @ref dma_buf_get() or @ref PTR_ERR_OR_ZERO().
|
||||||
|
*/
|
||||||
int capture_common_setup_progress_status_notifier(
|
int capture_common_setup_progress_status_notifier(
|
||||||
struct capture_common_status_notifier *status_notifier,
|
struct capture_common_status_notifier *status_notifier,
|
||||||
uint32_t mem,
|
uint32_t mem,
|
||||||
@@ -583,6 +889,29 @@ int capture_common_setup_progress_status_notifier(
|
|||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(capture_common_setup_progress_status_notifier);
|
EXPORT_SYMBOL_GPL(capture_common_setup_progress_status_notifier);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Releases the progress status notifier by unmapping the DMA buffer and
|
||||||
|
* clearing the notifier structure.
|
||||||
|
*
|
||||||
|
* This function performs the following operations:
|
||||||
|
* - Retrieves the DMA buffer and virtual address from the provided
|
||||||
|
* @ref capture_common_status_notifier structure.
|
||||||
|
* - Initializes the appropriate DMA buffer map structure based on the
|
||||||
|
* compilation configuration.
|
||||||
|
* - If NV_LINUX_IOSYS_MAP_H_PRESENT is defined, initializes the @ref iosys_map structure
|
||||||
|
* calling @ref IOSYS_MAP_INIT_VADDR() given the status notifier virtual address.
|
||||||
|
* - Else, initializes the @ref dma_buf_map structure using @ref DMA_BUF_MAP_INIT_VADDR().
|
||||||
|
* - If the DMA buffer is not NULL:
|
||||||
|
* - If the virtual address is not NULL, calls @ref dma_buf_vunmap() to unmap the DMA buffer.
|
||||||
|
* - Calls @ref dma_buf_put() to release the DMA buffer reference.
|
||||||
|
* - Resets the @ref capture_common_status_notifier structure members to NULL or 0.
|
||||||
|
*
|
||||||
|
* @param[in, out] progress_status_notifier Pointer to the
|
||||||
|
* @ref capture_common_status_notifier structure.
|
||||||
|
* Valid value: non-null.
|
||||||
|
*
|
||||||
|
* @retval 0 Operation completed successfully.
|
||||||
|
*/
|
||||||
int capture_common_release_progress_status_notifier(
|
int capture_common_release_progress_status_notifier(
|
||||||
struct capture_common_status_notifier *progress_status_notifier)
|
struct capture_common_status_notifier *progress_status_notifier)
|
||||||
{
|
{
|
||||||
@@ -609,6 +938,30 @@ int capture_common_release_progress_status_notifier(
|
|||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(capture_common_release_progress_status_notifier);
|
EXPORT_SYMBOL_GPL(capture_common_release_progress_status_notifier);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Sets the progress status for a specific buffer slot.
|
||||||
|
*
|
||||||
|
* This function performs the following operations:
|
||||||
|
* - Calculates the status notifier address by adding the memory offset to the virtual address.
|
||||||
|
* - Validates that the provided @a buffer_slot is within the range of @a buffer_depth.
|
||||||
|
* - Sanitizes @a buffer_slot using @ref array_index_nospec().
|
||||||
|
* - Inserts a memory barrier using @ref wmb() to ensure proper memory ordering.
|
||||||
|
* - Updates the progress status notifier buffer at the sanitized @a buffer_slot with @a new_val.
|
||||||
|
*
|
||||||
|
* @param[in, out] progress_status_notifier Pointer to the
|
||||||
|
* @ref capture_common_status_notifier structure.
|
||||||
|
* Valid value: non-null.
|
||||||
|
* @param[in] buffer_slot Index of the buffer slot to set the status.
|
||||||
|
* Valid range: [0 .. buffer_depth - 1].
|
||||||
|
* @param[in] buffer_depth Total number of buffer slots.
|
||||||
|
* Valid range: [1 .. UINT32_MAX].
|
||||||
|
* @param[in] new_val New value to set in the progress status.
|
||||||
|
* Valid range: [0 .. UINT8_MAX].
|
||||||
|
*
|
||||||
|
* @retval 0 Operation completed successfully.
|
||||||
|
* @retval -EINVAL If @a buffer_slot is out of range as validated by @ref array_index_nospec()
|
||||||
|
* or if the memory offset is invalid.
|
||||||
|
*/
|
||||||
int capture_common_set_progress_status(
|
int capture_common_set_progress_status(
|
||||||
struct capture_common_status_notifier *progress_status_notifier,
|
struct capture_common_status_notifier *progress_status_notifier,
|
||||||
uint32_t buffer_slot,
|
uint32_t buffer_slot,
|
||||||
@@ -638,6 +991,35 @@ int capture_common_set_progress_status(
|
|||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(capture_common_set_progress_status);
|
EXPORT_SYMBOL_GPL(capture_common_set_progress_status);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Pins a memory buffer and retrieves its IOVA address and associated data.
|
||||||
|
*
|
||||||
|
* This function performs the following operations:
|
||||||
|
* - Obtains a reference to the DMA buffer using @ref dma_buf_get() with the memory handle @a mem.
|
||||||
|
* - Attaches the DMA buffer to the device @a dev using @ref dma_buf_attach().
|
||||||
|
* - Maps the DMA buffer attachment with bidirectional access using @ref dma_buf_map_attachment().
|
||||||
|
* - Checks if the DMA scatter-gather list DMA address is zero using @ref sg_dma_address().
|
||||||
|
* - If zero, retrieves the physical address using @ref sg_phys() and updates the DMA address.
|
||||||
|
* - Maps the DMA buffer into the virtual address space using @ref dma_buf_vmap().
|
||||||
|
* - If @ref dma_buf_vmap() fails, sets @ref unpin_data virtual address to NULL.
|
||||||
|
* - Clears the mapped memory region using @ref memset().
|
||||||
|
* - Initializes the @ref capture_common_buf structure with the DMA buffer, virtual address,
|
||||||
|
* IOVA address, attachment, and scatter-gather table.
|
||||||
|
* - If any step fails, cleans up by calling @ref capture_common_unpin_memory().
|
||||||
|
*
|
||||||
|
* @param[in] dev Pointer to the @ref device structure.
|
||||||
|
* Valid value: non-null.
|
||||||
|
* @param[in] mem Memory handle representing the buffer.
|
||||||
|
* Valid range: [1 .. UINT32_MAX].
|
||||||
|
* @param[in, out] unpin_data Pointer to the @ref capture_common_buf structure to populate.
|
||||||
|
* Valid value: non-null.
|
||||||
|
*
|
||||||
|
* @retval 0 Operation completed successfully.
|
||||||
|
* @retval -EINVAL If the buffer handle is invalid or buffer offset exceeds buffer size.
|
||||||
|
* @retval -ENOMEM Failed to map the DMA buffer using @ref dma_buf_vmap().
|
||||||
|
* @retval (int) Errors returned by @ref dma_buf_get(), @ref dma_buf_attach(),
|
||||||
|
* or @ref dma_buf_map_attachment(), as retrieved by @ref PTR_ERR().
|
||||||
|
*/
|
||||||
int capture_common_pin_memory(
|
int capture_common_pin_memory(
|
||||||
struct device *dev,
|
struct device *dev,
|
||||||
uint32_t mem,
|
uint32_t mem,
|
||||||
@@ -694,6 +1076,30 @@ fail:
|
|||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(capture_common_pin_memory);
|
EXPORT_SYMBOL_GPL(capture_common_pin_memory);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Unpins previously pinned memory and performs necessary cleanup.
|
||||||
|
*
|
||||||
|
* This function performs the following operations:
|
||||||
|
* - Initializes a mapping structure based on the presence of
|
||||||
|
* NV_LINUX_IOSYS_MAP_H_PRESENT.
|
||||||
|
* - If present, initialize mapping structure by calling @ref IOSYS_MAP_INIT_VADDR()
|
||||||
|
* with the virtual address of the provided @ref capture_common_buf.
|
||||||
|
* - Else, initialize mapping structure by calling @ref DMA_BUF_MAP_INIT_VADDR()
|
||||||
|
* with the virtual address of the provided @ref capture_common_buf.
|
||||||
|
* - If the virtual address of @a unpin_data is non-null, calls @ref dma_buf_vunmap()
|
||||||
|
* to unmap the virtual address.
|
||||||
|
* - If the scatter gather table of @a unpin_data is non-null, calls
|
||||||
|
* @ref dma_buf_unmap_attachment() to unmap the DMA attachment with the @ref DMA_BIDIRECTIONAL
|
||||||
|
* flag.
|
||||||
|
* - If the buffer attattchment of @a unpin_data is non-null, calls @ref dma_buf_detach()
|
||||||
|
* to detach the DMA buffer from the device.
|
||||||
|
* - If DMA buffer of @a unpin_data is non-null, calls @ref dma_buf_put()
|
||||||
|
* to release the DMA buffer.
|
||||||
|
* - Resets all fields in the @ref capture_common_buf structure to NULL or zero.
|
||||||
|
*
|
||||||
|
* @param[in, out] unpin_data Pointer to the @ref capture_common_buf structure to be cleaned up.
|
||||||
|
* Valid value: non-null.
|
||||||
|
*/
|
||||||
void capture_common_unpin_memory(
|
void capture_common_unpin_memory(
|
||||||
struct capture_common_buf *unpin_data)
|
struct capture_common_buf *unpin_data)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -199,19 +199,41 @@ static struct isp_channel_drv *chdrv_;
|
|||||||
static DEFINE_MUTEX(chdrv_lock);
|
static DEFINE_MUTEX(chdrv_lock);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Open an ISP channel character device node, power on the camera
|
* @brief Opens an ISP channel for the given @a inode and @a file.
|
||||||
* subsystem and initialize the channel driver context.
|
|
||||||
*
|
*
|
||||||
* The act of opening an ISP channel character device node does not entail the
|
* This function handles the opening of an Image Signal Processor (ISP) channel by performing
|
||||||
|
* the following steps:
|
||||||
|
* - Acquires the channel driver lock using @ref mutex_lock_interruptible().
|
||||||
|
* - Retrieves the channel number from the provided @ref inode.
|
||||||
|
* - Validates the availability of the channel driver and the specified channel number.
|
||||||
|
* - Releases the channel driver lock using @ref mutex_unlock().
|
||||||
|
* - Allocates and initializes a new @ref tegra_isp_channel structure.
|
||||||
|
* - Initializes the capture process by calling @ref isp_capture_init().
|
||||||
|
* - Acquires the channel driver lock using @ref mutex_lock().
|
||||||
|
* - Registers the channel within the channel driver's channel array.
|
||||||
|
* - Releases the channel driver lock using @ref mutex_unlock().
|
||||||
|
* - Associates the channel with the opened file by setting private data for provided @ref file.
|
||||||
|
* - Opens the file in a non-seekable mode using @ref nonseekable_open().
|
||||||
|
*
|
||||||
|
* If any step fails, the function performs necessary cleanup, including shutting down the
|
||||||
|
* capture process by calling @ref isp_capture_shutdown() and freeing allocated memory
|
||||||
|
* by calling @ref kfree().
|
||||||
|
*
|
||||||
|
* @note The act of opening an ISP channel character device node does not entail the
|
||||||
* reservation of an ISP channel, ISP_CAPTURE_SETUP must be called afterwards
|
* reservation of an ISP channel, ISP_CAPTURE_SETUP must be called afterwards
|
||||||
* to request an allocation by RCE.
|
* to request an allocation by RCE.
|
||||||
*
|
*
|
||||||
* This is the @a open file operation handler for an ISP channel node.
|
* @param[in] inode Pointer to the @ref inode structure representing the file inode.
|
||||||
|
* Valid Value: non-NULL.
|
||||||
|
* @param[in] file Pointer to the @ref file structure representing the opened file.
|
||||||
|
* Valid Value: non-NULL.
|
||||||
*
|
*
|
||||||
* @param[in] inode ISP channel character device inode struct
|
* @retval 0 Successfully opened the ISP channel.
|
||||||
* @param[in] file ISP channel character device file struct
|
* @retval -ENOMEM Memory allocation @ref kzalloc() for the channel failed.
|
||||||
*
|
* @retval -ENODEV Channel driver is unavailable or the channel number is invalid.
|
||||||
* @returns 0 (success), neg. errno (failure)
|
* @retval -EBUSY The requested channel is already in use.
|
||||||
|
* @retval -ERESTARTSYS The lock acquisition was interrupted.
|
||||||
|
* @retval (int) Initialization or file opening failed.
|
||||||
*/
|
*/
|
||||||
static int isp_channel_open(
|
static int isp_channel_open(
|
||||||
struct inode *inode,
|
struct inode *inode,
|
||||||
@@ -270,18 +292,23 @@ init_err:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Release an ISP channel character device node, power off the camera
|
* @brief Releases an ISP channel and performs necessary cleanup.
|
||||||
* subsystem and free the ISP channel driver context.
|
|
||||||
*
|
*
|
||||||
* Under normal operation, ISP_CAPTURE_RESET followed by ISP_CAPTURE_RELEASE
|
* This function releases the ISP channel associated with the provided @a file and @a inode.
|
||||||
* should be called before releasing the file handle on the device node.
|
* It performs the following operations:
|
||||||
|
* - Calls @ref isp_capture_shutdown() to shut down the ISP capture process.
|
||||||
|
* - Acquires the channel driver's lock by invoking @ref mutex_lock().
|
||||||
|
* - Verifies that the channel being released matches the registered channel using @ref WARN_ON().
|
||||||
|
* - Removes the channel from the driver's channel array by setting the corresponding entry to NULL.
|
||||||
|
* - Releases the channel driver's lock by calling @ref mutex_unlock().
|
||||||
|
* - Frees the memory allocated for the channel using @ref kfree().
|
||||||
*
|
*
|
||||||
* This is the @a release file operation handler for an ISP channel node.
|
* @param[in] inode Pointer to the @ref inode structure representing the file's inode.
|
||||||
|
* Valid Value: non-NULL.
|
||||||
|
* @param[in] file Pointer to the @ref file structure representing the opened file.
|
||||||
|
* Valid Value: non-NULL.
|
||||||
*
|
*
|
||||||
* @param[in] inode ISP channel character device inode struct
|
* @retval 0 Successfully released the ISP channel and performed cleanup.
|
||||||
* @param[in] file ISP channel character device file struct
|
|
||||||
*
|
|
||||||
* @returns 0
|
|
||||||
*/
|
*/
|
||||||
static int isp_channel_release(
|
static int isp_channel_release(
|
||||||
struct inode *inode,
|
struct inode *inode,
|
||||||
@@ -320,6 +347,79 @@ static int isp_channel_release(
|
|||||||
*
|
*
|
||||||
* @returns 0 (success), neg. errno (failure)
|
* @returns 0 (success), neg. errno (failure)
|
||||||
*/
|
*/
|
||||||
|
/**
|
||||||
|
* @brief Handles ioctl commands for the ISP channel.
|
||||||
|
*
|
||||||
|
* This function performs the following operations:
|
||||||
|
* - Retrieves the ISP channel associated with the opened file.
|
||||||
|
* - Validates the existence of the channel.
|
||||||
|
* - Extracts the ioctl command number using @ref _IOC_NR().
|
||||||
|
* - Executes the corresponding operation based on the command number:
|
||||||
|
* - For ISP_CAPTURE_SETUP:
|
||||||
|
* - Copies the @ref isp_capture_setup structure from user space using
|
||||||
|
* @ref copy_from_user().
|
||||||
|
* - Calls @ref isp_get_nvhost_device() to obtain the NVHost device.
|
||||||
|
* - Ensures the ISP device is valid.
|
||||||
|
* - Invokes @ref isp_capture_setup() with the setup data.
|
||||||
|
* - For ISP_CAPTURE_RESET:
|
||||||
|
* - Copies the reset parameter from user space using @ref copy_from_user().
|
||||||
|
* - Calls @ref isp_capture_reset() with the reset value.
|
||||||
|
* - For ISP_CAPTURE_RELEASE:
|
||||||
|
* - Copies the release parameter from user space using @ref copy_from_user().
|
||||||
|
* - Invokes @ref isp_capture_release() to release the capture.
|
||||||
|
* - For ISP_CAPTURE_GET_INFO:
|
||||||
|
* - Initializes the @ref isp_capture_info structure.
|
||||||
|
* - Calls @ref isp_capture_get_info() to retrieve capture information.
|
||||||
|
* - Copies the information back to user space using @ref copy_to_user().
|
||||||
|
* - For ISP_CAPTURE_REQUEST:
|
||||||
|
* - Copies the capture request data from user space using
|
||||||
|
* @ref copy_from_user().
|
||||||
|
* - Calls @ref isp_capture_request() to process the capture request.
|
||||||
|
* - For ISP_CAPTURE_STATUS:
|
||||||
|
* - Copies the timeout value from user space using @ref copy_from_user().
|
||||||
|
* - Invokes @ref isp_capture_status() with the timeout.
|
||||||
|
* - For ISP_CAPTURE_PROGRAM_REQUEST:
|
||||||
|
* - Copies the program request data from user space using
|
||||||
|
* @ref copy_from_user().
|
||||||
|
* - Calls @ref isp_capture_program_request() to submit the program request.
|
||||||
|
* - For ISP_CAPTURE_PROGRAM_STATUS:
|
||||||
|
* - Invokes @ref isp_capture_program_status() to get program status.
|
||||||
|
* - For ISP_CAPTURE_REQUEST_EX:
|
||||||
|
* - Copies the extended request data from user space using
|
||||||
|
* @ref copy_from_user().
|
||||||
|
* - Calls @ref isp_capture_request_ex() to submit the extended request.
|
||||||
|
* - For ISP_CAPTURE_SET_PROGRESS_STATUS_NOTIFIER:
|
||||||
|
* - Copies the notifier data from user space using
|
||||||
|
* @ref copy_from_user().
|
||||||
|
* - Invokes @ref isp_capture_set_progress_status_notifier() to set the notifier.
|
||||||
|
* - For ISP_CAPTURE_BUFFER_REQUEST:
|
||||||
|
* - Copies the buffer request data from user space using
|
||||||
|
* @ref copy_from_user().
|
||||||
|
* - Calls @ref isp_capture_buffer_request() to request buffers.
|
||||||
|
* - Handles errors by setting appropriate error codes.
|
||||||
|
*
|
||||||
|
* @param[in] file Pointer to the @ref file structure representing the opened file.
|
||||||
|
* Valid Value: non-NULL.
|
||||||
|
* @param[in] cmd Ioctl command number.
|
||||||
|
* Valid Range: Defined in @ref ISP_CHANNEL_IOCTLS.
|
||||||
|
* @param[in] arg Argument for the ioctl command, typically a pointer to user data.
|
||||||
|
* Valid Value: Depends on @a cmd.
|
||||||
|
*
|
||||||
|
* @retval 0 Successfully executed the ioctl command.
|
||||||
|
* @retval -EINVAL If the channel is invalid or the channel
|
||||||
|
* device is NULL, potentially due to @ref
|
||||||
|
* _IOC_NR() or @ref isp_get_nvhost_device().
|
||||||
|
* @retval -EFAULT If copying data from/to user space fails
|
||||||
|
* using @ref copy_from_user() or @ref copy_to_user().
|
||||||
|
* @retval -ENOIOCTLCMD If an unknown ioctl command is received.
|
||||||
|
* @retval (int) Errors returned by @ref isp_capture_setup(),
|
||||||
|
* @ref isp_capture_reset(), @ref isp_capture_release(),
|
||||||
|
* @ref isp_capture_get_info(), @ref isp_capture_request(),
|
||||||
|
* @ref isp_capture_status(), @ref isp_capture_program_request(),
|
||||||
|
* @ref isp_capture_program_status(), @ref isp_capture_request_ex(),
|
||||||
|
* @ref isp_capture_set_progress_status_notifier(),
|
||||||
|
* or @ref isp_capture_buffer_request().
|
||||||
|
*/
|
||||||
static long isp_channel_ioctl(
|
static long isp_channel_ioctl(
|
||||||
struct file *file,
|
struct file *file,
|
||||||
unsigned int cmd,
|
unsigned int cmd,
|
||||||
@@ -501,6 +601,39 @@ static const struct file_operations isp_channel_fops = {
|
|||||||
static struct class *isp_channel_class;
|
static struct class *isp_channel_class;
|
||||||
static int isp_channel_major = -1;
|
static int isp_channel_major = -1;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Registers and initializes the ISP channel driver.
|
||||||
|
*
|
||||||
|
* This function performs the following operations:
|
||||||
|
* - Allocates memory for the @ref isp_channel_drv structure with space for
|
||||||
|
* the specified maximum number of ISP channels using @ref kzalloc().
|
||||||
|
* - Initializes the driver structure fields, including setting the platform
|
||||||
|
* device TO @a ndev and the maximum number of channels to @a max_isp_channels.
|
||||||
|
* - Initializes the driver mutex lock using @ref mutex_init().
|
||||||
|
* - Acquires the global channel driver lock by invoking @ref mutex_lock().
|
||||||
|
* - Checks if a channel driver is already registered using @ref WARN_ON().
|
||||||
|
* If a driver is already registered, it releases the lock and frees the allocated
|
||||||
|
* memory with @ref kfree().
|
||||||
|
* - Sets the global channel driver reference to the newly allocated driver and
|
||||||
|
* releases the global lock using @ref mutex_unlock.
|
||||||
|
* - Validates the ISP channel major number is not negative.
|
||||||
|
* - Iterates over the number of channels and creates device nodes for each
|
||||||
|
* channel using @ref device_create().
|
||||||
|
*
|
||||||
|
* @param[in] ndev Pointer to the @ref platform_device structure representing the
|
||||||
|
* platform device.
|
||||||
|
* Valid Value: non-NULL.
|
||||||
|
* @param[in] max_isp_channels Maximum number of ISP channels to support.
|
||||||
|
* Valid Range: [0 .. UINT32_MAX].
|
||||||
|
*
|
||||||
|
* @retval 0 Successfully registered and initialized the ISP channel driver.
|
||||||
|
* @retval -ENOMEM If memory allocation for the driver structure fails,
|
||||||
|
* as indicated by @ref kzalloc().
|
||||||
|
* @retval -EBUSY If an ISP channel driver is already registered, detected via
|
||||||
|
* @ref WARN_ON().
|
||||||
|
* @retval -EINVAL If the ISP channel major number is invalid, as checked before
|
||||||
|
* device creation.
|
||||||
|
*/
|
||||||
int isp_channel_drv_register(
|
int isp_channel_drv_register(
|
||||||
struct platform_device *ndev,
|
struct platform_device *ndev,
|
||||||
unsigned int max_isp_channels)
|
unsigned int max_isp_channels)
|
||||||
@@ -544,6 +677,27 @@ int isp_channel_drv_register(
|
|||||||
}
|
}
|
||||||
EXPORT_SYMBOL(isp_channel_drv_register);
|
EXPORT_SYMBOL(isp_channel_drv_register);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Registers file operations for the ISP channel driver.
|
||||||
|
*
|
||||||
|
* This function performs the following operations:
|
||||||
|
* - Retrieves the global ISP channel driver instance.
|
||||||
|
* - Checks if the channel driver is initialized by verifying the global driver reference.
|
||||||
|
* - Acquires the global channel driver lock using @ref mutex_lock().
|
||||||
|
* - If the driver operations are not set, assigns the provided operations.
|
||||||
|
* - If the operations are already registered, logs a debug message using
|
||||||
|
* @ref dev_dbg().
|
||||||
|
* - Releases the global channel driver lock using @ref mutex_unlock().
|
||||||
|
* - Returns a status code based on the operation outcome.
|
||||||
|
*
|
||||||
|
* @param[in] ops Pointer to the @ref isp_channel_drv_ops structure containing the
|
||||||
|
* file operations to be registered.
|
||||||
|
* Valid Value: non-NULL.
|
||||||
|
*
|
||||||
|
* @retval 0 Successfully registered the file operations.
|
||||||
|
* @retval -EPROBE_DEFER The ISP channel driver is not yet initialized,
|
||||||
|
* as indicated by @ref chdrv_ being NULL.
|
||||||
|
*/
|
||||||
int isp_channel_drv_fops_register(
|
int isp_channel_drv_fops_register(
|
||||||
const struct isp_channel_drv_ops *ops)
|
const struct isp_channel_drv_ops *ops)
|
||||||
{
|
{
|
||||||
@@ -570,6 +724,24 @@ error:
|
|||||||
}
|
}
|
||||||
EXPORT_SYMBOL(isp_channel_drv_fops_register);
|
EXPORT_SYMBOL(isp_channel_drv_fops_register);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Unregisters the ISP channel driver and performs cleanup.
|
||||||
|
*
|
||||||
|
* This function performs the following operations:
|
||||||
|
* - Acquires the global channel driver lock using @ref mutex_lock().
|
||||||
|
* - Retrieves the current ISP channel driver instance from the global reference.
|
||||||
|
* - Clears the global channel driver reference to indicate that it is no longer registered.
|
||||||
|
* - Validates that the provided device matches the driver's device using @ref WARN_ON().
|
||||||
|
* - Releases the global channel driver lock using @ref mutex_unlock().
|
||||||
|
* - Checks if the ISP channel major number is valid. If invalid, logs an error using
|
||||||
|
* @ref pr_err() and exits.
|
||||||
|
* - Iterates over all registered channels and destroys each device node using
|
||||||
|
* @ref device_destroy().
|
||||||
|
* - Frees the memory allocated for the ISP channel driver using @ref kfree().
|
||||||
|
*
|
||||||
|
* @param[in] dev Pointer to the @ref device structure representing the device to unregister.
|
||||||
|
* Valid Value: non-NULL.
|
||||||
|
*/
|
||||||
void isp_channel_drv_unregister(
|
void isp_channel_drv_unregister(
|
||||||
struct device *dev)
|
struct device *dev)
|
||||||
{
|
{
|
||||||
@@ -598,9 +770,18 @@ void isp_channel_drv_unregister(
|
|||||||
EXPORT_SYMBOL(isp_channel_drv_unregister);
|
EXPORT_SYMBOL(isp_channel_drv_unregister);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Initialize the ISP channel driver device (major).
|
* @brief Initializes and registers the ISP channel driver.
|
||||||
*
|
*
|
||||||
* @returns 0 (success), PTR_ERR or neg. ISP channel major no. (failuure)
|
* This function performs the following operations:
|
||||||
|
* - Creates the ISP channel device class using @ref class_create().
|
||||||
|
* - Registers a character device for the ISP channel with @ref register_chrdev().
|
||||||
|
* - If registration fails, destroys the created device class using
|
||||||
|
* @ref class_destroy().
|
||||||
|
* - Returns status based on the operation outcomes.
|
||||||
|
*
|
||||||
|
* @retval 0 Successfully initialized and registered the ISP channel driver.
|
||||||
|
* @retval (int) Error returned by @ref PTR_ERR() if @ref class_create() fails or by
|
||||||
|
* @ref register_chrdev() if character device registration fails.
|
||||||
*/
|
*/
|
||||||
int isp_channel_drv_init(void)
|
int isp_channel_drv_init(void)
|
||||||
{
|
{
|
||||||
@@ -624,7 +805,12 @@ int isp_channel_drv_init(void)
|
|||||||
EXPORT_SYMBOL(isp_channel_drv_init);
|
EXPORT_SYMBOL(isp_channel_drv_init);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief De-initialize the ISP channel driver device (major).
|
* @brief Cleans up and unregisters the ISP channel driver.
|
||||||
|
*
|
||||||
|
* This function performs the following operations:
|
||||||
|
* - Calls @ref unregister_chrdev() to unregister the character device associated
|
||||||
|
* with the ISP channel driver.
|
||||||
|
* - Calls @ref class_destroy() to destroy the device class for ISP channels.
|
||||||
*/
|
*/
|
||||||
void isp_channel_drv_exit(void)
|
void isp_channel_drv_exit(void)
|
||||||
{
|
{
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -155,6 +155,25 @@
|
|||||||
|
|
||||||
/** @} */
|
/** @} */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Unpins previously pinned buffers for a VI capture channel.
|
||||||
|
*
|
||||||
|
* This function unpins buffers associated with a specified buffer index in a VI capture channel.
|
||||||
|
* It performs the following operations:
|
||||||
|
* - Validates the input capture channel pointer.
|
||||||
|
* - Retrieves and validates the capture data from the channel.
|
||||||
|
* - Locks the unpins list mutex using @ref mutex_lock().
|
||||||
|
* - Accesses the unpins list for the specified buffer index.
|
||||||
|
* - If there are pending unpins, iterates through each and releases the mappings
|
||||||
|
* by calling @ref put_mapping().
|
||||||
|
* - Resets the unpins data using @ref memset().
|
||||||
|
* - Unlocks the unpins list mutex using @ref mutex_unlock().
|
||||||
|
*
|
||||||
|
* @param[in] chan Pointer to the @ref tegra_vi_channel structure.
|
||||||
|
* Valid value: non-NULL.
|
||||||
|
* @param[in] buffer_index Index of the buffer to unpin.
|
||||||
|
* Valid range: corresponds to entries in the unpins list.
|
||||||
|
*/
|
||||||
void vi_capture_request_unpin(
|
void vi_capture_request_unpin(
|
||||||
struct tegra_vi_channel *chan,
|
struct tegra_vi_channel *chan,
|
||||||
uint32_t buffer_index)
|
uint32_t buffer_index)
|
||||||
@@ -191,6 +210,39 @@ EXPORT_SYMBOL(vi_capture_request_unpin);
|
|||||||
static struct vi_channel_drv *chdrv_;
|
static struct vi_channel_drv *chdrv_;
|
||||||
static DEFINE_MUTEX(chdrv_lock);
|
static DEFINE_MUTEX(chdrv_lock);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Opens a VI channel with the specified configuration.
|
||||||
|
*
|
||||||
|
* This function performs the following operations:
|
||||||
|
* - Attempts to acquire the channel driver lock using @ref mutex_lock_interruptible().
|
||||||
|
* - Retrieves the channel driver instance.
|
||||||
|
* - Validates that the channel driver is initialized and the channel index is within
|
||||||
|
* the available range.
|
||||||
|
* - Releases the channel driver lock using @ref mutex_unlock().
|
||||||
|
* - Allocates memory for a new @ref tegra_vi_channel structure using @ref kzalloc().
|
||||||
|
* - Initializes the channel structure with driver data and operations.
|
||||||
|
* - Initializes capture settings by calling @ref vi_capture_init().
|
||||||
|
* - Acquires the channel driver's lock using @ref mutex_lock().
|
||||||
|
* - Checks if the specified channel is already in use via @ref rcu_access_pointer().
|
||||||
|
* - Assigns the new channel to the driver's channel array using @ref rcu_assign_pointer().
|
||||||
|
* - Releases the channel driver's lock.
|
||||||
|
* - On failure, cleans up resources by calling @ref vi_capture_shutdown() and
|
||||||
|
* @ref kfree().
|
||||||
|
*
|
||||||
|
* @param[in] channel The index of the channel to open.
|
||||||
|
* Valid range: [0 .. @ref vi_channel_drv.num_channels - 1]
|
||||||
|
* @param[in] is_mem_pinned Flag indicating whether memory should be pinned.
|
||||||
|
* Valid value: true or false.
|
||||||
|
*
|
||||||
|
* @retval (tegra_vi_channel *) Pointer to @ref tegra_vi_channel On successful completion.
|
||||||
|
* @retval ERR_PTR(-ERESTARTSYS) If @ref mutex_lock_interruptible() is interrupted.
|
||||||
|
* @retval ERR_PTR(-ENODEV) If the channel driver is unavailable or
|
||||||
|
* the channel index is out of range.
|
||||||
|
* @retval ERR_PTR(-ENOMEM) If memory allocation via @ref kzalloc() fails.
|
||||||
|
* @retval ERR_PTR(-EBUSY) If the specified channel is already open via
|
||||||
|
* @ref rcu_access_pointer().
|
||||||
|
* @retval ERR_PTR(err) Errors propagated from @ref vi_capture_init().
|
||||||
|
*/
|
||||||
struct tegra_vi_channel *vi_channel_open_ex(
|
struct tegra_vi_channel *vi_channel_open_ex(
|
||||||
unsigned int channel,
|
unsigned int channel,
|
||||||
bool is_mem_pinned)
|
bool is_mem_pinned)
|
||||||
@@ -243,6 +295,25 @@ error:
|
|||||||
}
|
}
|
||||||
EXPORT_SYMBOL(vi_channel_open_ex);
|
EXPORT_SYMBOL(vi_channel_open_ex);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Closes a VI channel and releases associated resources.
|
||||||
|
*
|
||||||
|
* This function performs the following operations:
|
||||||
|
* - Shuts down the capture on the specified channel using @ref vi_capture_shutdown().
|
||||||
|
* - Acquires the channel driver's lock using @ref mutex_lock().
|
||||||
|
* - Verifies that the channel being closed is the one stored in the driver's channel array
|
||||||
|
* using @ref rcu_access_pointer().
|
||||||
|
* - Sets the corresponding entry in the driver's channel array to NULL using @ref RCU_INIT_POINTER().
|
||||||
|
* - Releases the channel driver's lock using @ref mutex_unlock().
|
||||||
|
* - Frees the memory allocated for the channel structure using @ref kfree_rcu().
|
||||||
|
*
|
||||||
|
* @param[in] channel The index of the channel to close.
|
||||||
|
* Valid range: [0 .. @ref vi_channel_drv.num_channels - 1]
|
||||||
|
* @param[in] chan Pointer to the @ref tegra_vi_channel structure to close.
|
||||||
|
* Valid value: non-NULL.
|
||||||
|
*
|
||||||
|
* @retval 0 On successful completion.
|
||||||
|
*/
|
||||||
int vi_channel_close_ex(
|
int vi_channel_close_ex(
|
||||||
unsigned int channel,
|
unsigned int channel,
|
||||||
struct tegra_vi_channel *chan)
|
struct tegra_vi_channel *chan)
|
||||||
@@ -264,15 +335,33 @@ int vi_channel_close_ex(
|
|||||||
EXPORT_SYMBOL(vi_channel_close_ex);
|
EXPORT_SYMBOL(vi_channel_close_ex);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Open a VI channel character device node; pass parameters to
|
* @brief Opens a VI channel and associates it with a file instance.
|
||||||
* @ref vi_channel_open_ex subroutine to complete initialization.
|
|
||||||
*
|
*
|
||||||
* This is the @a open file operation handler for a VI channel node.
|
* This function performs the following operations:
|
||||||
|
* - Retrieves the channel index from the provided @ref inode using @ref iminor().
|
||||||
|
* - Calls @ref vi_channel_open_ex() with the channel index and a memory pinned flag.
|
||||||
|
* - Checks if the returned channel pointer is an error using @ref IS_ERR().
|
||||||
|
* - Assigns the opened channel to the @ref file's private data.
|
||||||
|
* - Calls @ref nonseekable_open() to perform standard file opening operations.
|
||||||
|
* - Returns the result of @ref nonseekable_open().
|
||||||
*
|
*
|
||||||
* @param[in] inode VI channel character device inode struct
|
* @param[in] inode Pointer to the @ref inode structure representing the file.
|
||||||
* @param[in] file VI channel character device file struct
|
* Valid value: non-NULL.
|
||||||
|
* @param[in] file Pointer to the @ref file structure representing the opened file.
|
||||||
|
* Valid value: non-NULL.
|
||||||
*
|
*
|
||||||
* @returns 0 (success), neg. errno (failure)
|
* @retval 0 On successful opening of the VI channel.
|
||||||
|
* @retval -ERESTARTSYS If @ref vi_channel_open_ex() fails due to
|
||||||
|
* @ref mutex_lock_interruptible() being interrupted.
|
||||||
|
* @retval -ENODEV If @ref vi_channel_open_ex() fails because the channel
|
||||||
|
* driver is unavailable or the channel index is out of range.
|
||||||
|
* @retval -ENOMEM If @ref vi_channel_open_ex() fails due to memory
|
||||||
|
* allocation failure via @ref kzalloc().
|
||||||
|
* @retval -EBUSY If @ref vi_channel_open_ex() fails because the specified
|
||||||
|
* channel is already open via @ref rcu_access_pointer().
|
||||||
|
* @retval (int) If @ref vi_channel_open_ex() fails via @ref vi_capture_init()
|
||||||
|
* or if @ref nonseekable_open() fails, returns the corresponding
|
||||||
|
* error code via @ref nonseekable_open().
|
||||||
*/
|
*/
|
||||||
static int vi_channel_open(
|
static int vi_channel_open(
|
||||||
struct inode *inode,
|
struct inode *inode,
|
||||||
@@ -291,15 +380,20 @@ static int vi_channel_open(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Release a VI channel character device node; pass parameters to
|
* @brief Releases a VI channel and cleans up associated resources.
|
||||||
* @ref vi_channel_close_ex subroutine to complete release.
|
|
||||||
*
|
*
|
||||||
* This is the @a release file operation handler for a VI channel node.
|
* This function performs the following operations:
|
||||||
|
* - Retrieves the channel index from the provided @ref inode using @ref iminor().
|
||||||
|
* - Obtains the channel data from the @a file's private data.
|
||||||
|
* - Calls @ref vi_channel_close_ex() with the channel index and channel data to close the VI channel.
|
||||||
|
* - Returns 0 to indicate successful release.
|
||||||
*
|
*
|
||||||
* @param[in] inode VI channel character device inode struct
|
* @param[in] inode Pointer to the @ref inode structure representing the file.
|
||||||
* @param[in] file VI channel character device file struct
|
* Valid value: non-NULL.
|
||||||
|
* @param[in] file Pointer to the @ref file structure representing the opened file.
|
||||||
|
* Valid value: non-NULL.
|
||||||
*
|
*
|
||||||
* @returns 0
|
* @retval 0 On successful release of the VI channel.
|
||||||
*/
|
*/
|
||||||
static int vi_channel_release(
|
static int vi_channel_release(
|
||||||
struct inode *inode,
|
struct inode *inode,
|
||||||
@@ -314,8 +408,34 @@ static int vi_channel_release(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Pin/map buffers and save iova boundaries into corresponding
|
* @brief Pins buffers for a VI capture request while holding the necessary lock.
|
||||||
* memoryinfo struct.
|
*
|
||||||
|
* This function performs the following operations:
|
||||||
|
* - Retrieves the capture data from the provided channel.
|
||||||
|
* - Calculates the buffer amount and checks for multiplication overflow by calling
|
||||||
|
* @ref check_mul_overflow().
|
||||||
|
* - Computes the pointer to the capture descriptor based on the buffer amount.
|
||||||
|
* - Validates that the number of surfaces does not exceed the maximum allowed by using
|
||||||
|
* @ref BUG_ON().
|
||||||
|
* - Iterates over the ATOMP surfaces and calls @ref capture_common_pin_and_get_iova()
|
||||||
|
* for each surface to pin and obtain IOVA mappings.
|
||||||
|
* - Attempts to pin and obtain an IOVA mapping for the engine status surface by calling
|
||||||
|
* @ref capture_common_pin_and_get_iova().
|
||||||
|
* @note Cleanup of unpinned buffers is handled by @ref vi_capture_request_unpin().
|
||||||
|
*
|
||||||
|
* @param[in] chan Pointer to the @ref tegra_vi_channel structure.
|
||||||
|
* Valid value: non-NULL.
|
||||||
|
* @param[in] req Pointer to the @ref vi_capture_req structure representing
|
||||||
|
* the capture request.
|
||||||
|
* Valid value: non-NULL.
|
||||||
|
* @param[in, out] request_unpins Pointer to the @ref capture_common_unpins structure
|
||||||
|
* used for managing unpin operations.
|
||||||
|
* Valid value: non-NULL.
|
||||||
|
*
|
||||||
|
* @retval 0 On successful pinning of all buffers.
|
||||||
|
* @retval -EFAULT If @ref check_mul_overflow() detects an overflow.
|
||||||
|
* @retval (int) If @ref capture_common_pin_and_get_iova() fails while pinning ATOMP
|
||||||
|
* surfaces or the engine status surface.
|
||||||
*/
|
*/
|
||||||
static int pin_vi_capture_request_buffers_locked(struct tegra_vi_channel *chan,
|
static int pin_vi_capture_request_buffers_locked(struct tegra_vi_channel *chan,
|
||||||
struct vi_capture_req *req,
|
struct vi_capture_req *req,
|
||||||
@@ -371,20 +491,86 @@ fail:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Process an IOCTL call on a VI channel character device.
|
* @brief Handles IOCTL commands for a VI channel.
|
||||||
*
|
*
|
||||||
* Depending on the specific IOCTL, the argument (@a arg) may be a pointer to a
|
* This function performs the following operations:
|
||||||
* defined struct payload that is copied from or back to user-space. This memory
|
* - Retrieves the channel data from the @ref file's private data.
|
||||||
* is allocated and mapped from user-space and must be kept available until
|
* - Validates that the channel and capture context are initialized.
|
||||||
* after the IOCTL call completes.
|
* - Determines the command number using @ref _IOC_NR().
|
||||||
|
* - Processes the command based on its number:
|
||||||
|
* - **VI_CAPTURE_SETUP:**
|
||||||
|
* - Copies setup data from user space using @ref copy_from_user().
|
||||||
|
* - Calls @ref vi_get_nvhost_device() to obtain the NVHost device.
|
||||||
|
* - Validates the request size.
|
||||||
|
* - Checks if buffer setup is already done.
|
||||||
|
* - Creates a buffer table using @ref create_buffer_table().
|
||||||
|
* - Pins memory using @ref capture_common_pin_memory() and validates buffer size.
|
||||||
|
* - Sets up capture using @ref vi_capture_setup().
|
||||||
|
* - Handles errors by cleaning up resources using @ref capture_common_unpin_memory()
|
||||||
|
* and @ref destroy_buffer_table().
|
||||||
|
* - **VI_CAPTURE_RESET:**
|
||||||
|
* - Copies reset flags from user space using @ref copy_from_user().
|
||||||
|
* - Calls @ref vi_capture_reset() to reset the capture.
|
||||||
|
* - If successful, unpins all requests using @ref vi_capture_request_unpin().
|
||||||
|
* - **VI_CAPTURE_RELEASE:**
|
||||||
|
* - Copies release flags from user space using @ref copy_from_user().
|
||||||
|
* - Calls @ref vi_capture_release() to release the capture.
|
||||||
|
* - If successful, unpins all requests using @ref vi_capture_request_unpin(),
|
||||||
|
* unpins memory using @ref capture_common_unpin_memory(), destroys the buffer
|
||||||
|
* table using @ref destroy_buffer_table(), and frees the unpins list using vfree().
|
||||||
|
* - **VI_CAPTURE_GET_INFO:**
|
||||||
|
* - Initializes an info structure.
|
||||||
|
* - Calls @ref vi_capture_get_info() to retrieve capture information.
|
||||||
|
* - Copies info back to user space using @ref copy_to_user().
|
||||||
|
* - **VI_CAPTURE_SET_CONFIG:**
|
||||||
|
* - Copies control message from user space using @ref copy_from_user().
|
||||||
|
* - Calls @ref vi_capture_control_message_from_user() to set the configuration.
|
||||||
|
* - **VI_CAPTURE_REQUEST:**
|
||||||
|
* - Copies capture request from user space using @ref copy_from_user().
|
||||||
|
* - Validates the number of relocs, buffer index, and non-null unpins list.
|
||||||
|
* - Calls @ref mutex_lock() to lock the unpins list mutex.
|
||||||
|
* - Pins request buffers using @ref pin_vi_capture_request_buffers_locked().
|
||||||
|
* - Calls @ref mutex_unlock() to unlock the unpins list mutex.
|
||||||
|
* - Submits the capture request using @ref vi_capture_request().
|
||||||
|
* - Unpins on failure using @ref vi_capture_request_unpin().
|
||||||
|
* - **VI_CAPTURE_STATUS:**
|
||||||
|
* - Copies timeout value from user space using @ref copy_from_user().
|
||||||
|
* - Calls @ref vi_capture_status() to get the capture status.
|
||||||
|
* - **VI_CAPTURE_SET_PROGRESS_STATUS_NOTIFIER:**
|
||||||
|
* - Copies progress status request from user space using @ref copy_from_user().
|
||||||
|
* - Calls @ref vi_capture_set_progress_status_notifier() to set the notifier.
|
||||||
|
* - **VI_CAPTURE_BUFFER_REQUEST:**
|
||||||
|
* - Copies buffer request from user space using @ref copy_from_user().
|
||||||
|
* - Calls @ref capture_buffer_request() to handle the buffer request.
|
||||||
|
* - Returns the appropriate status code based on the operation outcome.
|
||||||
*
|
*
|
||||||
* This is the @a ioctl file operation handler for a VI channel node.
|
* In case of any errors during the processing of commands, the function ensures that
|
||||||
|
* resources are properly cleaned up to maintain system stability.
|
||||||
*
|
*
|
||||||
* @param[in] file VI channel character device file struct
|
* @param[in] file Pointer to the @ref file structure representing the opened file.
|
||||||
* @param[in] cmd VI channel IOCTL command
|
* Valid value: non-NULL.
|
||||||
* @param[in,out] arg IOCTL argument; numerical value or pointer
|
* @param[in] cmd IOCTL command number to be processed.
|
||||||
|
* Valid range: Defined by @ref VI_CHANNEL_IOCTLS.
|
||||||
|
* @param[in] arg Argument for the IOCTL command, typically a user space pointer.
|
||||||
|
* Valid value: depends on the command.
|
||||||
*
|
*
|
||||||
* @returns 0 (success), neg. errno (failure)
|
* @retval 0 On successful processing of the IOCTL command.
|
||||||
|
* @retval -EINVAL If the channel is invalid, context is uninitialized, or
|
||||||
|
* specific validation checks fail via @ref vi_get_nvhost_device().
|
||||||
|
* @retval -EFAULT If copying data from or to user space fails using @ref copy_from_user()
|
||||||
|
* or @ref copy_to_user(), or if memory setup fails by invoking
|
||||||
|
* @ref capture_common_pin_memory() or @ref create_buffer_table().
|
||||||
|
* @retval -ENOMEM If buffer size does not match queue depth during setup.
|
||||||
|
* @retval -EBUSY If a descriptor is still in use by RTCU via @ref vi_capture_request_unpin().
|
||||||
|
* @retval -ENOIOCTLCMD If an unknown IOCTL command is received.
|
||||||
|
* @retval (int) Specific errors returned by external functions such as
|
||||||
|
* @ref vi_capture_setup(), @ref vi_capture_reset(),
|
||||||
|
* @ref vi_capture_release(), @ref vi_capture_get_info(),
|
||||||
|
* @ref vi_capture_control_message_from_user(),
|
||||||
|
* @ref pin_vi_capture_request_buffers_locked(),
|
||||||
|
* @ref vi_capture_request(), @ref vi_capture_status(),
|
||||||
|
* @ref vi_capture_set_progress_status_notifier(),
|
||||||
|
* or @ref capture_buffer_request().
|
||||||
*/
|
*/
|
||||||
static long vi_channel_ioctl(
|
static long vi_channel_ioctl(
|
||||||
struct file *file,
|
struct file *file,
|
||||||
@@ -659,6 +845,31 @@ static const struct file_operations vi_channel_fops = {
|
|||||||
static struct class *vi_channel_class;
|
static struct class *vi_channel_class;
|
||||||
static int vi_channel_major;
|
static int vi_channel_major;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Registers a VI channel driver with a specified number of channels.
|
||||||
|
*
|
||||||
|
* This function performs the following operations:
|
||||||
|
* - Allocates memory for the channel driver structure and channel pointers using
|
||||||
|
* @ref devm_kzalloc().
|
||||||
|
* - Initializes the channel driver structure with the platform device and the number
|
||||||
|
* of channels.
|
||||||
|
* - Initializes the driver's mutex lock using @ref mutex_init().
|
||||||
|
* - Acquires the global driver lock using @ref mutex_lock().
|
||||||
|
* - Assigns the newly allocated driver structure to the global driver reference.
|
||||||
|
* - Releases the global driver lock using @ref mutex_unlock().
|
||||||
|
* - Iterates over the number of channels and creates device entries for each channel
|
||||||
|
* using @ref device_create().
|
||||||
|
*
|
||||||
|
* @param[in] ndev Pointer to the @ref platform_device structure representing the
|
||||||
|
* platform device.
|
||||||
|
* Valid value: non-NULL.
|
||||||
|
* @param[in] max_vi_channels Maximum number of VI channels to register.
|
||||||
|
* Valid range: [0 .. UINT32_MAX].
|
||||||
|
*
|
||||||
|
* @retval 0 On successful registration of the VI channel driver.
|
||||||
|
* @retval -ENOMEM If memory allocation via @ref devm_kzalloc() fails.
|
||||||
|
* @retval -EBUSY If a VI channel driver is already registered.
|
||||||
|
*/
|
||||||
int vi_channel_drv_register(
|
int vi_channel_drv_register(
|
||||||
struct platform_device *ndev,
|
struct platform_device *ndev,
|
||||||
unsigned int max_vi_channels)
|
unsigned int max_vi_channels)
|
||||||
@@ -705,6 +916,25 @@ error:
|
|||||||
}
|
}
|
||||||
EXPORT_SYMBOL(vi_channel_drv_register);
|
EXPORT_SYMBOL(vi_channel_drv_register);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Registers the operations for the VI channel driver.
|
||||||
|
*
|
||||||
|
* This function performs the following operations:
|
||||||
|
* - Retrieves the channel driver instance from the global variable.
|
||||||
|
* - Checks if the channel driver instance is initialized.
|
||||||
|
* - Acquires the channel driver lock using @ref mutex_lock().
|
||||||
|
* - If the operations table in the channel driver is not already set, assigns the provided
|
||||||
|
* operations to it.
|
||||||
|
* - If the operations table is already registered, logs a debug message using @ref dev_dbg().
|
||||||
|
* - Releases the channel driver lock using @ref mutex_unlock().
|
||||||
|
*
|
||||||
|
* @param[in] ops Pointer to the @ref vi_channel_drv_ops structure containing
|
||||||
|
* the operations to register.
|
||||||
|
* Valid value: non-NULL.
|
||||||
|
*
|
||||||
|
* @retval 0 On successful registration of the operations.
|
||||||
|
* @retval -EPROBE_DEFER If the channel driver is NULL.
|
||||||
|
*/
|
||||||
int vi_channel_drv_fops_register(
|
int vi_channel_drv_fops_register(
|
||||||
const struct vi_channel_drv_ops *ops)
|
const struct vi_channel_drv_ops *ops)
|
||||||
{
|
{
|
||||||
@@ -731,6 +961,21 @@ error:
|
|||||||
}
|
}
|
||||||
EXPORT_SYMBOL(vi_channel_drv_fops_register);
|
EXPORT_SYMBOL(vi_channel_drv_fops_register);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Unregisters a VI channel driver and releases associated resources.
|
||||||
|
*
|
||||||
|
* This function performs the following operations:
|
||||||
|
* - Acquires the global driver lock using @ref mutex_lock().
|
||||||
|
* - Retrieves the current channel driver instance.
|
||||||
|
* - Clears the global driver reference.
|
||||||
|
* - Releases the global driver lock using @ref mutex_unlock().
|
||||||
|
* - Validates the major number.
|
||||||
|
* - Iterates over the number of channels and destroys each device using @ref device_destroy().
|
||||||
|
* - Frees the memory allocated for the channel driver structure using @ref devm_kfree().
|
||||||
|
*
|
||||||
|
* @param[in] dev Pointer to the @ref device structure representing the device.
|
||||||
|
* Valid value: non-NULL.
|
||||||
|
*/
|
||||||
void vi_channel_drv_unregister(
|
void vi_channel_drv_unregister(
|
||||||
struct device *dev)
|
struct device *dev)
|
||||||
{
|
{
|
||||||
@@ -760,9 +1005,19 @@ void vi_channel_drv_unregister(
|
|||||||
EXPORT_SYMBOL(vi_channel_drv_unregister);
|
EXPORT_SYMBOL(vi_channel_drv_unregister);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Initialize the VI channel driver device (major).
|
* @brief Initializes the VI channel driver by creating the device class and registering
|
||||||
|
* character devices.
|
||||||
*
|
*
|
||||||
* @returns 0 (success), PTR_ERR or neg. VI channel major no. (failure)
|
* This function performs the following operations:
|
||||||
|
* - Creates a device class for VI channels using @ref class_create().
|
||||||
|
* - Registers a character device with dynamic major number allocation using
|
||||||
|
* @ref register_chrdev().
|
||||||
|
* - If character device registration fails, destroys the created device class
|
||||||
|
* using @ref class_destroy().
|
||||||
|
*
|
||||||
|
* @retval 0 On successful initialization and registration.
|
||||||
|
* @retval -ENOMEM If device class creation fails due to insufficient memory.
|
||||||
|
* @retval -EINVAL If character device registration fails.
|
||||||
*/
|
*/
|
||||||
int vi_channel_drv_init(void)
|
int vi_channel_drv_init(void)
|
||||||
{
|
{
|
||||||
@@ -785,7 +1040,11 @@ int vi_channel_drv_init(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief De-initialize the VI channel driver device (major).
|
* @brief Unregisters the VI channel driver (major) and releases associated resources.
|
||||||
|
*
|
||||||
|
* This function performs the following operations:
|
||||||
|
* - Unregisters the character device for the VI channel using @ref unregister_chrdev().
|
||||||
|
* - Destroys the VI channel device class using @ref class_destroy().
|
||||||
*/
|
*/
|
||||||
void vi_channel_drv_exit(void)
|
void vi_channel_drv_exit(void)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -143,12 +143,30 @@ struct tegra_capture_vi_data {
|
|||||||
/**
|
/**
|
||||||
* @brief Initialize a VI syncpoint and get its GoS backing.
|
* @brief Initialize a VI syncpoint and get its GoS backing.
|
||||||
*
|
*
|
||||||
* @param[in] chan VI channel context
|
* This function performs the following operations:
|
||||||
* @param[in] name Syncpoint name
|
* - Clears the syncpoint handle if enable is false.
|
||||||
* @param[in] enable Whether to initialize or just clear @a sp
|
* - Allocates a syncpoint with the given name using
|
||||||
* @param[out] sp Syncpoint handle
|
* @ref struct syncpoint_info::ops::alloc_syncpt().
|
||||||
|
* - Gets the syncpoint handle using @ref host1x_syncpt_get_by_id_noref().
|
||||||
|
* - Reads the syncpoint value using @ref host1x_syncpt_read().
|
||||||
|
* - Gets the GoS backing for the syncpoint using
|
||||||
|
* @ref struct syncpoint_info::ops::get_gos_backing().
|
||||||
|
* - In case of failure during any step, releases the allocated syncpoint and clears
|
||||||
|
* the handle using @ref struct syncpoint_info::ops::release_syncpt().
|
||||||
*
|
*
|
||||||
* @returns 0 (success), neg. errno (failure)
|
* @param[in] chan VI channel context.
|
||||||
|
* Valid value: non-NULL
|
||||||
|
* @param[in] name Syncpoint name.
|
||||||
|
* Valid value: non-NULL
|
||||||
|
* @param[in] enable Whether to initialize or just clear the syncpoint.
|
||||||
|
* Valid range: [true, false]
|
||||||
|
* @param[out] sp Syncpoint handle to initialize.
|
||||||
|
* Valid value: non-NULL
|
||||||
|
*
|
||||||
|
* @retval 0 Operation completed successfully.
|
||||||
|
* @retval -EINVAL Error returned from @ref host1x_syncpt_get_by_id_noref().
|
||||||
|
* @retval (int) Error codes returned from @ref struct syncpoint_info::ops::alloc_syncpt() or
|
||||||
|
* @ref struct syncpoint_info::ops::get_syncpt_gos_backing().
|
||||||
*/
|
*/
|
||||||
static int vi_capture_setup_syncpt(
|
static int vi_capture_setup_syncpt(
|
||||||
struct tegra_vi_channel *chan,
|
struct tegra_vi_channel *chan,
|
||||||
@@ -200,7 +218,12 @@ cleanup:
|
|||||||
/**
|
/**
|
||||||
* @brief Fast forward a VI syncpoint to its threshold value.
|
* @brief Fast forward a VI syncpoint to its threshold value.
|
||||||
*
|
*
|
||||||
* @param[in] chan VI channel context
|
* This function performs the following operation:
|
||||||
|
* - If progress syncpoint exists, calls @ref struct syncpoint_info::ops::fast_forward_syncpt() to advance the
|
||||||
|
* syncpoint to its threshold value.
|
||||||
|
*
|
||||||
|
* @param[in] chan VI channel context.
|
||||||
|
* Valid value: non-NULL.
|
||||||
*/
|
*/
|
||||||
static void vi_capture_fastforward_syncpt(
|
static void vi_capture_fastforward_syncpt(
|
||||||
struct tegra_vi_channel *chan)
|
struct tegra_vi_channel *chan)
|
||||||
@@ -216,8 +239,14 @@ static void vi_capture_fastforward_syncpt(
|
|||||||
/**
|
/**
|
||||||
* @brief Release a VI syncpoint and clear its handle.
|
* @brief Release a VI syncpoint and clear its handle.
|
||||||
*
|
*
|
||||||
* @param[in] chan VI channel context
|
* This function performs the following operations:
|
||||||
* @param[out] sp Syncpoint handle
|
* - If syncpoint ID exists, releases it using @ref struct syncpoint_info::ops::release_syncpt().
|
||||||
|
* - Clears the syncpoint handle structure.
|
||||||
|
*
|
||||||
|
* @param[in] chan VI channel context.
|
||||||
|
* Valid value: non-NULL.
|
||||||
|
* @param[out] sp Syncpoint handle to release.
|
||||||
|
* Valid value: non-NULL.
|
||||||
*/
|
*/
|
||||||
static void vi_capture_release_syncpt(
|
static void vi_capture_release_syncpt(
|
||||||
struct tegra_vi_channel *chan,
|
struct tegra_vi_channel *chan,
|
||||||
@@ -230,10 +259,15 @@ static void vi_capture_release_syncpt(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Release the VI channel progress, embedded data and line timer
|
* @brief Release the VI channel progress, embedded data and line timer syncpoints.
|
||||||
* syncpoints.
|
|
||||||
*
|
*
|
||||||
* @param[in] chan VI channel context
|
* This function performs the following operations:
|
||||||
|
* - Releases the progress syncpoint using @ref vi_capture_release_syncpt()
|
||||||
|
* - Releases the embedded data syncpoint using @ref vi_capture_release_syncpt()
|
||||||
|
* - Releases the line timer syncpoint using @ref vi_capture_release_syncpt()
|
||||||
|
*
|
||||||
|
* @param[in] chan VI channel context
|
||||||
|
* Valid value: non-NULL
|
||||||
*/
|
*/
|
||||||
static void vi_capture_release_syncpts(
|
static void vi_capture_release_syncpts(
|
||||||
struct tegra_vi_channel *chan)
|
struct tegra_vi_channel *chan)
|
||||||
@@ -246,14 +280,22 @@ static void vi_capture_release_syncpts(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Set up the VI channel progress, embedded data and line timer
|
* @brief Set up the VI channel progress, embedded data and line timer syncpoints.
|
||||||
* syncpoints.
|
|
||||||
*
|
*
|
||||||
* @param[in] chan VI channel context
|
* This function performs the following operations:
|
||||||
* @param[in] flags Bitmask for channel flags, see
|
* - Gets the GoS table using @ref struct tegra_vi_channel::ops::get_gos_table().
|
||||||
* @ref CAPTURE_CHANNEL_FLAGS
|
* - Sets up the progress syncpoint using @ref vi_capture_setup_syncpt().
|
||||||
|
* - Sets up the embedded data syncpoint if enabled using @ref vi_capture_setup_syncpt().
|
||||||
|
* - Sets up the line timer syncpoint if enabled using @ref vi_capture_setup_syncpt().
|
||||||
|
* - In case of failure, releases all allocated syncpoints using @ref vi_capture_release_syncpts().
|
||||||
*
|
*
|
||||||
* @returns 0 (success), neg. errno (failure)
|
* @param[in] chan VI channel context.
|
||||||
|
* Valid value: non-NULL
|
||||||
|
* @param[in] flags Bitmask for channel flags.
|
||||||
|
* Valid range: @ref CAPTURE_CHANNEL_FLAGS
|
||||||
|
*
|
||||||
|
* @retval 0 Operation completed successfully.
|
||||||
|
* @retval -EINVAL Error returned from @ref vi_capture_setup_syncpt().
|
||||||
*/
|
*/
|
||||||
static int vi_capture_setup_syncpts(
|
static int vi_capture_setup_syncpts(
|
||||||
struct tegra_vi_channel *chan,
|
struct tegra_vi_channel *chan,
|
||||||
@@ -293,11 +335,19 @@ fail:
|
|||||||
/**
|
/**
|
||||||
* @brief Read the value of a VI channel syncpoint.
|
* @brief Read the value of a VI channel syncpoint.
|
||||||
*
|
*
|
||||||
* @param[in] chan VI channel context
|
* This function performs the following operation:
|
||||||
* @param[in] sp Syncpoint handle
|
* - If syncpoint ID exists, gets the syncpoint handle using @ref host1x_syncpt_get_by_id_noref().
|
||||||
* @param[out] val Syncpoint value
|
* - If handle is valid, reads its value using @ref host1x_syncpt_read().
|
||||||
*
|
*
|
||||||
* @returns 0 (success), neg. errno (failure)
|
* @param[in] chan VI channel context.
|
||||||
|
* Valid value: non-NULL
|
||||||
|
* @param[in] sp Syncpoint handle.
|
||||||
|
* Valid value: non-NULL
|
||||||
|
* @param[out] val Syncpoint value.
|
||||||
|
* Valid value: non-NULL
|
||||||
|
*
|
||||||
|
* @retval 0 Operation completed successfully.
|
||||||
|
* @retval -EINVAL Error returned from @ref host1x_syncpt_get_by_id_noref().
|
||||||
*/
|
*/
|
||||||
static int vi_capture_read_syncpt(
|
static int vi_capture_read_syncpt(
|
||||||
struct tegra_vi_channel *chan,
|
struct tegra_vi_channel *chan,
|
||||||
@@ -323,10 +373,20 @@ static int vi_capture_read_syncpt(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief VI channel callback function for @em capture IVC messages.
|
* @brief VI channel callback function for capture IVC messages.
|
||||||
*
|
*
|
||||||
* @param[in] ivc_resp IVC @ref CAPTURE_MSG from RCE
|
* This function performs the following operations:
|
||||||
* @param[in] pcontext VI channel capture context
|
* - Validates input parameters.
|
||||||
|
* - For CAPTURE_STATUS_IND messages:
|
||||||
|
* - Unpins memory if pinned using @ref vi_capture_request_unpin().
|
||||||
|
* - Synchronizes DMA memory using @ref dma_sync_single_range_for_cpu().
|
||||||
|
* - Updates progress status using @ref capture_common_set_progress_status() if enabled.
|
||||||
|
* - Otherwise completes the capture response using @ref complete().
|
||||||
|
*
|
||||||
|
* @param[in] ivc_resp IVC @ref CAPTURE_MSG from RCE.
|
||||||
|
* Valid value: non-NULL.
|
||||||
|
* @param[in] pcontext VI channel capture context.
|
||||||
|
* Valid value: non-NULL.
|
||||||
*/
|
*/
|
||||||
static void vi_capture_ivc_status_callback(
|
static void vi_capture_ivc_status_callback(
|
||||||
const void *ivc_resp,
|
const void *ivc_resp,
|
||||||
@@ -382,15 +442,28 @@ static void vi_capture_ivc_status_callback(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Send a @em capture-control IVC message to RCE on a VI channel, and
|
* @brief Send a capture-control IVC message to RCE on a VI channel.
|
||||||
* block w/ timeout, waiting for the RCE response.
|
|
||||||
*
|
*
|
||||||
* @param[in] chan VI channel context
|
* This function performs the following operations:
|
||||||
* @param[in] msg IVC message payload
|
* - Locks the control message mutex using @ref mutex_lock().
|
||||||
* @param[in] size Size of @a msg [byte]
|
* - Submits the capture control message using @ref tegra_capture_ivc_control_submit().
|
||||||
* @param[in] resp_id IVC message identifier, see @CAPTURE_MSG_IDS
|
* - Waits for the response with timeout using @ref wait_for_completion_timeout().
|
||||||
|
* - Validates the response header matches the request using @ref memcmp().
|
||||||
|
* - Unlocks the control message mutex using @ref mutex_unlock().
|
||||||
*
|
*
|
||||||
* @returns 0 (success), neg. errno (failure)
|
* @param[in] chan VI channel context.
|
||||||
|
* Valid value: non-NULL.
|
||||||
|
* @param[in] msg IVC message payload.
|
||||||
|
* Valid value: non-NULL
|
||||||
|
* @param[in] size Size of message in bytes.
|
||||||
|
* Valid value: non-zero.
|
||||||
|
* @param[in] resp_id IVC message identifier.
|
||||||
|
* Valid range: @ref CAPTURE_MSG_IDS.
|
||||||
|
*
|
||||||
|
* @retval 0 Operation completed successfully.
|
||||||
|
* @retval -EINVAL Response header validation failed.
|
||||||
|
* @retval -ETIMEDOUT Response timed out.
|
||||||
|
* @retval (int) Error codes returned from @ref tegra_capture_ivc_control_submit().
|
||||||
*/
|
*/
|
||||||
static int vi_capture_ivc_send_control(
|
static int vi_capture_ivc_send_control(
|
||||||
struct tegra_vi_channel *chan,
|
struct tegra_vi_channel *chan,
|
||||||
@@ -443,11 +516,18 @@ fail:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief VI channel callback function for @em capture-control IVC messages,
|
* @brief VI channel callback function for capture-control IVC messages.
|
||||||
* this unblocks the channel's @em capture-control completion.
|
|
||||||
*
|
*
|
||||||
* @param[in] ivc_resp IVC @ref CAPTURE_CONTROL_MSG from RCE
|
* This function performs the following operations:
|
||||||
* @param[in] pcontext VI channel capture context
|
* - Validates input parameters.
|
||||||
|
* - For supported control message responses:
|
||||||
|
* - Copies the response message to the channel's control response buffer using @ref memcpy().
|
||||||
|
* - Completes the control response wait using @ref complete().
|
||||||
|
*
|
||||||
|
* @param[in] ivc_resp IVC @ref CAPTURE_CONTROL_MSG from RCE.
|
||||||
|
* Valid value: non-NULL.
|
||||||
|
* @param[in] pcontext VI channel capture context.
|
||||||
|
* Valid value: non-NULL.
|
||||||
*/
|
*/
|
||||||
static void vi_capture_ivc_control_callback(
|
static void vi_capture_ivc_control_callback(
|
||||||
const void *ivc_resp,
|
const void *ivc_resp,
|
||||||
@@ -499,6 +579,27 @@ static void vi_capture_ivc_control_callback(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Initialize a VI capture channel.
|
||||||
|
*
|
||||||
|
* This function performs the following operations:
|
||||||
|
* - Finds and validates the RTCPU device node using @ref of_find_node_by_path().
|
||||||
|
* - Checks device availability using @ref of_device_is_available().
|
||||||
|
* - Gets platform device using @ref of_find_device_by_node().
|
||||||
|
* - Allocates and initializes the VI capture channel context using @ref kzalloc().
|
||||||
|
* - Initializes completion objects using @ref init_completion().
|
||||||
|
* - Initializes mutex locks using @ref mutex_init().
|
||||||
|
* - Sets up initial channel state.
|
||||||
|
*
|
||||||
|
* @param[in] chan VI channel context.
|
||||||
|
* Valid value: non-NULL.
|
||||||
|
* @param[in] is_mem_pinned Whether memory is pinned.
|
||||||
|
* Valid range: [true, false].
|
||||||
|
*
|
||||||
|
* @retval 0 Operation completed successfully.
|
||||||
|
* @retval -ENODEV RTCPU device node not found or invalid.
|
||||||
|
* @retval -ENOMEM Failed to allocate capture channel context from @ref kzalloc().
|
||||||
|
*/
|
||||||
int vi_capture_init(
|
int vi_capture_init(
|
||||||
struct tegra_vi_channel *chan,
|
struct tegra_vi_channel *chan,
|
||||||
bool is_mem_pinned)
|
bool is_mem_pinned)
|
||||||
@@ -552,6 +653,22 @@ int vi_capture_init(
|
|||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(vi_capture_init);
|
EXPORT_SYMBOL_GPL(vi_capture_init);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Shutdown and cleanup a VI capture channel.
|
||||||
|
*
|
||||||
|
* This function performs the following operations:
|
||||||
|
* - Validates input parameters.
|
||||||
|
* - Resets the channel using @ref vi_capture_reset() if active.
|
||||||
|
* - Releases CSI stream using @ref csi_stream_release() if active.
|
||||||
|
* - Releases the channel using @ref vi_capture_release().
|
||||||
|
* - Unpins memory using @ref vi_capture_request_unpin() if memory was pinned.
|
||||||
|
* - Unpins capture requests using @ref capture_common_unpin_memory().
|
||||||
|
* - Destroys buffer table using @ref destroy_buffer_table() if exists.
|
||||||
|
* - Frees allocated resources using @ref kfree() and @ref vfree().
|
||||||
|
*
|
||||||
|
* @param[in] chan VI channel context.
|
||||||
|
* Valid value: non-NULL.
|
||||||
|
*/
|
||||||
void vi_capture_shutdown(
|
void vi_capture_shutdown(
|
||||||
struct tegra_vi_channel *chan)
|
struct tegra_vi_channel *chan)
|
||||||
{
|
{
|
||||||
@@ -601,6 +718,22 @@ void vi_capture_shutdown(
|
|||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(vi_capture_shutdown);
|
EXPORT_SYMBOL_GPL(vi_capture_shutdown);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get the nvhost device for a VI channel based on CSI stream ID.
|
||||||
|
*
|
||||||
|
* This function performs the following operations:
|
||||||
|
* - Retrieves the platform driver data for the channel's capture device
|
||||||
|
* using @ref platform_get_drvdata().
|
||||||
|
* - Gets the VI instance from the mapping table using CSI stream ID.
|
||||||
|
* - Validates the VI instance ID.
|
||||||
|
* - Applies array bounds check using @ref array_index_nospec().
|
||||||
|
* - Sets the channel's device and nvhost device pointers from platform device.
|
||||||
|
*
|
||||||
|
* @param[in] chan VI channel context.
|
||||||
|
* Valid value: non-NULL.
|
||||||
|
* @param[in] setup VI capture setup parameters.
|
||||||
|
* Valid value: non-NULL.
|
||||||
|
*/
|
||||||
void vi_get_nvhost_device(
|
void vi_get_nvhost_device(
|
||||||
struct tegra_vi_channel *chan,
|
struct tegra_vi_channel *chan,
|
||||||
struct vi_capture_setup *setup)
|
struct vi_capture_setup *setup)
|
||||||
@@ -630,6 +763,23 @@ void vi_get_nvhost_device(
|
|||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(vi_get_nvhost_device);
|
EXPORT_SYMBOL_GPL(vi_get_nvhost_device);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get the nvhost device for a given CSI stream ID.
|
||||||
|
*
|
||||||
|
* This function performs the following operations:
|
||||||
|
* - Retrieves the platform driver data for the channel's capture device
|
||||||
|
* using @ref platform_get_drvdata().
|
||||||
|
* - Gets the VI instance ID from the mapping table using CSI stream ID.
|
||||||
|
* - Returns the corresponding platform device.
|
||||||
|
*
|
||||||
|
* @param[in] pdev Platform device pointer.
|
||||||
|
* Valid value: non-NULL.
|
||||||
|
* @param[in] csi_stream_id CSI stream identifier.
|
||||||
|
* Valid range: [0, MAX_NVCSI_STREAM_IDS - 1].
|
||||||
|
*
|
||||||
|
* @retval device* Pointer to the nvhost device on success.
|
||||||
|
* @retval NULL If CSI stream ID is invalid.
|
||||||
|
*/
|
||||||
struct device *vi_csi_stream_to_nvhost_device(
|
struct device *vi_csi_stream_to_nvhost_device(
|
||||||
struct platform_device *pdev,
|
struct platform_device *pdev,
|
||||||
uint32_t csi_stream_id)
|
uint32_t csi_stream_id)
|
||||||
@@ -647,6 +797,44 @@ struct device *vi_csi_stream_to_nvhost_device(
|
|||||||
}
|
}
|
||||||
EXPORT_SYMBOL(vi_csi_stream_to_nvhost_device);
|
EXPORT_SYMBOL(vi_csi_stream_to_nvhost_device);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Set up a VI capture channel.
|
||||||
|
*
|
||||||
|
* This function performs the following operations:
|
||||||
|
* - Validates input parameters and channel state.
|
||||||
|
* - Retrieves the platform driver data for the channel's capture device
|
||||||
|
* using @ref platform_get_drvdata().
|
||||||
|
* - Gets the VI instance from mapping table using CSI stream ID.
|
||||||
|
* - If the channel's device is NULL, gets the nvhost device for the channel
|
||||||
|
* using @ref vi_get_nvhost_device().
|
||||||
|
* - Validates setup parameters and capture channel ID.
|
||||||
|
* - Copies setup parameters to channel context.
|
||||||
|
* - Sets up channel syncpoints using @ref vi_capture_setup_syncpts().
|
||||||
|
* - Registers control callback using @ref tegra_capture_ivc_register_control_cb().
|
||||||
|
* - Allocates memory for memoryinfo ring buffer using @ref dma_alloc_coherent().
|
||||||
|
* - Allocates memory for unpins list using @ref vzalloc().
|
||||||
|
* - If @ref HAVE_VI_GOS_TABLES is defined, copies GoS tables to config.
|
||||||
|
* - Sends channel setup request using @ref vi_capture_ivc_send_control().
|
||||||
|
* - Updates channel state with response info.
|
||||||
|
* - Updates control callback with capture channel ID using
|
||||||
|
* @ref tegra_capture_ivc_notify_capture_cb().
|
||||||
|
* - Registers capture callback using @ref tegra_capture_ivc_register_capture_cb().
|
||||||
|
* - Updates global channels array.
|
||||||
|
* - In case of failure, releases allocated resources using @ref vfree(),
|
||||||
|
* @ref dma_free_coherent(), @ref tegra_capture_ivc_unregister_control_cb(),
|
||||||
|
* and @ref vi_capture_release_syncpts().
|
||||||
|
*
|
||||||
|
* @param[in] chan VI channel context.
|
||||||
|
* Valid value: non-NULL.
|
||||||
|
* @param[in] setup VI capture setup parameters.
|
||||||
|
* Valid value: non-NULL.
|
||||||
|
*
|
||||||
|
* @retval 0 Operation completed successfully.
|
||||||
|
* @retval -EINVAL Invalid input parameters or response.
|
||||||
|
* @retval -EEXIST Channel already set up.
|
||||||
|
* @retval -ENODEV Capture channel is not initialized.
|
||||||
|
* @retval (int) Error codes from helper functions.
|
||||||
|
*/
|
||||||
int vi_capture_setup(
|
int vi_capture_setup(
|
||||||
struct tegra_vi_channel *chan,
|
struct tegra_vi_channel *chan,
|
||||||
struct vi_capture_setup *setup)
|
struct vi_capture_setup *setup)
|
||||||
@@ -908,6 +1096,20 @@ syncpt_fail:
|
|||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(vi_capture_setup);
|
EXPORT_SYMBOL_GPL(vi_capture_setup);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get a VI channel handle for a given CSI stream and virtual channel ID.
|
||||||
|
*
|
||||||
|
* This function performs the following operation:
|
||||||
|
* - Returns the VI channel handle from the global channels array if valid IDs.
|
||||||
|
*
|
||||||
|
* @param[in] stream_id CSI stream identifier.
|
||||||
|
* Valid range: [0, MAX_NVCSI_STREAM_IDS - 1].
|
||||||
|
* @param[in] virtual_channel_id Virtual channel identifier.
|
||||||
|
* Valid range: [0, MAX_VIRTUAL_CHANNEL_PER_STREAM - 1].
|
||||||
|
*
|
||||||
|
* @retval tegra_vi_channel* VI channel handle if found.
|
||||||
|
* @retval NULL If IDs are invalid or no channel exists.
|
||||||
|
*/
|
||||||
struct tegra_vi_channel *get_tegra_vi_channel(
|
struct tegra_vi_channel *get_tegra_vi_channel(
|
||||||
unsigned int stream_id,
|
unsigned int stream_id,
|
||||||
unsigned int virtual_channel_id)
|
unsigned int virtual_channel_id)
|
||||||
@@ -918,6 +1120,30 @@ struct tegra_vi_channel *get_tegra_vi_channel(
|
|||||||
return channels[stream_id][virtual_channel_id];
|
return channels[stream_id][virtual_channel_id];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Reset a VI capture channel.
|
||||||
|
*
|
||||||
|
* This function performs the following operations:
|
||||||
|
* - Validates input parameters and channel state.
|
||||||
|
* - Locks the reset lock using @ref mutex_lock().
|
||||||
|
* - If @ref CAPTURE_RESET_BARRIER_IND is defined, sends reset barrier
|
||||||
|
* indication using @ref tegra_capture_ivc_capture_submit().
|
||||||
|
* - Sends channel reset request using @ref vi_capture_ivc_send_control().
|
||||||
|
* - If @ref CAPTURE_RESET_BARRIER_IND is defined, checks reset response.
|
||||||
|
* - Fast forwards syncpoints using @ref vi_capture_fastforward_syncpt().
|
||||||
|
* - Unlocks the reset lock using @ref mutex_unlock().
|
||||||
|
*
|
||||||
|
* @param[in] chan VI channel context.
|
||||||
|
* Valid value: non-NULL.
|
||||||
|
* @param[in] reset_flags Channel reset flags.
|
||||||
|
* Valid range: @ref CAPTURE_CHANNEL_RESET_FLAGS.
|
||||||
|
*
|
||||||
|
* @retval 0 Operation completed successfully.
|
||||||
|
* @retval -ENODEV Channel not initialized.
|
||||||
|
* @retval -EAGAIN Reset timed out.
|
||||||
|
* @retval -EINVAL Invalid response from RCE.
|
||||||
|
* @retval (int) Error codes from helper functions.
|
||||||
|
*/
|
||||||
int vi_capture_reset(
|
int vi_capture_reset(
|
||||||
struct tegra_vi_channel *chan,
|
struct tegra_vi_channel *chan,
|
||||||
uint32_t reset_flags)
|
uint32_t reset_flags)
|
||||||
@@ -992,6 +1218,33 @@ submit_fail:
|
|||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(vi_capture_reset);
|
EXPORT_SYMBOL_GPL(vi_capture_reset);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Release a VI capture channel.
|
||||||
|
*
|
||||||
|
* This function performs the following operations:
|
||||||
|
* - Validates input parameters and channel state.
|
||||||
|
* - Sends channel release request using @ref vi_capture_ivc_send_control().
|
||||||
|
* - If returns error, reboots the RTCPU using @ref tegra_camrtc_reboot().
|
||||||
|
* - Frees memory info ringbuffer using @ref dma_free_coherent() if allocated.
|
||||||
|
* - Unregisters callbacks using @ref tegra_capture_ivc_unregister_capture_cb()
|
||||||
|
* and @ref tegra_capture_ivc_unregister_control_cb().
|
||||||
|
* - Completes any pending capture responses using @ref complete().
|
||||||
|
* - Releases syncpoints using @ref vi_capture_release_syncpts().
|
||||||
|
* - Clears channel state and removes from global channels array.
|
||||||
|
* - Releases progress status notifier using @ref capture_common_release_progress_status_notifier()
|
||||||
|
* if set.
|
||||||
|
*
|
||||||
|
* @param[in] chan VI channel context.
|
||||||
|
* Valid value: non-NULL.
|
||||||
|
* @param[in] reset_flags Channel reset flags.
|
||||||
|
* Valid range: @ref CAPTURE_CHANNEL_RESET_FLAGS.
|
||||||
|
*
|
||||||
|
* @retval 0 Operation completed successfully.
|
||||||
|
* @retval -ENODEV Channel not initialized.
|
||||||
|
* @retval -EIO @ref vi_capture_ivc_send_control() failed or response is not CAPTURE_OK.
|
||||||
|
* @retval (int) Error codes from @ref tegra_capture_ivc_unregister_capture_cb()
|
||||||
|
* and @ref tegra_capture_ivc_unregister_control_cb().
|
||||||
|
*/
|
||||||
int vi_capture_release(
|
int vi_capture_release(
|
||||||
struct tegra_vi_channel *chan,
|
struct tegra_vi_channel *chan,
|
||||||
uint32_t reset_flags)
|
uint32_t reset_flags)
|
||||||
@@ -1094,6 +1347,30 @@ int vi_capture_release(
|
|||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(vi_capture_release);
|
EXPORT_SYMBOL_GPL(vi_capture_release);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Send a control message to RCE through IVC for a VI channel.
|
||||||
|
*
|
||||||
|
* This function performs the following operations:
|
||||||
|
* - Sets the channel ID in the message header.
|
||||||
|
* - Determines the expected response message ID based on request type.
|
||||||
|
* - For PHY stream open requests, checks channel stream is not already opened
|
||||||
|
* and copies stream ID and CSI port to channel context.
|
||||||
|
* - For PHY stream close requests, checks channel stream is opened.
|
||||||
|
* - For TPG start requests, copies virtual channel ID to channel context.
|
||||||
|
* - Sends the control message using @ref vi_capture_ivc_send_control().
|
||||||
|
* - Updates stream state for PHY stream operations.
|
||||||
|
*
|
||||||
|
* @param[in] chan VI channel context.
|
||||||
|
* Valid value: non-NULL.
|
||||||
|
* @param[in] msg_cpy Control message to send.
|
||||||
|
* Valid value: non-NULL.
|
||||||
|
* @param[in] size Size of message in bytes.
|
||||||
|
* Valid value: non-zero.
|
||||||
|
*
|
||||||
|
* @retval 0 Operation completed successfully.
|
||||||
|
* @retval -EINVAL Invalid message ID or response ID.
|
||||||
|
* @retval (int) Error codes from @ref vi_capture_ivc_send_control().
|
||||||
|
*/
|
||||||
static int vi_capture_control_send_message(
|
static int vi_capture_control_send_message(
|
||||||
struct tegra_vi_channel *chan,
|
struct tegra_vi_channel *chan,
|
||||||
struct CAPTURE_CONTROL_MSG *msg_cpy,
|
struct CAPTURE_CONTROL_MSG *msg_cpy,
|
||||||
@@ -1196,9 +1473,17 @@ static int vi_capture_control_send_message(
|
|||||||
/**
|
/**
|
||||||
* @brief Disable the VI channel's NVCSI TPG stream in RCE.
|
* @brief Disable the VI channel's NVCSI TPG stream in RCE.
|
||||||
*
|
*
|
||||||
* @param[in] chan VI channel context
|
* This function performs the following operations:
|
||||||
|
* - Prepares TPG stop request message.
|
||||||
|
* - Sends request to RCE using @ref vi_capture_ivc_send_control().
|
||||||
|
* - Validates response from RCE.
|
||||||
*
|
*
|
||||||
* @returns 0 (success), neg. errno (failure)
|
* @param[in] chan VI channel context.
|
||||||
|
* Valid value: non-NULL.
|
||||||
|
*
|
||||||
|
* @retval 0 Operation completed successfully.
|
||||||
|
* @retval -EINVAL Invalid response from RCE.
|
||||||
|
* @retval (int) Error codes from @ref vi_capture_ivc_send_control().
|
||||||
*/
|
*/
|
||||||
static int csi_stream_tpg_disable(
|
static int csi_stream_tpg_disable(
|
||||||
struct tegra_vi_channel *chan)
|
struct tegra_vi_channel *chan)
|
||||||
@@ -1226,11 +1511,19 @@ static int csi_stream_tpg_disable(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Disable the VI channel's NVCSI stream in RCE.
|
* @brief Close the VI channel's NVCSI stream in RCE.
|
||||||
*
|
*
|
||||||
* @param[in] chan VI channel context
|
* This function performs the following operations:
|
||||||
|
* - Prepares stream close request message.
|
||||||
|
* - Sends request to RCE using @ref vi_capture_control_send_message().
|
||||||
|
* - Validates response from RCE.
|
||||||
*
|
*
|
||||||
* @returns 0 (success), neg. errno (failure)
|
* @param[in] chan VI channel context.
|
||||||
|
* Valid value: non-NULL.
|
||||||
|
*
|
||||||
|
* @retval 0 Operation completed successfully.
|
||||||
|
* @retval -EINVAL Invalid response from RCE.
|
||||||
|
* @retval (int) Error codes from @ref vi_capture_control_send_message().
|
||||||
*/
|
*/
|
||||||
static int csi_stream_close(
|
static int csi_stream_close(
|
||||||
struct tegra_vi_channel *chan)
|
struct tegra_vi_channel *chan)
|
||||||
@@ -1256,6 +1549,20 @@ static int csi_stream_close(
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Release the VI channel's NVCSI stream resources.
|
||||||
|
*
|
||||||
|
* This function performs the following operations:
|
||||||
|
* - If stream ID is invalid, returns success.
|
||||||
|
* - If TPG virtual channel is active, disables it using @ref csi_stream_tpg_disable().
|
||||||
|
* - If stream is open, closes it using @ref csi_stream_close().
|
||||||
|
*
|
||||||
|
* @param[in] chan VI channel context.
|
||||||
|
* Valid value: non-NULL.
|
||||||
|
*
|
||||||
|
* @retval 0 Operation completed successfully.
|
||||||
|
* @retval (int) Error codes from @ref csi_stream_tpg_disable() or @ref csi_stream_close().
|
||||||
|
*/
|
||||||
int csi_stream_release(
|
int csi_stream_release(
|
||||||
struct tegra_vi_channel *chan)
|
struct tegra_vi_channel *chan)
|
||||||
{
|
{
|
||||||
@@ -1287,6 +1594,27 @@ int csi_stream_release(
|
|||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Process a VI capture control message from userspace.
|
||||||
|
*
|
||||||
|
* This function performs the following operations:
|
||||||
|
* - Validates input parameters.
|
||||||
|
* - Copies message from userspace using @ref kzalloc() and @ref copy_from_user().
|
||||||
|
* - Sends control message using @ref vi_capture_control_send_message().
|
||||||
|
* - Copies response back to userspace using @ref copy_to_user().
|
||||||
|
*
|
||||||
|
* @param[in] chan VI channel context.
|
||||||
|
* Valid value: non-NULL.
|
||||||
|
* @param[in] msg Control message from userspace.
|
||||||
|
* Valid value: non-NULL with valid pointers.
|
||||||
|
*
|
||||||
|
* @retval 0 Operation completed successfully.
|
||||||
|
* @retval -ENODEV Channel not initialized.
|
||||||
|
* @retval -EINVAL Invalid message parameters.
|
||||||
|
* @retval -ENOMEM Failed to allocate message copy buffer from @ref kzalloc().
|
||||||
|
* @retval (int) Error codes from @ref vi_capture_control_send_message(), @ref copy_to_user(),
|
||||||
|
* or @ref copy_from_user().
|
||||||
|
*/
|
||||||
int vi_capture_control_message_from_user(
|
int vi_capture_control_message_from_user(
|
||||||
struct tegra_vi_channel *chan,
|
struct tegra_vi_channel *chan,
|
||||||
struct vi_capture_control_msg *msg)
|
struct vi_capture_control_msg *msg)
|
||||||
@@ -1352,6 +1680,27 @@ fail:
|
|||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(vi_capture_control_message_from_user);
|
EXPORT_SYMBOL_GPL(vi_capture_control_message_from_user);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Process a VI capture control message from kernel space.
|
||||||
|
*
|
||||||
|
* This function performs the following operations:
|
||||||
|
* - Validates input parameters.
|
||||||
|
* - Copies message from kernel buffer using @ref kzalloc() and @ref memcpy().
|
||||||
|
* - Sends control message using @ref vi_capture_control_send_message().
|
||||||
|
* - Copies response to output buffer using @ref memcpy().
|
||||||
|
* - Frees message copy buffer using @ref kfree().
|
||||||
|
*
|
||||||
|
* @param[in] chan VI channel context.
|
||||||
|
* Valid value: non-NULL.
|
||||||
|
* @param[in] msg Control message from kernel.
|
||||||
|
* Valid value: non-NULL with valid pointers.
|
||||||
|
*
|
||||||
|
* @retval 0 Operation completed successfully.
|
||||||
|
* @retval -ENODEV Channel not initialized.
|
||||||
|
* @retval -EINVAL Invalid message parameters.
|
||||||
|
* @retval -ENOMEM Failed to allocate message copy buffer from @ref kzalloc().
|
||||||
|
* @retval (int) Error codes from @ref vi_capture_control_send_message().
|
||||||
|
*/
|
||||||
int vi_capture_control_message(
|
int vi_capture_control_message(
|
||||||
struct tegra_vi_channel *chan,
|
struct tegra_vi_channel *chan,
|
||||||
struct vi_capture_control_msg *msg)
|
struct vi_capture_control_msg *msg)
|
||||||
@@ -1401,6 +1750,27 @@ fail:
|
|||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get information about a VI capture channel.
|
||||||
|
*
|
||||||
|
* This function performs the following operations:
|
||||||
|
* - Validates input parameters and channel state.
|
||||||
|
* - Retrieves syncpoint IDs and values using @ref vi_capture_read_syncpt().
|
||||||
|
* - Returns channel configuration information including:
|
||||||
|
* - Progress, embedded data and line timer syncpoints.
|
||||||
|
* - Hardware channel ID.
|
||||||
|
* - VI channel masks.
|
||||||
|
*
|
||||||
|
* @param[in] chan VI channel context.
|
||||||
|
* Valid value: non-NULL.
|
||||||
|
* @param[out] info Capture channel information structure.
|
||||||
|
* Valid value: non-NULL.
|
||||||
|
*
|
||||||
|
* @retval 0 Operation completed successfully.
|
||||||
|
* @retval -ENODEV Channel not initialized.
|
||||||
|
* @retval -EINVAL Invalid info parameter.
|
||||||
|
* @retval (int) Error codes from @ref vi_capture_read_syncpt().
|
||||||
|
*/
|
||||||
int vi_capture_get_info(
|
int vi_capture_get_info(
|
||||||
struct tegra_vi_channel *chan,
|
struct tegra_vi_channel *chan,
|
||||||
struct vi_capture_info *info)
|
struct vi_capture_info *info)
|
||||||
@@ -1452,6 +1822,24 @@ int vi_capture_get_info(
|
|||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(vi_capture_get_info);
|
EXPORT_SYMBOL_GPL(vi_capture_get_info);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Calculate number of progress syncpoints needed for a capture request.
|
||||||
|
*
|
||||||
|
* This function performs the following operations:
|
||||||
|
* - Gets capture descriptor for the given buffer index using @ref check_mul_overflow().
|
||||||
|
* - Calculates required progress syncpoints based on:
|
||||||
|
* - Minimum of 2 for PXL_SOF and PXL_EOF.
|
||||||
|
* - Additional points for flush operations if enabled.
|
||||||
|
* - Adjusts count if HEIGHT is divisible by TRIPLINE.
|
||||||
|
* - Handles overflow conditions in calculations.
|
||||||
|
*
|
||||||
|
* @param[in] chan VI channel context.
|
||||||
|
* Valid value: non-NULL.
|
||||||
|
* @param[in] req Capture request parameters.
|
||||||
|
* Valid value: non-NULL.
|
||||||
|
*
|
||||||
|
* @retval (uint32_t) Number of progress syncpoints needed.
|
||||||
|
*/
|
||||||
static uint32_t vi_capture_get_num_progress(
|
static uint32_t vi_capture_get_num_progress(
|
||||||
struct tegra_vi_channel *chan,
|
struct tegra_vi_channel *chan,
|
||||||
struct vi_capture_req *req)
|
struct vi_capture_req *req)
|
||||||
@@ -1513,6 +1901,29 @@ static uint32_t vi_capture_get_num_progress(
|
|||||||
return (uint32_t)numProgress;
|
return (uint32_t)numProgress;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Submit a capture request to a VI channel.
|
||||||
|
*
|
||||||
|
* This function performs the following operations:
|
||||||
|
* - Validates input parameters and channel state.
|
||||||
|
* - Locks the reset lock using @ref mutex_lock().
|
||||||
|
* - Prepares capture request message.
|
||||||
|
* - Logs the capture request using @ref nv_camera_log_vi_submit().
|
||||||
|
* - Submits request using @ref tegra_capture_ivc_capture_submit().
|
||||||
|
* - Calculates progress points using @ref vi_capture_get_num_progress().
|
||||||
|
* - Updates progress syncpoint threshold using @ref check_add_overflow().
|
||||||
|
* - Unlocks the reset lock using @ref mutex_unlock().
|
||||||
|
*
|
||||||
|
* @param[in] chan VI channel context.
|
||||||
|
* Valid value: non-NULL.
|
||||||
|
* @param[in] req Capture request parameters.
|
||||||
|
* Valid value: non-NULL.
|
||||||
|
*
|
||||||
|
* @retval 0 Operation completed successfully.
|
||||||
|
* @retval -ENODEV Channel not initialized.
|
||||||
|
* @retval -EINVAL Invalid request parameter.
|
||||||
|
* @retval (int) Error codes from @ref tegra_capture_ivc_capture_submit().
|
||||||
|
*/
|
||||||
int vi_capture_request(
|
int vi_capture_request(
|
||||||
struct tegra_vi_channel *chan,
|
struct tegra_vi_channel *chan,
|
||||||
struct vi_capture_req *req)
|
struct vi_capture_req *req)
|
||||||
@@ -1583,6 +1994,28 @@ int vi_capture_request(
|
|||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(vi_capture_request);
|
EXPORT_SYMBOL_GPL(vi_capture_request);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Wait for capture status completion on a VI channel.
|
||||||
|
*
|
||||||
|
* This function performs the following operations:
|
||||||
|
* - Validates input parameters and channel state.
|
||||||
|
* - Waits for capture completion with specified timeout using
|
||||||
|
* @ref wait_for_completion_interruptible() if selected timtout is negative,
|
||||||
|
* or @ref wait_for_completion_timeout() otherwise.
|
||||||
|
* - Convert timeout value to jiffies using @ref msecs_to_jiffies().
|
||||||
|
*
|
||||||
|
* @param[in] chan VI channel context.
|
||||||
|
* Valid value: non-NULL.
|
||||||
|
* @param[in] timeout_ms Timeout in milliseconds.
|
||||||
|
* Valid range: [-1, INT_MAX].
|
||||||
|
* -1 means wait forever.
|
||||||
|
*
|
||||||
|
* @retval 0 Operation completed successfully.
|
||||||
|
* @retval -ENODEV Channel not initialized.
|
||||||
|
* @retval -ETIMEDOUT Wait timed out.
|
||||||
|
* @retval (int) Error codes from @ref wait_for_completion_interruptible()
|
||||||
|
* or @ref wait_for_completion_timeout().
|
||||||
|
*/
|
||||||
int vi_capture_status(
|
int vi_capture_status(
|
||||||
struct tegra_vi_channel *chan,
|
struct tegra_vi_channel *chan,
|
||||||
int32_t timeout_ms)
|
int32_t timeout_ms)
|
||||||
@@ -1638,6 +2071,25 @@ int vi_capture_status(
|
|||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(vi_capture_status);
|
EXPORT_SYMBOL_GPL(vi_capture_status);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Set up progress status notification for a VI channel.
|
||||||
|
*
|
||||||
|
* This function performs the following operations:
|
||||||
|
* - Validates input parameters and channel state.
|
||||||
|
* - Verifies buffer depth is sufficient for queue depth.
|
||||||
|
* - Sets up progress status notifier using @ref capture_common_setup_progress_status_notifier().
|
||||||
|
* - Updates channel state for progress status notification.
|
||||||
|
*
|
||||||
|
* @param[in] chan VI channel context.
|
||||||
|
* Valid value: non-NULL.
|
||||||
|
* @param[in] req Progress status request parameters.
|
||||||
|
* Valid value: non-NULL with valid memory parameters.
|
||||||
|
*
|
||||||
|
* @retval 0 Operation completed successfully.
|
||||||
|
* @retval -EINVAL Invalid request parameters.
|
||||||
|
* @retval -ENODEV Channel not initialized.
|
||||||
|
* @retval -EFAULT Error from @ref capture_common_setup_progress_status_notifier().
|
||||||
|
*/
|
||||||
int vi_capture_set_progress_status_notifier(
|
int vi_capture_set_progress_status_notifier(
|
||||||
struct tegra_vi_channel *chan,
|
struct tegra_vi_channel *chan,
|
||||||
struct vi_capture_progress_status_req *req)
|
struct vi_capture_progress_status_req *req)
|
||||||
@@ -1689,6 +2141,27 @@ int vi_capture_set_progress_status_notifier(
|
|||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(vi_capture_set_progress_status_notifier);
|
EXPORT_SYMBOL_GPL(vi_capture_set_progress_status_notifier);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Read CSI-to-VI mapping table from device tree.
|
||||||
|
*
|
||||||
|
* This function performs the following operations:
|
||||||
|
* - Reads mapping table size using @ref of_property_read_u32().
|
||||||
|
* - Ensures mapping table size is within valid range.
|
||||||
|
* - Validates mapping element names using @ref of_property_count_strings().
|
||||||
|
* - Checks element order using @ref of_property_match_string().
|
||||||
|
* - Reads and validates CSI stream ID and VI unit ID pairs using
|
||||||
|
* @ref of_property_read_u32_index().
|
||||||
|
* - Checks each CSI stream ID is unique and within valid range.
|
||||||
|
* - Checks each VI unit ID is within valid range.
|
||||||
|
* - Populates VI instance mapping table.
|
||||||
|
*
|
||||||
|
* @param[in] pdev Platform device pointer.
|
||||||
|
* Valid value: non-NULL.
|
||||||
|
*
|
||||||
|
* @retval 0 Operation completed successfully.
|
||||||
|
* @retval -EINVAL Invalid mapping parameters or device tree entries.
|
||||||
|
* @retval (int) Error codes from @ref of_property_read_u32_index().
|
||||||
|
*/
|
||||||
static int csi_vi_get_mapping_table(struct platform_device *pdev)
|
static int csi_vi_get_mapping_table(struct platform_device *pdev)
|
||||||
{
|
{
|
||||||
uint32_t index = 0;
|
uint32_t index = 0;
|
||||||
@@ -1781,6 +2254,34 @@ static int csi_vi_get_mapping_table(struct platform_device *pdev)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Probe function for VI capture driver.
|
||||||
|
*
|
||||||
|
* This function performs the following operations:
|
||||||
|
* - Allocates and initializes driver data using @ref devm_kzalloc().
|
||||||
|
* - Reads maximum VI channels using @ref of_property_read_u32().
|
||||||
|
* - Validates maximum VI channels is less than @ref NUM_VI_CHANNELS.
|
||||||
|
* - Gets VI device nodes using @ref of_parse_phandle().
|
||||||
|
* - Gets platform devices using @ref of_find_device_by_node().
|
||||||
|
* - Release each VI device node using @ref of_node_put().
|
||||||
|
* - Sets driver data using @ref platform_set_drvdata().
|
||||||
|
* - If more than one VI device, reads CSI-VI mapping using @ref csi_vi_get_mapping_table().
|
||||||
|
* - Registers VI channel driver using @ref vi_channel_drv_register().
|
||||||
|
* - If error, exits VI channel driver subsystem using @ref vi_channel_drv_exit().
|
||||||
|
* - Initializes media controller using @ref tegra_capture_vi_media_controller_init().
|
||||||
|
*
|
||||||
|
* @param[in] pdev Platform device pointer.
|
||||||
|
* Valid value: non-NULL.
|
||||||
|
*
|
||||||
|
* @retval 0 Operation completed successfully.
|
||||||
|
* @retval -ENOMEM Memory allocation failed from @ref devm_kzalloc().
|
||||||
|
* @retval -EINVAL Invalid device tree parameters or error from @ref of_property_read_u32().
|
||||||
|
* @retval -ENODEV Required devices not found from @ref of_parse_phandle() or
|
||||||
|
* @ref of_find_device_by_node().
|
||||||
|
* @retval (int) Error codes from @ref csi_vi_get_mapping_table(),
|
||||||
|
* @ref vi_channel_drv_register(),
|
||||||
|
* or @ref tegra_capture_vi_media_controller_init().
|
||||||
|
*/
|
||||||
static int capture_vi_probe(struct platform_device *pdev)
|
static int capture_vi_probe(struct platform_device *pdev)
|
||||||
{
|
{
|
||||||
uint32_t ii;
|
uint32_t ii;
|
||||||
@@ -1880,6 +2381,21 @@ cleanup:
|
|||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Remove function for VI capture driver.
|
||||||
|
*
|
||||||
|
* This function performs the following operations:
|
||||||
|
* - Retrieves capture driver data using @ref platform_get_drvdata().
|
||||||
|
* - Releases VI device references using @ref put_device().
|
||||||
|
* - Unregisters VI channel driver using @ref vi_channel_drv_unregister().
|
||||||
|
* - Cleans up media controller using @ref tegra_vi_media_controller_cleanup().
|
||||||
|
* - Exits VI channel driver using @ref vi_channel_drv_exit().
|
||||||
|
*
|
||||||
|
* @param[in] pdev Platform device pointer.
|
||||||
|
* Valid value: non-NULL.
|
||||||
|
*
|
||||||
|
* @retval 0 Operation completed successfully.
|
||||||
|
*/
|
||||||
static int capture_vi_remove(struct platform_device *pdev)
|
static int capture_vi_remove(struct platform_device *pdev)
|
||||||
{
|
{
|
||||||
struct tegra_capture_vi_data *info;
|
struct tegra_capture_vi_data *info;
|
||||||
@@ -1909,11 +2425,33 @@ static const struct of_device_id capture_vi_of_match[] = {
|
|||||||
MODULE_DEVICE_TABLE(of, capture_vi_of_match);
|
MODULE_DEVICE_TABLE(of, capture_vi_of_match);
|
||||||
|
|
||||||
#if defined(NV_PLATFORM_DRIVER_STRUCT_REMOVE_RETURNS_VOID) /* Linux v6.11 */
|
#if defined(NV_PLATFORM_DRIVER_STRUCT_REMOVE_RETURNS_VOID) /* Linux v6.11 */
|
||||||
|
/**
|
||||||
|
* @brief Wrapper function for VI capture driver removal (void return version).
|
||||||
|
*
|
||||||
|
* This function performs the following operations:
|
||||||
|
* - Calls @ref capture_vi_remove() to perform actual driver cleanup.
|
||||||
|
* - Used for Linux kernel version 6.11 and later where remove returns void.
|
||||||
|
*
|
||||||
|
* @param[in] pdev Platform device pointer.
|
||||||
|
* Valid value: non-NULL.
|
||||||
|
*/
|
||||||
static void capture_vi_remove_wrapper(struct platform_device *pdev)
|
static void capture_vi_remove_wrapper(struct platform_device *pdev)
|
||||||
{
|
{
|
||||||
capture_vi_remove(pdev);
|
capture_vi_remove(pdev);
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
|
/**
|
||||||
|
* @brief Wrapper function for VI capture driver removal (int return version).
|
||||||
|
*
|
||||||
|
* This function performs the following operations:
|
||||||
|
* - Calls @ref capture_vi_remove() to perform actual driver cleanup.
|
||||||
|
* - Used for Linux kernel versions before 6.11 where remove returns int.
|
||||||
|
*
|
||||||
|
* @param[in] pdev Platform device pointer.
|
||||||
|
* Valid value: non-NULL.
|
||||||
|
*
|
||||||
|
* @retval (int) Return value from @ref capture_vi_remove().
|
||||||
|
*/
|
||||||
static int capture_vi_remove_wrapper(struct platform_device *pdev)
|
static int capture_vi_remove_wrapper(struct platform_device *pdev)
|
||||||
{
|
{
|
||||||
return capture_vi_remove(pdev);
|
return capture_vi_remove(pdev);
|
||||||
@@ -1930,6 +2468,17 @@ static struct platform_driver capture_vi_driver = {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Module initialization function for VI capture driver.
|
||||||
|
*
|
||||||
|
* This function performs the following operations:
|
||||||
|
* - Initializes VI channel driver subsystem using @ref vi_channel_drv_init().
|
||||||
|
* - Registers platform driver using @ref platform_driver_register().
|
||||||
|
* - If error, exits VI channel driver subsystem using @ref vi_channel_drv_exit().
|
||||||
|
*
|
||||||
|
* @retval 0 Operation completed successfully.
|
||||||
|
* @retval (int) Error codes from @ref vi_channel_drv_init() or @ref platform_driver_register().
|
||||||
|
*/
|
||||||
static int __init capture_vi_init(void)
|
static int __init capture_vi_init(void)
|
||||||
{
|
{
|
||||||
int err;
|
int err;
|
||||||
@@ -1945,6 +2494,14 @@ static int __init capture_vi_init(void)
|
|||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Module exit function for VI capture driver.
|
||||||
|
*
|
||||||
|
* This function performs the following operations:
|
||||||
|
* - Exits VI channel driver subsystem using @ref vi_channel_drv_exit().
|
||||||
|
* - Unregisters platform driver using @ref platform_driver_unregister().
|
||||||
|
*/
|
||||||
static void __exit capture_vi_exit(void)
|
static void __exit capture_vi_exit(void)
|
||||||
{
|
{
|
||||||
vi_channel_drv_exit();
|
vi_channel_drv_exit();
|
||||||
|
|||||||
@@ -44,6 +44,29 @@ static DEFINE_SPINLOCK(tegra_camchar_lock);
|
|||||||
static dev_t tegra_camchar_major_number;
|
static dev_t tegra_camchar_major_number;
|
||||||
static struct class *tegra_camchar_class;
|
static struct class *tegra_camchar_class;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Opens the Tegra camera character device.
|
||||||
|
*
|
||||||
|
* This function performs the following operations:
|
||||||
|
* - Retrieves the device-specific data from the provided @ref inode structure
|
||||||
|
* using @ref container_of().
|
||||||
|
* - Checks if the device is already open.
|
||||||
|
* - Calls @ref tegra_ivc_channel_runtime_get() to obtain a runtime reference
|
||||||
|
* to the channel.
|
||||||
|
* - Marks the device as open and the connection as not established.
|
||||||
|
* - Assigns the channel to the file's private data.
|
||||||
|
* - Calls @ref nonseekable_open() to complete the open operation.
|
||||||
|
*
|
||||||
|
* @param[in] in Pointer to the @ref inode structure representing the device.
|
||||||
|
* Valid value: non-null.
|
||||||
|
* @param[in, out] f Pointer to the @ref file structure for the device file.
|
||||||
|
* Valid value: non-null.
|
||||||
|
*
|
||||||
|
* @retval EOK Successfully opened the device.
|
||||||
|
* @retval -EBUSY The device is already open.
|
||||||
|
* @retval (int) Returned errors from @ref tegra_ivc_channel_runtime_get() or
|
||||||
|
* @ref nonseekable_open().
|
||||||
|
*/
|
||||||
static int tegra_camchar_open(struct inode *in, struct file *f)
|
static int tegra_camchar_open(struct inode *in, struct file *f)
|
||||||
{
|
{
|
||||||
struct tegra_camchar_data *data;
|
struct tegra_camchar_data *data;
|
||||||
@@ -64,6 +87,23 @@ static int tegra_camchar_open(struct inode *in, struct file *f)
|
|||||||
return nonseekable_open(in, f);
|
return nonseekable_open(in, f);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Releases the Tegra camera character device.
|
||||||
|
*
|
||||||
|
* This function performs the following operations:
|
||||||
|
* - Retrieves the channel from the file's private data.
|
||||||
|
* - Obtains the device-specific data by calling @ref tegra_ivc_channel_get_drvdata().
|
||||||
|
* - Calls @ref tegra_ivc_channel_runtime_put() to release the runtime reference
|
||||||
|
* to the channel.
|
||||||
|
* - Marks the device as closed.
|
||||||
|
*
|
||||||
|
* @param[in] in Pointer to the @ref inode structure representing the device.
|
||||||
|
* Valid value: non-null.
|
||||||
|
* @param[in] fp Pointer to the @ref file structure for the device file.
|
||||||
|
* Valid value: non-null.
|
||||||
|
*
|
||||||
|
* @retval EOK Successfully released the device.
|
||||||
|
*/
|
||||||
static int tegra_camchar_release(struct inode *in, struct file *fp)
|
static int tegra_camchar_release(struct inode *in, struct file *fp)
|
||||||
{
|
{
|
||||||
struct tegra_ivc_channel *ch = fp->private_data;
|
struct tegra_ivc_channel *ch = fp->private_data;
|
||||||
@@ -76,6 +116,31 @@ static int tegra_camchar_release(struct inode *in, struct file *fp)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Polls the Tegra CamChar device for I/O readiness.
|
||||||
|
*
|
||||||
|
* This function performs the following operations:
|
||||||
|
* - Retrieves the driver data associated with the file pointer using
|
||||||
|
* @ref tegra_ivc_channel_get_drvdata().
|
||||||
|
* - Waits for events on the device's wait queue by calling @ref poll_wait().
|
||||||
|
* - Locks the I/O lock using @ref mutex_lock() to ensure exclusive access.
|
||||||
|
* - Checks if the device can be read by invoking @ref tegra_ivc_can_read().
|
||||||
|
* - Checks if the device can be written by invoking @ref tegra_ivc_can_write().
|
||||||
|
* - Unlocks the I/O lock using @ref mutex_unlock() after the checks.
|
||||||
|
* - Sets the appropriate event flags in the return value based on readability and writability.
|
||||||
|
*
|
||||||
|
* @param[in] fp Pointer to the @ref file structure.
|
||||||
|
* Valid value: non-null.
|
||||||
|
* @param[in] pt Pointer to the @ref poll_table_struct.
|
||||||
|
* Valid value: non-null.
|
||||||
|
*
|
||||||
|
* @retval 0 No events are available for
|
||||||
|
* reading or writing.
|
||||||
|
* @retval (EPOLLIN | EPOLLRDNORM) Data is available for reading.
|
||||||
|
* @retval (EPOLLOUT | EPOLLWRNORM) Space is available for writing.
|
||||||
|
* @retval (EPOLLIN | EPOLLRDNORM | EPOLLOUT | EPOLLWRNORM) Data is available for both
|
||||||
|
* reading and writing.
|
||||||
|
*/
|
||||||
static __poll_t tegra_camchar_poll(struct file *fp, struct poll_table_struct *pt)
|
static __poll_t tegra_camchar_poll(struct file *fp, struct poll_table_struct *pt)
|
||||||
{
|
{
|
||||||
__poll_t ret = 0;
|
__poll_t ret = 0;
|
||||||
@@ -94,6 +159,45 @@ static __poll_t tegra_camchar_poll(struct file *fp, struct poll_table_struct *pt
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Reads data from the Tegra camera character device.
|
||||||
|
*
|
||||||
|
* This function performs the following operations:
|
||||||
|
* - Retrieves the channel from the file's private data.
|
||||||
|
* - Obtains the device-specific data by calling @ref tegra_ivc_channel_get_drvdata().
|
||||||
|
* - Checks if the channel is ready by verifying the @ref tegra_ivc_channel.is_ready flag.
|
||||||
|
* - Limits the read length to the minimum of the requested length and the channel's
|
||||||
|
* frame size using @ref min_t().
|
||||||
|
* - If the adjusted length is zero, returns immediately with no data to read.
|
||||||
|
* - Attempts to acquire the I/O lock interruptibly by calling @ref mutex_lock_interruptible().
|
||||||
|
* - Prepares to wait on the device's wait queue by calling @ref prepare_to_wait().
|
||||||
|
* - Calls @ref tegra_ivc_read() to perform the actual read operation.
|
||||||
|
* - Releases the I/O lock using @ref mutex_unlock().
|
||||||
|
* - Exit read operation if @ref tegra_ivc_read() returns @ref -ENOMEM and:
|
||||||
|
* - A signal is pending based on @ref signal_pending().
|
||||||
|
* - If the file is opened with @ref O_NONBLOCK flag enabled.
|
||||||
|
* - Otherwise, retries the read operation.
|
||||||
|
* - Cleans up the wait by calling @ref finish_wait().
|
||||||
|
*
|
||||||
|
* @param[in] fp Pointer to the @ref file structure.
|
||||||
|
* Valid value: non-null.
|
||||||
|
* @param[out] buffer User-space buffer to store the read data.
|
||||||
|
* Valid value: non-null.
|
||||||
|
* @param[in] len Number of bytes to read.
|
||||||
|
* Valid range: [0 .. channel's frame size].
|
||||||
|
* @param[in, out] offset File position offset.
|
||||||
|
* Valid value: non-null.
|
||||||
|
*
|
||||||
|
* @retval -EIO If the channel is not ready.
|
||||||
|
* @retval 0 If the adjusted read length is zero.
|
||||||
|
* @retval -EINTR If the read operation was interrupted by a signal,
|
||||||
|
* as determined by @ref signal_pending().
|
||||||
|
* @retval -EAGAIN If the file is opened with @ref O_NONBLOCK and no data is available,
|
||||||
|
* as determined by @ref tegra_ivc_read().
|
||||||
|
* @retval (ssize_t) If postive, number of bytes successfully read. If negative, error
|
||||||
|
* codes returned from @ref tegra_ivc_read() or
|
||||||
|
* @ref mutex_lock_interruptible().
|
||||||
|
*/
|
||||||
static ssize_t tegra_camchar_read(struct file *fp, char __user *buffer, size_t len,
|
static ssize_t tegra_camchar_read(struct file *fp, char __user *buffer, size_t len,
|
||||||
loff_t *offset)
|
loff_t *offset)
|
||||||
{
|
{
|
||||||
@@ -134,6 +238,58 @@ static ssize_t tegra_camchar_read(struct file *fp, char __user *buffer, size_t l
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Writes data to the Tegra CamChar device.
|
||||||
|
*
|
||||||
|
* This function performs the following operations:
|
||||||
|
* - Retrieves the channel from the file's private data.
|
||||||
|
* - Obtains the device-specific data by calling
|
||||||
|
* @ref tegra_ivc_channel_get_drvdata().
|
||||||
|
* - Defines a wait queue using @ref DEFINE_WAIT().
|
||||||
|
* - Checks if the channel is ready using @ref WARN_ON().
|
||||||
|
* - Limits the write length to the minimum of the requested length and the
|
||||||
|
* channel's frame size using @ref min_t().
|
||||||
|
* - If the adjusted length is zero, returns 0 indicating no data to write.
|
||||||
|
* - Enters a loop to attempt the write operation:
|
||||||
|
* - Acquires the I/O lock interruptibly by calling
|
||||||
|
* @ref mutex_lock_interruptible().
|
||||||
|
* - If the lock acquisition is interrupted, breaks the loop.
|
||||||
|
* - Prepares to wait on the device's wait queue by calling
|
||||||
|
* @ref prepare_to_wait().
|
||||||
|
* - Calls @ref tegra_ivc_write() to perform the actual write operation.
|
||||||
|
* - Releases the I/O lock using @ref mutex_unlock().
|
||||||
|
* - If the write operation is successful, marks the connection as established.
|
||||||
|
* - Handles specific error conditions:
|
||||||
|
* - If @ref tegra_ivc_write() returns @ref -ENOMEM or @ref ECONNRESET,
|
||||||
|
* and a signal is pending as determined by @ref signal_pending().
|
||||||
|
* - If the file is opened with @c O_NONBLOCK and no data can be written.
|
||||||
|
* - Otherwise, calls @ref schedule() to retry the write operation.
|
||||||
|
* - Cleans up the wait by calling @ref finish_wait().
|
||||||
|
* - If a connection reset occurs and the connection was established, breaks
|
||||||
|
* the loop.
|
||||||
|
*
|
||||||
|
* @param[in] fp Pointer to the @ref file structure.
|
||||||
|
* Valid Value: non-NULL.
|
||||||
|
* @param[in] buffer User-space buffer containing the data to write.
|
||||||
|
* Valid Value: non-NULL.
|
||||||
|
* @param[in] len Number of bytes to write.
|
||||||
|
* Valid Range: [0 .. channel's frame size].
|
||||||
|
* @param[in, out] offset File position offset.
|
||||||
|
* Valid Value: non-NULL.
|
||||||
|
*
|
||||||
|
* @retval -EIO If the channel is not ready, as determined by
|
||||||
|
* @ref WARN_ON().
|
||||||
|
* @retval 0 If the adjusted write length is zero.
|
||||||
|
* @retval -EINTR If the write operation was interrupted by a signal,
|
||||||
|
* as determined by @ref mutex_lock_interruptible()
|
||||||
|
* or @ref signal_pending().
|
||||||
|
* @retval -EAGAIN If the file is opened with @ref O_NONBLOCK and no data
|
||||||
|
* can be written, as determined by @ref tegra_ivc_write().
|
||||||
|
* @retval (ssize_t) If positive, number of bytes successfully written. If negative,
|
||||||
|
* error codes returned from @ref tegra_ivc_write(),
|
||||||
|
* @ref mutex_lock_interruptible(), or other internal
|
||||||
|
* mechanisms such as @ref schedule() or @ref finish_wait().
|
||||||
|
*/
|
||||||
static ssize_t tegra_camchar_write(struct file *fp, const char __user *buffer,
|
static ssize_t tegra_camchar_write(struct file *fp, const char __user *buffer,
|
||||||
size_t len, loff_t *offset)
|
size_t len, loff_t *offset)
|
||||||
{
|
{
|
||||||
@@ -182,6 +338,36 @@ static ssize_t tegra_camchar_write(struct file *fp, const char __user *buffer,
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Handles ioctl commands for the Tegra camera character device.
|
||||||
|
*
|
||||||
|
* This function performs the following operations:
|
||||||
|
* - Retrieves the channel from the file's private data.
|
||||||
|
* - Obtains the device-specific data by calling @ref tegra_ivc_channel_get_drvdata().
|
||||||
|
* - Acquires the I/O lock by calling @ref mutex_lock().
|
||||||
|
* - Processes the ioctl command @a cmd using a switch statement:
|
||||||
|
* - For the @ref FIONREAD command:
|
||||||
|
* - Checks if the device can be read by invoking @ref tegra_ivc_can_read().
|
||||||
|
* - Copies channel frame size to user space by calling @ref put_user().
|
||||||
|
* - For the @ref CCIOGNFRAMES command:
|
||||||
|
* - Copies the number of frames in the channel to user space by calling @ref put_user().
|
||||||
|
* - For the @ref CCIOGNBYTES command:
|
||||||
|
* - Copies the channel's frame size to user space by calling @ref put_user().
|
||||||
|
* - Releases the I/O lock by calling @ref mutex_unlock().
|
||||||
|
*
|
||||||
|
* @param[in] fp Pointer to the @ref file structure.
|
||||||
|
* Valid value: non-null.
|
||||||
|
* @param[in] cmd Ioctl command number.
|
||||||
|
* Valid value: Supported ioctl commands such as
|
||||||
|
* @ref FIONREAD, @ref CCIOGNFRAMES, and @ref CCIOGNBYTES.
|
||||||
|
* @param[in] arg User-space pointer where the ioctl result will be stored.
|
||||||
|
* Valid value: Valid user-space address.
|
||||||
|
*
|
||||||
|
* @retval 0 Successfully handled the @c FIONREAD command and data is copied
|
||||||
|
* to user space.
|
||||||
|
* @retval -ENOTTY The ioctl command @a cmd is not supported.
|
||||||
|
* @retval (long) Error codes returned from @ref mutex_lock() or @ref put_user().
|
||||||
|
*/
|
||||||
static long tegra_camchar_ioctl(struct file *fp, unsigned int cmd,
|
static long tegra_camchar_ioctl(struct file *fp, unsigned int cmd,
|
||||||
unsigned long arg)
|
unsigned long arg)
|
||||||
{
|
{
|
||||||
@@ -231,6 +417,32 @@ static const struct file_operations tegra_camchar_fops = {
|
|||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Initializes the Tegra camera character device driver.
|
||||||
|
*
|
||||||
|
* This function performs the following operations:
|
||||||
|
* - Allocates a range of character device numbers by calling
|
||||||
|
* @ref alloc_chrdev_region().
|
||||||
|
* - Extracts the major number from the allocated device number using @ref MAJOR().
|
||||||
|
* - Creates a device class for the character device by calling
|
||||||
|
* @ref class_create() or @ref class_create().
|
||||||
|
* - Checks if class creation was successful. If it fails:
|
||||||
|
* - Unregisters the allocated device numbers by calling
|
||||||
|
* @ref unregister_chrdev_region().
|
||||||
|
* - Registers the IVC driver by calling @ref tegra_ivc_driver_register().
|
||||||
|
* - Checks if driver registration was successful. If it fails:
|
||||||
|
* - Destroys the created class using @ref class_destroy().
|
||||||
|
* - Unregisters the allocated device numbers by calling
|
||||||
|
* @ref unregister_chrdev_region().
|
||||||
|
* - Logs an informational message indicating successful loading of the driver.
|
||||||
|
*
|
||||||
|
* @param[in] drv Pointer to the @ref tegra_ivc_driver structure.
|
||||||
|
* Valid value: non-null.
|
||||||
|
*
|
||||||
|
* @retval 0 Successfully initialized the device driver.
|
||||||
|
* @retval (int) Error returned from @ref alloc_chrdev_region(), @ref class_create(),
|
||||||
|
* @ref PTR_ERR(), or @ref tegra_ivc_driver_register().
|
||||||
|
*/
|
||||||
static int __init tegra_camchar_init(struct tegra_ivc_driver *drv)
|
static int __init tegra_camchar_init(struct tegra_ivc_driver *drv)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
@@ -270,6 +482,21 @@ init_err_class:
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Exits and cleans up the Tegra camera character device driver.
|
||||||
|
*
|
||||||
|
* This function performs the following operations:
|
||||||
|
* - Creates a device number using @ref MKDEV() with the major number and minor number 0.
|
||||||
|
* - Unregisters the IVC driver by calling @ref tegra_ivc_driver_unregister().
|
||||||
|
* - Destroys the device class by calling @ref class_destroy().
|
||||||
|
* - Unregisters the allocated character device numbers by calling
|
||||||
|
* @ref unregister_chrdev_region().
|
||||||
|
* - Resets the major number to 0.
|
||||||
|
* - Logs an informational message indicating successful unloading of the driver.
|
||||||
|
*
|
||||||
|
* @param[in] drv Pointer to the @ref tegra_ivc_driver structure.
|
||||||
|
* Valid value: non-null.
|
||||||
|
*/
|
||||||
static void __exit tegra_camchar_exit(struct tegra_ivc_driver *drv)
|
static void __exit tegra_camchar_exit(struct tegra_ivc_driver *drv)
|
||||||
{
|
{
|
||||||
dev_t num = MKDEV(tegra_camchar_major_number, 0);
|
dev_t num = MKDEV(tegra_camchar_major_number, 0);
|
||||||
@@ -282,6 +509,17 @@ static void __exit tegra_camchar_exit(struct tegra_ivc_driver *drv)
|
|||||||
pr_info("camchar: unloaded rtcpu character device driver\n");
|
pr_info("camchar: unloaded rtcpu character device driver\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Notifies the Tegra camera character device of an event.
|
||||||
|
*
|
||||||
|
* This function performs the following operations:
|
||||||
|
* - Obtains the device-specific data by calling @ref tegra_ivc_channel_get_drvdata().
|
||||||
|
* - Wakes up any processes waiting on the device's wait queue by calling
|
||||||
|
* @ref wake_up_interruptible().
|
||||||
|
*
|
||||||
|
* @param[in] ch Pointer to the @ref tegra_ivc_channel structure.
|
||||||
|
* Valid value: non-null.
|
||||||
|
*/
|
||||||
static void tegra_camchar_notify(struct tegra_ivc_channel *ch)
|
static void tegra_camchar_notify(struct tegra_ivc_channel *ch)
|
||||||
{
|
{
|
||||||
struct tegra_camchar_data *dev_data = tegra_ivc_channel_get_drvdata(ch);
|
struct tegra_camchar_data *dev_data = tegra_ivc_channel_get_drvdata(ch);
|
||||||
@@ -289,6 +527,19 @@ static void tegra_camchar_notify(struct tegra_ivc_channel *ch)
|
|||||||
wake_up_interruptible(&dev_data->waitq);
|
wake_up_interruptible(&dev_data->waitq);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Allocates and returns the first available minor number for the CamChar device.
|
||||||
|
*
|
||||||
|
* This function performs the following operations:
|
||||||
|
* - Acquires the spinlock by calling @ref spin_lock().
|
||||||
|
* - Finds the first available minor number by calling @ref find_first_zero_bit().
|
||||||
|
* - If an available minor number is found:
|
||||||
|
* - Marks it as used by calling @ref set_bit().
|
||||||
|
* - Releases the spinlock by calling @ref spin_unlock().
|
||||||
|
*
|
||||||
|
* @retval (int) An available minor number, determined by @ref find_first_zero_bit().
|
||||||
|
* @retval -ENODEV If no available minor number was found.
|
||||||
|
*/
|
||||||
static int tegra_camchar_get_minor(void)
|
static int tegra_camchar_get_minor(void)
|
||||||
{
|
{
|
||||||
int minor;
|
int minor;
|
||||||
@@ -306,6 +557,19 @@ static int tegra_camchar_get_minor(void)
|
|||||||
return minor;
|
return minor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Releases a minor number for the Tegra camera character device.
|
||||||
|
*
|
||||||
|
* This function performs the following operations:
|
||||||
|
* - Acquires the spinlock by calling @ref spin_lock().
|
||||||
|
* - Checks if the provided minor number is within the valid range.
|
||||||
|
* - If valid, clears the corresponding bit in @ref tegra_camchar_minor_map
|
||||||
|
* using @ref clear_bit().
|
||||||
|
* - Releases the spinlock by calling @ref spin_unlock().
|
||||||
|
*
|
||||||
|
* @param[in] minor Minor number to release.
|
||||||
|
* Valid range: [0 .. @ref DEVICE_COUNT - 1].
|
||||||
|
*/
|
||||||
static void tegra_camchar_put_minor(unsigned minor)
|
static void tegra_camchar_put_minor(unsigned minor)
|
||||||
{
|
{
|
||||||
spin_lock(&tegra_camchar_lock);
|
spin_lock(&tegra_camchar_lock);
|
||||||
@@ -316,6 +580,37 @@ static void tegra_camchar_put_minor(unsigned minor)
|
|||||||
spin_unlock(&tegra_camchar_lock);
|
spin_unlock(&tegra_camchar_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Probes and initializes the Tegra CamChar device.
|
||||||
|
*
|
||||||
|
* This function performs the following operations:
|
||||||
|
* - Retrieves the device name from the device tree by invoking @ref of_device_get_match_data()
|
||||||
|
* with the provided @ref ch.dev.
|
||||||
|
* - If device name is NULL, read string from device tree property "nvidia,devname" using
|
||||||
|
* @ref of_property_read_string().
|
||||||
|
* - Allocates memory for device data using @ref devm_kzalloc().
|
||||||
|
* - Initializes the character device structure using @ref cdev_init().
|
||||||
|
* - Sets the owner of the character device to @ref THIS_MODULE.
|
||||||
|
* - Initializes the wait queue head using @ref init_waitqueue_head().
|
||||||
|
* - Initializes the I/O mutex using @ref mutex_init().
|
||||||
|
* - Associates the device data with the provided @ref tegra_ivc_channel using
|
||||||
|
* @ref tegra_ivc_channel_set_drvdata().
|
||||||
|
* - Allocates a minor number retrieved using @ref tegra_camchar_get_minor().
|
||||||
|
* - Creates a device number using @ref MKDEV().
|
||||||
|
* - Adds the character device to the system using @ref cdev_add().
|
||||||
|
* - In case of failure, release minor number using @ref tegra_camchar_put_minor().
|
||||||
|
* - Creates the device in sysfs using @ref device_create().
|
||||||
|
* - In case of failure, release minor number using @ref tegra_camchar_put_minor().
|
||||||
|
*
|
||||||
|
* @param[in] ch Pointer to the @ref tegra_ivc_channel structure.
|
||||||
|
* Valid value: non-null.
|
||||||
|
*
|
||||||
|
* @retval EOK Successfully probed and initialized the device.
|
||||||
|
* @retval -ENOMEM @ref devm_kzalloc() failed.
|
||||||
|
* @retval -ENODEV No available minor number was found using @ref tegra_camchar_get_minor().
|
||||||
|
* @retval (int) Other error codes indicating failure during device initialization originating
|
||||||
|
* from @ref cdev_add(), @ref device_create, or @ref of_property_read_string().
|
||||||
|
*/
|
||||||
static int tegra_camchar_probe(struct tegra_ivc_channel *ch)
|
static int tegra_camchar_probe(struct tegra_ivc_channel *ch)
|
||||||
{
|
{
|
||||||
const char *devname;
|
const char *devname;
|
||||||
@@ -369,6 +664,21 @@ static int tegra_camchar_probe(struct tegra_ivc_channel *ch)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Removes the Tegra CamChar device.
|
||||||
|
*
|
||||||
|
* This function performs the following operations:
|
||||||
|
* - Retrieves the device-specific data by calling
|
||||||
|
* @ref tegra_ivc_channel_get_drvdata().
|
||||||
|
* - Obtains the device number from the device data.
|
||||||
|
* - Destroys the device by calling @ref device_destroy().
|
||||||
|
* - Deletes the character device by calling @ref cdev_del().
|
||||||
|
* - Releases the allocated minor number by calling
|
||||||
|
* @ref tegra_camchar_put_minor().
|
||||||
|
*
|
||||||
|
* @param[in] ch Pointer to the @ref tegra_ivc_channel structure.
|
||||||
|
* Valid Value: non-NULL.
|
||||||
|
*/
|
||||||
static void tegra_camchar_remove(struct tegra_ivc_channel *ch)
|
static void tegra_camchar_remove(struct tegra_ivc_channel *ch)
|
||||||
{
|
{
|
||||||
struct tegra_camchar_data *data = tegra_ivc_channel_get_drvdata(ch);
|
struct tegra_camchar_data *data = tegra_ivc_channel_get_drvdata(ch);
|
||||||
|
|||||||
Reference in New Issue
Block a user