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
|
* 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/freezer.h>
|
||||||
#include <linux/kthread.h>
|
#include <linux/kthread.h>
|
||||||
#include <linux/nvhost.h>
|
#include <linux/nvhost.h>
|
||||||
|
#include <linux/errno.h>
|
||||||
#include <linux/semaphore.h>
|
#include <linux/semaphore.h>
|
||||||
#include <media/tegra_camera_platform.h>
|
#include <media/tegra_camera_platform.h>
|
||||||
#include <media/mc_common.h>
|
#include <media/mc_common.h>
|
||||||
@@ -25,6 +28,9 @@
|
|||||||
#define PG_BITRATE 32
|
#define PG_BITRATE 32
|
||||||
#define SLVSEC_STREAM_MAIN 0U
|
#define SLVSEC_STREAM_MAIN 0U
|
||||||
|
|
||||||
|
#define VI_CHANNEL_DEV "/dev/capture-vi-channel"
|
||||||
|
#define VI_CHAN_PATH_MAX 40
|
||||||
|
|
||||||
#define CAPTURE_TIMEOUT_MS 2500
|
#define CAPTURE_TIMEOUT_MS 2500
|
||||||
|
|
||||||
static const struct vi_capture_setup default_setup = {
|
static const struct vi_capture_setup default_setup = {
|
||||||
@@ -213,6 +219,50 @@ static int vi5_add_ctrls(struct tegra_channel *chan)
|
|||||||
return 0;
|
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,
|
static int vi5_channel_setup_queue(struct tegra_channel *chan,
|
||||||
unsigned int *nbuffers)
|
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");
|
dev_err(&chan->video->dev, "vi capture release failed\n");
|
||||||
goto done;
|
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;
|
chan->tegra_vi_channel[vi_port] = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -573,7 +624,7 @@ static int vi5_channel_error_recover(struct tegra_channel *chan,
|
|||||||
|
|
||||||
/* restart vi channel */
|
/* restart vi channel */
|
||||||
for (vi_port = 0; vi_port < chan->valid_ports; vi_port++) {
|
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])) {
|
if (IS_ERR(chan->tegra_vi_channel[vi_port])) {
|
||||||
err = PTR_ERR(chan);
|
err = PTR_ERR(chan);
|
||||||
goto done;
|
goto done;
|
||||||
@@ -766,12 +817,11 @@ static int vi5_channel_start_streaming(struct vb2_queue *vq, u32 count)
|
|||||||
/* Skip in bypass mode */
|
/* Skip in bypass mode */
|
||||||
if (!chan->bypass) {
|
if (!chan->bypass) {
|
||||||
for (vi_port = 0; vi_port < chan->valid_ports; vi_port++) {
|
for (vi_port = 0; vi_port < chan->valid_ports; vi_port++) {
|
||||||
chan->tegra_vi_channel[vi_port] =
|
int err = vi5_channel_open(chan, vi_port);
|
||||||
vi_channel_open_ex(chan->id + vi_port, false);
|
|
||||||
if (IS_ERR(chan->tegra_vi_channel[vi_port])) {
|
if (err)
|
||||||
ret = PTR_ERR(chan);
|
|
||||||
goto err_open_ex;
|
goto err_open_ex;
|
||||||
}
|
|
||||||
spin_lock_irqsave(&chan->capture_state_lock, flags);
|
spin_lock_irqsave(&chan->capture_state_lock, flags);
|
||||||
chan->capture_state = CAPTURE_IDLE;
|
chan->capture_state = CAPTURE_IDLE;
|
||||||
spin_unlock_irqrestore(&chan->capture_state_lock, flags);
|
spin_unlock_irqrestore(&chan->capture_state_lock, flags);
|
||||||
@@ -880,7 +930,8 @@ err_start_kthreads:
|
|||||||
err_setup:
|
err_setup:
|
||||||
if (!chan->bypass)
|
if (!chan->bypass)
|
||||||
for (vi_port = 0; vi_port < chan->valid_ports; vi_port++) {
|
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;
|
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,
|
dev_err(&chan->video->dev,
|
||||||
"vi capture release failed\n");
|
"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;
|
chan->tegra_vi_channel[vi_port] = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
/*
|
/*
|
||||||
* Tegra Media controller common APIs
|
* 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__
|
#ifndef __CAMERA_MC_COMMON_H__
|
||||||
@@ -157,6 +157,7 @@ struct tegra_channel {
|
|||||||
unsigned int num_video_formats;
|
unsigned int num_video_formats;
|
||||||
struct mutex stop_kthread_lock;
|
struct mutex stop_kthread_lock;
|
||||||
|
|
||||||
|
unsigned int vi_channel_id[TEGRA_CSI_BLOCKS];
|
||||||
unsigned char port[TEGRA_CSI_BLOCKS];
|
unsigned char port[TEGRA_CSI_BLOCKS];
|
||||||
unsigned int virtual_channel;
|
unsigned int virtual_channel;
|
||||||
unsigned int syncpt[TEGRA_CSI_BLOCKS][MAX_SYNCPT_PER_CHANNEL];
|
unsigned int syncpt[TEGRA_CSI_BLOCKS][MAX_SYNCPT_PER_CHANNEL];
|
||||||
|
|||||||
Reference in New Issue
Block a user