[libcamera-devel,09/13] libcamera: pipeline: simple: Reset routing table of subdevs
diff mbox series

Message ID 20220801000543.3501-10-laurent.pinchart@ideasonboard.com
State Accepted
Headers show
Series
  • libcamera: pipeline: simple: Support the NXP i.MX8 ISI
Related show

Commit Message

Laurent Pinchart Aug. 1, 2022, 12:05 a.m. UTC
From: Jacopo Mondi <jacopo@jmondi.org>

Reset the routing table of subdevices supporting the V4L2 streams API to
its default state when initializing the pipeline handler. This avoids
issues caused by usage of leftover state.

Signed-off-by: Jacopo Mondi <jacopo@jmondi.org>
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 src/libcamera/pipeline/simple/simple.cpp | 49 ++++++++++++++++++++++++
 1 file changed, 49 insertions(+)

Comments

Tomi Valkeinen Aug. 2, 2022, 11:05 a.m. UTC | #1
On 01/08/2022 03:05, Laurent Pinchart via libcamera-devel wrote:
> From: Jacopo Mondi <jacopo@jmondi.org>
> 
> Reset the routing table of subdevices supporting the V4L2 streams API to
> its default state when initializing the pipeline handler. This avoids
> issues caused by usage of leftover state.
> 
> Signed-off-by: Jacopo Mondi <jacopo@jmondi.org>
> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> ---
>   src/libcamera/pipeline/simple/simple.cpp | 49 ++++++++++++++++++++++++
>   1 file changed, 49 insertions(+)
> 
> diff --git a/src/libcamera/pipeline/simple/simple.cpp b/src/libcamera/pipeline/simple/simple.cpp
> index bc0cb1a00c2a..731d355efda6 100644
> --- a/src/libcamera/pipeline/simple/simple.cpp
> +++ b/src/libcamera/pipeline/simple/simple.cpp
> @@ -332,6 +332,7 @@ private:
>   	}
>   
>   	std::vector<MediaEntity *> locateSensors();
> +	static int resetRoutingTable(V4L2Subdevice *subdev);
>   
>   	const MediaPad *acquirePipeline(SimpleCameraData *data);
>   	void releasePipeline(SimpleCameraData *data);
> @@ -1260,6 +1261,37 @@ std::vector<MediaEntity *> SimplePipelineHandler::locateSensors()
>   	return sensors;
>   }
>   
> +int SimplePipelineHandler::resetRoutingTable(V4L2Subdevice *subdev)
> +{
> +	/* Reset the media entity routing table to its default state. */
> +	V4L2Subdevice::Routing routing = {};
> +
> +	int ret = subdev->getRouting(&routing, V4L2Subdevice::TryFormat);
> +	if (ret)
> +		return ret;
> +
> +	ret = subdev->setRouting(&routing, V4L2Subdevice::ActiveFormat);
> +	if (ret)
> +		return ret;

Is this a normal way to reset things in v4l2? Say, if you want to reset 
the fmt on a pad?

Reviewed-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>

  Tomi
Laurent Pinchart Aug. 2, 2022, 12:41 p.m. UTC | #2
Hi Tomi,

On Tue, Aug 02, 2022 at 02:05:16PM +0300, Tomi Valkeinen wrote:
> On 01/08/2022 03:05, Laurent Pinchart via libcamera-devel wrote:
> > From: Jacopo Mondi <jacopo@jmondi.org>
> > 
> > Reset the routing table of subdevices supporting the V4L2 streams API to
> > its default state when initializing the pipeline handler. This avoids
> > issues caused by usage of leftover state.
> > 
> > Signed-off-by: Jacopo Mondi <jacopo@jmondi.org>
> > Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> > ---
> >   src/libcamera/pipeline/simple/simple.cpp | 49 ++++++++++++++++++++++++
> >   1 file changed, 49 insertions(+)
> > 
> > diff --git a/src/libcamera/pipeline/simple/simple.cpp b/src/libcamera/pipeline/simple/simple.cpp
> > index bc0cb1a00c2a..731d355efda6 100644
> > --- a/src/libcamera/pipeline/simple/simple.cpp
> > +++ b/src/libcamera/pipeline/simple/simple.cpp
> > @@ -332,6 +332,7 @@ private:
> >   	}
> >   
> >   	std::vector<MediaEntity *> locateSensors();
> > +	static int resetRoutingTable(V4L2Subdevice *subdev);
> >   
> >   	const MediaPad *acquirePipeline(SimpleCameraData *data);
> >   	void releasePipeline(SimpleCameraData *data);
> > @@ -1260,6 +1261,37 @@ std::vector<MediaEntity *> SimplePipelineHandler::locateSensors()
> >   	return sensors;
> >   }
> >   
> > +int SimplePipelineHandler::resetRoutingTable(V4L2Subdevice *subdev)
> > +{
> > +	/* Reset the media entity routing table to its default state. */
> > +	V4L2Subdevice::Routing routing = {};
> > +
> > +	int ret = subdev->getRouting(&routing, V4L2Subdevice::TryFormat);
> > +	if (ret)
> > +		return ret;
> > +
> > +	ret = subdev->setRouting(&routing, V4L2Subdevice::ActiveFormat);
> > +	if (ret)
> > +		return ret;
> 
> Is this a normal way to reset things in v4l2? Say, if you want to reset 
> the fmt on a pad?

There's no explicit reset API, getting the default value using a try
context is the best way I know of. This only works if the try context
isn't modified of course, which is fine here.

> Reviewed-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>

Patch
diff mbox series

diff --git a/src/libcamera/pipeline/simple/simple.cpp b/src/libcamera/pipeline/simple/simple.cpp
index bc0cb1a00c2a..731d355efda6 100644
--- a/src/libcamera/pipeline/simple/simple.cpp
+++ b/src/libcamera/pipeline/simple/simple.cpp
@@ -332,6 +332,7 @@  private:
 	}
 
 	std::vector<MediaEntity *> locateSensors();
+	static int resetRoutingTable(V4L2Subdevice *subdev);
 
 	const MediaPad *acquirePipeline(SimpleCameraData *data);
 	void releasePipeline(SimpleCameraData *data);
@@ -1260,6 +1261,37 @@  std::vector<MediaEntity *> SimplePipelineHandler::locateSensors()
 	return sensors;
 }
 
+int SimplePipelineHandler::resetRoutingTable(V4L2Subdevice *subdev)
+{
+	/* Reset the media entity routing table to its default state. */
+	V4L2Subdevice::Routing routing = {};
+
+	int ret = subdev->getRouting(&routing, V4L2Subdevice::TryFormat);
+	if (ret)
+		return ret;
+
+	ret = subdev->setRouting(&routing, V4L2Subdevice::ActiveFormat);
+	if (ret)
+		return ret;
+
+	/*
+	 * If the routing table is empty we won't be able to meaningfully use
+	 * the subdev.
+	 */
+	if (routing.empty()) {
+		LOG(SimplePipeline, Error)
+			<< "Default routing table of " << subdev->deviceNode()
+			<< " is empty";
+		return -EINVAL;
+	}
+
+	LOG(SimplePipeline, Debug)
+		<< "Routing table of " << subdev->deviceNode()
+		<< " reset to " << routing.toString();
+
+	return 0;
+}
+
 bool SimplePipelineHandler::match(DeviceEnumerator *enumerator)
 {
 	const SimplePipelineInfo *info = nullptr;
@@ -1352,6 +1384,23 @@  bool SimplePipelineHandler::match(DeviceEnumerator *enumerator)
 					<< ": " << strerror(-ret);
 				return false;
 			}
+
+			if (subdev->caps().hasStreams()) {
+				/*
+				 * Reset the routing table to its default state
+				 * to make sure entities are enumerate according
+				 * to the defaul routing configuration.
+				 */
+				ret = resetRoutingTable(subdev.get());
+				if (ret) {
+					LOG(SimplePipeline, Error)
+						<< "Failed to reset routes for "
+						<< subdev->deviceNode() << ": "
+						<< strerror(-ret);
+					return false;
+				}
+			}
+
 			break;
 
 		default: