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:
Anubhav Rai
2022-08-30 00:23:01 -07:00
committed by mobile promotions
parent b66b703f0e
commit d6bcba5193
2 changed files with 64 additions and 11 deletions

View File

@@ -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;
}

View File

@@ -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];