pipeline: raspberrypi: Iterate over all Unicam instances in match()

On Raspberry Pi Compute Module platforms, it is possible to attach a
single camera device only to the secondary Unicam port. The current
logic of PipelineHandlerRPi::match() will return a failure during
enumeration of the first Unicam media device (due to no sensor attached,
or sensor failure) and thus the second Unicam media device will never be
enumerated.

Fix this by looping over all Unicam instances in PipelineHandlerRPi::match()
until a camera is correctly registered, or return a failure otherwise.

Reported-on: https://github.com/raspberrypi/libcamera/issues/44
Signed-off-by: Naushir Patuck <naush@raspberrypi.com>
Reviewed-by: David Plowman <david.plowman@raspberrypi.com>
Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
This commit is contained in:
Naushir Patuck
2023-02-24 07:30:23 +00:00
committed by Kieran Bingham
parent 471cbc0ef7
commit 2a261d911f

View File

@@ -1244,41 +1244,54 @@ int PipelineHandlerRPi::queueRequestDevice(Camera *camera, Request *request)
bool PipelineHandlerRPi::match(DeviceEnumerator *enumerator)
{
DeviceMatch unicam("unicam");
MediaDevice *unicamDevice = acquireMediaDevice(enumerator, unicam);
if (!unicamDevice) {
LOG(RPI, Debug) << "Unable to acquire a Unicam instance";
return false;
}
DeviceMatch isp("bcm2835-isp");
MediaDevice *ispDevice = acquireMediaDevice(enumerator, isp);
if (!ispDevice) {
LOG(RPI, Debug) << "Unable to acquire ISP instance";
return false;
}
constexpr unsigned int numUnicamDevices = 2;
/*
* The loop below is used to register multiple cameras behind one or more
* video mux devices that are attached to a particular Unicam instance.
* Obviously these cameras cannot be used simultaneously.
* Loop over all Unicam instances, but return out once a match is found.
* This is to ensure we correctly enumrate the camera when an instance
* of Unicam has registered with media controller, but has not registered
* device nodes due to a sensor subdevice failure.
*/
unsigned int numCameras = 0;
for (MediaEntity *entity : unicamDevice->entities()) {
if (entity->function() != MEDIA_ENT_F_CAM_SENSOR)
continue;
for (unsigned int i = 0; i < numUnicamDevices; i++) {
DeviceMatch unicam("unicam");
MediaDevice *unicamDevice = acquireMediaDevice(enumerator, unicam);
int ret = registerCamera(unicamDevice, ispDevice, entity);
if (ret)
LOG(RPI, Error) << "Failed to register camera "
<< entity->name() << ": " << ret;
else
numCameras++;
if (!unicamDevice) {
LOG(RPI, Debug) << "Unable to acquire a Unicam instance";
continue;
}
DeviceMatch isp("bcm2835-isp");
MediaDevice *ispDevice = acquireMediaDevice(enumerator, isp);
if (!ispDevice) {
LOG(RPI, Debug) << "Unable to acquire ISP instance";
continue;
}
/*
* The loop below is used to register multiple cameras behind one or more
* video mux devices that are attached to a particular Unicam instance.
* Obviously these cameras cannot be used simultaneously.
*/
unsigned int numCameras = 0;
for (MediaEntity *entity : unicamDevice->entities()) {
if (entity->function() != MEDIA_ENT_F_CAM_SENSOR)
continue;
int ret = registerCamera(unicamDevice, ispDevice, entity);
if (ret)
LOG(RPI, Error) << "Failed to register camera "
<< entity->name() << ": " << ret;
else
numCameras++;
}
if (numCameras)
return true;
}
return !!numCameras;
return false;
}
void PipelineHandlerRPi::releaseDevice(Camera *camera)