summaryrefslogtreecommitdiff
AgeCommit message (Collapse)Author
2024-06-20media: renesas: vsp1: Get configuration from partition instead of stateLaurent Pinchart
Entities access various piece of information from the subdev state when configuring a partition. The same data is available through the partition structure passed to the .configure_partition() operation. Use it to avoid accessing the state, which will simplify moving to the V4L2 subdev active state API. Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com> Reviewed-by: Jacopo Mondi <jacopo.mondi+renesas@ideasonboard.com>
2024-06-20media: renesas: vsp1: Compute partitions for DRM pipelinesLaurent Pinchart
The DRM pipelines don't partition frames, as the hardware operates synchronously with the display. The entity operations access configuration data from the entity state in that case, instead of accessing the partition structure. This requires special cases in entity-specific code, increasing the driver complexity. To prepare for simplifying the code, initialize a single partition for the DRM pipelines, similarly to how video pipelines create one partition spanning the full image when partitioning isn't needed. The partition is allocated statically in the vsp1_drm_pipeline structure instead of dynamically as for video pipelines, as DRM pipelines are guaranteed to operate on a single partition. Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com> Reviewed-by: Jacopo Mondi <jacopo.mondi+renesas@ideasonboard.com>
2024-06-20media: renesas: vsp1: Keep the DRM pipeline entities sortedLaurent Pinchart
Some of the code that handles pipeline configuration assumes that entities in a pipeline's entities list are sorted from sink to source. To prepare for using that code with the DRM pipeline, insert the BRx just before the WPF, and the RPFs at the head of the list. Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com> Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com> Reviewed-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
2024-06-20media: renesas: vsp1: Add and use function to dump a pipeline to the logLaurent Pinchart
It is useful for debugging purpose to dump a vsp1_pipeline to the kernel log. Add a new function to do so, and use it when initializing the video and DRM pipelines. As __vsp1_pipeline_dump() needs to construct the log message iteratively, it uses pr_cont(...) (exact equivalent to the more verbose "printk(KERN_CONT ..."). The function thus can't use dev_dbg() to log the initial part of the message, for two reasons: - pr_cont() doesn't seem to work with dev_*(). Even if the format string passed to dev_*() doesn't end with a '\n', pr_cont() starts a new line in the log. This behaviour doesn't seem to be clearly documented, and may or may not be on purpose. - Messages printed by dev_dbg() may be omitted if dynamic debugging is enabled. In that case, the continuation messages will still be printed, leading to confusing log messages. To still benefit from the dynamic debug infrastructure, we declare a vsp1_pipeline_dump() macro that uses _dynamic_func_call() when dynamic debugging is enabled. The whole vsp1_pipeline_dump() call can be selected at runtime. The __vsp1_pipeline_dump() function then uses a plain "printk(KERN_DEBUG ...)" to print the message header using the debug log level, and pr_cont() to print the rest of the message on the same line. Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com> Reviewed-by: Jacopo Mondi <jacopo.mondi+renesas@ideasonboard.com>
2024-06-20media: renesas: vsp1: Replace vsp1_partition_window with v4l2_rectLaurent Pinchart
The vsp1_partition_window structure is used to store the horizontal size of a partition window. This is all that is currently needed, as all partitions span the whole image vertically. The horizontal window size is retrieved in the .configure_partition() handler from the vsp1_partition_window structure, and the vertical window size from the subdev state. Accessing the subdev state in the .configure_partition() handler is problematic in the context of moving to the V4L2 subdev active state API, as .configure_partition() is called in non-interruptable context, and the state lock can't be taken. To avoid this, start by storing the vertical size in the window, replacing the custom vsp1_partition_window structure with a v4l2_rect. Retrieving the vertical size from the window in .configure_partition() will be done in a subsequent change. Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com> Reviewed-by: Jacopo Mondi <jacopo.mondi+renesas@ideasonboard.com>
2024-06-20media: renesas: vsp1: Pass partition pointer to .configure_partition()Laurent Pinchart
The entity .configure_partition() function operates on a partition, and has to retrieve that partition from the pipeline's current partition field. Pass the partition pointer to the function to make it clearer what partition it operates on, and remove the vsp1_pipeline.partition field. This change clearly shows that the DRM pipeline doesn't use partitions, which makes entity implementation more complex and error-prone. This will be addressed in a further cleanup. Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com> Reviewed-by: Jacopo Mondi <jacopo.mondi+renesas@ideasonboard.com>
2024-06-20media: renesas: vsp1: Store RPF partition configuration per RPF instanceLaurent Pinchart
The vsp1_partition structure stores the RPF partition configuration in a single field for all RPF instances, while each RPF can have its own configuration. Fix it by storing the configuration separately for each RPF instance. Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com> Fixes: ab45e8585182 ("media: v4l: vsp1: Allow entities to participate in the partition algorithm") Reviewed-by: Jacopo Mondi <jacopo.mondi+renesas@ideasonboard.com>
2024-06-20media: renesas: vsp1: Simplify partition calculationLaurent Pinchart
When calculation a partition in vsp1_pipeline_calculate_partition(), there is no need to handle the case where the whole image is covered by a single partition locally. In that case, the index and div_size parameters are 0 and format->width respectively, which makes the general code behave exactly as the special case. Drop the special case. Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com> Reviewed-by: Jacopo Mondi <jacopo.mondi+renesas@ideasonboard.com>
2024-06-20media: renesas: vsp1: Move partition calculation to vsp1_pipe.cLaurent Pinchart
The partition calculation code, located in vsp1_video.c, is not specific to video pipelines. To prepare for its usage in DRM pipelines, move it to vsp1_pipe.c. Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com> Reviewed-by: Jacopo Mondi <jacopo.mondi+renesas@ideasonboard.com>
2024-06-20media: renesas: vsp1: Drop custom .get_fmt() handler for histogramLaurent Pinchart
The histogram module is the only one that has a custom .get_fmt() handler, to handle the special case of the output format being fixed. This can equally well be handled in the .set_fmt() handler instead. Beside avoiding special cases and using the same .get_fmt() handler in all modules, it ensures that the correct format is stored in the active state for the source pad, including when .set_fmt() is called from vsp1_entity_init_state(). Both are needed to later switch to the V4L2 subdev active state API. Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com> Reviewed-by: Jacopo Mondi <jacopo.mondi+renesas@ideasonboard.com>
2024-06-20media: renesas: vsp1: Drop brx_get_compose() wrapperLaurent Pinchart
The brx_get_compose() function is just a wrapper around v4l2_subdev_state_get_compose() without any added value. Drop it and call v4l2_subdev_state_get_compose() directly. Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com> Reviewed-by: Jacopo Mondi <jacopo.mondi+renesas@ideasonboard.com>
2024-06-20media: renesas: vsp1: Drop vsp1_rwpf_get_crop() wrapperLaurent Pinchart
The vsp1_rwpf_get_crop() function is just a wrapper around v4l2_subdev_state_get_crop() without any added value. Drop it and call v4l2_subdev_state_get_crop() directly. Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com> Reviewed-by: Jacopo Mondi <jacopo.mondi+renesas@ideasonboard.com>
2024-06-20media: renesas: vsp1: Drop vsp1_entity_get_pad_selection() wrapperLaurent Pinchart
The vsp1_entity_get_pad_selection() function is just a wrapper around v4l2_subdev_state_get_crop() or v4l2_subdev_state_get_compose() without any added value. Drop it and call the functions it wraps directly. Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com> Reviewed-by: Jacopo Mondi <jacopo.mondi+renesas@ideasonboard.com>
2024-06-20media: renesas: vsp1: Drop vsp1_entity_get_pad_format() wrapperLaurent Pinchart
The vsp1_entity_get_pad_format() function is just a wrapper around v4l2_subdev_state_get_format() without any added value. Drop it and call v4l2_subdev_state_get_format() directly. Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com> Reviewed-by: Jacopo Mondi <jacopo.mondi+renesas@ideasonboard.com>
2024-06-20media: renesas: vsp1: Print debug message to diagnose validation failureLaurent Pinchart
When formats don't match between a subdev and a connected video device, starting streaming returns an error without giving the user any indication as to what went wrong. To help debugging pipeline misconfigurations, add a debug message that indicates the cause of the failure. Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com> Reviewed-by: Kieran Bingham <kieran.bingham+renesas@ideasonboard.com>
2024-06-19media: v4l2-subdev: Drop unreacheable warningLaurent Pinchart
The v4l2_subdev_link_validate_get_format() function warns if the pad given as argument belongs to a non-subdev entity. This can't happen, as the function is called from v4l2_subdev_link_validate() only (indirectly through v4l2_subdev_link_validate_locked()), and that function ensures that both ends of the link are subdevs. Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com> Reviewed-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
2024-06-19media: videobuf2: core: Drop unneeded forward declarationLaurent Pinchart
The static __enqueue_in_driver() function is forward-declared needlessly, as it isn't called before its definition. Drop the forward declaration. Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com> Reviewed-by: Tomasz Figa <tfiga@chromium.org>
2024-06-19media: renesas: vsp1: Fix _irqsave and _irq mixLaurent Pinchart
The histogram support mixes _irqsave and _irq, causing the following smatch warning: drivers/media/platform/renesas/vsp1/vsp1_histo.c:153 histo_stop_streaming() warn: mixing irqsave and irq The histo_stop_streaming() calls spin_lock_irqsave() followed by wait_event_lock_irq(). The former hints that interrupts may be disabled by the caller, while the latter reenables interrupts unconditionally. This doesn't cause any real bug, as the function is always called with interrupts enabled, but the pattern is still incorrect. Fix the problem by using spin_lock_irq() instead of spin_lock_irqsave() in histo_stop_streaming(). While at it, switch to spin_lock_irq() and spin_lock() as appropriate elsewhere. Fixes: 99362e32332b ("[media] v4l: vsp1: Add histogram support") Reported-by: Dan Carpenter <dan.carpenter@linaro.org> Closes: https://lore.kernel.org/linux-renesas-soc/164d74ff-312c-468f-be64-afa7182cd2f4@moroto.mountain/ Reviewed-by: Kieran Bingham <kieran.bingham+renesas@ideasonboard.com> Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
2024-06-19media: max9286: Use frame interval from subdev stateJacopo Mondi
Use the frame interval stored in the subdev state instead of storing a copy in the driver private structure. Initialize the frame interval to the special case 0/0 that in the max9286 driver represents automatic handling of frame sync. As the frame sync mode is set at s_stream() time, we can remove it from max9286_setup(). Signed-off-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Link: https://lore.kernel.org/r/20240617161135.130719-12-jacopo.mondi@ideasonboard.com Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
2024-06-19media: max9286: Use the subdev active stateJacopo Mondi
Use the subdev active state in the max9286 driver to store the image format. Replace the .open() function call with the .init_state() one and simplify the set/get_pad_fmt() operations. Signed-off-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com> Reviewed-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com> Link: https://lore.kernel.org/r/20240617161135.130719-11-jacopo.mondi@ideasonboard.com Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
2024-06-19media: max9286: Fix enum_mbus_codeJacopo Mondi
The max9286 driver supports multiple output formats but only a single one is reported through the .enum_mbus_code operation. Fix that. Signed-off-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com> Reviewed-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com> Link: https://lore.kernel.org/r/20240617161135.130719-10-jacopo.mondi@ideasonboard.com Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
2024-06-19media: adv748x-csi2: Use the subdev active stateJacopo Mondi
Initialize and use the subdev active state to store the subdevice format. This simplifies the implementation of the get_fmt and set_fmt pad operations. Signed-off-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Reviewed-by: Niklas Söderlund <niklas.soderlund+renesas@ragnatech.se> Tested-by: Niklas Söderlund <niklas.soderlund+renesas@ragnatech.se> Link: https://lore.kernel.org/r/20240617161135.130719-9-jacopo.mondi@ideasonboard.com Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
2024-06-19media: adv748x-csi2: Validate the image formatJacopo Mondi
The adv748x-csi2 driver configures the CSI-2 transmitter to automatically infer the image stream format from the connected frontend (HDMI or AFE). Setting a new format on the subdevice hence does not actually control the CSI-2 output format, but it's only there for the purpose of pipeline validation. However, there is currently no validation that the supplied media bus code is valid and supported by the device. With the introduction of enum_mbus_codes a list of supported format is now available, use it to validate that the supplied format is correct and use the default UYVY8 one if that's not the case. Signed-off-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com> Reviewed-by: Niklas Söderlund <niklas.soderlund+renesas@ragnatech.se> Tested-by: Niklas Söderlund <niklas.soderlund+renesas@ragnatech.se> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Link: https://lore.kernel.org/r/20240617161135.130719-8-jacopo.mondi@ideasonboard.com Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
2024-06-19media: adv748x-afe: Use 1X16 media bus codeJacopo Mondi
Now that the adv748x CSI-2 transmitter driver validates the supported formats, it is required for subdevices along the pipeline to produce and consume the same media bus codes. The adv748x analog front end driver use the 2X8 variant of the UYVY8 media bus code, while the CSI-2 transmitter use the 1X16 variant, which is the correct one to use for the serial bus. Make the adv748x afe use the 1X16 format variant to maintain the pipeline validation correct. Signed-off-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Reviewed-by: Niklas Söderlund <niklas.soderlund+renesas@ragnatech.se> Tested-by: Niklas Söderlund <niklas.soderlund+renesas@ragnatech.se> Link: https://lore.kernel.org/r/20240617161135.130719-7-jacopo.mondi@ideasonboard.com Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
2024-06-19media: adv748x-csi2: Implement enum_mbus_codesJacopo Mondi
Define a list of supported mbus codes for the TXA and TXB CSI-2 transmitters and implement the enum_mbus_code operation. The TXB transmitter only support YUV422 while the TXA one supports multiple formats as reported by the chip's manual in section 9.7. but the HDMI and AFE subdevices only provide RGB888 and YUV422, so only list those ones here. Signed-off-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Reviewed-by: Niklas Söderlund <niklas.soderlund+renesas@ragnatech.se> Tested-by: Niklas Söderlund <niklas.soderlund+renesas@ragnatech.se> Link: https://lore.kernel.org/r/20240617161135.130719-6-jacopo.mondi@ideasonboard.com Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
2024-06-19media: rcar-csi2: Use the subdev active stateJacopo Mondi
Create the subdevice state with v4l2_subdev_init_finalize() and implement the init_state() operation to guarantee the state is initialized. Store the current image format in the subdev active state and remove it from the driver private structure. To guarantee the same image format is applied to all source pads, propagate the format from the sink pad to the sources, disallowing changing format on a source pad. To support both gen3 and gen4, which feature a different number of source pads, introduce an helper function to return the correct number of pads. Signed-off-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com> Reviewed-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com> Reviewed-by: Niklas Söderlund <niklas.soderlund+renesas@ragnatech.se> Tested-by: Niklas Söderlund <niklas.soderlund+renesas@ragnatech.se> Link: https://lore.kernel.org/r/20240617161135.130719-5-jacopo.mondi@ideasonboard.com Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
2024-06-19media: rcar-csi2: Cleanup subdevice in remove()Jacopo Mondi
Cleanup the V4L2 subdevice in the driver's remove function to ensure its async connection are freed, and guarantee in future that the subdev active state is cleaned up. Fixes: 769afd212b16 ("media: rcar-csi2: add Renesas R-Car MIPI CSI-2 receiver driver") Signed-off-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com> Reviewed-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com> Reviewed-by: Niklas Söderlund <niklas.soderlund+renesas@ragnatech.se> Tested-by: Niklas Söderlund <niklas.soderlund+renesas@ragnatech.se> Link: https://lore.kernel.org/r/20240617161135.130719-4-jacopo.mondi@ideasonboard.com Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
2024-06-19media: rcar-csi2: Disable runtime_pm in probe errorJacopo Mondi
Disable pm_runtime in the probe() function error path. Fixes: 769afd212b16 ("media: rcar-csi2: add Renesas R-Car MIPI CSI-2 receiver driver") Signed-off-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com> Reviewed-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com> Reviewed-by: Niklas Söderlund <niklas.soderlund+renesas@ragnatech.se> Tested-by: Niklas Söderlund <niklas.soderlund+renesas@ragnatech.se> Link: https://lore.kernel.org/r/20240617161135.130719-3-jacopo.mondi@ideasonboard.com Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
2024-06-19media: rcar-vin: Fix YUYV8_1X16 handling for CSI-2Jacopo Mondi
The YUYV8_1X16 and UYVY8_1X16 formats are treated as 'ITU-R BT.601/BT.1358 16-bit YCbCr-422 input' (YUV16 - 0x5) in the R-Car VIN driver and are thus disallowed when capturing frames from the R-Car CSI-2 interface according to the hardware manual. As the 1X16 format variants are meant to be used with serial busses they have to be treated as 'YCbCr-422 8-bit data input' (0x1) when capturing from CSI-2, which is a valid setting for CSI-2. Commit 78b3f9d75a62 ("media: rcar-vin: Add check that input interface and format are valid") disallowed capturing YUV16 when using the CSI-2 interface. Fix this by using YUV8_BT601 for YCbCr422 when CSI-2 is in use. Fixes: 78b3f9d75a62 ("media: rcar-vin: Add check that input interface and format are valid") Signed-off-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com> Reviewed-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com> Reviewed-by: Niklas Söderlund <niklas.soderlund+renesas@ragnatech.se> Tested-by: Niklas Söderlund <niklas.soderlund+renesas@ragnatech.se> Link: https://lore.kernel.org/r/20240617161135.130719-2-jacopo.mondi@ideasonboard.com Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
2024-06-17media: uvcvideo: Remove mappings form uvc_device_infoRicardo Ribalda
We do not have any quirk device making us of this. Remove from now. It can be easily reverted later if needed. Signed-off-by: Ricardo Ribalda <ribalda@chromium.org> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Reviewed-by: Ricardo Ribalda <ribalda@chromium.org>
2024-06-17media: uvcvideo: Remove PLF device quirkingRicardo Ribalda
We can use heuristics to figure out the proper range of the control instead of quirking every single device. Reviewed-by: Sergey Senozhatsky <senozhatsky@chromium.org> Signed-off-by: Ricardo Ribalda <ribalda@chromium.org> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Reviewed-by: Ricardo Ribalda <ribalda@chromium.org>
2024-06-17media: uvcvideo: Cleanup version-specific mappingRicardo Ribalda
We do not have more version specific mappings. Let's remove this code for now. It can be easily reverted later if needed. Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Reviewed-by: Sergey Senozhatsky <senozhatsky@chromium.org> Signed-off-by: Ricardo Ribalda <ribalda@chromium.org> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Reviewed-by: Ricardo Ribalda <ribalda@chromium.org>
2024-06-17media: uvcvideo: Probe the PLF characteristicsRicardo Ribalda
The UVC 1.5 standard defines 4 values for the PLF control: Off, 50Hz, 60Hz and Auto. But it does not clearly define if all the values must be implemented or not. Instead of just using the UVC version to determine what the PLF control can do, probe it. Reviewed-by: Sergey Senozhatsky <senozhatsky@chromium.org> Signed-off-by: Ricardo Ribalda <ribalda@chromium.org> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Reviewed-by: Ricardo Ribalda <ribalda@chromium.org>
2024-06-17media: uvcvideo: Refactor Power Line Frequency limit selectionRicardo Ribalda
Move the PLF mapping logic to its own mapping filter function. This commit does not introduce any new functionality to the logic, it is just a preparation patch. Reviewed-by: Sergey Senozhatsky <senozhatsky@chromium.org> Signed-off-by: Ricardo Ribalda <ribalda@chromium.org> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Reviewed-by: Ricardo Ribalda <ribalda@chromium.org>
2024-06-17media: uvcvideo: Allow custom control mappingRicardo Ribalda
Some advanced controls might not be completely implemented by vendors. If the controls are a enumeration, UVC does not gives a way to probe what is implemented and what is not. Let's create a new callback function where heuristics can be implemented to detect what is implemented and what not and update the control mapping accordingly. Reviewed-by: Sergey Senozhatsky <senozhatsky@chromium.org> Signed-off-by: Ricardo Ribalda <ribalda@chromium.org> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Reviewed-by: Ricardo Ribalda <ribalda@chromium.org>
2024-06-17media: uvcvideo: Fix the bandwdith quirk on USB 3.xMichal Pecio
The bandwidth fixup quirk doesn't know that SuperSpeed exists and has the same 8 service intervals per millisecond as High Speed, hence its calculations are wrong. Assume that all speeds from HS up use 8 intervals per millisecond. No further changes are needed, updated code has been confirmed to work with all speeds from FS to SS. Signed-off-by: Michal Pecio <michal.pecio@gmail.com> Reviewed-by: Ricardo Ribalda <ribalda@chromium.org> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Link: https://lore.kernel.org/r/20240414190040.2255a0bc@foxbook Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
2024-06-17media: uvcvideo: Force UVC version to 1.0a for 0408:4035Laurent Pinchart
The Quanta ACER HD User Facing camera reports a UVC 1.50 version, but implements UVC 1.0a as shown by the UVC probe control being 26 bytes long. Force the UVC version for that device. Reported-by: Giuliano Lotta <giuliano.lotta@gmail.com> Closes: https://bugs.launchpad.net/ubuntu/+source/linux/+bug/2000947 Link: https://lore.kernel.org/r/20230115205210.20077-1-laurent.pinchart@ideasonboard.com Tested-by: Giuliano Lotta <giuliano.lotta@gmail.com> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
2024-06-17media: uvcvideo: Override default flagsDaniel Schaefer
When the UVC device has a control that is readonly it doesn't set the SET_CUR flag. For example the privacy control has SET_CUR flag set in the defaults in the `uvc_ctrls` variable. Even if the device does not have it set, it's not cleared by uvc_ctrl_get_flags(). Originally written with assignment in commit 859086ae3636 ("media: uvcvideo: Apply flags from device to actual properties"). But changed to |= in commit 0dc68cabdb62 ("media: uvcvideo: Prevent setting unavailable flags"). It would not clear the default flags. With this patch applied the correct flags are reported to user space. Tested with: ``` > v4l2-ctl --list-ctrls | grep privacy privacy 0x009a0910 (bool) : default=0 value=0 flags=read-only ``` Signed-off-by: Daniel Schaefer <dhs@frame.work> Fixes: 0dc68cabdb62 ("media: uvcvideo: Prevent setting unavailable flags") Reviewed-by: Ricardo Ribalda <ribalda@chromium.org> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Link: https://lore.kernel.org/r/20240602065053.36850-1-dhs@frame.work Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
2024-06-17media: uvcvideo: Enforce alignment of frame and intervalRicardo Ribalda
Struct uvc_frame and interval (u32*) are packaged together on streaming->formats on a single contiguous allocation. Right now they are allocated right after uvc_format, without taking into consideration their required alignment. This is working fine because both structures have a field with a pointer, but it will stop working when the sizeof() of any of those structs is not a multiple of the sizeof(void*). Enforce that alignment during the allocation. Signed-off-by: Ricardo Ribalda <ribalda@chromium.org> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Link: https://lore.kernel.org/r/20240404-uvc-align-v2-1-9e104b0ecfbd@chromium.org Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
2024-06-17media: uvcvideo: Add quirk for invalid dev_sof in Logitech C920Oleksandr Natalenko
Similarly to Logitech C922, C920 seems to also suffer from a firmware bug that breaks hardware timestamping. Add a quirk for this camera model too. Before applying the quirk: ``` 100 (4) [-] none 100 200717 B 212.919114 213.079004 33.727 fps ts mono/SoE 101 (5) [-] none 101 200889 B 213.003703 213.114996 11.822 fps ts mono/SoE 102 (6) [-] none 102 200926 B 213.035571 213.146999 31.379 fps ts mono/SoE 103 (7) [-] none 103 200839 B 213.067424 213.179003 31.394 fps ts mono/SoE 104 (0) [-] none 104 200692 B 213.293180 213.214991 4.430 fps ts mono/SoE 105 (1) [-] none 105 200937 B 213.322374 213.247001 34.254 fps ts mono/SoE 106 (2) [-] none 106 201013 B 213.352228 213.279005 33.496 fps ts mono/SoE … ``` After applying the quirk: ``` 154 (2) [-] none 154 192417 B 42.199823 42.207788 27.779 fps ts mono/SoE 155 (3) [-] none 155 192040 B 42.231834 42.239791 31.239 fps ts mono/SoE 156 (4) [-] none 156 192213 B 42.263823 42.271822 31.261 fps ts mono/SoE 157 (5) [-] none 157 191981 B 42.299824 42.303827 27.777 fps ts mono/SoE 158 (6) [-] none 158 191953 B 42.331835 42.339811 31.239 fps ts mono/SoE 159 (7) [-] none 159 191904 B 42.363824 42.371813 31.261 fps ts mono/SoE 160 (0) [-] none 160 192210 B 42.399834 42.407801 27.770 fps ts mono/SoE ``` Fixes: 5d0fd3c806b9 ("[media] uvcvideo: Disable hardware timestamps by default") Signed-off-by: Oleksandr Natalenko <oleksandr@natalenko.name> Reviewed-by: Ricardo Ribalda <ribalda@chromium.org> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Link: https://lore.kernel.org/r/20240325142611.15550-1-oleksandr@natalenko.name Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
2024-06-17media: uvcvideo: Fix integer overflow calculating timestampRicardo Ribalda
The function uvc_video_clock_update() supports a single SOF overflow. Or in other words, the maximum difference between the first ant the last timestamp can be 4096 ticks or 4.096 seconds. This results in a maximum value for y2 of: 0x12FBECA00, that overflows 32bits. y2 = (u32)ktime_to_ns(ktime_sub(last->host_time, first->host_time)) + y1; Extend the size of y2 to u64 to support all its values. Without this patch: # yavta -s 1920x1080 -f YUYV -t 1/5 -c /dev/video0 Device /dev/v4l/by-id/usb-Shine-Optics_Integrated_Camera_0001-video-index0 opened. Device `Integrated Camera: Integrated C' on `usb-0000:00:14.0-6' (driver 'uvcvideo') supports video, capture, without mplanes. Video format set: YUYV (56595559) 1920x1080 (stride 3840) field none buffer size 4147200 Video format: YUYV (56595559) 1920x1080 (stride 3840) field none buffer size 4147200 Current frame rate: 1/5 Setting frame rate to: 1/5 Frame rate set: 1/5 8 buffers requested. length: 4147200 offset: 0 timestamp type/source: mono/SoE Buffer 0/0 mapped at address 0x7947ea94c000. length: 4147200 offset: 4149248 timestamp type/source: mono/SoE Buffer 1/0 mapped at address 0x7947ea557000. length: 4147200 offset: 8298496 timestamp type/source: mono/SoE Buffer 2/0 mapped at address 0x7947ea162000. length: 4147200 offset: 12447744 timestamp type/source: mono/SoE Buffer 3/0 mapped at address 0x7947e9d6d000. length: 4147200 offset: 16596992 timestamp type/source: mono/SoE Buffer 4/0 mapped at address 0x7947e9978000. length: 4147200 offset: 20746240 timestamp type/source: mono/SoE Buffer 5/0 mapped at address 0x7947e9583000. length: 4147200 offset: 24895488 timestamp type/source: mono/SoE Buffer 6/0 mapped at address 0x7947e918e000. length: 4147200 offset: 29044736 timestamp type/source: mono/SoE Buffer 7/0 mapped at address 0x7947e8d99000. 0 (0) [-] none 0 4147200 B 507.554210 508.874282 242.836 fps ts mono/SoE 1 (1) [-] none 2 4147200 B 508.886298 509.074289 0.751 fps ts mono/SoE 2 (2) [-] none 3 4147200 B 509.076362 509.274307 5.261 fps ts mono/SoE 3 (3) [-] none 4 4147200 B 509.276371 509.474336 5.000 fps ts mono/SoE 4 (4) [-] none 5 4147200 B 509.476394 509.674394 4.999 fps ts mono/SoE 5 (5) [-] none 6 4147200 B 509.676506 509.874345 4.997 fps ts mono/SoE 6 (6) [-] none 7 4147200 B 509.876430 510.074370 5.002 fps ts mono/SoE 7 (7) [-] none 8 4147200 B 510.076434 510.274365 5.000 fps ts mono/SoE 8 (0) [-] none 9 4147200 B 510.276421 510.474333 5.000 fps ts mono/SoE 9 (1) [-] none 10 4147200 B 510.476391 510.674429 5.001 fps ts mono/SoE 10 (2) [-] none 11 4147200 B 510.676434 510.874283 4.999 fps ts mono/SoE 11 (3) [-] none 12 4147200 B 510.886264 511.074349 4.766 fps ts mono/SoE 12 (4) [-] none 13 4147200 B 511.070577 511.274304 5.426 fps ts mono/SoE 13 (5) [-] none 14 4147200 B 511.286249 511.474301 4.637 fps ts mono/SoE 14 (6) [-] none 15 4147200 B 511.470542 511.674251 5.426 fps ts mono/SoE 15 (7) [-] none 16 4147200 B 511.672651 511.874337 4.948 fps ts mono/SoE 16 (0) [-] none 17 4147200 B 511.873988 512.074462 4.967 fps ts mono/SoE 17 (1) [-] none 18 4147200 B 512.075982 512.278296 4.951 fps ts mono/SoE 18 (2) [-] none 19 4147200 B 512.282631 512.482423 4.839 fps ts mono/SoE 19 (3) [-] none 20 4147200 B 518.986637 512.686333 0.149 fps ts mono/SoE 20 (4) [-] none 21 4147200 B 518.342709 512.886386 -1.553 fps ts mono/SoE 21 (5) [-] none 22 4147200 B 517.909812 513.090360 -2.310 fps ts mono/SoE 22 (6) [-] none 23 4147200 B 517.590775 513.294454 -3.134 fps ts mono/SoE 23 (7) [-] none 24 4147200 B 513.298465 513.494335 -0.233 fps ts mono/SoE 24 (0) [-] none 25 4147200 B 513.510273 513.698375 4.721 fps ts mono/SoE 25 (1) [-] none 26 4147200 B 513.698904 513.902327 5.301 fps ts mono/SoE 26 (2) [-] none 27 4147200 B 513.895971 514.102348 5.074 fps ts mono/SoE 27 (3) [-] none 28 4147200 B 514.099091 514.306337 4.923 fps ts mono/SoE 28 (4) [-] none 29 4147200 B 514.310348 514.510567 4.734 fps ts mono/SoE 29 (5) [-] none 30 4147200 B 514.509295 514.710367 5.026 fps ts mono/SoE 30 (6) [-] none 31 4147200 B 521.532513 514.914398 0.142 fps ts mono/SoE 31 (7) [-] none 32 4147200 B 520.885277 515.118385 -1.545 fps ts mono/SoE 32 (0) [-] none 33 4147200 B 520.411140 515.318336 -2.109 fps ts mono/SoE 33 (1) [-] none 34 4147200 B 515.325425 515.522278 -0.197 fps ts mono/SoE 34 (2) [-] none 35 4147200 B 515.538276 515.726423 4.698 fps ts mono/SoE 35 (3) [-] none 36 4147200 B 515.720767 515.930373 5.480 fps ts mono/SoE Cc: stable@vger.kernel.org Fixes: 66847ef013cc ("[media] uvcvideo: Add UVC timestamps support") Signed-off-by: Ricardo Ribalda <ribalda@chromium.org> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Link: https://lore.kernel.org/r/20240610-hwtimestamp-followup-v1-2-f9eaed7be7f0@chromium.org Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
2024-06-17media: uvcvideo: Fix hw timestamp handling for slow FPSRicardo Ribalda
In UVC 1.5 we get a single clock value per frame. With the current buffer size of 32, FPS slowers than 32 might roll-over twice. The current code cannot handle two roll-over and provide invalid timestamps. Revome all the samples from the circular buffer that are more than two rollovers old, so the algorithm always provides good timestamps. Note that we are removing values that are more than one second old, which means that there is enough distance between the two points that we use for the interpolation to provide good values. Tested-by: HungNien Chen <hn.chen@sunplusit.com> Reviewed-by: Sergey Senozhatsky <senozhatsky@chromium.org> Reviewed-by: Tomasz Figa <tfiga@chromium.org> Signed-off-by: Ricardo Ribalda <ribalda@chromium.org> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Link: https://lore.kernel.org/r/20240610-hwtimestamp-followup-v1-1-f9eaed7be7f0@chromium.org Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
2024-06-17media: uvcvideo: Refactor clock circular bufferRicardo Ribalda
Isolate all the changes related to the clock circular buffer to its own function, that way we can make changes easier to the buffer logic. Also simplify the lock, by removing the circular buffer clock handling from uvc_video_clock_decode(). And now that we are at it, unify the API of the clock functions. Tested-by: HungNien Chen <hn.chen@sunplusit.com> Reviewed-by: Sergey Senozhatsky <senozhatsky@chromium.org> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Signed-off-by: Ricardo Ribalda <ribalda@chromium.org> Reviewed-by: Tomasz Figa <tfiga@chromium.org> Link: https://lore.kernel.org/r/20240323-resend-hwtimestamp-v10-5-b08e590d97c7@chromium.org Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
2024-06-17media: uvcvideo: Allow hw clock updates with buffers not fullRicardo Ribalda
With UVC 1.5 we get as little as one clock sample per frame. Which means that it takes 32 frames to move from the software timestamp to the hardware timestamp method. This results in abrupt changes in the timestamping after 32 frames (~1 second), resulting in noticeable artifacts when used for encoding. With this patch we modify the update algorithm to work with whatever amount of values are available. Tested-by: HungNien Chen <hn.chen@sunplusit.com> Reviewed-by: Sergey Senozhatsky <senozhatsky@chromium.org> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Signed-off-by: Ricardo Ribalda <ribalda@chromium.org> Reviewed-by: Tomasz Figa <tfiga@chromium.org> Link: https://lore.kernel.org/r/20240323-resend-hwtimestamp-v10-4-b08e590d97c7@chromium.org Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
2024-06-17media: uvcvideo: Quirk for invalid dev_sof in Logitech C922Ricardo Ribalda
Logitech C922 internal SOF does not increases at a stable rate of 1kHz. This causes that the device_sof and the host_sof run at different rates, breaking the clock domain conversion algorithm. Eg: 30 (6) [-] none 30 614400 B 21.245557 21.395214 34.133 fps ts mono/SoE 31 (7) [-] none 31 614400 B 21.275327 21.427246 33.591 fps ts mono/SoE 32 (0) [-] none 32 614400 B 21.304739 21.459256 34.000 fps ts mono/SoE 33 (1) [-] none 33 614400 B 21.334324 21.495274 33.801 fps ts mono/SoE * 34 (2) [-] none 34 614400 B 21.529237 21.527297 5.130 fps ts mono/SoE * 35 (3) [-] none 35 614400 B 21.649416 21.559306 8.321 fps ts mono/SoE 36 (4) [-] none 36 614400 B 21.678789 21.595320 34.045 fps ts mono/SoE ... 99 (3) [-] none 99 614400 B 23.542226 23.696352 33.541 fps ts mono/SoE 100 (4) [-] none 100 614400 B 23.571578 23.728404 34.069 fps ts mono/SoE 101 (5) [-] none 101 614400 B 23.601425 23.760420 33.504 fps ts mono/SoE * 102 (6) [-] none 102 614400 B 23.798324 23.796428 5.079 fps ts mono/SoE * 103 (7) [-] none 103 614400 B 23.916271 23.828450 8.478 fps ts mono/SoE 104 (0) [-] none 104 614400 B 23.945720 23.860479 33.957 fps ts mono/SoE Instead of disabling completely the hardware timestamping for such hardware we take the assumption that the packet handling jitter is under 2ms and use the host_sof as dev_sof. We can think of the UVC hardware clock as a system with a coarse clock (the SOF) and a fine clock (the PTS). The coarse clock can be replaced with a clock on the same frequency, if the jitter of such clock is smaller than its sampling rate. That way we can save some of the precision of the fine clock. To probe this point we have run three experiments on the Logitech C922. On that experiment we run the camera at 33fps and we analyse the difference in msec between a frame and its predecessor. If we display the histogram of that value, a thinner histogram will mean a better meassurement. The results for: - original hw timestamp: https://ibb.co/D1HJJ4x - pure software timestamp: https://ibb.co/QC9MgVK - modified hw timestamp: https://ibb.co/8s9dBdk This bug in the camera firmware has been confirmed by the vendor. lsusb -v Bus 001 Device 044: ID 046d:085c Logitech, Inc. C922 Pro Stream Webcam Device Descriptor: bLength 18 bDescriptorType 1 bcdUSB 2.00 bDeviceClass 239 Miscellaneous Device bDeviceSubClass 2 bDeviceProtocol 1 Interface Association bMaxPacketSize0 64 idVendor 0x046d Logitech, Inc. idProduct 0x085c C922 Pro Stream Webcam bcdDevice 0.16 iManufacturer 0 iProduct 2 C922 Pro Stream Webcam iSerial 1 80B912DF bNumConfigurations 1 Reviewed-by: Sergey Senozhatsky <senozhatsky@chromium.org> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Signed-off-by: Ricardo Ribalda <ribalda@chromium.org> Reviewed-by: Ricardo Ribalda <ribalda@chromium.org> Signed-off-by: Oleksandr Natalenko <oleksandr@natalenko.name> Reviewed-by: Tomasz Figa <tfiga@chromium.org> Link: https://lore.kernel.org/r/20240323-resend-hwtimestamp-v10-3-b08e590d97c7@chromium.org Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
2024-06-17media: uvcvideo: Ignore empty TS packetsRicardo Ribalda
Some SunplusIT cameras took a borderline interpretation of the UVC 1.5 standard, and fill the PTS and SCR fields with invalid data if the package does not contain data. "STC must be captured when the first video data of a video frame is put on the USB bus." Some SunplusIT devices send, e.g., buffer: 0xa7755c00 len 000012 header:0x8c stc 00000000 sof 0000 pts 00000000 buffer: 0xa7755c00 len 000012 header:0x8c stc 00000000 sof 0000 pts 00000000 buffer: 0xa7755c00 len 000668 header:0x8c stc 73779dba sof 070c pts 7376d37a While the UVC specification meant that the first two packets shouldn't have had the SCR bit set in the header. This borderline/buggy interpretation has been implemented in a variety of devices, from directly SunplusIT and from other OEMs that rebrand SunplusIT products. So quirking based on VID:PID will be problematic. All the affected modules have the following extension unit: VideoControl Interface Descriptor: guidExtensionCode {82066163-7050-ab49-b8cc-b3855e8d221d} But the vendor plans to use that GUID in the future and fix the bug, this means that we should use heuristic to figure out the broken packets. This patch takes care of this. lsusb of one of the affected cameras: Bus 001 Device 003: ID 1bcf:2a01 Sunplus Innovation Technology Inc. Device Descriptor: bLength 18 bDescriptorType 1 bcdUSB 2.01 bDeviceClass 239 Miscellaneous Device bDeviceSubClass 2 ? bDeviceProtocol 1 Interface Association bMaxPacketSize0 64 idVendor 0x1bcf Sunplus Innovation Technology Inc. idProduct 0x2a01 bcdDevice 0.02 iManufacturer 1 SunplusIT Inc iProduct 2 HanChen Wise Camera iSerial 3 01.00.00 bNumConfigurations 1 Tested-by: HungNien Chen <hn.chen@sunplusit.com> Reviewed-by: Sergey Senozhatsky <senozhatsky@chromium.org> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Signed-off-by: Ricardo Ribalda <ribalda@chromium.org> Reviewed-by: Tomasz Figa <tfiga@chromium.org> Link: https://lore.kernel.org/r/20240323-resend-hwtimestamp-v10-2-b08e590d97c7@chromium.org Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
2024-06-17media: uvcvideo: Support timestamp lists of any sizeRicardo Ribalda
The tail of the list lives at the position before the head. This is mathematically noted as: ``` (head-1) mod size. ``` Unfortunately C, does not have a modulus operator, but a remainder operator (%). The reminder operation has a different result than the modulus if (head -1) is a negative number and size is not a power of two. Adding size to (head-1) allows the code to run with any value of size. This does not change the current behaviour of the driver, as the size is always a power of two, but avoid tedious debugging if we ever change its size. Reviewed-by: Sergey Senozhatsky <senozhatsky@chromium.org> Signed-off-by: Ricardo Ribalda <ribalda@chromium.org> Reviewed-by: Tomasz Figa <tfiga@chromium.org> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Link: https://lore.kernel.org/r/20240323-resend-hwtimestamp-v10-1-b08e590d97c7@chromium.org Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
2024-06-15media: v4l: add missing MODULE_DESCRIPTION() macrosJeff Johnson
make allmodconfig && make W=1 C=1 reports: WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/media/v4l2-core/v4l2-async.o WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/media/v4l2-core/v4l2-fwnode.o Add the missing invocations of the MODULE_DESCRIPTION() macro. Signed-off-by: Jeff Johnson <quic_jjohnson@quicinc.com> Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com> Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
2024-06-15media: i2c: ov5647: replacing of_node_put with __free(device_node)Abdulrasaq Lawani
Replace instance of of_node_put with __free(device_node) to protect against any memory leaks due to future changes in control flow. Signed-off-by: Abdulrasaq Lawani <abdulrasaqolawani@gmail.com> Acked-by: Dave Stevenson <dave.stevenson@raspberrypi.com> Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com> Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
2024-06-15media: i2c: vgxy61: Fix device nameBenjamin Mugnier
Rename 'st-vgxy61' to 'vgxy61', dropping the vendor prefix to follow the same naming scheme as the vast majority of device drivers. The device tree binding does not fall into binding rename exceptions and therefore must not be changed. Keep its legacy name. Signed-off-by: Benjamin Mugnier <benjamin.mugnier@foss.st.com> Acked-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org> Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com> Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>