mirror of
git://nv-tegra.nvidia.com/linux-nv-oot.git
synced 2025-12-22 17:25:35 +03:00
vi5: fix v4l2 VI driver channel open
unmap chan_id from DT with capture channel id. Capture channel id is shared between isp capture and v4l2. Find a free capture channel that does not conflict with other clients bug 3691031 Change-Id: If3cd887db6feb2a1817a7451249185de47d6e9ad Signed-off-by: Anubhav Rai <arai@nvidia.com> Reviewed-on: https://git-master.nvidia.com/r/c/linux-nvidia/+/2768753 (cherry picked from commit cf54cc587eba0854236c634b8ec0c1c2c98a3a5d) Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/2866951 Reviewed-by: svcacv <svcacv@nvidia.com> Reviewed-by: Ankur Pawar <ankurp@nvidia.com> Reviewed-by: Laxman Dewangan <ldewangan@nvidia.com> Tested-by: Ankur Pawar <ankurp@nvidia.com> GVS: Gerrit_Virtual_Submit <buildbot_gerritrpt@nvidia.com>
This commit is contained in:
committed by
mobile promotions
parent
b66b703f0e
commit
d6bcba5193
@@ -2,12 +2,15 @@
|
||||
/*
|
||||
* Tegra Video Input 5 device common APIs
|
||||
*
|
||||
* Copyright (c) 2016-2022, NVIDIA CORPORATION. All rights reserved.
|
||||
* Copyright (c) 2016-2023, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <linux/syscalls.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/freezer.h>
|
||||
#include <linux/kthread.h>
|
||||
#include <linux/nvhost.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/semaphore.h>
|
||||
#include <media/tegra_camera_platform.h>
|
||||
#include <media/mc_common.h>
|
||||
@@ -25,6 +28,9 @@
|
||||
#define PG_BITRATE 32
|
||||
#define SLVSEC_STREAM_MAIN 0U
|
||||
|
||||
#define VI_CHANNEL_DEV "/dev/capture-vi-channel"
|
||||
#define VI_CHAN_PATH_MAX 40
|
||||
|
||||
#define CAPTURE_TIMEOUT_MS 2500
|
||||
|
||||
static const struct vi_capture_setup default_setup = {
|
||||
@@ -213,6 +219,50 @@ static int vi5_add_ctrls(struct tegra_channel *chan)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Find a free VI channel to open. Synchronize vi capture channel sharing
|
||||
* with other clients.
|
||||
*/
|
||||
static int vi5_channel_open(struct tegra_channel *chan, u32 vi_port)
|
||||
{
|
||||
bool found = false;
|
||||
char chanFilePath[VI_CHAN_PATH_MAX];
|
||||
int channel = 0;
|
||||
struct file *filp = NULL;
|
||||
long err = 0;
|
||||
|
||||
while (!found) {
|
||||
sprintf(chanFilePath, "%s%u", VI_CHANNEL_DEV, channel);
|
||||
|
||||
filp = filp_open(chanFilePath, O_RDONLY, 0);
|
||||
|
||||
if (IS_ERR(filp)) {
|
||||
err = PTR_ERR(filp);
|
||||
/* Retry with the next available channel. Opening
|
||||
* a channel number greater than the ones supported
|
||||
* by the platform will trigger a ENODEV from the
|
||||
* VI capture channel driver
|
||||
*/
|
||||
if (err == -EBUSY)
|
||||
channel++;
|
||||
else {
|
||||
dev_err(&chan->video->dev,
|
||||
"Error opening VI capture channel node %s with err: %ld\n",
|
||||
chanFilePath, err);
|
||||
return -ENODEV;
|
||||
}
|
||||
} else
|
||||
found = true;
|
||||
}
|
||||
|
||||
err = 0;
|
||||
chan->vi_channel_id[vi_port] = channel;
|
||||
|
||||
chan->tegra_vi_channel[vi_port] = filp->private_data;
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int vi5_channel_setup_queue(struct tegra_channel *chan,
|
||||
unsigned int *nbuffers)
|
||||
{
|
||||
@@ -534,7 +584,8 @@ static int vi5_channel_error_recover(struct tegra_channel *chan,
|
||||
dev_err(&chan->video->dev, "vi capture release failed\n");
|
||||
goto done;
|
||||
}
|
||||
vi_channel_close_ex(chan->id + vi_port, chan->tegra_vi_channel[vi_port]);
|
||||
vi_channel_close_ex(chan->vi_channel_id[vi_port],
|
||||
chan->tegra_vi_channel[vi_port]);
|
||||
chan->tegra_vi_channel[vi_port] = NULL;
|
||||
}
|
||||
|
||||
@@ -573,7 +624,7 @@ static int vi5_channel_error_recover(struct tegra_channel *chan,
|
||||
|
||||
/* restart vi channel */
|
||||
for (vi_port = 0; vi_port < chan->valid_ports; vi_port++) {
|
||||
chan->tegra_vi_channel[vi_port] = vi_channel_open_ex(chan->id + vi_port, false);
|
||||
err = vi5_channel_open(chan, vi_port);
|
||||
if (IS_ERR(chan->tegra_vi_channel[vi_port])) {
|
||||
err = PTR_ERR(chan);
|
||||
goto done;
|
||||
@@ -766,12 +817,11 @@ static int vi5_channel_start_streaming(struct vb2_queue *vq, u32 count)
|
||||
/* Skip in bypass mode */
|
||||
if (!chan->bypass) {
|
||||
for (vi_port = 0; vi_port < chan->valid_ports; vi_port++) {
|
||||
chan->tegra_vi_channel[vi_port] =
|
||||
vi_channel_open_ex(chan->id + vi_port, false);
|
||||
if (IS_ERR(chan->tegra_vi_channel[vi_port])) {
|
||||
ret = PTR_ERR(chan);
|
||||
int err = vi5_channel_open(chan, vi_port);
|
||||
|
||||
if (err)
|
||||
goto err_open_ex;
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&chan->capture_state_lock, flags);
|
||||
chan->capture_state = CAPTURE_IDLE;
|
||||
spin_unlock_irqrestore(&chan->capture_state_lock, flags);
|
||||
@@ -880,7 +930,8 @@ err_start_kthreads:
|
||||
err_setup:
|
||||
if (!chan->bypass)
|
||||
for (vi_port = 0; vi_port < chan->valid_ports; vi_port++) {
|
||||
vi_channel_close_ex(chan->id + vi_port, chan->tegra_vi_channel[vi_port]);
|
||||
vi_channel_close_ex(chan->vi_channel_id[vi_port],
|
||||
chan->tegra_vi_channel[vi_port]);
|
||||
chan->tegra_vi_channel[vi_port] = NULL;
|
||||
}
|
||||
|
||||
@@ -911,7 +962,8 @@ static int vi5_channel_stop_streaming(struct vb2_queue *vq)
|
||||
dev_err(&chan->video->dev,
|
||||
"vi capture release failed\n");
|
||||
|
||||
vi_channel_close_ex(chan->id + vi_port, chan->tegra_vi_channel[vi_port]);
|
||||
vi_channel_close_ex(chan->vi_channel_id[vi_port],
|
||||
chan->tegra_vi_channel[vi_port]);
|
||||
chan->tegra_vi_channel[vi_port] = NULL;
|
||||
}
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
/*
|
||||
* Tegra Media controller common APIs
|
||||
*
|
||||
* Copyright (c) 2012-2022, NVIDIA CORPORATION. All rights reserved.
|
||||
* Copyright (c) 2012-2023 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef __CAMERA_MC_COMMON_H__
|
||||
@@ -157,6 +157,7 @@ struct tegra_channel {
|
||||
unsigned int num_video_formats;
|
||||
struct mutex stop_kthread_lock;
|
||||
|
||||
unsigned int vi_channel_id[TEGRA_CSI_BLOCKS];
|
||||
unsigned char port[TEGRA_CSI_BLOCKS];
|
||||
unsigned int virtual_channel;
|
||||
unsigned int syncpt[TEGRA_CSI_BLOCKS][MAX_SYNCPT_PER_CHANNEL];
|
||||
|
||||
Reference in New Issue
Block a user