public inbox for linux-media@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH v12 00/86] Generic line based metadata support, internal pads
@ 2026-04-09 20:13 Sakari Ailus
  2026-04-09 20:13 ` [PATCH v12 01/86] media: mc: Add INTERNAL pad flag Sakari Ailus
                   ` (85 more replies)
  0 siblings, 86 replies; 88+ messages in thread
From: Sakari Ailus @ 2026-04-09 20:13 UTC (permalink / raw)
  To: linux-media
  Cc: hans, laurent.pinchart, Prabhakar, Kate Hsuan, Dave Stevenson,
	Tommaso Merciai, Benjamin Mugnier, Sylvain Petinot,
	Christophe JAILLET, Julien Massot, Naushir Patuck, Stefan Klug,
	Mirela Rabulea, André Apitzsch, Heimir Thor Sverrisson,
	Kieran Bingham, Mehdi Djait, Ricardo Ribalda Delgado,
	Hans de Goede, Jacopo Mondi, Tomi Valkeinen, David Plowman,
	Yu, Ong Hock, Ng, Khai Wen, Jai Luthra, Rishikesh Donadkar

Hi folks,

Here are a few patches to add support generic, line based metadata as well
as internal pads, sub-device configuration models (including the common
raw sensor model) and a streaming control helper for MC-enabled drivers.
The amount of code and documentation is in this version is no longer small
but it still requires some explaining.

Metadata mbus codes and formats have existed for some time in V4L2. They
however have been only used by drivers that produce the data itself and
effectively this metadata has always been statistics of some sort (at
least when it comes to ISPs). What is different here is that we intend to
add support for metadata originating from camera sensors.

Camera sensors produce different kinds of metadata, embedded data (usually
register address--value pairs used to capture the frame, in a more or less
sensor specific format), histograms (in a very sensor specific format),
dark pixels etc. The number of these formats is probably going to be about
as large as image data formats if not larger, as the image data formats
are much better standardised but a smaller subset of them will be
supported by V4L2, at least initially but possibly much more in the long
run.

Having this many device specific formats would be a major problem for all
the other drivers along that pipeline (not to mention the users of those
drivers), including bridge (e.g. CSI-2 to parallel) but especially CSI-2
receiver drivers that have DMA: the poor driver developer would not only
need to know camera sensor specific formats but to choose the specific
packing of that format suitable for the DMA used by the hardware. It is
unlikely many of these would ever get tested while being present on the
driver API. Also adding new sensors with new embedded data formats would
involve updating all bridge and CSI-2 receiver drivers. I don't expect
this to be a workable approach.

Instead what I'm proposing is to use controls to convey the colour pattern
and metadata layout. Generic mbus codes convey the width of the data
transferred on serial buses (for now, corresponding parallel formats may
be added when needed) but the control is only relevant on the UAPI, not
between drivers. This approach unsnarls the layout of the data and its
colour components, defining what data there is (specific mbus code) and
how that is transported and packed (generic mbus codes and V4L2 formats)
separately.

The user space would be required to "know" the path of that data from the
sensor's internal pad to the V4L2 video node. I do not see this as these
devices require at least some knowledge of the pipeline, i.e. hardware at
hand. Separating what the data means and how it is packed may even be
beneficial: it allows separating code that interprets the data (sensor
internal mbus code) from the code that accesses it (packing).

These formats are in practice line based, meaning that there may be
padding at the end of the line, depending on the bus as well as the DMA.
If non-line based formats are needed, it is always possible to set the
"height" field to 1.

Internal sink pads behave mostly like regular sink pads, but they describe
a flow of data that originates from a sub-device instead of arriving to a
sub-device. The SUBDEV_S_ROUTING IOCTLs are used to enable and disable
routes from internal sink pads to sub-device's source pads. The subdev
format IOCTLs are usable, too, so one can find which subdev format is
available on given internal sink pad.

I've tested the patches using the IPU6 / ov2740 pair of drivers as well as
Unicam / imx219.

Questions and comments are most welcome.

Preliminary media-ctl and yavta patches can be found here:

<URL:https://git.retiisi.eu/?p=~sailus/yavta.git;a=shortlog;h=refs/heads/metadata>
<URL:https://git.retiisi.eu/?p=~sailus/v4l-utils.git;a=shortlog;h=refs/heads/metadata>

I have used IMX219 as an example on routing in a sensor driver in this
version.

The patches are on my metadata branch
<URL:https://git.linuxtv.org/sailus/media_tree.git/log/>.

These patches are on top of my metadata preparation set
<20260408153939.969381-1-sakari.ailus@linux.intel.com>, all of these can
be found in the GitWeb URL above.

The documentation build output can be found here:
<URL:https://www.retiisi.eu/~sailus/v4l2/tmp/common-raw/>.

since v11:

- Add a note (patch "media: Documentation: Add a note on Bayer raw mbus
  codes") to document the use of new generic raw formats

- Link to the LINK_FREQ control from the tx-rx driver documentation. 

- Refer to V4L2 fwnode endpoint parsing functions in tx-rx driver
  documentation.

- Rename V4L2_CID_COLOR_PATTERN as V4L2_CID_CFA_PATTERN. This matches
  better with the established use of the terms (CFA in particular).

- Improve and fix references in new camera sensor driver documentation.

- Improve and fix language regarding embedded data in camera sensor driver
  documentation.

- Improve language in routing documentation in dev-subdev.rst.

- Document the IMMUTABLE route flag in routing documentation.

- Add a note in routing documentation that a sub-device may have either
  user-created or static routes.

- Also use IMMUTABLE and STATIC flags in internal pads example.

- Elaborate image and metadata stream dependencies in imx219
  documentation.

- Don't mention selections in sub-device configuration documentation for
  internal pads.

- The source format of the camera sensor is configured using the source
  pad; document this in the Common raw sensor model.

- Move binning factors from camera controls class to image source class
  where they belong.

- Improve description of colour filter array patterns.

- Add that CFA_PATTERN_FLIP is a read-only control.

- Add references to metadata layouts into the metadata layout control.

- Refer to V4L2_METADATA_LAYOUT_OV2740 in ov2740 documentation (not
  V4L2_METADATA_LAYOUT_CCS).

- Note that ov2740 embedded data dpc correction threshold uses bits 9--2.

- Postpone adding 16 and higher bpp generic raw formats until we have a
  user (split into separate patches later in the set).

- Generic 16- and 24-bit format isn't really CSI-2 packed (but appears to
  be big endian) so rename the two accordingly.

- Small but numerous fixes in generic raw image data format documentation.

- Improve documentation of different parts of the pixel array and relation
  of that to the UAPI under common raw sensor model documentation.

- Reword documentation of the compose rectangle in common raw sensor
  model documentation.

- Add crop bounds rectangle to the common raw sensor model to convey the
  bounds of the pixel array. This allows using negative numbers as well.

- Document that the sensor's output format is configured on the source
  pad.

- Add references to relevant controls in generic raw format documentation.

- Introduce V4L2_SUBDEV_CLIENT_CAP_COMMON_RAW_SENSOR sub-device capability
  bit. This bit is set by the userspace to signal support for the common
  raw sensor model and allows supporting common raw sensor model also in
  existing drivers.

- Introduce the static route flag to indicate a route is always present.

- Add new struct v4l2_subdev_client_info as argument to certain pad
  operations in order to support passing information on client
  capabilities to sub-device drivers.

- Added common raw format support to the CCS driver.

- Drop leftover mutex_unlock() in ccs_set_format().

- Fully rely on sub-device state locking in the CCS driver.

- Make METADATA_LAYOUT control read-only.

- Add new controls FRAME_LENGTH_LINES and LINE_LENGTH_PIXELS.

- Don't handle the CFA pattern control in set_ctrl() -- ops is NULL.

- Support the common raw sensor model in imx219:

	- Add support for BINNING_FACTORS, FRAME_LENGTH_LINES and
	  LINE_LENGTH_PIXELS controls.

	- Support both Common Raw Sensor Model and old behaviour,
	  depending on V4L2_SUBDEV_CLIENT_CAP_COMMON_RAW_SENSOR bit. The
	  internal state is the same in both cases but the view to the
	  state and UAPI behaviour differs based on that bit.

	- Keep track of enabled streams; any started stream starts
	  streaming on the sensor.

	- Enumerate only generic raw mbus code on the internal image
	  source pad.

	- Support set_selection for setting analogue crop area.

	- Remove redundant comments in imx219_probe().

- Ipu6 driver changes:

	- Lots of cleanups.

	- Only start streaming on the upstream sub-device when all queues
	  in the pipeline have been set streaming.

	- Use VALIDATE_LATE link flag for links to video nodes.

	- Move streaming control to the CSI-2 driver. Streaming now starts
	  on the upstream sub-device once all participating video nodes
	  have been set streaming.

- Support generic raw formats in the unicam driver.

- Document that common raw sensor model requires implementing
  FRAME_LENGTH_LINES and LINE_LENGTH_PIXELS controls.

since v10:

- Merge a few patches that aren't strictly related to metadata, mostly
  documentation cleanups and improvements.

- Add V4L2_SUBDEV_ROUTE_FL_STATIC, to indicate a route is mutable but
  hardware specific so it remains even if disabled. An example of this are
  embedded data routes on camera sensors. IMMUTABLE implies STATIC.

- Postpone adding formats higher than 14 bpp and remove reference to
  "little endian" for the CSI-2 packed formats. It's not entirely clear
  how the data on higher bit depth formats are laid out in memory. The
  documentation suggests these are in big endian format but that would be
  impractical for CPU processing.

- Add references to controls in flipping documentation in
  subdev-formats.rst.

- Add -ENXIO return code for device specific invalid routing configuration
  and clarify routing error conditions for -EINVAL.

- Add braces for the case in imx219_enum_mbus_code() to make Clang happy.

- Rebase off of mc-streamon set (to my cleanup branch). The problem of
  when to stream on and off still needs to be addressed but I'm looking
  into a different, better integrated approach right now.

- Rename generic metadata formats at bit depths 16 and 24 as it seems
  these have more generic packing than CSI-2.

since v9:

- Introduce controls for sub-device configuration models (separately
  discussed in <20250203085853.1361401-1-sakari.ailus@linux.intel.com>),
  with the following changes:

	- Fix spelling and improve wording in documentation based on
	  comments.
	
	- Use US English spelling for V4L2 control names.
	
	- Allow for more than one internal pad for pixel data.
	
	- Introduce (or change a bit) generic mbus codes for raw pixel
	  data and metadata.
	
	- Introduce generic and CSI-2 specifc V4L2 pixelformats for image
	  data and metadata. Also 16- and 24-bit formats are generic, not
	  specific to CSI-2.

	- Introduce new controls to convey metadata layout on bus and by
	  extension, in memory, instead of relying on separate metadata
	  mbus codes, aligning with pixel data.

	- Use generic metadata codes in the example.

- Include imx219 embedded data support patches from Laurent, with
  modifications.

- Patches to IPU6 ISYS driver needed to support metadata capture. Luma
  formats added, too.

- Improved debug prints in v4l2_subdev_{en,dis}able_streams().

- Added a patch to make media_entity_to_video_device() NULL-safe.

- Drop _media-glossary-data-unit reference, use :term: to reference it.

- Include a patch to set IPU6 ISYS minimum height to 1.

- Patch 'media: uapi: Document which mbus format fields are valid for
  metadata' already merged.

- Patch 'media: uapi: v4l: Add generic 8-bit metadata format definitions'
  already merged.

- Patch 'media: v4l: Support line-based metadata capture' already merged.

- Patch 'media: Documentation: Document S_ROUTING behaviour' already merged.

- Patch 'media: v4l: subdev: Add len_routes field to struct
  v4l2_subdev_routing' already merged.

since v8:

- Move the patch adding internal pad flag past the routing API reworks, as
  well as a few other patches, in order to separate the patches to those
  that could still be merged for v6.10 (routing changes) and those that
  couldn't (sensor API related). The patch on the edge is "media: uapi:
  v4l: subdev: Enable streams API".

- Include Laurent's two patches to address crop API issues wrt. streams.

- Add two patches to prepare for CCS driver rework (media: ccs: Move
  ccs_pm_get_init function up and media: ccs: Rename out label of
  ccs_start_streaming).

- Address issues in the ov2740 driver patches (as well as the driver
  itself), 4 more patches towards the end of the set.

- Improved generic metadata format names, align with other existing
  formats.

- Improved ov2740 embedded data documentation.

- Reworked streams and camera sensor documentation based on Laurent's
  comments mainly. In particular, the contradictory concept of internal
  source pads no longer should exist in the patches.

- Fixed pad numbering in the CCS example.

- Fixed S_ROUTING behaviour when len_routes is too small and when
  S_ROUTING isn't implemented by the driver.

- Reorder sections in meta-formats.rst alphabetically.

- Add a note per struct fields that certain struct v4l2_subdev_format are
  zero for metadata mbus codes.

- CCS driver patch cleanups.

- CCS driver metadata width fix for space-efficient embedded data at 16
  bpp and over.

- Postpone CCS frame descriptor quirk for now.

- Use MIPI_CSI2_DT_USER_DEFINED(0) instead of a numerical value for
  compressed data datatype.

since v7:

- Add embedded data support for the ov2740 driver.

- Add three patches on top, to add an IMMUTABLE flag to source streams
  when they cannot be disabled.

- Improved documentation of len_routes and num_routes arguments of
  [GS]_ROUTING.

- Remove one inclusion of twice-included media/v4l2-fwnode.h in
  drivers/media/i2c/ccs/ccs-core.c .

- Add missing forward declaration of ccs_internal_ops in
  drivers/media/i2c/ccs/ccs-core.c .

since v6:

- Improve embedded data UAPI documentation on camera sensors.

- Improve wording of stream glossary entry.

- Improve internal pad flag documentation.

- Fix definition of "data unit" and remove an extra "only" in INTERNAL pad
  flag description (1st patch).

- Use IMX219 driver in examples consistently.

- Remove the CSI-2 to parallel bridge from the example to simplify the
  example.

- Minor rewording of some parts of the routing examples.

- Rebase on unified sub-device state information access functions:
  <URL:https://lore.kernel.org/linux-media/20231027095913.1010187-1-sakari.ailus@linux.intel.com/T/#t>

- In CCS driver, do not maintain current active configuration in driver's
  device context struct (apart from mbus codes). Rely on sub-device state
  locking and clean up the code. (Multiple patches towards the end of the
  set.)

- Arrange the CCS patches early in the set towards the end of the set.

- Move the patch enabling streams API to the end of the set.

- Rework IOCTL argument copying condition for [GS]_ROUTING).

- Handle copying back routes in S_ROUTING, do not rely on G_ROUTING
  IOCTL implementation.

- Rebase on metadata preparation patchset v6:
  <URL:https://lore.kernel.org/linux-media/20231106121805.1266696-1-sakari.ailus@linux.intel.com/T/#t>.

since v5:

- Rebase on new set of preparation patches.

- Switch CCS driver from s_stream to enable_streams/disable_streams. Keep
  streaming state information --- the sensor remains in streaming state if
  any of the streams is enabled.

- Fix setting mbus code on embedded data in get_frame_desc() op in the CCS
  driver.

since v4:

- Add a patch to acquire two sub-device states that may use the same lock.

- Add a patch for CCS driver to remove ccs_get_crop_compose() helper.

- Add a patch for CCS driver moving acquiring and releasing the mutex to
  the s_stream callback.

- Add a patch for CCS driver to rely on sub-device state locking using a
  single driver-provided lock.

- Fixed calculating minimum number of routes in copying the routes
  (thanks, Laurent).

- Moved a label in S_ROUTING handling to make Clang happy (hopefully).

- Fixed setting emb_data_ctrl register for CCS embedded data support.

- Rebase on Laurent's cleanup patches.

- Wrap a few long lines.

- Write in embedded data documentation sensor drivers generally don't
  allow configuring it.

since v3:

- Separate preparation patches from this set.

- Add a definition for "Data unit", a pixel that is not image data and use
  it instead in format documentation.

- Fix more numbered lists in dev-subdev.rst.

- Remove a redundant definition for V4L2_META_FMT_GENERIC_CSI2_2_24 ---
  V4L2_META_FMT_GENERIC_CSI2_12 can be used instead.

- Use "X" instead of "p" to denote padding in format documentation.

- Use IMX219 in examples instead of CCS.

- Document that the generic V4L2 CSI-2 metadata formats use padding
  defined in CSI-2 spec and packing defined in CCS spec.

- Add patches to align [GS]_ROUTING behaviour with V4L2. This means mainly
  returning configured routes as part of S_ROUTING as well. "len_routes"
  field is added to denote the length of the array and having more routes
  than fits in the array is no longer an error. Also added more reserved
  fields.

- Added trivial support for S_ROUTING (via G_ROUTING implementation) for
  use in drivers with static-only routes.

- Added helper functions to obtain mbus format as well as crop and compose
  rectangles that are streams-independent.

- Added a patch to define generic CSI-2 long packet types.

- Removed MEDIA_BUS_FMT_IS_META() macro. It didn't seem useful in the end.

- Use a single CCS embedded data format. The bit depth can be selected
  using the meta stream on the source pad.

- Fix mbus code numbers (there were holes due to removed redundant
  formats).

- Fix generic mbus code documentation (byte was being used instead of
  bit).

- Fix spelling of "length".

- Added a patch to remove v4l2_subdev_enable_streams_api that disables
  streams API. This should be merged once libcamera support for streams
  works nicely.

- Don't use strings in printing frame descriptor flags.

- Warn on string truncation in printing frame descriptor.

since v2:

- Add a better example, with formats.

- Add CCS static data media bus codes.

- Added an example demonstrating the use of internal pads. --- Is the
  level of detail enough for the purpose?

- Improved documentation.

- Added a macro to tell whether a format is a metadata format.
  (Documentation could be added.)

- A small ReST syntax fix in the same section.

- Drop leftovers of a patch checking for the INTERNAL_SOURCE flag.

since v1:

- Make the new pad flag just "INTERNAL", requiring either SINK or SOURCE
  pad flag to accompany it. Removed the union in struct v4l2_subdev_route.

- Add the term "stream" to MC glossary.

- Improved and fixed documentation (according to comments).

- Note these formats are little endian.

- Remove 1X8 from the names of the mbus codes. These formats have generally
  8 bits per pixel.

- Fix mbus code numbering (had holes in RFC).

- Add new metadata fields to debug prints.

- Fix a minor documentation build issue.

Laurent Pinchart (4):
  media: imx219: Add image stream
  media: imx219: Report internal routes to userspace
  media: imx219: Report streams using frame descriptors
  media: imx219: Add embedded data support

Sakari Ailus (82):
  media: mc: Add INTERNAL pad flag
  media: uapi: Add generic CSI-2 raw pixelformats
  media: uapi: Add new media bus codes for generic raw formats
  media: uapi: Add V4L2_CID_CONFIG_MODEL control
  media: uapi: Add V4L2_CID_CFA_PATTERN for describing color patterns
  media: Documentation: Reference CFA pattern control in pixelformat
    docs
  media: Documentation: Reference CFA_PATTERN control in raw mbus docs
  media: v4l: uapi: Add a control for color pattern flipping effect
  media: Documentation: Reference flipping controls in raw format docs
  media: Documentation: Document raw mbus codes and CFA for cameras
  media: uapi: Add V4L2_CID_METADATA_LAYOUT control
  media: Documentation: Refer to metadata layout in metadata
    documentation
  media: Documentation: v4l: Document internal sink pads
  media: Documentation: Document embedded data guidelines for camera
    sensors
  media: Documentation: Document non-CCS use of CCS embedded data layout
  media: uapi: Correct generic CSI-2 metadata format 4cc
  Revert "media: uapi: v4l: Don't expose generic metadata formats to
    userspace"
  media: v4l: Add V4L2_SUBDEV_ROUTE_FL_IMMUTABLE sub-device routing flag
  media: v4l: Add V4L2_SUBDEV_ROUTE_FL_STATIC sub-device routing flag
  media: Documentation: There are either immutable or mutable routes
  media: Documentation: Document IMMUTABLE and STATIC route flags
  media: Documentation: Add subdev configuration models, raw sensor
    model
  media: v4l2-subdev: Prevent accessing internal pads without STREAMS
    cap
  media: Documentation: Add scaling and post-scaler crop for common raw
  media: uapi: Add MIPI CCS configuration model
  media: uapi: Add V4L2_SUBDEV_CLIENT_CAP_COMMON_RAW_SENSOR
  media: uapi: Add V4L2_CID_BINNING control for binning configuration
  media: uapi: Add controls for sub-sampling configuration
  media: v4l2-mc: Add v4l2_subdev_sensor_fll_llp_set()
  media: Documentation: Add binning and sub-sampling controls
  media: v4l2-subdev: Set STATIC route flag if IMMUTABLE route flag is
    set
  media: uapi: v4l: subdev: Enable streams API
  media: uapi: Add new controls for camera sensor FLL and LLP
  media: uapi: Add binning factor helper macros
  media: Documentation: Document frame controls for common raw sensor
    model
  media: v4l2-ctrl: Improve v4l2_ctrl_g_ctrl{,int64} documentation
  media: Documentation: Add sub-device internal pads example
  media: Documentation: Document streaming behaviour for common raw
    cameras
  media: Documentation: Add a note on Bayer raw mbus codes
  media: v4l2-subdev: Add generic raw formats to
    v4l2_subdev_get_frame_desc
  media: uapi: Add generic CSI-2 raw pixelformats for 16, 20, 24 and 28
    bpp
  media: uapi: Add more media bus codes for generic raw formats
  media: uapi: ccs: Add metadata layout for MIPI CCS embedded data
  media: ccs: Add support for generic raw mbus codes
  media: ccs: Add support for embedded data stream
  media: Documentation: ccs: Document routing
  media: ccs: Add IMMUTABLE and STATIC route flags
  media: uapi: Add metadata layout for ov2740 embedded data
  media: ov2740: Add support for embedded data
  media: ov2740: Add support for generic raw formats
  media: ov2740: Add metadata layout control
  media: ov2740: Add support for G_SELECTION IOCTL
  media: ov2740: Add support for FLL and LLP controls
  media: ov2740: Signal common raw sensor model support
  media: ov2740: Add IMMUTABLE and STATIC route flags
  media: imx219: Add internal pads, routes for common raw sensor model
  media: imx219: Add support for generic raw formats
  media: imx219: Add V4L2_CID_BINNING_FACTORS
  media: imx219: Allow configuring cropping and binning through CRSM
  media: imx219: Support LINE_LENGTH_PIXELS and FRAME_LENGTH_LINES
    controls
  media: ipu6: Add support for raw CFA-agnostic formats
  media: ipu6: Use VALIDATE_LATE flag to postpone V4L2 format validation
  media: ipu6: Move streaming control to CSI-2 receiver driver
  media: ipu6: Stream number on CSI-2 receiver source pads is always 0
  media: ipu6: Rename misnamed out_free_watermark label in video init
  media: ipu6: Always request a capture ack
  media: ipu6: Clean up link frequency calculation
  media: ipu6: Get watermark configuration directly from ipdata
  media: ipu6: Collect IPU streams into CSI-2 receiver sub-device
    context
  media: ipu6: Start streaming once all queues have started, stop when
    not
  media: ipu6: Add lockdep checks for CSI-2 streaming enable and disable
  media: ipu6: Remove nr_queues and nr_streaming fields in
    ipu6_isys_stream
  media: ipu6: Collect enabled stream IDs
  media: ipu6: Avoid accessing av->streams before streaming
  media: ipu6: Rework watermark calculation
  media: ipu6: Rework watermark setting
  media: ipu6: Bridge the gap between streams in V4L2 and IPU6 firmware
  media: ipu6: Drop {get,put}_streams_opened()
  media: ipu6: Serialise access to stream pointers by isys stream_lock
  media: ipu6: Move firmware init/cleanup to RPM callbacks
  media: ipu6: Don't track power status, rely on runtime PM
  media: bcm2835-unicam: Support generic raw formats

 .../driver-api/media/camera-sensor.rst        |  11 +
 .../media/drivers/camera-sensor.rst           |  79 ++
 .../userspace-api/media/drivers/ccs.rst       |  43 +-
 .../media/mediactl/media-types.rst            |   8 +
 .../media/v4l/common-raw-sensor.dia           | 442 ++++++++++
 .../media/v4l/common-raw-sensor.svg           | 134 +++
 .../userspace-api/media/v4l/dev-subdev.rst    | 178 +++-
 .../media/v4l/ext-ctrls-image-process.rst     |   6 +
 .../media/v4l/ext-ctrls-image-source.rst      | 133 +++
 .../userspace-api/media/v4l/meta-formats.rst  |   1 +
 .../media/v4l/metadata-layouts.rst            | 114 +++
 .../media/v4l/metafmt-generic.rst             |  48 +-
 .../media/v4l/pixfmt-raw-generic.rst          | 383 +++++++++
 .../userspace-api/media/v4l/pixfmt.rst        |   1 +
 .../media/v4l/subdev-config-model.rst         | 301 +++++++
 .../media/v4l/subdev-formats.rst              |  48 ++
 .../media/v4l/vidioc-subdev-g-client-cap.rst  |   6 +
 .../media/v4l/vidioc-subdev-g-routing.rst     |   9 +
 drivers/media/i2c/ccs/ccs-core.c              | 398 ++++++++-
 drivers/media/i2c/ccs/ccs.h                   |  17 +-
 drivers/media/i2c/imx219.c                    | 797 +++++++++++++++---
 drivers/media/i2c/ov2740.c                    | 379 +++++++--
 drivers/media/mc/mc-entity.c                  |  15 +-
 drivers/media/pci/intel/ipu6/ipu6-fw-isys.c   |   5 -
 drivers/media/pci/intel/ipu6/ipu6-isys-csi2.c | 269 ++++--
 drivers/media/pci/intel/ipu6/ipu6-isys-csi2.h |   9 +
 .../media/pci/intel/ipu6/ipu6-isys-queue.c    | 125 +--
 .../media/pci/intel/ipu6/ipu6-isys-queue.h    |   2 +
 .../media/pci/intel/ipu6/ipu6-isys-subdev.c   |  25 +-
 .../media/pci/intel/ipu6/ipu6-isys-subdev.h   |   2 +
 .../media/pci/intel/ipu6/ipu6-isys-video.c    | 707 +++++-----------
 .../media/pci/intel/ipu6/ipu6-isys-video.h    |  42 +-
 drivers/media/pci/intel/ipu6/ipu6-isys.c      | 261 +++---
 drivers/media/pci/intel/ipu6/ipu6-isys.h      |  50 +-
 .../media/platform/broadcom/bcm2835-unicam.c  |  27 +
 drivers/media/v4l2-core/v4l2-ctrls-defs.c     |  21 +
 drivers/media/v4l2-core/v4l2-ioctl.c          |  16 +-
 drivers/media/v4l2-core/v4l2-mc.c             |  67 ++
 drivers/media/v4l2-core/v4l2-subdev.c         |  83 +-
 include/media/v4l2-ctrls.h                    |   4 +
 include/media/v4l2-mc.h                       |   8 +
 include/uapi/linux/media-bus-format.h         |  10 +
 include/uapi/linux/media.h                    |   1 +
 include/uapi/linux/v4l2-controls.h            |  33 +
 include/uapi/linux/v4l2-subdev.h              |  15 +
 include/uapi/linux/videodev2.h                |  24 +-
 46 files changed, 4165 insertions(+), 1192 deletions(-)
 create mode 100644 Documentation/userspace-api/media/v4l/common-raw-sensor.dia
 create mode 100644 Documentation/userspace-api/media/v4l/common-raw-sensor.svg
 create mode 100644 Documentation/userspace-api/media/v4l/metadata-layouts.rst
 create mode 100644 Documentation/userspace-api/media/v4l/pixfmt-raw-generic.rst
 create mode 100644 Documentation/userspace-api/media/v4l/subdev-config-model.rst


base-commit: 1921001887975f465397b3b5ed2535114d9a475c
-- 
2.47.3


^ permalink raw reply	[flat|nested] 88+ messages in thread

* [PATCH v12 01/86] media: mc: Add INTERNAL pad flag
  2026-04-09 20:13 [PATCH v12 00/86] Generic line based metadata support, internal pads Sakari Ailus
@ 2026-04-09 20:13 ` Sakari Ailus
  2026-04-09 20:13 ` [PATCH v12 02/86] media: uapi: Add generic CSI-2 raw pixelformats Sakari Ailus
                   ` (84 subsequent siblings)
  85 siblings, 0 replies; 88+ messages in thread
From: Sakari Ailus @ 2026-04-09 20:13 UTC (permalink / raw)
  To: linux-media
  Cc: hans, laurent.pinchart, Prabhakar, Kate Hsuan, Dave Stevenson,
	Tommaso Merciai, Benjamin Mugnier, Sylvain Petinot,
	Christophe JAILLET, Julien Massot, Naushir Patuck, Stefan Klug,
	Mirela Rabulea, André Apitzsch, Heimir Thor Sverrisson,
	Kieran Bingham, Mehdi Djait, Ricardo Ribalda Delgado,
	Hans de Goede, Jacopo Mondi, Tomi Valkeinen, David Plowman,
	Yu, Ong Hock, Ng, Khai Wen, Jai Luthra, Rishikesh Donadkar

Internal sink pads will be used as routing endpoints in V4L2 [GS]_ROUTING
IOCTLs, to indicate that the stream begins in the entity. Internal sink
pads are pads that have both SINK and INTERNAL flags set.

Also prevent creating links to pads that have been flagged as internal and
initialising SOURCE pads with INTERNAL flag set.

Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
Reviewed-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Reviewed-by: Mirela Rabulea <mirela.rabulea@nxp.com>
---
 .../userspace-api/media/mediactl/media-types.rst  |  8 ++++++++
 drivers/media/mc/mc-entity.c                      | 15 ++++++++++++---
 include/uapi/linux/media.h                        |  1 +
 3 files changed, 21 insertions(+), 3 deletions(-)

diff --git a/Documentation/userspace-api/media/mediactl/media-types.rst b/Documentation/userspace-api/media/mediactl/media-types.rst
index d6a690655a01..032f55ea0b33 100644
--- a/Documentation/userspace-api/media/mediactl/media-types.rst
+++ b/Documentation/userspace-api/media/mediactl/media-types.rst
@@ -361,6 +361,7 @@ Types and flags used to represent the media graph elements
 .. _MEDIA-PAD-FL-SINK:
 .. _MEDIA-PAD-FL-SOURCE:
 .. _MEDIA-PAD-FL-MUST-CONNECT:
+.. _MEDIA-PAD-FL-INTERNAL:
 
 .. flat-table:: Media pad flags
     :header-rows:  0
@@ -381,6 +382,13 @@ Types and flags used to represent the media graph elements
 	  enabled links even when this flag isn't set; the absence of the flag
 	  doesn't imply there is none.
 
+    *  -  ``MEDIA_PAD_FL_INTERNAL``
+       -  The internal flag indicates an internal pad that has no external
+	  connections. As they are internal to entities, internal pads shall not
+	  be connected with links.
+
+	  The internal flag may currently be present only in a sink pad where it
+	  indicates that the :term:`Stream` originates from within the entity.
 
 One and only one of ``MEDIA_PAD_FL_SINK`` and ``MEDIA_PAD_FL_SOURCE``
 must be set for every pad.
diff --git a/drivers/media/mc/mc-entity.c b/drivers/media/mc/mc-entity.c
index 5b0162f81425..0373ca7afc16 100644
--- a/drivers/media/mc/mc-entity.c
+++ b/drivers/media/mc/mc-entity.c
@@ -209,11 +209,16 @@ int media_entity_pads_init(struct media_entity *entity, u16 num_pads,
 		mutex_lock(&mdev->graph_mutex);
 
 	media_entity_for_each_pad(entity, iter) {
+		const u32 pad_flags = iter->flags & (MEDIA_PAD_FL_SINK |
+						     MEDIA_PAD_FL_SOURCE |
+						     MEDIA_PAD_FL_INTERNAL);
+
 		iter->entity = entity;
 		iter->index = i++;
 
-		if (hweight32(iter->flags & (MEDIA_PAD_FL_SINK |
-					     MEDIA_PAD_FL_SOURCE)) != 1) {
+		if (pad_flags != MEDIA_PAD_FL_SINK &&
+		    pad_flags != (MEDIA_PAD_FL_SINK | MEDIA_PAD_FL_INTERNAL) &&
+		    pad_flags != MEDIA_PAD_FL_SOURCE) {
 			ret = -EINVAL;
 			break;
 		}
@@ -1174,7 +1179,8 @@ int media_get_pad_index(struct media_entity *entity, u32 pad_type,
 
 	for (i = 0; i < entity->num_pads; i++) {
 		if ((entity->pads[i].flags &
-		     (MEDIA_PAD_FL_SINK | MEDIA_PAD_FL_SOURCE)) != pad_type)
+		     (MEDIA_PAD_FL_SINK | MEDIA_PAD_FL_SOURCE |
+		      MEDIA_PAD_FL_INTERNAL)) != pad_type)
 			continue;
 
 		if (entity->pads[i].sig_type == sig_type)
@@ -1204,6 +1210,9 @@ media_create_pad_link(struct media_entity *source, u16 source_pad,
 		return -EINVAL;
 	if (WARN_ON(!(sink->pads[sink_pad].flags & MEDIA_PAD_FL_SINK)))
 		return -EINVAL;
+	if (WARN_ON(source->pads[source_pad].flags & MEDIA_PAD_FL_INTERNAL) ||
+	    WARN_ON(sink->pads[sink_pad].flags & MEDIA_PAD_FL_INTERNAL))
+		return -EINVAL;
 
 	/*
 	 * With the late validate flag, either source or sink shall have exactly
diff --git a/include/uapi/linux/media.h b/include/uapi/linux/media.h
index c96e2118ea99..39e0a778edb5 100644
--- a/include/uapi/linux/media.h
+++ b/include/uapi/linux/media.h
@@ -208,6 +208,7 @@ struct media_entity_desc {
 #define MEDIA_PAD_FL_SINK			(1U << 0)
 #define MEDIA_PAD_FL_SOURCE			(1U << 1)
 #define MEDIA_PAD_FL_MUST_CONNECT		(1U << 2)
+#define MEDIA_PAD_FL_INTERNAL			(1U << 3)
 
 struct media_pad_desc {
 	__u32 entity;		/* entity ID */
-- 
2.47.3


^ permalink raw reply related	[flat|nested] 88+ messages in thread

* [PATCH v12 02/86] media: uapi: Add generic CSI-2 raw pixelformats
  2026-04-09 20:13 [PATCH v12 00/86] Generic line based metadata support, internal pads Sakari Ailus
  2026-04-09 20:13 ` [PATCH v12 01/86] media: mc: Add INTERNAL pad flag Sakari Ailus
@ 2026-04-09 20:13 ` Sakari Ailus
  2026-04-09 20:13 ` [PATCH v12 03/86] media: uapi: Add new media bus codes for generic raw formats Sakari Ailus
                   ` (83 subsequent siblings)
  85 siblings, 0 replies; 88+ messages in thread
From: Sakari Ailus @ 2026-04-09 20:13 UTC (permalink / raw)
  To: linux-media
  Cc: hans, laurent.pinchart, Prabhakar, Kate Hsuan, Dave Stevenson,
	Tommaso Merciai, Benjamin Mugnier, Sylvain Petinot,
	Christophe JAILLET, Julien Massot, Naushir Patuck, Stefan Klug,
	Mirela Rabulea, André Apitzsch, Heimir Thor Sverrisson,
	Kieran Bingham, Mehdi Djait, Ricardo Ribalda Delgado,
	Hans de Goede, Jacopo Mondi, Tomi Valkeinen, David Plowman,
	Yu, Ong Hock, Ng, Khai Wen, Jai Luthra, Rishikesh Donadkar

Add generic raw pixelformats for bit depths 8, 10, 12 and 14. These
formats are CSI-2 packed, apart from the 8-bit format.

Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
Reviewed-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 .../media/v4l/pixfmt-raw-generic.rst          | 175 ++++++++++++++++++
 .../userspace-api/media/v4l/pixfmt.rst        |   1 +
 drivers/media/v4l2-core/v4l2-ioctl.c          |   4 +
 include/uapi/linux/videodev2.h                |   6 +
 4 files changed, 186 insertions(+)
 create mode 100644 Documentation/userspace-api/media/v4l/pixfmt-raw-generic.rst

diff --git a/Documentation/userspace-api/media/v4l/pixfmt-raw-generic.rst b/Documentation/userspace-api/media/v4l/pixfmt-raw-generic.rst
new file mode 100644
index 000000000000..254f8f18c7c5
--- /dev/null
+++ b/Documentation/userspace-api/media/v4l/pixfmt-raw-generic.rst
@@ -0,0 +1,175 @@
+.. SPDX-License-Identifier: GPL-2.0 OR GFDL-1.1-no-invariants-or-later
+
+************************************************************************************************************************************
+V4L2_PIX_FMT_RAW_8 ('RAW8'), V4L2_PIX_FMT_RAW_CSI2_10 ('RACA'), V4L2_PIX_FMT_RAW_CSI2_12 ('RACC'), V4L2_PIX_FMT_RAW_CSI2_14 ('RACE')
+************************************************************************************************************************************
+
+
+Generic line-based raw image data formats
+
+
+Description
+===========
+
+These generic raw image data formats define the memory layout of the data without
+defining the order of the colour components or even the colour components
+themselves.
+
+.. _v4l2-pix-fmt-raw-8:
+
+V4L2_PIX_FMT_RAW_8
+------------------
+
+The V4L2_PIX_FMT_RAW_8 format is a plain 8-bit raw pixel data format. This
+format is used on CSI-2 for 8 bits per :term:`Data Unit`.
+
+**Byte Order Of V4L2_PIX_FMT_RAW_8.**
+Each cell is one byte. "P" denotes a pixel.
+
+.. tabularcolumns:: |p{2.4cm}|p{1.2cm}|p{1.2cm}|p{1.2cm}|p{1.2cm}|
+
+.. flat-table:: Sample 4x2 Image Frame
+    :header-rows:  0
+    :stub-columns: 0
+    :widths: 12 8 8 8 8
+
+    * - start + 0:
+      - P\ :sub:`00`
+      - P\ :sub:`10`
+      - P\ :sub:`20`
+      - P\ :sub:`30`
+    * - start + 4:
+      - P\ :sub:`01`
+      - P\ :sub:`11`
+      - P\ :sub:`21`
+      - P\ :sub:`31`
+
+.. _v4l2-pix-fmt-raw-csi2-10:
+
+V4L2_PIX_FMT_RAW_CSI2_10
+------------------------
+
+V4L2_PIX_FMT_RAW_CSI2_10 contains 10-bit packed image data, with four bytes
+containing the top 8 bits of the pixels followed by lowest 2 bits of the pixels
+packed into one byte. This format is typically used by CSI-2 receivers with
+a source that transmits MEDIA_BUS_FMT_RAW_10 and the CSI-2 receiver writes the
+received data to memory as-is.
+
+The packing of the data follows the MIPI CSI-2 specification.
+
+**Byte Order Of V4L2_PIX_FMT_RAW_CSI2_10.**
+Each cell is one byte. "P" denotes a pixel.
+
+.. tabularcolumns:: |p{2.4cm}|p{1.2cm}|p{1.2cm}|p{1.2cm}|p{1.2cm}|p{2cm}|
+
+.. flat-table:: Sample 4x2 Image Frame
+    :header-rows:  0
+    :stub-columns: 0
+    :widths: 12 8 8 8 8 8
+
+    * - start + 0:
+      - P\ :sub:`00 bits 9--2`
+      - P\ :sub:`10 bits 9--2`
+      - P\ :sub:`20 bits 9--2`
+      - P\ :sub:`30 bits 9--2`
+      - P\ :sub:`00 bits 1--0` (bits 1--0),
+        P\ :sub:`10 bits 1--0` (bits 3--2),
+        P\ :sub:`20 bits 1--0` (bits 5--4),
+        P\ :sub:`30 bits 1--0` (bits 7--6)
+    * - start + 5:
+      - P\ :sub:`01 bits 9--2`
+      - P\ :sub:`11 bits 9--2`
+      - P\ :sub:`21 bits 9--2`
+      - P\ :sub:`31 bits 9--2`
+      - P\ :sub:`01 bits 1--0` (bits 1--0),
+        P\ :sub:`11 bits 1--0` (bits 3--2),
+        P\ :sub:`21 bits 1--0` (bits 5--4),
+        P\ :sub:`31 bits 1--0` (bits 7--6)
+
+.. _v4l2-pix-fmt-raw-csi2-12:
+
+V4L2_PIX_FMT_RAW_CSI2_12
+------------------------
+
+V4L2_PIX_FMT_RAW_CSI2_12 contains 12-bit packed image data, with two bytes
+containing the top 8 bits of the pixels followed by lowest 4 bits of the pixels
+packed into 1 byte. This format is typically used by CSI-2 receivers with
+a source that transmits MEDIA_BUS_FMT_RAW_12 and the CSI-2 receiver writes the
+received data to memory as-is.
+
+The packing of the data follows the MIPI CSI-2 specification.
+
+**Byte Order Of V4L2_PIX_FMT_RAW_CSI2_12.**
+Each cell is one byte. "P" denotes a pixel.
+
+.. tabularcolumns:: |p{2.4cm}|p{1.2cm}|p{1.2cm}|p{2cm}|p{1.2cm}|p{1.2cm}|p{2cm}|
+
+.. flat-table:: Sample 4x2 Image Frame
+    :header-rows:  0
+    :stub-columns: 0
+    :widths: 12 8 8 8 8 8 8
+
+    * - start + 0:
+      - P\ :sub:`00 bits 11--4`
+      - P\ :sub:`10 bits 11--4`
+      - P\ :sub:`00 bits 3--0` (bits 3--0),
+        P\ :sub:`10 bits 3--0` (bits 7--4)
+      - P\ :sub:`20 bits 11--4`
+      - P\ :sub:`30 bits 11--4`
+      - P\ :sub:`20 bits 3--0` (bits 3--0),
+        P\ :sub:`30 bits 3--0` (bits 7--4)
+    * - start + 6:
+      - P\ :sub:`01 bits 11--4`
+      - P\ :sub:`11 bits 11--4`
+      - P\ :sub:`01 bits 3--0` (bits 3--0),
+        P\ :sub:`11 bits 3--0` (bits 7--4)
+      - P\ :sub:`21 bits 11--4`
+      - P\ :sub:`31 bits 11--4`
+      - P\ :sub:`21 bits 3--0` (bits 3--0),
+        P\ :sub:`31 bits 3--0` (bits 7--4)
+
+.. _v4l2-pix-fmt-raw-csi2-14:
+
+V4L2_PIX_FMT_RAW_CSI2_14
+------------------------
+
+V4L2_PIX_FMT_RAW_CSI2_14 contains 14-bit packed image data, with four bytes
+containing the top 8 bits of the pixels followed by lowest 6 bits of the pixels
+packed into three bytes. This format is typically used by CSI-2 receivers with a
+source that transmits MEDIA_BUS_FMT_RAW_14 and the CSI-2 receiver writes the
+received data to memory as-is.
+
+The packing of the data follows the MIPI CSI-2 specification.
+
+**Byte Order Of V4L2_PIX_FMT_RAW_CSI2_14.**
+Each cell is one byte. "P" denotes a pixel.
+
+.. tabularcolumns:: |p{2.4cm}|p{1.2cm}|p{1.2cm}|p{1.2cm}|p{1.2cm}|p{2cm}|p{2cm}|p{2cm}|
+
+.. flat-table:: Sample 4x2 Image Frame
+    :header-rows:  0
+    :stub-columns: 0
+    :widths: 12 8 8 8 8 8 8 8
+
+    * - start + 0:
+      - P\ :sub:`00 bits 13--6`
+      - P\ :sub:`10 bits 13--6`
+      - P\ :sub:`20 bits 13--6`
+      - P\ :sub:`30 bits 13--6`
+      - P\ :sub:`10 bits 1--0` (bits 7--6),
+        P\ :sub:`00 bits 5--0` (bits 5--0)
+      - P\ :sub:`20 bits 3--0` (bits 7--4),
+        P\ :sub:`10 bits 5--2` (bits 3--0)
+      - P\ :sub:`30 bits 5--0` (bits 7--2),
+        P\ :sub:`20 bits 5--4` (bits 1--0)
+    * - start + 7:
+      - P\ :sub:`01 bits 13--6`
+      - P\ :sub:`11 bits 13--6`
+      - P\ :sub:`21 bits 13--6`
+      - P\ :sub:`31 bits 13--6`
+      - P\ :sub:`11 bits 1--0` (bits 7--6),
+        P\ :sub:`01 bits 5--0` (bits 5--0)
+      - P\ :sub:`21 bits 3--0` (bits 7--4),
+        P\ :sub:`11 bits 5--2` (bits 3--0)
+      - P\ :sub:`31 bits 5--0` (bits 7--2),
+        P\ :sub:`21 bits 5--4` (bits 1--0)
diff --git a/Documentation/userspace-api/media/v4l/pixfmt.rst b/Documentation/userspace-api/media/v4l/pixfmt.rst
index 71b29267488f..520a8ec438c9 100644
--- a/Documentation/userspace-api/media/v4l/pixfmt.rst
+++ b/Documentation/userspace-api/media/v4l/pixfmt.rst
@@ -26,6 +26,7 @@ see also :ref:`VIDIOC_G_FBUF <VIDIOC_G_FBUF>`.)
     pixfmt-indexed
     pixfmt-rgb
     pixfmt-bayer
+    pixfmt-raw-generic
     yuv-formats
     hsv-formats
     depth-formats
diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c b/drivers/media/v4l2-core/v4l2-ioctl.c
index 37d33d4a363d..5fda3835f680 100644
--- a/drivers/media/v4l2-core/v4l2-ioctl.c
+++ b/drivers/media/v4l2-core/v4l2-ioctl.c
@@ -1434,6 +1434,10 @@ static void v4l_fill_fmtdesc(struct v4l2_fmtdesc *fmt)
 	case V4L2_PIX_FMT_SGBRG16:	descr = "16-bit Bayer GBGB/RGRG"; break;
 	case V4L2_PIX_FMT_SGRBG16:	descr = "16-bit Bayer GRGR/BGBG"; break;
 	case V4L2_PIX_FMT_SRGGB16:	descr = "16-bit Bayer RGRG/GBGB"; break;
+	case V4L2_PIX_FMT_RAW_8:	descr = "8-bit Raw"; break;
+	case V4L2_PIX_FMT_RAW_CSI2_10:	descr = "10-bit Raw, CSI-2 Packed"; break;
+	case V4L2_PIX_FMT_RAW_CSI2_12:	descr = "12-bit Raw, CSI-2 Packed"; break;
+	case V4L2_PIX_FMT_RAW_CSI2_14:	descr = "14-bit Raw, CSI-2 Packed"; break;
 	case V4L2_PIX_FMT_RAW_CRU20:	descr = "14-bit Raw CRU Packed"; break;
 	case V4L2_PIX_FMT_SN9C20X_I420:	descr = "GSPCA SN9C20X I420"; break;
 	case V4L2_PIX_FMT_SPCA501:	descr = "GSPCA SPCA501"; break;
diff --git a/include/uapi/linux/videodev2.h b/include/uapi/linux/videodev2.h
index eda4492e40dc..901c2b788edd 100644
--- a/include/uapi/linux/videodev2.h
+++ b/include/uapi/linux/videodev2.h
@@ -745,6 +745,12 @@ struct v4l2_pix_format {
 #define V4L2_PIX_FMT_SGRBG16 v4l2_fourcc('G', 'R', '1', '6') /* 16  GRGR.. BGBG.. */
 #define V4L2_PIX_FMT_SRGGB16 v4l2_fourcc('R', 'G', '1', '6') /* 16  RGRG.. GBGB.. */
 
+/* Generic CSI-2 packed raw pixel formats */
+#define V4L2_PIX_FMT_RAW_8 v4l2_fourcc('R', 'A', 'W', '8')
+#define V4L2_PIX_FMT_RAW_CSI2_10 v4l2_fourcc('R', 'A', 'C', 'A')
+#define V4L2_PIX_FMT_RAW_CSI2_12 v4l2_fourcc('R', 'A', 'C', 'C')
+#define V4L2_PIX_FMT_RAW_CSI2_14 v4l2_fourcc('R', 'A', 'C', 'E')
+
 /* HSV formats */
 #define V4L2_PIX_FMT_HSV24 v4l2_fourcc('H', 'S', 'V', '3')
 #define V4L2_PIX_FMT_HSV32 v4l2_fourcc('H', 'S', 'V', '4')
-- 
2.47.3


^ permalink raw reply related	[flat|nested] 88+ messages in thread

* [PATCH v12 03/86] media: uapi: Add new media bus codes for generic raw formats
  2026-04-09 20:13 [PATCH v12 00/86] Generic line based metadata support, internal pads Sakari Ailus
  2026-04-09 20:13 ` [PATCH v12 01/86] media: mc: Add INTERNAL pad flag Sakari Ailus
  2026-04-09 20:13 ` [PATCH v12 02/86] media: uapi: Add generic CSI-2 raw pixelformats Sakari Ailus
@ 2026-04-09 20:13 ` Sakari Ailus
  2026-04-09 20:13 ` [PATCH v12 04/86] media: uapi: Add V4L2_CID_CONFIG_MODEL control Sakari Ailus
                   ` (82 subsequent siblings)
  85 siblings, 0 replies; 88+ messages in thread
From: Sakari Ailus @ 2026-04-09 20:13 UTC (permalink / raw)
  To: linux-media
  Cc: hans, laurent.pinchart, Prabhakar, Kate Hsuan, Dave Stevenson,
	Tommaso Merciai, Benjamin Mugnier, Sylvain Petinot,
	Christophe JAILLET, Julien Massot, Naushir Patuck, Stefan Klug,
	Mirela Rabulea, André Apitzsch, Heimir Thor Sverrisson,
	Kieran Bingham, Mehdi Djait, Ricardo Ribalda Delgado,
	Hans de Goede, Jacopo Mondi, Tomi Valkeinen, David Plowman,
	Yu, Ong Hock, Ng, Khai Wen, Jai Luthra, Rishikesh Donadkar

Add new media bus codes for generic raw formats that are not specific to
the colour filter array but that simply specify the bit depth. The layout
(packing) of the data is interface specific.

The rest of the properties of the format are specified with controls in
the image source.

The mbus codes added by this patch have bit depth of 8, 10, 12 and 14.

Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
Reviewed-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 .../media/v4l/subdev-formats.rst              | 27 +++++++++++++++++++
 include/uapi/linux/media-bus-format.h         |  6 +++++
 2 files changed, 33 insertions(+)

diff --git a/Documentation/userspace-api/media/v4l/subdev-formats.rst b/Documentation/userspace-api/media/v4l/subdev-formats.rst
index c9999b929773..fecb786cb8af 100644
--- a/Documentation/userspace-api/media/v4l/subdev-formats.rst
+++ b/Documentation/userspace-api/media/v4l/subdev-formats.rst
@@ -3855,6 +3855,33 @@ organization is given as an example for the first pixel only.
 
     \endgroup
 
+Generic raw formats on serial interfaces
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Those formats transfer raw pixel data typically from raw camera sensors using
+Bayer and other Colour Filter Arrays (CFAs) on serial interfaces. The packing of
+the data on the bus is determined by the hardware, however the bit depth is
+still specific to the format.
+
+.. tabularcolumns:: |p{2.0cm}|p{4.0cm}|p{11.3cm}|
+
+.. cssclass:: longtable
+
+.. flat-table:: Generic raw formats on serial buses
+    :header-rows:  1
+    :stub-columns: 0
+    :widths:       1 1
+
+    * - Format name
+      - Bit depth
+    * - MEDIA_BUS_FMT_RAW_8
+      - 8
+    * - MEDIA_BUS_FMT_RAW_10
+      - 10
+    * - MEDIA_BUS_FMT_RAW_12
+      - 12
+    * - MEDIA_BUS_FMT_RAW_14
+      - 14
 
 Packed YUV Formats
 ^^^^^^^^^^^^^^^^^^
diff --git a/include/uapi/linux/media-bus-format.h b/include/uapi/linux/media-bus-format.h
index 6005f033e62c..83feeae6a31e 100644
--- a/include/uapi/linux/media-bus-format.h
+++ b/include/uapi/linux/media-bus-format.h
@@ -190,4 +190,10 @@
 #define MEDIA_BUS_FMT_META_20			0x8006
 #define MEDIA_BUS_FMT_META_24			0x8007
 
+/* Generic (CFA independent) pixel data formats. Next is 0x9005. */
+#define MEDIA_BUS_FMT_RAW_8			0x9001
+#define MEDIA_BUS_FMT_RAW_10			0x9002
+#define MEDIA_BUS_FMT_RAW_12			0x9003
+#define MEDIA_BUS_FMT_RAW_14			0x9004
+
 #endif /* __LINUX_MEDIA_BUS_FORMAT_H */
-- 
2.47.3


^ permalink raw reply related	[flat|nested] 88+ messages in thread

* [PATCH v12 04/86] media: uapi: Add V4L2_CID_CONFIG_MODEL control
  2026-04-09 20:13 [PATCH v12 00/86] Generic line based metadata support, internal pads Sakari Ailus
                   ` (2 preceding siblings ...)
  2026-04-09 20:13 ` [PATCH v12 03/86] media: uapi: Add new media bus codes for generic raw formats Sakari Ailus
@ 2026-04-09 20:13 ` Sakari Ailus
  2026-04-09 20:13 ` [PATCH v12 05/86] media: uapi: Add V4L2_CID_CFA_PATTERN for describing color patterns Sakari Ailus
                   ` (81 subsequent siblings)
  85 siblings, 0 replies; 88+ messages in thread
From: Sakari Ailus @ 2026-04-09 20:13 UTC (permalink / raw)
  To: linux-media
  Cc: hans, laurent.pinchart, Prabhakar, Kate Hsuan, Dave Stevenson,
	Tommaso Merciai, Benjamin Mugnier, Sylvain Petinot,
	Christophe JAILLET, Julien Massot, Naushir Patuck, Stefan Klug,
	Mirela Rabulea, André Apitzsch, Heimir Thor Sverrisson,
	Kieran Bingham, Mehdi Djait, Ricardo Ribalda Delgado,
	Hans de Goede, Jacopo Mondi, Tomi Valkeinen, David Plowman,
	Yu, Ong Hock, Ng, Khai Wen, Jai Luthra, Rishikesh Donadkar

Add the V4L2_CID_CONFIG_MODEL control for the configuration model.

Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Reviewed-by: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
---
 .../userspace-api/media/v4l/ext-ctrls-image-process.rst      | 4 ++++
 drivers/media/v4l2-core/v4l2-ctrls-defs.c                    | 5 +++++
 include/uapi/linux/v4l2-controls.h                           | 3 +++
 3 files changed, 12 insertions(+)

diff --git a/Documentation/userspace-api/media/v4l/ext-ctrls-image-process.rst b/Documentation/userspace-api/media/v4l/ext-ctrls-image-process.rst
index ee88933256dd..51188e7febae 100644
--- a/Documentation/userspace-api/media/v4l/ext-ctrls-image-process.rst
+++ b/Documentation/userspace-api/media/v4l/ext-ctrls-image-process.rst
@@ -58,3 +58,7 @@ Image Process Control IDs
     control value divided by e.g. 0x100, meaning that to get no
     digital gain the control value needs to be 0x100. The no-gain
     configuration is also typically the default.
+
+``V4L2_CID_CONFIG_MODEL (bitmask)``
+    Which configuration models the sub-device supports. Please see
+    :ref:`media_subdev_config_model`. This is a read-only control.
diff --git a/drivers/media/v4l2-core/v4l2-ctrls-defs.c b/drivers/media/v4l2-core/v4l2-ctrls-defs.c
index 551426c4cd01..aab785e8948c 100644
--- a/drivers/media/v4l2-core/v4l2-ctrls-defs.c
+++ b/drivers/media/v4l2-core/v4l2-ctrls-defs.c
@@ -1166,6 +1166,7 @@ const char *v4l2_ctrl_get_name(u32 id)
 	case V4L2_CID_TEST_PATTERN:		return "Test Pattern";
 	case V4L2_CID_DEINTERLACING_MODE:	return "Deinterlacing Mode";
 	case V4L2_CID_DIGITAL_GAIN:		return "Digital Gain";
+	case V4L2_CID_CONFIG_MODEL:		return "Sub-device Configuration Model";
 
 	/* DV controls */
 	/* Keep the order of the 'case's the same as in v4l2-controls.h! */
@@ -1486,6 +1487,10 @@ void v4l2_ctrl_fill(u32 id, const char **name, enum v4l2_ctrl_type *type,
 	case V4L2_CID_DV_RX_POWER_PRESENT:
 		*type = V4L2_CTRL_TYPE_BITMASK;
 		break;
+	case V4L2_CID_CONFIG_MODEL:
+		*flags |= V4L2_CTRL_FLAG_READ_ONLY;
+		*type = V4L2_CTRL_TYPE_BITMASK;
+		break;
 	case V4L2_CID_MIN_BUFFERS_FOR_CAPTURE:
 	case V4L2_CID_MIN_BUFFERS_FOR_OUTPUT:
 		*type = V4L2_CTRL_TYPE_INTEGER;
diff --git a/include/uapi/linux/v4l2-controls.h b/include/uapi/linux/v4l2-controls.h
index 68dd0c4e47b2..349d75d0da32 100644
--- a/include/uapi/linux/v4l2-controls.h
+++ b/include/uapi/linux/v4l2-controls.h
@@ -1246,6 +1246,9 @@ enum v4l2_jpeg_chroma_subsampling {
 #define V4L2_CID_TEST_PATTERN			(V4L2_CID_IMAGE_PROC_CLASS_BASE + 3)
 #define V4L2_CID_DEINTERLACING_MODE		(V4L2_CID_IMAGE_PROC_CLASS_BASE + 4)
 #define V4L2_CID_DIGITAL_GAIN			(V4L2_CID_IMAGE_PROC_CLASS_BASE + 5)
+#define V4L2_CID_CONFIG_MODEL			(V4L2_CID_IMAGE_PROC_CLASS_BASE + 6)
+
+#define V4L2_CONFIG_MODEL_COMMON_RAW_SENSOR	(1U << 0)
 
 /*  DV-class control IDs defined by V4L2 */
 #define V4L2_CID_DV_CLASS_BASE			(V4L2_CTRL_CLASS_DV | 0x900)
-- 
2.47.3


^ permalink raw reply related	[flat|nested] 88+ messages in thread

* [PATCH v12 05/86] media: uapi: Add V4L2_CID_CFA_PATTERN for describing color patterns
  2026-04-09 20:13 [PATCH v12 00/86] Generic line based metadata support, internal pads Sakari Ailus
                   ` (3 preceding siblings ...)
  2026-04-09 20:13 ` [PATCH v12 04/86] media: uapi: Add V4L2_CID_CONFIG_MODEL control Sakari Ailus
@ 2026-04-09 20:13 ` Sakari Ailus
  2026-04-09 20:13 ` [PATCH v12 06/86] media: Documentation: Reference CFA pattern control in pixelformat docs Sakari Ailus
                   ` (80 subsequent siblings)
  85 siblings, 0 replies; 88+ messages in thread
From: Sakari Ailus @ 2026-04-09 20:13 UTC (permalink / raw)
  To: linux-media
  Cc: hans, laurent.pinchart, Prabhakar, Kate Hsuan, Dave Stevenson,
	Tommaso Merciai, Benjamin Mugnier, Sylvain Petinot,
	Christophe JAILLET, Julien Massot, Naushir Patuck, Stefan Klug,
	Mirela Rabulea, André Apitzsch, Heimir Thor Sverrisson,
	Kieran Bingham, Mehdi Djait, Ricardo Ribalda Delgado,
	Hans de Goede, Jacopo Mondi, Tomi Valkeinen, David Plowman,
	Yu, Ong Hock, Ng, Khai Wen, Jai Luthra, Rishikesh Donadkar

Add V4L2_CID_CFA_PATTERN to tell the camera sensor's native Color Filter
Array (CFA) pattern.

Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
Reviewed-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
Reviewed-by: Mirela Rabulea <mirela.rabulea@nxp.com>
---
 .../media/v4l/ext-ctrls-image-source.rst      | 43 +++++++++++++++++++
 .../media/v4l/subdev-formats.rst              |  2 +
 drivers/media/v4l2-core/v4l2-ctrls-defs.c     |  1 +
 include/uapi/linux/v4l2-controls.h            |  6 +++
 4 files changed, 52 insertions(+)

diff --git a/Documentation/userspace-api/media/v4l/ext-ctrls-image-source.rst b/Documentation/userspace-api/media/v4l/ext-ctrls-image-source.rst
index f9c0b7ad3b4e..b09ad4b4576e 100644
--- a/Documentation/userspace-api/media/v4l/ext-ctrls-image-source.rst
+++ b/Documentation/userspace-api/media/v4l/ext-ctrls-image-source.rst
@@ -93,3 +93,46 @@ Image Source Control IDs
     representing a gain of exactly 1.0. For example, if this default value
     is reported as being (say) 128, then a value of 192 would represent
     a gain of exactly 1.5.
+
+``V4L2_CID_CFA_PATTERN (integer)``
+    This control determines the color components and native pixel order in the
+    sensor's CFA (Color Filter Array) when used in conjunction with
+    :ref:`generic raw mbus codes MEDIA_BUS_FMT_RAW_x (where 'x' is the bit
+    depth) <v4l2-mbus-pixelcode-generic-raw>` pixelcodes. The native pixel
+    order is constant for a given device, it is not affected by cropping or
+    flipping.
+
+    This control may only be used on V4L2 sub-devices.
+
+    This is a read-only control.
+
+    Available patterns:
+
+.. flat-table:: V4L2 Color Filter Array Patterns
+    :header-rows:  1
+    :stub-columns: 0
+    :widths:       1 2 1
+
+    * - Macro name
+      - Synopsis
+      - Value
+    * - V4L2_CFA_PATTERN_GRBG
+      - Bayer pattern (2x2 macroblocks). Each macroblock has a green filter in
+        the top-left and bottom-right pixels, a red filter in the top-right
+        pixel, and a blue filter in the bottom-left pixel.
+      - 0
+    * - V4L2_CFA_PATTERN_RGGB
+      - Bayer pattern (2x2 macroblocks). Each macroblock has a green filter in
+        the top-right and bottom-left pixels, a red filter in the top-left
+        pixel, and a blue filter in the bottom-right pixel.
+      - 1
+    * - V4L2_CFA_PATTERN_BGGR
+      - Bayer pattern (2x2 macroblocks). Each macroblock has a green filter in
+        the top-right and bottom-left pixels, a blue filter in the top-left
+        pixel, and a red filter in the bottom-right pixel.
+      - 2
+    * - V4L2_CFA_PATTERN_GBRG
+      - Bayer pattern (2x2 macroblocks). Each macroblock has a green filter in
+        the top-left and bottom-right pixels, a blue filter in the top-right
+        pixel, and a red filter in the bottom-left pixel.
+      - 3
diff --git a/Documentation/userspace-api/media/v4l/subdev-formats.rst b/Documentation/userspace-api/media/v4l/subdev-formats.rst
index fecb786cb8af..7d34c2991f81 100644
--- a/Documentation/userspace-api/media/v4l/subdev-formats.rst
+++ b/Documentation/userspace-api/media/v4l/subdev-formats.rst
@@ -3855,6 +3855,8 @@ organization is given as an example for the first pixel only.
 
     \endgroup
 
+.. _v4l2-mbus-pixelcode-generic-raw:
+
 Generic raw formats on serial interfaces
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
diff --git a/drivers/media/v4l2-core/v4l2-ctrls-defs.c b/drivers/media/v4l2-core/v4l2-ctrls-defs.c
index aab785e8948c..4fafc7a3c233 100644
--- a/drivers/media/v4l2-core/v4l2-ctrls-defs.c
+++ b/drivers/media/v4l2-core/v4l2-ctrls-defs.c
@@ -1157,6 +1157,7 @@ const char *v4l2_ctrl_get_name(u32 id)
 	case V4L2_CID_TEST_PATTERN_BLUE:	return "Blue Pixel Value";
 	case V4L2_CID_TEST_PATTERN_GREENB:	return "Green (Blue) Pixel Value";
 	case V4L2_CID_NOTIFY_GAINS:		return "Notify Gains";
+	case V4L2_CID_CFA_PATTERN:		return "Color Filter Array Pattern";
 
 	/* Image processing controls */
 	/* Keep the order of the 'case's the same as in v4l2-controls.h! */
diff --git a/include/uapi/linux/v4l2-controls.h b/include/uapi/linux/v4l2-controls.h
index 349d75d0da32..78c6fc69b1c1 100644
--- a/include/uapi/linux/v4l2-controls.h
+++ b/include/uapi/linux/v4l2-controls.h
@@ -1235,6 +1235,12 @@ enum v4l2_jpeg_chroma_subsampling {
 #define V4L2_CID_UNIT_CELL_SIZE			(V4L2_CID_IMAGE_SOURCE_CLASS_BASE + 8)
 #define V4L2_CID_NOTIFY_GAINS			(V4L2_CID_IMAGE_SOURCE_CLASS_BASE + 9)
 
+#define V4L2_CID_CFA_PATTERN			(V4L2_CID_IMAGE_SOURCE_CLASS_BASE + 10)
+#define V4L2_CFA_PATTERN_GRBG			0U
+#define V4L2_CFA_PATTERN_RGGB			1U
+#define V4L2_CFA_PATTERN_BGGR			2U
+#define V4L2_CFA_PATTERN_GBRG			3U
+
 
 /* Image processing controls */
 
-- 
2.47.3


^ permalink raw reply related	[flat|nested] 88+ messages in thread

* [PATCH v12 06/86] media: Documentation: Reference CFA pattern control in pixelformat docs
  2026-04-09 20:13 [PATCH v12 00/86] Generic line based metadata support, internal pads Sakari Ailus
                   ` (4 preceding siblings ...)
  2026-04-09 20:13 ` [PATCH v12 05/86] media: uapi: Add V4L2_CID_CFA_PATTERN for describing color patterns Sakari Ailus
@ 2026-04-09 20:13 ` Sakari Ailus
  2026-04-09 20:13 ` [PATCH v12 07/86] media: Documentation: Reference CFA_PATTERN control in raw mbus docs Sakari Ailus
                   ` (79 subsequent siblings)
  85 siblings, 0 replies; 88+ messages in thread
From: Sakari Ailus @ 2026-04-09 20:13 UTC (permalink / raw)
  To: linux-media
  Cc: hans, laurent.pinchart, Prabhakar, Kate Hsuan, Dave Stevenson,
	Tommaso Merciai, Benjamin Mugnier, Sylvain Petinot,
	Christophe JAILLET, Julien Massot, Naushir Patuck, Stefan Klug,
	Mirela Rabulea, André Apitzsch, Heimir Thor Sverrisson,
	Kieran Bingham, Mehdi Djait, Ricardo Ribalda Delgado,
	Hans de Goede, Jacopo Mondi, Tomi Valkeinen, David Plowman,
	Yu, Ong Hock, Ng, Khai Wen, Jai Luthra, Rishikesh Donadkar

Refer to the CFA pattern control in the generic raw pixelformat
documentation.

Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
Reviewed-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 .../userspace-api/media/v4l/ext-ctrls-image-source.rst        | 2 ++
 Documentation/userspace-api/media/v4l/pixfmt-raw-generic.rst  | 4 +++-
 2 files changed, 5 insertions(+), 1 deletion(-)

diff --git a/Documentation/userspace-api/media/v4l/ext-ctrls-image-source.rst b/Documentation/userspace-api/media/v4l/ext-ctrls-image-source.rst
index b09ad4b4576e..2328ac99e97a 100644
--- a/Documentation/userspace-api/media/v4l/ext-ctrls-image-source.rst
+++ b/Documentation/userspace-api/media/v4l/ext-ctrls-image-source.rst
@@ -94,6 +94,8 @@ Image Source Control IDs
     is reported as being (say) 128, then a value of 192 would represent
     a gain of exactly 1.5.
 
+.. _image-source-control-cfa-pattern:
+
 ``V4L2_CID_CFA_PATTERN (integer)``
     This control determines the color components and native pixel order in the
     sensor's CFA (Color Filter Array) when used in conjunction with
diff --git a/Documentation/userspace-api/media/v4l/pixfmt-raw-generic.rst b/Documentation/userspace-api/media/v4l/pixfmt-raw-generic.rst
index 254f8f18c7c5..708aa17b80b0 100644
--- a/Documentation/userspace-api/media/v4l/pixfmt-raw-generic.rst
+++ b/Documentation/userspace-api/media/v4l/pixfmt-raw-generic.rst
@@ -13,7 +13,9 @@ Description
 
 These generic raw image data formats define the memory layout of the data without
 defining the order of the colour components or even the colour components
-themselves.
+themselves. These formats may only be used with a Media Controller pipeline where
+the more specific format is reported by the :ref:`V4L2_CID_CFA_PATTERN
+<image-source-control-cfa-pattern>` control on the source sub-device.
 
 .. _v4l2-pix-fmt-raw-8:
 
-- 
2.47.3


^ permalink raw reply related	[flat|nested] 88+ messages in thread

* [PATCH v12 07/86] media: Documentation: Reference CFA_PATTERN control in raw mbus docs
  2026-04-09 20:13 [PATCH v12 00/86] Generic line based metadata support, internal pads Sakari Ailus
                   ` (5 preceding siblings ...)
  2026-04-09 20:13 ` [PATCH v12 06/86] media: Documentation: Reference CFA pattern control in pixelformat docs Sakari Ailus
@ 2026-04-09 20:13 ` Sakari Ailus
  2026-04-09 20:13 ` [PATCH v12 08/86] media: v4l: uapi: Add a control for color pattern flipping effect Sakari Ailus
                   ` (78 subsequent siblings)
  85 siblings, 0 replies; 88+ messages in thread
From: Sakari Ailus @ 2026-04-09 20:13 UTC (permalink / raw)
  To: linux-media
  Cc: hans, laurent.pinchart, Prabhakar, Kate Hsuan, Dave Stevenson,
	Tommaso Merciai, Benjamin Mugnier, Sylvain Petinot,
	Christophe JAILLET, Julien Massot, Naushir Patuck, Stefan Klug,
	Mirela Rabulea, André Apitzsch, Heimir Thor Sverrisson,
	Kieran Bingham, Mehdi Djait, Ricardo Ribalda Delgado,
	Hans de Goede, Jacopo Mondi, Tomi Valkeinen, David Plowman,
	Yu, Ong Hock, Ng, Khai Wen, Jai Luthra, Rishikesh Donadkar

Add a reference to the V4L2_CID_CFA_PATTERN control in the generic raw
media bus code documentation.

Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
Reviewed-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
---
 Documentation/userspace-api/media/v4l/subdev-formats.rst | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/Documentation/userspace-api/media/v4l/subdev-formats.rst b/Documentation/userspace-api/media/v4l/subdev-formats.rst
index 7d34c2991f81..3aa5bfdd5175 100644
--- a/Documentation/userspace-api/media/v4l/subdev-formats.rst
+++ b/Documentation/userspace-api/media/v4l/subdev-formats.rst
@@ -3865,6 +3865,9 @@ Bayer and other Colour Filter Arrays (CFAs) on serial interfaces. The packing of
 the data on the bus is determined by the hardware, however the bit depth is
 still specific to the format.
 
+The native Colour Filter Array (CFA) pattern is determined by the
+:ref:`V4L2_CID_CFA_PATTERN <image-source-control-cfa-pattern>` control.
+
 .. tabularcolumns:: |p{2.0cm}|p{4.0cm}|p{11.3cm}|
 
 .. cssclass:: longtable
-- 
2.47.3


^ permalink raw reply related	[flat|nested] 88+ messages in thread

* [PATCH v12 08/86] media: v4l: uapi: Add a control for color pattern flipping effect
  2026-04-09 20:13 [PATCH v12 00/86] Generic line based metadata support, internal pads Sakari Ailus
                   ` (6 preceding siblings ...)
  2026-04-09 20:13 ` [PATCH v12 07/86] media: Documentation: Reference CFA_PATTERN control in raw mbus docs Sakari Ailus
@ 2026-04-09 20:13 ` Sakari Ailus
  2026-04-09 20:13 ` [PATCH v12 09/86] media: Documentation: Reference flipping controls in raw format docs Sakari Ailus
                   ` (77 subsequent siblings)
  85 siblings, 0 replies; 88+ messages in thread
From: Sakari Ailus @ 2026-04-09 20:13 UTC (permalink / raw)
  To: linux-media
  Cc: hans, laurent.pinchart, Prabhakar, Kate Hsuan, Dave Stevenson,
	Tommaso Merciai, Benjamin Mugnier, Sylvain Petinot,
	Christophe JAILLET, Julien Massot, Naushir Patuck, Stefan Klug,
	Mirela Rabulea, André Apitzsch, Heimir Thor Sverrisson,
	Kieran Bingham, Mehdi Djait, Ricardo Ribalda Delgado,
	Hans de Goede, Jacopo Mondi, Tomi Valkeinen, David Plowman,
	Yu, Ong Hock, Ng, Khai Wen, Jai Luthra, Rishikesh Donadkar

Add a bitmask control (V4L2_CID_CFA_PATTERN_FLIP) to tell whether flipping
results in a change in the sensor's Color Filter Array (CFA) pattern,
separately horizontally and vertically. The information is essential for
raw formats when using generic raw mbus codes.

Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
---
 .../media/v4l/ext-ctrls-image-source.rst             | 12 ++++++++++++
 drivers/media/v4l2-core/v4l2-ctrls-defs.c            |  2 ++
 include/uapi/linux/v4l2-controls.h                   |  6 ++++++
 3 files changed, 20 insertions(+)

diff --git a/Documentation/userspace-api/media/v4l/ext-ctrls-image-source.rst b/Documentation/userspace-api/media/v4l/ext-ctrls-image-source.rst
index 2328ac99e97a..f3e4428c4bf1 100644
--- a/Documentation/userspace-api/media/v4l/ext-ctrls-image-source.rst
+++ b/Documentation/userspace-api/media/v4l/ext-ctrls-image-source.rst
@@ -138,3 +138,15 @@ Image Source Control IDs
         the top-left and bottom-right pixels, a blue filter in the top-right
         pixel, and a red filter in the bottom-left pixel.
       - 3
+
+``V4L2_CID_CFA_PATTERN_FLIP (bitmask)``
+    This control determines whether the horizontal or vertical flipping controls
+    (V4L2_CID_HFLIP and V4L2_CID_VFLIP) have an effect on the pixel order of the
+    output color pattern. Macros ``V4L2_CFA_PATTERN_FLIP_HORIZONTAL`` and
+    ``V4L2_CFA_PATTERN_FLIP_VERTICAL`` define bitmasks for both bits. If either
+    horizontal or vertical bit is set, the readout pattern order is that of the
+    reversed readout. ``V4L2_CFA_PATTERN_FLIP_BOTH`` for setting both
+    ``V4L2_CFA_PATTERN_FLIP_HORIZONTAL`` and ``V4L2_CFA_PATTERN_FLIP_VERTICAL``
+    is provided as well.
+
+    This is a read-only control.
diff --git a/drivers/media/v4l2-core/v4l2-ctrls-defs.c b/drivers/media/v4l2-core/v4l2-ctrls-defs.c
index 4fafc7a3c233..32a4b1b3fc0e 100644
--- a/drivers/media/v4l2-core/v4l2-ctrls-defs.c
+++ b/drivers/media/v4l2-core/v4l2-ctrls-defs.c
@@ -1158,6 +1158,7 @@ const char *v4l2_ctrl_get_name(u32 id)
 	case V4L2_CID_TEST_PATTERN_GREENB:	return "Green (Blue) Pixel Value";
 	case V4L2_CID_NOTIFY_GAINS:		return "Notify Gains";
 	case V4L2_CID_CFA_PATTERN:		return "Color Filter Array Pattern";
+	case V4L2_CID_CFA_PATTERN_FLIP:		return "CFA Pattern Flip";
 
 	/* Image processing controls */
 	/* Keep the order of the 'case's the same as in v4l2-controls.h! */
@@ -1489,6 +1490,7 @@ void v4l2_ctrl_fill(u32 id, const char **name, enum v4l2_ctrl_type *type,
 		*type = V4L2_CTRL_TYPE_BITMASK;
 		break;
 	case V4L2_CID_CONFIG_MODEL:
+	case V4L2_CID_CFA_PATTERN_FLIP:
 		*flags |= V4L2_CTRL_FLAG_READ_ONLY;
 		*type = V4L2_CTRL_TYPE_BITMASK;
 		break;
diff --git a/include/uapi/linux/v4l2-controls.h b/include/uapi/linux/v4l2-controls.h
index 78c6fc69b1c1..d5cedb28a564 100644
--- a/include/uapi/linux/v4l2-controls.h
+++ b/include/uapi/linux/v4l2-controls.h
@@ -1241,6 +1241,12 @@ enum v4l2_jpeg_chroma_subsampling {
 #define V4L2_CFA_PATTERN_BGGR			2U
 #define V4L2_CFA_PATTERN_GBRG			3U
 
+#define V4L2_CID_CFA_PATTERN_FLIP		(V4L2_CID_IMAGE_SOURCE_CLASS_BASE + 11)
+#define V4L2_CFA_PATTERN_FLIP_HORIZONTAL	(1U << 0)
+#define V4L2_CFA_PATTERN_FLIP_VERTICAL		(1U << 1)
+#define V4L2_CFA_PATTERN_FLIP_BOTH \
+	(V4L2_CFA_PATTERN_FLIP_HORIZONTAL | V4L2_CFA_PATTERN_FLIP_VERTICAL)
+
 
 /* Image processing controls */
 
-- 
2.47.3


^ permalink raw reply related	[flat|nested] 88+ messages in thread

* [PATCH v12 09/86] media: Documentation: Reference flipping controls in raw format docs
  2026-04-09 20:13 [PATCH v12 00/86] Generic line based metadata support, internal pads Sakari Ailus
                   ` (7 preceding siblings ...)
  2026-04-09 20:13 ` [PATCH v12 08/86] media: v4l: uapi: Add a control for color pattern flipping effect Sakari Ailus
@ 2026-04-09 20:13 ` Sakari Ailus
  2026-04-09 20:13 ` [PATCH v12 10/86] media: Documentation: Document raw mbus codes and CFA for cameras Sakari Ailus
                   ` (76 subsequent siblings)
  85 siblings, 0 replies; 88+ messages in thread
From: Sakari Ailus @ 2026-04-09 20:13 UTC (permalink / raw)
  To: linux-media
  Cc: hans, laurent.pinchart, Prabhakar, Kate Hsuan, Dave Stevenson,
	Tommaso Merciai, Benjamin Mugnier, Sylvain Petinot,
	Christophe JAILLET, Julien Massot, Naushir Patuck, Stefan Klug,
	Mirela Rabulea, André Apitzsch, Heimir Thor Sverrisson,
	Kieran Bingham, Mehdi Djait, Ricardo Ribalda Delgado,
	Hans de Goede, Jacopo Mondi, Tomi Valkeinen, David Plowman,
	Yu, Ong Hock, Ng, Khai Wen, Jai Luthra, Rishikesh Donadkar

Add a reference to the flipping related controls (V4L2_CID_HFLIP,
V4L2_CID_VFLIP and V4L2_CID_COLOR_PATTERN_FLIP) to the generic raw format
documentation.

Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
Reviewed-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 .../userspace-api/media/v4l/ext-ctrls-image-source.rst         | 2 ++
 Documentation/userspace-api/media/v4l/subdev-formats.rst       | 3 +++
 2 files changed, 5 insertions(+)

diff --git a/Documentation/userspace-api/media/v4l/ext-ctrls-image-source.rst b/Documentation/userspace-api/media/v4l/ext-ctrls-image-source.rst
index f3e4428c4bf1..e1f96987ad59 100644
--- a/Documentation/userspace-api/media/v4l/ext-ctrls-image-source.rst
+++ b/Documentation/userspace-api/media/v4l/ext-ctrls-image-source.rst
@@ -139,6 +139,8 @@ Image Source Control IDs
         pixel, and a red filter in the bottom-left pixel.
       - 3
 
+.. _image-source-control-cfa-pattern-flip:
+
 ``V4L2_CID_CFA_PATTERN_FLIP (bitmask)``
     This control determines whether the horizontal or vertical flipping controls
     (V4L2_CID_HFLIP and V4L2_CID_VFLIP) have an effect on the pixel order of the
diff --git a/Documentation/userspace-api/media/v4l/subdev-formats.rst b/Documentation/userspace-api/media/v4l/subdev-formats.rst
index 3aa5bfdd5175..b207119415f1 100644
--- a/Documentation/userspace-api/media/v4l/subdev-formats.rst
+++ b/Documentation/userspace-api/media/v4l/subdev-formats.rst
@@ -3867,6 +3867,9 @@ still specific to the format.
 
 The native Colour Filter Array (CFA) pattern is determined by the
 :ref:`V4L2_CID_CFA_PATTERN <image-source-control-cfa-pattern>` control.
+Whether or not flipping controls (``V4L2_CID_HFLIP`` and ``V4L2_CID_VFLIP``)
+affect the pattern is conveyed via the :ref:`V4L2_CID_CFA_PATTERN_FLIP
+<image-source-control-cfa-pattern-flip>` control.
 
 .. tabularcolumns:: |p{2.0cm}|p{4.0cm}|p{11.3cm}|
 
-- 
2.47.3


^ permalink raw reply related	[flat|nested] 88+ messages in thread

* [PATCH v12 10/86] media: Documentation: Document raw mbus codes and CFA for cameras
  2026-04-09 20:13 [PATCH v12 00/86] Generic line based metadata support, internal pads Sakari Ailus
                   ` (8 preceding siblings ...)
  2026-04-09 20:13 ` [PATCH v12 09/86] media: Documentation: Reference flipping controls in raw format docs Sakari Ailus
@ 2026-04-09 20:13 ` Sakari Ailus
  2026-04-09 20:13 ` [PATCH v12 11/86] media: uapi: Add V4L2_CID_METADATA_LAYOUT control Sakari Ailus
                   ` (75 subsequent siblings)
  85 siblings, 0 replies; 88+ messages in thread
From: Sakari Ailus @ 2026-04-09 20:13 UTC (permalink / raw)
  To: linux-media
  Cc: hans, laurent.pinchart, Prabhakar, Kate Hsuan, Dave Stevenson,
	Tommaso Merciai, Benjamin Mugnier, Sylvain Petinot,
	Christophe JAILLET, Julien Massot, Naushir Patuck, Stefan Klug,
	Mirela Rabulea, André Apitzsch, Heimir Thor Sverrisson,
	Kieran Bingham, Mehdi Djait, Ricardo Ribalda Delgado,
	Hans de Goede, Jacopo Mondi, Tomi Valkeinen, David Plowman,
	Yu, Ong Hock, Ng, Khai Wen, Jai Luthra, Rishikesh Donadkar

Document the use of raw mbus codes for camera sensors and how the
V4L2_CID_CFA_PATTERN and V4L2_CID_CFA_PATTERN_FLIP controls are used to
convey the color filter array pattern on UAPI.

Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 .../userspace-api/media/drivers/camera-sensor.rst   | 13 +++++++++++++
 1 file changed, 13 insertions(+)

diff --git a/Documentation/userspace-api/media/drivers/camera-sensor.rst b/Documentation/userspace-api/media/drivers/camera-sensor.rst
index 75fd9166383f..75d783b75c48 100644
--- a/Documentation/userspace-api/media/drivers/camera-sensor.rst
+++ b/Documentation/userspace-api/media/drivers/camera-sensor.rst
@@ -39,6 +39,19 @@ format set on a source pad at the end of the device's internal pipeline.
 
 Most sensor drivers are implemented this way.
 
+V4L2_CID_CFA_PATTERN, raw mbus formats, flipping and cropping
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+For raw image data originating from camera sensors, specific :ref:`raw mbus
+codes MEDIA_BUS_FMT_RAW_x (where 'x' is the bit depth)
+<v4l2-mbus-pixelcode-generic-raw>` are used as Color Filter Array (CFA) agnostic
+raw formats. The :ref:`V4L2_CID_CFA_PATTERN <image-source-control-cfa-pattern>`
+control in the same sub-device defines the native CFA pattern of the
+device. Flipping may further affect the readout pattern as indicated by the
+:ref:`V4L2_CID_CFA_PATTERN_FLIP <image-source-control-cfa-pattern-flip>`
+control. Further on, cropping also has an effect on the pattern if cropped
+amount is not divisible by the size of the pattern, horizontally and vertically.
+
 Frame interval configuration
 ----------------------------
 
-- 
2.47.3


^ permalink raw reply related	[flat|nested] 88+ messages in thread

* [PATCH v12 11/86] media: uapi: Add V4L2_CID_METADATA_LAYOUT control
  2026-04-09 20:13 [PATCH v12 00/86] Generic line based metadata support, internal pads Sakari Ailus
                   ` (9 preceding siblings ...)
  2026-04-09 20:13 ` [PATCH v12 10/86] media: Documentation: Document raw mbus codes and CFA for cameras Sakari Ailus
@ 2026-04-09 20:13 ` Sakari Ailus
  2026-04-09 20:13 ` [PATCH v12 12/86] media: Documentation: Refer to metadata layout in metadata documentation Sakari Ailus
                   ` (74 subsequent siblings)
  85 siblings, 0 replies; 88+ messages in thread
From: Sakari Ailus @ 2026-04-09 20:13 UTC (permalink / raw)
  To: linux-media
  Cc: hans, laurent.pinchart, Prabhakar, Kate Hsuan, Dave Stevenson,
	Tommaso Merciai, Benjamin Mugnier, Sylvain Petinot,
	Christophe JAILLET, Julien Massot, Naushir Patuck, Stefan Klug,
	Mirela Rabulea, André Apitzsch, Heimir Thor Sverrisson,
	Kieran Bingham, Mehdi Djait, Ricardo Ribalda Delgado,
	Hans de Goede, Jacopo Mondi, Tomi Valkeinen, David Plowman,
	Yu, Ong Hock, Ng, Khai Wen, Jai Luthra, Rishikesh Donadkar

The metadata layout control defines the layout of the metadata on the bus.
It is used on sub-devices that use generic metadata mbus codes on at least
one of the pads.

Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
Reviewed-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
---
 .../userspace-api/media/v4l/ext-ctrls-image-source.rst     | 6 ++++++
 drivers/media/v4l2-core/v4l2-ctrls-defs.c                  | 7 +++++++
 include/uapi/linux/v4l2-controls.h                         | 1 +
 3 files changed, 14 insertions(+)

diff --git a/Documentation/userspace-api/media/v4l/ext-ctrls-image-source.rst b/Documentation/userspace-api/media/v4l/ext-ctrls-image-source.rst
index e1f96987ad59..e369978c2b50 100644
--- a/Documentation/userspace-api/media/v4l/ext-ctrls-image-source.rst
+++ b/Documentation/userspace-api/media/v4l/ext-ctrls-image-source.rst
@@ -152,3 +152,9 @@ Image Source Control IDs
     is provided as well.
 
     This is a read-only control.
+
+``V4L2_CID_METADATA_LAYOUT (integer)``
+    The metadata layout control defines the metadata layout on the device's data
+    interface for metadata streams. The control is used in conjunction with
+    :ref:`generic metadata formats <media-bus-format-generic-meta>` formats to
+    specify the layout of the data.
diff --git a/drivers/media/v4l2-core/v4l2-ctrls-defs.c b/drivers/media/v4l2-core/v4l2-ctrls-defs.c
index 32a4b1b3fc0e..4618252d24f2 100644
--- a/drivers/media/v4l2-core/v4l2-ctrls-defs.c
+++ b/drivers/media/v4l2-core/v4l2-ctrls-defs.c
@@ -1159,6 +1159,7 @@ const char *v4l2_ctrl_get_name(u32 id)
 	case V4L2_CID_NOTIFY_GAINS:		return "Notify Gains";
 	case V4L2_CID_CFA_PATTERN:		return "Color Filter Array Pattern";
 	case V4L2_CID_CFA_PATTERN_FLIP:		return "CFA Pattern Flip";
+	case V4L2_CID_METADATA_LAYOUT:		return "Metadata Layout";
 
 	/* Image processing controls */
 	/* Keep the order of the 'case's the same as in v4l2-controls.h! */
@@ -1322,6 +1323,12 @@ void v4l2_ctrl_fill(u32 id, const char **name, enum v4l2_ctrl_type *type,
 		*min = 0;
 		*max = *step = 1;
 		break;
+	case V4L2_CID_METADATA_LAYOUT:
+		*type = V4L2_CTRL_TYPE_INTEGER;
+		*flags |= V4L2_CTRL_FLAG_READ_ONLY;
+		*min = 0;
+		*step = 1;
+		break;
 	case V4L2_CID_ROTATE:
 		*type = V4L2_CTRL_TYPE_INTEGER;
 		*flags |= V4L2_CTRL_FLAG_MODIFY_LAYOUT;
diff --git a/include/uapi/linux/v4l2-controls.h b/include/uapi/linux/v4l2-controls.h
index d5cedb28a564..2f0bd33bbc3d 100644
--- a/include/uapi/linux/v4l2-controls.h
+++ b/include/uapi/linux/v4l2-controls.h
@@ -1247,6 +1247,7 @@ enum v4l2_jpeg_chroma_subsampling {
 #define V4L2_CFA_PATTERN_FLIP_BOTH \
 	(V4L2_CFA_PATTERN_FLIP_HORIZONTAL | V4L2_CFA_PATTERN_FLIP_VERTICAL)
 
+#define V4L2_CID_METADATA_LAYOUT		(V4L2_CID_IMAGE_SOURCE_CLASS_BASE + 12)
 
 /* Image processing controls */
 
-- 
2.47.3


^ permalink raw reply related	[flat|nested] 88+ messages in thread

* [PATCH v12 12/86] media: Documentation: Refer to metadata layout in metadata documentation
  2026-04-09 20:13 [PATCH v12 00/86] Generic line based metadata support, internal pads Sakari Ailus
                   ` (10 preceding siblings ...)
  2026-04-09 20:13 ` [PATCH v12 11/86] media: uapi: Add V4L2_CID_METADATA_LAYOUT control Sakari Ailus
@ 2026-04-09 20:13 ` Sakari Ailus
  2026-04-09 20:13 ` [PATCH v12 13/86] media: Documentation: v4l: Document internal sink pads Sakari Ailus
                   ` (73 subsequent siblings)
  85 siblings, 0 replies; 88+ messages in thread
From: Sakari Ailus @ 2026-04-09 20:13 UTC (permalink / raw)
  To: linux-media
  Cc: hans, laurent.pinchart, Prabhakar, Kate Hsuan, Dave Stevenson,
	Tommaso Merciai, Benjamin Mugnier, Sylvain Petinot,
	Christophe JAILLET, Julien Massot, Naushir Patuck, Stefan Klug,
	Mirela Rabulea, André Apitzsch, Heimir Thor Sverrisson,
	Kieran Bingham, Mehdi Djait, Ricardo Ribalda Delgado,
	Hans de Goede, Jacopo Mondi, Tomi Valkeinen, David Plowman,
	Yu, Ong Hock, Ng, Khai Wen, Jai Luthra, Rishikesh Donadkar

Using generic metadata mbus codes requires the use of
V4L2_CID_METADATA_LAYOUT control to define the metadata layout. Document
this in generic metadata format documentation.

Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
Reviewed-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 Documentation/userspace-api/media/v4l/metafmt-generic.rst | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/Documentation/userspace-api/media/v4l/metafmt-generic.rst b/Documentation/userspace-api/media/v4l/metafmt-generic.rst
index 23f69e1a1afa..7226b4810088 100644
--- a/Documentation/userspace-api/media/v4l/metafmt-generic.rst
+++ b/Documentation/userspace-api/media/v4l/metafmt-generic.rst
@@ -8,12 +8,16 @@ V4L2_META_FMT_GENERIC_8 ('MET8'), V4L2_META_FMT_GENERIC_CSI2_10 ('MC1A'), V4L2_M
 
 Generic line-based metadata formats
 
-
 Description
 ===========
 
 These generic line-based metadata formats define the memory layout of the data
-without defining the format or meaning of the metadata itself.
+without defining the format or meaning of the metadata itself. These formats may
+only be used with a Media Controller pipeline where the exact metadata layout is
+reported using the :ref:`V4L2_CID_METADATA_LAYOUT control
+<image_source_control_metadata_layout>` by the sub-device generating the
+metadata. See also :ref:`source routes <subdev-routing>`.
+
 
 .. _v4l2-meta-fmt-generic-8:
 
-- 
2.47.3


^ permalink raw reply related	[flat|nested] 88+ messages in thread

* [PATCH v12 13/86] media: Documentation: v4l: Document internal sink pads
  2026-04-09 20:13 [PATCH v12 00/86] Generic line based metadata support, internal pads Sakari Ailus
                   ` (11 preceding siblings ...)
  2026-04-09 20:13 ` [PATCH v12 12/86] media: Documentation: Refer to metadata layout in metadata documentation Sakari Ailus
@ 2026-04-09 20:13 ` Sakari Ailus
  2026-04-09 20:13 ` [PATCH v12 14/86] media: Documentation: Document embedded data guidelines for camera sensors Sakari Ailus
                   ` (72 subsequent siblings)
  85 siblings, 0 replies; 88+ messages in thread
From: Sakari Ailus @ 2026-04-09 20:13 UTC (permalink / raw)
  To: linux-media
  Cc: hans, laurent.pinchart, Prabhakar, Kate Hsuan, Dave Stevenson,
	Tommaso Merciai, Benjamin Mugnier, Sylvain Petinot,
	Christophe JAILLET, Julien Massot, Naushir Patuck, Stefan Klug,
	Mirela Rabulea, André Apitzsch, Heimir Thor Sverrisson,
	Kieran Bingham, Mehdi Djait, Ricardo Ribalda Delgado,
	Hans de Goede, Jacopo Mondi, Tomi Valkeinen, David Plowman,
	Yu, Ong Hock, Ng, Khai Wen, Jai Luthra, Rishikesh Donadkar

Document internal sink pads, pads that have both SINK and INTERNAL flags
set. Use the IMX219 camera sensor as an example.

Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
Reviewed-by: Julien Massot <julien.massot@collabora.com>
Reviewed-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Reviewed-by: Mirela Rabulea <mirela.rabulea@nxp.com>
---
 .../userspace-api/media/v4l/dev-subdev.rst    | 24 +++++++++++++++++++
 .../media/v4l/ext-ctrls-image-source.rst      |  2 ++
 2 files changed, 26 insertions(+)

diff --git a/Documentation/userspace-api/media/v4l/dev-subdev.rst b/Documentation/userspace-api/media/v4l/dev-subdev.rst
index 142e2cd95062..39c281991460 100644
--- a/Documentation/userspace-api/media/v4l/dev-subdev.rst
+++ b/Documentation/userspace-api/media/v4l/dev-subdev.rst
@@ -554,6 +554,25 @@ A stream at a specific point in the media pipeline is identified by the
 sub-device and a (pad, stream) pair. For sub-devices that do not support
 multiplexed streams the 'stream' field is always 0.
 
+Internal sink pads and routing
+------------------------------
+
+Cases where a single sub-device source pad is carries multiple streams, one or
+more of which originate from within the sub-device itself, are special as there
+is no external sink pad for such routes. In those cases, the sources of the
+internally generated streams are represented by internal sink pads, which are
+sink pads that have the :ref:`MEDIA_PAD_FL_INTERNAL <MEDIA-PAD-FL-INTERNAL>` pad
+flag set.
+
+Internal pads have all the properties of an external pad, including formats and
+selections. The format in this case is the source format of the stream. An
+internal pad always has a single stream only (0).
+
+Routes from an internal sink pad to an external source pad are created by the
+driver and can be activated and deactivated using the
+:ref:`V4L2_SUBDEV_ROUTE_FL_ACTIVE <v4l2-subdev-routing-flags>` flag, depending
+on the device capabilities.
+
 Interaction between routes, streams, formats and selections
 -----------------------------------------------------------
 
@@ -691,3 +710,8 @@ To configure this pipeline, the userspace must take the following steps:
    the configurations along the stream towards the receiver, using
    :ref:`VIDIOC_SUBDEV_S_FMT <VIDIOC_SUBDEV_G_FMT>` ioctls to configure each
    stream endpoint in each sub-device.
+
+   In case generic raw and metadata formats are used, :ref:`V4L2_CID_CFA_PATTERN
+   <image-source-control-cfa-pattern>` and :ref:`V4L2_CID_METADATA_LAYOUT
+   <image_source_control_metadata_layout>` controls are present on the source
+   sub-device to obtain the pixel array CFA pattern and metadata layout.
diff --git a/Documentation/userspace-api/media/v4l/ext-ctrls-image-source.rst b/Documentation/userspace-api/media/v4l/ext-ctrls-image-source.rst
index e369978c2b50..490cd16186cd 100644
--- a/Documentation/userspace-api/media/v4l/ext-ctrls-image-source.rst
+++ b/Documentation/userspace-api/media/v4l/ext-ctrls-image-source.rst
@@ -153,6 +153,8 @@ Image Source Control IDs
 
     This is a read-only control.
 
+.. _image_source_control_metadata_layout:
+
 ``V4L2_CID_METADATA_LAYOUT (integer)``
     The metadata layout control defines the metadata layout on the device's data
     interface for metadata streams. The control is used in conjunction with
-- 
2.47.3


^ permalink raw reply related	[flat|nested] 88+ messages in thread

* [PATCH v12 14/86] media: Documentation: Document embedded data guidelines for camera sensors
  2026-04-09 20:13 [PATCH v12 00/86] Generic line based metadata support, internal pads Sakari Ailus
                   ` (12 preceding siblings ...)
  2026-04-09 20:13 ` [PATCH v12 13/86] media: Documentation: v4l: Document internal sink pads Sakari Ailus
@ 2026-04-09 20:13 ` Sakari Ailus
  2026-04-09 20:13 ` [PATCH v12 15/86] media: Documentation: Document non-CCS use of CCS embedded data layout Sakari Ailus
                   ` (71 subsequent siblings)
  85 siblings, 0 replies; 88+ messages in thread
From: Sakari Ailus @ 2026-04-09 20:13 UTC (permalink / raw)
  To: linux-media
  Cc: hans, laurent.pinchart, Prabhakar, Kate Hsuan, Dave Stevenson,
	Tommaso Merciai, Benjamin Mugnier, Sylvain Petinot,
	Christophe JAILLET, Julien Massot, Naushir Patuck, Stefan Klug,
	Mirela Rabulea, André Apitzsch, Heimir Thor Sverrisson,
	Kieran Bingham, Mehdi Djait, Ricardo Ribalda Delgado,
	Hans de Goede, Jacopo Mondi, Tomi Valkeinen, David Plowman,
	Yu, Ong Hock, Ng, Khai Wen, Jai Luthra, Rishikesh Donadkar

Document how embedded data support should be implemented for camera
sensors, and when and how CCS embedded data layout should be referenced.

Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
Reviewed-by: Julien Massot <julien.massot@collabora.com>
Reviewed-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
---
 .../media/drivers/camera-sensor.rst           | 19 +++++++++++++++++++
 1 file changed, 19 insertions(+)

diff --git a/Documentation/userspace-api/media/drivers/camera-sensor.rst b/Documentation/userspace-api/media/drivers/camera-sensor.rst
index 75d783b75c48..87f86a2f6cc5 100644
--- a/Documentation/userspace-api/media/drivers/camera-sensor.rst
+++ b/Documentation/userspace-api/media/drivers/camera-sensor.rst
@@ -117,3 +117,22 @@ register programming sequences shall initialize the :ref:`V4L2_CID_HFLIP
 values programmed by the register sequences. The default values of these
 controls shall be 0 (disabled). Especially these controls shall not be inverted,
 independently of the sensor's mounting rotation.
+
+Embedded data
+-------------
+
+Many sensors, mostly raw sensors, support embedded data which is used to convey
+the sensor configuration for the captured frame back to the host. While CSI-2 is
+the most common data interface used by such sensors, embedded data can be
+available on other interfaces as well.
+
+Embedded data support is indicated by the presence of an internal sink pad (pad
+that has both the :ref:`MEDIA_PAD_FL_SINK <MEDIA-PAD-FL-SINK>` and
+:ref:`MEDIA_PAD_FL_INTERNAL <MEDIA-PAD-FL-INTERNAL>` flags set) with a metadata
+format to model the embedded data stream. If the sub-device driver supports
+disabling embedded data, this can be done by disabling the embedded data route
+via the ``VIDIOC_SUBDEV_S_ROUTING`` IOCTL.
+
+In general, changing the embedded data layout from the driver-configured values
+is not supported. The width of the metadata is device-specific and equal to or
+less than the width of the image data, as configured on the pixel data stream.
-- 
2.47.3


^ permalink raw reply related	[flat|nested] 88+ messages in thread

* [PATCH v12 15/86] media: Documentation: Document non-CCS use of CCS embedded data layout
  2026-04-09 20:13 [PATCH v12 00/86] Generic line based metadata support, internal pads Sakari Ailus
                   ` (13 preceding siblings ...)
  2026-04-09 20:13 ` [PATCH v12 14/86] media: Documentation: Document embedded data guidelines for camera sensors Sakari Ailus
@ 2026-04-09 20:13 ` Sakari Ailus
  2026-04-09 20:13 ` [PATCH v12 16/86] media: uapi: Correct generic CSI-2 metadata format 4cc Sakari Ailus
                   ` (70 subsequent siblings)
  85 siblings, 0 replies; 88+ messages in thread
From: Sakari Ailus @ 2026-04-09 20:13 UTC (permalink / raw)
  To: linux-media
  Cc: hans, laurent.pinchart, Prabhakar, Kate Hsuan, Dave Stevenson,
	Tommaso Merciai, Benjamin Mugnier, Sylvain Petinot,
	Christophe JAILLET, Julien Massot, Naushir Patuck, Stefan Klug,
	Mirela Rabulea, André Apitzsch, Heimir Thor Sverrisson,
	Kieran Bingham, Mehdi Djait, Ricardo Ribalda Delgado,
	Hans de Goede, Jacopo Mondi, Tomi Valkeinen, David Plowman,
	Yu, Ong Hock, Ng, Khai Wen, Jai Luthra, Rishikesh Donadkar

The CCS embedded data layout has multiple aspects (packing, encoding and
the rest, including register addresses and semantics). Explicitly allow
non-compliant embedded data to use the two former to reduce redundant
documentation.

Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 .../userspace-api/media/drivers/camera-sensor.rst   | 13 +++++++++++++
 1 file changed, 13 insertions(+)

diff --git a/Documentation/userspace-api/media/drivers/camera-sensor.rst b/Documentation/userspace-api/media/drivers/camera-sensor.rst
index 87f86a2f6cc5..88d8c5c04e54 100644
--- a/Documentation/userspace-api/media/drivers/camera-sensor.rst
+++ b/Documentation/userspace-api/media/drivers/camera-sensor.rst
@@ -136,3 +136,16 @@ via the ``VIDIOC_SUBDEV_S_ROUTING`` IOCTL.
 In general, changing the embedded data layout from the driver-configured values
 is not supported. The width of the metadata is device-specific and equal to or
 less than the width of the image data, as configured on the pixel data stream.
+
+CCS and non-CCS embedded data layout
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Embedded data which is fully compliant with CCS definitions uses :ref:`CCS
+embedded data layout <media-metadata-layout-ccs>` (level 3) for :ref:`the
+metadata layout control <image_source_control_metadata_layout>`. Device-specific
+embedded data compliant with either MIPI CCS embedded data levels 1 or 2 only
+shall not use CCS embedded data value ``V4L2_METADATA_LAYOUT_CCS`` for metadata
+layout, but may refer to CCS embedded data documentation with the level of
+conformance specified and omit documenting these aspects of the layout. The rest
+of the device-specific embedded data layout is documented in the context of the
+data layout itself.
-- 
2.47.3


^ permalink raw reply related	[flat|nested] 88+ messages in thread

* [PATCH v12 16/86] media: uapi: Correct generic CSI-2 metadata format 4cc
  2026-04-09 20:13 [PATCH v12 00/86] Generic line based metadata support, internal pads Sakari Ailus
                   ` (14 preceding siblings ...)
  2026-04-09 20:13 ` [PATCH v12 15/86] media: Documentation: Document non-CCS use of CCS embedded data layout Sakari Ailus
@ 2026-04-09 20:13 ` Sakari Ailus
  2026-04-09 20:13 ` [PATCH v12 17/86] Revert "media: uapi: v4l: Don't expose generic metadata formats to userspace" Sakari Ailus
                   ` (69 subsequent siblings)
  85 siblings, 0 replies; 88+ messages in thread
From: Sakari Ailus @ 2026-04-09 20:13 UTC (permalink / raw)
  To: linux-media
  Cc: hans, laurent.pinchart, Prabhakar, Kate Hsuan, Dave Stevenson,
	Tommaso Merciai, Benjamin Mugnier, Sylvain Petinot,
	Christophe JAILLET, Julien Massot, Naushir Patuck, Stefan Klug,
	Mirela Rabulea, André Apitzsch, Heimir Thor Sverrisson,
	Kieran Bingham, Mehdi Djait, Ricardo Ribalda Delgado,
	Hans de Goede, Jacopo Mondi, Tomi Valkeinen, David Plowman,
	Yu, Ong Hock, Ng, Khai Wen, Jai Luthra, Rishikesh Donadkar

Rework the pixelformat 4cc for CSI-2 generic metadata, the 16- and 24-bit
variants are not specific to CSI-2. This can be done as no driver uses
this yet and the interface is disabled.

Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
Reviewed-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 .../media/v4l/metafmt-generic.rst             | 40 +++++++++----------
 .../media/pci/intel/ipu6/ipu6-isys-video.c    |  2 +-
 drivers/media/v4l2-core/v4l2-ioctl.c          |  8 ++--
 include/uapi/linux/videodev2.h                | 12 +++---
 4 files changed, 30 insertions(+), 32 deletions(-)

diff --git a/Documentation/userspace-api/media/v4l/metafmt-generic.rst b/Documentation/userspace-api/media/v4l/metafmt-generic.rst
index 7226b4810088..07147b4d0dd2 100644
--- a/Documentation/userspace-api/media/v4l/metafmt-generic.rst
+++ b/Documentation/userspace-api/media/v4l/metafmt-generic.rst
@@ -2,7 +2,7 @@
 .. c:namespace:: V4L
 
 ********************************************************************************************************************************************************************************************************************************************************************************
-V4L2_META_FMT_GENERIC_8 ('MET8'), V4L2_META_FMT_GENERIC_CSI2_10 ('MC1A'), V4L2_META_FMT_GENERIC_CSI2_12 ('MC1C'), V4L2_META_FMT_GENERIC_CSI2_14 ('MC1E'), V4L2_META_FMT_GENERIC_CSI2_16 ('MC1G'), V4L2_META_FMT_GENERIC_CSI2_20 ('MC1K'), V4L2_META_FMT_GENERIC_CSI2_24 ('MC1O')
+V4L2_META_FMT_GENERIC_8 ('MET8'), V4L2_META_FMT_GENERIC_CSI2_10 ('MECA'), V4L2_META_FMT_GENERIC_CSI2_12 ('MECC'), V4L2_META_FMT_GENERIC_CSI2_14 ('MECE'), V4L2_META_FMT_GENERIC_16 ('METG'), V4L2_META_FMT_GENERIC_CSI2_20 ('MECK'), V4L2_META_FMT_GENERIC_24 ('METO')
 ********************************************************************************************************************************************************************************************************************************************************************************
 
 
@@ -29,7 +29,7 @@ is used on CSI-2 for 8 bits per :term:`Data Unit`.
 
 Additionally it is used for 16 bits per Data Unit when two bytes of metadata are
 packed into one 16-bit Data Unit. Otherwise the 16 bits per pixel dataformat is
-:ref:`V4L2_META_FMT_GENERIC_CSI2_16 <v4l2-meta-fmt-generic-csi2-16>`.
+:ref:`V4L2_META_FMT_GENERIC_16 <v4l2-meta-fmt-generic-16>`.
 
 **Byte Order Of V4L2_META_FMT_GENERIC_8.**
 Each cell is one byte. "M" denotes a byte of metadata.
@@ -112,8 +112,8 @@ the data is defined in the MIPI CCS specification.
 
 This format is also used in conjunction with 24 bits per :term:`Data Unit`
 formats that pack two bytes of metadata into one Data Unit. Otherwise the
-24 bits per pixel dataformat is :ref:`V4L2_META_FMT_GENERIC_CSI2_24
-<v4l2-meta-fmt-generic-csi2-24>`.
+24 bits per pixel dataformat is :ref:`V4L2_META_FMT_GENERIC_24
+<v4l2-meta-fmt-generic-24>`.
 
 This format is little endian.
 
@@ -185,16 +185,15 @@ Each cell is one byte. "M" denotes a byte of metadata and "x" a byte of padding.
       - x
       - x
 
-.. _v4l2-meta-fmt-generic-csi2-16:
+.. _v4l2-meta-fmt-generic-16:
 
-V4L2_META_FMT_GENERIC_CSI2_16
------------------------------
+V4L2_META_FMT_GENERIC_16
+------------------------
 
-V4L2_META_FMT_GENERIC_CSI2_16 contains 8-bit generic metadata packed in 16-bit
-Data Units, with one padding byte after every byte of metadata. This format is
-typically used by CSI-2 receivers with a source that transmits
-MEDIA_BUS_FMT_META_16 and the CSI-2 receiver writes the received data to memory
-as-is.
+V4L2_META_FMT_GENERIC_16 contains 8-bit generic metadata packed in 16-bit Data
+Units, with one padding byte after every byte of metadata. This format is also
+used by CSI-2 receivers with a source that transmits MEDIA_BUS_FMT_META_16 and
+the CSI-2 receiver writes the received data to memory as-is.
 
 The packing of the data follows the MIPI CSI-2 specification and the padding of
 the data is defined in the MIPI CCS specification.
@@ -205,7 +204,7 @@ Some devices support more efficient packing of metadata in conjunction with
 
 This format is little endian.
 
-**Byte Order Of V4L2_META_FMT_GENERIC_CSI2_16.**
+**Byte Order Of V4L2_META_FMT_GENERIC_16.**
 Each cell is one byte. "M" denotes a byte of metadata and "x" a byte of padding.
 
 .. tabularcolumns:: |p{2.4cm}|p{1.2cm}|p{.8cm}|p{1.2cm}|p{.8cm}|p{1.2cm}|p{.8cm}|p{1.2cm}|p{.8cm}|
@@ -287,16 +286,15 @@ Each cell is one byte. "M" denotes a byte of metadata and "x" a byte of padding.
       - x
       - x
 
-.. _v4l2-meta-fmt-generic-csi2-24:
+.. _v4l2-meta-fmt-generic-24:
 
-V4L2_META_FMT_GENERIC_CSI2_24
------------------------------
+V4L2_META_FMT_GENERIC_24
+------------------------
 
-V4L2_META_FMT_GENERIC_CSI2_24 contains 8-bit generic metadata packed in 24-bit
-Data Units, with two padding bytes after every byte of metadata. This format is
-typically used by CSI-2 receivers with a source that transmits
-MEDIA_BUS_FMT_META_24 and the CSI-2 receiver writes the received data to memory
-as-is.
+V4L2_META_FMT_GENERIC_24 contains 8-bit generic metadata packed in 24-bit Data
+Units, with two padding bytes after every byte of metadata. This format is also
+used by CSI-2 receivers with a source that transmits MEDIA_BUS_FMT_META_24 and
+the CSI-2 receiver writes the received data to memory as-is.
 
 The packing of the data follows the MIPI CSI-2 specification and the padding of
 the data is defined in the MIPI CCS specification.
diff --git a/drivers/media/pci/intel/ipu6/ipu6-isys-video.c b/drivers/media/pci/intel/ipu6/ipu6-isys-video.c
index 3ac48d2076da..cf0eef64e503 100644
--- a/drivers/media/pci/intel/ipu6/ipu6-isys-video.c
+++ b/drivers/media/pci/intel/ipu6/ipu6-isys-video.c
@@ -105,7 +105,7 @@ const struct ipu6_isys_pixelformat ipu6_isys_pfmts[] = {
 	  IPU6_FW_ISYS_FRAME_FORMAT_RAW10, true },
 	{ V4L2_META_FMT_GENERIC_CSI2_12, 12, 12, MEDIA_BUS_FMT_META_12,
 	  IPU6_FW_ISYS_FRAME_FORMAT_RAW12, true },
-	{ V4L2_META_FMT_GENERIC_CSI2_16, 16, 16, MEDIA_BUS_FMT_META_16,
+	{ V4L2_META_FMT_GENERIC_16, 16, 16, MEDIA_BUS_FMT_META_16,
 	  IPU6_FW_ISYS_FRAME_FORMAT_RAW16, true },
 };
 
diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c b/drivers/media/v4l2-core/v4l2-ioctl.c
index 5fda3835f680..8e99cdefead3 100644
--- a/drivers/media/v4l2-core/v4l2-ioctl.c
+++ b/drivers/media/v4l2-core/v4l2-ioctl.c
@@ -1489,9 +1489,9 @@ static void v4l_fill_fmtdesc(struct v4l2_fmtdesc *fmt)
 	case V4L2_META_FMT_GENERIC_CSI2_10:	descr = "8-bit Generic Meta, 10b CSI-2"; break;
 	case V4L2_META_FMT_GENERIC_CSI2_12:	descr = "8-bit Generic Meta, 12b CSI-2"; break;
 	case V4L2_META_FMT_GENERIC_CSI2_14:	descr = "8-bit Generic Meta, 14b CSI-2"; break;
-	case V4L2_META_FMT_GENERIC_CSI2_16:	descr = "8-bit Generic Meta, 16b CSI-2"; break;
+	case V4L2_META_FMT_GENERIC_16:	descr = "8-bit Generic Meta, 16b"; break;
 	case V4L2_META_FMT_GENERIC_CSI2_20:	descr = "8-bit Generic Meta, 20b CSI-2"; break;
-	case V4L2_META_FMT_GENERIC_CSI2_24:	descr = "8-bit Generic Meta, 24b CSI-2"; break;
+	case V4L2_META_FMT_GENERIC_24:	descr = "8-bit Generic Meta, 24b"; break;
 
 	default:
 		/* Compressed formats */
@@ -1579,9 +1579,9 @@ static void v4l_fill_fmtdesc(struct v4l2_fmtdesc *fmt)
 		case V4L2_META_FMT_GENERIC_CSI2_10:
 		case V4L2_META_FMT_GENERIC_CSI2_12:
 		case V4L2_META_FMT_GENERIC_CSI2_14:
-		case V4L2_META_FMT_GENERIC_CSI2_16:
+		case V4L2_META_FMT_GENERIC_16:
 		case V4L2_META_FMT_GENERIC_CSI2_20:
-		case V4L2_META_FMT_GENERIC_CSI2_24:
+		case V4L2_META_FMT_GENERIC_24:
 			fmt->flags |= V4L2_FMT_FLAG_META_LINE_BASED;
 			break;
 		default:
diff --git a/include/uapi/linux/videodev2.h b/include/uapi/linux/videodev2.h
index 901c2b788edd..fe5bb00ffe91 100644
--- a/include/uapi/linux/videodev2.h
+++ b/include/uapi/linux/videodev2.h
@@ -901,12 +901,12 @@ struct v4l2_pix_format {
  * adding new ones!
  */
 #define V4L2_META_FMT_GENERIC_8		v4l2_fourcc('M', 'E', 'T', '8') /* Generic 8-bit metadata */
-#define V4L2_META_FMT_GENERIC_CSI2_10	v4l2_fourcc('M', 'C', '1', 'A') /* 10-bit CSI-2 packed 8-bit metadata */
-#define V4L2_META_FMT_GENERIC_CSI2_12	v4l2_fourcc('M', 'C', '1', 'C') /* 12-bit CSI-2 packed 8-bit metadata */
-#define V4L2_META_FMT_GENERIC_CSI2_14	v4l2_fourcc('M', 'C', '1', 'E') /* 14-bit CSI-2 packed 8-bit metadata */
-#define V4L2_META_FMT_GENERIC_CSI2_16	v4l2_fourcc('M', 'C', '1', 'G') /* 16-bit CSI-2 packed 8-bit metadata */
-#define V4L2_META_FMT_GENERIC_CSI2_20	v4l2_fourcc('M', 'C', '1', 'K') /* 20-bit CSI-2 packed 8-bit metadata */
-#define V4L2_META_FMT_GENERIC_CSI2_24	v4l2_fourcc('M', 'C', '1', 'O') /* 24-bit CSI-2 packed 8-bit metadata */
+#define V4L2_META_FMT_GENERIC_CSI2_10	v4l2_fourcc('M', 'E', 'C', 'A') /* 10-bit CSI-2 packed 8-bit metadata */
+#define V4L2_META_FMT_GENERIC_CSI2_12	v4l2_fourcc('M', 'E', 'C', 'C') /* 12-bit CSI-2 packed 8-bit metadata */
+#define V4L2_META_FMT_GENERIC_CSI2_14	v4l2_fourcc('M', 'E', 'C', 'E') /* 14-bit CSI-2 packed 8-bit metadata */
+#define V4L2_META_FMT_GENERIC_16	v4l2_fourcc('M', 'E', 'T', 'G') /* Generic 16-bit 8-bit metadata */
+#define V4L2_META_FMT_GENERIC_CSI2_20	v4l2_fourcc('M', 'E', 'C', 'K') /* 20-bit CSI-2 packed 8-bit metadata */
+#define V4L2_META_FMT_GENERIC_24	v4l2_fourcc('M', 'E', 'T', 'O') /* Generic 24-bit 8-bit metadata */
 #endif
 
 /* priv field value to indicates that subsequent fields are valid. */
-- 
2.47.3


^ permalink raw reply related	[flat|nested] 88+ messages in thread

* [PATCH v12 17/86] Revert "media: uapi: v4l: Don't expose generic metadata formats to userspace"
  2026-04-09 20:13 [PATCH v12 00/86] Generic line based metadata support, internal pads Sakari Ailus
                   ` (15 preceding siblings ...)
  2026-04-09 20:13 ` [PATCH v12 16/86] media: uapi: Correct generic CSI-2 metadata format 4cc Sakari Ailus
@ 2026-04-09 20:13 ` Sakari Ailus
  2026-04-09 20:13 ` [PATCH v12 18/86] media: v4l: Add V4L2_SUBDEV_ROUTE_FL_IMMUTABLE sub-device routing flag Sakari Ailus
                   ` (68 subsequent siblings)
  85 siblings, 0 replies; 88+ messages in thread
From: Sakari Ailus @ 2026-04-09 20:13 UTC (permalink / raw)
  To: linux-media
  Cc: hans, laurent.pinchart, Prabhakar, Kate Hsuan, Dave Stevenson,
	Tommaso Merciai, Benjamin Mugnier, Sylvain Petinot,
	Christophe JAILLET, Julien Massot, Naushir Patuck, Stefan Klug,
	Mirela Rabulea, André Apitzsch, Heimir Thor Sverrisson,
	Kieran Bingham, Mehdi Djait, Ricardo Ribalda Delgado,
	Hans de Goede, Jacopo Mondi, Tomi Valkeinen, David Plowman,
	Yu, Ong Hock, Ng, Khai Wen, Jai Luthra, Rishikesh Donadkar

This reverts commit d69c8429ea80af02e89e5b3eecb78e417ad049c8.

Now that the API has stabilised, make the generic metadata formats visible
for the userspace again.

Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
Reviewed-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 include/uapi/linux/videodev2.h | 2 --
 1 file changed, 2 deletions(-)

diff --git a/include/uapi/linux/videodev2.h b/include/uapi/linux/videodev2.h
index fe5bb00ffe91..3ba872deeeb9 100644
--- a/include/uapi/linux/videodev2.h
+++ b/include/uapi/linux/videodev2.h
@@ -895,7 +895,6 @@ struct v4l2_pix_format {
 #define V4L2_META_FMT_MALI_C55_PARAMS	v4l2_fourcc('C', '5', '5', 'P') /* ARM Mali-C55 Parameters */
 #define V4L2_META_FMT_MALI_C55_STATS	v4l2_fourcc('C', '5', '5', 'S') /* ARM Mali-C55 3A Statistics */
 
-#ifdef __KERNEL__
 /*
  * Line-based metadata formats. Remember to update v4l_fill_fmtdesc() when
  * adding new ones!
@@ -907,7 +906,6 @@ struct v4l2_pix_format {
 #define V4L2_META_FMT_GENERIC_16	v4l2_fourcc('M', 'E', 'T', 'G') /* Generic 16-bit 8-bit metadata */
 #define V4L2_META_FMT_GENERIC_CSI2_20	v4l2_fourcc('M', 'E', 'C', 'K') /* 20-bit CSI-2 packed 8-bit metadata */
 #define V4L2_META_FMT_GENERIC_24	v4l2_fourcc('M', 'E', 'T', 'O') /* Generic 24-bit 8-bit metadata */
-#endif
 
 /* priv field value to indicates that subsequent fields are valid. */
 #define V4L2_PIX_FMT_PRIV_MAGIC		0xfeedcafe
-- 
2.47.3


^ permalink raw reply related	[flat|nested] 88+ messages in thread

* [PATCH v12 18/86] media: v4l: Add V4L2_SUBDEV_ROUTE_FL_IMMUTABLE sub-device routing flag
  2026-04-09 20:13 [PATCH v12 00/86] Generic line based metadata support, internal pads Sakari Ailus
                   ` (16 preceding siblings ...)
  2026-04-09 20:13 ` [PATCH v12 17/86] Revert "media: uapi: v4l: Don't expose generic metadata formats to userspace" Sakari Ailus
@ 2026-04-09 20:13 ` Sakari Ailus
  2026-04-09 20:13 ` [PATCH v12 19/86] media: v4l: Add V4L2_SUBDEV_ROUTE_FL_STATIC " Sakari Ailus
                   ` (67 subsequent siblings)
  85 siblings, 0 replies; 88+ messages in thread
From: Sakari Ailus @ 2026-04-09 20:13 UTC (permalink / raw)
  To: linux-media
  Cc: hans, laurent.pinchart, Prabhakar, Kate Hsuan, Dave Stevenson,
	Tommaso Merciai, Benjamin Mugnier, Sylvain Petinot,
	Christophe JAILLET, Julien Massot, Naushir Patuck, Stefan Klug,
	Mirela Rabulea, André Apitzsch, Heimir Thor Sverrisson,
	Kieran Bingham, Mehdi Djait, Ricardo Ribalda Delgado,
	Hans de Goede, Jacopo Mondi, Tomi Valkeinen, David Plowman,
	Yu, Ong Hock, Ng, Khai Wen, Jai Luthra, Rishikesh Donadkar

Add a flag to denote immutable routes, V4L2_SUBDEV_ROUTE_FL_IMMUTABLE.
Such routes cannot be changed and they're always active.

Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 Documentation/userspace-api/media/v4l/dev-subdev.rst         | 4 +++-
 .../userspace-api/media/v4l/vidioc-subdev-g-routing.rst      | 5 +++++
 include/uapi/linux/v4l2-subdev.h                             | 5 +++++
 3 files changed, 13 insertions(+), 1 deletion(-)

diff --git a/Documentation/userspace-api/media/v4l/dev-subdev.rst b/Documentation/userspace-api/media/v4l/dev-subdev.rst
index 39c281991460..78842b9fbe67 100644
--- a/Documentation/userspace-api/media/v4l/dev-subdev.rst
+++ b/Documentation/userspace-api/media/v4l/dev-subdev.rst
@@ -571,7 +571,9 @@ internal pad always has a single stream only (0).
 Routes from an internal sink pad to an external source pad are created by the
 driver and can be activated and deactivated using the
 :ref:`V4L2_SUBDEV_ROUTE_FL_ACTIVE <v4l2-subdev-routing-flags>` flag, depending
-on the device capabilities.
+on the device capabilities. The :ref:`V4L2_SUBDEV_ROUTE_FL_IMMUTABLE
+<v4l2-subdev-routing-flags>` flag indicates that the
+``V4L2_SUBDEV_ROUTE_FLAG_ACTIVE`` of the route may not be unset.
 
 Interaction between routes, streams, formats and selections
 -----------------------------------------------------------
diff --git a/Documentation/userspace-api/media/v4l/vidioc-subdev-g-routing.rst b/Documentation/userspace-api/media/v4l/vidioc-subdev-g-routing.rst
index 6f66ca38589e..2fd55d875075 100644
--- a/Documentation/userspace-api/media/v4l/vidioc-subdev-g-routing.rst
+++ b/Documentation/userspace-api/media/v4l/vidioc-subdev-g-routing.rst
@@ -146,6 +146,11 @@ wants to retrieve the missing routes, it can issue a new
     * - V4L2_SUBDEV_ROUTE_FL_ACTIVE
       - 0x0001
       - The route is enabled. Set by applications.
+    * - V4L2_SUBDEV_ROUTE_FL_IMMUTABLE
+      - 0x0002
+      - The route is immutable. Set by the driver. Indicates that the
+	``V4L2_SUBDEV_ROUTE_FL_ACTIVE`` flag of an immutable route may not be
+	unset.
 
 Return Value
 ============
diff --git a/include/uapi/linux/v4l2-subdev.h b/include/uapi/linux/v4l2-subdev.h
index 6160c3e21436..2be7db814288 100644
--- a/include/uapi/linux/v4l2-subdev.h
+++ b/include/uapi/linux/v4l2-subdev.h
@@ -207,6 +207,11 @@ struct v4l2_subdev_capability {
  * on a video node.
  */
 #define V4L2_SUBDEV_ROUTE_FL_ACTIVE		(1U << 0)
+/*
+ * Is the route immutable? The ACTIVE flag of an immutable route may not be
+ * unset.
+ */
+#define V4L2_SUBDEV_ROUTE_FL_IMMUTABLE		(1U << 1)
 
 /**
  * struct v4l2_subdev_route - A route inside a subdev
-- 
2.47.3


^ permalink raw reply related	[flat|nested] 88+ messages in thread

* [PATCH v12 19/86] media: v4l: Add V4L2_SUBDEV_ROUTE_FL_STATIC sub-device routing flag
  2026-04-09 20:13 [PATCH v12 00/86] Generic line based metadata support, internal pads Sakari Ailus
                   ` (17 preceding siblings ...)
  2026-04-09 20:13 ` [PATCH v12 18/86] media: v4l: Add V4L2_SUBDEV_ROUTE_FL_IMMUTABLE sub-device routing flag Sakari Ailus
@ 2026-04-09 20:13 ` Sakari Ailus
  2026-04-09 20:13 ` [PATCH v12 20/86] media: Documentation: There are either immutable or mutable routes Sakari Ailus
                   ` (66 subsequent siblings)
  85 siblings, 0 replies; 88+ messages in thread
From: Sakari Ailus @ 2026-04-09 20:13 UTC (permalink / raw)
  To: linux-media
  Cc: hans, laurent.pinchart, Prabhakar, Kate Hsuan, Dave Stevenson,
	Tommaso Merciai, Benjamin Mugnier, Sylvain Petinot,
	Christophe JAILLET, Julien Massot, Naushir Patuck, Stefan Klug,
	Mirela Rabulea, André Apitzsch, Heimir Thor Sverrisson,
	Kieran Bingham, Mehdi Djait, Ricardo Ribalda Delgado,
	Hans de Goede, Jacopo Mondi, Tomi Valkeinen, David Plowman,
	Yu, Ong Hock, Ng, Khai Wen, Jai Luthra, Rishikesh Donadkar

Add a flag to denote static routes, V4L2_SUBDEV_ROUTE_FL_STATIC. Such
routes cannot be removed as they are related to hardware features.

Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
---
 .../userspace-api/media/v4l/vidioc-subdev-g-routing.rst     | 6 +++++-
 include/uapi/linux/v4l2-subdev.h                            | 4 ++++
 2 files changed, 9 insertions(+), 1 deletion(-)

diff --git a/Documentation/userspace-api/media/v4l/vidioc-subdev-g-routing.rst b/Documentation/userspace-api/media/v4l/vidioc-subdev-g-routing.rst
index 2fd55d875075..e99c83d21165 100644
--- a/Documentation/userspace-api/media/v4l/vidioc-subdev-g-routing.rst
+++ b/Documentation/userspace-api/media/v4l/vidioc-subdev-g-routing.rst
@@ -150,7 +150,11 @@ wants to retrieve the missing routes, it can issue a new
       - 0x0002
       - The route is immutable. Set by the driver. Indicates that the
 	``V4L2_SUBDEV_ROUTE_FL_ACTIVE`` flag of an immutable route may not be
-	unset.
+	unset. Implies ``V4L2_SUBDEV_ROUTE_FL_STATIC``.
+    * - ``V4L2_SUBDEV_ROUTE_FL_STATIC``
+      - 0x0004
+      - The route is static. Set by the driver. Indicates that the route is
+        always present and cannot be removed.
 
 Return Value
 ============
diff --git a/include/uapi/linux/v4l2-subdev.h b/include/uapi/linux/v4l2-subdev.h
index 2be7db814288..477d3ce3ddb4 100644
--- a/include/uapi/linux/v4l2-subdev.h
+++ b/include/uapi/linux/v4l2-subdev.h
@@ -212,6 +212,10 @@ struct v4l2_subdev_capability {
  * unset.
  */
 #define V4L2_SUBDEV_ROUTE_FL_IMMUTABLE		(1U << 1)
+/*
+ * Is the route static? Routes with the STATIC flag are not removable.
+ */
+#define V4L2_SUBDEV_ROUTE_FL_STATIC		(1U << 2)
 
 /**
  * struct v4l2_subdev_route - A route inside a subdev
-- 
2.47.3


^ permalink raw reply related	[flat|nested] 88+ messages in thread

* [PATCH v12 20/86] media: Documentation: There are either immutable or mutable routes
  2026-04-09 20:13 [PATCH v12 00/86] Generic line based metadata support, internal pads Sakari Ailus
                   ` (18 preceding siblings ...)
  2026-04-09 20:13 ` [PATCH v12 19/86] media: v4l: Add V4L2_SUBDEV_ROUTE_FL_STATIC " Sakari Ailus
@ 2026-04-09 20:13 ` Sakari Ailus
  2026-04-09 20:13 ` [PATCH v12 21/86] media: Documentation: Document IMMUTABLE and STATIC route flags Sakari Ailus
                   ` (65 subsequent siblings)
  85 siblings, 0 replies; 88+ messages in thread
From: Sakari Ailus @ 2026-04-09 20:13 UTC (permalink / raw)
  To: linux-media
  Cc: hans, laurent.pinchart, Prabhakar, Kate Hsuan, Dave Stevenson,
	Tommaso Merciai, Benjamin Mugnier, Sylvain Petinot,
	Christophe JAILLET, Julien Massot, Naushir Patuck, Stefan Klug,
	Mirela Rabulea, André Apitzsch, Heimir Thor Sverrisson,
	Kieran Bingham, Mehdi Djait, Ricardo Ribalda Delgado,
	Hans de Goede, Jacopo Mondi, Tomi Valkeinen, David Plowman,
	Yu, Ong Hock, Ng, Khai Wen, Jai Luthra, Rishikesh Donadkar

Document that each sub-device may have either immutable or mutable routes,
not both of them.

Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
---
 Documentation/userspace-api/media/v4l/dev-subdev.rst | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/Documentation/userspace-api/media/v4l/dev-subdev.rst b/Documentation/userspace-api/media/v4l/dev-subdev.rst
index 78842b9fbe67..57bd44dbbeea 100644
--- a/Documentation/userspace-api/media/v4l/dev-subdev.rst
+++ b/Documentation/userspace-api/media/v4l/dev-subdev.rst
@@ -616,6 +616,12 @@ and user-created routes are fully replaced when ``VIDIOC_SUBDEV_S_ROUTING`` is
 called on the sub-device. Such newly created routes have the device's default
 configuration for format and selection rectangles.
 
+A sub-device may only have either static routes (routes that have
+``V4L2_SUBDEV_ROUTE_FL_STATIC`` flag set) or routes that are all user-created or
+user-removable (routes that do not have ``V4L2_SUBDEV_ROUTE_FL_STATIC``
+flag). Mixing static and non-static routes is not allowed in the same
+sub-device. This is subject to change in the future.
+
 Configuring streams
 -------------------
 
-- 
2.47.3


^ permalink raw reply related	[flat|nested] 88+ messages in thread

* [PATCH v12 21/86] media: Documentation: Document IMMUTABLE and STATIC route flags
  2026-04-09 20:13 [PATCH v12 00/86] Generic line based metadata support, internal pads Sakari Ailus
                   ` (19 preceding siblings ...)
  2026-04-09 20:13 ` [PATCH v12 20/86] media: Documentation: There are either immutable or mutable routes Sakari Ailus
@ 2026-04-09 20:13 ` Sakari Ailus
  2026-04-09 20:13 ` [PATCH v12 22/86] media: Documentation: Add subdev configuration models, raw sensor model Sakari Ailus
                   ` (64 subsequent siblings)
  85 siblings, 0 replies; 88+ messages in thread
From: Sakari Ailus @ 2026-04-09 20:13 UTC (permalink / raw)
  To: linux-media
  Cc: hans, laurent.pinchart, Prabhakar, Kate Hsuan, Dave Stevenson,
	Tommaso Merciai, Benjamin Mugnier, Sylvain Petinot,
	Christophe JAILLET, Julien Massot, Naushir Patuck, Stefan Klug,
	Mirela Rabulea, André Apitzsch, Heimir Thor Sverrisson,
	Kieran Bingham, Mehdi Djait, Ricardo Ribalda Delgado,
	Hans de Goede, Jacopo Mondi, Tomi Valkeinen, David Plowman,
	Yu, Ong Hock, Ng, Khai Wen, Jai Luthra, Rishikesh Donadkar

Include the V4L2_SUBDEV_ROUTE_FL_IMMUTABLE and V4L2_SUBDEV_ROUTE_FL_STATIC
flags in V4L2 sub-device documentation that discusses routing.

Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
Reviewed-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
---
 .../userspace-api/media/v4l/dev-subdev.rst         | 14 +++++++++-----
 1 file changed, 9 insertions(+), 5 deletions(-)

diff --git a/Documentation/userspace-api/media/v4l/dev-subdev.rst b/Documentation/userspace-api/media/v4l/dev-subdev.rst
index 57bd44dbbeea..6b67f526f312 100644
--- a/Documentation/userspace-api/media/v4l/dev-subdev.rst
+++ b/Documentation/userspace-api/media/v4l/dev-subdev.rst
@@ -602,11 +602,15 @@ depending on the hardware. In all cases, however, only routes that have the
 ``V4L2_SUBDEV_ROUTE_FL_ACTIVE`` flag set are active.
 
 Devices generating the streams may allow enabling and disabling some of the
-routes or have a fixed routing configuration. If the routes can be disabled, not
-declaring the routes (or declaring them without ``V4L2_SUBDEV_ROUTE_FL_ACTIVE``
-flag set) in ``VIDIOC_SUBDEV_S_ROUTING`` will disable the routes.
-``VIDIOC_SUBDEV_S_ROUTING`` will still return such routes back to the user in
-the routes array, with the ``V4L2_SUBDEV_ROUTE_FL_ACTIVE`` flag unset.
+routes or have a fixed routing configuration. Routes that are bound to hardware
+resources and are always present are marked with ``V4L2_SUBDEV_ROUTE_FL_STATIC``
+flag. Static routes that cannot be disabled are marked with
+``V4L2_SUBDEV_ROUTE_FL_IMMUTABLE`` route flag. Static routes can be disabled by
+not declaring the routes (or declaring them without
+``V4L2_SUBDEV_ROUTE_FL_ACTIVE`` flag set) in
+``VIDIOC_SUBDEV_S_ROUTING``. ``VIDIOC_SUBDEV_S_ROUTING`` will still return such
+routes back to the user in the routes array, with the
+``V4L2_SUBDEV_ROUTE_FL_ACTIVE`` flag unset.
 
 Devices transporting the streams almost always have more configurability with
 respect to routing. Typically any route between the sub-device's sink and source
-- 
2.47.3


^ permalink raw reply related	[flat|nested] 88+ messages in thread

* [PATCH v12 22/86] media: Documentation: Add subdev configuration models, raw sensor model
  2026-04-09 20:13 [PATCH v12 00/86] Generic line based metadata support, internal pads Sakari Ailus
                   ` (20 preceding siblings ...)
  2026-04-09 20:13 ` [PATCH v12 21/86] media: Documentation: Document IMMUTABLE and STATIC route flags Sakari Ailus
@ 2026-04-09 20:13 ` Sakari Ailus
  2026-04-09 20:13 ` [PATCH v12 23/86] media: v4l2-subdev: Prevent accessing internal pads without STREAMS cap Sakari Ailus
                   ` (63 subsequent siblings)
  85 siblings, 0 replies; 88+ messages in thread
From: Sakari Ailus @ 2026-04-09 20:13 UTC (permalink / raw)
  To: linux-media
  Cc: hans, laurent.pinchart, Prabhakar, Kate Hsuan, Dave Stevenson,
	Tommaso Merciai, Benjamin Mugnier, Sylvain Petinot,
	Christophe JAILLET, Julien Massot, Naushir Patuck, Stefan Klug,
	Mirela Rabulea, André Apitzsch, Heimir Thor Sverrisson,
	Kieran Bingham, Mehdi Djait, Ricardo Ribalda Delgado,
	Hans de Goede, Jacopo Mondi, Tomi Valkeinen, David Plowman,
	Yu, Ong Hock, Ng, Khai Wen, Jai Luthra, Rishikesh Donadkar

Sub-device configuration models define what V4L2 API elements are
available on a compliant sub-device and how do they behave.

The patch also adds a model for common raw sensors.

Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
Reviewed-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
Reviewed-by: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
Reviewed-by: Mirela Rabulea <mirela.rabulea@nxp.com>
Reviewed-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
---
 .../media/drivers/camera-sensor.rst           |   4 +
 .../media/v4l/common-raw-sensor.dia           | 442 ++++++++++++++++++
 .../media/v4l/common-raw-sensor.svg           | 134 ++++++
 .../userspace-api/media/v4l/dev-subdev.rst    |  11 +-
 .../media/v4l/subdev-config-model.rst         | 250 ++++++++++
 5 files changed, 837 insertions(+), 4 deletions(-)
 create mode 100644 Documentation/userspace-api/media/v4l/common-raw-sensor.dia
 create mode 100644 Documentation/userspace-api/media/v4l/common-raw-sensor.svg
 create mode 100644 Documentation/userspace-api/media/v4l/subdev-config-model.rst

diff --git a/Documentation/userspace-api/media/drivers/camera-sensor.rst b/Documentation/userspace-api/media/drivers/camera-sensor.rst
index 88d8c5c04e54..d8ba809486c5 100644
--- a/Documentation/userspace-api/media/drivers/camera-sensor.rst
+++ b/Documentation/userspace-api/media/drivers/camera-sensor.rst
@@ -18,6 +18,8 @@ binning functionality. The sensor drivers belong to two distinct classes, freely
 configurable and register list-based drivers, depending on how the driver
 configures this functionality.
 
+Also see :ref:`media_subdev_config_model_common_raw_sensor`.
+
 Freely configurable camera sensor drivers
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
@@ -118,6 +120,8 @@ values programmed by the register sequences. The default values of these
 controls shall be 0 (disabled). Especially these controls shall not be inverted,
 independently of the sensor's mounting rotation.
 
+.. _media_using_camera_sensor_drivers_embedded_data:
+
 Embedded data
 -------------
 
diff --git a/Documentation/userspace-api/media/v4l/common-raw-sensor.dia b/Documentation/userspace-api/media/v4l/common-raw-sensor.dia
new file mode 100644
index 000000000000..24b3f2b2a626
--- /dev/null
+++ b/Documentation/userspace-api/media/v4l/common-raw-sensor.dia
@@ -0,0 +1,442 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<dia:diagram xmlns:dia="http://www.lysator.liu.se/~alla/dia/">
+  <dia:diagramdata>
+    <dia:attribute name="background">
+      <dia:color val="#ffffffff"/>
+    </dia:attribute>
+    <dia:attribute name="pagebreak">
+      <dia:color val="#000099ff"/>
+    </dia:attribute>
+    <dia:attribute name="paper">
+      <dia:composite type="paper">
+        <dia:attribute name="name">
+          <dia:string>#A4#</dia:string>
+        </dia:attribute>
+        <dia:attribute name="tmargin">
+          <dia:real val="2.8222"/>
+        </dia:attribute>
+        <dia:attribute name="bmargin">
+          <dia:real val="2.8222"/>
+        </dia:attribute>
+        <dia:attribute name="lmargin">
+          <dia:real val="2.8222"/>
+        </dia:attribute>
+        <dia:attribute name="rmargin">
+          <dia:real val="2.8222"/>
+        </dia:attribute>
+        <dia:attribute name="is_portrait">
+          <dia:boolean val="true"/>
+        </dia:attribute>
+        <dia:attribute name="scaling">
+          <dia:real val="1"/>
+        </dia:attribute>
+        <dia:attribute name="fitto">
+          <dia:boolean val="false"/>
+        </dia:attribute>
+      </dia:composite>
+    </dia:attribute>
+    <dia:attribute name="grid">
+      <dia:composite type="grid">
+        <dia:attribute name="dynamic">
+          <dia:boolean val="true"/>
+        </dia:attribute>
+        <dia:attribute name="width_x">
+          <dia:real val="1"/>
+        </dia:attribute>
+        <dia:attribute name="width_y">
+          <dia:real val="1"/>
+        </dia:attribute>
+        <dia:attribute name="visible_x">
+          <dia:int val="1"/>
+        </dia:attribute>
+        <dia:attribute name="visible_y">
+          <dia:int val="1"/>
+        </dia:attribute>
+        <dia:composite type="color"/>
+      </dia:composite>
+    </dia:attribute>
+    <dia:attribute name="color">
+      <dia:color val="#d8e5e5ff"/>
+    </dia:attribute>
+    <dia:attribute name="guides"/>
+    <dia:attribute name="guide_color">
+      <dia:color val="#00ff00ff"/>
+    </dia:attribute>
+    <dia:attribute name="display">
+      <dia:composite type="display">
+        <dia:attribute name="antialiased">
+          <dia:boolean val="true"/>
+        </dia:attribute>
+        <dia:attribute name="snap-to-grid">
+          <dia:boolean val="false"/>
+        </dia:attribute>
+        <dia:attribute name="snap-to-guides">
+          <dia:boolean val="true"/>
+        </dia:attribute>
+        <dia:attribute name="snap-to-object">
+          <dia:boolean val="true"/>
+        </dia:attribute>
+        <dia:attribute name="show-grid">
+          <dia:boolean val="true"/>
+        </dia:attribute>
+        <dia:attribute name="show-guides">
+          <dia:boolean val="true"/>
+        </dia:attribute>
+        <dia:attribute name="show-connection-points">
+          <dia:boolean val="true"/>
+        </dia:attribute>
+      </dia:composite>
+    </dia:attribute>
+  </dia:diagramdata>
+  <dia:layer name="Background" visible="true" connectable="false"/>
+  <dia:layer name="Background" visible="true" connectable="false"/>
+  <dia:layer name="Background" visible="true" connectable="false"/>
+  <dia:layer name="Background" visible="true" connectable="true" active="true">
+    <dia:object type="Standard - Box" version="0" id="O0">
+      <dia:attribute name="obj_pos">
+        <dia:point val="16.35,11.5"/>
+      </dia:attribute>
+      <dia:attribute name="obj_bb">
+        <dia:rectangle val="16.3,11.45;25.8,18.45"/>
+      </dia:attribute>
+      <dia:attribute name="elem_corner">
+        <dia:point val="16.35,11.5"/>
+      </dia:attribute>
+      <dia:attribute name="elem_width">
+        <dia:real val="9.4000000000000021"/>
+      </dia:attribute>
+      <dia:attribute name="elem_height">
+        <dia:real val="6.9000000000000021"/>
+      </dia:attribute>
+      <dia:attribute name="show_background">
+        <dia:boolean val="true"/>
+      </dia:attribute>
+    </dia:object>
+    <dia:object type="Geometric - Perfect Circle" version="1" id="O1">
+      <dia:attribute name="obj_pos">
+        <dia:point val="25.5627,14.578"/>
+      </dia:attribute>
+      <dia:attribute name="obj_bb">
+        <dia:rectangle val="25.4627,14.478;26.0191,15.0344"/>
+      </dia:attribute>
+      <dia:attribute name="meta">
+        <dia:composite type="dict"/>
+      </dia:attribute>
+      <dia:attribute name="elem_corner">
+        <dia:point val="25.5627,14.578"/>
+      </dia:attribute>
+      <dia:attribute name="elem_width">
+        <dia:real val="0.35638032780853468"/>
+      </dia:attribute>
+      <dia:attribute name="elem_height">
+        <dia:real val="0.35638032780853468"/>
+      </dia:attribute>
+      <dia:attribute name="line_width">
+        <dia:real val="0.10000000000000001"/>
+      </dia:attribute>
+      <dia:attribute name="line_colour">
+        <dia:color val="#000000ff"/>
+      </dia:attribute>
+      <dia:attribute name="fill_colour">
+        <dia:color val="#ffffffff"/>
+      </dia:attribute>
+      <dia:attribute name="show_background">
+        <dia:boolean val="true"/>
+      </dia:attribute>
+      <dia:attribute name="line_style">
+        <dia:enum val="0"/>
+        <dia:real val="1"/>
+      </dia:attribute>
+      <dia:attribute name="flip_horizontal">
+        <dia:boolean val="false"/>
+      </dia:attribute>
+      <dia:attribute name="flip_vertical">
+        <dia:boolean val="false"/>
+      </dia:attribute>
+      <dia:attribute name="subscale">
+        <dia:real val="1"/>
+      </dia:attribute>
+    </dia:object>
+    <dia:object type="Geometric - Perfect Circle" version="1" id="O2">
+      <dia:attribute name="obj_pos">
+        <dia:point val="17.7702,13.2656"/>
+      </dia:attribute>
+      <dia:attribute name="obj_bb">
+        <dia:rectangle val="17.6702,13.1656;18.24,13.7354"/>
+      </dia:attribute>
+      <dia:attribute name="meta">
+        <dia:composite type="dict"/>
+      </dia:attribute>
+      <dia:attribute name="elem_corner">
+        <dia:point val="17.7702,13.2656"/>
+      </dia:attribute>
+      <dia:attribute name="elem_width">
+        <dia:real val="0.36980024191863681"/>
+      </dia:attribute>
+      <dia:attribute name="elem_height">
+        <dia:real val="0.36980024191863681"/>
+      </dia:attribute>
+      <dia:attribute name="line_width">
+        <dia:real val="0.10000000000000001"/>
+      </dia:attribute>
+      <dia:attribute name="line_colour">
+        <dia:color val="#000000ff"/>
+      </dia:attribute>
+      <dia:attribute name="fill_colour">
+        <dia:color val="#ffffffff"/>
+      </dia:attribute>
+      <dia:attribute name="show_background">
+        <dia:boolean val="true"/>
+      </dia:attribute>
+      <dia:attribute name="line_style">
+        <dia:enum val="0"/>
+        <dia:real val="1"/>
+      </dia:attribute>
+      <dia:attribute name="flip_horizontal">
+        <dia:boolean val="false"/>
+      </dia:attribute>
+      <dia:attribute name="flip_vertical">
+        <dia:boolean val="false"/>
+      </dia:attribute>
+      <dia:attribute name="subscale">
+        <dia:real val="1"/>
+      </dia:attribute>
+    </dia:object>
+    <dia:object type="Geometric - Perfect Circle" version="1" id="O3">
+      <dia:attribute name="obj_pos">
+        <dia:point val="17.7464,16.2056"/>
+      </dia:attribute>
+      <dia:attribute name="obj_bb">
+        <dia:rectangle val="17.6464,16.1056;18.2162,16.6754"/>
+      </dia:attribute>
+      <dia:attribute name="meta">
+        <dia:composite type="dict"/>
+      </dia:attribute>
+      <dia:attribute name="elem_corner">
+        <dia:point val="17.7464,16.2056"/>
+      </dia:attribute>
+      <dia:attribute name="elem_width">
+        <dia:real val="0.36980024191863681"/>
+      </dia:attribute>
+      <dia:attribute name="elem_height">
+        <dia:real val="0.36980024191863681"/>
+      </dia:attribute>
+      <dia:attribute name="line_width">
+        <dia:real val="0.10000000000000001"/>
+      </dia:attribute>
+      <dia:attribute name="line_colour">
+        <dia:color val="#000000ff"/>
+      </dia:attribute>
+      <dia:attribute name="fill_colour">
+        <dia:color val="#ffffffff"/>
+      </dia:attribute>
+      <dia:attribute name="show_background">
+        <dia:boolean val="true"/>
+      </dia:attribute>
+      <dia:attribute name="line_style">
+        <dia:enum val="0"/>
+        <dia:real val="1"/>
+      </dia:attribute>
+      <dia:attribute name="flip_horizontal">
+        <dia:boolean val="false"/>
+      </dia:attribute>
+      <dia:attribute name="flip_vertical">
+        <dia:boolean val="false"/>
+      </dia:attribute>
+      <dia:attribute name="subscale">
+        <dia:real val="1"/>
+      </dia:attribute>
+    </dia:object>
+    <dia:object type="Standard - Line" version="0" id="O4">
+      <dia:attribute name="obj_pos">
+        <dia:point val="18.1609,16.3413"/>
+      </dia:attribute>
+      <dia:attribute name="obj_bb">
+        <dia:rectangle val="18.1016,14.5712;25.6221,16.4007"/>
+      </dia:attribute>
+      <dia:attribute name="conn_endpoints">
+        <dia:point val="18.1609,16.3413"/>
+        <dia:point val="25.5627,14.7562"/>
+      </dia:attribute>
+      <dia:attribute name="numcp">
+        <dia:int val="1"/>
+      </dia:attribute>
+      <dia:attribute name="line_style">
+        <dia:enum val="1"/>
+      </dia:attribute>
+      <dia:attribute name="end_arrow">
+        <dia:enum val="1"/>
+      </dia:attribute>
+      <dia:attribute name="end_arrow_length">
+        <dia:real val="0.5"/>
+      </dia:attribute>
+      <dia:attribute name="end_arrow_width">
+        <dia:real val="0.5"/>
+      </dia:attribute>
+      <dia:connections>
+        <dia:connection handle="0" to="O3" connection="8"/>
+        <dia:connection handle="1" to="O1" connection="2"/>
+      </dia:connections>
+    </dia:object>
+    <dia:object type="Standard - Line" version="0" id="O5">
+      <dia:attribute name="obj_pos">
+        <dia:point val="18.14,13.4505"/>
+      </dia:attribute>
+      <dia:attribute name="obj_bb">
+        <dia:rectangle val="18.0821,13.3926;25.6206,14.9674"/>
+      </dia:attribute>
+      <dia:attribute name="conn_endpoints">
+        <dia:point val="18.14,13.4505"/>
+        <dia:point val="25.5627,14.7562"/>
+      </dia:attribute>
+      <dia:attribute name="numcp">
+        <dia:int val="1"/>
+      </dia:attribute>
+      <dia:attribute name="end_arrow">
+        <dia:enum val="1"/>
+      </dia:attribute>
+      <dia:attribute name="end_arrow_length">
+        <dia:real val="0.5"/>
+      </dia:attribute>
+      <dia:attribute name="end_arrow_width">
+        <dia:real val="0.5"/>
+      </dia:attribute>
+      <dia:connections>
+        <dia:connection handle="0" to="O2" connection="3"/>
+        <dia:connection handle="1" to="O1" connection="2"/>
+      </dia:connections>
+    </dia:object>
+    <dia:object type="Standard - Line" version="0" id="O6">
+      <dia:attribute name="obj_pos">
+        <dia:point val="25.919,14.7562"/>
+      </dia:attribute>
+      <dia:attribute name="obj_bb">
+        <dia:rectangle val="25.8686,14.3879;31.0068,15.0497"/>
+      </dia:attribute>
+      <dia:attribute name="conn_endpoints">
+        <dia:point val="25.919,14.7562"/>
+        <dia:point val="30.9564,14.7131"/>
+      </dia:attribute>
+      <dia:attribute name="numcp">
+        <dia:int val="1"/>
+      </dia:attribute>
+      <dia:attribute name="end_arrow">
+        <dia:enum val="1"/>
+      </dia:attribute>
+      <dia:attribute name="end_arrow_length">
+        <dia:real val="0.5"/>
+      </dia:attribute>
+      <dia:attribute name="end_arrow_width">
+        <dia:real val="0.5"/>
+      </dia:attribute>
+      <dia:connections>
+        <dia:connection handle="0" to="O1" connection="3"/>
+      </dia:connections>
+    </dia:object>
+    <dia:object type="Standard - Text" version="1" id="O7">
+      <dia:attribute name="obj_pos">
+        <dia:point val="17.9551,13.2656"/>
+      </dia:attribute>
+      <dia:attribute name="obj_bb">
+        <dia:rectangle val="17.9551,12.5181;22.7051,13.2656"/>
+      </dia:attribute>
+      <dia:attribute name="text">
+        <dia:composite type="text">
+          <dia:attribute name="string">
+            <dia:string>#image data (1)#</dia:string>
+          </dia:attribute>
+          <dia:attribute name="font">
+            <dia:font family="sans" style="0" name="Helvetica"/>
+          </dia:attribute>
+          <dia:attribute name="height">
+            <dia:real val="0.80000000000000004"/>
+          </dia:attribute>
+          <dia:attribute name="pos">
+            <dia:point val="17.9551,13.1131"/>
+          </dia:attribute>
+          <dia:attribute name="color">
+            <dia:color val="#000000ff"/>
+          </dia:attribute>
+          <dia:attribute name="alignment">
+            <dia:enum val="0"/>
+          </dia:attribute>
+        </dia:composite>
+      </dia:attribute>
+      <dia:attribute name="valign">
+        <dia:enum val="1"/>
+      </dia:attribute>
+      <dia:connections>
+        <dia:connection handle="0" to="O2" connection="1"/>
+      </dia:connections>
+    </dia:object>
+    <dia:object type="Standard - Text" version="1" id="O8">
+      <dia:attribute name="obj_pos">
+        <dia:point val="17.9313,16.5754"/>
+      </dia:attribute>
+      <dia:attribute name="obj_bb">
+        <dia:rectangle val="17.9313,16.5754;25.1825,17.379"/>
+      </dia:attribute>
+      <dia:attribute name="text">
+        <dia:composite type="text">
+          <dia:attribute name="string">
+            <dia:string>#embedded data (n - 1)#</dia:string>
+          </dia:attribute>
+          <dia:attribute name="font">
+            <dia:font family="sans" style="0" name="Helvetica"/>
+          </dia:attribute>
+          <dia:attribute name="height">
+            <dia:real val="0.80000000000000004"/>
+          </dia:attribute>
+          <dia:attribute name="pos">
+            <dia:point val="17.9313,17.1891"/>
+          </dia:attribute>
+          <dia:attribute name="color">
+            <dia:color val="#000000ff"/>
+          </dia:attribute>
+          <dia:attribute name="alignment">
+            <dia:enum val="0"/>
+          </dia:attribute>
+        </dia:composite>
+      </dia:attribute>
+      <dia:attribute name="valign">
+        <dia:enum val="0"/>
+      </dia:attribute>
+      <dia:connections>
+        <dia:connection handle="0" to="O3" connection="0"/>
+      </dia:connections>
+    </dia:object>
+    <dia:object type="Standard - Text" version="1" id="O9">
+      <dia:attribute name="obj_pos">
+        <dia:point val="26.1,14.125"/>
+      </dia:attribute>
+      <dia:attribute name="obj_bb">
+        <dia:rectangle val="26.1,13.53;30.7475,14.2775"/>
+      </dia:attribute>
+      <dia:attribute name="text">
+        <dia:composite type="text">
+          <dia:attribute name="string">
+            <dia:string>#source pad (0)#</dia:string>
+          </dia:attribute>
+          <dia:attribute name="font">
+            <dia:font family="sans" style="0" name="Helvetica"/>
+          </dia:attribute>
+          <dia:attribute name="height">
+            <dia:real val="0.80000000000000004"/>
+          </dia:attribute>
+          <dia:attribute name="pos">
+            <dia:point val="26.1,14.125"/>
+          </dia:attribute>
+          <dia:attribute name="color">
+            <dia:color val="#000000ff"/>
+          </dia:attribute>
+          <dia:attribute name="alignment">
+            <dia:enum val="0"/>
+          </dia:attribute>
+        </dia:composite>
+      </dia:attribute>
+      <dia:attribute name="valign">
+        <dia:enum val="3"/>
+      </dia:attribute>
+    </dia:object>
+  </dia:layer>
+</dia:diagram>
diff --git a/Documentation/userspace-api/media/v4l/common-raw-sensor.svg b/Documentation/userspace-api/media/v4l/common-raw-sensor.svg
new file mode 100644
index 000000000000..1d6055da2519
--- /dev/null
+++ b/Documentation/userspace-api/media/v4l/common-raw-sensor.svg
@@ -0,0 +1,134 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="296pt" height="142pt" viewBox="0 0 296 142" version="1.1">
+<defs>
+<g>
+<symbol overflow="visible" id="glyph0-0">
+<path style="stroke:none;" d="M 0.640625 2.265625 L 0.640625 -9.015625 L 7.03125 -9.015625 L 7.03125 2.265625 Z M 1.359375 1.546875 L 6.328125 1.546875 L 6.328125 -8.296875 L 1.359375 -8.296875 Z M 1.359375 1.546875 "/>
+</symbol>
+<symbol overflow="visible" id="glyph0-1">
+<path style="stroke:none;" d="M 1.203125 -7 L 2.359375 -7 L 2.359375 0 L 1.203125 0 Z M 1.203125 -9.71875 L 2.359375 -9.71875 L 2.359375 -8.265625 L 1.203125 -8.265625 Z M 1.203125 -9.71875 "/>
+</symbol>
+<symbol overflow="visible" id="glyph0-2">
+<path style="stroke:none;" d="M 6.65625 -5.65625 C 6.9375 -6.164062 7.273438 -6.546875 7.671875 -6.796875 C 8.078125 -7.046875 8.550781 -7.171875 9.09375 -7.171875 C 9.820312 -7.171875 10.382812 -6.914062 10.78125 -6.40625 C 11.175781 -5.894531 11.375 -5.164062 11.375 -4.21875 L 11.375 0 L 10.21875 0 L 10.21875 -4.1875 C 10.21875 -4.851562 10.097656 -5.347656 9.859375 -5.671875 C 9.628906 -6.003906 9.269531 -6.171875 8.78125 -6.171875 C 8.1875 -6.171875 7.710938 -5.972656 7.359375 -5.578125 C 7.015625 -5.179688 6.84375 -4.640625 6.84375 -3.953125 L 6.84375 0 L 5.6875 0 L 5.6875 -4.1875 C 5.6875 -4.863281 5.566406 -5.363281 5.328125 -5.6875 C 5.097656 -6.007812 4.734375 -6.171875 4.234375 -6.171875 C 3.648438 -6.171875 3.179688 -5.96875 2.828125 -5.5625 C 2.484375 -5.164062 2.3125 -4.628906 2.3125 -3.953125 L 2.3125 0 L 1.15625 0 L 1.15625 -7 L 2.3125 -7 L 2.3125 -5.90625 C 2.582031 -6.332031 2.898438 -6.648438 3.265625 -6.859375 C 3.628906 -7.066406 4.0625 -7.171875 4.5625 -7.171875 C 5.070312 -7.171875 5.503906 -7.039062 5.859375 -6.78125 C 6.222656 -6.519531 6.488281 -6.144531 6.65625 -5.65625 Z M 6.65625 -5.65625 "/>
+</symbol>
+<symbol overflow="visible" id="glyph0-3">
+<path style="stroke:none;" d="M 4.390625 -3.515625 C 3.460938 -3.515625 2.816406 -3.40625 2.453125 -3.1875 C 2.097656 -2.976562 1.921875 -2.617188 1.921875 -2.109375 C 1.921875 -1.703125 2.050781 -1.378906 2.3125 -1.140625 C 2.582031 -0.898438 2.953125 -0.78125 3.421875 -0.78125 C 4.054688 -0.78125 4.566406 -1.003906 4.953125 -1.453125 C 5.335938 -1.910156 5.53125 -2.515625 5.53125 -3.265625 L 5.53125 -3.515625 Z M 6.671875 -4 L 6.671875 0 L 5.53125 0 L 5.53125 -1.0625 C 5.269531 -0.632812 4.941406 -0.316406 4.546875 -0.109375 C 4.160156 0.0859375 3.679688 0.1875 3.109375 0.1875 C 2.390625 0.1875 1.816406 -0.015625 1.390625 -0.421875 C 0.972656 -0.828125 0.765625 -1.363281 0.765625 -2.03125 C 0.765625 -2.820312 1.023438 -3.414062 1.546875 -3.8125 C 2.078125 -4.21875 2.867188 -4.421875 3.921875 -4.421875 L 5.53125 -4.421875 L 5.53125 -4.53125 C 5.53125 -5.0625 5.351562 -5.46875 5 -5.75 C 4.65625 -6.039062 4.171875 -6.1875 3.546875 -6.1875 C 3.140625 -6.1875 2.75 -6.140625 2.375 -6.046875 C 2 -5.953125 1.632812 -5.8125 1.28125 -5.625 L 1.28125 -6.671875 C 1.695312 -6.835938 2.101562 -6.960938 2.5 -7.046875 C 2.894531 -7.128906 3.28125 -7.171875 3.65625 -7.171875 C 4.675781 -7.171875 5.429688 -6.90625 5.921875 -6.375 C 6.421875 -5.851562 6.671875 -5.0625 6.671875 -4 Z M 6.671875 -4 "/>
+</symbol>
+<symbol overflow="visible" id="glyph0-4">
+<path style="stroke:none;" d="M 5.8125 -3.578125 C 5.8125 -4.410156 5.640625 -5.054688 5.296875 -5.515625 C 4.953125 -5.972656 4.46875 -6.203125 3.84375 -6.203125 C 3.226562 -6.203125 2.75 -5.972656 2.40625 -5.515625 C 2.0625 -5.054688 1.890625 -4.410156 1.890625 -3.578125 C 1.890625 -2.753906 2.0625 -2.113281 2.40625 -1.65625 C 2.75 -1.195312 3.226562 -0.96875 3.84375 -0.96875 C 4.46875 -0.96875 4.953125 -1.195312 5.296875 -1.65625 C 5.640625 -2.113281 5.8125 -2.753906 5.8125 -3.578125 Z M 6.953125 -0.875 C 6.953125 0.320312 6.6875 1.207031 6.15625 1.78125 C 5.632812 2.363281 4.828125 2.65625 3.734375 2.65625 C 3.328125 2.65625 2.945312 2.625 2.59375 2.5625 C 2.238281 2.507812 1.890625 2.421875 1.546875 2.296875 L 1.546875 1.171875 C 1.890625 1.359375 2.222656 1.492188 2.546875 1.578125 C 2.878906 1.671875 3.21875 1.71875 3.5625 1.71875 C 4.3125 1.71875 4.875 1.519531 5.25 1.125 C 5.625 0.726562 5.8125 0.132812 5.8125 -0.65625 L 5.8125 -1.234375 C 5.570312 -0.816406 5.265625 -0.503906 4.890625 -0.296875 C 4.523438 -0.0976562 4.082031 0 3.5625 0 C 2.707031 0 2.015625 -0.328125 1.484375 -0.984375 C 0.960938 -1.640625 0.703125 -2.503906 0.703125 -3.578125 C 0.703125 -4.660156 0.960938 -5.53125 1.484375 -6.1875 C 2.015625 -6.84375 2.707031 -7.171875 3.5625 -7.171875 C 4.082031 -7.171875 4.523438 -7.066406 4.890625 -6.859375 C 5.265625 -6.648438 5.570312 -6.34375 5.8125 -5.9375 L 5.8125 -7 L 6.953125 -7 Z M 6.953125 -0.875 "/>
+</symbol>
+<symbol overflow="visible" id="glyph0-5">
+<path style="stroke:none;" d="M 7.1875 -3.78125 L 7.1875 -3.21875 L 1.90625 -3.21875 C 1.957031 -2.425781 2.195312 -1.820312 2.625 -1.40625 C 3.050781 -1 3.644531 -0.796875 4.40625 -0.796875 C 4.84375 -0.796875 5.269531 -0.847656 5.6875 -0.953125 C 6.101562 -1.066406 6.515625 -1.226562 6.921875 -1.4375 L 6.921875 -0.359375 C 6.515625 -0.179688 6.09375 -0.046875 5.65625 0.046875 C 5.21875 0.140625 4.78125 0.1875 4.34375 0.1875 C 3.21875 0.1875 2.328125 -0.132812 1.671875 -0.78125 C 1.023438 -1.4375 0.703125 -2.320312 0.703125 -3.4375 C 0.703125 -4.582031 1.007812 -5.488281 1.625 -6.15625 C 2.25 -6.832031 3.085938 -7.171875 4.140625 -7.171875 C 5.078125 -7.171875 5.816406 -6.863281 6.359375 -6.25 C 6.910156 -5.644531 7.1875 -4.820312 7.1875 -3.78125 Z M 6.046875 -4.125 C 6.035156 -4.75 5.859375 -5.25 5.515625 -5.625 C 5.171875 -6 4.71875 -6.1875 4.15625 -6.1875 C 3.507812 -6.1875 2.992188 -6.003906 2.609375 -5.640625 C 2.222656 -5.285156 2 -4.78125 1.9375 -4.125 Z M 6.046875 -4.125 "/>
+</symbol>
+<symbol overflow="visible" id="glyph0-6">
+<path style="stroke:none;" d=""/>
+</symbol>
+<symbol overflow="visible" id="glyph0-7">
+<path style="stroke:none;" d="M 5.8125 -5.9375 L 5.8125 -9.71875 L 6.953125 -9.71875 L 6.953125 0 L 5.8125 0 L 5.8125 -1.046875 C 5.570312 -0.628906 5.265625 -0.316406 4.890625 -0.109375 C 4.523438 0.0859375 4.082031 0.1875 3.5625 0.1875 C 2.71875 0.1875 2.03125 -0.148438 1.5 -0.828125 C 0.96875 -1.503906 0.703125 -2.394531 0.703125 -3.5 C 0.703125 -4.59375 0.96875 -5.476562 1.5 -6.15625 C 2.03125 -6.832031 2.71875 -7.171875 3.5625 -7.171875 C 4.082031 -7.171875 4.523438 -7.066406 4.890625 -6.859375 C 5.265625 -6.660156 5.570312 -6.351562 5.8125 -5.9375 Z M 1.890625 -3.5 C 1.890625 -2.644531 2.0625 -1.976562 2.40625 -1.5 C 2.757812 -1.019531 3.238281 -0.78125 3.84375 -0.78125 C 4.457031 -0.78125 4.9375 -1.019531 5.28125 -1.5 C 5.632812 -1.976562 5.8125 -2.644531 5.8125 -3.5 C 5.8125 -4.34375 5.632812 -5.003906 5.28125 -5.484375 C 4.9375 -5.960938 4.457031 -6.203125 3.84375 -6.203125 C 3.238281 -6.203125 2.757812 -5.960938 2.40625 -5.484375 C 2.0625 -5.003906 1.890625 -4.34375 1.890625 -3.5 Z M 1.890625 -3.5 "/>
+</symbol>
+<symbol overflow="visible" id="glyph0-8">
+<path style="stroke:none;" d="M 2.34375 -8.984375 L 2.34375 -7 L 4.71875 -7 L 4.71875 -6.109375 L 2.34375 -6.109375 L 2.34375 -2.3125 C 2.34375 -1.738281 2.421875 -1.367188 2.578125 -1.203125 C 2.734375 -1.046875 3.050781 -0.96875 3.53125 -0.96875 L 4.71875 -0.96875 L 4.71875 0 L 3.53125 0 C 2.644531 0 2.03125 -0.164062 1.6875 -0.5 C 1.351562 -0.832031 1.1875 -1.4375 1.1875 -2.3125 L 1.1875 -6.109375 L 0.34375 -6.109375 L 0.34375 -7 L 1.1875 -7 L 1.1875 -8.984375 Z M 2.34375 -8.984375 "/>
+</symbol>
+<symbol overflow="visible" id="glyph0-9">
+<path style="stroke:none;" d="M 3.96875 -9.703125 C 3.40625 -8.742188 2.988281 -7.796875 2.71875 -6.859375 C 2.445312 -5.929688 2.3125 -4.984375 2.3125 -4.015625 C 2.3125 -3.054688 2.445312 -2.101562 2.71875 -1.15625 C 3 -0.21875 3.414062 0.726562 3.96875 1.6875 L 2.96875 1.6875 C 2.34375 0.707031 1.875 -0.253906 1.5625 -1.203125 C 1.25 -2.148438 1.09375 -3.085938 1.09375 -4.015625 C 1.09375 -4.941406 1.25 -5.875 1.5625 -6.8125 C 1.875 -7.757812 2.34375 -8.722656 2.96875 -9.703125 Z M 3.96875 -9.703125 "/>
+</symbol>
+<symbol overflow="visible" id="glyph0-10">
+<path style="stroke:none;" d="M 1.59375 -1.0625 L 3.65625 -1.0625 L 3.65625 -8.171875 L 1.40625 -7.734375 L 1.40625 -8.875 L 3.640625 -9.328125 L 4.90625 -9.328125 L 4.90625 -1.0625 L 6.953125 -1.0625 L 6.953125 0 L 1.59375 0 Z M 1.59375 -1.0625 "/>
+</symbol>
+<symbol overflow="visible" id="glyph0-11">
+<path style="stroke:none;" d="M 1.03125 -9.703125 L 2.03125 -9.703125 C 2.65625 -8.722656 3.117188 -7.757812 3.421875 -6.8125 C 3.734375 -5.875 3.890625 -4.941406 3.890625 -4.015625 C 3.890625 -3.085938 3.734375 -2.148438 3.421875 -1.203125 C 3.117188 -0.253906 2.65625 0.707031 2.03125 1.6875 L 1.03125 1.6875 C 1.582031 0.726562 1.992188 -0.21875 2.265625 -1.15625 C 2.535156 -2.101562 2.671875 -3.054688 2.671875 -4.015625 C 2.671875 -4.984375 2.535156 -5.929688 2.265625 -6.859375 C 1.992188 -7.796875 1.582031 -8.742188 1.03125 -9.703125 Z M 1.03125 -9.703125 "/>
+</symbol>
+<symbol overflow="visible" id="glyph0-12">
+<path style="stroke:none;" d="M 6.234375 -3.5 C 6.234375 -4.34375 6.054688 -5.003906 5.703125 -5.484375 C 5.359375 -5.960938 4.882812 -6.203125 4.28125 -6.203125 C 3.664062 -6.203125 3.179688 -5.960938 2.828125 -5.484375 C 2.484375 -5.003906 2.3125 -4.34375 2.3125 -3.5 C 2.3125 -2.644531 2.484375 -1.976562 2.828125 -1.5 C 3.179688 -1.019531 3.664062 -0.78125 4.28125 -0.78125 C 4.882812 -0.78125 5.359375 -1.019531 5.703125 -1.5 C 6.054688 -1.976562 6.234375 -2.644531 6.234375 -3.5 Z M 2.3125 -5.9375 C 2.5625 -6.351562 2.867188 -6.660156 3.234375 -6.859375 C 3.597656 -7.066406 4.039062 -7.171875 4.5625 -7.171875 C 5.40625 -7.171875 6.09375 -6.832031 6.625 -6.15625 C 7.15625 -5.476562 7.421875 -4.59375 7.421875 -3.5 C 7.421875 -2.394531 7.15625 -1.503906 6.625 -0.828125 C 6.09375 -0.148438 5.40625 0.1875 4.5625 0.1875 C 4.039062 0.1875 3.597656 0.0859375 3.234375 -0.109375 C 2.867188 -0.316406 2.5625 -0.628906 2.3125 -1.046875 L 2.3125 0 L 1.15625 0 L 1.15625 -9.71875 L 2.3125 -9.71875 Z M 2.3125 -5.9375 "/>
+</symbol>
+<symbol overflow="visible" id="glyph0-13">
+<path style="stroke:none;" d="M 2.453125 -1.0625 L 6.859375 -1.0625 L 6.859375 0 L 0.9375 0 L 0.9375 -1.0625 C 1.414062 -1.5625 2.066406 -2.226562 2.890625 -3.0625 C 3.722656 -3.894531 4.242188 -4.429688 4.453125 -4.671875 C 4.859375 -5.128906 5.140625 -5.515625 5.296875 -5.828125 C 5.460938 -6.140625 5.546875 -6.445312 5.546875 -6.75 C 5.546875 -7.25 5.367188 -7.65625 5.015625 -7.96875 C 4.671875 -8.28125 4.21875 -8.4375 3.65625 -8.4375 C 3.257812 -8.4375 2.84375 -8.363281 2.40625 -8.21875 C 1.96875 -8.082031 1.5 -7.878906 1 -7.609375 L 1 -8.875 C 1.507812 -9.082031 1.984375 -9.238281 2.421875 -9.34375 C 2.867188 -9.445312 3.273438 -9.5 3.640625 -9.5 C 4.609375 -9.5 5.378906 -9.253906 5.953125 -8.765625 C 6.523438 -8.285156 6.8125 -7.640625 6.8125 -6.828125 C 6.8125 -6.453125 6.738281 -6.09375 6.59375 -5.75 C 6.445312 -5.40625 6.1875 -5 5.8125 -4.53125 C 5.707031 -4.40625 5.375 -4.054688 4.8125 -3.484375 C 4.257812 -2.910156 3.472656 -2.101562 2.453125 -1.0625 Z M 2.453125 -1.0625 "/>
+</symbol>
+<symbol overflow="visible" id="glyph0-14">
+<path style="stroke:none;" d="M 5.671875 -6.796875 L 5.671875 -5.703125 C 5.347656 -5.867188 5.007812 -5.992188 4.65625 -6.078125 C 4.300781 -6.160156 3.9375 -6.203125 3.5625 -6.203125 C 3 -6.203125 2.570312 -6.113281 2.28125 -5.9375 C 2 -5.769531 1.859375 -5.507812 1.859375 -5.15625 C 1.859375 -4.882812 1.957031 -4.671875 2.15625 -4.515625 C 2.363281 -4.367188 2.773438 -4.226562 3.390625 -4.09375 L 3.78125 -4 C 4.601562 -3.832031 5.1875 -3.585938 5.53125 -3.265625 C 5.875 -2.941406 6.046875 -2.5 6.046875 -1.9375 C 6.046875 -1.28125 5.785156 -0.757812 5.265625 -0.375 C 4.753906 0 4.050781 0.1875 3.15625 0.1875 C 2.78125 0.1875 2.390625 0.148438 1.984375 0.078125 C 1.578125 0.00390625 1.144531 -0.101562 0.6875 -0.25 L 0.6875 -1.4375 C 1.113281 -1.21875 1.53125 -1.050781 1.9375 -0.9375 C 2.351562 -0.832031 2.765625 -0.78125 3.171875 -0.78125 C 3.710938 -0.78125 4.128906 -0.875 4.421875 -1.0625 C 4.710938 -1.25 4.859375 -1.507812 4.859375 -1.84375 C 4.859375 -2.15625 4.753906 -2.394531 4.546875 -2.5625 C 4.335938 -2.726562 3.875 -2.890625 3.15625 -3.046875 L 2.765625 -3.140625 C 2.046875 -3.285156 1.53125 -3.515625 1.21875 -3.828125 C 0.90625 -4.140625 0.75 -4.566406 0.75 -5.109375 C 0.75 -5.765625 0.976562 -6.269531 1.4375 -6.625 C 1.90625 -6.988281 2.570312 -7.171875 3.4375 -7.171875 C 3.851562 -7.171875 4.25 -7.140625 4.625 -7.078125 C 5 -7.015625 5.347656 -6.921875 5.671875 -6.796875 Z M 5.671875 -6.796875 "/>
+</symbol>
+<symbol overflow="visible" id="glyph0-15">
+<path style="stroke:none;" d="M 3.921875 -6.1875 C 3.304688 -6.1875 2.816406 -5.945312 2.453125 -5.46875 C 2.097656 -4.988281 1.921875 -4.332031 1.921875 -3.5 C 1.921875 -2.65625 2.097656 -1.992188 2.453125 -1.515625 C 2.804688 -1.035156 3.296875 -0.796875 3.921875 -0.796875 C 4.535156 -0.796875 5.019531 -1.035156 5.375 -1.515625 C 5.726562 -2.003906 5.90625 -2.664062 5.90625 -3.5 C 5.90625 -4.320312 5.726562 -4.972656 5.375 -5.453125 C 5.019531 -5.941406 4.535156 -6.1875 3.921875 -6.1875 Z M 3.921875 -7.171875 C 4.921875 -7.171875 5.703125 -6.84375 6.265625 -6.1875 C 6.835938 -5.539062 7.125 -4.644531 7.125 -3.5 C 7.125 -2.351562 6.835938 -1.453125 6.265625 -0.796875 C 5.703125 -0.140625 4.921875 0.1875 3.921875 0.1875 C 2.910156 0.1875 2.117188 -0.140625 1.546875 -0.796875 C 0.984375 -1.453125 0.703125 -2.351562 0.703125 -3.5 C 0.703125 -4.644531 0.984375 -5.539062 1.546875 -6.1875 C 2.117188 -6.84375 2.910156 -7.171875 3.921875 -7.171875 Z M 3.921875 -7.171875 "/>
+</symbol>
+<symbol overflow="visible" id="glyph0-16">
+<path style="stroke:none;" d="M 1.09375 -2.765625 L 1.09375 -7 L 2.234375 -7 L 2.234375 -2.8125 C 2.234375 -2.144531 2.363281 -1.644531 2.625 -1.3125 C 2.882812 -0.976562 3.269531 -0.8125 3.78125 -0.8125 C 4.40625 -0.8125 4.894531 -1.007812 5.25 -1.40625 C 5.613281 -1.800781 5.796875 -2.34375 5.796875 -3.03125 L 5.796875 -7 L 6.953125 -7 L 6.953125 0 L 5.796875 0 L 5.796875 -1.078125 C 5.515625 -0.648438 5.191406 -0.332031 4.828125 -0.125 C 4.460938 0.0820312 4.035156 0.1875 3.546875 0.1875 C 2.742188 0.1875 2.132812 -0.0625 1.71875 -0.5625 C 1.300781 -1.0625 1.09375 -1.796875 1.09375 -2.765625 Z M 3.984375 -7.171875 Z M 3.984375 -7.171875 "/>
+</symbol>
+<symbol overflow="visible" id="glyph0-17">
+<path style="stroke:none;" d="M 5.265625 -5.921875 C 5.128906 -5.992188 4.984375 -6.046875 4.828125 -6.078125 C 4.679688 -6.117188 4.519531 -6.140625 4.34375 -6.140625 C 3.6875 -6.140625 3.179688 -5.925781 2.828125 -5.5 C 2.484375 -5.082031 2.3125 -4.476562 2.3125 -3.6875 L 2.3125 0 L 1.15625 0 L 1.15625 -7 L 2.3125 -7 L 2.3125 -5.90625 C 2.5625 -6.332031 2.878906 -6.648438 3.265625 -6.859375 C 3.648438 -7.066406 4.117188 -7.171875 4.671875 -7.171875 C 4.753906 -7.171875 4.84375 -7.164062 4.9375 -7.15625 C 5.03125 -7.144531 5.132812 -7.128906 5.25 -7.109375 Z M 5.265625 -5.921875 "/>
+</symbol>
+<symbol overflow="visible" id="glyph0-18">
+<path style="stroke:none;" d="M 6.25 -6.734375 L 6.25 -5.65625 C 5.914062 -5.832031 5.585938 -5.960938 5.265625 -6.046875 C 4.941406 -6.140625 4.613281 -6.1875 4.28125 -6.1875 C 3.53125 -6.1875 2.945312 -5.953125 2.53125 -5.484375 C 2.125 -5.015625 1.921875 -4.351562 1.921875 -3.5 C 1.921875 -2.644531 2.125 -1.976562 2.53125 -1.5 C 2.945312 -1.03125 3.53125 -0.796875 4.28125 -0.796875 C 4.613281 -0.796875 4.941406 -0.835938 5.265625 -0.921875 C 5.585938 -1.015625 5.914062 -1.148438 6.25 -1.328125 L 6.25 -0.265625 C 5.925781 -0.117188 5.59375 -0.0078125 5.25 0.0625 C 4.90625 0.144531 4.539062 0.1875 4.15625 0.1875 C 3.09375 0.1875 2.25 -0.144531 1.625 -0.8125 C 1.007812 -1.476562 0.703125 -2.375 0.703125 -3.5 C 0.703125 -4.632812 1.015625 -5.53125 1.640625 -6.1875 C 2.273438 -6.84375 3.132812 -7.171875 4.21875 -7.171875 C 4.570312 -7.171875 4.914062 -7.132812 5.25 -7.0625 C 5.59375 -6.988281 5.925781 -6.878906 6.25 -6.734375 Z M 6.25 -6.734375 "/>
+</symbol>
+<symbol overflow="visible" id="glyph0-19">
+<path style="stroke:none;" d="M 2.3125 -1.046875 L 2.3125 2.65625 L 1.15625 2.65625 L 1.15625 -7 L 2.3125 -7 L 2.3125 -5.9375 C 2.5625 -6.351562 2.867188 -6.660156 3.234375 -6.859375 C 3.597656 -7.066406 4.039062 -7.171875 4.5625 -7.171875 C 5.40625 -7.171875 6.09375 -6.832031 6.625 -6.15625 C 7.15625 -5.476562 7.421875 -4.59375 7.421875 -3.5 C 7.421875 -2.394531 7.15625 -1.503906 6.625 -0.828125 C 6.09375 -0.148438 5.40625 0.1875 4.5625 0.1875 C 4.039062 0.1875 3.597656 0.0859375 3.234375 -0.109375 C 2.867188 -0.316406 2.5625 -0.628906 2.3125 -1.046875 Z M 6.234375 -3.5 C 6.234375 -4.34375 6.054688 -5.003906 5.703125 -5.484375 C 5.359375 -5.960938 4.882812 -6.203125 4.28125 -6.203125 C 3.664062 -6.203125 3.179688 -5.960938 2.828125 -5.484375 C 2.484375 -5.003906 2.3125 -4.34375 2.3125 -3.5 C 2.3125 -2.644531 2.484375 -1.976562 2.828125 -1.5 C 3.179688 -1.019531 3.664062 -0.78125 4.28125 -0.78125 C 4.882812 -0.78125 5.359375 -1.019531 5.703125 -1.5 C 6.054688 -1.976562 6.234375 -2.644531 6.234375 -3.5 Z M 6.234375 -3.5 "/>
+</symbol>
+<symbol overflow="visible" id="glyph0-20">
+<path style="stroke:none;" d="M 4.0625 -8.5 C 3.414062 -8.5 2.925781 -8.175781 2.59375 -7.53125 C 2.269531 -6.894531 2.109375 -5.9375 2.109375 -4.65625 C 2.109375 -3.375 2.269531 -2.410156 2.59375 -1.765625 C 2.925781 -1.128906 3.414062 -0.8125 4.0625 -0.8125 C 4.71875 -0.8125 5.207031 -1.128906 5.53125 -1.765625 C 5.863281 -2.410156 6.03125 -3.375 6.03125 -4.65625 C 6.03125 -5.9375 5.863281 -6.894531 5.53125 -7.53125 C 5.207031 -8.175781 4.71875 -8.5 4.0625 -8.5 Z M 4.0625 -9.5 C 5.113281 -9.5 5.914062 -9.082031 6.46875 -8.25 C 7.019531 -7.425781 7.296875 -6.226562 7.296875 -4.65625 C 7.296875 -3.082031 7.019531 -1.878906 6.46875 -1.046875 C 5.914062 -0.222656 5.113281 0.1875 4.0625 0.1875 C 3.019531 0.1875 2.222656 -0.222656 1.671875 -1.046875 C 1.117188 -1.878906 0.84375 -3.082031 0.84375 -4.65625 C 0.84375 -6.226562 1.117188 -7.425781 1.671875 -8.25 C 2.222656 -9.082031 3.019531 -9.5 4.0625 -9.5 Z M 4.0625 -9.5 "/>
+</symbol>
+</g>
+</defs>
+<g id="surface11910">
+<rect x="0" y="0" width="296" height="142" style="fill:rgb(100%,100%,100%);fill-opacity:1;stroke:none;"/>
+<path style="fill-rule:evenodd;fill:rgb(100%,100%,100%);fill-opacity:1;stroke-width:0.1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 16.35 11.5 L 25.75 11.5 L 25.75 18.4 L 16.35 18.4 Z M 16.35 11.5 " transform="matrix(20,0,0,20,-325,-228)"/>
+<path style="fill-rule:evenodd;fill:rgb(100%,100%,100%);fill-opacity:1;stroke-width:0.1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 25.919141 14.75625 C 25.919141 14.99375 25.562695 14.99375 25.562695 14.75625 C 25.562695 14.518555 25.919141 14.518555 25.919141 14.75625 " transform="matrix(20,0,0,20,-325,-228)"/>
+<path style="fill-rule:evenodd;fill:rgb(100%,100%,100%);fill-opacity:1;stroke-width:0.1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 18.140039 13.450586 C 18.140039 13.69707 17.770117 13.69707 17.770117 13.450586 C 17.770117 13.203906 18.140039 13.203906 18.140039 13.450586 " transform="matrix(20,0,0,20,-325,-228)"/>
+<path style="fill-rule:evenodd;fill:rgb(100%,100%,100%);fill-opacity:1;stroke-width:0.1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 18.116211 16.39043 C 18.116211 16.637109 17.746484 16.637109 17.746484 16.39043 C 17.746484 16.143945 18.116211 16.143945 18.116211 16.39043 " transform="matrix(20,0,0,20,-325,-228)"/>
+<path style="fill:none;stroke-width:0.1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-dasharray:1,1;stroke-miterlimit:10;" d="M 18.160937 16.341406 L 25.344141 14.80293 " transform="matrix(20,0,0,20,-325,-228)"/>
+<path style="fill:none;stroke-width:0.1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 25.016797 15.128711 L 25.45332 14.779687 L 24.912109 14.639844 " transform="matrix(20,0,0,20,-325,-228)"/>
+<path style="fill:none;stroke-width:0.1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 18.140039 13.450586 L 25.342383 14.717383 " transform="matrix(20,0,0,20,-325,-228)"/>
+<path style="fill:none;stroke-width:0.1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 24.916797 14.896484 L 25.452539 14.736914 L 25.003516 14.403906 " transform="matrix(20,0,0,20,-325,-228)"/>
+<path style="fill:none;stroke-width:0.1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 25.918945 14.75625 L 30.732813 14.715039 " transform="matrix(20,0,0,20,-325,-228)"/>
+<path style="fill:none;stroke-width:0.1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 30.34668 14.968359 L 30.844531 14.714062 L 30.342383 14.468359 " transform="matrix(20,0,0,20,-325,-228)"/>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+  <use xlink:href="#glyph0-1" x="34.101562" y="34.267687"/>
+  <use xlink:href="#glyph0-2" x="37.712674" y="34.267687"/>
+  <use xlink:href="#glyph0-3" x="50.212674" y="34.267687"/>
+  <use xlink:href="#glyph0-4" x="57.990451" y="34.267687"/>
+  <use xlink:href="#glyph0-5" x="66.046007" y="34.267687"/>
+  <use xlink:href="#glyph0-6" x="73.823785" y="34.267687"/>
+  <use xlink:href="#glyph0-7" x="77.990451" y="34.267687"/>
+  <use xlink:href="#glyph0-3" x="86.046007" y="34.267687"/>
+  <use xlink:href="#glyph0-8" x="93.823785" y="34.267687"/>
+  <use xlink:href="#glyph0-3" x="98.823785" y="34.267687"/>
+  <use xlink:href="#glyph0-6" x="106.601562" y="34.267687"/>
+  <use xlink:href="#glyph0-9" x="110.768229" y="34.267687"/>
+  <use xlink:href="#glyph0-10" x="115.768229" y="34.267687"/>
+  <use xlink:href="#glyph0-11" x="123.823785" y="34.267687"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+  <use xlink:href="#glyph0-5" x="33.625" y="115.412218"/>
+  <use xlink:href="#glyph0-2" x="41.402778" y="115.412218"/>
+  <use xlink:href="#glyph0-12" x="53.902778" y="115.412218"/>
+  <use xlink:href="#glyph0-5" x="61.958333" y="115.412218"/>
+  <use xlink:href="#glyph0-7" x="69.736111" y="115.412218"/>
+  <use xlink:href="#glyph0-7" x="77.791667" y="115.412218"/>
+  <use xlink:href="#glyph0-5" x="85.847222" y="115.412218"/>
+  <use xlink:href="#glyph0-7" x="93.625" y="115.412218"/>
+  <use xlink:href="#glyph0-6" x="101.680556" y="115.412218"/>
+  <use xlink:href="#glyph0-7" x="105.847222" y="115.412218"/>
+  <use xlink:href="#glyph0-3" x="113.902778" y="115.412218"/>
+  <use xlink:href="#glyph0-8" x="121.680556" y="115.412218"/>
+  <use xlink:href="#glyph0-3" x="126.680556" y="115.412218"/>
+  <use xlink:href="#glyph0-6" x="134.458333" y="115.412218"/>
+  <use xlink:href="#glyph0-9" x="138.625" y="115.412218"/>
+  <use xlink:href="#glyph0-13" x="143.625" y="115.412218"/>
+  <use xlink:href="#glyph0-11" x="151.680556" y="115.412218"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+  <use xlink:href="#glyph0-14" x="197" y="54.505968"/>
+  <use xlink:href="#glyph0-15" x="203.666667" y="54.505968"/>
+  <use xlink:href="#glyph0-16" x="211.444444" y="54.505968"/>
+  <use xlink:href="#glyph0-17" x="219.5" y="54.505968"/>
+  <use xlink:href="#glyph0-18" x="224.5" y="54.505968"/>
+  <use xlink:href="#glyph0-5" x="231.444444" y="54.505968"/>
+  <use xlink:href="#glyph0-6" x="239.222222" y="54.505968"/>
+  <use xlink:href="#glyph0-19" x="243.388889" y="54.505968"/>
+  <use xlink:href="#glyph0-3" x="251.444444" y="54.505968"/>
+  <use xlink:href="#glyph0-7" x="259.222222" y="54.505968"/>
+  <use xlink:href="#glyph0-6" x="267.277778" y="54.505968"/>
+  <use xlink:href="#glyph0-9" x="271.444444" y="54.505968"/>
+  <use xlink:href="#glyph0-20" x="276.444444" y="54.505968"/>
+  <use xlink:href="#glyph0-11" x="284.5" y="54.505968"/>
+</g>
+</g>
+</svg>
diff --git a/Documentation/userspace-api/media/v4l/dev-subdev.rst b/Documentation/userspace-api/media/v4l/dev-subdev.rst
index 6b67f526f312..2fc81e0205dc 100644
--- a/Documentation/userspace-api/media/v4l/dev-subdev.rst
+++ b/Documentation/userspace-api/media/v4l/dev-subdev.rst
@@ -723,7 +723,10 @@ To configure this pipeline, the userspace must take the following steps:
    :ref:`VIDIOC_SUBDEV_S_FMT <VIDIOC_SUBDEV_G_FMT>` ioctls to configure each
    stream endpoint in each sub-device.
 
-   In case generic raw and metadata formats are used, :ref:`V4L2_CID_CFA_PATTERN
-   <image-source-control-cfa-pattern>` and :ref:`V4L2_CID_METADATA_LAYOUT
-   <image_source_control_metadata_layout>` controls are present on the source
-   sub-device to obtain the pixel array CFA pattern and metadata layout.
+   In case generic raw and metadata formats are used,
+   :ref:`V4L2_CID_CFA_PATTERN <image-source-control-cfa-pattern>` and
+   :ref:`V4L2_CID_METADATA_LAYOUT <image_source_control_metadata_layout>`
+   controls are present on the source sub-device to obtain the pixel array CFA
+   pattern and metadata layout.
+
+.. include:: subdev-config-model.rst
diff --git a/Documentation/userspace-api/media/v4l/subdev-config-model.rst b/Documentation/userspace-api/media/v4l/subdev-config-model.rst
new file mode 100644
index 000000000000..b450f698a608
--- /dev/null
+++ b/Documentation/userspace-api/media/v4l/subdev-config-model.rst
@@ -0,0 +1,250 @@
+.. SPDX-License-Identifier: GPL-2.0 OR GFDL-1.1-no-invariants-or-later
+
+.. _media_subdev_config_model:
+
+Sub-device configuration models
+===============================
+
+The V4L2 specification defines a subdev API that exposes three type of
+configuration elements: formats, selection rectangles and controls. The
+specification contains generic information about how those configuration
+elements behave, but not precisely how they apply to particular hardware
+features. We leave some leeway to drivers to decide how to map selection
+rectangles to device features, as long as they comply with the V4L2
+specification. This is needed as hardware features differ between devices, so
+it's the driver's responsibility to handle this mapping.
+
+Unfortunately, this lack of clearly defined mapping in the specification has led
+to different drivers mapping the same hardware features to different API
+elements, or implementing the API elements with slightly different
+behaviours. Furthermore, many drivers have implemented selection rectangles in
+ways that do not comply with the V4L2 specification. All of this makes userspace
+development difficult.
+
+Sub-device configuration models specify in detail what the user space can expect
+from a sub-device in terms of V4L2 sub-device interface support, semantics
+included.
+
+A sub-device may implement more than one configuration model at the same
+time. The implemented configuration models can be obtained from the sub-device's
+``V4L2_CID_CONFIG_MODEL`` control.
+
+.. _media_subdev_config_model_common_raw_sensor:
+
+Common raw camera sensor model
+------------------------------
+
+The common raw camera sensor model defines a set of enumeration and
+configuration interfaces (formats, selections etc.) that cover the vast majority
+of functionality of raw camera sensors. Not all of the interfaces are
+necessarily offered by all drivers.
+
+A sub-device complies with the common raw sensor model if the
+``V4L2_CONFIG_MODEL_COMMON_RAW_SENSOR`` bit is set in the
+``V4L2_CID_CONFIG_MODEL`` control of the sub-device.
+
+The common raw camera sensor model is aligned with
+:ref:`media_using_camera_sensor_drivers`. Please refer to that regarding aspects
+not specified here.
+
+Each camera sensor implementing the common raw sensor model exposes a single
+V4L2 sub-device. The sub-device contains a single source pad (0) and two or more
+internal pads: one or more image data internal pads (starting from 1) and
+optionally an embedded data pad.
+
+Additionally, further internal pads may be supported for other features. Using
+more than one image data internal pad or more than one non-image data pad
+requires these pads documented separately for the given device. The indices of
+the image data internal pads shall be lower than those of the non-image data
+pads.
+
+This is shown in :ref:`media_subdev_config_model_common_raw_sensor_subdev`.
+
+.. _media_subdev_config_model_common_raw_sensor_subdev:
+
+.. kernel-figure:: common-raw-sensor.svg
+    :alt:    common-raw-sensor.svg
+    :align:  center
+
+    **Common raw sensor sub-device with two pads**
+
+Routes
+^^^^^^
+
+A sub-device conforming to common raw camera sensor model implements the
+following routes.
+
+.. flat-table:: Routes
+    :header-rows: 1
+
+    * - Sink pad/stream
+      - Source pad/stream
+      - Static (X/M(aybe)/-)
+      - Mandatory (X/-)
+      - Synopsis
+    * - 1/0
+      - 0/0
+      - X
+      - X
+      - Image data
+    * - 2/0
+      - 0/1
+      - M
+      - \-
+      - Embedded data
+
+Support for the embedded data stream is optional. Drivers supporting the
+embedded data stream may allow disabling and enabling the route.
+
+Sensor pixel array size, cropping and binning
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+The sensor's pixel array is divided into one or more areas. The areas around the
+the visible pixel area in the pixel array, usually one or more sides, may
+contain optical black pixels, dummy pixels and other non-image pixels. The full
+size of the pixel array, including pixels that cannot be captured, is conveyed
+by the format on (pad, stream) pair 1/0.
+
+Capturing the non-visible pixels outside the visible pixel area may be supported
+by the sensor. This area corresponds to the ``V4L2_SEL_TGT_CROP_BOUNDS``
+selection target on (pad, stream) pair 1/0. Non-visible pixels may include
+optical black pixels, dummy pixels or other non-visible pixels. The visible
+pixel area corresponds to the ``V4L2_SEL_TGT_CROP_DEFAULT`` selection target on
+(pad, stream) pair 1/0.
+
+A rectangle within the pixel array contains the visible pixels. Capturing the
+non-visible pixels outside the visible pixel area may be supported by the
+sensor. The visible pixel area corresponds to the ``V4L2_SEL_TGT_CROP_DEFAULT``
+selection target on (pad, stream) pair 1/0.
+
+Sensors can perform multiple operations that affect the output image size. The first
+of these is the analogue crop. Analogue crop limits the area of the pixel array
+which the sensor will read, affecting sensor timing as well. The granularity of
+the analogue crop configuration varies greatly across sensors: some sensors
+support only a few different analogue crop configurations whereas others may
+support anything divisible by a given number of pixels. The analogue crop
+configuration corresponds to the ``V4L2_SEL_TGT_CROP`` selection target on (pad,
+stream) pair 1/0. The default analogue crop rectangle corresponds to the visible
+pixel area.
+
+In the next step, binning is performed on the image data read from camera
+sensor's pixel array, as determined by the analogue crop configuration. Enabling
+binning will effectively result in an image smaller than the original by given
+binning factors horizontally and vertically. Typical values are 1/2 and 1/3 but
+others may well be supported by the hardware as well.
+
+Sub-sampling follows binning. Sub-sampling, like binning, reduces the size of
+the image by including only a subset of samples read from the sensor's pixel
+matrix, typically every n'th pixel horizontally and vertically, taking the
+sensor's color pattern into account. Sub-sampling is generally configurable
+separately horizontally and vertically.
+
+The combined effect of binning and sub-sampling is configured using the
+``V4L2_SEL_TGT_COMPOSE`` rectangle, relative to the analogue crop rectangle, on
+(pad, stream) pair 1/0. The driver implementation determines how to configure
+binning and sub-sampling to achieve the desired size.
+
+The digital crop operation takes place after binning and sub-sampling. It is
+configured by setting the ``V4L2_SEL_TGT_CROP`` rectangle on (pad, stream) pair
+0/0. The resulting image size is further output by the sensor on the sensor's
+data interface.
+
+The sensor's output mbus code is configured by setting the format on the (pad,
+stream) pair 0/0. When setting the format, always use the same width and height
+as for the digital crop setting.
+
+Drivers may only support some or even none of these configurations, in which
+case they do not expose the corresponding selection rectangles. If any selection
+targets are omitted, the further selection rectangle or format is instead
+related to the previous implemented selection rectangle. For instance, if the
+sensor supports binning but not analogue crop, then the binning configuration
+(``V4L2_SEL_TGT_COMPOSE`` selection target) is done in relation to the visible
+pixel area (``V4L2_SEL_TGT_CROP_DEFAULT`` selection target).
+
+Also refer to :ref:`Selection targets <v4l2-selection-targets-table>`.
+
+.. flat-table:: Selection targets on pads
+    :header-rows: 1
+
+    * - Pad/Stream
+      - Selection target/format
+      - Mandatory (X/-)
+      - Modifiable (X/-)
+      - Synopsis
+    * - 1/0
+      - Format
+      - X
+      - \-
+      - The width and the height fields indicates the full size of the physical
+        pixel array, including non-visible pixels and pixels that cannot be
+        captured. The media bus code of this format reflects the native pixel
+        depth of the sensor.
+    * - 1/0
+      - ``V4L2_SEL_TGT_CROP_BOUNDS``
+      - X
+      - \-
+      - The width and the height fields indicates the full size of the pixel
+        array that can be captured, including non-visible pixels. Should the
+        shape of the pixel array not be a rectangle, this rectangle is the
+        smallest possible rectangle that covers all capturable pixels of the
+        pixel array. This rectangle is relative to the format on the same (pad,
+        stream).
+    * - 1/0
+      - ``V4L2_SEL_TGT_CROP_DEFAULT``
+      - X
+      - \-
+      - The visible pixel area. This rectangle is relative to the format on the
+        same (pad, stream).
+    * - 1/0
+      - ``V4L2_SEL_TGT_CROP``
+      - \-
+      - X
+      - Analogue crop. Analogue crop typically has a coarse granularity. This
+        rectangle is relative to the format on the same (pad, stream).
+    * - 1/0
+      - ``V4L2_SEL_TGT_COMPOSE``
+      - \-
+      - X
+      - Binning and sub-sampling. This rectangle is relative to the
+        ``V4L2_SEL_TGT_CROP`` rectangle on the same (pad, stream). The
+        combination of binning and sub-sampling is configured using this
+        selection target.
+    * - 2/0
+      - Format
+      - X
+      - \-
+      - Embedded data format.
+    * - 0/0
+      - ``V4L2_SEL_TGT_CROP``
+      - \-
+      - X
+      - Digital crop. This rectangle is relative to the ``V4L2_SEL_TGT_COMPOSE``
+        rectangle on (pad, stream) pair 1/0.
+    * - 0/0
+      - Format
+      - X
+      - X
+      - Image data source format. Always assign the width and height fields of
+        the format to the same values than for the ``V4L2_SEL_TGT_CROP``
+        rectangle on (pad, stream) pair 0/0. The media bus code reflects the
+        pixel data output of the sensor. Setting the media bus code on this pad
+        configures the output format.
+    * - 0/1
+      - Format
+      - X
+      - \-
+      - Embedded data source format.
+
+Embedded data
+^^^^^^^^^^^^^
+
+The embedded data stream is produced by the sensor when the corresponding route
+is enabled. The embedded data route may also be immutable or not exist at all,
+in case the sensor (or the driver) does not support it.
+
+Generally the sensor embedded data width is determined by the width of the image
+data whereas the number of lines are constant for the embedded data. The user
+space may obtain the size of the embedded data once the image data size on the
+source pad has been configured.
+
+Also see :ref:`media_using_camera_sensor_drivers_embedded_data`.
-- 
2.47.3


^ permalink raw reply related	[flat|nested] 88+ messages in thread

* [PATCH v12 23/86] media: v4l2-subdev: Prevent accessing internal pads without STREAMS cap
  2026-04-09 20:13 [PATCH v12 00/86] Generic line based metadata support, internal pads Sakari Ailus
                   ` (21 preceding siblings ...)
  2026-04-09 20:13 ` [PATCH v12 22/86] media: Documentation: Add subdev configuration models, raw sensor model Sakari Ailus
@ 2026-04-09 20:13 ` Sakari Ailus
  2026-04-09 20:13 ` [PATCH v12 24/86] media: Documentation: Add scaling and post-scaler crop for common raw Sakari Ailus
                   ` (62 subsequent siblings)
  85 siblings, 0 replies; 88+ messages in thread
From: Sakari Ailus @ 2026-04-09 20:13 UTC (permalink / raw)
  To: linux-media
  Cc: hans, laurent.pinchart, Prabhakar, Kate Hsuan, Dave Stevenson,
	Tommaso Merciai, Benjamin Mugnier, Sylvain Petinot,
	Christophe JAILLET, Julien Massot, Naushir Patuck, Stefan Klug,
	Mirela Rabulea, André Apitzsch, Heimir Thor Sverrisson,
	Kieran Bingham, Mehdi Djait, Ricardo Ribalda Delgado,
	Hans de Goede, Jacopo Mondi, Tomi Valkeinen, David Plowman,
	Yu, Ong Hock, Ng, Khai Wen, Jai Luthra, Rishikesh Donadkar

The internal pads are expected to be accessed by users that are aware of
streams. Require the V4L2_SUBDEV_CLIENT_CAP_STREAMS client capability to
be set before allowing accessing internal pads from the user space.

Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
---
 drivers/media/v4l2-core/v4l2-subdev.c | 41 ++++++++++++++++++++++++---
 1 file changed, 37 insertions(+), 4 deletions(-)

diff --git a/drivers/media/v4l2-core/v4l2-subdev.c b/drivers/media/v4l2-core/v4l2-subdev.c
index 7723e37a0ff5..c6d8399c2252 100644
--- a/drivers/media/v4l2-core/v4l2-subdev.c
+++ b/drivers/media/v4l2-core/v4l2-subdev.c
@@ -234,6 +234,18 @@ static int check_state(struct v4l2_subdev *sd, struct v4l2_subdev_state *state,
 	return 0;
 }
 
+static inline int check_caps(struct v4l2_subdev *sd,
+			     struct v4l2_subdev_state *state,
+			     const struct v4l2_subdev_client_info *ci,
+			     u32 pad)
+{
+	if (sd->entity.pads[pad].flags & MEDIA_PAD_FL_INTERNAL)
+		return ci->client_caps & V4L2_SUBDEV_CLIENT_CAP_STREAMS ?
+			0 : -EINVAL;
+
+	return 0;
+}
+
 static inline int check_format(struct v4l2_subdev *sd,
 			       struct v4l2_subdev_state *state,
 			       struct v4l2_subdev_format *format)
@@ -245,12 +257,21 @@ static inline int check_format(struct v4l2_subdev *sd,
 	       check_state(sd, state, format->which, format->pad, format->stream);
 }
 
+static inline int check_format_caps(struct v4l2_subdev *sd,
+				    const struct v4l2_subdev_client_info *ci,
+				    struct v4l2_subdev_state *state,
+				    struct v4l2_subdev_format *format)
+{
+	return check_format(sd, state, format) ?:
+		check_caps(sd, state, ci, format->pad);
+}
+
 static int call_get_fmt(struct v4l2_subdev *sd,
 			const struct v4l2_subdev_client_info *ci,
 			struct v4l2_subdev_state *state,
 			struct v4l2_subdev_format *format)
 {
-	return check_format(sd, state, format) ? :
+	return check_format_caps(sd, ci, state, format) ? :
 		sd->ops->pad->get_fmt(sd, ci, state, format);
 }
 
@@ -259,7 +280,7 @@ static int call_set_fmt(struct v4l2_subdev *sd,
 			struct v4l2_subdev_state *state,
 			struct v4l2_subdev_format *format)
 {
-	return check_format(sd, state, format) ? :
+	return check_format_caps(sd, ci, state, format) ? :
 		sd->ops->pad->set_fmt(sd, ci, state, format);
 }
 
@@ -310,12 +331,24 @@ static inline int check_selection(struct v4l2_subdev *sd,
 	       check_state(sd, state, sel->which, sel->pad, sel->stream);
 }
 
+static inline int check_selection_caps(struct v4l2_subdev *sd,
+				       const struct v4l2_subdev_client_info *ci,
+				       struct v4l2_subdev_state *state,
+				       struct v4l2_subdev_selection *sel)
+{
+	if (!sel)
+		return -EINVAL;
+
+	return check_selection(sd, state, sel) ? :
+		check_caps(sd, state, ci, sel->pad);
+}
+
 static int call_get_selection(struct v4l2_subdev *sd,
 			      const struct v4l2_subdev_client_info *ci,
 			      struct v4l2_subdev_state *state,
 			      struct v4l2_subdev_selection *sel)
 {
-	return check_selection(sd, state, sel) ? :
+	return check_selection_caps(sd, ci, state, sel) ? :
 		sd->ops->pad->get_selection(sd, ci, state, sel);
 }
 
@@ -324,7 +357,7 @@ static int call_set_selection(struct v4l2_subdev *sd,
 			      struct v4l2_subdev_state *state,
 			      struct v4l2_subdev_selection *sel)
 {
-	return check_selection(sd, state, sel) ? :
+	return check_selection_caps(sd, ci, state, sel) ? :
 		sd->ops->pad->set_selection(sd, ci, state, sel);
 }
 
-- 
2.47.3


^ permalink raw reply related	[flat|nested] 88+ messages in thread

* [PATCH v12 24/86] media: Documentation: Add scaling and post-scaler crop for common raw
  2026-04-09 20:13 [PATCH v12 00/86] Generic line based metadata support, internal pads Sakari Ailus
                   ` (22 preceding siblings ...)
  2026-04-09 20:13 ` [PATCH v12 23/86] media: v4l2-subdev: Prevent accessing internal pads without STREAMS cap Sakari Ailus
@ 2026-04-09 20:13 ` Sakari Ailus
  2026-04-09 20:14 ` [PATCH v12 25/86] media: uapi: Add MIPI CCS configuration model Sakari Ailus
                   ` (61 subsequent siblings)
  85 siblings, 0 replies; 88+ messages in thread
From: Sakari Ailus @ 2026-04-09 20:13 UTC (permalink / raw)
  To: linux-media
  Cc: hans, laurent.pinchart, Prabhakar, Kate Hsuan, Dave Stevenson,
	Tommaso Merciai, Benjamin Mugnier, Sylvain Petinot,
	Christophe JAILLET, Julien Massot, Naushir Patuck, Stefan Klug,
	Mirela Rabulea, André Apitzsch, Heimir Thor Sverrisson,
	Kieran Bingham, Mehdi Djait, Ricardo Ribalda Delgado,
	Hans de Goede, Jacopo Mondi, Tomi Valkeinen, David Plowman,
	Yu, Ong Hock, Ng, Khai Wen, Jai Luthra, Rishikesh Donadkar

Document scaling and post-scaler digital crop operations for the common
raw sensor model.

Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
Reviewed-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
Reviewed-by: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
Reviewed-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
---
 .../media/v4l/subdev-config-model.rst         | 26 ++++++++++++++-----
 1 file changed, 20 insertions(+), 6 deletions(-)

diff --git a/Documentation/userspace-api/media/v4l/subdev-config-model.rst b/Documentation/userspace-api/media/v4l/subdev-config-model.rst
index b450f698a608..1525119cbeb9 100644
--- a/Documentation/userspace-api/media/v4l/subdev-config-model.rst
+++ b/Documentation/userspace-api/media/v4l/subdev-config-model.rst
@@ -146,12 +146,19 @@ binning and sub-sampling to achieve the desired size.
 
 The digital crop operation takes place after binning and sub-sampling. It is
 configured by setting the ``V4L2_SEL_TGT_CROP`` rectangle on (pad, stream) pair
-0/0. The resulting image size is further output by the sensor on the sensor's
-data interface.
+0/0.
+
+The scaling operation is performed after the digital crop. It is configured by
+setting the ``V4L2_SEL_TGT_COMPOSE`` rectangle on (pad, stream) pair 0/0,
+relative to the digital crop. The resulting image size is further output by the
+sensor on the sensor's data interface.
 
 The sensor's output mbus code is configured by setting the format on the (pad,
-stream) pair 0/0. When setting the format, always use the same width and height
-as for the digital crop setting.
+stream) pair 0/0. The width and height fields are used to configure post-scaler
+digital crop if supported by the driver, affecting the right and bottom edges of
+the frame. If post-scaler digital crop is not supported, the width and height
+fields of the format will match the compose rectangle sizes applied on the same
+0/0 (pad, stream) pair.
 
 Drivers may only support some or even none of these configurations, in which
 case they do not expose the corresponding selection rectangles. If any selection
@@ -220,12 +227,19 @@ Also refer to :ref:`Selection targets <v4l2-selection-targets-table>`.
       - X
       - Digital crop. This rectangle is relative to the ``V4L2_SEL_TGT_COMPOSE``
         rectangle on (pad, stream) pair 1/0.
+    * - 0/0
+      - ``V4L2_SEL_TGT_COMPOSE``
+      - \-
+      - X
+      - Scaling. This rectangle is relative to the ``V4L2_SEL_TGT_CROP``
+        rectangle on (pad, stream) pair 0/0.
     * - 0/0
       - Format
       - X
       - X
-      - Image data source format. Always assign the width and height fields of
-        the format to the same values than for the ``V4L2_SEL_TGT_CROP``
+      - Image data source format and post-scaler crop. The width and height
+        fields of the format, used to configure post-scaler crop on the right
+        and bottom edges of the image, are related to the ``V4L2_SEL_TGT_COMPOSE``
         rectangle on (pad, stream) pair 0/0. The media bus code reflects the
         pixel data output of the sensor. Setting the media bus code on this pad
         configures the output format.
-- 
2.47.3


^ permalink raw reply related	[flat|nested] 88+ messages in thread

* [PATCH v12 25/86] media: uapi: Add MIPI CCS configuration model
  2026-04-09 20:13 [PATCH v12 00/86] Generic line based metadata support, internal pads Sakari Ailus
                   ` (23 preceding siblings ...)
  2026-04-09 20:13 ` [PATCH v12 24/86] media: Documentation: Add scaling and post-scaler crop for common raw Sakari Ailus
@ 2026-04-09 20:14 ` Sakari Ailus
  2026-04-09 20:14 ` [PATCH v12 26/86] media: uapi: Add V4L2_SUBDEV_CLIENT_CAP_COMMON_RAW_SENSOR Sakari Ailus
                   ` (60 subsequent siblings)
  85 siblings, 0 replies; 88+ messages in thread
From: Sakari Ailus @ 2026-04-09 20:14 UTC (permalink / raw)
  To: linux-media
  Cc: hans, laurent.pinchart, Prabhakar, Kate Hsuan, Dave Stevenson,
	Tommaso Merciai, Benjamin Mugnier, Sylvain Petinot,
	Christophe JAILLET, Julien Massot, Naushir Patuck, Stefan Klug,
	Mirela Rabulea, André Apitzsch, Heimir Thor Sverrisson,
	Kieran Bingham, Mehdi Djait, Ricardo Ribalda Delgado,
	Hans de Goede, Jacopo Mondi, Tomi Valkeinen, David Plowman,
	Yu, Ong Hock, Ng, Khai Wen, Jai Luthra, Rishikesh Donadkar

Add a configuration model for MIPI CCS sensors and refer to the CCS driver
documentation from it. If more drivers start implementing the CCS model
the documentation should be split into two but that appears to be unlikely
at the moment.

Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
---
 .../userspace-api/media/v4l/subdev-config-model.rst         | 6 ++++++
 include/uapi/linux/v4l2-controls.h                          | 1 +
 2 files changed, 7 insertions(+)

diff --git a/Documentation/userspace-api/media/v4l/subdev-config-model.rst b/Documentation/userspace-api/media/v4l/subdev-config-model.rst
index 1525119cbeb9..3011643d58cf 100644
--- a/Documentation/userspace-api/media/v4l/subdev-config-model.rst
+++ b/Documentation/userspace-api/media/v4l/subdev-config-model.rst
@@ -262,3 +262,9 @@ space may obtain the size of the embedded data once the image data size on the
 source pad has been configured.
 
 Also see :ref:`media_using_camera_sensor_drivers_embedded_data`.
+
+MIPI Camera Command Set (CCS) model
+-----------------------------------
+
+The MIPI Camera Command Set configuration model is implemented by the :ref:`CCS
+driver <media-ccs-uapi>`.
diff --git a/include/uapi/linux/v4l2-controls.h b/include/uapi/linux/v4l2-controls.h
index 2f0bd33bbc3d..1bf6d298e3c4 100644
--- a/include/uapi/linux/v4l2-controls.h
+++ b/include/uapi/linux/v4l2-controls.h
@@ -1262,6 +1262,7 @@ enum v4l2_jpeg_chroma_subsampling {
 #define V4L2_CID_CONFIG_MODEL			(V4L2_CID_IMAGE_PROC_CLASS_BASE + 6)
 
 #define V4L2_CONFIG_MODEL_COMMON_RAW_SENSOR	(1U << 0)
+#define V4L2_CONFIG_MODEL_MIPI_CCS		(1U << 1)
 
 /*  DV-class control IDs defined by V4L2 */
 #define V4L2_CID_DV_CLASS_BASE			(V4L2_CTRL_CLASS_DV | 0x900)
-- 
2.47.3


^ permalink raw reply related	[flat|nested] 88+ messages in thread

* [PATCH v12 26/86] media: uapi: Add V4L2_SUBDEV_CLIENT_CAP_COMMON_RAW_SENSOR
  2026-04-09 20:13 [PATCH v12 00/86] Generic line based metadata support, internal pads Sakari Ailus
                   ` (24 preceding siblings ...)
  2026-04-09 20:14 ` [PATCH v12 25/86] media: uapi: Add MIPI CCS configuration model Sakari Ailus
@ 2026-04-09 20:14 ` Sakari Ailus
  2026-04-09 20:14 ` [PATCH v12 27/86] media: uapi: Add V4L2_CID_BINNING control for binning configuration Sakari Ailus
                   ` (59 subsequent siblings)
  85 siblings, 0 replies; 88+ messages in thread
From: Sakari Ailus @ 2026-04-09 20:14 UTC (permalink / raw)
  To: linux-media
  Cc: hans, laurent.pinchart, Prabhakar, Kate Hsuan, Dave Stevenson,
	Tommaso Merciai, Benjamin Mugnier, Sylvain Petinot,
	Christophe JAILLET, Julien Massot, Naushir Patuck, Stefan Klug,
	Mirela Rabulea, André Apitzsch, Heimir Thor Sverrisson,
	Kieran Bingham, Mehdi Djait, Ricardo Ribalda Delgado,
	Hans de Goede, Jacopo Mondi, Tomi Valkeinen, David Plowman,
	Yu, Ong Hock, Ng, Khai Wen, Jai Luthra, Rishikesh Donadkar

Add V4L2_SUBDEV_CLIENT_CAP_COMMON_RAW_SENSOR client capability bit to
signal the userspace's support for the common raw sensor model and
document it. A specific capability bit is required for the purpose of
adding support for the common raw sensor model to existing drivers that
already have a well-established UAPI that cannot be modified without
breaking the userspace.

Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
---
 .../userspace-api/media/v4l/ext-ctrls-image-process.rst     | 2 ++
 .../userspace-api/media/v4l/subdev-config-model.rst         | 5 ++++-
 .../userspace-api/media/v4l/vidioc-subdev-g-client-cap.rst  | 6 ++++++
 drivers/media/v4l2-core/v4l2-subdev.c                       | 3 ++-
 include/uapi/linux/v4l2-subdev.h                            | 6 ++++++
 5 files changed, 20 insertions(+), 2 deletions(-)

diff --git a/Documentation/userspace-api/media/v4l/ext-ctrls-image-process.rst b/Documentation/userspace-api/media/v4l/ext-ctrls-image-process.rst
index 51188e7febae..983c7412c9f4 100644
--- a/Documentation/userspace-api/media/v4l/ext-ctrls-image-process.rst
+++ b/Documentation/userspace-api/media/v4l/ext-ctrls-image-process.rst
@@ -59,6 +59,8 @@ Image Process Control IDs
     digital gain the control value needs to be 0x100. The no-gain
     configuration is also typically the default.
 
+.. _v4l2-cid-config-model:
+
 ``V4L2_CID_CONFIG_MODEL (bitmask)``
     Which configuration models the sub-device supports. Please see
     :ref:`media_subdev_config_model`. This is a read-only control.
diff --git a/Documentation/userspace-api/media/v4l/subdev-config-model.rst b/Documentation/userspace-api/media/v4l/subdev-config-model.rst
index 3011643d58cf..0fb01bf6c825 100644
--- a/Documentation/userspace-api/media/v4l/subdev-config-model.rst
+++ b/Documentation/userspace-api/media/v4l/subdev-config-model.rst
@@ -41,7 +41,10 @@ necessarily offered by all drivers.
 
 A sub-device complies with the common raw sensor model if the
 ``V4L2_CONFIG_MODEL_COMMON_RAW_SENSOR`` bit is set in the
-``V4L2_CID_CONFIG_MODEL`` control of the sub-device.
+``V4L2_CID_CONFIG_MODEL`` control of the sub-device. A client supporting the
+common raw sensor model shall set the
+``V4L2_SUBDEV_CLIENT_CAP_COMMON_RAW_SENSOR`` :ref:`sub-device client capability
+<VIDIOC_SUBDEV_G_CLIENT_CAP>` bit.
 
 The common raw camera sensor model is aligned with
 :ref:`media_using_camera_sensor_drivers`. Please refer to that regarding aspects
diff --git a/Documentation/userspace-api/media/v4l/vidioc-subdev-g-client-cap.rst b/Documentation/userspace-api/media/v4l/vidioc-subdev-g-client-cap.rst
index da4a358ce762..50ac223e10db 100644
--- a/Documentation/userspace-api/media/v4l/vidioc-subdev-g-client-cap.rst
+++ b/Documentation/userspace-api/media/v4l/vidioc-subdev-g-client-cap.rst
@@ -91,6 +91,12 @@ is unknown to the kernel.
         ``which`` field. If this is not set (which is the default), the
         ``which`` field is forced to ``V4L2_SUBDEV_FORMAT_ACTIVE`` by the
         kernel.
+    * - ``V4L2_SUBDEV_CLIENT_CAP_COMMON_RAW_SENSOR``
+      - The client is aware of the :ref:`common raw sensor model
+        <media_subdev_config_model_common_raw_sensor>` and expects it where it
+        is supported, as indicated by the :ref:`V4L2_CID_CONFIG_MODEL
+        <v4l2-cid-config-model>` control bit
+        ``V4L2_CONFIG_MODEL_COMMON_RAW_SENSOR``.
 
 Return Value
 ============
diff --git a/drivers/media/v4l2-core/v4l2-subdev.c b/drivers/media/v4l2-core/v4l2-subdev.c
index c6d8399c2252..4b7830f705a2 100644
--- a/drivers/media/v4l2-core/v4l2-subdev.c
+++ b/drivers/media/v4l2-core/v4l2-subdev.c
@@ -1200,7 +1200,8 @@ static long subdev_do_ioctl(struct file *file, unsigned int cmd, void *arg,
 
 		/* Filter out unsupported capabilities */
 		client_cap->capabilities &= (V4L2_SUBDEV_CLIENT_CAP_STREAMS |
-					     V4L2_SUBDEV_CLIENT_CAP_INTERVAL_USES_WHICH);
+					     V4L2_SUBDEV_CLIENT_CAP_INTERVAL_USES_WHICH |
+					     V4L2_SUBDEV_CLIENT_CAP_COMMON_RAW_SENSOR);
 
 		subdev_fh->ci.client_caps = client_cap->capabilities;
 
diff --git a/include/uapi/linux/v4l2-subdev.h b/include/uapi/linux/v4l2-subdev.h
index 477d3ce3ddb4..9d5ba062be19 100644
--- a/include/uapi/linux/v4l2-subdev.h
+++ b/include/uapi/linux/v4l2-subdev.h
@@ -270,6 +270,12 @@ struct v4l2_subdev_routing {
  */
 #define V4L2_SUBDEV_CLIENT_CAP_INTERVAL_USES_WHICH	(1ULL << 1)
 
+/*
+ * The client is aware of the common raw sensor model and expects that on camera
+ * sensor UAPI where supported.
+ */
+#define V4L2_SUBDEV_CLIENT_CAP_COMMON_RAW_SENSOR	(1ULL << 2)
+
 /**
  * struct v4l2_subdev_client_capability - Capabilities of the client accessing
  *					  the subdev
-- 
2.47.3


^ permalink raw reply related	[flat|nested] 88+ messages in thread

* [PATCH v12 27/86] media: uapi: Add V4L2_CID_BINNING control for binning configuration
  2026-04-09 20:13 [PATCH v12 00/86] Generic line based metadata support, internal pads Sakari Ailus
                   ` (25 preceding siblings ...)
  2026-04-09 20:14 ` [PATCH v12 26/86] media: uapi: Add V4L2_SUBDEV_CLIENT_CAP_COMMON_RAW_SENSOR Sakari Ailus
@ 2026-04-09 20:14 ` Sakari Ailus
  2026-04-14 15:55   ` Jacopo Mondi
  2026-04-09 20:14 ` [PATCH v12 28/86] media: uapi: Add controls for sub-sampling configuration Sakari Ailus
                   ` (58 subsequent siblings)
  85 siblings, 1 reply; 88+ messages in thread
From: Sakari Ailus @ 2026-04-09 20:14 UTC (permalink / raw)
  To: linux-media
  Cc: hans, laurent.pinchart, Prabhakar, Kate Hsuan, Dave Stevenson,
	Tommaso Merciai, Benjamin Mugnier, Sylvain Petinot,
	Christophe JAILLET, Julien Massot, Naushir Patuck, Stefan Klug,
	Mirela Rabulea, André Apitzsch, Heimir Thor Sverrisson,
	Kieran Bingham, Mehdi Djait, Ricardo Ribalda Delgado,
	Hans de Goede, Jacopo Mondi, Tomi Valkeinen, David Plowman,
	Yu, Ong Hock, Ng, Khai Wen, Jai Luthra, Rishikesh Donadkar

Add V4L2_CID_BINNING control for configuring binning and enumerating a
camera sensor's binning capabilities. The control combines horizontal and
vertical binning into a single control as the two are generally related.

New drivers should use this control to configure binning.

Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
Reviewed-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
Reviewed-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
---
 .../media/drivers/camera-sensor.rst           | 12 ++++++++
 .../media/v4l/ext-ctrls-image-source.rst      | 30 +++++++++++++++++++
 drivers/media/v4l2-core/v4l2-ctrls-defs.c     |  2 ++
 include/uapi/linux/v4l2-controls.h            |  2 ++
 4 files changed, 46 insertions(+)

diff --git a/Documentation/userspace-api/media/drivers/camera-sensor.rst b/Documentation/userspace-api/media/drivers/camera-sensor.rst
index d8ba809486c5..12f075379bc8 100644
--- a/Documentation/userspace-api/media/drivers/camera-sensor.rst
+++ b/Documentation/userspace-api/media/drivers/camera-sensor.rst
@@ -120,6 +120,18 @@ values programmed by the register sequences. The default values of these
 controls shall be 0 (disabled). Especially these controls shall not be inverted,
 independently of the sensor's mounting rotation.
 
+Binning
+-------
+
+Binning has traditionally been configured using :ref:`the compose selection
+rectangle <v4l2-selection-targets-table>`. The :ref:`V4L2_CID_BINNING
+<image_source_control_binning_factors>` control is also available for binning
+configuration and users should use it when it's available. Drivers supporting
+the control shall also support the compose rectangle, albeit the rectangle may
+be read-only when the control is present.
+
+Binning isn't affected by flipping.
+
 .. _media_using_camera_sensor_drivers_embedded_data:
 
 Embedded data
diff --git a/Documentation/userspace-api/media/v4l/ext-ctrls-image-source.rst b/Documentation/userspace-api/media/v4l/ext-ctrls-image-source.rst
index 490cd16186cd..0ef76b02a6e1 100644
--- a/Documentation/userspace-api/media/v4l/ext-ctrls-image-source.rst
+++ b/Documentation/userspace-api/media/v4l/ext-ctrls-image-source.rst
@@ -160,3 +160,33 @@ Image Source Control IDs
     interface for metadata streams. The control is used in conjunction with
     :ref:`generic metadata formats <media-bus-format-generic-meta>` formats to
     specify the layout of the data.
+
+.. _image_source_control_binning_factors:
+
+``V4L2_CID_BINNING_FACTORS (integer menu)``
+
+    This control determines horizontal and vertical binning factors. Binning
+    combines several horizontal, vertical or both pixel values into a single
+    pixel. It is a way to scale an image. Binning typically produces fairly good
+    quality output.
+
+    Determines both horizontal and vertical binning factors for a camera
+    sensor. The values are encoded in the following way:
+
+.. flat-table::
+    :header-rows:  1
+    :stub-columns: 0
+
+    * - Bits
+      - Synopsis
+    * - 48--63
+      - Horizontal binning numerator.
+    * - 32--47
+      - Horizontal binning denominator.
+    * - 16--31
+      - Vertical binning numerator.
+    * - 0--15
+      - Vertical binning denominator.
+
+For instance, a value of ``0x0001000300020003`` indicates binning by 3
+(horizontally) * 3/2 (vertically).
diff --git a/drivers/media/v4l2-core/v4l2-ctrls-defs.c b/drivers/media/v4l2-core/v4l2-ctrls-defs.c
index 4618252d24f2..fee343667b69 100644
--- a/drivers/media/v4l2-core/v4l2-ctrls-defs.c
+++ b/drivers/media/v4l2-core/v4l2-ctrls-defs.c
@@ -1160,6 +1160,7 @@ const char *v4l2_ctrl_get_name(u32 id)
 	case V4L2_CID_CFA_PATTERN:		return "Color Filter Array Pattern";
 	case V4L2_CID_CFA_PATTERN_FLIP:		return "CFA Pattern Flip";
 	case V4L2_CID_METADATA_LAYOUT:		return "Metadata Layout";
+	case V4L2_CID_BINNING_FACTORS:		return "Binning Factors";
 
 	/* Image processing controls */
 	/* Keep the order of the 'case's the same as in v4l2-controls.h! */
@@ -1438,6 +1439,7 @@ void v4l2_ctrl_fill(u32 id, const char **name, enum v4l2_ctrl_type *type,
 	case V4L2_CID_HDR_SENSOR_MODE:
 		*type = V4L2_CTRL_TYPE_MENU;
 		break;
+	case V4L2_CID_BINNING_FACTORS:
 	case V4L2_CID_LINK_FREQ:
 		*type = V4L2_CTRL_TYPE_INTEGER_MENU;
 		break;
diff --git a/include/uapi/linux/v4l2-controls.h b/include/uapi/linux/v4l2-controls.h
index 1bf6d298e3c4..5496b1664432 100644
--- a/include/uapi/linux/v4l2-controls.h
+++ b/include/uapi/linux/v4l2-controls.h
@@ -1249,6 +1249,8 @@ enum v4l2_jpeg_chroma_subsampling {
 
 #define V4L2_CID_METADATA_LAYOUT		(V4L2_CID_IMAGE_SOURCE_CLASS_BASE + 12)
 
+#define V4L2_CID_BINNING_FACTORS		(V4L2_CID_IMAGE_SOURCE_CLASS_BASE + 13)
+
 /* Image processing controls */
 
 #define V4L2_CID_IMAGE_PROC_CLASS_BASE		(V4L2_CTRL_CLASS_IMAGE_PROC | 0x900)
-- 
2.47.3


^ permalink raw reply related	[flat|nested] 88+ messages in thread

* [PATCH v12 28/86] media: uapi: Add controls for sub-sampling configuration
  2026-04-09 20:13 [PATCH v12 00/86] Generic line based metadata support, internal pads Sakari Ailus
                   ` (26 preceding siblings ...)
  2026-04-09 20:14 ` [PATCH v12 27/86] media: uapi: Add V4L2_CID_BINNING control for binning configuration Sakari Ailus
@ 2026-04-09 20:14 ` Sakari Ailus
  2026-04-09 20:14 ` [PATCH v12 29/86] media: v4l2-mc: Add v4l2_subdev_sensor_fll_llp_set() Sakari Ailus
                   ` (57 subsequent siblings)
  85 siblings, 0 replies; 88+ messages in thread
From: Sakari Ailus @ 2026-04-09 20:14 UTC (permalink / raw)
  To: linux-media
  Cc: hans, laurent.pinchart, Prabhakar, Kate Hsuan, Dave Stevenson,
	Tommaso Merciai, Benjamin Mugnier, Sylvain Petinot,
	Christophe JAILLET, Julien Massot, Naushir Patuck, Stefan Klug,
	Mirela Rabulea, André Apitzsch, Heimir Thor Sverrisson,
	Kieran Bingham, Mehdi Djait, Ricardo Ribalda Delgado,
	Hans de Goede, Jacopo Mondi, Tomi Valkeinen, David Plowman,
	Yu, Ong Hock, Ng, Khai Wen, Jai Luthra, Rishikesh Donadkar

Sub-sampling is a way to decrease the data rates after the pixel array by
systematically discarding some samples, either vertically or horizontally
or both. Add two controls for the purpose and document them. The
sub-sampling configuration is taken into account in the compose rectangle.

Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
Reviewed-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
---
 .../media/drivers/camera-sensor.rst              | 16 +++++++++++++---
 .../media/v4l/ext-ctrls-image-source.rst         | 11 +++++++++++
 drivers/media/v4l2-core/v4l2-ctrls-defs.c        |  2 ++
 include/uapi/linux/v4l2-controls.h               |  2 ++
 4 files changed, 28 insertions(+), 3 deletions(-)

diff --git a/Documentation/userspace-api/media/drivers/camera-sensor.rst b/Documentation/userspace-api/media/drivers/camera-sensor.rst
index 12f075379bc8..aa05681c7090 100644
--- a/Documentation/userspace-api/media/drivers/camera-sensor.rst
+++ b/Documentation/userspace-api/media/drivers/camera-sensor.rst
@@ -120,8 +120,8 @@ values programmed by the register sequences. The default values of these
 controls shall be 0 (disabled). Especially these controls shall not be inverted,
 independently of the sensor's mounting rotation.
 
-Binning
--------
+Binning and sub-sampling
+------------------------
 
 Binning has traditionally been configured using :ref:`the compose selection
 rectangle <v4l2-selection-targets-table>`. The :ref:`V4L2_CID_BINNING
@@ -130,7 +130,17 @@ configuration and users should use it when it's available. Drivers supporting
 the control shall also support the compose rectangle, albeit the rectangle may
 be read-only when the control is present.
 
-Binning isn't affected by flipping.
+Sub-sampling is often supported as part of a camera sensor's binning
+functionality and performed after the binning operation. Sub-sampling typically
+produces quality-wise worse results than binning. Sub-sampling factors are
+independent horizontally and vertically and they are controlled using two
+controls, :ref:`V4L2_CID_SUBSAMPLING_HORIZONTAL and
+V4L2_CID_SUBSAMPLING_VERTICAL <image_source_control_subsampling>`. In
+sub-sampling, the image size before sub-sampling is horizontally and vertically
+divided by the respective sub-sampling factors. Drivers supporting the control shall
+also reflect the sub-sampling configuration in the compose rectangle.
+
+Binning and sub-sampling aren't affected by flipping.
 
 .. _media_using_camera_sensor_drivers_embedded_data:
 
diff --git a/Documentation/userspace-api/media/v4l/ext-ctrls-image-source.rst b/Documentation/userspace-api/media/v4l/ext-ctrls-image-source.rst
index 0ef76b02a6e1..63e53c883db6 100644
--- a/Documentation/userspace-api/media/v4l/ext-ctrls-image-source.rst
+++ b/Documentation/userspace-api/media/v4l/ext-ctrls-image-source.rst
@@ -190,3 +190,14 @@ Image Source Control IDs
 
 For instance, a value of ``0x0001000300020003`` indicates binning by 3
 (horizontally) * 3/2 (vertically).
+
+.. _image_source_control_subsampling:
+
+``V4L2_CID_SUBSAMPLING_HORIZONTAL`` and ``V4L2_CID_SUBSAMPLING_VERTICAL``
+(integer)
+
+    Horizontal and vertical subsampling factors.
+
+    Sub-sampling is used to downscale an image, horizontally and vertically, by
+    discarding a part of the image data. Typically sub-sampling produces lower
+    quality images than binning.
diff --git a/drivers/media/v4l2-core/v4l2-ctrls-defs.c b/drivers/media/v4l2-core/v4l2-ctrls-defs.c
index fee343667b69..227bcb5a549d 100644
--- a/drivers/media/v4l2-core/v4l2-ctrls-defs.c
+++ b/drivers/media/v4l2-core/v4l2-ctrls-defs.c
@@ -1161,6 +1161,8 @@ const char *v4l2_ctrl_get_name(u32 id)
 	case V4L2_CID_CFA_PATTERN_FLIP:		return "CFA Pattern Flip";
 	case V4L2_CID_METADATA_LAYOUT:		return "Metadata Layout";
 	case V4L2_CID_BINNING_FACTORS:		return "Binning Factors";
+	case V4L2_CID_SUBSAMPLING_HORIZONTAL:	return "Sub-Sampling Factor, Horizontal";
+	case V4L2_CID_SUBSAMPLING_VERTICAL:	return "Sub-Sampling Factor, Vertical";
 
 	/* Image processing controls */
 	/* Keep the order of the 'case's the same as in v4l2-controls.h! */
diff --git a/include/uapi/linux/v4l2-controls.h b/include/uapi/linux/v4l2-controls.h
index 5496b1664432..acb6f9ad4d1b 100644
--- a/include/uapi/linux/v4l2-controls.h
+++ b/include/uapi/linux/v4l2-controls.h
@@ -1250,6 +1250,8 @@ enum v4l2_jpeg_chroma_subsampling {
 #define V4L2_CID_METADATA_LAYOUT		(V4L2_CID_IMAGE_SOURCE_CLASS_BASE + 12)
 
 #define V4L2_CID_BINNING_FACTORS		(V4L2_CID_IMAGE_SOURCE_CLASS_BASE + 13)
+#define V4L2_CID_SUBSAMPLING_HORIZONTAL		(V4L2_CID_IMAGE_SOURCE_CLASS_BASE + 14)
+#define V4L2_CID_SUBSAMPLING_VERTICAL		(V4L2_CID_IMAGE_SOURCE_CLASS_BASE + 15)
 
 /* Image processing controls */
 
-- 
2.47.3


^ permalink raw reply related	[flat|nested] 88+ messages in thread

* [PATCH v12 29/86] media: v4l2-mc: Add v4l2_subdev_sensor_fll_llp_set()
  2026-04-09 20:13 [PATCH v12 00/86] Generic line based metadata support, internal pads Sakari Ailus
                   ` (27 preceding siblings ...)
  2026-04-09 20:14 ` [PATCH v12 28/86] media: uapi: Add controls for sub-sampling configuration Sakari Ailus
@ 2026-04-09 20:14 ` Sakari Ailus
  2026-04-09 20:14 ` [PATCH v12 30/86] media: Documentation: Add binning and sub-sampling controls Sakari Ailus
                   ` (56 subsequent siblings)
  85 siblings, 0 replies; 88+ messages in thread
From: Sakari Ailus @ 2026-04-09 20:14 UTC (permalink / raw)
  To: linux-media
  Cc: hans, laurent.pinchart, Prabhakar, Kate Hsuan, Dave Stevenson,
	Tommaso Merciai, Benjamin Mugnier, Sylvain Petinot,
	Christophe JAILLET, Julien Massot, Naushir Patuck, Stefan Klug,
	Mirela Rabulea, André Apitzsch, Heimir Thor Sverrisson,
	Kieran Bingham, Mehdi Djait, Ricardo Ribalda Delgado,
	Hans de Goede, Jacopo Mondi, Tomi Valkeinen, David Plowman,
	Yu, Ong Hock, Ng, Khai Wen, Jai Luthra, Rishikesh Donadkar

Add v4l2_subdev_sensor_fll_llp_set() to facilitate driver implementation
of both blanking and line and frame lenght controls.

Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
---
 drivers/media/v4l2-core/v4l2-mc.c | 67 +++++++++++++++++++++++++++++++
 include/media/v4l2-mc.h           |  8 ++++
 2 files changed, 75 insertions(+)

diff --git a/drivers/media/v4l2-core/v4l2-mc.c b/drivers/media/v4l2-core/v4l2-mc.c
index 937d358697e1..2e0be23d7511 100644
--- a/drivers/media/v4l2-core/v4l2-mc.c
+++ b/drivers/media/v4l2-core/v4l2-mc.c
@@ -14,6 +14,7 @@
 #include <linux/usb.h>
 #include <media/media-device.h>
 #include <media/media-entity.h>
+#include <media/v4l2-ctrls.h>
 #include <media/v4l2-fh.h>
 #include <media/v4l2-mc.h>
 #include <media/v4l2-subdev.h>
@@ -427,6 +428,72 @@ int v4l2_create_fwnode_links(struct v4l2_subdev *src_sd,
 }
 EXPORT_SYMBOL_GPL(v4l2_create_fwnode_links);
 
+int v4l2_subdev_sensor_fll_llp_set(struct v4l2_ctrl *fll, struct v4l2_ctrl *vblank,
+				   struct v4l2_ctrl *llp, struct v4l2_ctrl *hblank,
+				   struct v4l2_ctrl *exposure,
+				   const struct v4l2_mbus_framefmt *format,
+				   struct v4l2_ctrl *src, bool *setting_ctrl,
+				   int exposure_margin)
+{
+	struct v4l2_ctrl *dest;
+	s32 val;
+	int ret;
+
+	/* Was setting the control user-initiated or were we called again? */
+	if (*setting_ctrl) {
+		*setting_ctrl = false;
+		return 0;
+	}
+
+	/* Are we being called for writing a value to a register? */
+	if (src->val == src->cur.val)
+		return 0;
+
+	switch (src->id) {
+	case V4L2_CID_FRAME_LENGTH_LINES:
+		dest = vblank;
+		val = src->val - format->height;
+		break;
+	case V4L2_CID_VBLANK:
+		dest = fll;
+		val = src->val + format->height;
+		break;
+	case V4L2_CID_LINE_LENGTH_PIXELS:
+		dest = hblank;
+		val = src->val - format->width;
+		break;
+	case V4L2_CID_HBLANK:
+		dest = llp;
+		val = src->val + format->width;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	if (val == dest->val)
+		return 0;
+
+	*setting_ctrl = true;
+
+	ret = __v4l2_ctrl_s_ctrl(dest, val);
+	if (ret)
+		return ret;
+
+	/*
+	 * Only modify exposure range when setting fll, directly or via vblank.
+	 */
+	if (src->id != V4L2_CID_FRAME_LENGTH_LINES &&
+	    dest->id != V4L2_CID_FRAME_LENGTH_LINES)
+		return 0;
+
+	int exposure_max = fll->val - exposure_margin;
+
+	return __v4l2_ctrl_modify_range(exposure, exposure->minimum,
+					exposure_max, exposure->step,
+					exposure_max);
+}
+EXPORT_SYMBOL_GPL(v4l2_subdev_sensor_fll_llp_set);
+
 /* -----------------------------------------------------------------------------
  * Pipeline power management
  *
diff --git a/include/media/v4l2-mc.h b/include/media/v4l2-mc.h
index 1837c9fd78cf..8618a74e4e0c 100644
--- a/include/media/v4l2-mc.h
+++ b/include/media/v4l2-mc.h
@@ -18,6 +18,7 @@
 /* We don't need to include pci.h or usb.h here */
 struct pci_dev;
 struct usb_device;
+struct v4l2_ctrl;
 
 #ifdef CONFIG_MEDIA_CONTROLLER
 /**
@@ -139,6 +140,13 @@ int v4l2_create_fwnode_links_to_pad(struct v4l2_subdev *src_sd,
 int v4l2_create_fwnode_links(struct v4l2_subdev *src_sd,
 			     struct v4l2_subdev *sink_sd);
 
+int v4l2_subdev_sensor_fll_llp_set(struct v4l2_ctrl *fll, struct v4l2_ctrl *vblank,
+				   struct v4l2_ctrl *llp, struct v4l2_ctrl *hblank,
+				   struct v4l2_ctrl *exposure,
+				   const struct v4l2_mbus_framefmt *format,
+				   struct v4l2_ctrl *src, bool *setting_ctrl,
+				   int exposure_margin);
+
 /**
  * v4l2_pipeline_pm_get - Increase the use count of a pipeline
  * @entity: The root entity of a pipeline
-- 
2.47.3


^ permalink raw reply related	[flat|nested] 88+ messages in thread

* [PATCH v12 30/86] media: Documentation: Add binning and sub-sampling controls
  2026-04-09 20:13 [PATCH v12 00/86] Generic line based metadata support, internal pads Sakari Ailus
                   ` (28 preceding siblings ...)
  2026-04-09 20:14 ` [PATCH v12 29/86] media: v4l2-mc: Add v4l2_subdev_sensor_fll_llp_set() Sakari Ailus
@ 2026-04-09 20:14 ` Sakari Ailus
  2026-04-09 20:14 ` [PATCH v12 31/86] media: v4l2-subdev: Set STATIC route flag if IMMUTABLE route flag is set Sakari Ailus
                   ` (55 subsequent siblings)
  85 siblings, 0 replies; 88+ messages in thread
From: Sakari Ailus @ 2026-04-09 20:14 UTC (permalink / raw)
  To: linux-media
  Cc: hans, laurent.pinchart, Prabhakar, Kate Hsuan, Dave Stevenson,
	Tommaso Merciai, Benjamin Mugnier, Sylvain Petinot,
	Christophe JAILLET, Julien Massot, Naushir Patuck, Stefan Klug,
	Mirela Rabulea, André Apitzsch, Heimir Thor Sverrisson,
	Kieran Bingham, Mehdi Djait, Ricardo Ribalda Delgado,
	Hans de Goede, Jacopo Mondi, Tomi Valkeinen, David Plowman,
	Yu, Ong Hock, Ng, Khai Wen, Jai Luthra, Rishikesh Donadkar

Document the binning and scaling controls (V4L2_CID_BINNING and
V4L2_CID_SUBSAMPLING_{HORIZONTAL,VERTICAL}) in the common raw sensor
model.

Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
Reviewed-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
Reviewed-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
---
 .../media/v4l/subdev-config-model.rst         | 20 ++++++++++++++-----
 1 file changed, 15 insertions(+), 5 deletions(-)

diff --git a/Documentation/userspace-api/media/v4l/subdev-config-model.rst b/Documentation/userspace-api/media/v4l/subdev-config-model.rst
index 0fb01bf6c825..fb6d8a1bcac7 100644
--- a/Documentation/userspace-api/media/v4l/subdev-config-model.rst
+++ b/Documentation/userspace-api/media/v4l/subdev-config-model.rst
@@ -144,8 +144,12 @@ separately horizontally and vertically.
 
 The combined effect of binning and sub-sampling is configured using the
 ``V4L2_SEL_TGT_COMPOSE`` rectangle, relative to the analogue crop rectangle, on
-(pad, stream) pair 1/0. The driver implementation determines how to configure
-binning and sub-sampling to achieve the desired size.
+(pad, stream) pair 1/0. It depends on the driver which of these operations are
+being used to achieve the resulting size. Binning and sub-sampling are also
+directly configured using :ref:`V4L2_CID_BINNING_FACTORS
+<image_source_control_binning_factors>` and
+:ref:`V4L2_CID_SUBSAMPLING_HORIZONTAL and V4L2_CID_SUBSAMPLING_VERTICAL
+<image_source_control_subsampling>` controls on drivers that support them.
 
 The digital crop operation takes place after binning and sub-sampling. It is
 configured by setting the ``V4L2_SEL_TGT_CROP`` rectangle on (pad, stream) pair
@@ -216,9 +220,15 @@ Also refer to :ref:`Selection targets <v4l2-selection-targets-table>`.
       - \-
       - X
       - Binning and sub-sampling. This rectangle is relative to the
-        ``V4L2_SEL_TGT_CROP`` rectangle on the same (pad, stream). The
-        combination of binning and sub-sampling is configured using this
-        selection target.
+        ``V4L2_SEL_TGT_CROP`` rectangle on the same (pad, stream). Binning is
+        configured using the :ref:`V4L2_CID_BINNING_FACTORS
+        <image_source_control_binning_factors>` control and sub-sampling is configured
+        using the :ref:`V4L2_CID_SUBSAMPLING_HORIZONTAL and
+        V4L2_CID_SUBSAMPLING_VERTICAL <image_source_control_subsampling>`
+        controls on drivers that support these controls. To configure binning
+        and sub-sampling on drivers that do not support these controls, the
+        selection rectangle may be changed directly to configure the combined
+        effect on the image size.
     * - 2/0
       - Format
       - X
-- 
2.47.3


^ permalink raw reply related	[flat|nested] 88+ messages in thread

* [PATCH v12 31/86] media: v4l2-subdev: Set STATIC route flag if IMMUTABLE route flag is set
  2026-04-09 20:13 [PATCH v12 00/86] Generic line based metadata support, internal pads Sakari Ailus
                   ` (29 preceding siblings ...)
  2026-04-09 20:14 ` [PATCH v12 30/86] media: Documentation: Add binning and sub-sampling controls Sakari Ailus
@ 2026-04-09 20:14 ` Sakari Ailus
  2026-04-09 20:14 ` [PATCH v12 32/86] media: uapi: v4l: subdev: Enable streams API Sakari Ailus
                   ` (54 subsequent siblings)
  85 siblings, 0 replies; 88+ messages in thread
From: Sakari Ailus @ 2026-04-09 20:14 UTC (permalink / raw)
  To: linux-media
  Cc: hans, laurent.pinchart, Prabhakar, Kate Hsuan, Dave Stevenson,
	Tommaso Merciai, Benjamin Mugnier, Sylvain Petinot,
	Christophe JAILLET, Julien Massot, Naushir Patuck, Stefan Klug,
	Mirela Rabulea, André Apitzsch, Heimir Thor Sverrisson,
	Kieran Bingham, Mehdi Djait, Ricardo Ribalda Delgado,
	Hans de Goede, Jacopo Mondi, Tomi Valkeinen, David Plowman,
	Yu, Ong Hock, Ng, Khai Wen, Jai Luthra, Rishikesh Donadkar

As the IMMUTABLE sub-device route flag implies the STATIC flag, do set the
STATIC flag for all IMMUTABLE routes returned to the user space.

Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
---
 drivers/media/v4l2-core/v4l2-subdev.c | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/drivers/media/v4l2-core/v4l2-subdev.c b/drivers/media/v4l2-core/v4l2-subdev.c
index 4b7830f705a2..3f671282ee91 100644
--- a/drivers/media/v4l2-core/v4l2-subdev.c
+++ b/drivers/media/v4l2-core/v4l2-subdev.c
@@ -698,8 +698,11 @@ static void copy_routes_state_to_routing(struct v4l2_subdev_routing *routing,
 		(struct v4l2_subdev_route *)(uintptr_t)routing->routes;
 	u32 copy_routes = min(routing->len_routes, state->routing.num_routes);
 
-	for (u32 i = 0; i < copy_routes; i++)
+	for (u32 i = 0; i < copy_routes; i++) {
 		routes[i] = state->routing.routes[i];
+		if (routes[i].flags & V4L2_SUBDEV_ROUTE_FL_IMMUTABLE)
+			routes[i].flags |= V4L2_SUBDEV_ROUTE_FL_STATIC;
+	}
 
 	routing->num_routes = state->routing.num_routes;
 }
-- 
2.47.3


^ permalink raw reply related	[flat|nested] 88+ messages in thread

* [PATCH v12 32/86] media: uapi: v4l: subdev: Enable streams API
  2026-04-09 20:13 [PATCH v12 00/86] Generic line based metadata support, internal pads Sakari Ailus
                   ` (30 preceding siblings ...)
  2026-04-09 20:14 ` [PATCH v12 31/86] media: v4l2-subdev: Set STATIC route flag if IMMUTABLE route flag is set Sakari Ailus
@ 2026-04-09 20:14 ` Sakari Ailus
  2026-04-09 20:14 ` [PATCH v12 33/86] media: uapi: Add new controls for camera sensor FLL and LLP Sakari Ailus
                   ` (53 subsequent siblings)
  85 siblings, 0 replies; 88+ messages in thread
From: Sakari Ailus @ 2026-04-09 20:14 UTC (permalink / raw)
  To: linux-media
  Cc: hans, laurent.pinchart, Prabhakar, Kate Hsuan, Dave Stevenson,
	Tommaso Merciai, Benjamin Mugnier, Sylvain Petinot,
	Christophe JAILLET, Julien Massot, Naushir Patuck, Stefan Klug,
	Mirela Rabulea, André Apitzsch, Heimir Thor Sverrisson,
	Kieran Bingham, Mehdi Djait, Ricardo Ribalda Delgado,
	Hans de Goede, Jacopo Mondi, Tomi Valkeinen, David Plowman,
	Yu, Ong Hock, Ng, Khai Wen, Jai Luthra, Rishikesh Donadkar

Remove v4l2_subdev_enable_streams_api variable that was used to easily
enable streams API for development, and conditions that use the variable.

This patch enables the streams API for V4L2 sub-device interface which
allows transporting multiple streams on a single MC link.

Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
Reviewed-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
Reviewed-by: Mirela Rabulea <mirela.rabulea@nxp.com>
---
 drivers/media/v4l2-core/v4l2-subdev.c | 30 ---------------------------
 1 file changed, 30 deletions(-)

diff --git a/drivers/media/v4l2-core/v4l2-subdev.c b/drivers/media/v4l2-core/v4l2-subdev.c
index 3f671282ee91..af9024b0f788 100644
--- a/drivers/media/v4l2-core/v4l2-subdev.c
+++ b/drivers/media/v4l2-core/v4l2-subdev.c
@@ -51,15 +51,6 @@ struct v4l2_subdev_stream_config {
 	struct v4l2_fract interval;
 };
 
-#if defined(CONFIG_VIDEO_V4L2_SUBDEV_API)
-/*
- * The Streams API is an experimental feature. To use the Streams API, set
- * 'v4l2_subdev_enable_streams_api' to 1 below.
- */
-
-static bool v4l2_subdev_enable_streams_api;
-#endif
-
 /*
  * Maximum stream ID is 63 for now, as we use u64 bitmask to represent a set
  * of streams.
@@ -720,13 +711,6 @@ static long subdev_do_ioctl(struct file *file, unsigned int cmd, void *arg,
 				       V4L2_SUBDEV_CLIENT_CAP_STREAMS;
 	int rval;
 
-	/*
-	 * If the streams API is not enabled, remove V4L2_SUBDEV_CAP_STREAMS.
-	 * Remove this when the API is no longer experimental.
-	 */
-	if (!v4l2_subdev_enable_streams_api)
-		streams_subdev = false;
-
 	switch (cmd) {
 	case VIDIOC_SUBDEV_QUERYCAP: {
 		struct v4l2_subdev_capability *cap = arg;
@@ -1081,9 +1065,6 @@ static long subdev_do_ioctl(struct file *file, unsigned int cmd, void *arg,
 	case VIDIOC_SUBDEV_G_ROUTING: {
 		struct v4l2_subdev_routing *routing = arg;
 
-		if (!v4l2_subdev_enable_streams_api)
-			return -ENOIOCTLCMD;
-
 		if (!(sd->flags & V4L2_SUBDEV_FL_STREAMS))
 			return -ENOIOCTLCMD;
 
@@ -1105,9 +1086,6 @@ static long subdev_do_ioctl(struct file *file, unsigned int cmd, void *arg,
 		unsigned int num_active_routes = 0;
 		unsigned int i;
 
-		if (!v4l2_subdev_enable_streams_api)
-			return -ENOIOCTLCMD;
-
 		if (!(sd->flags & V4L2_SUBDEV_FL_STREAMS))
 			return -ENOIOCTLCMD;
 
@@ -1193,14 +1171,6 @@ static long subdev_do_ioctl(struct file *file, unsigned int cmd, void *arg,
 	case VIDIOC_SUBDEV_S_CLIENT_CAP: {
 		struct v4l2_subdev_client_capability *client_cap = arg;
 
-		/*
-		 * Clear V4L2_SUBDEV_CLIENT_CAP_STREAMS if streams API is not
-		 * enabled. Remove this when streams API is no longer
-		 * experimental.
-		 */
-		if (!v4l2_subdev_enable_streams_api)
-			client_cap->capabilities &= ~V4L2_SUBDEV_CLIENT_CAP_STREAMS;
-
 		/* Filter out unsupported capabilities */
 		client_cap->capabilities &= (V4L2_SUBDEV_CLIENT_CAP_STREAMS |
 					     V4L2_SUBDEV_CLIENT_CAP_INTERVAL_USES_WHICH |
-- 
2.47.3


^ permalink raw reply related	[flat|nested] 88+ messages in thread

* [PATCH v12 33/86] media: uapi: Add new controls for camera sensor FLL and LLP
  2026-04-09 20:13 [PATCH v12 00/86] Generic line based metadata support, internal pads Sakari Ailus
                   ` (31 preceding siblings ...)
  2026-04-09 20:14 ` [PATCH v12 32/86] media: uapi: v4l: subdev: Enable streams API Sakari Ailus
@ 2026-04-09 20:14 ` Sakari Ailus
  2026-04-09 20:14 ` [PATCH v12 34/86] media: uapi: Add binning factor helper macros Sakari Ailus
                   ` (52 subsequent siblings)
  85 siblings, 0 replies; 88+ messages in thread
From: Sakari Ailus @ 2026-04-09 20:14 UTC (permalink / raw)
  To: linux-media
  Cc: hans, laurent.pinchart, Prabhakar, Kate Hsuan, Dave Stevenson,
	Tommaso Merciai, Benjamin Mugnier, Sylvain Petinot,
	Christophe JAILLET, Julien Massot, Naushir Patuck, Stefan Klug,
	Mirela Rabulea, André Apitzsch, Heimir Thor Sverrisson,
	Kieran Bingham, Mehdi Djait, Ricardo Ribalda Delgado,
	Hans de Goede, Jacopo Mondi, Tomi Valkeinen, David Plowman,
	Yu, Ong Hock, Ng, Khai Wen, Jai Luthra, Rishikesh Donadkar

Add new controls for camera sensors, V4L2_CID_LINE_LENGTH_PIXELS and
V4L2_CID_FRAME_LENGTH_LINES, to convey the combined size of the analogue
crop rectangle and horizontal and vertical blanking.

The reason for adding the new controls is that they're much easier to use
as the user doesn't have to be concerned of the analogue crop in the same
context. Secondarily, the newly added common raw sensor model uses
different values for the same.

Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
---
 .../userspace-api/media/v4l/ext-ctrls-image-source.rst | 10 ++++++++++
 drivers/media/v4l2-core/v4l2-ctrls-defs.c              |  2 ++
 include/uapi/linux/v4l2-controls.h                     |  3 +++
 3 files changed, 15 insertions(+)

diff --git a/Documentation/userspace-api/media/v4l/ext-ctrls-image-source.rst b/Documentation/userspace-api/media/v4l/ext-ctrls-image-source.rst
index 63e53c883db6..fb4dee1b4f94 100644
--- a/Documentation/userspace-api/media/v4l/ext-ctrls-image-source.rst
+++ b/Documentation/userspace-api/media/v4l/ext-ctrls-image-source.rst
@@ -201,3 +201,13 @@ For instance, a value of ``0x0001000300020003`` indicates binning by 3
     Sub-sampling is used to downscale an image, horizontally and vertically, by
     discarding a part of the image data. Typically sub-sampling produces lower
     quality images than binning.
+
+.. _image_source_control_frame_length:
+
+``V4L2_CID_FRAME_LENGTH_LINES (integer)``
+    Frame length in lines. The value of the control is the number of lines
+    captured in the sensor's pixel array added to the vertical blanking.
+
+``V4L2_CID_LINE_LENGTH_PIXELS (integer)``
+    Line length in pixels. The value of the control is the number of pixels per
+    line captured in the sensor's pixel array added to the horizontal blanking.
diff --git a/drivers/media/v4l2-core/v4l2-ctrls-defs.c b/drivers/media/v4l2-core/v4l2-ctrls-defs.c
index 227bcb5a549d..bd23c5640722 100644
--- a/drivers/media/v4l2-core/v4l2-ctrls-defs.c
+++ b/drivers/media/v4l2-core/v4l2-ctrls-defs.c
@@ -1163,6 +1163,8 @@ const char *v4l2_ctrl_get_name(u32 id)
 	case V4L2_CID_BINNING_FACTORS:		return "Binning Factors";
 	case V4L2_CID_SUBSAMPLING_HORIZONTAL:	return "Sub-Sampling Factor, Horizontal";
 	case V4L2_CID_SUBSAMPLING_VERTICAL:	return "Sub-Sampling Factor, Vertical";
+	case V4L2_CID_FRAME_LENGTH_LINES:	return "Frame Length in Lines";
+	case V4L2_CID_LINE_LENGTH_PIXELS:	return "Line Length in Pixels";
 
 	/* Image processing controls */
 	/* Keep the order of the 'case's the same as in v4l2-controls.h! */
diff --git a/include/uapi/linux/v4l2-controls.h b/include/uapi/linux/v4l2-controls.h
index acb6f9ad4d1b..60f0fb599926 100644
--- a/include/uapi/linux/v4l2-controls.h
+++ b/include/uapi/linux/v4l2-controls.h
@@ -1253,6 +1253,9 @@ enum v4l2_jpeg_chroma_subsampling {
 #define V4L2_CID_SUBSAMPLING_HORIZONTAL		(V4L2_CID_IMAGE_SOURCE_CLASS_BASE + 14)
 #define V4L2_CID_SUBSAMPLING_VERTICAL		(V4L2_CID_IMAGE_SOURCE_CLASS_BASE + 15)
 
+#define V4L2_CID_FRAME_LENGTH_LINES		(V4L2_CID_IMAGE_SOURCE_CLASS_BASE + 16)
+#define V4L2_CID_LINE_LENGTH_PIXELS		(V4L2_CID_IMAGE_SOURCE_CLASS_BASE + 17)
+
 /* Image processing controls */
 
 #define V4L2_CID_IMAGE_PROC_CLASS_BASE		(V4L2_CTRL_CLASS_IMAGE_PROC | 0x900)
-- 
2.47.3


^ permalink raw reply related	[flat|nested] 88+ messages in thread

* [PATCH v12 34/86] media: uapi: Add binning factor helper macros
  2026-04-09 20:13 [PATCH v12 00/86] Generic line based metadata support, internal pads Sakari Ailus
                   ` (32 preceding siblings ...)
  2026-04-09 20:14 ` [PATCH v12 33/86] media: uapi: Add new controls for camera sensor FLL and LLP Sakari Ailus
@ 2026-04-09 20:14 ` Sakari Ailus
  2026-04-09 20:14 ` [PATCH v12 35/86] media: Documentation: Document frame controls for common raw sensor model Sakari Ailus
                   ` (51 subsequent siblings)
  85 siblings, 0 replies; 88+ messages in thread
From: Sakari Ailus @ 2026-04-09 20:14 UTC (permalink / raw)
  To: linux-media
  Cc: hans, laurent.pinchart, Prabhakar, Kate Hsuan, Dave Stevenson,
	Tommaso Merciai, Benjamin Mugnier, Sylvain Petinot,
	Christophe JAILLET, Julien Massot, Naushir Patuck, Stefan Klug,
	Mirela Rabulea, André Apitzsch, Heimir Thor Sverrisson,
	Kieran Bingham, Mehdi Djait, Ricardo Ribalda Delgado,
	Hans de Goede, Jacopo Mondi, Tomi Valkeinen, David Plowman,
	Yu, Ong Hock, Ng, Khai Wen, Jai Luthra, Rishikesh Donadkar

Add helper macros for handling binning factor integer control menu items.

Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
---
 include/uapi/linux/v4l2-controls.h | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/include/uapi/linux/v4l2-controls.h b/include/uapi/linux/v4l2-controls.h
index 60f0fb599926..aaa0d88d7e6e 100644
--- a/include/uapi/linux/v4l2-controls.h
+++ b/include/uapi/linux/v4l2-controls.h
@@ -1250,6 +1250,13 @@ enum v4l2_jpeg_chroma_subsampling {
 #define V4L2_CID_METADATA_LAYOUT		(V4L2_CID_IMAGE_SOURCE_CLASS_BASE + 12)
 
 #define V4L2_CID_BINNING_FACTORS		(V4L2_CID_IMAGE_SOURCE_CLASS_BASE + 13)
+#define V4L2_BINNING_FACTORS_MAKE(hnum, hdem, vnum, vdem)		\
+	(((uint64_t)(0xffff & hnum) << 48) | ((uint64_t)(0xffff & hdem) << 32) | \
+	 ((uint64_t)(0xffff & vnum) << 16) | (uint64_t)(0xffff & vdem))
+#define V4L2_BINNING_FACTORS_HNUM(binning)	((binning >> 48) & 0xffff)
+#define V4L2_BINNING_FACTORS_HDEM(binning)	((binning >> 32) & 0xffff)
+#define V4L2_BINNING_FACTORS_VNUM(binning)	((binning >> 16) & 0xffff)
+#define V4L2_BINNING_FACTORS_VDEM(binning)	(binning & 0xffff)
 #define V4L2_CID_SUBSAMPLING_HORIZONTAL		(V4L2_CID_IMAGE_SOURCE_CLASS_BASE + 14)
 #define V4L2_CID_SUBSAMPLING_VERTICAL		(V4L2_CID_IMAGE_SOURCE_CLASS_BASE + 15)
 
-- 
2.47.3


^ permalink raw reply related	[flat|nested] 88+ messages in thread

* [PATCH v12 35/86] media: Documentation: Document frame controls for common raw sensor model
  2026-04-09 20:13 [PATCH v12 00/86] Generic line based metadata support, internal pads Sakari Ailus
                   ` (33 preceding siblings ...)
  2026-04-09 20:14 ` [PATCH v12 34/86] media: uapi: Add binning factor helper macros Sakari Ailus
@ 2026-04-09 20:14 ` Sakari Ailus
  2026-04-09 20:14 ` [PATCH v12 36/86] media: v4l2-ctrl: Improve v4l2_ctrl_g_ctrl{,int64} documentation Sakari Ailus
                   ` (50 subsequent siblings)
  85 siblings, 0 replies; 88+ messages in thread
From: Sakari Ailus @ 2026-04-09 20:14 UTC (permalink / raw)
  To: linux-media
  Cc: hans, laurent.pinchart, Prabhakar, Kate Hsuan, Dave Stevenson,
	Tommaso Merciai, Benjamin Mugnier, Sylvain Petinot,
	Christophe JAILLET, Julien Massot, Naushir Patuck, Stefan Klug,
	Mirela Rabulea, André Apitzsch, Heimir Thor Sverrisson,
	Kieran Bingham, Mehdi Djait, Ricardo Ribalda Delgado,
	Hans de Goede, Jacopo Mondi, Tomi Valkeinen, David Plowman,
	Yu, Ong Hock, Ng, Khai Wen, Jai Luthra, Rishikesh Donadkar

Document that V4L2_CID_LINE_LENGTH_PIXELS V4L2_CID_FRAME_LENGTH_LINES are
used to configure frame rate in common raw camera sensor model. Also
mention the controls in camera sensor documentation.

Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
---
 .../userspace-api/media/drivers/camera-sensor.rst         | 8 ++++++++
 .../userspace-api/media/v4l/subdev-config-model.rst       | 8 ++++++++
 2 files changed, 16 insertions(+)

diff --git a/Documentation/userspace-api/media/drivers/camera-sensor.rst b/Documentation/userspace-api/media/drivers/camera-sensor.rst
index aa05681c7090..6d9dadab3277 100644
--- a/Documentation/userspace-api/media/drivers/camera-sensor.rst
+++ b/Documentation/userspace-api/media/drivers/camera-sensor.rst
@@ -61,6 +61,8 @@ There are two different methods for obtaining possibilities for different frame
 intervals as well as configuring the frame interval. Which one to implement
 depends on the type of the device.
 
+.. _media_camera_sensor_frame_rate_raw:
+
 Raw camera sensors
 ~~~~~~~~~~~~~~~~~~
 
@@ -78,6 +80,12 @@ The formula is bus independent and is applicable for raw timing parameters on
 large variety of devices beyond camera sensors. Devices that have no analogue
 crop, use the full source image size, i.e. pixel array size.
 
+The combined *analogue crop width + horizontal blanking* and *analogue crop
+height + vertical blanking* can be controlled directly using the
+:ref:`V4L2_CID_LINE_LENGTH_PIXELS and V4L2_CID_FRAME_LENGTH_LINES
+<image_source_control_frame_length>` controls, respectively, should the driver
+support them.
+
 Horizontal and vertical blanking are specified by ``V4L2_CID_HBLANK`` and
 ``V4L2_CID_VBLANK``, respectively. The unit of the ``V4L2_CID_HBLANK`` control
 is pixels and the unit of the ``V4L2_CID_VBLANK`` is lines. The pixel rate in
diff --git a/Documentation/userspace-api/media/v4l/subdev-config-model.rst b/Documentation/userspace-api/media/v4l/subdev-config-model.rst
index fb6d8a1bcac7..1923ccbafdd0 100644
--- a/Documentation/userspace-api/media/v4l/subdev-config-model.rst
+++ b/Documentation/userspace-api/media/v4l/subdev-config-model.rst
@@ -262,6 +262,14 @@ Also refer to :ref:`Selection targets <v4l2-selection-targets-table>`.
       - \-
       - Embedded data source format.
 
+Frame rate
+^^^^^^^^^^
+
+Drivers supporting the Common raw camera sensor model support
+:ref:`V4L2_CID_LINE_LENGTH_PIXELS and V4L2_CID_FRAME_LENGTH_LINES
+<image_source_control_frame_length>` controls for :ref:`frame rate configuration
+<media_camera_sensor_frame_rate_raw>`.
+
 Embedded data
 ^^^^^^^^^^^^^
 
-- 
2.47.3


^ permalink raw reply related	[flat|nested] 88+ messages in thread

* [PATCH v12 36/86] media: v4l2-ctrl: Improve v4l2_ctrl_g_ctrl{,int64} documentation
  2026-04-09 20:13 [PATCH v12 00/86] Generic line based metadata support, internal pads Sakari Ailus
                   ` (34 preceding siblings ...)
  2026-04-09 20:14 ` [PATCH v12 35/86] media: Documentation: Document frame controls for common raw sensor model Sakari Ailus
@ 2026-04-09 20:14 ` Sakari Ailus
  2026-04-09 20:14 ` [PATCH v12 37/86] media: Documentation: Add sub-device internal pads example Sakari Ailus
                   ` (49 subsequent siblings)
  85 siblings, 0 replies; 88+ messages in thread
From: Sakari Ailus @ 2026-04-09 20:14 UTC (permalink / raw)
  To: linux-media
  Cc: hans, laurent.pinchart, Prabhakar, Kate Hsuan, Dave Stevenson,
	Tommaso Merciai, Benjamin Mugnier, Sylvain Petinot,
	Christophe JAILLET, Julien Massot, Naushir Patuck, Stefan Klug,
	Mirela Rabulea, André Apitzsch, Heimir Thor Sverrisson,
	Kieran Bingham, Mehdi Djait, Ricardo Ribalda Delgado,
	Hans de Goede, Jacopo Mondi, Tomi Valkeinen, David Plowman,
	Yu, Ong Hock, Ng, Khai Wen, Jai Luthra, Rishikesh Donadkar

Improve documentation of v4l2_ctrl_g_ctrl() and v4l2_ctrl_g_ctrl_int64()
by documenting what the function returns on error (i.e. 0).

Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
---
 include/media/v4l2-ctrls.h | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/include/media/v4l2-ctrls.h b/include/media/v4l2-ctrls.h
index 327976b14d50..183683b6add8 100644
--- a/include/media/v4l2-ctrls.h
+++ b/include/media/v4l2-ctrls.h
@@ -1105,6 +1105,8 @@ const s64 *v4l2_ctrl_get_int_menu(u32 id, u32 *len);
  * used from within the &v4l2_ctrl_ops functions.
  *
  * This function is for integer type controls only.
+ *
+ * Returns: the value of the control or 0 on error.
  */
 s32 v4l2_ctrl_g_ctrl(struct v4l2_ctrl *ctrl);
 
@@ -1156,6 +1158,8 @@ static inline int v4l2_ctrl_s_ctrl(struct v4l2_ctrl *ctrl, s32 val)
  * used from within the &v4l2_ctrl_ops functions.
  *
  * This function is for 64-bit integer type controls only.
+ *
+ * Returns: the value of the control or 0 on error.
  */
 s64 v4l2_ctrl_g_ctrl_int64(struct v4l2_ctrl *ctrl);
 
-- 
2.47.3


^ permalink raw reply related	[flat|nested] 88+ messages in thread

* [PATCH v12 37/86] media: Documentation: Add sub-device internal pads example
  2026-04-09 20:13 [PATCH v12 00/86] Generic line based metadata support, internal pads Sakari Ailus
                   ` (35 preceding siblings ...)
  2026-04-09 20:14 ` [PATCH v12 36/86] media: v4l2-ctrl: Improve v4l2_ctrl_g_ctrl{,int64} documentation Sakari Ailus
@ 2026-04-09 20:14 ` Sakari Ailus
  2026-04-09 20:14 ` [PATCH v12 38/86] media: Documentation: Document streaming behaviour for common raw cameras Sakari Ailus
                   ` (48 subsequent siblings)
  85 siblings, 0 replies; 88+ messages in thread
From: Sakari Ailus @ 2026-04-09 20:14 UTC (permalink / raw)
  To: linux-media
  Cc: hans, laurent.pinchart, Prabhakar, Kate Hsuan, Dave Stevenson,
	Tommaso Merciai, Benjamin Mugnier, Sylvain Petinot,
	Christophe JAILLET, Julien Massot, Naushir Patuck, Stefan Klug,
	Mirela Rabulea, André Apitzsch, Heimir Thor Sverrisson,
	Kieran Bingham, Mehdi Djait, Ricardo Ribalda Delgado,
	Hans de Goede, Jacopo Mondi, Tomi Valkeinen, David Plowman,
	Yu, Ong Hock, Ng, Khai Wen, Jai Luthra, Rishikesh Donadkar

Add an example using sub-device internal pads, with the Sony IMX219 camera
sensor.

Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 .../userspace-api/media/v4l/dev-subdev.rst    | 129 ++++++++++++++++++
 1 file changed, 129 insertions(+)

diff --git a/Documentation/userspace-api/media/v4l/dev-subdev.rst b/Documentation/userspace-api/media/v4l/dev-subdev.rst
index 2fc81e0205dc..a9d462b57b54 100644
--- a/Documentation/userspace-api/media/v4l/dev-subdev.rst
+++ b/Documentation/userspace-api/media/v4l/dev-subdev.rst
@@ -729,4 +729,133 @@ To configure this pipeline, the userspace must take the following steps:
    controls are present on the source sub-device to obtain the pixel array CFA
    pattern and metadata layout.
 
+Internal pads setup example
+---------------------------
+
+A simple example of a multiplexed stream setup might be as follows:
+
+- An IMX219 camera sensor source sub-device, with one source pad (0), one
+  internal sink pad (1) as the source of the image data and an internal sink
+  pad (2) as the source of the embedded data. There are two routes, one from the
+  internal sink pad 1 to the source pad 0 (image data) and another from the
+  internal sink pad 2 to the source pad 0 (embedded data). Both streams are
+  always active, i.e. there is no need to separately enable the embedded data
+  stream. The sensor uses the CSI-2 interface.
+
+- A CSI-2 receiver in the SoC. The receiver has a single sink pad (pad 0),
+  connected to the sensor's source pad (0), and two source pads (pads 1 and 2),
+  to two DMA engines. The receiver demultiplexes the incoming streams to the
+  source pads.
+
+- Two DMA engines in the SoC, one for each stream. Each DMA engine is connected
+  to a different source pad of the receiver.
+
+The sensor and the receiver are modelled as V4L2 sub-devices, exposed to
+userspace via /dev/v4l-subdevX device nodes. The DMA engines are modelled as
+V4L2 video devices, exposed to userspace via /dev/videoX nodes.
+
+To configure this pipeline, the userspace must take the following steps:
+
+1) Set up media links between entities: enable the links from the sensor to the
+   receiver and from the receiver to the DMA engines. This step does not differ
+   from normal non-multiplexed media controller setup.
+
+2) Configure routing
+
+.. flat-table:: Camera sensor. There are no configurable routes.
+    :header-rows: 1
+
+    * - Sink Pad/Stream
+      - Source Pad/Stream
+      - Routing Flags
+      - Comments
+    * - 1/0
+      - 0/0
+      - V4L2_SUBDEV_ROUTE_FL_ACTIVE | V4L2_SUBDEV_ROUTE_FL_IMMUTABLE |
+        V4L2_SUBDEV_ROUTE_FL_STATIC
+      - Pixel data stream from the internal image sink pad
+    * - 2/0
+      - 0/1
+      - V4L2_SUBDEV_ROUTE_FL_ACTIVE | V4L2_SUBDEV_ROUTE_FL_IMMUTABLE |
+        V4L2_SUBDEV_ROUTE_FL_STATIC
+      - Metadata stream from the internal embedded data sink pad
+
+While both routes are immutable for the IMX219, other camera sensors may offer
+more flexible configuration options. Routing configuration is dictated by the
+hardware capabilities: camera sensors typically always produce an image data
+stream, but some of them support enabling and disabling the embedded data
+stream.
+
+.. flat-table:: Receiver routing table. Typically both routes need to be
+		explicitly created.
+    :header-rows:  1
+
+    * - Sink Pad/Stream
+      - Source Pad/Stream
+      - Routing Flags
+      - Comments
+    * - 0/0
+      - 1/0
+      - V4L2_SUBDEV_ROUTE_FL_ACTIVE
+      - Pixel data stream from camera sensor
+    * - 0/1
+      - 2/0
+      - V4L2_SUBDEV_ROUTE_FL_ACTIVE
+      - Metadata stream from camera sensor
+
+3) Configure formats
+
+   This example assumes that the formats are propagated from sink pad to the
+   source pad as-is. The tables contain fields of both struct v4l2_subdev_format
+   and struct v4l2_mbus_framefmt.
+
+.. flat-table:: Formats set on the sub-devices. Bold values are set, others are
+                static or propagated. The order is aligned with configured
+                routes.
+    :header-rows: 1
+    :fill-cells:
+
+    * - Sub-device
+      - Pad/Stream
+      - Width
+      - Height
+      - Code
+    * - :rspan:`3` IMX219
+      - 1/0
+      - 3296
+      - 2480
+      - MEDIA_BUS_FMT_RAW_10
+    * - 0/0
+      - 3296
+      - 2480
+      - **MEDIA_BUS_FMT_RAW_10**
+    * - 2/0
+      - 3296
+      - 2
+      - MEDIA_BUS_FMT_META_10
+    * - 0/1
+      - 3296
+      - 2
+      - MEDIA_BUS_FMT_META_10
+    * - :rspan:`3` CSI-2 receiver
+      - 0/0
+      - **3296**
+      - **2480**
+      - **MEDIA_BUS_FMT_RAW_10**
+    * - 1/0
+      - 3296
+      - 2480
+      - MEDIA_BUS_FMT_RAW_10
+    * - 0/1
+      - **3296**
+      - **2**
+      - **MEDIA_BUS_FMT_META_10**
+    * - 2/0
+      - 3296
+      - 2
+      - MEDIA_BUS_FMT_META_10
+
+The embedded data format does not need to be configured on the sensor's pads as
+the format is dictated by the pixel data format in this case.
+
 .. include:: subdev-config-model.rst
-- 
2.47.3


^ permalink raw reply related	[flat|nested] 88+ messages in thread

* [PATCH v12 38/86] media: Documentation: Document streaming behaviour for common raw cameras
  2026-04-09 20:13 [PATCH v12 00/86] Generic line based metadata support, internal pads Sakari Ailus
                   ` (36 preceding siblings ...)
  2026-04-09 20:14 ` [PATCH v12 37/86] media: Documentation: Add sub-device internal pads example Sakari Ailus
@ 2026-04-09 20:14 ` Sakari Ailus
  2026-04-09 20:14 ` [PATCH v12 39/86] media: Documentation: Add a note on Bayer raw mbus codes Sakari Ailus
                   ` (47 subsequent siblings)
  85 siblings, 0 replies; 88+ messages in thread
From: Sakari Ailus @ 2026-04-09 20:14 UTC (permalink / raw)
  To: linux-media
  Cc: hans, laurent.pinchart, Prabhakar, Kate Hsuan, Dave Stevenson,
	Tommaso Merciai, Benjamin Mugnier, Sylvain Petinot,
	Christophe JAILLET, Julien Massot, Naushir Patuck, Stefan Klug,
	Mirela Rabulea, André Apitzsch, Heimir Thor Sverrisson,
	Kieran Bingham, Mehdi Djait, Ricardo Ribalda Delgado,
	Hans de Goede, Jacopo Mondi, Tomi Valkeinen, David Plowman,
	Yu, Ong Hock, Ng, Khai Wen, Jai Luthra, Rishikesh Donadkar

Document that streaming control is based on stream number 0 and additional
streams need to be started before that.

Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
---
 .../userspace-api/media/v4l/subdev-config-model.rst    | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/Documentation/userspace-api/media/v4l/subdev-config-model.rst b/Documentation/userspace-api/media/v4l/subdev-config-model.rst
index 1923ccbafdd0..3d0f14dfdded 100644
--- a/Documentation/userspace-api/media/v4l/subdev-config-model.rst
+++ b/Documentation/userspace-api/media/v4l/subdev-config-model.rst
@@ -99,6 +99,16 @@ following routes.
 Support for the embedded data stream is optional. Drivers supporting the
 embedded data stream may allow disabling and enabling the route.
 
+Starting and stopping streaming
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Starting and stopping streaming is controlled through the stream number 0; if
+there's a desire to capture additional streams, such streams need to be started
+before stream 0. All streams start and stop at the same moment.
+
+This is subject to change in the future through additional API elements while
+the default behaviour will be maintained.
+
 Sensor pixel array size, cropping and binning
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-- 
2.47.3


^ permalink raw reply related	[flat|nested] 88+ messages in thread

* [PATCH v12 39/86] media: Documentation: Add a note on Bayer raw mbus codes
  2026-04-09 20:13 [PATCH v12 00/86] Generic line based metadata support, internal pads Sakari Ailus
                   ` (37 preceding siblings ...)
  2026-04-09 20:14 ` [PATCH v12 38/86] media: Documentation: Document streaming behaviour for common raw cameras Sakari Ailus
@ 2026-04-09 20:14 ` Sakari Ailus
  2026-04-09 20:14 ` [PATCH v12 40/86] media: v4l2-subdev: Add generic raw formats to v4l2_subdev_get_frame_desc Sakari Ailus
                   ` (46 subsequent siblings)
  85 siblings, 0 replies; 88+ messages in thread
From: Sakari Ailus @ 2026-04-09 20:14 UTC (permalink / raw)
  To: linux-media
  Cc: hans, laurent.pinchart, Prabhakar, Kate Hsuan, Dave Stevenson,
	Tommaso Merciai, Benjamin Mugnier, Sylvain Petinot,
	Christophe JAILLET, Julien Massot, Naushir Patuck, Stefan Klug,
	Mirela Rabulea, André Apitzsch, Heimir Thor Sverrisson,
	Kieran Bingham, Mehdi Djait, Ricardo Ribalda Delgado,
	Hans de Goede, Jacopo Mondi, Tomi Valkeinen, David Plowman,
	Yu, Ong Hock, Ng, Khai Wen, Jai Luthra, Rishikesh Donadkar

Now that we do have CFA-independent raw mbus codes, document that using
them is required in sensor drivers and preferred in other drivers, too.

Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
---
 Documentation/driver-api/media/camera-sensor.rst | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/Documentation/driver-api/media/camera-sensor.rst b/Documentation/driver-api/media/camera-sensor.rst
index 94bd1dae82d5..5fafd874d925 100644
--- a/Documentation/driver-api/media/camera-sensor.rst
+++ b/Documentation/driver-api/media/camera-sensor.rst
@@ -127,6 +127,17 @@ Use ``v4l2_fwnode_device_parse()`` to obtain rotation and orientation
 information from system firmware and ``v4l2_ctrl_new_fwnode_properties()`` to
 register the appropriate controls.
 
+Media bus codes
+---------------
+
+Supporting the new :ref:`CFA-independent Media bus codes
+<v4l2-mbus-pixelcode-generic-raw>` is required in new drivers on serial
+interfaces and the old Bayer pattern specific Media bus codes are thus
+deprecated. If the rest of the pipeline does not support the new generic raw
+Media bus codes, the preference is to add support for the codes in the entire
+pipeline instead of supporting old Bayer pattern specific mbus codes in a sensor
+driver.
+
 .. _media-camera-sensor-examples:
 
 Example drivers
-- 
2.47.3


^ permalink raw reply related	[flat|nested] 88+ messages in thread

* [PATCH v12 40/86] media: v4l2-subdev: Add generic raw formats to v4l2_subdev_get_frame_desc
  2026-04-09 20:13 [PATCH v12 00/86] Generic line based metadata support, internal pads Sakari Ailus
                   ` (38 preceding siblings ...)
  2026-04-09 20:14 ` [PATCH v12 39/86] media: Documentation: Add a note on Bayer raw mbus codes Sakari Ailus
@ 2026-04-09 20:14 ` Sakari Ailus
  2026-04-09 20:14 ` [PATCH v12 41/86] media: uapi: Add generic CSI-2 raw pixelformats for 16, 20, 24 and 28 bpp Sakari Ailus
                   ` (45 subsequent siblings)
  85 siblings, 0 replies; 88+ messages in thread
From: Sakari Ailus @ 2026-04-09 20:14 UTC (permalink / raw)
  To: linux-media
  Cc: hans, laurent.pinchart, Prabhakar, Kate Hsuan, Dave Stevenson,
	Tommaso Merciai, Benjamin Mugnier, Sylvain Petinot,
	Christophe JAILLET, Julien Massot, Naushir Patuck, Stefan Klug,
	Mirela Rabulea, André Apitzsch, Heimir Thor Sverrisson,
	Kieran Bingham, Mehdi Djait, Ricardo Ribalda Delgado,
	Hans de Goede, Jacopo Mondi, Tomi Valkeinen, David Plowman,
	Yu, Ong Hock, Ng, Khai Wen, Jai Luthra, Rishikesh Donadkar

Support generic raw formats in v4l2_subdev_get_frame_desc() at bit depths
8, 10, 12 and 14.

Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
---
 drivers/media/v4l2-core/v4l2-subdev.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/drivers/media/v4l2-core/v4l2-subdev.c b/drivers/media/v4l2-core/v4l2-subdev.c
index af9024b0f788..e7774402c44d 100644
--- a/drivers/media/v4l2-core/v4l2-subdev.c
+++ b/drivers/media/v4l2-core/v4l2-subdev.c
@@ -2804,6 +2804,7 @@ static int get_mipi_dt_for_mbus(u32 code)
 	switch (code) {
 	case MEDIA_BUS_FMT_BGR888_1X24:
 		return MIPI_CSI2_DT_RGB888;
+	case MEDIA_BUS_FMT_RAW_8:
 	case MEDIA_BUS_FMT_Y8_1X8:
 	case MEDIA_BUS_FMT_SBGGR8_1X8:
 	case MEDIA_BUS_FMT_SGBRG8_1X8:
@@ -2811,18 +2812,21 @@ static int get_mipi_dt_for_mbus(u32 code)
 	case MEDIA_BUS_FMT_SRGGB8_1X8:
 		return MIPI_CSI2_DT_RAW8;
 	case MEDIA_BUS_FMT_Y10_1X10:
+	case MEDIA_BUS_FMT_RAW_10:
 	case MEDIA_BUS_FMT_SBGGR10_1X10:
 	case MEDIA_BUS_FMT_SGBRG10_1X10:
 	case MEDIA_BUS_FMT_SGRBG10_1X10:
 	case MEDIA_BUS_FMT_SRGGB10_1X10:
 		return MIPI_CSI2_DT_RAW10;
 	case MEDIA_BUS_FMT_Y12_1X12:
+	case MEDIA_BUS_FMT_RAW_12:
 	case MEDIA_BUS_FMT_SBGGR12_1X12:
 	case MEDIA_BUS_FMT_SGBRG12_1X12:
 	case MEDIA_BUS_FMT_SGRBG12_1X12:
 	case MEDIA_BUS_FMT_SRGGB12_1X12:
 		return MIPI_CSI2_DT_RAW12;
 	case MEDIA_BUS_FMT_Y14_1X14:
+	case MEDIA_BUS_FMT_RAW_14:
 	case MEDIA_BUS_FMT_SBGGR14_1X14:
 	case MEDIA_BUS_FMT_SGBRG14_1X14:
 	case MEDIA_BUS_FMT_SGRBG14_1X14:
-- 
2.47.3


^ permalink raw reply related	[flat|nested] 88+ messages in thread

* [PATCH v12 41/86] media: uapi: Add generic CSI-2 raw pixelformats for 16, 20, 24 and 28 bpp
  2026-04-09 20:13 [PATCH v12 00/86] Generic line based metadata support, internal pads Sakari Ailus
                   ` (39 preceding siblings ...)
  2026-04-09 20:14 ` [PATCH v12 40/86] media: v4l2-subdev: Add generic raw formats to v4l2_subdev_get_frame_desc Sakari Ailus
@ 2026-04-09 20:14 ` Sakari Ailus
  2026-04-09 20:14 ` [PATCH v12 42/86] media: uapi: Add more media bus codes for generic raw formats Sakari Ailus
                   ` (44 subsequent siblings)
  85 siblings, 0 replies; 88+ messages in thread
From: Sakari Ailus @ 2026-04-09 20:14 UTC (permalink / raw)
  To: linux-media
  Cc: hans, laurent.pinchart, Prabhakar, Kate Hsuan, Dave Stevenson,
	Tommaso Merciai, Benjamin Mugnier, Sylvain Petinot,
	Christophe JAILLET, Julien Massot, Naushir Patuck, Stefan Klug,
	Mirela Rabulea, André Apitzsch, Heimir Thor Sverrisson,
	Kieran Bingham, Mehdi Djait, Ricardo Ribalda Delgado,
	Hans de Goede, Jacopo Mondi, Tomi Valkeinen, David Plowman,
	Yu, Ong Hock, Ng, Khai Wen, Jai Luthra, Rishikesh Donadkar

Add generic raw pixelformats for bit depths 16, 20, 24 and 28. These
formats are CSI-2 packed, apart from the 16-bit and 24-bit formats.

Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
Reviewed-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
---
 .../media/v4l/pixfmt-raw-generic.rst          | 212 +++++++++++++++++-
 drivers/media/v4l2-core/v4l2-ioctl.c          |   4 +
 include/uapi/linux/videodev2.h                |   4 +
 3 files changed, 217 insertions(+), 3 deletions(-)

diff --git a/Documentation/userspace-api/media/v4l/pixfmt-raw-generic.rst b/Documentation/userspace-api/media/v4l/pixfmt-raw-generic.rst
index 708aa17b80b0..1992a797ce50 100644
--- a/Documentation/userspace-api/media/v4l/pixfmt-raw-generic.rst
+++ b/Documentation/userspace-api/media/v4l/pixfmt-raw-generic.rst
@@ -1,8 +1,8 @@
 .. SPDX-License-Identifier: GPL-2.0 OR GFDL-1.1-no-invariants-or-later
 
-************************************************************************************************************************************
-V4L2_PIX_FMT_RAW_8 ('RAW8'), V4L2_PIX_FMT_RAW_CSI2_10 ('RACA'), V4L2_PIX_FMT_RAW_CSI2_12 ('RACC'), V4L2_PIX_FMT_RAW_CSI2_14 ('RACE')
-************************************************************************************************************************************
+**********************************************************************************************************************************************************************************************************************************************************************
+V4L2_PIX_FMT_RAW_8 ('RAW8'), V4L2_PIX_FMT_RAW_CSI2_10 ('RACA'), V4L2_PIX_FMT_RAW_CSI2_12 ('RACC'), V4L2_PIX_FMT_RAW_CSI2_14 ('RACE'), V4L2_PIX_FMT_RAW_16 ('RAWG'), V4L2_PIX_FMT_RAW_CSI2_20 ('RACK'), V4L2_PIX_FMT_RAW_24 ('RAWO'), V4L2_PIX_FMT_RAW_CSI2_28 ('RACS')
+**********************************************************************************************************************************************************************************************************************************************************************
 
 
 Generic line-based raw image data formats
@@ -175,3 +175,209 @@ Each cell is one byte. "P" denotes a pixel.
         P\ :sub:`11 bits 5--2` (bits 3--0)
       - P\ :sub:`31 bits 5--0` (bits 7--2),
         P\ :sub:`21 bits 5--4` (bits 1--0)
+
+.. _v4l2-pix-fmt-raw-16:
+
+V4L2_PIX_FMT_RAW_16
+-------------------
+
+V4L2_PIX_FMT_RAW_16 contains 16-bit image data, with each two consecutive
+bytes forming a pixel value. This format is typically used by CSI-2 receivers
+with a source that transmits MEDIA_BUS_FMT_RAW_16 and the CSI-2 receiver writes
+the received data to memory as-is.
+
+The packing of the data follows the MIPI CSI-2 specification.
+
+**Byte Order Of V4L2_PIX_FMT_RAW_16.**
+Each cell is one byte. "P" denotes a pixel.
+
+.. tabularcolumns:: |p{2.4cm}|p{1.2cm}|p{1.2cm}|p{1.2cm}|p{1.2cm}|p{1.2cm}|p{1.2cm}|p{1.2cm}|p{1.2cm}|
+
+.. flat-table:: Sample 4x2 Image Frame
+    :header-rows:  0
+    :stub-columns: 0
+    :widths: 12 8 8 8 8 8 8 8 8
+
+    * - start + 0:
+      - P\ :sub:`00 bits 15--8`
+      - P\ :sub:`00 bits 7--0`
+      - P\ :sub:`10 bits 15--8`
+      - P\ :sub:`10 bits 7--0`
+      - P\ :sub:`20 bits 15--8`
+      - P\ :sub:`20 bits 7--0`
+      - P\ :sub:`30 bits 15--8`
+      - P\ :sub:`30 bits 7--0`
+    * - start + 8:
+      - P\ :sub:`01 bits 15--8`
+      - P\ :sub:`01 bits 7--0`
+      - P\ :sub:`11 bits 15--8`
+      - P\ :sub:`11 bits 7--0`
+      - P\ :sub:`21 bits 15--8`
+      - P\ :sub:`21 bits 7--0`
+      - P\ :sub:`31 bits 15--8`
+      - P\ :sub:`31 bits 7--0`
+
+.. _v4l2-pix-fmt-raw-csi2-20:
+
+V4L2_PIX_FMT_RAW_CSI2_20
+------------------------
+
+V4L2_PIX_FMT_RAW_CSI2_20 contains 20-bit packed image data, with four bytes
+containing the top 8 bits of two pixels followed by lowest 4 bits of the pixels
+packed into one byte. This format is typically used by CSI-2 receivers with a
+source that transmits MEDIA_BUS_FMT_RAW_20 and the CSI-2 receiver writes the
+received data to memory as-is.
+
+The packing of the data follows the MIPI CSI-2 specification.
+
+**Byte Order Of V4L2_PIX_FMT_RAW_CSI2_20.**
+Each cell is one byte. "P" denotes a pixel.
+
+.. tabularcolumns:: |p{2.4cm}|p{1.2cm}|p{1.2cm}|p{1.2cm}|p{1.2cm}|p{2cm}|p{1.2cm}|p{1.2cm}|p{1.2cm}|p{1.2cm}|p{2cm}
+
+.. flat-table:: Sample 4x2 Image Frame
+    :header-rows:  0
+    :stub-columns: 0
+    :widths: 12 8 8 8 8 8 8 8 8 8 8
+
+    * - start + 0:
+      - P\ :sub:`00 bits 19--12`
+      - P\ :sub:`00 bits 11--4`
+      - P\ :sub:`10 bits 19--12`
+      - P\ :sub:`10 bits 11--4`
+      - P\ :sub:`10 bits 3--0` (bits 7--4),
+        P\ :sub:`00 bits 3--0` (bits 3--0)
+      - P\ :sub:`20 bits 19--12`
+      - P\ :sub:`20 bits 11--4`
+      - P\ :sub:`30 bits 19--12`
+      - P\ :sub:`30 bits 11--4`
+      - P\ :sub:`30 bits 3--0` (bits 7--4),
+        P\ :sub:`20 bits 3--0` (bits 3--0)
+    * - start + 10:
+      - P\ :sub:`01 bits 19--12`
+      - P\ :sub:`01 bits 11--4`
+      - P\ :sub:`11 bits 19--12`
+      - P\ :sub:`11 bits 11--4`
+      - P\ :sub:`11 bits 3--0` (bits 7--4),
+        P\ :sub:`01 bits 3--0` (bits 3--0)
+      - P\ :sub:`21 bits 19--12`
+      - P\ :sub:`21 bits 11--4`
+      - P\ :sub:`31 bits 19--12`
+      - P\ :sub:`31 bits 11--4`
+      - P\ :sub:`31 bits 3--0` (bits 7--4),
+        P\ :sub:`21 bits 3--0` (bits 3--0)
+
+.. _v4l2-pix-fmt-raw-24:
+
+V4L2_PIX_FMT_RAW_24
+-------------------
+
+V4L2_PIX_FMT_RAW_24 contains 24-bit packed image data, with each three bytes
+containing the value of one pixel. This format is typically used by CSI-2
+receivers with a source that transmits MEDIA_BUS_FMT_RAW_24 and the CSI-2
+receiver writes the received data to memory as-is.
+
+The packing of the data follows the MIPI CSI-2 specification.
+
+**Byte Order Of V4L2_PIX_FMT_RAW_24.**
+Each cell is one byte. "P" denotes a pixel.
+
+.. tabularcolumns:: |p{2.4cm}|p{1.2cm}|p{.8cm}|p{.8cm}|p{1.2cm}|p{.8cm}|p{.8cm}|p{1.2cm}|p{.8cm}|p{.8cm}|p{1.2cm}|p{.8cm}|p{.8cm}|
+
+.. flat-table:: Sample 4x2 Image Frame
+    :header-rows:  0
+    :stub-columns: 0
+    :widths: 12 8 8 8 8 8 8 8 8 8 8 8 8
+
+    * - start + 0:
+      - P\ :sub:`00 bits 23--16`
+      - P\ :sub:`00 bits 15--8`
+      - P\ :sub:`00 bits 7--0`
+      - P\ :sub:`10 bits 23--16`
+      - P\ :sub:`10 bits 15--8`
+      - P\ :sub:`10 bits 7--0`
+      - P\ :sub:`20 bits 23--16`
+      - P\ :sub:`20 bits 15--8`
+      - P\ :sub:`20 bits 7--0`
+      - P\ :sub:`30 bits 23--16`
+      - P\ :sub:`30 bits 15--8`
+      - P\ :sub:`30 bits 7--0`
+    * - start + 12:
+      - P\ :sub:`01 bits 23--16`
+      - P\ :sub:`01 bits 15--8`
+      - P\ :sub:`01 bits 7--0`
+      - P\ :sub:`11 bits 23--16`
+      - P\ :sub:`11 bits 15--8`
+      - P\ :sub:`11 bits 7--0`
+      - P\ :sub:`21 bits 23--16`
+      - P\ :sub:`21 bits 15--8`
+      - P\ :sub:`21 bits 7--0`
+      - P\ :sub:`31 bits 23--16`
+      - P\ :sub:`31 bits 15--8`
+      - P\ :sub:`31 bits 7--0`
+
+.. _v4l2-pix-fmt-raw-csi2-28:
+
+V4L2_PIX_FMT_RAW_CSI2_28
+------------------------
+
+V4L2_PIX_FMT_RAW_CSI2_28 contains 28-bit packed image data, with four bytes
+containing the top 8 bits of two pixels followed by lowest 4 bits of the pixels
+packed into one byte. This format is typically used by CSI-2 receivers with a
+source that transmits MEDIA_BUS_FMT_RAW_28 and the CSI-2 receiver writes the
+received data to memory as-is.
+
+The packing of the data follows the MIPI CSI-2 specification.
+
+**Byte Order Of V4L2_PIX_FMT_RAW_CSI2_28.**
+Each cell is one byte. "P" denotes a pixel.
+
+.. tabularcolumns:: |p{2.4cm}|p{1.2cm}|p{1.2cm}|p{1.2cm}|p{1.2cm}|p{1.2cm}|p{1.2cm}|p{1.2cm}|p{1.2cm}|p{1.2cm}|p{1.2cm}|p{1.2cm}|p{1.2cm}|p{1.2cm}|p{1.2cm}
+
+.. flat-table:: Sample 4x2 Image Frame
+    :header-rows:  0
+    :stub-columns: 0
+    :widths: 12 8 8 8 8 8 8 8 8 8 8 8 8 8 8
+
+    * - start + 0:
+      - P\ :sub:`00 bits 27--20`
+      - P\ :sub:`00 bits 13--6`
+      - P\ :sub:`10 bits 27--20`
+      - P\ :sub:`10 bits 13--6`
+      - P\ :sub:`00 bits 19--14` (bits 7--2),
+	P\ :sub:`00 bits 1--0` (bits 1--0)
+      - P\ :sub:`00 bits 5--2` (bits 7--4),
+	P\ :sub:`10 bits 17--14` (bits 3--0)
+      - P\ :sub:`10 bits 19--18` (bits 7--6),
+	P\ :sub:`10 bits 5--0` (bits 5--0)
+      - P\ :sub:`20 bits 27--20`
+      - P\ :sub:`20 bits 13--6`
+      - P\ :sub:`30 bits 27--20`
+      - P\ :sub:`30 bits 13--6`
+      - P\ :sub:`20 bits 19--14` (bits 7--2),
+	P\ :sub:`20 bits 1--0` (bits 1--0)
+      - P\ :sub:`20 bits 5--2` (bits 7--4),
+	P\ :sub:`30 bits 17--14` (bits 3--0)
+      - P\ :sub:`30 bits 19--18` (bits 7--6),
+	P\ :sub:`30 bits 5--0` (bits 5--0)
+    * - start + 14:
+      - P\ :sub:`01 bits 27--20`
+      - P\ :sub:`01 bits 13--6`
+      - P\ :sub:`11 bits 27--20`
+      - P\ :sub:`11 bits 13--6`
+      - P\ :sub:`01 bits 19--14` (bits 7--2),
+	P\ :sub:`01 bits 1--0` (bits 1--0)
+      - P\ :sub:`01 bits 5--2` (bits 7--4),
+	P\ :sub:`11 bits 17--14` (bits 3--0)
+      - P\ :sub:`11 bits 19--18` (bits 7--6),
+	P\ :sub:`11 bits 5--0` (bits 5--0)
+      - P\ :sub:`21 bits 27--20`
+      - P\ :sub:`21 bits 13--6`
+      - P\ :sub:`31 bits 27--20`
+      - P\ :sub:`31 bits 13--6`
+      - P\ :sub:`21 bits 19--14` (bits 7--2),
+	P\ :sub:`21 bits 1--0` (bits 1--0)
+      - P\ :sub:`21 bits 5--2` (bits 7--4),
+	P\ :sub:`31 bits 17--14` (bits 3--0)
+      - P\ :sub:`31 bits 19--18` (bits 7--6),
+	P\ :sub:`31 bits 5--0` (bits 5--0)
diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c b/drivers/media/v4l2-core/v4l2-ioctl.c
index 8e99cdefead3..9e2d18fe1056 100644
--- a/drivers/media/v4l2-core/v4l2-ioctl.c
+++ b/drivers/media/v4l2-core/v4l2-ioctl.c
@@ -1438,6 +1438,10 @@ static void v4l_fill_fmtdesc(struct v4l2_fmtdesc *fmt)
 	case V4L2_PIX_FMT_RAW_CSI2_10:	descr = "10-bit Raw, CSI-2 Packed"; break;
 	case V4L2_PIX_FMT_RAW_CSI2_12:	descr = "12-bit Raw, CSI-2 Packed"; break;
 	case V4L2_PIX_FMT_RAW_CSI2_14:	descr = "14-bit Raw, CSI-2 Packed"; break;
+	case V4L2_PIX_FMT_RAW_16:	descr = "16-bit Raw"; break;
+	case V4L2_PIX_FMT_RAW_CSI2_20:	descr = "20-bit Raw, CSI-2 Packed"; break;
+	case V4L2_PIX_FMT_RAW_24:	descr = "24-bit Raw"; break;
+	case V4L2_PIX_FMT_RAW_CSI2_28:	descr = "28-bit Raw, CSI-2 Packed"; break;
 	case V4L2_PIX_FMT_RAW_CRU20:	descr = "14-bit Raw CRU Packed"; break;
 	case V4L2_PIX_FMT_SN9C20X_I420:	descr = "GSPCA SN9C20X I420"; break;
 	case V4L2_PIX_FMT_SPCA501:	descr = "GSPCA SPCA501"; break;
diff --git a/include/uapi/linux/videodev2.h b/include/uapi/linux/videodev2.h
index 3ba872deeeb9..db172ecb131b 100644
--- a/include/uapi/linux/videodev2.h
+++ b/include/uapi/linux/videodev2.h
@@ -750,6 +750,10 @@ struct v4l2_pix_format {
 #define V4L2_PIX_FMT_RAW_CSI2_10 v4l2_fourcc('R', 'A', 'C', 'A')
 #define V4L2_PIX_FMT_RAW_CSI2_12 v4l2_fourcc('R', 'A', 'C', 'C')
 #define V4L2_PIX_FMT_RAW_CSI2_14 v4l2_fourcc('R', 'A', 'C', 'E')
+#define V4L2_PIX_FMT_RAW_16 v4l2_fourcc('R', 'A', 'W', 'G')
+#define V4L2_PIX_FMT_RAW_CSI2_20 v4l2_fourcc('R', 'A', 'C', 'K')
+#define V4L2_PIX_FMT_RAW_24 v4l2_fourcc('R', 'A', 'W', 'O')
+#define V4L2_PIX_FMT_RAW_CSI2_28 v4l2_fourcc('R', 'A', 'C', 'S')
 
 /* HSV formats */
 #define V4L2_PIX_FMT_HSV24 v4l2_fourcc('H', 'S', 'V', '3')
-- 
2.47.3


^ permalink raw reply related	[flat|nested] 88+ messages in thread

* [PATCH v12 42/86] media: uapi: Add more media bus codes for generic raw formats
  2026-04-09 20:13 [PATCH v12 00/86] Generic line based metadata support, internal pads Sakari Ailus
                   ` (40 preceding siblings ...)
  2026-04-09 20:14 ` [PATCH v12 41/86] media: uapi: Add generic CSI-2 raw pixelformats for 16, 20, 24 and 28 bpp Sakari Ailus
@ 2026-04-09 20:14 ` Sakari Ailus
  2026-04-09 20:14 ` [PATCH v12 43/86] media: uapi: ccs: Add metadata layout for MIPI CCS embedded data Sakari Ailus
                   ` (43 subsequent siblings)
  85 siblings, 0 replies; 88+ messages in thread
From: Sakari Ailus @ 2026-04-09 20:14 UTC (permalink / raw)
  To: linux-media
  Cc: hans, laurent.pinchart, Prabhakar, Kate Hsuan, Dave Stevenson,
	Tommaso Merciai, Benjamin Mugnier, Sylvain Petinot,
	Christophe JAILLET, Julien Massot, Naushir Patuck, Stefan Klug,
	Mirela Rabulea, André Apitzsch, Heimir Thor Sverrisson,
	Kieran Bingham, Mehdi Djait, Ricardo Ribalda Delgado,
	Hans de Goede, Jacopo Mondi, Tomi Valkeinen, David Plowman,
	Yu, Ong Hock, Ng, Khai Wen, Jai Luthra, Rishikesh Donadkar

Add new generic raw media bus codes for serial buses at bit depths or 16,
20, 24 and 28.

Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
---
 Documentation/userspace-api/media/v4l/subdev-formats.rst | 8 ++++++++
 include/uapi/linux/media-bus-format.h                    | 6 +++++-
 2 files changed, 13 insertions(+), 1 deletion(-)

diff --git a/Documentation/userspace-api/media/v4l/subdev-formats.rst b/Documentation/userspace-api/media/v4l/subdev-formats.rst
index b207119415f1..4b832118060a 100644
--- a/Documentation/userspace-api/media/v4l/subdev-formats.rst
+++ b/Documentation/userspace-api/media/v4l/subdev-formats.rst
@@ -3890,6 +3890,14 @@ affect the pattern is conveyed via the :ref:`V4L2_CID_CFA_PATTERN_FLIP
       - 12
     * - MEDIA_BUS_FMT_RAW_14
       - 14
+    * - MEDIA_BUS_FMT_RAW_16
+      - 16
+    * - MEDIA_BUS_FMT_RAW_20
+      - 20
+    * - MEDIA_BUS_FMT_RAW_24
+      - 24
+    * - MEDIA_BUS_FMT_RAW_28
+      - 28
 
 Packed YUV Formats
 ^^^^^^^^^^^^^^^^^^
diff --git a/include/uapi/linux/media-bus-format.h b/include/uapi/linux/media-bus-format.h
index 83feeae6a31e..40912155c741 100644
--- a/include/uapi/linux/media-bus-format.h
+++ b/include/uapi/linux/media-bus-format.h
@@ -190,10 +190,14 @@
 #define MEDIA_BUS_FMT_META_20			0x8006
 #define MEDIA_BUS_FMT_META_24			0x8007
 
-/* Generic (CFA independent) pixel data formats. Next is 0x9005. */
+/* Generic (CFA independent) pixel data formats. Next is 0x9009. */
 #define MEDIA_BUS_FMT_RAW_8			0x9001
 #define MEDIA_BUS_FMT_RAW_10			0x9002
 #define MEDIA_BUS_FMT_RAW_12			0x9003
 #define MEDIA_BUS_FMT_RAW_14			0x9004
+#define MEDIA_BUS_FMT_RAW_16			0x9005
+#define MEDIA_BUS_FMT_RAW_20			0x9006
+#define MEDIA_BUS_FMT_RAW_24			0x9007
+#define MEDIA_BUS_FMT_RAW_28			0x9008
 
 #endif /* __LINUX_MEDIA_BUS_FORMAT_H */
-- 
2.47.3


^ permalink raw reply related	[flat|nested] 88+ messages in thread

* [PATCH v12 43/86] media: uapi: ccs: Add metadata layout for MIPI CCS embedded data
  2026-04-09 20:13 [PATCH v12 00/86] Generic line based metadata support, internal pads Sakari Ailus
                   ` (41 preceding siblings ...)
  2026-04-09 20:14 ` [PATCH v12 42/86] media: uapi: Add more media bus codes for generic raw formats Sakari Ailus
@ 2026-04-09 20:14 ` Sakari Ailus
  2026-04-09 20:14 ` [PATCH v12 44/86] media: ccs: Add support for generic raw mbus codes Sakari Ailus
                   ` (42 subsequent siblings)
  85 siblings, 0 replies; 88+ messages in thread
From: Sakari Ailus @ 2026-04-09 20:14 UTC (permalink / raw)
  To: linux-media
  Cc: hans, laurent.pinchart, Prabhakar, Kate Hsuan, Dave Stevenson,
	Tommaso Merciai, Benjamin Mugnier, Sylvain Petinot,
	Christophe JAILLET, Julien Massot, Naushir Patuck, Stefan Klug,
	Mirela Rabulea, André Apitzsch, Heimir Thor Sverrisson,
	Kieran Bingham, Mehdi Djait, Ricardo Ribalda Delgado,
	Hans de Goede, Jacopo Mondi, Tomi Valkeinen, David Plowman,
	Yu, Ong Hock, Ng, Khai Wen, Jai Luthra, Rishikesh Donadkar

Add new metadata layout (V4L2_METADATA_LAYOUT_CCS) for MIPI CCS embedded
data.

Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
Reviewed-by: Julien Massot <julien.massot@collabora.com>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 .../media/v4l/ext-ctrls-image-source.rst      | 12 ++++++
 .../userspace-api/media/v4l/meta-formats.rst  |  1 +
 .../media/v4l/metadata-layouts.rst            | 39 +++++++++++++++++++
 .../media/v4l/metafmt-generic.rst             |  2 +
 .../media/v4l/subdev-formats.rst              |  5 +++
 include/uapi/linux/v4l2-controls.h            |  1 +
 6 files changed, 60 insertions(+)
 create mode 100644 Documentation/userspace-api/media/v4l/metadata-layouts.rst

diff --git a/Documentation/userspace-api/media/v4l/ext-ctrls-image-source.rst b/Documentation/userspace-api/media/v4l/ext-ctrls-image-source.rst
index fb4dee1b4f94..4ed9bea89101 100644
--- a/Documentation/userspace-api/media/v4l/ext-ctrls-image-source.rst
+++ b/Documentation/userspace-api/media/v4l/ext-ctrls-image-source.rst
@@ -161,6 +161,18 @@ Image Source Control IDs
     :ref:`generic metadata formats <media-bus-format-generic-meta>` formats to
     specify the layout of the data.
 
+.. flat-table:: V4L2 metadata layouts
+    :header-rows:  1
+    :stub-columns: 0
+    :widths:       1 2 1
+
+    * - Macro name
+      - Synopsis
+      - Value
+    * - V4L2_METADATA_LAYOUT_CCS
+      - :ref:`CCS embedded data <media-metadata-layout-ccs>`
+      - 1
+
 .. _image_source_control_binning_factors:
 
 ``V4L2_CID_BINNING_FACTORS (integer menu)``
diff --git a/Documentation/userspace-api/media/v4l/meta-formats.rst b/Documentation/userspace-api/media/v4l/meta-formats.rst
index 3e0cab153f0a..218d75965a73 100644
--- a/Documentation/userspace-api/media/v4l/meta-formats.rst
+++ b/Documentation/userspace-api/media/v4l/meta-formats.rst
@@ -17,6 +17,7 @@ These formats are used for the :ref:`metadata` interface only.
     metafmt-c3-isp
     metafmt-d4xx
     metafmt-generic
+    metadata-layouts
     metafmt-intel-ipu3
     metafmt-pisp-be
     metafmt-pisp-fe
diff --git a/Documentation/userspace-api/media/v4l/metadata-layouts.rst b/Documentation/userspace-api/media/v4l/metadata-layouts.rst
new file mode 100644
index 000000000000..cd190f453994
--- /dev/null
+++ b/Documentation/userspace-api/media/v4l/metadata-layouts.rst
@@ -0,0 +1,39 @@
+.. SPDX-License-Identifier: GPL-2.0 OR GFDL-1.1-no-invariants-or-later
+
+.. _media_metadata_layouts:
+
+Metadata Layouts
+----------------
+
+The :ref:`metadata layout control <image_source_control_metadata_layout>`
+specifies the exact layout of the metadata stream while the a :ref:`generic
+metadata mbus code <media-bus-format-generic-meta>` on the subdevice pads
+only describe the size of the :term:`Data Unit`.
+
+.. _media-metadata-layout-ccs:
+
+MIPI CCS Embedded Data Layout (``V4L2_METADATA_LAYOUT_CCS``)
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+`MIPI CCS <https://www.mipi.org/specifications/camera-command-set>`_ defines a
+metadata layout for sensor embedded data, identified by
+``V4L2_CID_METADATA_LAYOUT`` control value ``V4L2_METADATA_LAYOUT_CCS``, which
+is used to store the register configuration used for capturing a given
+frame. The layout itself is defined in the CCS specification.
+
+The CCS embedded data format (code ``0xa``) definition includes three levels:
+
+1. Padding within CSI-2 bus :term:`Data Unit` as documented in the MIPI CCS
+   specification.
+
+2. The tagged data format as documented in the MIPI CCS specification.
+
+3. Register addresses and register documentation as documented in the MIPI CCS
+   specification.
+
+The ``V4L2_METADATA_LAYOUT_CCS`` metadata layout value shall be used only by
+devices that fulfill all three levels above.
+
+This metadata layout code is only used for "2-byte simplified tagged data
+format" (code ``0xa``) but their use may be extended further in the future, to
+cover other CCS embedded data format codes.
diff --git a/Documentation/userspace-api/media/v4l/metafmt-generic.rst b/Documentation/userspace-api/media/v4l/metafmt-generic.rst
index 07147b4d0dd2..fb97fe4d3c72 100644
--- a/Documentation/userspace-api/media/v4l/metafmt-generic.rst
+++ b/Documentation/userspace-api/media/v4l/metafmt-generic.rst
@@ -8,6 +8,8 @@ V4L2_META_FMT_GENERIC_8 ('MET8'), V4L2_META_FMT_GENERIC_CSI2_10 ('MECA'), V4L2_M
 
 Generic line-based metadata formats
 
+.. _v4l2-format-generic-meta:
+
 Description
 ===========
 
diff --git a/Documentation/userspace-api/media/v4l/subdev-formats.rst b/Documentation/userspace-api/media/v4l/subdev-formats.rst
index 4b832118060a..30dd26804776 100644
--- a/Documentation/userspace-api/media/v4l/subdev-formats.rst
+++ b/Documentation/userspace-api/media/v4l/subdev-formats.rst
@@ -8932,6 +8932,11 @@ content is more or less device specific but the data is transmitted and received
 by multiple devices that do not process the data in any way, simply writing
 it to system memory for processing in software at the end of the pipeline.
 
+The exact layout of the data generated by the device is reported by the
+:ref:`V4L2_CID_METADATA_LAYOUT <image_source_control_metadata_layout>`
+control. For in-memory formats, :ref:`Generic line-based metadata formats
+<v4l2-format-generic-meta>` are used.
+
 "b" in an array cell signifies a byte of data, followed by the number of the bit
 and finally the bit number in subscript. "x" indicates a padding bit.
 
diff --git a/include/uapi/linux/v4l2-controls.h b/include/uapi/linux/v4l2-controls.h
index aaa0d88d7e6e..e27a7ad47c51 100644
--- a/include/uapi/linux/v4l2-controls.h
+++ b/include/uapi/linux/v4l2-controls.h
@@ -1248,6 +1248,7 @@ enum v4l2_jpeg_chroma_subsampling {
 	(V4L2_CFA_PATTERN_FLIP_HORIZONTAL | V4L2_CFA_PATTERN_FLIP_VERTICAL)
 
 #define V4L2_CID_METADATA_LAYOUT		(V4L2_CID_IMAGE_SOURCE_CLASS_BASE + 12)
+#define V4L2_METADATA_LAYOUT_CCS		1U
 
 #define V4L2_CID_BINNING_FACTORS		(V4L2_CID_IMAGE_SOURCE_CLASS_BASE + 13)
 #define V4L2_BINNING_FACTORS_MAKE(hnum, hdem, vnum, vdem)		\
-- 
2.47.3


^ permalink raw reply related	[flat|nested] 88+ messages in thread

* [PATCH v12 44/86] media: ccs: Add support for generic raw mbus codes
  2026-04-09 20:13 [PATCH v12 00/86] Generic line based metadata support, internal pads Sakari Ailus
                   ` (42 preceding siblings ...)
  2026-04-09 20:14 ` [PATCH v12 43/86] media: uapi: ccs: Add metadata layout for MIPI CCS embedded data Sakari Ailus
@ 2026-04-09 20:14 ` Sakari Ailus
  2026-04-09 20:14 ` [PATCH v12 45/86] media: ccs: Add support for embedded data stream Sakari Ailus
                   ` (41 subsequent siblings)
  85 siblings, 0 replies; 88+ messages in thread
From: Sakari Ailus @ 2026-04-09 20:14 UTC (permalink / raw)
  To: linux-media
  Cc: hans, laurent.pinchart, Prabhakar, Kate Hsuan, Dave Stevenson,
	Tommaso Merciai, Benjamin Mugnier, Sylvain Petinot,
	Christophe JAILLET, Julien Massot, Naushir Patuck, Stefan Klug,
	Mirela Rabulea, André Apitzsch, Heimir Thor Sverrisson,
	Kieran Bingham, Mehdi Djait, Ricardo Ribalda Delgado,
	Hans de Goede, Jacopo Mondi, Tomi Valkeinen, David Plowman,
	Yu, Ong Hock, Ng, Khai Wen, Jai Luthra, Rishikesh Donadkar

Add support for generic media bus codes for 8, 10, 12 and 14 bits per
pixel.

Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
---
 drivers/media/i2c/ccs/ccs-core.c | 54 ++++++++++++++++++++++----------
 drivers/media/i2c/ccs/ccs.h      |  2 ++
 2 files changed, 39 insertions(+), 17 deletions(-)

diff --git a/drivers/media/i2c/ccs/ccs-core.c b/drivers/media/i2c/ccs/ccs-core.c
index 1cd4db3f5708..0248a51eba8f 100644
--- a/drivers/media/i2c/ccs/ccs-core.c
+++ b/drivers/media/i2c/ccs/ccs-core.c
@@ -642,13 +642,18 @@ static const struct ccs_csi_data_format ccs_csi_data_formats[] = {
 	{ MEDIA_BUS_FMT_SRGGB8_1X8, 8, 8, CCS_PIXEL_ORDER_RGGB, },
 	{ MEDIA_BUS_FMT_SBGGR8_1X8, 8, 8, CCS_PIXEL_ORDER_BGGR, },
 	{ MEDIA_BUS_FMT_SGBRG8_1X8, 8, 8, CCS_PIXEL_ORDER_GBRG, },
+	/* Generic formats are placed below. */
+	{ MEDIA_BUS_FMT_RAW_8, 8, 8, 0, true },
+	{ MEDIA_BUS_FMT_RAW_10, 10, 10, 0, true },
+	{ MEDIA_BUS_FMT_RAW_12, 12, 12, 0, true },
+	{ MEDIA_BUS_FMT_RAW_14, 14, 14, 0, true },
 };
 
 static const char *pixel_order_str[] = { "GRBG", "RGGB", "BGGR", "GBRG" };
 
-#define to_csi_format_idx(fmt) (((unsigned long)(fmt)			\
-				 - (unsigned long)ccs_csi_data_formats) \
-				/ sizeof(*ccs_csi_data_formats))
+#define to_csi_format_idx(fmt)						\
+	(((unsigned long)(fmt) - (unsigned long)ccs_csi_data_formats)	\
+	 / sizeof(*ccs_csi_data_formats))
 
 static u32 ccs_pixel_order(struct ccs_sensor *sensor)
 {
@@ -669,27 +674,25 @@ static u32 ccs_pixel_order(struct ccs_sensor *sensor)
 
 static void ccs_update_mbus_formats(struct ccs_sensor *sensor)
 {
-	struct i2c_client *client = v4l2_get_subdevdata(&sensor->src->sd);
+	unsigned int mask = sensor->csi_format->is_generic ? ~0 : ~3;
 	unsigned int csi_format_idx =
-		to_csi_format_idx(sensor->csi_format) & ~3;
+		to_csi_format_idx(sensor->csi_format) & mask;
 	unsigned int internal_csi_format_idx =
-		to_csi_format_idx(sensor->internal_csi_format) & ~3;
-	unsigned int pixel_order = ccs_pixel_order(sensor);
+		to_csi_format_idx(sensor->internal_csi_format) & mask;
+	unsigned int pixel_order = sensor->csi_format->is_generic ?
+		0 : ccs_pixel_order(sensor);
 
 	if (WARN_ON_ONCE(max(internal_csi_format_idx, csi_format_idx) +
 			 pixel_order >= ARRAY_SIZE(ccs_csi_data_formats)))
 		return;
 
 	sensor->mbus_frame_fmts =
-		sensor->default_mbus_frame_fmts << pixel_order;
+		(sensor->default_mbus_frame_fmts << pixel_order) |
+		sensor->default_generic_mbus_frame_fmts;
 	sensor->csi_format =
 		&ccs_csi_data_formats[csi_format_idx + pixel_order];
 	sensor->internal_csi_format =
-		&ccs_csi_data_formats[internal_csi_format_idx
-					 + pixel_order];
-
-	dev_dbg(&client->dev, "new pixel order %s\n",
-		pixel_order_str[pixel_order]);
+		&ccs_csi_data_formats[internal_csi_format_idx + pixel_order];
 }
 
 static const char * const ccs_test_patterns[] = {
@@ -896,7 +899,7 @@ static int ccs_init_controls(struct ccs_sensor *sensor)
 	struct v4l2_fwnode_device_properties props;
 	int rval;
 
-	rval = v4l2_ctrl_handler_init(&sensor->pixel_array->ctrl_handler, 19);
+	rval = v4l2_ctrl_handler_init(&sensor->pixel_array->ctrl_handler, 21);
 	if (rval)
 		return rval;
 
@@ -1091,6 +1094,17 @@ static int ccs_init_controls(struct ccs_sensor *sensor)
 
 	v4l2_ctrl_cluster(2, &sensor->hflip);
 
+	v4l2_ctrl_new_std(&sensor->pixel_array->ctrl_handler, NULL,
+			  V4L2_CID_CFA_PATTERN, sensor->default_pixel_order,
+			  sensor->default_pixel_order, 1,
+			  sensor->default_pixel_order);
+
+	v4l2_ctrl_new_std(&sensor->pixel_array->ctrl_handler, NULL,
+			  V4L2_CID_CFA_PATTERN_FLIP,
+			  V4L2_CFA_PATTERN_FLIP_BOTH,
+			  V4L2_CFA_PATTERN_FLIP_BOTH, 1,
+			  V4L2_CFA_PATTERN_FLIP_BOTH);
+
 	rval = v4l2_ctrl_handler_init(&sensor->src->ctrl_handler, 0);
 	if (rval)
 		return rval;
@@ -1199,15 +1213,21 @@ static int ccs_get_mbus_formats(struct ccs_sensor *sensor)
 			const struct ccs_csi_data_format *f =
 				&ccs_csi_data_formats[j];
 
-			if (f->pixel_order != CCS_PIXEL_ORDER_GRBG)
-				continue;
-
 			if (f->width != fmt >>
 			    CCS_DATA_FORMAT_DESCRIPTOR_UNCOMPRESSED_SHIFT ||
 			    f->compressed !=
 			    (fmt & CCS_DATA_FORMAT_DESCRIPTOR_COMPRESSED_MASK))
 				continue;
 
+			if (f->is_generic) {
+				sensor->default_generic_mbus_frame_fmts |=
+					BIT_U64(j);
+				continue;
+			}
+
+			if (f->pixel_order != CCS_PIXEL_ORDER_GRBG)
+				continue;
+
 			dev_dbg(&client->dev, "jolly good! %u\n", j);
 
 			sensor->default_mbus_frame_fmts |= BIT_U64(j);
diff --git a/drivers/media/i2c/ccs/ccs.h b/drivers/media/i2c/ccs/ccs.h
index 58952c5bf06b..df044dbde23f 100644
--- a/drivers/media/i2c/ccs/ccs.h
+++ b/drivers/media/i2c/ccs/ccs.h
@@ -170,6 +170,7 @@ struct ccs_csi_data_format {
 	u8 width;
 	u8 compressed;
 	u8 pixel_order;
+	bool is_generic;
 };
 
 #define CCS_SUBDEVS			3
@@ -226,6 +227,7 @@ struct ccs_sensor {
 	const struct ccs_csi_data_format *csi_format;
 	const struct ccs_csi_data_format *internal_csi_format;
 	u64 default_mbus_frame_fmts;
+	u64 default_generic_mbus_frame_fmts;
 	int default_pixel_order;
 	struct ccs_data_container sdata, mdata;
 
-- 
2.47.3


^ permalink raw reply related	[flat|nested] 88+ messages in thread

* [PATCH v12 45/86] media: ccs: Add support for embedded data stream
  2026-04-09 20:13 [PATCH v12 00/86] Generic line based metadata support, internal pads Sakari Ailus
                   ` (43 preceding siblings ...)
  2026-04-09 20:14 ` [PATCH v12 44/86] media: ccs: Add support for generic raw mbus codes Sakari Ailus
@ 2026-04-09 20:14 ` Sakari Ailus
  2026-04-09 20:14 ` [PATCH v12 46/86] media: Documentation: ccs: Document routing Sakari Ailus
                   ` (40 subsequent siblings)
  85 siblings, 0 replies; 88+ messages in thread
From: Sakari Ailus @ 2026-04-09 20:14 UTC (permalink / raw)
  To: linux-media
  Cc: hans, laurent.pinchart, Prabhakar, Kate Hsuan, Dave Stevenson,
	Tommaso Merciai, Benjamin Mugnier, Sylvain Petinot,
	Christophe JAILLET, Julien Massot, Naushir Patuck, Stefan Klug,
	Mirela Rabulea, André Apitzsch, Heimir Thor Sverrisson,
	Kieran Bingham, Mehdi Djait, Ricardo Ribalda Delgado,
	Hans de Goede, Jacopo Mondi, Tomi Valkeinen, David Plowman,
	Yu, Ong Hock, Ng, Khai Wen, Jai Luthra, Rishikesh Donadkar

Add support for embedded data stream, in UAPI and frame descriptor.

This patch adds also a new embedded data pad (2) to the source sub-device.

Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
---
 drivers/media/i2c/ccs/ccs-core.c | 342 +++++++++++++++++++++++++++++--
 drivers/media/i2c/ccs/ccs.h      |  15 +-
 2 files changed, 338 insertions(+), 19 deletions(-)

diff --git a/drivers/media/i2c/ccs/ccs-core.c b/drivers/media/i2c/ccs/ccs-core.c
index 0248a51eba8f..c4fe400d1cef 100644
--- a/drivers/media/i2c/ccs/ccs-core.c
+++ b/drivers/media/i2c/ccs/ccs-core.c
@@ -899,7 +899,7 @@ static int ccs_init_controls(struct ccs_sensor *sensor)
 	struct v4l2_fwnode_device_properties props;
 	int rval;
 
-	rval = v4l2_ctrl_handler_init(&sensor->pixel_array->ctrl_handler, 21);
+	rval = v4l2_ctrl_handler_init(&sensor->pixel_array->ctrl_handler, 22);
 	if (rval)
 		return rval;
 
@@ -1105,6 +1105,12 @@ static int ccs_init_controls(struct ccs_sensor *sensor)
 			  V4L2_CFA_PATTERN_FLIP_BOTH, 1,
 			  V4L2_CFA_PATTERN_FLIP_BOTH);
 
+	v4l2_ctrl_new_std(&sensor->pixel_array->ctrl_handler, NULL,
+			  V4L2_CID_METADATA_LAYOUT,
+			  V4L2_METADATA_LAYOUT_CCS,
+			  V4L2_METADATA_LAYOUT_CCS, 1,
+			  V4L2_METADATA_LAYOUT_CCS);
+
 	rval = v4l2_ctrl_handler_init(&sensor->src->ctrl_handler, 0);
 	if (rval)
 		return rval;
@@ -1871,6 +1877,57 @@ static int ccs_pm_get_init(struct ccs_sensor *sensor)
 	return rval;
 }
 
+#define CCS_EMBEDDED_CODE_DEPTH(depth, half_depth)			\
+	depth,								\
+	CCS_EMB_DATA_CAPABILITY_TWO_BYTES_PER_RAW##depth,		\
+	CCS_EMB_DATA_CAPABILITY_NO_ONE_BYTE_PER_RAW##depth,		\
+	CCS_EMB_DATA_CTRL_RAW##half_depth##_PACKING_FOR_RAW##depth,	\
+	MEDIA_BUS_FMT_META_##half_depth,				\
+	MEDIA_BUS_FMT_META_##depth,					\
+
+static const struct ccs_embedded_code {
+	u8 depth;
+	u8 cap_two_bytes_per_sample;
+	u8 cap_no_legacy;
+	u8 ctrl;
+	u32 code_two_bytes;
+	u32 code_legacy;
+} ccs_embedded_codes[] = {
+	{ CCS_EMBEDDED_CODE_DEPTH(16, 8) },
+	{ CCS_EMBEDDED_CODE_DEPTH(20, 10) },
+	{ CCS_EMBEDDED_CODE_DEPTH(24, 12) },
+};
+
+static const struct ccs_embedded_code *ccs_embedded_code(unsigned int bpp)
+{
+	unsigned int i;
+
+	for (i = 0; i < ARRAY_SIZE(ccs_embedded_codes); i++)
+		if (ccs_embedded_codes[i].depth == bpp)
+			return ccs_embedded_codes + i;
+
+	WARN_ON(1);
+
+	return ccs_embedded_codes;
+}
+
+static u32
+ccs_default_embedded_code(struct ccs_sensor *sensor,
+			  const struct ccs_embedded_code *embedded_code)
+{
+	if (CCS_LIM(sensor, EMB_DATA_CAPABILITY) &
+	    BIT(embedded_code->cap_two_bytes_per_sample))
+		return embedded_code->code_two_bytes;
+
+	if (!(CCS_LIM(sensor, EMB_DATA_CAPABILITY) &
+	      BIT(embedded_code->cap_no_legacy)))
+		return embedded_code->code_legacy;
+
+	WARN_ON(1);
+
+	return embedded_code->code_legacy;
+}
+
 static int ccs_enable_streams(struct v4l2_subdev *subdev,
 			      struct v4l2_subdev_state *state, u32 pad,
 			      u64 streams_mask)
@@ -2003,6 +2060,22 @@ static int ccs_enable_streams(struct v4l2_subdev *subdev,
 	if (rval < 0)
 		goto err_pm_put;
 
+	/* Configure embedded data */
+	if (sensor->csi_format->compressed >= 16) {
+		const struct ccs_embedded_code *embedded_code =
+			ccs_embedded_code(sensor->csi_format->compressed);
+		const struct v4l2_mbus_framefmt *meta_out_fmt =
+			v4l2_subdev_state_get_format(src_state, CCS_PAD_SRC,
+						     CCS_STREAM_META);
+
+		rval = ccs_write(sensor, EMB_DATA_CTRL,
+				 meta_out_fmt->code ==
+				 embedded_code->code_legacy ?
+				 0 : embedded_code->ctrl);
+		if (rval < 0)
+			goto err_pm_put;
+	}
+
 	if (CCS_LIM(sensor, FLASH_MODE_CAPABILITY) &
 	    (CCS_FLASH_MODE_CAPABILITY_SINGLE_STROBE |
 	     SMIAPP_FLASH_MODE_CAPABILITY_MULTIPLE_STROBE) &&
@@ -2133,6 +2206,61 @@ static int ccs_enum_mbus_code(struct v4l2_subdev *subdev,
 	dev_err(&client->dev, "subdev %s, pad %u, index %u\n",
 		subdev->name, code->pad, code->index);
 
+	if (subdev == &sensor->src->sd) {
+		if (code->pad == CCS_PAD_META ||
+		    code->stream == CCS_STREAM_META) {
+			struct v4l2_mbus_framefmt *pix_fmt =
+				v4l2_subdev_state_get_format(sd_state,
+							     CCS_PAD_SRC,
+							     CCS_STREAM_PIXEL);
+			const struct ccs_csi_data_format *csi_format =
+				ccs_validate_csi_data_format(sensor,
+							     pix_fmt->code);
+			unsigned int i = 0;
+			u32 codes[2];
+
+			switch (csi_format->compressed) {
+			case 8:
+				codes[i++] = MEDIA_BUS_FMT_META_8;
+				break;
+			case 10:
+				codes[i++] = MEDIA_BUS_FMT_META_10;
+				break;
+			case 12:
+				codes[i++] = MEDIA_BUS_FMT_META_12;
+				break;
+			case 14:
+				codes[i++] = MEDIA_BUS_FMT_META_14;
+				break;
+			case 16:
+			case 20:
+			case 24: {
+				const struct ccs_embedded_code *embedded_code =
+					ccs_embedded_code(csi_format->compressed);
+
+				if (CCS_LIM(sensor, EMB_DATA_CAPABILITY) &
+				    BIT(embedded_code->cap_two_bytes_per_sample))
+					codes[i++] =
+						embedded_code->code_two_bytes;
+
+				if (!(CCS_LIM(sensor, EMB_DATA_CAPABILITY) &
+				      BIT(embedded_code->cap_no_legacy)))
+					codes[i++] = embedded_code->code_legacy;
+				break;
+			}
+			default:
+				WARN_ON(1);
+			}
+
+			if (WARN_ON(i > ARRAY_SIZE(codes)) || code->index >= i)
+				return -EINVAL;
+
+			code->code = codes[code->index];
+
+			return 0;
+		}
+	}
+
 	if (subdev != &sensor->src->sd || code->pad != CCS_PAD_SRC) {
 		if (code->index)
 			return -EINVAL;
@@ -2172,8 +2300,11 @@ static int ccs_get_format(struct v4l2_subdev *subdev,
 			  struct v4l2_subdev_state *sd_state,
 			  struct v4l2_subdev_format *fmt)
 {
-	fmt->format = *v4l2_subdev_state_get_format(sd_state, fmt->pad);
-	fmt->format.code = ccs_get_mbus_code(subdev, fmt->pad);
+	fmt->format = *v4l2_subdev_state_get_format(sd_state, fmt->pad,
+						    fmt->stream);
+
+	if (fmt->pad != CCS_PAD_META && fmt->stream != CCS_STREAM_META)
+		fmt->format.code = ccs_get_mbus_code(subdev, fmt->pad);
 
 	return 0;
 }
@@ -2263,6 +2394,86 @@ static int ccs_set_format_source(struct v4l2_subdev *subdev,
 	return ccs_pll_update(sensor);
 }
 
+static inline unsigned int ccs_embedded_data_lines(struct ccs_sensor *sensor)
+{
+	return sensor->embedded_end - sensor->embedded_start;
+}
+
+static int ccs_set_format_meta(struct v4l2_subdev *subdev,
+			       struct v4l2_subdev_state *sd_state,
+			       struct v4l2_mbus_framefmt *fmt)
+{
+	struct ccs_sensor *sensor = to_ccs_sensor(subdev);
+	const struct ccs_csi_data_format *csi_format;
+	struct v4l2_mbus_framefmt *pix_fmt;
+	struct v4l2_mbus_framefmt *meta_fmt;
+	struct v4l2_mbus_framefmt *meta_out_fmt;
+	u32 code;
+
+	pix_fmt = v4l2_subdev_state_get_format(sd_state, CCS_PAD_SRC,
+					       CCS_STREAM_PIXEL);
+	meta_fmt = v4l2_subdev_state_get_format(sd_state, CCS_PAD_META, 0);
+	meta_out_fmt = v4l2_subdev_state_get_format(sd_state, CCS_PAD_SRC,
+						    CCS_STREAM_META);
+
+	code = fmt ? fmt->code : 0;
+
+	meta_fmt->width = pix_fmt->width;
+	meta_fmt->height = ccs_embedded_data_lines(sensor);
+
+	csi_format = ccs_validate_csi_data_format(sensor, pix_fmt->code);
+
+	switch (csi_format->compressed) {
+	case 8:
+		meta_fmt->code = MEDIA_BUS_FMT_META_8;
+		break;
+	case 10:
+		meta_fmt->code = MEDIA_BUS_FMT_META_10;
+		break;
+	case 12:
+		meta_fmt->code = MEDIA_BUS_FMT_META_12;
+		break;
+	case 14:
+		meta_fmt->code = MEDIA_BUS_FMT_META_14;
+		break;
+	case 16:
+	case 20:
+	case 24: {
+		const struct ccs_embedded_code *embedded_code;
+
+		embedded_code = ccs_embedded_code(csi_format->compressed);
+		meta_fmt->code =
+			ccs_default_embedded_code(sensor, embedded_code);
+
+		if (!(CCS_LIM(sensor, EMB_DATA_CAPABILITY) &
+		      BIT(embedded_code->cap_no_legacy)) &&
+		    code == embedded_code->code_legacy)
+			meta_fmt->code = embedded_code->code_legacy;
+
+		if (CCS_LIM(sensor, EMB_DATA_CAPABILITY) &
+		    BIT(embedded_code->cap_two_bytes_per_sample) &&
+		    code == embedded_code->code_two_bytes) {
+			meta_fmt->code = embedded_code->code_two_bytes;
+			meta_fmt->width <<= 1;
+		}
+
+		break;
+	}
+	default:
+		WARN_ON(1);
+		return 0;
+	}
+
+	meta_out_fmt->width = meta_fmt->width;
+	meta_out_fmt->height = meta_fmt->height;
+	meta_out_fmt->code = meta_fmt->code;
+
+	if (fmt)
+		*fmt = *meta_out_fmt;
+
+	return 0;
+}
+
 static int ccs_set_format(struct v4l2_subdev *subdev,
 			  const struct v4l2_subdev_client_info *ci,
 			  struct v4l2_subdev_state *sd_state,
@@ -2272,10 +2483,21 @@ static int ccs_set_format(struct v4l2_subdev *subdev,
 	struct ccs_subdev *ssd = to_ccs_subdev(subdev);
 	struct v4l2_rect *crop;
 
+	if (ssd == sensor->src && fmt->pad == CCS_PAD_META)
+		return ccs_get_format(subdev, ci, sd_state, fmt);
+
+	if (ssd == sensor->src && fmt->stream == CCS_STREAM_META) {
+		ccs_set_format_meta(subdev, sd_state, &fmt->format);
+
+		return 0;
+	}
+
 	if (fmt->pad == ssd->source_pad) {
 		int rval;
 
 		rval = ccs_set_format_source(subdev, NULL, sd_state, fmt);
+		if (ccs_embedded_data_lines(sensor) && ssd == sensor->src)
+			ccs_set_format_meta(subdev, sd_state, NULL);
 
 		return rval;
 	}
@@ -2527,6 +2749,12 @@ static int ccs_sel_supported(struct v4l2_subdev *subdev,
 	struct ccs_sensor *sensor = to_ccs_sensor(subdev);
 	struct ccs_subdev *ssd = to_ccs_subdev(subdev);
 
+	if (sel->stream != CCS_STREAM_PIXEL)
+		return -EINVAL;
+
+	if (sel->pad == CCS_PAD_META)
+		return -EINVAL;
+
 	/* We only implement crop in three places. */
 	switch (sel->target) {
 	case V4L2_SEL_TGT_CROP:
@@ -2576,7 +2804,8 @@ static int ccs_set_crop(struct v4l2_subdev *subdev,
 
 	if (sel->pad == ssd->sink_pad) {
 		struct v4l2_mbus_framefmt *mfmt =
-			v4l2_subdev_state_get_format(sd_state, sel->pad);
+			v4l2_subdev_state_get_format(sd_state, sel->pad,
+						     CCS_STREAM_PIXEL);
 
 		src_size.width = mfmt->width;
 		src_size.height = mfmt->height;
@@ -2638,7 +2867,9 @@ static int ccs_get_selection(struct v4l2_subdev *subdev,
 		} else if (sel->pad == ssd->sink_pad) {
 			struct v4l2_mbus_framefmt *sink_fmt =
 				v4l2_subdev_state_get_format(sd_state,
-							     ssd->sink_pad);
+							     ssd->sink_pad,
+							     CCS_STREAM_PIXEL);
+
 			sel->r.top = sel->r.left = 0;
 			sel->r.width = sink_fmt->width;
 			sel->r.height = sink_fmt->height;
@@ -2724,6 +2955,18 @@ static int ccs_get_frame_desc(struct v4l2_subdev *subdev, unsigned int pad,
 	entry++;
 	desc->num_entries++;
 
+	if (ccs_embedded_data_lines(sensor)) {
+		struct v4l2_mbus_framefmt *meta_out_fmt =
+			v4l2_subdev_state_get_format(sd_state, CCS_PAD_SRC,
+						     CCS_STREAM_META);
+
+		entry->pixelcode = meta_out_fmt->code;
+		entry->stream = CCS_STREAM_META;
+		entry->bus.csi2.dt = MIPI_CSI2_DT_EMBEDDED_8B;
+		entry++;
+		desc->num_entries++;
+	}
+
 	v4l2_subdev_unlock_state(sd_state);
 
 	return 0;
@@ -3064,7 +3307,8 @@ static int ccs_init_subdev(struct ccs_sensor *sensor,
 	ssd->sensor = sensor;
 
 	ssd->npads = num_pads;
-	ssd->source_pad = num_pads - 1;
+	ssd->source_pad =
+		ssd == sensor->pixel_array ? CCS_PA_PAD_SRC : CCS_PAD_SRC;
 
 	v4l2_i2c_subdev_set_name(&ssd->sd, client, sensor->minfo.name, name);
 
@@ -3078,6 +3322,10 @@ static int ccs_init_subdev(struct ccs_sensor *sensor,
 		ssd->sd.owner = THIS_MODULE;
 		ssd->sd.dev = &client->dev;
 		v4l2_set_subdevdata(&ssd->sd, client);
+	} else {
+		ssd->sd.flags |= V4L2_SUBDEV_FL_STREAMS;
+		ssd->pads[CCS_PAD_META].flags =
+			MEDIA_PAD_FL_SINK | MEDIA_PAD_FL_INTERNAL;
 	}
 
 	rval = media_entity_pads_init(&ssd->sd.entity, ssd->npads, ssd->pads);
@@ -3103,9 +3351,9 @@ static int ccs_init_state(struct v4l2_subdev *sd,
 	unsigned int pad = ssd == sensor->pixel_array ?
 		CCS_PA_PAD_SRC : CCS_PAD_SINK;
 	struct v4l2_mbus_framefmt *fmt =
-		v4l2_subdev_state_get_format(sd_state, pad);
+		v4l2_subdev_state_get_format(sd_state, pad, CCS_STREAM_PIXEL);
 	struct v4l2_rect *crop =
-		v4l2_subdev_state_get_crop(sd_state, pad);
+		v4l2_subdev_state_get_crop(sd_state, pad, CCS_STREAM_PIXEL);
 
 	guard(mutex)(&sensor->mutex);
 
@@ -3119,7 +3367,8 @@ static int ccs_init_state(struct v4l2_subdev *sd,
 	if (ssd == sensor->pixel_array)
 		return 0;
 
-	fmt = v4l2_subdev_state_get_format(sd_state, CCS_PAD_SRC);
+	fmt = v4l2_subdev_state_get_format(sd_state, CCS_PAD_SRC,
+					   CCS_STREAM_PIXEL);
 	fmt->code = ssd == sensor->src ?
 		sensor->csi_format->code : sensor->internal_csi_format->code;
 	fmt->field = V4L2_FIELD_NONE;
@@ -3129,6 +3378,47 @@ static int ccs_init_state(struct v4l2_subdev *sd,
 	return 0;
 }
 
+static int ccs_src_init_state(struct v4l2_subdev *sd,
+			      struct v4l2_subdev_state *sd_state)
+{
+	struct v4l2_subdev_route routes[] = {
+		{
+			.sink_pad = CCS_PAD_SINK,
+			.source_pad = CCS_PAD_SRC,
+			.source_stream = CCS_STREAM_PIXEL,
+			.flags = V4L2_SUBDEV_ROUTE_FL_ACTIVE,
+		}, {
+			.sink_pad = CCS_PAD_META,
+			.source_pad = CCS_PAD_SRC,
+			.source_stream = CCS_STREAM_META,
+			.flags = V4L2_SUBDEV_ROUTE_FL_ACTIVE,
+		}
+	};
+	struct v4l2_subdev_krouting routing = {
+		.routes = routes,
+		.num_routes = 1,
+	};
+	struct ccs_subdev *ssd = to_ccs_subdev(sd);
+	struct ccs_sensor *sensor = ssd->sensor;
+	int rval;
+
+	if (ccs_embedded_data_lines(sensor))
+		routing.num_routes++;
+
+	rval = v4l2_subdev_set_routing(sd, sd_state, &routing);
+	if (rval)
+		return rval;
+
+	rval = ccs_init_state(sd, sd_state);
+	if (rval)
+		return rval;
+
+	if (ccs_embedded_data_lines(sensor))
+		ccs_set_format_meta(sd, sd_state, NULL);
+
+	return 0;
+}
+
 static const struct v4l2_subdev_video_ops ccs_video_ops = {
 	.s_stream = v4l2_subdev_s_stream_helper,
 	.pre_streamon = ccs_pre_streamon,
@@ -3141,6 +3431,14 @@ static const struct v4l2_subdev_pad_ops ccs_pad_ops = {
 	.set_fmt = ccs_set_format,
 	.get_selection = ccs_get_selection,
 	.set_selection = ccs_set_selection,
+};
+
+static const struct v4l2_subdev_pad_ops ccs_src_pad_ops = {
+	.enum_mbus_code = ccs_enum_mbus_code,
+	.get_fmt = ccs_get_format,
+	.set_fmt = ccs_set_format,
+	.get_selection = ccs_get_selection,
+	.set_selection = ccs_set_selection,
 	.enable_streams = ccs_enable_streams,
 	.disable_streams = ccs_disable_streams,
 	.get_frame_desc = ccs_get_frame_desc,
@@ -3157,6 +3455,12 @@ static const struct v4l2_subdev_ops ccs_ops = {
 	.sensor = &ccs_sensor_ops,
 };
 
+static const struct v4l2_subdev_ops ccs_src_ops = {
+	.video = &ccs_video_ops,
+	.pad = &ccs_src_pad_ops,
+	.sensor = &ccs_sensor_ops,
+};
+
 static const struct media_entity_operations ccs_entity_ops = {
 	.link_validate = v4l2_subdev_link_validate,
 };
@@ -3165,8 +3469,8 @@ static const struct v4l2_subdev_internal_ops ccs_internal_ops = {
 	.init_state = ccs_init_state,
 };
 
-static const struct v4l2_subdev_internal_ops ccs_internal_src_ops = {
-	.init_state = ccs_init_state,
+static const struct v4l2_subdev_internal_ops ccs_src_internal_ops = {
+	.init_state = ccs_src_init_state,
 	.registered = ccs_registered,
 	.unregistered = ccs_unregistered,
 };
@@ -3308,8 +3612,8 @@ static int ccs_probe(struct i2c_client *client)
 
 	sensor->src = &sensor->ssds[sensor->ssds_used];
 
-	v4l2_i2c_subdev_init(&sensor->src->sd, client, &ccs_ops);
-	sensor->src->sd.internal_ops = &ccs_internal_src_ops;
+	v4l2_i2c_subdev_init(&sensor->src->sd, client, &ccs_src_ops);
+	sensor->src->sd.internal_ops = &ccs_src_internal_ops;
 
 	sensor->regulators = devm_kcalloc(&client->dev,
 					  ARRAY_SIZE(ccs_regulators),
@@ -3576,12 +3880,20 @@ static int ccs_probe(struct i2c_client *client)
 		goto out_cleanup;
 	}
 
-	rval = ccs_init_subdev(sensor, sensor->scaler, " scaler", 2,
+	rval = ccs_init_subdev(sensor, sensor->scaler, " scaler",
+			       sensor->ssds_used != CCS_SUBDEVS ?
+			       CCS_PADS_NOMETA :
+			       ccs_embedded_data_lines(sensor) ?
+			       CCS_PADS : CCS_PADS_NOMETA,
 			       MEDIA_ENT_F_PROC_VIDEO_SCALER,
 			       "ccs scaler mutex", &scaler_lock_key);
 	if (rval)
 		goto out_cleanup;
-	rval = ccs_init_subdev(sensor, sensor->binner, " binner", 2,
+	rval = ccs_init_subdev(sensor, sensor->binner, " binner",
+			       sensor->ssds_used == CCS_SUBDEVS ?
+			       CCS_PADS_NOMETA :
+			       ccs_embedded_data_lines(sensor) ?
+			       CCS_PADS : CCS_PADS_NOMETA,
 			       MEDIA_ENT_F_PROC_VIDEO_SCALER,
 			       "ccs binner mutex", &binner_lock_key);
 	if (rval)
diff --git a/drivers/media/i2c/ccs/ccs.h b/drivers/media/i2c/ccs/ccs.h
index df044dbde23f..122287ab5399 100644
--- a/drivers/media/i2c/ccs/ccs.h
+++ b/drivers/media/i2c/ccs/ccs.h
@@ -176,11 +176,18 @@ struct ccs_csi_data_format {
 #define CCS_SUBDEVS			3
 
 #define CCS_PA_PAD_SRC			0
-#define CCS_PAD_SINK			0
-#define CCS_PAD_SRC			1
-#define CCS_PADS			2
+enum {
+	CCS_PAD_SINK,
+	CCS_PAD_SRC,
+	CCS_PAD_META,
+	CCS_PADS_NOMETA = CCS_PAD_META,
+	CCS_PADS,
+};
 
-#define CCS_STREAM_PIXEL		0
+enum {
+	CCS_STREAM_PIXEL,
+	CCS_STREAM_META,
+};
 
 struct ccs_binning_subtype {
 	u8 horizontal:4;
-- 
2.47.3


^ permalink raw reply related	[flat|nested] 88+ messages in thread

* [PATCH v12 46/86] media: Documentation: ccs: Document routing
  2026-04-09 20:13 [PATCH v12 00/86] Generic line based metadata support, internal pads Sakari Ailus
                   ` (44 preceding siblings ...)
  2026-04-09 20:14 ` [PATCH v12 45/86] media: ccs: Add support for embedded data stream Sakari Ailus
@ 2026-04-09 20:14 ` Sakari Ailus
  2026-04-09 20:14 ` [PATCH v12 47/86] media: ccs: Add IMMUTABLE and STATIC route flags Sakari Ailus
                   ` (39 subsequent siblings)
  85 siblings, 0 replies; 88+ messages in thread
From: Sakari Ailus @ 2026-04-09 20:14 UTC (permalink / raw)
  To: linux-media
  Cc: hans, laurent.pinchart, Prabhakar, Kate Hsuan, Dave Stevenson,
	Tommaso Merciai, Benjamin Mugnier, Sylvain Petinot,
	Christophe JAILLET, Julien Massot, Naushir Patuck, Stefan Klug,
	Mirela Rabulea, André Apitzsch, Heimir Thor Sverrisson,
	Kieran Bingham, Mehdi Djait, Ricardo Ribalda Delgado,
	Hans de Goede, Jacopo Mondi, Tomi Valkeinen, David Plowman,
	Yu, Ong Hock, Ng, Khai Wen, Jai Luthra, Rishikesh Donadkar

Document which routes are available for the CCS driver (source) sub-device
and what configuration are possible.

Also update copyright.

Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 .../userspace-api/media/drivers/ccs.rst       | 43 ++++++++++++++++++-
 .../media/v4l/metadata-layouts.rst            |  2 +
 2 files changed, 44 insertions(+), 1 deletion(-)

diff --git a/Documentation/userspace-api/media/drivers/ccs.rst b/Documentation/userspace-api/media/drivers/ccs.rst
index 03015b33d5ab..67c7d2b62ed5 100644
--- a/Documentation/userspace-api/media/drivers/ccs.rst
+++ b/Documentation/userspace-api/media/drivers/ccs.rst
@@ -111,4 +111,45 @@ than in the centre.
 Shading correction needs to be enabled for luminance correction level to have an
 effect.
 
-**Copyright** |copy| 2020 Intel Corporation
+.. _media-ccs-routes:
+
+Routes
+------
+
+The CCS driver implements one or two :ref:`routes <subdev-routing>` in
+its source sub-device (scaler sub-device if it exists for the device, otherwise
+binner) depending on whether the sensor supports embedded data. (All CCS
+compliant sensors do but the CCS driver supports preceding standards that did
+not require embedded data support, too.)
+
+The first route of the CCS source sub-device is for pixel data (sink pad
+0/stream 0 -> source pad 1/stream 0) and the second one is for embedded data
+(internal sink pad 2/stream 0 -> source pad 1/stream 1).
+
+Embedded data
+~~~~~~~~~~~~~
+
+MIPI CCS supports generation of camera sensor embedded data. The metadata layout
+used for this format on the internal sink pad is :ref:`V4L2_METADATA_LAYOUT_CCS
+<media-metadata-layout-ccs>`.
+
+The bit depth of the CCS pixel data affects how the sensor will output the
+embedded data, adding padding to align with CSI-2 bus :term:`Data Unit` for that
+particular bit depth. This is indicated by the generic metadata format on the
+source pad of the sensor's source sub-device.
+
+Devices supporting embedded data for bit depths greater than or equal to 16 may
+support more dense packing or legacy single metadata byte per data unit, or both
+of these. The supported embedded data formats can be enumerated and configured
+on stream 1 of the source pad (1) of the CCS source sub-device.
+
+The use of the denser packing results in embedded data lines being longer than
+the pixel data in data units since the data units are smaller. In bytes the
+embedded data lines are still not longer than the image data lines.
+
+The embedded data format is determined by the sub-device image data format
+configured on the source sub-device. The embedded data mbus code is only changed
+when the bit depth of the image data changes in the source pad of the source
+sub-device.
+
+**Copyright** |copy| 2020, 2024--2025 Intel Corporation
diff --git a/Documentation/userspace-api/media/v4l/metadata-layouts.rst b/Documentation/userspace-api/media/v4l/metadata-layouts.rst
index cd190f453994..0f8709f2e9af 100644
--- a/Documentation/userspace-api/media/v4l/metadata-layouts.rst
+++ b/Documentation/userspace-api/media/v4l/metadata-layouts.rst
@@ -37,3 +37,5 @@ devices that fulfill all three levels above.
 This metadata layout code is only used for "2-byte simplified tagged data
 format" (code ``0xa``) but their use may be extended further in the future, to
 cover other CCS embedded data format codes.
+
+Also see :ref:`CCS driver documentation <media-ccs-routes>`.
-- 
2.47.3


^ permalink raw reply related	[flat|nested] 88+ messages in thread

* [PATCH v12 47/86] media: ccs: Add IMMUTABLE and STATIC route flags
  2026-04-09 20:13 [PATCH v12 00/86] Generic line based metadata support, internal pads Sakari Ailus
                   ` (45 preceding siblings ...)
  2026-04-09 20:14 ` [PATCH v12 46/86] media: Documentation: ccs: Document routing Sakari Ailus
@ 2026-04-09 20:14 ` Sakari Ailus
  2026-04-09 20:14 ` [PATCH v12 48/86] media: uapi: Add metadata layout for ov2740 embedded data Sakari Ailus
                   ` (38 subsequent siblings)
  85 siblings, 0 replies; 88+ messages in thread
From: Sakari Ailus @ 2026-04-09 20:14 UTC (permalink / raw)
  To: linux-media
  Cc: hans, laurent.pinchart, Prabhakar, Kate Hsuan, Dave Stevenson,
	Tommaso Merciai, Benjamin Mugnier, Sylvain Petinot,
	Christophe JAILLET, Julien Massot, Naushir Patuck, Stefan Klug,
	Mirela Rabulea, André Apitzsch, Heimir Thor Sverrisson,
	Kieran Bingham, Mehdi Djait, Ricardo Ribalda Delgado,
	Hans de Goede, Jacopo Mondi, Tomi Valkeinen, David Plowman,
	Yu, Ong Hock, Ng, Khai Wen, Jai Luthra, Rishikesh Donadkar

Add immutable and static route flags to the routing table. The embedded
data stream is always there.

Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
Reviewed-by: Julien Massot <julien.massot@collabora.com>
Reviewed-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
 drivers/media/i2c/ccs/ccs-core.c | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/drivers/media/i2c/ccs/ccs-core.c b/drivers/media/i2c/ccs/ccs-core.c
index c4fe400d1cef..af68aa68897c 100644
--- a/drivers/media/i2c/ccs/ccs-core.c
+++ b/drivers/media/i2c/ccs/ccs-core.c
@@ -3386,12 +3386,16 @@ static int ccs_src_init_state(struct v4l2_subdev *sd,
 			.sink_pad = CCS_PAD_SINK,
 			.source_pad = CCS_PAD_SRC,
 			.source_stream = CCS_STREAM_PIXEL,
-			.flags = V4L2_SUBDEV_ROUTE_FL_ACTIVE,
+			.flags = V4L2_SUBDEV_ROUTE_FL_ACTIVE |
+				 V4L2_SUBDEV_ROUTE_FL_IMMUTABLE	|
+				 V4L2_SUBDEV_ROUTE_FL_STATIC,
 		}, {
 			.sink_pad = CCS_PAD_META,
 			.source_pad = CCS_PAD_SRC,
 			.source_stream = CCS_STREAM_META,
-			.flags = V4L2_SUBDEV_ROUTE_FL_ACTIVE,
+			.flags = V4L2_SUBDEV_ROUTE_FL_ACTIVE |
+				 V4L2_SUBDEV_ROUTE_FL_IMMUTABLE	|
+				 V4L2_SUBDEV_ROUTE_FL_STATIC,
 		}
 	};
 	struct v4l2_subdev_krouting routing = {
-- 
2.47.3


^ permalink raw reply related	[flat|nested] 88+ messages in thread

* [PATCH v12 48/86] media: uapi: Add metadata layout for ov2740 embedded data
  2026-04-09 20:13 [PATCH v12 00/86] Generic line based metadata support, internal pads Sakari Ailus
                   ` (46 preceding siblings ...)
  2026-04-09 20:14 ` [PATCH v12 47/86] media: ccs: Add IMMUTABLE and STATIC route flags Sakari Ailus
@ 2026-04-09 20:14 ` Sakari Ailus
  2026-04-09 20:14 ` [PATCH v12 49/86] media: ov2740: Add support for " Sakari Ailus
                   ` (37 subsequent siblings)
  85 siblings, 0 replies; 88+ messages in thread
From: Sakari Ailus @ 2026-04-09 20:14 UTC (permalink / raw)
  To: linux-media
  Cc: hans, laurent.pinchart, Prabhakar, Kate Hsuan, Dave Stevenson,
	Tommaso Merciai, Benjamin Mugnier, Sylvain Petinot,
	Christophe JAILLET, Julien Massot, Naushir Patuck, Stefan Klug,
	Mirela Rabulea, André Apitzsch, Heimir Thor Sverrisson,
	Kieran Bingham, Mehdi Djait, Ricardo Ribalda Delgado,
	Hans de Goede, Jacopo Mondi, Tomi Valkeinen, David Plowman,
	Yu, Ong Hock, Ng, Khai Wen, Jai Luthra, Rishikesh Donadkar

Add a metadata layout for ov2740 camera sensor embedded data and document
it.

Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
Reviewed-by: Julien Massot <julien.massot@collabora.com>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 .../media/v4l/ext-ctrls-image-source.rst      |  3 +
 .../media/v4l/metadata-layouts.rst            | 73 +++++++++++++++++++
 include/uapi/linux/v4l2-controls.h            |  1 +
 3 files changed, 77 insertions(+)

diff --git a/Documentation/userspace-api/media/v4l/ext-ctrls-image-source.rst b/Documentation/userspace-api/media/v4l/ext-ctrls-image-source.rst
index 4ed9bea89101..bf208de8e626 100644
--- a/Documentation/userspace-api/media/v4l/ext-ctrls-image-source.rst
+++ b/Documentation/userspace-api/media/v4l/ext-ctrls-image-source.rst
@@ -172,6 +172,9 @@ Image Source Control IDs
     * - V4L2_METADATA_LAYOUT_CCS
       - :ref:`CCS embedded data <media-metadata-layout-ccs>`
       - 1
+    * - V4L2_METADATA_LAYOUT_OV2740
+      - :ref:`OV2740 embedded data <media-metadata-layout-ov2740>`
+      - 2
 
 .. _image_source_control_binning_factors:
 
diff --git a/Documentation/userspace-api/media/v4l/metadata-layouts.rst b/Documentation/userspace-api/media/v4l/metadata-layouts.rst
index 0f8709f2e9af..b4d04d82662b 100644
--- a/Documentation/userspace-api/media/v4l/metadata-layouts.rst
+++ b/Documentation/userspace-api/media/v4l/metadata-layouts.rst
@@ -39,3 +39,76 @@ format" (code ``0xa``) but their use may be extended further in the future, to
 cover other CCS embedded data format codes.
 
 Also see :ref:`CCS driver documentation <media-ccs-routes>`.
+
+.. _media-metadata-layout-ov2740:
+
+Omnivision OV2740 Embedded Data Layout (``V4L2_METADATA_LAYOUT_OV2740``)
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+The Omnivision OV2740 camera sensor produces the following embedded data layout,
+indicated by ``V4L2_METADATA_LAYOUT_OV2740`` metadata layout. The format
+conforms to :ref:`CCS embedded data layout <media-metadata-layout-ccs>` up to
+level 1.
+
+.. flat-table:: Omnivision OV2740 Embedded Data Layout. Octets at indices marked
+                reserved or unused have been omitted from the table. The values
+                are in big endian byte order.
+    :header-rows: 1
+
+    * - Offset
+      - Size in bits (active bits if not the same as size)
+      - Content description
+    * - 4
+      - 16 (10--0)
+      - Analogue gain
+    * - 6
+      - 16
+      - Coarse integration time
+    * - 10
+      - 8
+      - DPC correction threshold bits 9--2
+    * - 15
+      - 16
+      - Output image width
+    * - 17
+      - 16
+      - Output image height
+    * - 23
+      - 8
+      - MIPI header revision number (2)
+    * - 31
+      - 8
+      - Vertical (bit 1) and horizontal flip (bit 0)
+    * - 32
+      - 8
+      - Frame duration A
+    * - 33
+      - 8
+      - Frame duration B
+    * - 34
+      - 8
+      - Context count (2)
+    * - 35
+      - 8
+      - Context select
+    * - 54
+      - 8
+      - Data pedestal bits 9--2
+    * - 63
+      - 8
+      - Frame average bits 9--2
+    * - 64
+      - 16
+      - Digital gain red
+    * - 66
+      - 16
+      - Digital gain greenr
+    * - 68
+      - 16
+      - Digital gain blue
+    * - 70
+      - 16
+      - Digital gain greenb
+    * - 89
+      - 8
+      - Frame counter (starts at 1, wraps to 0 after 255)
diff --git a/include/uapi/linux/v4l2-controls.h b/include/uapi/linux/v4l2-controls.h
index e27a7ad47c51..b2f1ffd7071c 100644
--- a/include/uapi/linux/v4l2-controls.h
+++ b/include/uapi/linux/v4l2-controls.h
@@ -1249,6 +1249,7 @@ enum v4l2_jpeg_chroma_subsampling {
 
 #define V4L2_CID_METADATA_LAYOUT		(V4L2_CID_IMAGE_SOURCE_CLASS_BASE + 12)
 #define V4L2_METADATA_LAYOUT_CCS		1U
+#define V4L2_METADATA_LAYOUT_OV2740		2U
 
 #define V4L2_CID_BINNING_FACTORS		(V4L2_CID_IMAGE_SOURCE_CLASS_BASE + 13)
 #define V4L2_BINNING_FACTORS_MAKE(hnum, hdem, vnum, vdem)		\
-- 
2.47.3


^ permalink raw reply related	[flat|nested] 88+ messages in thread

* [PATCH v12 49/86] media: ov2740: Add support for embedded data
  2026-04-09 20:13 [PATCH v12 00/86] Generic line based metadata support, internal pads Sakari Ailus
                   ` (47 preceding siblings ...)
  2026-04-09 20:14 ` [PATCH v12 48/86] media: uapi: Add metadata layout for ov2740 embedded data Sakari Ailus
@ 2026-04-09 20:14 ` Sakari Ailus
  2026-04-09 20:14 ` [PATCH v12 50/86] media: ov2740: Add support for generic raw formats Sakari Ailus
                   ` (36 subsequent siblings)
  85 siblings, 0 replies; 88+ messages in thread
From: Sakari Ailus @ 2026-04-09 20:14 UTC (permalink / raw)
  To: linux-media
  Cc: hans, laurent.pinchart, Prabhakar, Kate Hsuan, Dave Stevenson,
	Tommaso Merciai, Benjamin Mugnier, Sylvain Petinot,
	Christophe JAILLET, Julien Massot, Naushir Patuck, Stefan Klug,
	Mirela Rabulea, André Apitzsch, Heimir Thor Sverrisson,
	Kieran Bingham, Mehdi Djait, Ricardo Ribalda Delgado,
	Hans de Goede, Jacopo Mondi, Tomi Valkeinen, David Plowman,
	Yu, Ong Hock, Ng, Khai Wen, Jai Luthra, Rishikesh Donadkar

Add support for embedded data. This introduces two internal pads for pixel
and embedded data streams. As the driver supports a single mode only,
there's no need for backward compatibility in mode selection.

The embedded data is configured to be placed before the image data whereas
after the image data is the default.

This patch includes switching to {enable,disable}_streams as well.

Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
---
 drivers/media/i2c/ov2740.c | 266 ++++++++++++++++++++++++++++---------
 1 file changed, 205 insertions(+), 61 deletions(-)

diff --git a/drivers/media/i2c/ov2740.c b/drivers/media/i2c/ov2740.c
index 4023b5b7ca82..b3d0c7e81585 100644
--- a/drivers/media/i2c/ov2740.c
+++ b/drivers/media/i2c/ov2740.c
@@ -12,6 +12,7 @@
 #include <linux/regmap.h>
 #include <linux/regulator/consumer.h>
 #include <linux/unaligned.h>
+#include <media/mipi-csi2.h>
 #include <media/v4l2-ctrls.h>
 #include <media/v4l2-device.h>
 #include <media/v4l2-fwnode.h>
@@ -23,6 +24,11 @@
 #define OV2740_DATA_LANES		2
 #define OV2740_RGB_DEPTH		10
 
+#define OV2740_CROP_TOP			4U
+#define OV2740_CROP_LEFT		4U
+#define OV2740_ACTIVE_WIDTH		1936U
+#define OV2740_ACTIVE_HEIGHT		1096U
+
 #define OV2740_REG_CHIP_ID		0x300a
 #define OV2740_CHIP_ID			0x2740
 
@@ -72,6 +78,15 @@
 #define OV2740_REG_ISP_CTRL00		0x5000
 /* ISP CTRL01 */
 #define OV2740_REG_ISP_CTRL01		0x5001
+
+/* Embedded data line location control */
+#define OV2740_REG_EMBEDDED_FLAG	0x5a08
+#define OV2740_EMBEDDED_FLAG_FOOTER	BIT(2) /* otherwise it's in header */
+#define OV2740_EMBEDDED_FLAG_MYSTERY	BIT(1)
+#define OV2740_REG_EMBEDDED_DT		0x3036
+#define OV2740_REG_EMBEDDED_CTRL	0x4307
+#define OV2740_EMBEDDED_CTRL_MYSTERY	0x30
+#define OV2740_EMBEDDED_CTRL_ENABLE	BIT(0)
 /* Customer Addresses: 0x7010 - 0x710F */
 #define CUSTOMER_USE_OTP_SIZE		0x100
 /* OTP registers from sensor */
@@ -83,6 +98,21 @@ static const char * const ov2740_supply_name[] = {
 	"DVDD",
 };
 
+enum {
+	OV2740_PAD_SOURCE,
+	OV2740_PAD_PIXEL,
+	OV2740_PAD_META,
+	OV2740_NUM_PADS,
+};
+
+enum {
+	OV2740_STREAM_PIXEL,
+	OV2740_STREAM_META,
+};
+
+#define OV2740_META_WIDTH		100U
+#define OV2740_META_HEIGHT		1U
+
 struct nvm_data {
 	struct nvmem_device *nvmem;
 	struct regmap *regmap;
@@ -156,6 +186,7 @@ static const struct ov2740_reg mode_1932x1092_regs_360mhz[] = {
 	{0x3000, 0x00},
 	{0x3018, 0x32},
 	{0x3031, 0x0a},
+	{OV2740_REG_EMBEDDED_DT, MIPI_CSI2_DT_EMBEDDED_8B},
 	{0x3080, 0x08},
 	{0x3083, 0xB4},
 	{0x3103, 0x00},
@@ -260,7 +291,8 @@ static const struct ov2740_reg mode_1932x1092_regs_360mhz[] = {
 	{0x4017, 0x10},
 	{0x4044, 0x02},
 	{0x4304, 0x08},
-	{0x4307, 0x30},
+	{OV2740_REG_EMBEDDED_CTRL,
+	 OV2740_EMBEDDED_CTRL_MYSTERY | OV2740_EMBEDDED_CTRL_ENABLE},
 	{0x4320, 0x80},
 	{0x4322, 0x00},
 	{0x4323, 0x00},
@@ -309,6 +341,7 @@ static const struct ov2740_reg mode_1932x1092_regs_180mhz[] = {
 	{0x3000, 0x00},
 	{0x3018, 0x32},	/* 0x32 for 2 lanes, 0x12 for 1 lane */
 	{0x3031, 0x0a},
+	{OV2740_REG_EMBEDDED_DT, MIPI_CSI2_DT_EMBEDDED_8B},
 	{0x3080, 0x08},
 	{0x3083, 0xB4},
 	{0x3103, 0x00},
@@ -413,7 +446,8 @@ static const struct ov2740_reg mode_1932x1092_regs_180mhz[] = {
 	{0x4017, 0x10},
 	{0x4044, 0x02},
 	{0x4304, 0x08},
-	{0x4307, 0x30},
+	{OV2740_REG_EMBEDDED_CTRL,
+	 OV2740_EMBEDDED_CTRL_MYSTERY | OV2740_EMBEDDED_CTRL_ENABLE},
 	{0x4320, 0x80},
 	{0x4322, 0x00},
 	{0x4323, 0x00},
@@ -522,7 +556,7 @@ struct ov2740 {
 	struct device *dev;
 
 	struct v4l2_subdev sd;
-	struct media_pad pad;
+	struct media_pad pads[OV2740_NUM_PADS];
 	struct v4l2_ctrl_handler ctrl_handler;
 
 	/* V4L2 Controls */
@@ -550,6 +584,9 @@ struct ov2740 {
 
 	/* True if the device has been identified */
 	bool identified;
+
+	/* Track streaming state */
+	u8 streaming;
 };
 
 static inline struct ov2740 *to_ov2740(struct v4l2_subdev *subdev)
@@ -837,15 +874,6 @@ static int ov2740_init_controls(struct ov2740 *ov2740)
 	return 0;
 }
 
-static void ov2740_update_pad_format(const struct ov2740_mode *mode,
-				     struct v4l2_mbus_framefmt *fmt)
-{
-	fmt->width = mode->width;
-	fmt->height = mode->height;
-	fmt->code = MEDIA_BUS_FMT_SGRBG10_1X10;
-	fmt->field = V4L2_FIELD_NONE;
-}
-
 static int ov2740_load_otp_data(struct nvm_data *nvm)
 {
 	struct device *dev = regmap_get_device(nvm->regmap);
@@ -936,15 +964,27 @@ static int ov2740_load_otp_data(struct nvm_data *nvm)
 	return ret;
 }
 
-static int ov2740_start_streaming(struct ov2740 *ov2740)
+static int ov2740_enable_streams(struct v4l2_subdev *sd,
+				 struct v4l2_subdev_state *state, u32 pad,
+				 u64 streams_mask)
 {
+	struct ov2740 *ov2740 = to_ov2740(sd);
 	const struct ov2740_reg_list *reg_list;
 	int link_freq_index;
 	int ret;
 
+	if (ov2740->streaming) {
+		ov2740->streaming |= streams_mask;
+		return 0;
+	}
+
+	ret = pm_runtime_resume_and_get(ov2740->dev);
+	if (ret < 0)
+		return ret;
+
 	ret = ov2740_identify_module(ov2740);
 	if (ret)
-		return ret;
+		goto out_pm_put;
 
 	if (ov2740->nvm)
 		ov2740_load_otp_data(ov2740->nvm);
@@ -953,7 +993,7 @@ static int ov2740_start_streaming(struct ov2740 *ov2740)
 	ret = ov2740_write_reg(ov2740, 0x0103, 1, 0x01);
 	if (ret) {
 		dev_err(ov2740->dev, "failed to reset\n");
-		return ret;
+		goto out_pm_put;
 	}
 
 	usleep_range(10000, 15000);
@@ -963,83 +1003,101 @@ static int ov2740_start_streaming(struct ov2740 *ov2740)
 	ret = ov2740_write_reg_list(ov2740, reg_list);
 	if (ret) {
 		dev_err(ov2740->dev, "failed to set plls\n");
-		return ret;
+		goto out_pm_put;
 	}
 
 	reg_list = &ov2740->cur_mode->reg_list;
 	ret = ov2740_write_reg_list(ov2740, reg_list);
 	if (ret) {
 		dev_err(ov2740->dev, "failed to set mode\n");
-		return ret;
+		goto out_pm_put;
 	}
 
 	ret = __v4l2_ctrl_handler_setup(ov2740->sd.ctrl_handler);
 	if (ret)
-		return ret;
+		goto out_pm_put;
+
+	ret = ov2740_write_reg(ov2740, OV2740_REG_EMBEDDED_FLAG, 1,
+			       OV2740_EMBEDDED_FLAG_MYSTERY);
+	if (ret)
+		goto out_pm_put;
 
 	ret = ov2740_write_reg(ov2740, OV2740_REG_MODE_SELECT, 1,
 			       OV2740_MODE_STREAMING);
-	if (ret)
+	if (ret) {
 		dev_err(ov2740->dev, "failed to start streaming\n");
+		goto out_pm_put;
+	}
 
-	return ret;
-}
+	ov2740->streaming |= streams_mask;
 
-static void ov2740_stop_streaming(struct ov2740 *ov2740)
-{
-	if (ov2740_write_reg(ov2740, OV2740_REG_MODE_SELECT, 1,
-			     OV2740_MODE_STANDBY))
-		dev_err(ov2740->dev, "failed to stop streaming\n");
+	return 0;
+
+out_pm_put:
+	pm_runtime_put(ov2740->dev);
+
+	return ret;
 }
 
-static int ov2740_set_stream(struct v4l2_subdev *sd, int enable)
+static int ov2740_disable_streams(struct v4l2_subdev *sd,
+				  struct v4l2_subdev_state *state, u32 pad,
+				  u64 streams_mask)
 {
 	struct ov2740 *ov2740 = to_ov2740(sd);
-	struct v4l2_subdev_state *sd_state;
-	int ret = 0;
-
-	sd_state = v4l2_subdev_lock_and_get_active_state(&ov2740->sd);
+	int ret;
 
-	if (enable) {
-		ret = pm_runtime_resume_and_get(ov2740->dev);
-		if (ret < 0)
-			goto out_unlock;
+	ov2740->streaming &= ~streams_mask;
+	if (ov2740->streaming)
+		return 0;
 
-		ret = ov2740_start_streaming(ov2740);
-		if (ret) {
-			enable = 0;
-			ov2740_stop_streaming(ov2740);
-			pm_runtime_put(ov2740->dev);
-		}
-	} else {
-		ov2740_stop_streaming(ov2740);
-		pm_runtime_put(ov2740->dev);
-	}
+	ret = ov2740_write_reg(ov2740, OV2740_REG_MODE_SELECT, 1,
+			       OV2740_MODE_STANDBY);
 
-out_unlock:
-	v4l2_subdev_unlock_state(sd_state);
+	pm_runtime_put(ov2740->dev);
 
 	return ret;
 }
 
-static int ov2740_set_format(struct v4l2_subdev *sd,
-			     const struct v4l2_subdev_client_info *ci,
-			     struct v4l2_subdev_state *sd_state,
-			     struct v4l2_subdev_format *fmt)
+static int __ov2740_set_format(struct v4l2_subdev *sd,
+			       struct v4l2_subdev_state *sd_state,
+			       struct v4l2_mbus_framefmt *format,
+			       enum v4l2_subdev_format_whence which,
+			       unsigned int pad, unsigned int stream)
 {
+	struct v4l2_mbus_framefmt *src_pix_fmt, *src_meta_fmt, *meta_fmt;
 	struct ov2740 *ov2740 = to_ov2740(sd);
 	const struct ov2740_mode *mode;
 	s32 vblank_def, h_blank;
 
+	/*
+	 * Allow setting format on internal pixel pad as well as the source
+	 * pad's pixel stream (for compatibility).
+	 */
+	if ((pad == OV2740_PAD_SOURCE && stream == OV2740_STREAM_META) ||
+	    pad == OV2740_PAD_META) {
+		*format = *v4l2_subdev_state_get_format(sd_state, pad, stream);
+		return 0;
+	}
+
+	meta_fmt = v4l2_subdev_state_get_format(sd_state, OV2740_PAD_META, 0);
+	src_pix_fmt = v4l2_subdev_state_get_format(sd_state, OV2740_PAD_SOURCE,
+						   OV2740_STREAM_PIXEL);
+	src_meta_fmt = v4l2_subdev_state_get_format(sd_state, OV2740_PAD_SOURCE,
+						    OV2740_STREAM_META);
+
 	mode = v4l2_find_nearest_size(ov2740->supported_modes,
 				      ov2740->supported_modes_count,
 				      width, height,
-				      fmt->format.width, fmt->format.height);
+				      format->width, format->height);
+
+	src_pix_fmt->code = format->code;
+	src_pix_fmt->width = mode->width;
+	src_pix_fmt->height = mode->height;
 
-	ov2740_update_pad_format(mode, &fmt->format);
-	*v4l2_subdev_state_get_format(sd_state, fmt->pad) = fmt->format;
+	*format = *src_pix_fmt;
+	*src_meta_fmt = *meta_fmt;
 
-	if (fmt->which == V4L2_SUBDEV_FORMAT_TRY)
+	if (which == V4L2_SUBDEV_FORMAT_TRY)
 		return 0;
 
 	ov2740->cur_mode = mode;
@@ -1059,6 +1117,15 @@ static int ov2740_set_format(struct v4l2_subdev *sd,
 	return 0;
 }
 
+static int ov2740_set_format(struct v4l2_subdev *sd,
+			     const struct v4l2_subdev_client_info *ci,
+			     struct v4l2_subdev_state *sd_state,
+			     struct v4l2_subdev_format *fmt)
+{
+	return __ov2740_set_format(sd, sd_state, &fmt->format, fmt->which,
+				   fmt->pad, fmt->stream);
+}
+
 static int ov2740_enum_mbus_code(struct v4l2_subdev *sd,
 				 struct v4l2_subdev_state *sd_state,
 				 struct v4l2_subdev_mbus_code_enum *code)
@@ -1095,15 +1162,84 @@ static int ov2740_enum_frame_size(struct v4l2_subdev *sd,
 static int ov2740_init_state(struct v4l2_subdev *sd,
 			     struct v4l2_subdev_state *sd_state)
 {
+	struct v4l2_subdev_route routes[] = {
+		{
+			.sink_pad = OV2740_PAD_PIXEL,
+			.source_pad = OV2740_PAD_SOURCE,
+			.source_stream = OV2740_STREAM_PIXEL,
+			.flags = V4L2_SUBDEV_ROUTE_FL_ACTIVE,
+		}, {
+			.sink_pad = OV2740_PAD_META,
+			.source_pad = OV2740_PAD_SOURCE,
+			.source_stream = OV2740_STREAM_META,
+			.flags = V4L2_SUBDEV_ROUTE_FL_ACTIVE,
+		},
+	};
+	struct v4l2_subdev_krouting routing = {
+		.routes = routes,
+		.num_routes = ARRAY_SIZE(routes),
+	};
 	struct ov2740 *ov2740 = to_ov2740(sd);
+	int ret;
+
+	ret = v4l2_subdev_set_routing(sd, sd_state, &routing);
+	if (ret)
+		return ret;
+
+	struct v4l2_subdev_state *active_state =
+		v4l2_subdev_get_locked_active_state(sd);
+	struct v4l2_mbus_framefmt *pix_fmt =
+		v4l2_subdev_state_get_format(sd_state, OV2740_PAD_PIXEL, 0);
+
+	pix_fmt->code = MEDIA_BUS_FMT_RAW_10;
+	pix_fmt->width = OV2740_CROP_LEFT + OV2740_ACTIVE_WIDTH;
+	pix_fmt->height = OV2740_CROP_TOP + OV2740_ACTIVE_HEIGHT;
+	pix_fmt->field = V4L2_FIELD_NONE;
+
+	struct v4l2_mbus_framefmt *meta_fmt =
+		v4l2_subdev_state_get_format(sd_state, OV2740_PAD_META, 0);
+
+	meta_fmt->code = MEDIA_BUS_FMT_META_10;
+	meta_fmt->width = OV2740_META_WIDTH;
+	meta_fmt->height = OV2740_META_HEIGHT;
+
+	return __ov2740_set_format(sd, sd_state, pix_fmt,
+				   active_state == sd_state ?
+				   V4L2_SUBDEV_FORMAT_ACTIVE :
+				   V4L2_SUBDEV_FORMAT_TRY, OV2740_PAD_PIXEL, 0);
+}
+
+static int ov2740_get_frame_desc(struct v4l2_subdev *sd, unsigned int pad,
+				 struct v4l2_mbus_frame_desc *desc)
+{
+	struct v4l2_mbus_frame_desc_entry *entry = desc->entry;
+	struct v4l2_subdev_state *sd_state;
+	struct v4l2_mbus_framefmt *fmt;
+
+	desc->type = V4L2_MBUS_FRAME_DESC_TYPE_CSI2;
+
+	sd_state = v4l2_subdev_lock_and_get_active_state(sd);
+	fmt = v4l2_subdev_state_get_format(sd_state, OV2740_PAD_SOURCE,
+					   OV2740_STREAM_PIXEL);
+	entry->pixelcode = fmt->code;
+	v4l2_subdev_unlock_state(sd_state);
+
+	entry->stream = OV2740_STREAM_PIXEL;
+	entry->bus.csi2.dt = MIPI_CSI2_DT_RAW10;
+	entry++;
+	desc->num_entries++;
+
+	entry->pixelcode = MEDIA_BUS_FMT_META_10;
+	entry->stream = OV2740_STREAM_META;
+	entry->bus.csi2.dt = MIPI_CSI2_DT_EMBEDDED_8B;
+	entry++;
+	desc->num_entries++;
 
-	ov2740_update_pad_format(&ov2740->supported_modes[0],
-				 v4l2_subdev_state_get_format(sd_state, 0));
 	return 0;
 }
 
 static const struct v4l2_subdev_video_ops ov2740_video_ops = {
-	.s_stream = ov2740_set_stream,
+	.s_stream = v4l2_subdev_s_stream_helper,
 };
 
 static const struct v4l2_subdev_pad_ops ov2740_pad_ops = {
@@ -1111,6 +1247,9 @@ static const struct v4l2_subdev_pad_ops ov2740_pad_ops = {
 	.set_fmt = ov2740_set_format,
 	.enum_mbus_code = ov2740_enum_mbus_code,
 	.enum_frame_size = ov2740_enum_frame_size,
+	.enable_streams = ov2740_enable_streams,
+	.disable_streams = ov2740_disable_streams,
+	.get_frame_desc = ov2740_get_frame_desc,
 };
 
 static const struct v4l2_subdev_ops ov2740_subdev_ops = {
@@ -1407,11 +1546,16 @@ static int ov2740_probe(struct i2c_client *client)
 	}
 
 	ov2740->sd.state_lock = ov2740->ctrl_handler.lock;
-	ov2740->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
+	ov2740->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE | V4L2_SUBDEV_FL_STREAMS;
 	ov2740->sd.entity.ops = &ov2740_subdev_entity_ops;
 	ov2740->sd.entity.function = MEDIA_ENT_F_CAM_SENSOR;
-	ov2740->pad.flags = MEDIA_PAD_FL_SOURCE;
-	ret = media_entity_pads_init(&ov2740->sd.entity, 1, &ov2740->pad);
+	ov2740->pads[OV2740_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE;
+	ov2740->pads[OV2740_PAD_PIXEL].flags =
+		MEDIA_PAD_FL_SINK | MEDIA_PAD_FL_INTERNAL;
+	ov2740->pads[OV2740_PAD_META].flags =
+		MEDIA_PAD_FL_SINK | MEDIA_PAD_FL_INTERNAL;
+	ret = media_entity_pads_init(&ov2740->sd.entity,
+				     ARRAY_SIZE(ov2740->pads), ov2740->pads);
 	if (ret) {
 		dev_err_probe(dev, ret, "failed to init entity pads\n");
 		goto probe_error_v4l2_ctrl_handler_free;
-- 
2.47.3


^ permalink raw reply related	[flat|nested] 88+ messages in thread

* [PATCH v12 50/86] media: ov2740: Add support for generic raw formats
  2026-04-09 20:13 [PATCH v12 00/86] Generic line based metadata support, internal pads Sakari Ailus
                   ` (48 preceding siblings ...)
  2026-04-09 20:14 ` [PATCH v12 49/86] media: ov2740: Add support for " Sakari Ailus
@ 2026-04-09 20:14 ` Sakari Ailus
  2026-04-09 20:14 ` [PATCH v12 51/86] media: ov2740: Add metadata layout control Sakari Ailus
                   ` (35 subsequent siblings)
  85 siblings, 0 replies; 88+ messages in thread
From: Sakari Ailus @ 2026-04-09 20:14 UTC (permalink / raw)
  To: linux-media
  Cc: hans, laurent.pinchart, Prabhakar, Kate Hsuan, Dave Stevenson,
	Tommaso Merciai, Benjamin Mugnier, Sylvain Petinot,
	Christophe JAILLET, Julien Massot, Naushir Patuck, Stefan Klug,
	Mirela Rabulea, André Apitzsch, Heimir Thor Sverrisson,
	Kieran Bingham, Mehdi Djait, Ricardo Ribalda Delgado,
	Hans de Goede, Jacopo Mondi, Tomi Valkeinen, David Plowman,
	Yu, Ong Hock, Ng, Khai Wen, Jai Luthra, Rishikesh Donadkar

Add RAW_10 media bus code and V4L2_CID_CFA_PATTERN as well as
V4L2_CID_CFA_PATTERN_FLIP control support.

Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
---
 drivers/media/i2c/ov2740.c | 23 +++++++++++++++++++----
 1 file changed, 19 insertions(+), 4 deletions(-)

diff --git a/drivers/media/i2c/ov2740.c b/drivers/media/i2c/ov2740.c
index b3d0c7e81585..cc9cd7ccbf1f 100644
--- a/drivers/media/i2c/ov2740.c
+++ b/drivers/media/i2c/ov2740.c
@@ -807,7 +807,7 @@ static int ov2740_init_controls(struct ov2740 *ov2740)
 	int ret;
 
 	ctrl_hdlr = &ov2740->ctrl_handler;
-	ret = v4l2_ctrl_handler_init(ctrl_hdlr, 10);
+	ret = v4l2_ctrl_handler_init(ctrl_hdlr, 12);
 	if (ret)
 		return ret;
 
@@ -855,6 +855,13 @@ static int ov2740_init_controls(struct ov2740 *ov2740)
 				     V4L2_CID_TEST_PATTERN,
 				     ARRAY_SIZE(ov2740_test_pattern_menu) - 1,
 				     0, 0, ov2740_test_pattern_menu);
+	v4l2_ctrl_new_std(ctrl_hdlr, NULL, V4L2_CID_CFA_PATTERN,
+			  V4L2_CFA_PATTERN_GRBG, V4L2_CFA_PATTERN_GRBG,
+			  1, V4L2_CFA_PATTERN_GRBG);
+	v4l2_ctrl_new_std(ctrl_hdlr, NULL,
+			  V4L2_CID_CFA_PATTERN_FLIP,
+			  0, V4L2_CFA_PATTERN_FLIP_BOTH,
+			  0, V4L2_CFA_PATTERN_FLIP_BOTH);
 
 	ret = v4l2_fwnode_device_parse(ov2740->dev, &props);
 	if (ret) {
@@ -1090,6 +1097,9 @@ static int __ov2740_set_format(struct v4l2_subdev *sd,
 				      width, height,
 				      format->width, format->height);
 
+	if (format->code != MEDIA_BUS_FMT_RAW_10)
+		format->code = MEDIA_BUS_FMT_SGRBG10_1X10;
+
 	src_pix_fmt->code = format->code;
 	src_pix_fmt->width = mode->width;
 	src_pix_fmt->height = mode->height;
@@ -1130,10 +1140,14 @@ static int ov2740_enum_mbus_code(struct v4l2_subdev *sd,
 				 struct v4l2_subdev_state *sd_state,
 				 struct v4l2_subdev_mbus_code_enum *code)
 {
-	if (code->index > 0)
+	const u32 codes[] = {
+		MEDIA_BUS_FMT_SGRBG10_1X10,
+		MEDIA_BUS_FMT_RAW_10,
+	};
+	if (code->index >= ARRAY_SIZE(codes))
 		return -EINVAL;
 
-	code->code = MEDIA_BUS_FMT_SGRBG10_1X10;
+	code->code = codes[code->index];
 
 	return 0;
 }
@@ -1148,7 +1162,8 @@ static int ov2740_enum_frame_size(struct v4l2_subdev *sd,
 	if (fse->index >= ov2740->supported_modes_count)
 		return -EINVAL;
 
-	if (fse->code != MEDIA_BUS_FMT_SGRBG10_1X10)
+	if (fse->code != MEDIA_BUS_FMT_SGRBG10_1X10 &&
+	    fse->code != MEDIA_BUS_FMT_RAW_10)
 		return -EINVAL;
 
 	fse->min_width = supported_modes[fse->index].width;
-- 
2.47.3


^ permalink raw reply related	[flat|nested] 88+ messages in thread

* [PATCH v12 51/86] media: ov2740: Add metadata layout control
  2026-04-09 20:13 [PATCH v12 00/86] Generic line based metadata support, internal pads Sakari Ailus
                   ` (49 preceding siblings ...)
  2026-04-09 20:14 ` [PATCH v12 50/86] media: ov2740: Add support for generic raw formats Sakari Ailus
@ 2026-04-09 20:14 ` Sakari Ailus
  2026-04-09 20:14 ` [PATCH v12 52/86] media: ov2740: Add support for G_SELECTION IOCTL Sakari Ailus
                   ` (34 subsequent siblings)
  85 siblings, 0 replies; 88+ messages in thread
From: Sakari Ailus @ 2026-04-09 20:14 UTC (permalink / raw)
  To: linux-media
  Cc: hans, laurent.pinchart, Prabhakar, Kate Hsuan, Dave Stevenson,
	Tommaso Merciai, Benjamin Mugnier, Sylvain Petinot,
	Christophe JAILLET, Julien Massot, Naushir Patuck, Stefan Klug,
	Mirela Rabulea, André Apitzsch, Heimir Thor Sverrisson,
	Kieran Bingham, Mehdi Djait, Ricardo Ribalda Delgado,
	Hans de Goede, Jacopo Mondi, Tomi Valkeinen, David Plowman,
	Yu, Ong Hock, Ng, Khai Wen, Jai Luthra, Rishikesh Donadkar

Add the V4L2_CID_METADATA_LAYOUT control to the sub-device's control
handler, to convey the metadata layout for the sensor-generated embedded
data.

Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
---
 drivers/media/i2c/ov2740.c | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/drivers/media/i2c/ov2740.c b/drivers/media/i2c/ov2740.c
index cc9cd7ccbf1f..3308c51933aa 100644
--- a/drivers/media/i2c/ov2740.c
+++ b/drivers/media/i2c/ov2740.c
@@ -807,7 +807,7 @@ static int ov2740_init_controls(struct ov2740 *ov2740)
 	int ret;
 
 	ctrl_hdlr = &ov2740->ctrl_handler;
-	ret = v4l2_ctrl_handler_init(ctrl_hdlr, 12);
+	ret = v4l2_ctrl_handler_init(ctrl_hdlr, 13);
 	if (ret)
 		return ret;
 
@@ -862,6 +862,9 @@ static int ov2740_init_controls(struct ov2740 *ov2740)
 			  V4L2_CID_CFA_PATTERN_FLIP,
 			  0, V4L2_CFA_PATTERN_FLIP_BOTH,
 			  0, V4L2_CFA_PATTERN_FLIP_BOTH);
+	v4l2_ctrl_new_std(ctrl_hdlr, NULL, V4L2_CID_METADATA_LAYOUT,
+			  0, V4L2_METADATA_LAYOUT_OV2740,
+			  1, V4L2_METADATA_LAYOUT_OV2740);
 
 	ret = v4l2_fwnode_device_parse(ov2740->dev, &props);
 	if (ret) {
-- 
2.47.3


^ permalink raw reply related	[flat|nested] 88+ messages in thread

* [PATCH v12 52/86] media: ov2740: Add support for G_SELECTION IOCTL
  2026-04-09 20:13 [PATCH v12 00/86] Generic line based metadata support, internal pads Sakari Ailus
                   ` (50 preceding siblings ...)
  2026-04-09 20:14 ` [PATCH v12 51/86] media: ov2740: Add metadata layout control Sakari Ailus
@ 2026-04-09 20:14 ` Sakari Ailus
  2026-04-09 20:14 ` [PATCH v12 53/86] media: ov2740: Add support for FLL and LLP controls Sakari Ailus
                   ` (33 subsequent siblings)
  85 siblings, 0 replies; 88+ messages in thread
From: Sakari Ailus @ 2026-04-09 20:14 UTC (permalink / raw)
  To: linux-media
  Cc: hans, laurent.pinchart, Prabhakar, Kate Hsuan, Dave Stevenson,
	Tommaso Merciai, Benjamin Mugnier, Sylvain Petinot,
	Christophe JAILLET, Julien Massot, Naushir Patuck, Stefan Klug,
	Mirela Rabulea, André Apitzsch, Heimir Thor Sverrisson,
	Kieran Bingham, Mehdi Djait, Ricardo Ribalda Delgado,
	Hans de Goede, Jacopo Mondi, Tomi Valkeinen, David Plowman,
	Yu, Ong Hock, Ng, Khai Wen, Jai Luthra, Rishikesh Donadkar

Add support for the G_SELECTION IOCTL in the ov2740 driver.

Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
---
 drivers/media/i2c/ov2740.c | 27 +++++++++++++++++++++++++++
 1 file changed, 27 insertions(+)

diff --git a/drivers/media/i2c/ov2740.c b/drivers/media/i2c/ov2740.c
index 3308c51933aa..1ab2b82f4099 100644
--- a/drivers/media/i2c/ov2740.c
+++ b/drivers/media/i2c/ov2740.c
@@ -1139,6 +1139,32 @@ static int ov2740_set_format(struct v4l2_subdev *sd,
 				   fmt->pad, fmt->stream);
 }
 
+static int ov2740_get_selection(struct v4l2_subdev *sd,
+				const struct v4l2_subdev_client_info *ci,
+				struct v4l2_subdev_state *state,
+				struct v4l2_subdev_selection *sel)
+{
+	if (!(ci && ci->client_caps & V4L2_SUBDEV_CLIENT_CAP_COMMON_RAW_SENSOR))
+		return -EINVAL;
+
+	if (sel->stream != OV2740_STREAM_PIXEL ||
+	    sel->pad != OV2740_PAD_PIXEL)
+		return -EINVAL;
+
+	switch (sel->target) {
+	case V4L2_SEL_TGT_CROP_BOUNDS:
+	case V4L2_SEL_TGT_CROP_DEFAULT:
+	case V4L2_SEL_TGT_CROP:
+		sel->r.top = OV2740_CROP_TOP;
+		sel->r.left = OV2740_CROP_LEFT;
+		sel->r.width = OV2740_ACTIVE_WIDTH - OV2740_CROP_LEFT;
+		sel->r.height = OV2740_ACTIVE_HEIGHT - OV2740_CROP_TOP;
+		return 0;
+	}
+
+	return -EINVAL;
+}
+
 static int ov2740_enum_mbus_code(struct v4l2_subdev *sd,
 				 struct v4l2_subdev_state *sd_state,
 				 struct v4l2_subdev_mbus_code_enum *code)
@@ -1263,6 +1289,7 @@ static const struct v4l2_subdev_video_ops ov2740_video_ops = {
 static const struct v4l2_subdev_pad_ops ov2740_pad_ops = {
 	.get_fmt = v4l2_subdev_get_fmt,
 	.set_fmt = ov2740_set_format,
+	.get_selection = ov2740_get_selection,
 	.enum_mbus_code = ov2740_enum_mbus_code,
 	.enum_frame_size = ov2740_enum_frame_size,
 	.enable_streams = ov2740_enable_streams,
-- 
2.47.3


^ permalink raw reply related	[flat|nested] 88+ messages in thread

* [PATCH v12 53/86] media: ov2740: Add support for FLL and LLP controls
  2026-04-09 20:13 [PATCH v12 00/86] Generic line based metadata support, internal pads Sakari Ailus
                   ` (51 preceding siblings ...)
  2026-04-09 20:14 ` [PATCH v12 52/86] media: ov2740: Add support for G_SELECTION IOCTL Sakari Ailus
@ 2026-04-09 20:14 ` Sakari Ailus
  2026-04-09 20:14 ` [PATCH v12 54/86] media: ov2740: Signal common raw sensor model support Sakari Ailus
                   ` (32 subsequent siblings)
  85 siblings, 0 replies; 88+ messages in thread
From: Sakari Ailus @ 2026-04-09 20:14 UTC (permalink / raw)
  To: linux-media
  Cc: hans, laurent.pinchart, Prabhakar, Kate Hsuan, Dave Stevenson,
	Tommaso Merciai, Benjamin Mugnier, Sylvain Petinot,
	Christophe JAILLET, Julien Massot, Naushir Patuck, Stefan Klug,
	Mirela Rabulea, André Apitzsch, Heimir Thor Sverrisson,
	Kieran Bingham, Mehdi Djait, Ricardo Ribalda Delgado,
	Hans de Goede, Jacopo Mondi, Tomi Valkeinen, David Plowman,
	Yu, Ong Hock, Ng, Khai Wen, Jai Luthra, Rishikesh Donadkar

Add support for the V4L2_CID_FRAME_LENGTH_LINES and
V4L2_CID_LINE_LENGTH_PIXELS controls.

Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
---
 drivers/media/i2c/ov2740.c | 55 ++++++++++++++++++++++++++++----------
 1 file changed, 41 insertions(+), 14 deletions(-)

diff --git a/drivers/media/i2c/ov2740.c b/drivers/media/i2c/ov2740.c
index 1ab2b82f4099..833785ab419d 100644
--- a/drivers/media/i2c/ov2740.c
+++ b/drivers/media/i2c/ov2740.c
@@ -16,6 +16,7 @@
 #include <media/v4l2-ctrls.h>
 #include <media/v4l2-device.h>
 #include <media/v4l2-fwnode.h>
+#include <media/v4l2-mc.h>
 
 #define OV2740_LINK_FREQ_360MHZ		360000000ULL
 #define OV2740_LINK_FREQ_180MHZ		180000000ULL
@@ -562,9 +563,12 @@ struct ov2740 {
 	/* V4L2 Controls */
 	struct v4l2_ctrl *link_freq;
 	struct v4l2_ctrl *pixel_rate;
+	struct v4l2_ctrl *fll;
 	struct v4l2_ctrl *vblank;
+	struct v4l2_ctrl *llp;
 	struct v4l2_ctrl *hblank;
 	struct v4l2_ctrl *exposure;
+	bool setting_ctrl;
 
 	/* GPIOs, clocks, regulators */
 	struct gpio_desc *reset_gpio;
@@ -741,18 +745,28 @@ static int ov2740_set_ctrl(struct v4l2_ctrl *ctrl)
 {
 	struct ov2740 *ov2740 = container_of(ctrl->handler,
 					     struct ov2740, ctrl_handler);
-	s64 exposure_max;
-	int ret;
+	int ret = 0;
 
 	/* Propagate change of current control to all related controls */
-	if (ctrl->id == V4L2_CID_VBLANK) {
-		/* Update max exposure while meeting expected vblanking */
-		exposure_max = ov2740->cur_mode->height + ctrl->val -
-			       OV2740_EXPOSURE_MAX_MARGIN;
-		__v4l2_ctrl_modify_range(ov2740->exposure,
-					 ov2740->exposure->minimum,
-					 exposure_max, ov2740->exposure->step,
-					 exposure_max);
+	switch (ctrl->id) {
+	case V4L2_CID_FRAME_LENGTH_LINES:
+	case V4L2_CID_VBLANK:
+	case V4L2_CID_LINE_LENGTH_PIXELS:
+	case V4L2_CID_HBLANK: {
+		struct v4l2_subdev_state *state =
+			v4l2_subdev_get_locked_active_state(&ov2740->sd);
+		const struct v4l2_mbus_framefmt *format =
+			v4l2_subdev_state_get_format(state, OV2740_PAD_SOURCE,
+						     OV2740_STREAM_PIXEL);
+
+		ret = v4l2_subdev_sensor_fll_llp_set(ov2740->fll, ov2740->vblank,
+						     ov2740->llp, ov2740->hblank,
+						     ov2740->exposure, format,
+						     ctrl, &ov2740->setting_ctrl,
+						     OV2740_EXPOSURE_MAX_MARGIN);
+		if (ret)
+			return ret;
+	}
 	}
 
 	/* V4L2 controls values will be applied only when power is already up */
@@ -776,8 +790,10 @@ static int ov2740_set_ctrl(struct v4l2_ctrl *ctrl)
 		break;
 
 	case V4L2_CID_VBLANK:
-		ret = ov2740_write_reg(ov2740, OV2740_REG_VTS, 2,
-				       ov2740->cur_mode->height + ctrl->val);
+		break;
+
+	case V4L2_CID_FRAME_LENGTH_LINES:
+		ret = ov2740_write_reg(ov2740, OV2740_REG_VTS, 2, ctrl->val);
 		break;
 
 	case V4L2_CID_TEST_PATTERN:
@@ -807,7 +823,7 @@ static int ov2740_init_controls(struct ov2740 *ov2740)
 	int ret;
 
 	ctrl_hdlr = &ov2740->ctrl_handler;
-	ret = v4l2_ctrl_handler_init(ctrl_hdlr, 13);
+	ret = v4l2_ctrl_handler_init(ctrl_hdlr, 15);
 	if (ret)
 		return ret;
 
@@ -828,10 +844,22 @@ static int ov2740_init_controls(struct ov2740 *ov2740)
 	vblank_min = ov2740->cur_mode->vts_min - ov2740->cur_mode->height;
 	vblank_max = ov2740->cur_mode->vts_max - ov2740->cur_mode->height;
 	vblank_default = ov2740->cur_mode->vts_def - ov2740->cur_mode->height;
+	ov2740->fll = v4l2_ctrl_new_std(ctrl_hdlr, &ov2740_ctrl_ops,
+					V4L2_CID_FRAME_LENGTH_LINES,
+					ov2740->cur_mode->vts_min,
+					ov2740->cur_mode->vts_max, 1,
+					ov2740->cur_mode->vts_def);
 	ov2740->vblank = v4l2_ctrl_new_std(ctrl_hdlr, &ov2740_ctrl_ops,
 					   V4L2_CID_VBLANK, vblank_min,
 					   vblank_max, 1, vblank_default);
 
+	ov2740->llp = v4l2_ctrl_new_std(ctrl_hdlr, &ov2740_ctrl_ops,
+					V4L2_CID_LINE_LENGTH_PIXELS,
+					ov2740->cur_mode->hts,
+					ov2740->cur_mode->hts, 1,
+					ov2740->cur_mode->hts);
+	if (ov2740->llp)
+		ov2740->llp->flags |= V4L2_CTRL_FLAG_READ_ONLY;
 	h_blank = ov2740->cur_mode->hts - ov2740->cur_mode->width;
 	ov2740->hblank = v4l2_ctrl_new_std(ctrl_hdlr, &ov2740_ctrl_ops,
 					   V4L2_CID_HBLANK, h_blank, h_blank, 1,
@@ -1223,7 +1251,6 @@ static int ov2740_init_state(struct v4l2_subdev *sd,
 		.routes = routes,
 		.num_routes = ARRAY_SIZE(routes),
 	};
-	struct ov2740 *ov2740 = to_ov2740(sd);
 	int ret;
 
 	ret = v4l2_subdev_set_routing(sd, sd_state, &routing);
-- 
2.47.3


^ permalink raw reply related	[flat|nested] 88+ messages in thread

* [PATCH v12 54/86] media: ov2740: Signal common raw sensor model support
  2026-04-09 20:13 [PATCH v12 00/86] Generic line based metadata support, internal pads Sakari Ailus
                   ` (52 preceding siblings ...)
  2026-04-09 20:14 ` [PATCH v12 53/86] media: ov2740: Add support for FLL and LLP controls Sakari Ailus
@ 2026-04-09 20:14 ` Sakari Ailus
  2026-04-09 20:14 ` [PATCH v12 55/86] media: ov2740: Add IMMUTABLE and STATIC route flags Sakari Ailus
                   ` (31 subsequent siblings)
  85 siblings, 0 replies; 88+ messages in thread
From: Sakari Ailus @ 2026-04-09 20:14 UTC (permalink / raw)
  To: linux-media
  Cc: hans, laurent.pinchart, Prabhakar, Kate Hsuan, Dave Stevenson,
	Tommaso Merciai, Benjamin Mugnier, Sylvain Petinot,
	Christophe JAILLET, Julien Massot, Naushir Patuck, Stefan Klug,
	Mirela Rabulea, André Apitzsch, Heimir Thor Sverrisson,
	Kieran Bingham, Mehdi Djait, Ricardo Ribalda Delgado,
	Hans de Goede, Jacopo Mondi, Tomi Valkeinen, David Plowman,
	Yu, Ong Hock, Ng, Khai Wen, Jai Luthra, Rishikesh Donadkar

Add support for the CONFIG_MODEL control and signal support for the common
raw sensor model.

Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
---
 drivers/media/i2c/ov2740.c | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/drivers/media/i2c/ov2740.c b/drivers/media/i2c/ov2740.c
index 833785ab419d..0efc69e58f13 100644
--- a/drivers/media/i2c/ov2740.c
+++ b/drivers/media/i2c/ov2740.c
@@ -823,7 +823,7 @@ static int ov2740_init_controls(struct ov2740 *ov2740)
 	int ret;
 
 	ctrl_hdlr = &ov2740->ctrl_handler;
-	ret = v4l2_ctrl_handler_init(ctrl_hdlr, 15);
+	ret = v4l2_ctrl_handler_init(ctrl_hdlr, 16);
 	if (ret)
 		return ret;
 
@@ -893,6 +893,9 @@ static int ov2740_init_controls(struct ov2740 *ov2740)
 	v4l2_ctrl_new_std(ctrl_hdlr, NULL, V4L2_CID_METADATA_LAYOUT,
 			  0, V4L2_METADATA_LAYOUT_OV2740,
 			  1, V4L2_METADATA_LAYOUT_OV2740);
+	v4l2_ctrl_new_std(ctrl_hdlr, NULL, V4L2_CID_CONFIG_MODEL,
+			  0, V4L2_CONFIG_MODEL_COMMON_RAW_SENSOR,
+			  0, V4L2_CONFIG_MODEL_COMMON_RAW_SENSOR);
 
 	ret = v4l2_fwnode_device_parse(ov2740->dev, &props);
 	if (ret) {
-- 
2.47.3


^ permalink raw reply related	[flat|nested] 88+ messages in thread

* [PATCH v12 55/86] media: ov2740: Add IMMUTABLE and STATIC route flags
  2026-04-09 20:13 [PATCH v12 00/86] Generic line based metadata support, internal pads Sakari Ailus
                   ` (53 preceding siblings ...)
  2026-04-09 20:14 ` [PATCH v12 54/86] media: ov2740: Signal common raw sensor model support Sakari Ailus
@ 2026-04-09 20:14 ` Sakari Ailus
  2026-04-09 20:14 ` [PATCH v12 56/86] media: imx219: Add internal pads, routes for common raw sensor model Sakari Ailus
                   ` (30 subsequent siblings)
  85 siblings, 0 replies; 88+ messages in thread
From: Sakari Ailus @ 2026-04-09 20:14 UTC (permalink / raw)
  To: linux-media
  Cc: hans, laurent.pinchart, Prabhakar, Kate Hsuan, Dave Stevenson,
	Tommaso Merciai, Benjamin Mugnier, Sylvain Petinot,
	Christophe JAILLET, Julien Massot, Naushir Patuck, Stefan Klug,
	Mirela Rabulea, André Apitzsch, Heimir Thor Sverrisson,
	Kieran Bingham, Mehdi Djait, Ricardo Ribalda Delgado,
	Hans de Goede, Jacopo Mondi, Tomi Valkeinen, David Plowman,
	Yu, Ong Hock, Ng, Khai Wen, Jai Luthra, Rishikesh Donadkar

Add immutable and static route flags to the routing table. The driver does
not support disabling the embedded data whereas the sensor itself does.

Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
Reviewed-by: Julien Massot <julien.massot@collabora.com>
Reviewed-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
 drivers/media/i2c/ov2740.c | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/drivers/media/i2c/ov2740.c b/drivers/media/i2c/ov2740.c
index 0efc69e58f13..6ba3db496bb7 100644
--- a/drivers/media/i2c/ov2740.c
+++ b/drivers/media/i2c/ov2740.c
@@ -1242,12 +1242,16 @@ static int ov2740_init_state(struct v4l2_subdev *sd,
 			.sink_pad = OV2740_PAD_PIXEL,
 			.source_pad = OV2740_PAD_SOURCE,
 			.source_stream = OV2740_STREAM_PIXEL,
-			.flags = V4L2_SUBDEV_ROUTE_FL_ACTIVE,
+			.flags = V4L2_SUBDEV_ROUTE_FL_ACTIVE |
+				 V4L2_SUBDEV_ROUTE_FL_IMMUTABLE |
+				 V4L2_SUBDEV_ROUTE_FL_STATIC,
 		}, {
 			.sink_pad = OV2740_PAD_META,
 			.source_pad = OV2740_PAD_SOURCE,
 			.source_stream = OV2740_STREAM_META,
-			.flags = V4L2_SUBDEV_ROUTE_FL_ACTIVE,
+			.flags = V4L2_SUBDEV_ROUTE_FL_ACTIVE |
+				 V4L2_SUBDEV_ROUTE_FL_IMMUTABLE |
+				 V4L2_SUBDEV_ROUTE_FL_STATIC,
 		},
 	};
 	struct v4l2_subdev_krouting routing = {
-- 
2.47.3


^ permalink raw reply related	[flat|nested] 88+ messages in thread

* [PATCH v12 56/86] media: imx219: Add internal pads, routes for common raw sensor model
  2026-04-09 20:13 [PATCH v12 00/86] Generic line based metadata support, internal pads Sakari Ailus
                   ` (54 preceding siblings ...)
  2026-04-09 20:14 ` [PATCH v12 55/86] media: ov2740: Add IMMUTABLE and STATIC route flags Sakari Ailus
@ 2026-04-09 20:14 ` Sakari Ailus
  2026-04-09 20:14 ` [PATCH v12 57/86] media: imx219: Add image stream Sakari Ailus
                   ` (29 subsequent siblings)
  85 siblings, 0 replies; 88+ messages in thread
From: Sakari Ailus @ 2026-04-09 20:14 UTC (permalink / raw)
  To: linux-media
  Cc: hans, laurent.pinchart, Prabhakar, Kate Hsuan, Dave Stevenson,
	Tommaso Merciai, Benjamin Mugnier, Sylvain Petinot,
	Christophe JAILLET, Julien Massot, Naushir Patuck, Stefan Klug,
	Mirela Rabulea, André Apitzsch, Heimir Thor Sverrisson,
	Kieran Bingham, Mehdi Djait, Ricardo Ribalda Delgado,
	Hans de Goede, Jacopo Mondi, Tomi Valkeinen, David Plowman,
	Yu, Ong Hock, Ng, Khai Wen, Jai Luthra, Rishikesh Donadkar

Support internal pads, routing, formats and selections for the newly added
common raw sensor model, with compatibility interface provided for the
existing users.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Co-developed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
---
 drivers/media/i2c/imx219.c | 230 +++++++++++++++++++++++++++----------
 1 file changed, 171 insertions(+), 59 deletions(-)

diff --git a/drivers/media/i2c/imx219.c b/drivers/media/i2c/imx219.c
index 67b02fa338d0..b4aa62cbb826 100644
--- a/drivers/media/i2c/imx219.c
+++ b/drivers/media/i2c/imx219.c
@@ -139,13 +139,19 @@
 #define IMX219_DEFAULT_LINK_FREQ_4LANE_UNSUPPORTED	363000000
 #define IMX219_DEFAULT_LINK_FREQ_4LANE	364000000
 
+/* For compatibility with the old UAPI. */
+#define IMX219_COMPAT_VISIBLE_TOP	8U
 /* IMX219 native and active pixel array size. */
-#define IMX219_NATIVE_WIDTH		3296U
-#define IMX219_NATIVE_HEIGHT		2480U
+#define IMX219_NON_VISIBLE_HEIGHT	42U
 #define IMX219_VISIBLE_LEFT		8U
-#define IMX219_VISIBLE_TOP		8U
+#define IMX219_VISIBLE_TOP		(IMX219_NON_VISIBLE_HEIGHT + 8U)
 #define IMX219_VISIBLE_WIDTH		3280U
 #define IMX219_VISIBLE_HEIGHT		2464U
+#define IMX219_PIXEL_ARRAY_LEFT		0U
+#define IMX219_PIXEL_ARRAY_TOP		IMX219_NON_VISIBLE_HEIGHT
+#define IMX219_PIXEL_ARRAY_WIDTH	3296U
+#define IMX219_PIXEL_ARRAY_HEIGHT	2480U
+#define IMX219_NATIVE_FORMAT		MEDIA_BUS_FMT_SRGGB10_1X10
 
 /* Mode : resolution and related config&values */
 struct imx219_mode {
@@ -335,9 +341,15 @@ static const struct imx219_mode supported_modes[] = {
 	},
 };
 
+enum imx219_pad_ids {
+	IMX219_PAD_SOURCE = 0,
+	IMX219_PAD_IMAGE,
+	IMX219_NUM_PADS,
+};
+
 struct imx219 {
 	struct v4l2_subdev sd;
-	struct media_pad pad;
+	struct media_pad pads[IMX219_NUM_PADS];
 
 	struct regmap *regmap;
 	struct clk *xclk; /* system clock to IMX219 */
@@ -405,8 +417,9 @@ static void imx219_get_binning(struct v4l2_subdev_state *state, u8 *bin_h,
 			       u8 *bin_v)
 {
 	const struct v4l2_mbus_framefmt *format =
-		v4l2_subdev_state_get_format(state, 0);
-	const struct v4l2_rect *crop = v4l2_subdev_state_get_crop(state, 0);
+		v4l2_subdev_state_get_format(state, IMX219_PAD_SOURCE);
+	const struct v4l2_rect *crop =
+		v4l2_subdev_state_get_crop(state, IMX219_PAD_SOURCE);
 	u32 hbin = crop->width / format->width;
 	u32 vbin = crop->height / format->height;
 
@@ -434,7 +447,7 @@ static int imx219_set_ctrl(struct v4l2_ctrl *ctrl)
 	int ret = 0;
 
 	state = v4l2_subdev_get_locked_active_state(&imx219->sd);
-	format = v4l2_subdev_state_get_format(state, 0);
+	format = v4l2_subdev_state_get_format(state, IMX219_PAD_SOURCE);
 
 	if (ctrl->id == V4L2_CID_VBLANK) {
 		int exposure_max, exposure_def;
@@ -659,8 +672,8 @@ static int imx219_set_framefmt(struct imx219 *imx219,
 	u32 bpp;
 	int ret = 0;
 
-	format = v4l2_subdev_state_get_format(state, 0);
-	crop = v4l2_subdev_state_get_crop(state, 0);
+	format = v4l2_subdev_state_get_format(state, IMX219_PAD_SOURCE);
+	crop = v4l2_subdev_state_get_crop(state, IMX219_PAD_IMAGE);
 	bpp = imx219_get_format_bpp(format);
 
 	cci_write(imx219->regmap, IMX219_REG_X_ADD_STA_A,
@@ -787,10 +800,25 @@ static int imx219_enum_mbus_code(struct v4l2_subdev *sd,
 {
 	struct imx219 *imx219 = to_imx219(sd);
 
-	if (code->index >= (ARRAY_SIZE(imx219_mbus_formats) / 4))
-		return -EINVAL;
+	if (code->pad == IMX219_PAD_IMAGE) {
+		/* The internal image pad is hardwired to the native format. */
+		if (code->index > 0)
+			return -EINVAL;
+
+		code->code = IMX219_NATIVE_FORMAT;
+	} else {
+		/*
+		 * On the source pad, the sensor supports multiple raw formats
+		 * with different bit depths.
+		 */
+		u32 format;
 
-	code->code = imx219_get_format_code(imx219, imx219_mbus_formats[code->index * 4]);
+		if (code->index >= ARRAY_SIZE(imx219_mbus_formats) / 4)
+			return -EINVAL;
+
+		format = imx219_mbus_formats[code->index * 4];
+		code->code = imx219_get_format_code(imx219, format);
+	}
 
 	return 0;
 }
@@ -800,27 +828,32 @@ static int imx219_enum_frame_size(struct v4l2_subdev *sd,
 				  struct v4l2_subdev_frame_size_enum *fse)
 {
 	struct imx219 *imx219 = to_imx219(sd);
-	u32 code;
-
-	if (fse->index >= ARRAY_SIZE(supported_modes))
-		return -EINVAL;
 
-	code = imx219_get_format_code(imx219, fse->code);
-	if (fse->code != code)
-		return -EINVAL;
+	if (fse->pad == IMX219_PAD_IMAGE) {
+		if (fse->code != IMX219_NATIVE_FORMAT || fse->index > 0)
+			return -EINVAL;
 
-	fse->min_width = supported_modes[fse->index].width;
-	fse->max_width = fse->min_width;
-	fse->min_height = supported_modes[fse->index].height;
-	fse->max_height = fse->min_height;
+		fse->min_width = IMX219_PIXEL_ARRAY_WIDTH;
+		fse->max_width = IMX219_PIXEL_ARRAY_WIDTH;
+		fse->min_height = IMX219_PIXEL_ARRAY_HEIGHT;
+		fse->max_height = IMX219_PIXEL_ARRAY_HEIGHT;
+	} else {
+		if (fse->code != imx219_get_format_code(imx219, fse->code) ||
+		    fse->index >= ARRAY_SIZE(supported_modes))
+			return -EINVAL;
+
+		fse->min_width = supported_modes[fse->index].width;
+		fse->max_width = fse->min_width;
+		fse->min_height = supported_modes[fse->index].height;
+		fse->max_height = fse->min_height;
+	}
 
 	return 0;
 }
 
-static int imx219_set_pad_format(struct v4l2_subdev *sd,
-				 const struct v4l2_subdev_client_info *ci,
-				 struct v4l2_subdev_state *state,
-				 struct v4l2_subdev_format *fmt)
+static int imx219_set_pad_format_compat(struct v4l2_subdev *sd,
+					struct v4l2_subdev_state *state,
+					struct v4l2_subdev_format *fmt)
 {
 	struct imx219 *imx219 = to_imx219(sd);
 	const struct imx219_mode *mode;
@@ -829,7 +862,7 @@ static int imx219_set_pad_format(struct v4l2_subdev *sd,
 	u8 bin_h, bin_v, bin_hv;
 	int ret;
 
-	format = v4l2_subdev_state_get_format(state, 0);
+	format = v4l2_subdev_state_get_format(state, IMX219_PAD_SOURCE);
 
 	/*
 	 * Adjust the requested format to match the closest mode. The Bayer
@@ -861,11 +894,11 @@ static int imx219_set_pad_format(struct v4l2_subdev *sd,
 	/* Ensure bin_h and bin_v are same to avoid 1:2 or 2:1 stretching */
 	bin_hv = min(bin_h, bin_v);
 
-	crop = v4l2_subdev_state_get_crop(state, 0);
+	crop = v4l2_subdev_state_get_crop(state, IMX219_PAD_SOURCE);
 	crop->width = format->width * bin_hv;
 	crop->height = format->height * bin_hv;
-	crop->left = (IMX219_NATIVE_WIDTH - crop->width) / 2;
-	crop->top = (IMX219_NATIVE_HEIGHT - crop->height) / 2;
+	crop->left = (IMX219_PIXEL_ARRAY_WIDTH - crop->width) / 2;
+	crop->top = (IMX219_PIXEL_ARRAY_HEIGHT - crop->height) / 2;
 
 	if (fmt->which == V4L2_SUBDEV_FORMAT_ACTIVE) {
 		int llp_min;
@@ -917,51 +950,129 @@ static int imx219_set_pad_format(struct v4l2_subdev *sd,
 	return 0;
 }
 
+static int imx219_set_pad_format(struct v4l2_subdev *sd,
+				 const struct v4l2_subdev_client_info *ci,
+				 struct v4l2_subdev_state *state,
+				 struct v4l2_subdev_format *fmt)
+{
+	struct imx219 *imx219 = to_imx219(sd);
+	struct v4l2_mbus_framefmt *format;
+
+	if (!(ci && ci->client_caps & V4L2_SUBDEV_CLIENT_CAP_COMMON_RAW_SENSOR))
+		return imx219_set_pad_format_compat(sd, state, fmt);
+
+	if (fmt->pad != IMX219_PAD_SOURCE)
+		return v4l2_subdev_get_fmt(sd, ci, state, fmt);
+
+	format = v4l2_subdev_state_get_format(state, IMX219_PAD_SOURCE);
+
+	format->code = fmt->format.code =
+		imx219_get_format_code(imx219, fmt->format.code);
+
+	return 0;
+}
+
 static int imx219_get_selection(struct v4l2_subdev *sd,
 				const struct v4l2_subdev_client_info *ci,
 				struct v4l2_subdev_state *state,
 				struct v4l2_subdev_selection *sel)
 {
-	switch (sel->target) {
-	case V4L2_SEL_TGT_CROP:
-		sel->r = *v4l2_subdev_state_get_crop(state, 0);
-		return 0;
+	if (!(ci &&
+	      ci->client_caps & V4L2_SUBDEV_CLIENT_CAP_COMMON_RAW_SENSOR)) {
+		if (sel->pad != IMX219_PAD_SOURCE)
+			return -EINVAL;
+
+		switch (sel->target) {
+		case V4L2_SEL_TGT_CROP:
+			sel->r = *v4l2_subdev_state_get_crop(state,
+							     IMX219_PAD_IMAGE);
+			sel->r.top -= IMX219_VISIBLE_TOP;
+			return 0;
+
+		case V4L2_SEL_TGT_NATIVE_SIZE:
+			sel->r.top = 0;
+			sel->r.left = 0;
+			sel->r.width = IMX219_VISIBLE_WIDTH;
+			sel->r.height = IMX219_VISIBLE_HEIGHT;
+
+			return 0;
+
+		case V4L2_SEL_TGT_CROP_DEFAULT:
+		case V4L2_SEL_TGT_CROP_BOUNDS:
+			sel->r.top = IMX219_COMPAT_VISIBLE_TOP;
+			sel->r.left = IMX219_VISIBLE_LEFT;
+			sel->r.width = IMX219_VISIBLE_WIDTH;
+			sel->r.height = IMX219_VISIBLE_HEIGHT;
+
+			return 0;
+		}
 
-	case V4L2_SEL_TGT_NATIVE_SIZE:
-		sel->r.top = 0;
-		sel->r.left = 0;
-		sel->r.width = IMX219_NATIVE_WIDTH;
-		sel->r.height = IMX219_NATIVE_HEIGHT;
+		return -EINVAL;
+	}
 
-		return 0;
+	if (sel->pad != IMX219_PAD_IMAGE)
+		return -EINVAL;
 
-	case V4L2_SEL_TGT_CROP_DEFAULT:
+	switch (sel->target) {
 	case V4L2_SEL_TGT_CROP_BOUNDS:
 		sel->r.top = IMX219_VISIBLE_TOP;
 		sel->r.left = IMX219_VISIBLE_LEFT;
 		sel->r.width = IMX219_VISIBLE_WIDTH;
 		sel->r.height = IMX219_VISIBLE_HEIGHT;
-
 		return 0;
+	case V4L2_SEL_TGT_CROP_DEFAULT:
+		sel->r.top = IMX219_VISIBLE_TOP;
+		sel->r.left = IMX219_VISIBLE_LEFT;
+		sel->r.width = IMX219_VISIBLE_WIDTH;
+		sel->r.height = IMX219_VISIBLE_HEIGHT;
+		return 0;
+	case V4L2_SEL_TGT_CROP:
+		sel->r = *v4l2_subdev_state_get_crop(state, sel->pad);
+		return 0;
+	case V4L2_SEL_TGT_COMPOSE:
+		sel->r = *v4l2_subdev_state_get_compose(state, sel->pad);
+		return 0;
+	default:
+		return -EINVAL;
 	}
-
-	return -EINVAL;
 }
 
 static int imx219_init_state(struct v4l2_subdev *sd,
 			     struct v4l2_subdev_state *state)
 {
-	struct v4l2_subdev_format fmt = {
-		.which = V4L2_SUBDEV_FORMAT_TRY,
-		.pad = 0,
-		.format = {
-			.code = MEDIA_BUS_FMT_SRGGB10_1X10,
-			.width = supported_modes[0].width,
-			.height = supported_modes[0].height,
-		},
-	};
+	struct v4l2_mbus_framefmt *pixel_array_format =
+		v4l2_subdev_state_get_format(state, IMX219_PAD_IMAGE);
+	struct v4l2_rect *analogue_crop =
+		v4l2_subdev_state_get_crop(state, IMX219_PAD_IMAGE);
+	struct v4l2_rect *compose =
+		v4l2_subdev_state_get_compose(state, IMX219_PAD_IMAGE);
+	struct v4l2_mbus_framefmt *source_format =
+		v4l2_subdev_state_get_format(state, IMX219_PAD_SOURCE);
+
+	/* The image pad models the pixel array, and thus has a fixed format. */
+	pixel_array_format->code = MEDIA_BUS_FMT_RAW_10;
+	pixel_array_format->width = IMX219_VISIBLE_WIDTH;
+	pixel_array_format->height = IMX219_VISIBLE_HEIGHT;
+	pixel_array_format->field = V4L2_FIELD_NONE;
+	pixel_array_format->colorspace = V4L2_COLORSPACE_RAW;
+	pixel_array_format->ycbcr_enc = V4L2_YCBCR_ENC_601;
+	pixel_array_format->quantization = V4L2_QUANTIZATION_FULL_RANGE;
+	pixel_array_format->xfer_func = V4L2_XFER_FUNC_NONE;
+
+	analogue_crop->top = IMX219_VISIBLE_TOP;
+	analogue_crop->left = IMX219_VISIBLE_LEFT;
+	analogue_crop->width = IMX219_VISIBLE_WIDTH;
+	analogue_crop->height = IMX219_VISIBLE_HEIGHT;
+
+	compose->width = analogue_crop->width;
+	compose->height = analogue_crop->height;
+
+	*source_format = *pixel_array_format;
+	source_format->code = IMX219_NATIVE_FORMAT;
+	source_format->width = compose->width;
+	source_format->height = compose->height;
 
-	return imx219_set_pad_format(sd, NULL, state, &fmt);
+	return 0;
 }
 
 static const struct v4l2_subdev_video_ops imx219_video_ops = {
@@ -1228,14 +1339,15 @@ static int imx219_probe(struct i2c_client *client)
 	if (ret)
 		goto error_power_off;
 
-	/* Initialize subdev */
 	imx219->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
 	imx219->sd.entity.function = MEDIA_ENT_F_CAM_SENSOR;
 
-	/* Initialize source pad */
-	imx219->pad.flags = MEDIA_PAD_FL_SOURCE;
+	imx219->pads[IMX219_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE;
+	imx219->pads[IMX219_PAD_IMAGE].flags = MEDIA_PAD_FL_SINK
+					     | MEDIA_PAD_FL_INTERNAL;
 
-	ret = media_entity_pads_init(&imx219->sd.entity, 1, &imx219->pad);
+	ret = media_entity_pads_init(&imx219->sd.entity,
+				     ARRAY_SIZE(imx219->pads), imx219->pads);
 	if (ret) {
 		dev_err_probe(dev, ret, "failed to init entity pads\n");
 		goto error_handler_free;
-- 
2.47.3


^ permalink raw reply related	[flat|nested] 88+ messages in thread

* [PATCH v12 57/86] media: imx219: Add image stream
  2026-04-09 20:13 [PATCH v12 00/86] Generic line based metadata support, internal pads Sakari Ailus
                   ` (55 preceding siblings ...)
  2026-04-09 20:14 ` [PATCH v12 56/86] media: imx219: Add internal pads, routes for common raw sensor model Sakari Ailus
@ 2026-04-09 20:14 ` Sakari Ailus
  2026-04-09 20:14 ` [PATCH v12 58/86] media: imx219: Report internal routes to userspace Sakari Ailus
                   ` (28 subsequent siblings)
  85 siblings, 0 replies; 88+ messages in thread
From: Sakari Ailus @ 2026-04-09 20:14 UTC (permalink / raw)
  To: linux-media
  Cc: hans, laurent.pinchart, Prabhakar, Kate Hsuan, Dave Stevenson,
	Tommaso Merciai, Benjamin Mugnier, Sylvain Petinot,
	Christophe JAILLET, Julien Massot, Naushir Patuck, Stefan Klug,
	Mirela Rabulea, André Apitzsch, Heimir Thor Sverrisson,
	Kieran Bingham, Mehdi Djait, Ricardo Ribalda Delgado,
	Hans de Goede, Jacopo Mondi, Tomi Valkeinen, David Plowman,
	Yu, Ong Hock, Ng, Khai Wen, Jai Luthra, Rishikesh Donadkar

From: Laurent Pinchart <laurent.pinchart@ideasonboard.com>

In preparation for embedded data stream support, introduce a new
imx219_stream_ids enumeration for stream IDs, with a single value,
IMX219_STREAM_IMAGE for the image data stream. Use it when accessing the
formats, crop and compose rectangles on the source pad. This is meant to
reduce the size of further commits, and doesn't introduce any functional
change.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Co-developed-by: Sakari Ailus <sakari.ailus@linux.intel.com>
Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
---
 drivers/media/i2c/imx219.c | 26 ++++++++++++++++++--------
 1 file changed, 18 insertions(+), 8 deletions(-)

diff --git a/drivers/media/i2c/imx219.c b/drivers/media/i2c/imx219.c
index b4aa62cbb826..bb7b2e4b34fd 100644
--- a/drivers/media/i2c/imx219.c
+++ b/drivers/media/i2c/imx219.c
@@ -347,6 +347,10 @@ enum imx219_pad_ids {
 	IMX219_NUM_PADS,
 };
 
+enum imx219_stream_ids {
+	IMX219_STREAM_IMAGE,
+};
+
 struct imx219 {
 	struct v4l2_subdev sd;
 	struct media_pad pads[IMX219_NUM_PADS];
@@ -417,9 +421,10 @@ static void imx219_get_binning(struct v4l2_subdev_state *state, u8 *bin_h,
 			       u8 *bin_v)
 {
 	const struct v4l2_mbus_framefmt *format =
-		v4l2_subdev_state_get_format(state, IMX219_PAD_SOURCE);
+		v4l2_subdev_state_get_format(state, IMX219_PAD_SOURCE,
+					      IMX219_STREAM_IMAGE);
 	const struct v4l2_rect *crop =
-		v4l2_subdev_state_get_crop(state, IMX219_PAD_SOURCE);
+		v4l2_subdev_state_get_crop(state, IMX219_PAD_IMAGE);
 	u32 hbin = crop->width / format->width;
 	u32 vbin = crop->height / format->height;
 
@@ -447,7 +452,8 @@ static int imx219_set_ctrl(struct v4l2_ctrl *ctrl)
 	int ret = 0;
 
 	state = v4l2_subdev_get_locked_active_state(&imx219->sd);
-	format = v4l2_subdev_state_get_format(state, IMX219_PAD_SOURCE);
+	format = v4l2_subdev_state_get_format(state, IMX219_PAD_SOURCE,
+					      IMX219_STREAM_IMAGE);
 
 	if (ctrl->id == V4L2_CID_VBLANK) {
 		int exposure_max, exposure_def;
@@ -672,7 +678,8 @@ static int imx219_set_framefmt(struct imx219 *imx219,
 	u32 bpp;
 	int ret = 0;
 
-	format = v4l2_subdev_state_get_format(state, IMX219_PAD_SOURCE);
+	format = v4l2_subdev_state_get_format(state, IMX219_PAD_SOURCE,
+					      IMX219_STREAM_IMAGE);
 	crop = v4l2_subdev_state_get_crop(state, IMX219_PAD_IMAGE);
 	bpp = imx219_get_format_bpp(format);
 
@@ -862,7 +869,8 @@ static int imx219_set_pad_format_compat(struct v4l2_subdev *sd,
 	u8 bin_h, bin_v, bin_hv;
 	int ret;
 
-	format = v4l2_subdev_state_get_format(state, IMX219_PAD_SOURCE);
+	format = v4l2_subdev_state_get_format(state, IMX219_PAD_SOURCE,
+					      IMX219_STREAM_IMAGE);
 
 	/*
 	 * Adjust the requested format to match the closest mode. The Bayer
@@ -894,7 +902,7 @@ static int imx219_set_pad_format_compat(struct v4l2_subdev *sd,
 	/* Ensure bin_h and bin_v are same to avoid 1:2 or 2:1 stretching */
 	bin_hv = min(bin_h, bin_v);
 
-	crop = v4l2_subdev_state_get_crop(state, IMX219_PAD_SOURCE);
+	crop = v4l2_subdev_state_get_crop(state, IMX219_PAD_IMAGE);
 	crop->width = format->width * bin_hv;
 	crop->height = format->height * bin_hv;
 	crop->left = (IMX219_PIXEL_ARRAY_WIDTH - crop->width) / 2;
@@ -964,7 +972,8 @@ static int imx219_set_pad_format(struct v4l2_subdev *sd,
 	if (fmt->pad != IMX219_PAD_SOURCE)
 		return v4l2_subdev_get_fmt(sd, ci, state, fmt);
 
-	format = v4l2_subdev_state_get_format(state, IMX219_PAD_SOURCE);
+	format = v4l2_subdev_state_get_format(state, IMX219_PAD_SOURCE,
+					      IMX219_STREAM_IMAGE);
 
 	format->code = fmt->format.code =
 		imx219_get_format_code(imx219, fmt->format.code);
@@ -1047,7 +1056,8 @@ static int imx219_init_state(struct v4l2_subdev *sd,
 	struct v4l2_rect *compose =
 		v4l2_subdev_state_get_compose(state, IMX219_PAD_IMAGE);
 	struct v4l2_mbus_framefmt *source_format =
-		v4l2_subdev_state_get_format(state, IMX219_PAD_SOURCE);
+		v4l2_subdev_state_get_format(state, IMX219_PAD_SOURCE,
+					     IMX219_STREAM_IMAGE);
 
 	/* The image pad models the pixel array, and thus has a fixed format. */
 	pixel_array_format->code = MEDIA_BUS_FMT_RAW_10;
-- 
2.47.3


^ permalink raw reply related	[flat|nested] 88+ messages in thread

* [PATCH v12 58/86] media: imx219: Report internal routes to userspace
  2026-04-09 20:13 [PATCH v12 00/86] Generic line based metadata support, internal pads Sakari Ailus
                   ` (56 preceding siblings ...)
  2026-04-09 20:14 ` [PATCH v12 57/86] media: imx219: Add image stream Sakari Ailus
@ 2026-04-09 20:14 ` Sakari Ailus
  2026-04-09 20:14 ` [PATCH v12 59/86] media: imx219: Report streams using frame descriptors Sakari Ailus
                   ` (27 subsequent siblings)
  85 siblings, 0 replies; 88+ messages in thread
From: Sakari Ailus @ 2026-04-09 20:14 UTC (permalink / raw)
  To: linux-media
  Cc: hans, laurent.pinchart, Prabhakar, Kate Hsuan, Dave Stevenson,
	Tommaso Merciai, Benjamin Mugnier, Sylvain Petinot,
	Christophe JAILLET, Julien Massot, Naushir Patuck, Stefan Klug,
	Mirela Rabulea, André Apitzsch, Heimir Thor Sverrisson,
	Kieran Bingham, Mehdi Djait, Ricardo Ribalda Delgado,
	Hans de Goede, Jacopo Mondi, Tomi Valkeinen, David Plowman,
	Yu, Ong Hock, Ng, Khai Wen, Jai Luthra, Rishikesh Donadkar

From: Laurent Pinchart <laurent.pinchart@ideasonboard.com>

Usage of internal pads creates a route internal to the subdev, and the
V4L2 camera sensor API requires such routes to be reported to userspace.
Create the route in the .init_state() operation.

Internal routing support requires stream support, so set the
V4L2_SUBDEV_FL_STREAMS flag. As the route is immutable, there's no need
to implement the .set_routing() operation.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Reviewed-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
---
 drivers/media/i2c/imx219.c | 25 ++++++++++++++++++++++++-
 1 file changed, 24 insertions(+), 1 deletion(-)

diff --git a/drivers/media/i2c/imx219.c b/drivers/media/i2c/imx219.c
index bb7b2e4b34fd..e79b26268415 100644
--- a/drivers/media/i2c/imx219.c
+++ b/drivers/media/i2c/imx219.c
@@ -1049,6 +1049,28 @@ static int imx219_get_selection(struct v4l2_subdev *sd,
 static int imx219_init_state(struct v4l2_subdev *sd,
 			     struct v4l2_subdev_state *state)
 {
+	struct v4l2_subdev_route routes[1] = {
+		{
+			.sink_pad = IMX219_PAD_IMAGE,
+			.sink_stream = 0,
+			.source_pad = IMX219_PAD_SOURCE,
+			.source_stream = IMX219_STREAM_IMAGE,
+			.flags = V4L2_SUBDEV_ROUTE_FL_ACTIVE |
+				 V4L2_SUBDEV_ROUTE_FL_IMMUTABLE |
+				 V4L2_SUBDEV_ROUTE_FL_STATIC,
+		},
+	};
+	struct v4l2_subdev_krouting routing = {
+		.len_routes = ARRAY_SIZE(routes),
+		.num_routes = ARRAY_SIZE(routes),
+		.routes = routes,
+	};
+	int ret;
+
+	ret = v4l2_subdev_set_routing(sd, state, &routing);
+	if (ret)
+		return ret;
+
 	struct v4l2_mbus_framefmt *pixel_array_format =
 		v4l2_subdev_state_get_format(state, IMX219_PAD_IMAGE);
 	struct v4l2_rect *analogue_crop =
@@ -1349,7 +1371,8 @@ static int imx219_probe(struct i2c_client *client)
 	if (ret)
 		goto error_power_off;
 
-	imx219->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
+	imx219->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE |
+			    V4L2_SUBDEV_FL_STREAMS;
 	imx219->sd.entity.function = MEDIA_ENT_F_CAM_SENSOR;
 
 	imx219->pads[IMX219_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE;
-- 
2.47.3


^ permalink raw reply related	[flat|nested] 88+ messages in thread

* [PATCH v12 59/86] media: imx219: Report streams using frame descriptors
  2026-04-09 20:13 [PATCH v12 00/86] Generic line based metadata support, internal pads Sakari Ailus
                   ` (57 preceding siblings ...)
  2026-04-09 20:14 ` [PATCH v12 58/86] media: imx219: Report internal routes to userspace Sakari Ailus
@ 2026-04-09 20:14 ` Sakari Ailus
  2026-04-09 20:14 ` [PATCH v12 60/86] media: imx219: Add embedded data support Sakari Ailus
                   ` (26 subsequent siblings)
  85 siblings, 0 replies; 88+ messages in thread
From: Sakari Ailus @ 2026-04-09 20:14 UTC (permalink / raw)
  To: linux-media
  Cc: hans, laurent.pinchart, Prabhakar, Kate Hsuan, Dave Stevenson,
	Tommaso Merciai, Benjamin Mugnier, Sylvain Petinot,
	Christophe JAILLET, Julien Massot, Naushir Patuck, Stefan Klug,
	Mirela Rabulea, André Apitzsch, Heimir Thor Sverrisson,
	Kieran Bingham, Mehdi Djait, Ricardo Ribalda Delgado,
	Hans de Goede, Jacopo Mondi, Tomi Valkeinen, David Plowman,
	Yu, Ong Hock, Ng, Khai Wen, Jai Luthra, Rishikesh Donadkar

From: Laurent Pinchart <laurent.pinchart@ideasonboard.com>

Implement the .get_frame_desc() subdev operation to report information
about streams to the connected CSI-2 receiver. This is required to let
the CSI-2 receiver driver know about virtual channels and data types for
each stream.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Reviewed-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
---
 drivers/media/i2c/imx219.c | 48 ++++++++++++++++++++++++++++++++++++++
 1 file changed, 48 insertions(+)

diff --git a/drivers/media/i2c/imx219.c b/drivers/media/i2c/imx219.c
index e79b26268415..d695987839e4 100644
--- a/drivers/media/i2c/imx219.c
+++ b/drivers/media/i2c/imx219.c
@@ -23,6 +23,7 @@
 #include <linux/pm_runtime.h>
 #include <linux/regulator/consumer.h>
 
+#include <media/mipi-csi2.h>
 #include <media/v4l2-cci.h>
 #include <media/v4l2-ctrls.h>
 #include <media/v4l2-device.h>
@@ -669,6 +670,24 @@ static void imx219_free_controls(struct imx219 *imx219)
  * Subdev operations
  */
 
+static unsigned int imx219_format_bpp(u32 code)
+{
+	switch (code) {
+	case MEDIA_BUS_FMT_SRGGB8_1X8:
+	case MEDIA_BUS_FMT_SGRBG8_1X8:
+	case MEDIA_BUS_FMT_SGBRG8_1X8:
+	case MEDIA_BUS_FMT_SBGGR8_1X8:
+		return 8;
+
+	case MEDIA_BUS_FMT_SRGGB10_1X10:
+	case MEDIA_BUS_FMT_SGRBG10_1X10:
+	case MEDIA_BUS_FMT_SGBRG10_1X10:
+	case MEDIA_BUS_FMT_SBGGR10_1X10:
+	default:
+		return 10;
+	}
+}
+
 static int imx219_set_framefmt(struct imx219 *imx219,
 			       struct v4l2_subdev_state *state)
 {
@@ -1046,6 +1065,34 @@ static int imx219_get_selection(struct v4l2_subdev *sd,
 	}
 }
 
+static int imx219_get_frame_desc(struct v4l2_subdev *sd, unsigned int pad,
+				 struct v4l2_mbus_frame_desc *fd)
+{
+	const struct v4l2_mbus_framefmt *fmt;
+	struct v4l2_subdev_state *state;
+	u32 code;
+
+	if (pad != IMX219_PAD_SOURCE)
+		return -EINVAL;
+
+	state = v4l2_subdev_lock_and_get_active_state(sd);
+	fmt = v4l2_subdev_state_get_format(state, IMX219_PAD_SOURCE,
+					   IMX219_STREAM_IMAGE);
+	code = fmt->code;
+	v4l2_subdev_unlock_state(state);
+
+	fd->type = V4L2_MBUS_FRAME_DESC_TYPE_CSI2;
+	fd->num_entries = 1;
+
+	fd->entry[0].pixelcode = code;
+	fd->entry[0].stream = IMX219_STREAM_IMAGE;
+	fd->entry[0].bus.csi2.vc = 0;
+	fd->entry[0].bus.csi2.dt = imx219_format_bpp(code) == 8 ?
+		MIPI_CSI2_DT_RAW8 : MIPI_CSI2_DT_RAW10;
+
+	return 0;
+}
+
 static int imx219_init_state(struct v4l2_subdev *sd,
 			     struct v4l2_subdev_state *state)
 {
@@ -1117,6 +1164,7 @@ static const struct v4l2_subdev_pad_ops imx219_pad_ops = {
 	.set_fmt = imx219_set_pad_format,
 	.get_selection = imx219_get_selection,
 	.enum_frame_size = imx219_enum_frame_size,
+	.get_frame_desc = imx219_get_frame_desc,
 	.enable_streams = imx219_enable_streams,
 	.disable_streams = imx219_disable_streams,
 };
-- 
2.47.3


^ permalink raw reply related	[flat|nested] 88+ messages in thread

* [PATCH v12 60/86] media: imx219: Add embedded data support
  2026-04-09 20:13 [PATCH v12 00/86] Generic line based metadata support, internal pads Sakari Ailus
                   ` (58 preceding siblings ...)
  2026-04-09 20:14 ` [PATCH v12 59/86] media: imx219: Report streams using frame descriptors Sakari Ailus
@ 2026-04-09 20:14 ` Sakari Ailus
  2026-04-09 20:14 ` [PATCH v12 61/86] media: imx219: Add support for generic raw formats Sakari Ailus
                   ` (25 subsequent siblings)
  85 siblings, 0 replies; 88+ messages in thread
From: Sakari Ailus @ 2026-04-09 20:14 UTC (permalink / raw)
  To: linux-media
  Cc: hans, laurent.pinchart, Prabhakar, Kate Hsuan, Dave Stevenson,
	Tommaso Merciai, Benjamin Mugnier, Sylvain Petinot,
	Christophe JAILLET, Julien Massot, Naushir Patuck, Stefan Klug,
	Mirela Rabulea, André Apitzsch, Heimir Thor Sverrisson,
	Kieran Bingham, Mehdi Djait, Ricardo Ribalda Delgado,
	Hans de Goede, Jacopo Mondi, Tomi Valkeinen, David Plowman,
	Yu, Ong Hock, Ng, Khai Wen, Jai Luthra, Rishikesh Donadkar

From: Laurent Pinchart <laurent.pinchart@ideasonboard.com>

The IMX219 generates embedded data unconditionally. Report it as an
additional stream, with a new internal embedded data pad, and update
subdev operations accordingly.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Co-developed-by: Sakari Ailus <sakari.ailus@linux.intel.com>
Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
---
 drivers/media/i2c/imx219.c | 187 +++++++++++++++++++++++++++++++------
 1 file changed, 161 insertions(+), 26 deletions(-)

diff --git a/drivers/media/i2c/imx219.c b/drivers/media/i2c/imx219.c
index d695987839e4..e744b96a08f6 100644
--- a/drivers/media/i2c/imx219.c
+++ b/drivers/media/i2c/imx219.c
@@ -154,6 +154,9 @@
 #define IMX219_PIXEL_ARRAY_HEIGHT	2480U
 #define IMX219_NATIVE_FORMAT		MEDIA_BUS_FMT_SRGGB10_1X10
 
+/* Embedded metadata stream height */
+#define IMX219_EMBEDDED_DATA_HEIGHT	2U
+
 /* Mode : resolution and related config&values */
 struct imx219_mode {
 	/* Frame width */
@@ -345,11 +348,13 @@ static const struct imx219_mode supported_modes[] = {
 enum imx219_pad_ids {
 	IMX219_PAD_SOURCE = 0,
 	IMX219_PAD_IMAGE,
+	IMX219_PAD_EDATA,
 	IMX219_NUM_PADS,
 };
 
 enum imx219_stream_ids {
 	IMX219_STREAM_IMAGE,
+	IMX219_STREAM_EDATA,
 };
 
 struct imx219 {
@@ -375,6 +380,8 @@ struct imx219 {
 
 	/* Two or Four lanes */
 	u8 lanes;
+
+	u64 streams_enabled;
 };
 
 static inline struct imx219 *to_imx219(struct v4l2_subdev *_sd)
@@ -418,6 +425,25 @@ static u32 imx219_get_format_bpp(const struct v4l2_mbus_framefmt *format)
 	}
 }
 
+static u32
+imx219_get_embedded_format_code(const struct v4l2_mbus_framefmt *format)
+{
+	switch (format->code) {
+	case MEDIA_BUS_FMT_SRGGB8_1X8:
+	case MEDIA_BUS_FMT_SGRBG8_1X8:
+	case MEDIA_BUS_FMT_SGBRG8_1X8:
+	case MEDIA_BUS_FMT_SBGGR8_1X8:
+		return MEDIA_BUS_FMT_META_8;
+
+	case MEDIA_BUS_FMT_SRGGB10_1X10:
+	case MEDIA_BUS_FMT_SGRBG10_1X10:
+	case MEDIA_BUS_FMT_SGBRG10_1X10:
+	case MEDIA_BUS_FMT_SBGGR10_1X10:
+	default:
+		return MEDIA_BUS_FMT_META_10;
+	}
+}
+
 static void imx219_get_binning(struct v4l2_subdev_state *state, u8 *bin_h,
 			       u8 *bin_v)
 {
@@ -749,6 +775,15 @@ static int imx219_enable_streams(struct v4l2_subdev *sd,
 	struct i2c_client *client = v4l2_get_subdevdata(&imx219->sd);
 	int ret;
 
+	/*
+	 * The image stream controls sensor streaming, as embedded data isn't
+	 * controllable independently.
+	 */
+	if (imx219->streams_enabled) {
+		imx219->streams_enabled |= streams_mask;
+		return 0;
+	}
+
 	ret = pm_runtime_resume_and_get(&client->dev);
 	if (ret < 0)
 		return ret;
@@ -791,6 +826,8 @@ static int imx219_enable_streams(struct v4l2_subdev *sd,
 	__v4l2_ctrl_grab(imx219->vflip, true);
 	__v4l2_ctrl_grab(imx219->hflip, true);
 
+	imx219->streams_enabled = streams_mask;
+
 	return 0;
 
 err_rpm_put:
@@ -806,6 +843,10 @@ static int imx219_disable_streams(struct v4l2_subdev *sd,
 	struct i2c_client *client = v4l2_get_subdevdata(&imx219->sd);
 	int ret;
 
+	imx219->streams_enabled &= ~streams_mask;
+	if (imx219->streams_enabled)
+		return 0;
+
 	/* set stream off register */
 	ret = cci_write(imx219->regmap, IMX219_REG_MODE_SELECT,
 			IMX219_MODE_STANDBY, NULL);
@@ -826,17 +867,32 @@ static int imx219_enum_mbus_code(struct v4l2_subdev *sd,
 {
 	struct imx219 *imx219 = to_imx219(sd);
 
-	if (code->pad == IMX219_PAD_IMAGE) {
-		/* The internal image pad is hardwired to the native format. */
+	switch (code->pad) {
+	case IMX219_PAD_IMAGE:
 		if (code->index > 0)
 			return -EINVAL;
 
-		code->code = IMX219_NATIVE_FORMAT;
-	} else {
-		/*
-		 * On the source pad, the sensor supports multiple raw formats
-		 * with different bit depths.
-		 */
+		code->code = MEDIA_BUS_FMT_RAW_10;
+		return 0;
+
+	case IMX219_PAD_EDATA:
+		if (code->index > 0)
+			return -EINVAL;
+
+		code->code = MEDIA_BUS_FMT_META_10;
+		return 0;
+
+	case IMX219_PAD_SOURCE:
+	default:
+		break;
+	}
+
+	/*
+	 * On the source pad, the sensor supports multiple image raw formats
+	 * with different bit depths. The embedded data format bit depth
+	 * follows the image stream.
+	 */
+	if (code->stream == IMX219_STREAM_IMAGE) {
 		u32 format;
 
 		if (code->index >= ARRAY_SIZE(imx219_mbus_formats) / 4)
@@ -844,6 +900,15 @@ static int imx219_enum_mbus_code(struct v4l2_subdev *sd,
 
 		format = imx219_mbus_formats[code->index * 4];
 		code->code = imx219_get_format_code(imx219, format);
+	} else {
+		struct v4l2_mbus_framefmt *fmt;
+
+		if (code->index > 0)
+			return -EINVAL;
+
+		fmt = v4l2_subdev_state_get_format(state, IMX219_PAD_SOURCE,
+						   IMX219_STREAM_EDATA);
+		code->code = fmt->code;
 	}
 
 	return 0;
@@ -855,15 +920,33 @@ static int imx219_enum_frame_size(struct v4l2_subdev *sd,
 {
 	struct imx219 *imx219 = to_imx219(sd);
 
-	if (fse->pad == IMX219_PAD_IMAGE) {
+	switch (fse->pad) {
+	case IMX219_PAD_IMAGE:
 		if (fse->code != IMX219_NATIVE_FORMAT || fse->index > 0)
 			return -EINVAL;
 
-		fse->min_width = IMX219_PIXEL_ARRAY_WIDTH;
-		fse->max_width = IMX219_PIXEL_ARRAY_WIDTH;
-		fse->min_height = IMX219_PIXEL_ARRAY_HEIGHT;
-		fse->max_height = IMX219_PIXEL_ARRAY_HEIGHT;
-	} else {
+		fse->min_width = IMX219_VISIBLE_WIDTH;
+		fse->max_width = IMX219_VISIBLE_WIDTH;
+		fse->min_height = IMX219_VISIBLE_HEIGHT;
+		fse->max_height = IMX219_VISIBLE_HEIGHT;
+		return 0;
+
+	case IMX219_PAD_EDATA:
+		if (fse->code != MEDIA_BUS_FMT_META_8 || fse->index > 0)
+			return -EINVAL;
+
+		fse->min_width = IMX219_VISIBLE_WIDTH;
+		fse->max_width = IMX219_VISIBLE_WIDTH;
+		fse->min_height = IMX219_EMBEDDED_DATA_HEIGHT;
+		fse->max_height = IMX219_EMBEDDED_DATA_HEIGHT;
+		return 0;
+
+	case IMX219_PAD_SOURCE:
+	default:
+		break;
+	}
+
+	if (fse->stream == IMX219_STREAM_IMAGE) {
 		if (fse->code != imx219_get_format_code(imx219, fse->code) ||
 		    fse->index >= ARRAY_SIZE(supported_modes))
 			return -EINVAL;
@@ -872,6 +955,21 @@ static int imx219_enum_frame_size(struct v4l2_subdev *sd,
 		fse->max_width = fse->min_width;
 		fse->min_height = supported_modes[fse->index].height;
 		fse->max_height = fse->min_height;
+	} else {
+		struct v4l2_mbus_framefmt *fmt;
+
+		fmt = v4l2_subdev_state_get_format(state, IMX219_PAD_SOURCE,
+						   IMX219_STREAM_EDATA);
+		if (fse->code != fmt->code)
+			return -EINVAL;
+
+		if (fse->index > 0)
+			return -EINVAL;
+
+		fse->min_width = fmt->width;
+		fse->max_width = fmt->width;
+		fse->min_height = IMX219_EMBEDDED_DATA_HEIGHT;
+		fse->max_height = IMX219_EMBEDDED_DATA_HEIGHT;
 	}
 
 	return 0;
@@ -883,13 +981,16 @@ static int imx219_set_pad_format_compat(struct v4l2_subdev *sd,
 {
 	struct imx219 *imx219 = to_imx219(sd);
 	const struct imx219_mode *mode;
-	struct v4l2_mbus_framefmt *format;
+	struct v4l2_mbus_framefmt *format, *embedded_format;
 	struct v4l2_rect *crop;
 	u8 bin_h, bin_v, bin_hv;
 	int ret;
 
 	format = v4l2_subdev_state_get_format(state, IMX219_PAD_SOURCE,
 					      IMX219_STREAM_IMAGE);
+	embedded_format =
+		v4l2_subdev_state_get_format(state, IMX219_PAD_SOURCE,
+					     IMX219_STREAM_EDATA);
 
 	/*
 	 * Adjust the requested format to match the closest mode. The Bayer
@@ -911,6 +1012,8 @@ static int imx219_set_pad_format_compat(struct v4l2_subdev *sd,
 
 	*format = fmt->format;
 
+	embedded_format->code = imx219_get_embedded_format_code(format);
+
 	/*
 	 * Use binning to maximize the crop rectangle size, and centre it in the
 	 * sensor.
@@ -988,7 +1091,7 @@ static int imx219_set_pad_format(struct v4l2_subdev *sd,
 	if (!(ci && ci->client_caps & V4L2_SUBDEV_CLIENT_CAP_COMMON_RAW_SENSOR))
 		return imx219_set_pad_format_compat(sd, state, fmt);
 
-	if (fmt->pad != IMX219_PAD_SOURCE)
+	if (fmt->pad != IMX219_PAD_SOURCE && fmt->stream != IMX219_STREAM_IMAGE)
 		return v4l2_subdev_get_fmt(sd, ci, state, fmt);
 
 	format = v4l2_subdev_state_get_format(state, IMX219_PAD_SOURCE,
@@ -1038,7 +1141,11 @@ static int imx219_get_selection(struct v4l2_subdev *sd,
 		return -EINVAL;
 	}
 
-	if (sel->pad != IMX219_PAD_IMAGE)
+	/*
+	 * The embedded data stream doesn't support selection rectangles,
+	 * neither on the embedded data pad nor on the source pad.
+	 */
+	if (sel->pad != IMX219_PAD_IMAGE || sel->stream != IMX219_STREAM_IMAGE)
 		return -EINVAL;
 
 	switch (sel->target) {
@@ -1068,35 +1175,41 @@ static int imx219_get_selection(struct v4l2_subdev *sd,
 static int imx219_get_frame_desc(struct v4l2_subdev *sd, unsigned int pad,
 				 struct v4l2_mbus_frame_desc *fd)
 {
-	const struct v4l2_mbus_framefmt *fmt;
 	struct v4l2_subdev_state *state;
-	u32 code;
+	u32 img_code;
+	u32 ed_code;
 
 	if (pad != IMX219_PAD_SOURCE)
 		return -EINVAL;
 
 	state = v4l2_subdev_lock_and_get_active_state(sd);
-	fmt = v4l2_subdev_state_get_format(state, IMX219_PAD_SOURCE,
-					   IMX219_STREAM_IMAGE);
-	code = fmt->code;
+	img_code = v4l2_subdev_state_get_format(state, IMX219_PAD_SOURCE,
+						IMX219_STREAM_IMAGE)->code;
+	ed_code = v4l2_subdev_state_get_format(state, IMX219_PAD_SOURCE,
+					       IMX219_STREAM_EDATA)->code;
 	v4l2_subdev_unlock_state(state);
 
 	fd->type = V4L2_MBUS_FRAME_DESC_TYPE_CSI2;
-	fd->num_entries = 1;
+	fd->num_entries = 2;
 
-	fd->entry[0].pixelcode = code;
+	fd->entry[0].pixelcode = img_code;
 	fd->entry[0].stream = IMX219_STREAM_IMAGE;
 	fd->entry[0].bus.csi2.vc = 0;
-	fd->entry[0].bus.csi2.dt = imx219_format_bpp(code) == 8 ?
+	fd->entry[0].bus.csi2.dt = imx219_format_bpp(img_code) == 8 ?
 		MIPI_CSI2_DT_RAW8 : MIPI_CSI2_DT_RAW10;
 
+	fd->entry[1].pixelcode = ed_code;
+	fd->entry[1].stream = IMX219_STREAM_EDATA;
+	fd->entry[1].bus.csi2.vc = 0;
+	fd->entry[1].bus.csi2.dt = MIPI_CSI2_DT_EMBEDDED_8B;
+
 	return 0;
 }
 
 static int imx219_init_state(struct v4l2_subdev *sd,
 			     struct v4l2_subdev_state *state)
 {
-	struct v4l2_subdev_route routes[1] = {
+	struct v4l2_subdev_route routes[] = {
 		{
 			.sink_pad = IMX219_PAD_IMAGE,
 			.sink_stream = 0,
@@ -1105,6 +1218,14 @@ static int imx219_init_state(struct v4l2_subdev *sd,
 			.flags = V4L2_SUBDEV_ROUTE_FL_ACTIVE |
 				 V4L2_SUBDEV_ROUTE_FL_IMMUTABLE |
 				 V4L2_SUBDEV_ROUTE_FL_STATIC,
+		}, {
+			.sink_pad = IMX219_PAD_EDATA,
+			.sink_stream = 0,
+			.source_pad = IMX219_PAD_SOURCE,
+			.source_stream = IMX219_STREAM_EDATA,
+			.flags = V4L2_SUBDEV_ROUTE_FL_ACTIVE |
+				 V4L2_SUBDEV_ROUTE_FL_IMMUTABLE |
+				 V4L2_SUBDEV_ROUTE_FL_STATIC,
 		},
 	};
 	struct v4l2_subdev_krouting routing = {
@@ -1127,6 +1248,11 @@ static int imx219_init_state(struct v4l2_subdev *sd,
 	struct v4l2_mbus_framefmt *source_format =
 		v4l2_subdev_state_get_format(state, IMX219_PAD_SOURCE,
 					     IMX219_STREAM_IMAGE);
+	struct v4l2_mbus_framefmt *embedded_format =
+		v4l2_subdev_state_get_format(state, IMX219_PAD_EDATA);
+	struct v4l2_mbus_framefmt *embedded_source_format =
+		v4l2_subdev_state_get_format(state, IMX219_PAD_SOURCE,
+					     IMX219_STREAM_EDATA);
 
 	/* The image pad models the pixel array, and thus has a fixed format. */
 	pixel_array_format->code = MEDIA_BUS_FMT_RAW_10;
@@ -1151,6 +1277,13 @@ static int imx219_init_state(struct v4l2_subdev *sd,
 	source_format->width = compose->width;
 	source_format->height = compose->height;
 
+	embedded_format->code = MEDIA_BUS_FMT_META_10;
+	embedded_format->width = source_format->width;
+	embedded_format->height = IMX219_EMBEDDED_DATA_HEIGHT;
+	embedded_format->field = V4L2_FIELD_NONE;
+
+	*embedded_source_format = *embedded_format;
+
 	return 0;
 }
 
@@ -1426,6 +1559,8 @@ static int imx219_probe(struct i2c_client *client)
 	imx219->pads[IMX219_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE;
 	imx219->pads[IMX219_PAD_IMAGE].flags = MEDIA_PAD_FL_SINK
 					     | MEDIA_PAD_FL_INTERNAL;
+	imx219->pads[IMX219_PAD_EDATA].flags = MEDIA_PAD_FL_SINK
+					     | MEDIA_PAD_FL_INTERNAL;
 
 	ret = media_entity_pads_init(&imx219->sd.entity,
 				     ARRAY_SIZE(imx219->pads), imx219->pads);
-- 
2.47.3


^ permalink raw reply related	[flat|nested] 88+ messages in thread

* [PATCH v12 61/86] media: imx219: Add support for generic raw formats
  2026-04-09 20:13 [PATCH v12 00/86] Generic line based metadata support, internal pads Sakari Ailus
                   ` (59 preceding siblings ...)
  2026-04-09 20:14 ` [PATCH v12 60/86] media: imx219: Add embedded data support Sakari Ailus
@ 2026-04-09 20:14 ` Sakari Ailus
  2026-04-09 20:14 ` [PATCH v12 62/86] media: imx219: Add V4L2_CID_BINNING_FACTORS Sakari Ailus
                   ` (24 subsequent siblings)
  85 siblings, 0 replies; 88+ messages in thread
From: Sakari Ailus @ 2026-04-09 20:14 UTC (permalink / raw)
  To: linux-media
  Cc: hans, laurent.pinchart, Prabhakar, Kate Hsuan, Dave Stevenson,
	Tommaso Merciai, Benjamin Mugnier, Sylvain Petinot,
	Christophe JAILLET, Julien Massot, Naushir Patuck, Stefan Klug,
	Mirela Rabulea, André Apitzsch, Heimir Thor Sverrisson,
	Kieran Bingham, Mehdi Djait, Ricardo Ribalda Delgado,
	Hans de Goede, Jacopo Mondi, Tomi Valkeinen, David Plowman,
	Yu, Ong Hock, Ng, Khai Wen, Jai Luthra, Rishikesh Donadkar

Add support for colour pattern agnostic raw formats, including controls to
convey the colour pattern and the configuration model (common raw sensor).

Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
---
 drivers/media/i2c/imx219.c | 40 +++++++++++++++++++++++++++++++++++---
 1 file changed, 37 insertions(+), 3 deletions(-)

diff --git a/drivers/media/i2c/imx219.c b/drivers/media/i2c/imx219.c
index e744b96a08f6..a7d59d16add5 100644
--- a/drivers/media/i2c/imx219.c
+++ b/drivers/media/i2c/imx219.c
@@ -290,6 +290,11 @@ static const u32 imx219_mbus_formats[] = {
 	MEDIA_BUS_FMT_SBGGR8_1X8,
 };
 
+static const u32 imx219_mbus_formats_generic[] = {
+	MEDIA_BUS_FMT_RAW_10,
+	MEDIA_BUS_FMT_RAW_8,
+};
+
 /*
  * Initialisation delay between XCLR low->high and the moment when the sensor
  * can start capture (i.e. can leave software stanby) must be not less than:
@@ -394,6 +399,10 @@ static u32 imx219_get_format_code(struct imx219 *imx219, u32 code)
 {
 	unsigned int i;
 
+	for (i = 0; i < ARRAY_SIZE(imx219_mbus_formats_generic); i++)
+		if (imx219_mbus_formats_generic[i] == code)
+			return code;
+
 	for (i = 0; i < ARRAY_SIZE(imx219_mbus_formats); i++)
 		if (imx219_mbus_formats[i] == code)
 			break;
@@ -414,12 +423,14 @@ static u32 imx219_get_format_bpp(const struct v4l2_mbus_framefmt *format)
 	case MEDIA_BUS_FMT_SGRBG8_1X8:
 	case MEDIA_BUS_FMT_SGBRG8_1X8:
 	case MEDIA_BUS_FMT_SBGGR8_1X8:
+	case MEDIA_BUS_FMT_RAW_8:
 		return 8;
 
 	case MEDIA_BUS_FMT_SRGGB10_1X10:
 	case MEDIA_BUS_FMT_SGRBG10_1X10:
 	case MEDIA_BUS_FMT_SGBRG10_1X10:
 	case MEDIA_BUS_FMT_SBGGR10_1X10:
+	case MEDIA_BUS_FMT_RAW_10:
 	default:
 		return 10;
 	}
@@ -433,12 +444,14 @@ imx219_get_embedded_format_code(const struct v4l2_mbus_framefmt *format)
 	case MEDIA_BUS_FMT_SGRBG8_1X8:
 	case MEDIA_BUS_FMT_SGBRG8_1X8:
 	case MEDIA_BUS_FMT_SBGGR8_1X8:
+	case MEDIA_BUS_FMT_RAW_8:
 		return MEDIA_BUS_FMT_META_8;
 
 	case MEDIA_BUS_FMT_SRGGB10_1X10:
 	case MEDIA_BUS_FMT_SGRBG10_1X10:
 	case MEDIA_BUS_FMT_SGBRG10_1X10:
 	case MEDIA_BUS_FMT_SBGGR10_1X10:
+	case MEDIA_BUS_FMT_RAW_10:
 	default:
 		return MEDIA_BUS_FMT_META_10;
 	}
@@ -662,6 +675,20 @@ static int imx219_init_controls(struct imx219 *imx219)
 		/* The "Solid color" pattern is white by default */
 	}
 
+	v4l2_ctrl_new_std(ctrl_hdlr, NULL, V4L2_CID_CFA_PATTERN,
+			  V4L2_CFA_PATTERN_RGGB, V4L2_CFA_PATTERN_RGGB,
+			  1, V4L2_CFA_PATTERN_RGGB);
+	v4l2_ctrl_new_std(ctrl_hdlr, NULL,
+			  V4L2_CID_CFA_PATTERN_FLIP,
+			  0, V4L2_CFA_PATTERN_FLIP_BOTH,
+			  0, V4L2_CFA_PATTERN_FLIP_BOTH);
+	v4l2_ctrl_new_std(ctrl_hdlr, NULL, V4L2_CID_METADATA_LAYOUT,
+			  0, V4L2_METADATA_LAYOUT_CCS,
+			  1, V4L2_METADATA_LAYOUT_CCS);
+	v4l2_ctrl_new_std(ctrl_hdlr, NULL, V4L2_CID_CONFIG_MODEL,
+			  0, V4L2_CONFIG_MODEL_COMMON_RAW_SENSOR,
+			  0, V4L2_CONFIG_MODEL_COMMON_RAW_SENSOR);
+
 	if (ctrl_hdlr->error) {
 		ret = ctrl_hdlr->error;
 		dev_err_probe(&client->dev, ret, "Control init failed\n");
@@ -895,10 +922,17 @@ static int imx219_enum_mbus_code(struct v4l2_subdev *sd,
 	if (code->stream == IMX219_STREAM_IMAGE) {
 		u32 format;
 
-		if (code->index >= ARRAY_SIZE(imx219_mbus_formats) / 4)
-			return -EINVAL;
+		if (code->index >= ARRAY_SIZE(imx219_mbus_formats) / 4) {
+			u32 idx = code->index -
+				ARRAY_SIZE(imx219_mbus_formats) / 4;
+
+			if (idx >= ARRAY_SIZE(imx219_mbus_formats_generic))
+				return -EINVAL;
 
-		format = imx219_mbus_formats[code->index * 4];
+			format = imx219_mbus_formats_generic[idx];
+		} else {
+			format = imx219_mbus_formats[code->index * 4];
+		}
 		code->code = imx219_get_format_code(imx219, format);
 	} else {
 		struct v4l2_mbus_framefmt *fmt;
-- 
2.47.3


^ permalink raw reply related	[flat|nested] 88+ messages in thread

* [PATCH v12 62/86] media: imx219: Add V4L2_CID_BINNING_FACTORS
  2026-04-09 20:13 [PATCH v12 00/86] Generic line based metadata support, internal pads Sakari Ailus
                   ` (60 preceding siblings ...)
  2026-04-09 20:14 ` [PATCH v12 61/86] media: imx219: Add support for generic raw formats Sakari Ailus
@ 2026-04-09 20:14 ` Sakari Ailus
  2026-04-09 20:14 ` [PATCH v12 63/86] media: imx219: Allow configuring cropping and binning through CRSM Sakari Ailus
                   ` (23 subsequent siblings)
  85 siblings, 0 replies; 88+ messages in thread
From: Sakari Ailus @ 2026-04-09 20:14 UTC (permalink / raw)
  To: linux-media
  Cc: hans, laurent.pinchart, Prabhakar, Kate Hsuan, Dave Stevenson,
	Tommaso Merciai, Benjamin Mugnier, Sylvain Petinot,
	Christophe JAILLET, Julien Massot, Naushir Patuck, Stefan Klug,
	Mirela Rabulea, André Apitzsch, Heimir Thor Sverrisson,
	Kieran Bingham, Mehdi Djait, Ricardo Ribalda Delgado,
	Hans de Goede, Jacopo Mondi, Tomi Valkeinen, David Plowman,
	Yu, Ong Hock, Ng, Khai Wen, Jai Luthra, Rishikesh Donadkar

Add support for the V4L2_CID_BINNING_FACTORS control. It'll be read-only
for now.

Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
---
 drivers/media/i2c/imx219.c | 77 +++++++++++++++++++++++---------------
 1 file changed, 47 insertions(+), 30 deletions(-)

diff --git a/drivers/media/i2c/imx219.c b/drivers/media/i2c/imx219.c
index a7d59d16add5..7ed53810f941 100644
--- a/drivers/media/i2c/imx219.c
+++ b/drivers/media/i2c/imx219.c
@@ -382,6 +382,7 @@ struct imx219 {
 	struct v4l2_ctrl *hflip;
 	struct v4l2_ctrl *vblank;
 	struct v4l2_ctrl *hblank;
+	struct v4l2_ctrl *binning;
 
 	/* Two or Four lanes */
 	u8 lanes;
@@ -457,31 +458,27 @@ imx219_get_embedded_format_code(const struct v4l2_mbus_framefmt *format)
 	}
 }
 
-static void imx219_get_binning(struct v4l2_subdev_state *state, u8 *bin_h,
-			       u8 *bin_v)
-{
-	const struct v4l2_mbus_framefmt *format =
-		v4l2_subdev_state_get_format(state, IMX219_PAD_SOURCE,
-					      IMX219_STREAM_IMAGE);
-	const struct v4l2_rect *crop =
-		v4l2_subdev_state_get_crop(state, IMX219_PAD_IMAGE);
-	u32 hbin = crop->width / format->width;
-	u32 vbin = crop->height / format->height;
-
-	if (hbin == 2 && vbin == 2) {
-		*bin_h = IMX219_BINNING_X2_ANALOG;
-		*bin_v = IMX219_BINNING_X2_ANALOG;
-	} else {
-		*bin_h = IMX219_BINNING_NONE;
-		*bin_v = IMX219_BINNING_NONE;
-	}
-
-}
-
 /* -----------------------------------------------------------------------------
  * Controls
  */
 
+enum imx219_binning_factor_indices {
+	IMX219_BINNING_11,
+	IMX219_BINNING_22,
+};
+
+static const struct {
+	u8 h, v;
+} imx219_binnings[] = {
+	[IMX219_BINNING_11] = { IMX219_BINNING_NONE, IMX219_BINNING_NONE, },
+	[IMX219_BINNING_22] = { IMX219_BINNING_X2_ANALOG, IMX219_BINNING_X2_ANALOG, },
+};
+
+static const s64 imx219_binning_factors[] = {
+	[IMX219_BINNING_11] = V4L2_BINNING_FACTORS_MAKE(1, 1, 1, 1),
+	[IMX219_BINNING_22] = V4L2_BINNING_FACTORS_MAKE(2, 1, 2, 1),
+};
+
 static int imx219_set_ctrl(struct v4l2_ctrl *ctrl)
 {
 	struct imx219 *imx219 =
@@ -495,7 +492,8 @@ static int imx219_set_ctrl(struct v4l2_ctrl *ctrl)
 	format = v4l2_subdev_state_get_format(state, IMX219_PAD_SOURCE,
 					      IMX219_STREAM_IMAGE);
 
-	if (ctrl->id == V4L2_CID_VBLANK) {
+	switch (ctrl->id) {
+	case V4L2_CID_VBLANK: {
 		int exposure_max, exposure_def;
 
 		/* Update max exposure while meeting expected vblanking */
@@ -509,7 +507,10 @@ static int imx219_set_ctrl(struct v4l2_ctrl *ctrl)
 					       exposure_def);
 		if (ret)
 			return ret;
-
+		break;
+	}
+	case V4L2_CID_BINNING_FACTORS:
+		return 0;
 	}
 
 	/*
@@ -587,6 +588,9 @@ static unsigned long imx219_get_pixel_rate(struct imx219 *imx219)
 	return (imx219->lanes == 2) ? IMX219_PIXEL_RATE : IMX219_PIXEL_RATE_4LANE;
 }
 
+static_assert(ARRAY_SIZE(imx219_binnings) ==
+	      ARRAY_SIZE(imx219_binning_factors));
+
 /* Initialize control handlers */
 static int imx219_init_controls(struct imx219 *imx219)
 {
@@ -688,6 +692,12 @@ static int imx219_init_controls(struct imx219 *imx219)
 	v4l2_ctrl_new_std(ctrl_hdlr, NULL, V4L2_CID_CONFIG_MODEL,
 			  0, V4L2_CONFIG_MODEL_COMMON_RAW_SENSOR,
 			  0, V4L2_CONFIG_MODEL_COMMON_RAW_SENSOR);
+	imx219->binning =
+		v4l2_ctrl_new_int_menu(ctrl_hdlr, &imx219_ctrl_ops,
+				       V4L2_CID_BINNING_FACTORS,
+				       ARRAY_SIZE(imx219_binning_factors) - 1,
+				       IMX219_BINNING_11,
+				       imx219_binning_factors);
 
 	if (ctrl_hdlr->error) {
 		ret = ctrl_hdlr->error;
@@ -695,6 +705,8 @@ static int imx219_init_controls(struct imx219 *imx219)
 		goto error;
 	}
 
+	imx219->binning->flags = V4L2_CTRL_FLAG_READ_ONLY;
+
 	ret = v4l2_fwnode_device_parse(&client->dev, &props);
 	if (ret)
 		goto error;
@@ -746,7 +758,6 @@ static int imx219_set_framefmt(struct imx219 *imx219,
 {
 	const struct v4l2_mbus_framefmt *format;
 	const struct v4l2_rect *crop;
-	u8 bin_h, bin_v;
 	u32 bpp;
 	int ret = 0;
 
@@ -764,9 +775,10 @@ static int imx219_set_framefmt(struct imx219 *imx219,
 	cci_write(imx219->regmap, IMX219_REG_Y_ADD_END_A,
 		  crop->top - IMX219_VISIBLE_TOP + crop->height - 1, &ret);
 
-	imx219_get_binning(state, &bin_h, &bin_v);
-	cci_write(imx219->regmap, IMX219_REG_BINNING_MODE_H, bin_h, &ret);
-	cci_write(imx219->regmap, IMX219_REG_BINNING_MODE_V, bin_v, &ret);
+	cci_write(imx219->regmap, IMX219_REG_BINNING_MODE_H,
+		  imx219_binnings[imx219->binning->val].h, &ret);
+	cci_write(imx219->regmap, IMX219_REG_BINNING_MODE_V,
+		  imx219_binnings[imx219->binning->val].v, &ret);
 
 	cci_write(imx219->regmap, IMX219_REG_X_OUTPUT_SIZE,
 		  format->width, &ret);
@@ -1068,6 +1080,11 @@ static int imx219_set_pad_format_compat(struct v4l2_subdev *sd,
 		int llp_min;
 		int pixel_rate;
 
+		ret = __v4l2_ctrl_s_ctrl(imx219->binning, bin_hv == 1 ?
+					 IMX219_BINNING_11 : IMX219_BINNING_22);
+		if (ret)
+			return ret;
+
 		/* Update limits and set FPS to default */
 		ret = __v4l2_ctrl_modify_range(imx219->vblank,
 					       (int)(mode->height / bin_hv),
@@ -1089,9 +1106,9 @@ static int imx219_set_pad_format_compat(struct v4l2_subdev *sd,
 		 * operates on two lines together. So we switch to a higher
 		 * minimum of 3560.
 		 */
-		imx219_get_binning(state, &bin_h, &bin_v);
-		llp_min = (bin_h & bin_v) == IMX219_BINNING_X2_ANALOG ?
-				  IMX219_BINNED_LLP_MIN : IMX219_LLP_MIN;
+		llp_min = imx219_binnings[imx219->binning->val].h ==
+			IMX219_BINNING_X2_ANALOG ?
+			IMX219_BINNED_LLP_MIN : IMX219_LLP_MIN;
 		ret = __v4l2_ctrl_modify_range(imx219->hblank,
 					       llp_min - mode->width,
 					       IMX219_LLP_MAX - mode->width, 1,
-- 
2.47.3


^ permalink raw reply related	[flat|nested] 88+ messages in thread

* [PATCH v12 63/86] media: imx219: Allow configuring cropping and binning through CRSM
  2026-04-09 20:13 [PATCH v12 00/86] Generic line based metadata support, internal pads Sakari Ailus
                   ` (61 preceding siblings ...)
  2026-04-09 20:14 ` [PATCH v12 62/86] media: imx219: Add V4L2_CID_BINNING_FACTORS Sakari Ailus
@ 2026-04-09 20:14 ` Sakari Ailus
  2026-04-09 20:14 ` [PATCH v12 64/86] media: imx219: Support LINE_LENGTH_PIXELS and FRAME_LENGTH_LINES controls Sakari Ailus
                   ` (22 subsequent siblings)
  85 siblings, 0 replies; 88+ messages in thread
From: Sakari Ailus @ 2026-04-09 20:14 UTC (permalink / raw)
  To: linux-media
  Cc: hans, laurent.pinchart, Prabhakar, Kate Hsuan, Dave Stevenson,
	Tommaso Merciai, Benjamin Mugnier, Sylvain Petinot,
	Christophe JAILLET, Julien Massot, Naushir Patuck, Stefan Klug,
	Mirela Rabulea, André Apitzsch, Heimir Thor Sverrisson,
	Kieran Bingham, Mehdi Djait, Ricardo Ribalda Delgado,
	Hans de Goede, Jacopo Mondi, Tomi Valkeinen, David Plowman,
	Yu, Ong Hock, Ng, Khai Wen, Jai Luthra, Rishikesh Donadkar

Enable the configuration of cropping and binning through the Common Raw
Sensor Model. Also change the minimum embedded data line length the same
as that of the output pixel data line.

Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
---
 drivers/media/i2c/imx219.c | 104 +++++++++++++++++++++++++++++++++----
 1 file changed, 95 insertions(+), 9 deletions(-)

diff --git a/drivers/media/i2c/imx219.c b/drivers/media/i2c/imx219.c
index 7ed53810f941..591feb3d539f 100644
--- a/drivers/media/i2c/imx219.c
+++ b/drivers/media/i2c/imx219.c
@@ -154,6 +154,9 @@
 #define IMX219_PIXEL_ARRAY_HEIGHT	2480U
 #define IMX219_NATIVE_FORMAT		MEDIA_BUS_FMT_SRGGB10_1X10
 
+#define IMX219_OUTPUT_X_SIZE_MIN	0x100
+#define IMX219_OUTPUT_Y_SIZE_MIN	0x100
+
 /* Embedded metadata stream height */
 #define IMX219_EMBEDDED_DATA_HEIGHT	2U
 
@@ -479,6 +482,45 @@ static const s64 imx219_binning_factors[] = {
 	[IMX219_BINNING_22] = V4L2_BINNING_FACTORS_MAKE(2, 1, 2, 1),
 };
 
+static void imx219_apply_binning(struct v4l2_subdev_state *state,
+				 struct v4l2_rect *crop, unsigned int index)
+{
+	struct v4l2_rect *compose =
+		v4l2_subdev_state_get_compose(state, IMX219_PAD_IMAGE);
+	struct v4l2_mbus_framefmt *source_format =
+		v4l2_subdev_state_get_format(state, IMX219_PAD_SOURCE,
+					     IMX219_STREAM_IMAGE);
+	struct v4l2_mbus_framefmt *embedded_source_format =
+		v4l2_subdev_state_get_format(state, IMX219_PAD_SOURCE,
+					     IMX219_STREAM_EDATA);
+	s64 binning = imx219_binning_factors[index];
+
+	crop->width = clamp(crop->width, IMX219_OUTPUT_X_SIZE_MIN *
+			    V4L2_BINNING_FACTORS_HNUM(binning),
+			    IMX219_VISIBLE_WIDTH) & ~1;
+	crop->height = clamp(crop->height, IMX219_OUTPUT_Y_SIZE_MIN *
+			     V4L2_BINNING_FACTORS_VNUM(binning),
+			     IMX219_VISIBLE_HEIGHT) & ~1;
+	crop->left = clamp((unsigned int)crop->left, IMX219_VISIBLE_LEFT,
+			   IMX219_VISIBLE_LEFT + IMX219_VISIBLE_WIDTH -
+			   crop->width);
+	crop->top = clamp((unsigned int)crop->top, IMX219_VISIBLE_TOP,
+			  IMX219_VISIBLE_TOP + IMX219_VISIBLE_HEIGHT -
+			  crop->height);
+
+	compose->width = crop->width / V4L2_BINNING_FACTORS_HNUM(binning);
+	compose->height = crop->height / V4L2_BINNING_FACTORS_VNUM(binning);
+
+	source_format->width = compose->width;
+	source_format->height = compose->height;
+
+	struct v4l2_mbus_framefmt *embedded_format =
+		v4l2_subdev_state_get_format(state, IMX219_PAD_EDATA);
+
+	embedded_format->width =
+		embedded_source_format->width = source_format->width;
+}
+
 static int imx219_set_ctrl(struct v4l2_ctrl *ctrl)
 {
 	struct imx219 *imx219 =
@@ -509,9 +551,24 @@ static int imx219_set_ctrl(struct v4l2_ctrl *ctrl)
 			return ret;
 		break;
 	}
-	case V4L2_CID_BINNING_FACTORS:
+	case V4L2_CID_BINNING_FACTORS: {
+		struct v4l2_rect *crop =
+			v4l2_subdev_state_get_crop(state, IMX219_PAD_IMAGE);
+
+		if (imx219->streams_enabled)
+			return -EBUSY;
+
+		cci_write(imx219->regmap, IMX219_REG_BINNING_MODE_H,
+			  imx219_binnings[ctrl->val].h, &ret);
+		cci_write(imx219->regmap, IMX219_REG_BINNING_MODE_V,
+			  imx219_binnings[ctrl->val].v, &ret);
+
+		if (ctrl->val != ctrl->cur.val)
+			imx219_apply_binning(state, crop, ctrl->val);
+
 		return 0;
 	}
+	}
 
 	/*
 	 * Applying V4L2 control value only happens
@@ -705,8 +762,6 @@ static int imx219_init_controls(struct imx219 *imx219)
 		goto error;
 	}
 
-	imx219->binning->flags = V4L2_CTRL_FLAG_READ_ONLY;
-
 	ret = v4l2_fwnode_device_parse(&client->dev, &props);
 	if (ret)
 		goto error;
@@ -775,11 +830,6 @@ static int imx219_set_framefmt(struct imx219 *imx219,
 	cci_write(imx219->regmap, IMX219_REG_Y_ADD_END_A,
 		  crop->top - IMX219_VISIBLE_TOP + crop->height - 1, &ret);
 
-	cci_write(imx219->regmap, IMX219_REG_BINNING_MODE_H,
-		  imx219_binnings[imx219->binning->val].h, &ret);
-	cci_write(imx219->regmap, IMX219_REG_BINNING_MODE_V,
-		  imx219_binnings[imx219->binning->val].v, &ret);
-
 	cci_write(imx219->regmap, IMX219_REG_X_OUTPUT_SIZE,
 		  format->width, &ret);
 	cci_write(imx219->regmap, IMX219_REG_Y_OUTPUT_SIZE,
@@ -981,7 +1031,7 @@ static int imx219_enum_frame_size(struct v4l2_subdev *sd,
 		if (fse->code != MEDIA_BUS_FMT_META_8 || fse->index > 0)
 			return -EINVAL;
 
-		fse->min_width = IMX219_VISIBLE_WIDTH;
+		fse->min_width = IMX219_OUTPUT_X_SIZE_MIN;
 		fse->max_width = IMX219_VISIBLE_WIDTH;
 		fse->min_height = IMX219_EMBEDDED_DATA_HEIGHT;
 		fse->max_height = IMX219_EMBEDDED_DATA_HEIGHT;
@@ -1223,6 +1273,41 @@ static int imx219_get_selection(struct v4l2_subdev *sd,
 	}
 }
 
+static int imx219_set_selection(struct v4l2_subdev *sd,
+				const struct v4l2_subdev_client_info *ci,
+				struct v4l2_subdev_state *state,
+				struct v4l2_subdev_selection *sel)
+{
+	if (!(ci && ci->client_caps & V4L2_SUBDEV_CLIENT_CAP_COMMON_RAW_SENSOR))
+		return -EINVAL;
+
+	/*
+	 * The embedded data stream doesn't support selection rectangles,
+	 * neither on the embedded data pad nor on the source pad.
+	 */
+	if (sel->pad != IMX219_PAD_IMAGE || sel->stream != IMX219_STREAM_IMAGE)
+		return -EINVAL;
+
+	switch (sel->target) {
+	case V4L2_SEL_TGT_CROP: {
+		struct imx219 *imx219 = to_imx219(sd);
+		struct v4l2_rect *crop =
+			v4l2_subdev_state_get_crop(state, IMX219_PAD_IMAGE);
+
+		imx219_apply_binning(state, &sel->r, imx219->binning->val);
+
+		*crop = sel->r;
+
+		return 0;
+	}
+	case V4L2_SEL_TGT_COMPOSE:
+		sel->r = *v4l2_subdev_state_get_compose(state, sel->pad);
+		return 0;
+	default:
+		return -EINVAL;
+	}
+}
+
 static int imx219_get_frame_desc(struct v4l2_subdev *sd, unsigned int pad,
 				 struct v4l2_mbus_frame_desc *fd)
 {
@@ -1347,6 +1432,7 @@ static const struct v4l2_subdev_pad_ops imx219_pad_ops = {
 	.get_fmt = v4l2_subdev_get_fmt,
 	.set_fmt = imx219_set_pad_format,
 	.get_selection = imx219_get_selection,
+	.set_selection = imx219_set_selection,
 	.enum_frame_size = imx219_enum_frame_size,
 	.get_frame_desc = imx219_get_frame_desc,
 	.enable_streams = imx219_enable_streams,
-- 
2.47.3


^ permalink raw reply related	[flat|nested] 88+ messages in thread

* [PATCH v12 64/86] media: imx219: Support LINE_LENGTH_PIXELS and FRAME_LENGTH_LINES controls
  2026-04-09 20:13 [PATCH v12 00/86] Generic line based metadata support, internal pads Sakari Ailus
                   ` (62 preceding siblings ...)
  2026-04-09 20:14 ` [PATCH v12 63/86] media: imx219: Allow configuring cropping and binning through CRSM Sakari Ailus
@ 2026-04-09 20:14 ` Sakari Ailus
  2026-04-09 20:14 ` [PATCH v12 65/86] media: ipu6: Add support for raw CFA-agnostic formats Sakari Ailus
                   ` (21 subsequent siblings)
  85 siblings, 0 replies; 88+ messages in thread
From: Sakari Ailus @ 2026-04-09 20:14 UTC (permalink / raw)
  To: linux-media
  Cc: hans, laurent.pinchart, Prabhakar, Kate Hsuan, Dave Stevenson,
	Tommaso Merciai, Benjamin Mugnier, Sylvain Petinot,
	Christophe JAILLET, Julien Massot, Naushir Patuck, Stefan Klug,
	Mirela Rabulea, André Apitzsch, Heimir Thor Sverrisson,
	Kieran Bingham, Mehdi Djait, Ricardo Ribalda Delgado,
	Hans de Goede, Jacopo Mondi, Tomi Valkeinen, David Plowman,
	Yu, Ong Hock, Ng, Khai Wen, Jai Luthra, Rishikesh Donadkar

Support V4L2_CID_LINE_LENGTH_PIXELS and V4L2_CID_FRAME_LENGTH_LINES
controls. These two controls provide direct access to sensor's line and
frame lengths, without requiring a reference crop rectangle.

Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
---
 drivers/media/i2c/imx219.c | 216 ++++++++++++++++++++++++++++---------
 1 file changed, 168 insertions(+), 48 deletions(-)

diff --git a/drivers/media/i2c/imx219.c b/drivers/media/i2c/imx219.c
index 591feb3d539f..9f9503602040 100644
--- a/drivers/media/i2c/imx219.c
+++ b/drivers/media/i2c/imx219.c
@@ -383,13 +383,18 @@ struct imx219 {
 	struct v4l2_ctrl *exposure;
 	struct v4l2_ctrl *vflip;
 	struct v4l2_ctrl *hflip;
+	struct v4l2_ctrl *fll;
 	struct v4l2_ctrl *vblank;
+	struct v4l2_ctrl *llp;
 	struct v4l2_ctrl *hblank;
 	struct v4l2_ctrl *binning;
 
 	/* Two or Four lanes */
 	u8 lanes;
 
+	/* For handling frame timing dependencies. */
+	bool setting_ctrl;
+
 	u64 streams_enabled;
 };
 
@@ -472,9 +477,10 @@ enum imx219_binning_factor_indices {
 
 static const struct {
 	u8 h, v;
+	u16 llp_min;
 } imx219_binnings[] = {
-	[IMX219_BINNING_11] = { IMX219_BINNING_NONE, IMX219_BINNING_NONE, },
-	[IMX219_BINNING_22] = { IMX219_BINNING_X2_ANALOG, IMX219_BINNING_X2_ANALOG, },
+	[IMX219_BINNING_11] = { IMX219_BINNING_NONE, IMX219_BINNING_NONE, IMX219_LLP_MIN, },
+	[IMX219_BINNING_22] = { IMX219_BINNING_X2_ANALOG, IMX219_BINNING_X2_ANALOG, IMX219_BINNED_LLP_MIN, },
 };
 
 static const s64 imx219_binning_factors[] = {
@@ -482,8 +488,9 @@ static const s64 imx219_binning_factors[] = {
 	[IMX219_BINNING_22] = V4L2_BINNING_FACTORS_MAKE(2, 1, 2, 1),
 };
 
-static void imx219_apply_binning(struct v4l2_subdev_state *state,
-				 struct v4l2_rect *crop, unsigned int index)
+static int imx219_apply_binning(struct imx219 *imx219,
+				struct v4l2_subdev_state *state,
+				struct v4l2_rect *crop, unsigned int index)
 {
 	struct v4l2_rect *compose =
 		v4l2_subdev_state_get_compose(state, IMX219_PAD_IMAGE);
@@ -494,6 +501,7 @@ static void imx219_apply_binning(struct v4l2_subdev_state *state,
 		v4l2_subdev_state_get_format(state, IMX219_PAD_SOURCE,
 					     IMX219_STREAM_EDATA);
 	s64 binning = imx219_binning_factors[index];
+	int ret;
 
 	crop->width = clamp(crop->width, IMX219_OUTPUT_X_SIZE_MIN *
 			    V4L2_BINNING_FACTORS_HNUM(binning),
@@ -519,6 +527,102 @@ static void imx219_apply_binning(struct v4l2_subdev_state *state,
 
 	embedded_format->width =
 		embedded_source_format->width = source_format->width;
+
+	int fll_min = IMX219_VBLANK_MIN + source_format->height /
+		V4L2_BINNING_FACTORS_VNUM(binning);
+	ret = __v4l2_ctrl_modify_range(imx219->fll, fll_min, IMX219_FLL_MAX,
+				       1, fll_min);
+	if (ret)
+		return ret;
+
+	int vblank_min = IMX219_VBLANK_MIN -
+		(int)(source_format->height *
+		      (V4L2_BINNING_FACTORS_VNUM(binning) - 1 ) /
+		      V4L2_BINNING_FACTORS_VNUM(binning));
+	ret = __v4l2_ctrl_modify_range(imx219->vblank,
+				       vblank_min,
+				       IMX219_FLL_MAX - source_format->height,
+				       1, vblank_min);
+	if (ret)
+		return ret;
+
+	int llp_min = imx219_binnings[index].llp_min;
+	ret = __v4l2_ctrl_modify_range(imx219->llp, llp_min, IMX219_LLP_MAX, 1,
+				       llp_min);
+	if (ret)
+		return ret;
+
+	return __v4l2_ctrl_modify_range(imx219->hblank,
+					llp_min - (int)source_format->width,
+					IMX219_LLP_MAX -
+					(int)source_format->width, 1,
+					llp_min - (int)source_format->width);
+}
+
+/* Do not copy this function to other drivers, make it generic instead. */
+static int imx219_fll_llp_set(struct imx219 *imx219,
+			      const struct v4l2_mbus_framefmt *format,
+			      struct v4l2_ctrl *src)
+{
+	struct v4l2_ctrl *dest;
+	s32 val;
+	int ret;
+
+	/* Was setting the control user-initiated or were we called again? */
+	if (imx219->setting_ctrl) {
+		imx219->setting_ctrl = false;
+		return 0;
+	}
+
+	/* We're being called for applying a value to register, bail out now. */
+	if (src->val == src->cur.val)
+		return 0;
+
+	switch (src->id) {
+	case V4L2_CID_FRAME_LENGTH_LINES:
+		dest = imx219->vblank;
+		val = src->val - format->height;
+		break;
+	case V4L2_CID_VBLANK:
+		dest = imx219->fll;
+		val = src->val + format->height;
+		break;
+	case V4L2_CID_LINE_LENGTH_PIXELS:
+		dest = imx219->hblank;
+		val = src->val - format->width;
+		break;
+	case V4L2_CID_HBLANK:
+		dest = imx219->llp;
+		val = src->val + format->width;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	if (val == dest->val)
+		return 0;
+
+	imx219->setting_ctrl = true;
+
+	ret = __v4l2_ctrl_s_ctrl(dest, val);
+	if (ret)
+		return ret;
+
+	/*
+	 * Only modify exposure range when setting fll, directly or via vblank.
+	 */
+	if (src->id != V4L2_CID_FRAME_LENGTH_LINES &&
+	    dest->id != V4L2_CID_FRAME_LENGTH_LINES)
+		return 0;
+
+	int exposure_max = imx219->fll->val - IMX219_EXPOSURE_OFFSET;
+
+	return __v4l2_ctrl_modify_range(imx219->exposure,
+					imx219->exposure->minimum,
+					exposure_max,
+					imx219->exposure->step,
+					min(exposure_max,
+					    IMX219_EXPOSURE_DEFAULT));
 }
 
 static int imx219_set_ctrl(struct v4l2_ctrl *ctrl)
@@ -535,22 +639,14 @@ static int imx219_set_ctrl(struct v4l2_ctrl *ctrl)
 					      IMX219_STREAM_IMAGE);
 
 	switch (ctrl->id) {
-	case V4L2_CID_VBLANK: {
-		int exposure_max, exposure_def;
-
-		/* Update max exposure while meeting expected vblanking */
-		exposure_max = format->height + ctrl->val - IMX219_EXPOSURE_OFFSET;
-		exposure_def = (exposure_max < IMX219_EXPOSURE_DEFAULT) ?
-				exposure_max : IMX219_EXPOSURE_DEFAULT;
-		ret = __v4l2_ctrl_modify_range(imx219->exposure,
-					       imx219->exposure->minimum,
-					       exposure_max,
-					       imx219->exposure->step,
-					       exposure_def);
+	case V4L2_CID_FRAME_LENGTH_LINES:
+	case V4L2_CID_VBLANK:
+	case V4L2_CID_LINE_LENGTH_PIXELS:
+	case V4L2_CID_HBLANK:
+		ret = imx219_fll_llp_set(imx219, format, ctrl);
 		if (ret)
 			return ret;
 		break;
-	}
 	case V4L2_CID_BINNING_FACTORS: {
 		struct v4l2_rect *crop =
 			v4l2_subdev_state_get_crop(state, IMX219_PAD_IMAGE);
@@ -558,15 +654,9 @@ static int imx219_set_ctrl(struct v4l2_ctrl *ctrl)
 		if (imx219->streams_enabled)
 			return -EBUSY;
 
-		cci_write(imx219->regmap, IMX219_REG_BINNING_MODE_H,
-			  imx219_binnings[ctrl->val].h, &ret);
-		cci_write(imx219->regmap, IMX219_REG_BINNING_MODE_V,
-			  imx219_binnings[ctrl->val].v, &ret);
-
-		if (ctrl->val != ctrl->cur.val)
-			imx219_apply_binning(state, crop, ctrl->val);
-
-		return 0;
+		ret = imx219_apply_binning(imx219, state, crop, ctrl->val);
+		if (ret)
+			return ret;
 	}
 	}
 
@@ -599,13 +689,22 @@ static int imx219_set_ctrl(struct v4l2_ctrl *ctrl)
 		cci_write(imx219->regmap, IMX219_REG_ORIENTATION,
 			  imx219->hflip->val | imx219->vflip->val << 1, &ret);
 		break;
-	case V4L2_CID_VBLANK:
-		cci_write(imx219->regmap, IMX219_REG_FRM_LENGTH_A,
-			  format->height + ctrl->val, &ret);
+	case V4L2_CID_FRAME_LENGTH_LINES:
+		cci_write(imx219->regmap, IMX219_REG_FRM_LENGTH_A, ctrl->val,
+			  &ret);
 		break;
+	case V4L2_CID_LINE_LENGTH_PIXELS:
+		cci_write(imx219->regmap, IMX219_REG_LINE_LENGTH_A, ctrl->val,
+			  &ret);
+		break;
+	case V4L2_CID_VBLANK:
 	case V4L2_CID_HBLANK:
-		cci_write(imx219->regmap, IMX219_REG_LINE_LENGTH_A,
-			  format->width + ctrl->val, &ret);
+		break;
+	case V4L2_CID_BINNING_FACTORS:
+		cci_write(imx219->regmap, IMX219_REG_BINNING_MODE_H,
+			  imx219_binnings[ctrl->val].h, &ret);
+		cci_write(imx219->regmap, IMX219_REG_BINNING_MODE_V,
+			  imx219_binnings[ctrl->val].v, &ret);
 		break;
 	case V4L2_CID_TEST_PATTERN_RED:
 		cci_write(imx219->regmap, IMX219_REG_TESTP_RED,
@@ -680,10 +779,19 @@ static int imx219_init_controls(struct imx219 *imx219)
 		imx219->link_freq->flags |= V4L2_CTRL_FLAG_READ_ONLY;
 
 	/* Initial blanking and exposure. Limits are updated during set_fmt */
+	imx219->fll = v4l2_ctrl_new_std(ctrl_hdlr, &imx219_ctrl_ops,
+					V4L2_CID_FRAME_LENGTH_LINES,
+					IMX219_VISIBLE_HEIGHT +
+					IMX219_VBLANK_MIN, IMX219_FLL_MAX, 1,
+					mode->fll_def);
 	imx219->vblank = v4l2_ctrl_new_std(ctrl_hdlr, &imx219_ctrl_ops,
 					   V4L2_CID_VBLANK, IMX219_VBLANK_MIN,
 					   IMX219_FLL_MAX - mode->height, 1,
 					   mode->fll_def - mode->height);
+	imx219->llp = v4l2_ctrl_new_std(ctrl_hdlr, &imx219_ctrl_ops,
+					V4L2_CID_LINE_LENGTH_PIXELS,
+					IMX219_LLP_MIN, IMX219_LLP_MAX, 1,
+					IMX219_LLP_MIN);
 	imx219->hblank = v4l2_ctrl_new_std(ctrl_hdlr, &imx219_ctrl_ops,
 					   V4L2_CID_HBLANK,
 					   IMX219_LLP_MIN - mode->width,
@@ -762,6 +870,11 @@ static int imx219_init_controls(struct imx219 *imx219)
 		goto error;
 	}
 
+	imx219->fll->flags |= V4L2_CTRL_FLAG_UPDATE;
+	imx219->vblank->flags |= V4L2_CTRL_FLAG_UPDATE;
+	imx219->llp->flags |= V4L2_CTRL_FLAG_UPDATE;
+	imx219->hblank->flags |= V4L2_CTRL_FLAG_UPDATE;
+
 	ret = v4l2_fwnode_device_parse(&client->dev, &props);
 	if (ret)
 		goto error;
@@ -1127,23 +1240,34 @@ static int imx219_set_pad_format_compat(struct v4l2_subdev *sd,
 	crop->top = (IMX219_PIXEL_ARRAY_HEIGHT - crop->height) / 2;
 
 	if (fmt->which == V4L2_SUBDEV_FORMAT_ACTIVE) {
-		int llp_min;
+		unsigned int binning = bin_hv == 1 ?
+			IMX219_BINNING_11 : IMX219_BINNING_22;
 		int pixel_rate;
 
-		ret = __v4l2_ctrl_s_ctrl(imx219->binning, bin_hv == 1 ?
-					 IMX219_BINNING_11 : IMX219_BINNING_22);
+		ret = __v4l2_ctrl_s_ctrl(imx219->binning, binning);
+		if (ret)
+			return ret;
+
+		ret = imx219_apply_binning(imx219, state, crop, binning);
 		if (ret)
 			return ret;
 
 		/* Update limits and set FPS to default */
 		ret = __v4l2_ctrl_modify_range(imx219->vblank,
-					       (int)(mode->height / bin_hv),
-					       IMX219_FLL_MAX - mode->height, 1,
+					       imx219->vblank->minimum,
+					       imx219->vblank->maximum, 1,
 					       (int)(mode->fll_def / bin_hv) -
 					       (int)mode->height);
 		if (ret)
 			return ret;
 
+		ret = __v4l2_ctrl_modify_range(imx219->fll,
+					       imx219->fll->minimum,
+					       imx219->fll->maximum, 1,
+					       (int)(mode->fll_def / bin_hv));
+		if (ret)
+			return ret;
+
 		ret = __v4l2_ctrl_s_ctrl(imx219->vblank,
 					 (int)(mode->fll_def / bin_hv) -
 					 (int)mode->height);
@@ -1156,17 +1280,9 @@ static int imx219_set_pad_format_compat(struct v4l2_subdev *sd,
 		 * operates on two lines together. So we switch to a higher
 		 * minimum of 3560.
 		 */
-		llp_min = imx219_binnings[imx219->binning->val].h ==
-			IMX219_BINNING_X2_ANALOG ?
-			IMX219_BINNED_LLP_MIN : IMX219_LLP_MIN;
-		ret = __v4l2_ctrl_modify_range(imx219->hblank,
-					       llp_min - mode->width,
-					       IMX219_LLP_MAX - mode->width, 1,
-					       llp_min - mode->width);
-		if (ret)
-			return ret;
-
-		ret = __v4l2_ctrl_s_ctrl(imx219->hblank, llp_min - mode->width);
+		ret = __v4l2_ctrl_s_ctrl(imx219->hblank,
+					 imx219_binnings[binning].llp_min -
+					 mode->width);
 		if (ret)
 			return ret;
 
@@ -1293,8 +1409,12 @@ static int imx219_set_selection(struct v4l2_subdev *sd,
 		struct imx219 *imx219 = to_imx219(sd);
 		struct v4l2_rect *crop =
 			v4l2_subdev_state_get_crop(state, IMX219_PAD_IMAGE);
+		int ret;
 
-		imx219_apply_binning(state, &sel->r, imx219->binning->val);
+		ret = imx219_apply_binning(imx219, state, &sel->r,
+					   imx219->binning->val);
+		if (ret)
+			return ret;
 
 		*crop = sel->r;
 
-- 
2.47.3


^ permalink raw reply related	[flat|nested] 88+ messages in thread

* [PATCH v12 65/86] media: ipu6: Add support for raw CFA-agnostic formats
  2026-04-09 20:13 [PATCH v12 00/86] Generic line based metadata support, internal pads Sakari Ailus
                   ` (63 preceding siblings ...)
  2026-04-09 20:14 ` [PATCH v12 64/86] media: imx219: Support LINE_LENGTH_PIXELS and FRAME_LENGTH_LINES controls Sakari Ailus
@ 2026-04-09 20:14 ` Sakari Ailus
  2026-04-09 20:14 ` [PATCH v12 66/86] media: ipu6: Use VALIDATE_LATE flag to postpone V4L2 format validation Sakari Ailus
                   ` (20 subsequent siblings)
  85 siblings, 0 replies; 88+ messages in thread
From: Sakari Ailus @ 2026-04-09 20:14 UTC (permalink / raw)
  To: linux-media
  Cc: hans, laurent.pinchart, Prabhakar, Kate Hsuan, Dave Stevenson,
	Tommaso Merciai, Benjamin Mugnier, Sylvain Petinot,
	Christophe JAILLET, Julien Massot, Naushir Patuck, Stefan Klug,
	Mirela Rabulea, André Apitzsch, Heimir Thor Sverrisson,
	Kieran Bingham, Mehdi Djait, Ricardo Ribalda Delgado,
	Hans de Goede, Jacopo Mondi, Tomi Valkeinen, David Plowman,
	Yu, Ong Hock, Ng, Khai Wen, Jai Luthra, Rishikesh Donadkar

Add support for CFA-agnostic mbus codes and V4L2 pixelformats.

Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
Reviewed-by: Bingbu Cao <bingbu.cao@intel.com>
---
 drivers/media/pci/intel/ipu6/ipu6-isys-csi2.c   | 3 +++
 drivers/media/pci/intel/ipu6/ipu6-isys-subdev.c | 3 +++
 drivers/media/pci/intel/ipu6/ipu6-isys-video.c  | 8 ++++++++
 3 files changed, 14 insertions(+)

diff --git a/drivers/media/pci/intel/ipu6/ipu6-isys-csi2.c b/drivers/media/pci/intel/ipu6/ipu6-isys-csi2.c
index f64d8d9a6281..e01a8518c15a 100644
--- a/drivers/media/pci/intel/ipu6/ipu6-isys-csi2.c
+++ b/drivers/media/pci/intel/ipu6/ipu6-isys-csi2.c
@@ -46,6 +46,9 @@ static const u32 csi2_supported_codes[] = {
 	MEDIA_BUS_FMT_Y10_1X10,
 	MEDIA_BUS_FMT_Y12_1X12,
 	MEDIA_BUS_FMT_Y16_1X16,
+	MEDIA_BUS_FMT_RAW_8,
+	MEDIA_BUS_FMT_RAW_10,
+	MEDIA_BUS_FMT_RAW_12,
 	MEDIA_BUS_FMT_META_8,
 	MEDIA_BUS_FMT_META_10,
 	MEDIA_BUS_FMT_META_12,
diff --git a/drivers/media/pci/intel/ipu6/ipu6-isys-subdev.c b/drivers/media/pci/intel/ipu6/ipu6-isys-subdev.c
index 5dacc0a2aa9f..2ae15343bc0f 100644
--- a/drivers/media/pci/intel/ipu6/ipu6-isys-subdev.c
+++ b/drivers/media/pci/intel/ipu6/ipu6-isys-subdev.c
@@ -33,6 +33,7 @@ unsigned int ipu6_isys_mbus_code_to_bpp(u32 code)
 	case MEDIA_BUS_FMT_SGRBG12_1X12:
 	case MEDIA_BUS_FMT_SRGGB12_1X12:
 	case MEDIA_BUS_FMT_Y12_1X12:
+	case MEDIA_BUS_FMT_RAW_12:
 	case MEDIA_BUS_FMT_META_12:
 		return 12;
 	case MEDIA_BUS_FMT_SBGGR10_1X10:
@@ -40,6 +41,7 @@ unsigned int ipu6_isys_mbus_code_to_bpp(u32 code)
 	case MEDIA_BUS_FMT_SGRBG10_1X10:
 	case MEDIA_BUS_FMT_SRGGB10_1X10:
 	case MEDIA_BUS_FMT_Y10_1X10:
+	case MEDIA_BUS_FMT_RAW_10:
 	case MEDIA_BUS_FMT_META_10:
 		return 10;
 	case MEDIA_BUS_FMT_SBGGR8_1X8:
@@ -47,6 +49,7 @@ unsigned int ipu6_isys_mbus_code_to_bpp(u32 code)
 	case MEDIA_BUS_FMT_SGRBG8_1X8:
 	case MEDIA_BUS_FMT_SRGGB8_1X8:
 	case MEDIA_BUS_FMT_Y8_1X8:
+	case MEDIA_BUS_FMT_RAW_8:
 	case MEDIA_BUS_FMT_META_8:
 		return 8;
 	default:
diff --git a/drivers/media/pci/intel/ipu6/ipu6-isys-video.c b/drivers/media/pci/intel/ipu6/ipu6-isys-video.c
index cf0eef64e503..284002ab1e77 100644
--- a/drivers/media/pci/intel/ipu6/ipu6-isys-video.c
+++ b/drivers/media/pci/intel/ipu6/ipu6-isys-video.c
@@ -99,6 +99,14 @@ const struct ipu6_isys_pixelformat ipu6_isys_pfmts[] = {
 	  IPU6_FW_ISYS_FRAME_FORMAT_RGB565 },
 	{ V4L2_PIX_FMT_BGR24, 24, 24, MEDIA_BUS_FMT_RGB888_1X24,
 	  IPU6_FW_ISYS_FRAME_FORMAT_RGBA888 },
+
+	{ V4L2_PIX_FMT_RAW_8, 8, 8, MEDIA_BUS_FMT_RAW_8,
+	  IPU6_FW_ISYS_FRAME_FORMAT_RAW8 },
+	{ V4L2_PIX_FMT_RAW_CSI2_10, 10, 10, MEDIA_BUS_FMT_RAW_10,
+	  IPU6_FW_ISYS_FRAME_FORMAT_RAW10 },
+	{ V4L2_PIX_FMT_RAW_CSI2_12, 12, 12, MEDIA_BUS_FMT_RAW_12,
+	  IPU6_FW_ISYS_FRAME_FORMAT_RAW12 },
+
 	{ V4L2_META_FMT_GENERIC_8, 8, 8, MEDIA_BUS_FMT_META_8,
 	  IPU6_FW_ISYS_FRAME_FORMAT_RAW8, true },
 	{ V4L2_META_FMT_GENERIC_CSI2_10, 10, 10, MEDIA_BUS_FMT_META_10,
-- 
2.47.3


^ permalink raw reply related	[flat|nested] 88+ messages in thread

* [PATCH v12 66/86] media: ipu6: Use VALIDATE_LATE flag to postpone V4L2 format validation
  2026-04-09 20:13 [PATCH v12 00/86] Generic line based metadata support, internal pads Sakari Ailus
                   ` (64 preceding siblings ...)
  2026-04-09 20:14 ` [PATCH v12 65/86] media: ipu6: Add support for raw CFA-agnostic formats Sakari Ailus
@ 2026-04-09 20:14 ` Sakari Ailus
  2026-04-09 20:14 ` [PATCH v12 67/86] media: ipu6: Move streaming control to CSI-2 receiver driver Sakari Ailus
                   ` (19 subsequent siblings)
  85 siblings, 0 replies; 88+ messages in thread
From: Sakari Ailus @ 2026-04-09 20:14 UTC (permalink / raw)
  To: linux-media
  Cc: hans, laurent.pinchart, Prabhakar, Kate Hsuan, Dave Stevenson,
	Tommaso Merciai, Benjamin Mugnier, Sylvain Petinot,
	Christophe JAILLET, Julien Massot, Naushir Patuck, Stefan Klug,
	Mirela Rabulea, André Apitzsch, Heimir Thor Sverrisson,
	Kieran Bingham, Mehdi Djait, Ricardo Ribalda Delgado,
	Hans de Goede, Jacopo Mondi, Tomi Valkeinen, David Plowman,
	Yu, Ong Hock, Ng, Khai Wen, Jai Luthra, Rishikesh Donadkar

Postpone V4L2 format validation until streamon time on each video node.
This allows changing V4L2 format on video nodes while performing pipeline
validation through media_pipeline_start().

Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
---
 drivers/media/pci/intel/ipu6/ipu6-isys.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/media/pci/intel/ipu6/ipu6-isys.c b/drivers/media/pci/intel/ipu6/ipu6-isys.c
index c9cdeb7054d7..1a2d6b107b73 100644
--- a/drivers/media/pci/intel/ipu6/ipu6-isys.c
+++ b/drivers/media/pci/intel/ipu6/ipu6-isys.c
@@ -209,7 +209,8 @@ static int isys_csi2_create_media_links(struct ipu6_isys *isys)
 			struct ipu6_isys_video *av = &isys->csi2[i].av[j];
 
 			ret = media_create_pad_link(sd, CSI2_PAD_SRC + j,
-						    &av->vdev.entity, 0, 0);
+						    &av->vdev.entity, 0,
+						    MEDIA_LNK_FL_VALIDATE_LATE);
 			if (ret) {
 				dev_err(dev, "CSI2 can't create link\n");
 				return ret;
-- 
2.47.3


^ permalink raw reply related	[flat|nested] 88+ messages in thread

* [PATCH v12 67/86] media: ipu6: Move streaming control to CSI-2 receiver driver
  2026-04-09 20:13 [PATCH v12 00/86] Generic line based metadata support, internal pads Sakari Ailus
                   ` (65 preceding siblings ...)
  2026-04-09 20:14 ` [PATCH v12 66/86] media: ipu6: Use VALIDATE_LATE flag to postpone V4L2 format validation Sakari Ailus
@ 2026-04-09 20:14 ` Sakari Ailus
  2026-04-09 20:14 ` [PATCH v12 68/86] media: ipu6: Stream number on CSI-2 receiver source pads is always 0 Sakari Ailus
                   ` (18 subsequent siblings)
  85 siblings, 0 replies; 88+ messages in thread
From: Sakari Ailus @ 2026-04-09 20:14 UTC (permalink / raw)
  To: linux-media
  Cc: hans, laurent.pinchart, Prabhakar, Kate Hsuan, Dave Stevenson,
	Tommaso Merciai, Benjamin Mugnier, Sylvain Petinot,
	Christophe JAILLET, Julien Massot, Naushir Patuck, Stefan Klug,
	Mirela Rabulea, André Apitzsch, Heimir Thor Sverrisson,
	Kieran Bingham, Mehdi Djait, Ricardo Ribalda Delgado,
	Hans de Goede, Jacopo Mondi, Tomi Valkeinen, David Plowman,
	Yu, Ong Hock, Ng, Khai Wen, Jai Luthra, Rishikesh Donadkar

Move the streaming control out of the video nodes to the CSI-2 receiver
driver which is better positioned to consider stream configuration and so
when to actually start and stop streaming.

Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
---
 drivers/media/pci/intel/ipu6/ipu6-isys-csi2.c | 40 ++++++++--
 .../media/pci/intel/ipu6/ipu6-isys-queue.c    | 43 ++++-------
 .../media/pci/intel/ipu6/ipu6-isys-queue.h    |  2 +
 .../media/pci/intel/ipu6/ipu6-isys-subdev.c   | 22 ++++--
 .../media/pci/intel/ipu6/ipu6-isys-subdev.h   |  2 +
 .../media/pci/intel/ipu6/ipu6-isys-video.c    | 73 ++++++-------------
 .../media/pci/intel/ipu6/ipu6-isys-video.h    |  6 +-
 7 files changed, 96 insertions(+), 92 deletions(-)

diff --git a/drivers/media/pci/intel/ipu6/ipu6-isys-csi2.c b/drivers/media/pci/intel/ipu6/ipu6-isys-csi2.c
index e01a8518c15a..93ae5f767cc0 100644
--- a/drivers/media/pci/intel/ipu6/ipu6-isys-csi2.c
+++ b/drivers/media/pci/intel/ipu6/ipu6-isys-csi2.c
@@ -23,6 +23,7 @@
 #include "ipu6-isys.h"
 #include "ipu6-isys-csi2.h"
 #include "ipu6-isys-subdev.h"
+#include "ipu6-isys-video.h"
 #include "ipu6-platform-isys-csi2-reg.h"
 
 static const u32 csi2_supported_codes[] = {
@@ -354,10 +355,19 @@ static int ipu6_isys_csi2_enable_streams(struct v4l2_subdev *sd,
 	struct ipu6_isys_csi2 *csi2 = to_ipu6_isys_csi2(asd);
 	struct ipu6_isys_csi2_timing timing = { };
 	struct v4l2_subdev *remote_sd;
-	struct media_pad *remote_pad;
+	struct media_pad *remote_pad,
+		*vdev_pad = media_pad_remote_pad_unique(&sd->entity.pads[pad]);
+	struct ipu6_isys_video *av =
+		container_of_const(vdev_pad, struct ipu6_isys_video, pad);
 	u64 sink_streams;
 	int ret;
 
+	ret = ipu6_isys_start_stream_firmware(av);
+	if (ret) {
+		dev_err(sd->dev, "start stream of firmware failed\n");
+		return ret;
+	}
+
 	remote_pad = media_pad_remote_pad_first(&sd->entity.pads[CSI2_PAD_SINK]);
 	remote_sd = media_entity_to_v4l2_subdev(remote_pad->entity);
 
@@ -367,28 +377,38 @@ static int ipu6_isys_csi2_enable_streams(struct v4l2_subdev *sd,
 
 	ret = ipu6_isys_csi2_calc_timing(csi2, &timing, CSI2_ACCINV);
 	if (ret)
-		return ret;
+		goto err_stop_stream_firmware;
 
 	ret = ipu6_isys_csi2_set_stream(sd, &timing, csi2->nlanes, true);
 	if (ret)
-		return ret;
+		goto err_stop_stream_firmware;
 
 	ret = v4l2_subdev_enable_streams(remote_sd, remote_pad->index,
 					 sink_streams);
-	if (ret) {
-		ipu6_isys_csi2_set_stream(sd, NULL, 0, false);
-		return ret;
-	}
+	if (ret)
+		goto err_stop_stream_csi2;
 
 	return 0;
+
+err_stop_stream_csi2:
+	ipu6_isys_csi2_set_stream(sd, NULL, 0, false);
+
+err_stop_stream_firmware:
+	ipu6_isys_stop_streaming_firmware(av);
+	ipu6_isys_close_streaming_firmware(av);
+
+	return ret;
 }
 
 static int ipu6_isys_csi2_disable_streams(struct v4l2_subdev *sd,
 					  struct v4l2_subdev_state *state,
 					  u32 pad, u64 streams_mask)
 {
+	struct media_pad *remote_pad,
+		*vdev_pad = media_pad_remote_pad_unique(&sd->entity.pads[pad]);
+	struct ipu6_isys_video *av =
+		container_of_const(vdev_pad, struct ipu6_isys_video, pad);
 	struct v4l2_subdev *remote_sd;
-	struct media_pad *remote_pad;
 	u64 sink_streams;
 
 	sink_streams =
@@ -398,10 +418,14 @@ static int ipu6_isys_csi2_disable_streams(struct v4l2_subdev *sd,
 	remote_pad = media_pad_remote_pad_first(&sd->entity.pads[CSI2_PAD_SINK]);
 	remote_sd = media_entity_to_v4l2_subdev(remote_pad->entity);
 
+	ipu6_isys_stop_streaming_firmware(av);
+
 	ipu6_isys_csi2_set_stream(sd, NULL, 0, false);
 
 	v4l2_subdev_disable_streams(remote_sd, remote_pad->index, sink_streams);
 
+	ipu6_isys_close_streaming_firmware(av);
+
 	return 0;
 }
 
diff --git a/drivers/media/pci/intel/ipu6/ipu6-isys-queue.c b/drivers/media/pci/intel/ipu6/ipu6-isys-queue.c
index fabaed63df0c..7f24b113338c 100644
--- a/drivers/media/pci/intel/ipu6/ipu6-isys-queue.c
+++ b/drivers/media/pci/intel/ipu6/ipu6-isys-queue.c
@@ -21,6 +21,7 @@
 #include "ipu6-dma.h"
 #include "ipu6-fw-isys.h"
 #include "ipu6-isys.h"
+#include "ipu6-isys-queue.h"
 #include "ipu6-isys-video.h"
 
 static int ipu6_isys_buf_init(struct vb2_buffer *vb)
@@ -191,8 +192,8 @@ static void flush_firmware_streamon_fail(struct ipu6_isys_stream *stream)
  * that contains one entry from each video buffer queue. If a buffer can't be
  * obtained from every queue, the buffers are returned back to the queue.
  */
-static int buffer_list_get(struct ipu6_isys_stream *stream,
-			   struct ipu6_isys_buffer_list *bl)
+int ipu6_isys_buffer_list_get(struct ipu6_isys_stream *stream,
+			      struct ipu6_isys_buffer_list *bl)
 {
 	struct device *dev = &stream->isys->adev->auxdev.dev;
 	struct ipu6_isys_queue *aq;
@@ -286,29 +287,26 @@ ipu6_isys_buf_to_fw_frame_buf(struct ipu6_fw_isys_frame_buff_set_abi *set,
 }
 
 /* Start streaming for real. The buffer list must be available. */
-static int ipu6_isys_stream_start(struct ipu6_isys_video *av,
-				  struct ipu6_isys_buffer_list *bl)
+static int ipu6_isys_stream_start(struct ipu6_isys_video *av)
 {
 	struct ipu6_isys_stream *stream = av->stream;
 	struct device *dev = &stream->isys->adev->auxdev.dev;
-	struct ipu6_isys_buffer_list __bl;
+	struct ipu6_isys_buffer_list bl;
 	int ret;
 
 	guard(mutex)(&stream->isys->stream_mutex);
-	ret = ipu6_isys_video_set_streaming(av, 1, bl);
+	ret = ipu6_isys_video_set_streaming(av, 1);
 	if (ret)
-		goto out_requeue;
+		return ret;
 
 	stream->streaming = 1;
 
-	bl = &__bl;
-
 	do {
 		struct ipu6_fw_isys_frame_buff_set_abi *buf = NULL;
 		struct isys_fw_msgs *msg;
 		u16 send_type = IPU6_FW_ISYS_SEND_TYPE_STREAM_CAPTURE;
 
-		ret = buffer_list_get(stream, bl);
+		ret = ipu6_isys_buffer_list_get(stream, &bl);
 		if (ret < 0)
 			break;
 
@@ -317,11 +315,11 @@ static int ipu6_isys_stream_start(struct ipu6_isys_video *av,
 			return -ENOMEM;
 
 		buf = &msg->fw_msg.frame;
-		ipu6_isys_buf_to_fw_frame_buf(buf, stream, bl);
+		ipu6_isys_buf_to_fw_frame_buf(buf, stream, &bl);
 		ipu6_fw_isys_dump_frame_buff_set(dev, buf,
 						 stream->nr_output_pins);
-		ipu6_isys_buffer_list_queue(bl, IPU6_ISYS_BUFFER_LIST_FL_ACTIVE,
-					    0);
+		ipu6_isys_buffer_list_queue(&bl,
+					    IPU6_ISYS_BUFFER_LIST_FL_ACTIVE, 0);
 		ret = ipu6_fw_isys_complex_cmd(stream->isys,
 					       stream->stream_handle, buf,
 					       msg->dma_addr, sizeof(*buf),
@@ -330,9 +328,8 @@ static int ipu6_isys_stream_start(struct ipu6_isys_video *av,
 
 	return 0;
 
-out_requeue:
-	if (bl && bl->nbufs)
-		ipu6_isys_buffer_list_queue(bl,
+	if (bl.nbufs)
+		ipu6_isys_buffer_list_queue(&bl,
 					    IPU6_ISYS_BUFFER_LIST_FL_INCOMING,
 					    VB2_BUF_STATE_QUEUED);
 	flush_firmware_streamon_fail(stream);
@@ -384,7 +381,7 @@ static void buf_queue(struct vb2_buffer *vb)
 	 * (above). Let's see whether all queues in the pipeline would
 	 * have a buffer.
 	 */
-	ret = buffer_list_get(stream, &bl);
+	ret = ipu6_isys_buffer_list_get(stream, &bl);
 	if (ret < 0) {
 		dev_dbg(dev, "No buffers available\n");
 		goto out;
@@ -536,7 +533,6 @@ static int start_streaming(struct vb2_queue *q, unsigned int count)
 	struct device *dev = &av->isys->adev->auxdev.dev;
 	const struct ipu6_isys_pixelformat *pfmt =
 		ipu6_isys_get_isys_format(ipu6_isys_get_format(av), 0);
-	struct ipu6_isys_buffer_list __bl, *bl = NULL;
 	struct ipu6_isys_stream *stream;
 	struct media_pad *source_pad, *remote_pad;
 	int nr_queues, ret;
@@ -597,14 +593,7 @@ static int start_streaming(struct vb2_queue *q, unsigned int count)
 	if (stream->nr_streaming != stream->nr_queues)
 		goto out;
 
-	bl = &__bl;
-	ret = buffer_list_get(stream, bl);
-	if (ret < 0) {
-		dev_warn(dev, "no buffer available, DRIVER BUG?\n");
-		goto out;
-	}
-
-	ret = ipu6_isys_stream_start(av, bl);
+	ret = ipu6_isys_stream_start(av);
 	if (ret)
 		goto out_stream_start;
 
@@ -643,7 +632,7 @@ static void stop_streaming(struct vb2_queue *q)
 
 	mutex_lock(&av->isys->stream_mutex);
 	if (stream->nr_streaming == stream->nr_queues && stream->streaming)
-		ipu6_isys_video_set_streaming(av, 0, NULL);
+		ipu6_isys_video_set_streaming(av, 0);
 	list_del(&aq->node);
 	mutex_unlock(&av->isys->stream_mutex);
 
diff --git a/drivers/media/pci/intel/ipu6/ipu6-isys-queue.h b/drivers/media/pci/intel/ipu6/ipu6-isys-queue.h
index dec1fed44dd2..f2e887dad861 100644
--- a/drivers/media/pci/intel/ipu6/ipu6-isys-queue.h
+++ b/drivers/media/pci/intel/ipu6/ipu6-isys-queue.h
@@ -60,6 +60,8 @@ struct ipu6_isys_buffer_list {
 void ipu6_isys_buffer_list_queue(struct ipu6_isys_buffer_list *bl,
 				 unsigned long op_flags,
 				 enum vb2_buffer_state state);
+int ipu6_isys_buffer_list_get(struct ipu6_isys_stream *stream,
+			      struct ipu6_isys_buffer_list *bl);
 void
 ipu6_isys_buf_to_fw_frame_buf(struct ipu6_fw_isys_frame_buff_set_abi *set,
 			      struct ipu6_isys_stream *stream,
diff --git a/drivers/media/pci/intel/ipu6/ipu6-isys-subdev.c b/drivers/media/pci/intel/ipu6/ipu6-isys-subdev.c
index 2ae15343bc0f..5dd2c2995d01 100644
--- a/drivers/media/pci/intel/ipu6/ipu6-isys-subdev.c
+++ b/drivers/media/pci/intel/ipu6/ipu6-isys-subdev.c
@@ -269,17 +269,13 @@ static int subdev_set_routing(struct v4l2_subdev *sd,
 	return v4l2_subdev_set_routing_with_fmt(sd, state, routing, &format);
 }
 
-u32 ipu6_isys_get_src_stream_by_src_pad(struct v4l2_subdev *sd, u32 pad)
+u32 __ipu6_isys_get_src_stream_by_src_pad(struct v4l2_subdev_state *state,
+					  u32 pad)
 {
-	struct v4l2_subdev_state *state;
 	struct v4l2_subdev_route *routes;
 	unsigned int i;
 	u32 source_stream = 0;
 
-	state = v4l2_subdev_lock_and_get_active_state(sd);
-	if (!state)
-		return 0;
-
 	routes = state->routing.routes;
 	for (i = 0; i < state->routing.num_routes; i++) {
 		if (routes[i].source_pad == pad) {
@@ -288,6 +284,20 @@ u32 ipu6_isys_get_src_stream_by_src_pad(struct v4l2_subdev *sd, u32 pad)
 		}
 	}
 
+	return source_stream;
+}
+
+u32 ipu6_isys_get_src_stream_by_src_pad(struct v4l2_subdev *sd, u32 pad)
+{
+	struct v4l2_subdev_state *state;
+	u32 source_stream = 0;
+
+	state = v4l2_subdev_lock_and_get_active_state(sd);
+	if (!state)
+		return 0;
+
+	source_stream = __ipu6_isys_get_src_stream_by_src_pad(state, pad);
+
 	v4l2_subdev_unlock_state(state);
 
 	return source_stream;
diff --git a/drivers/media/pci/intel/ipu6/ipu6-isys-subdev.h b/drivers/media/pci/intel/ipu6/ipu6-isys-subdev.h
index d4f76d513dc6..b892d96992af 100644
--- a/drivers/media/pci/intel/ipu6/ipu6-isys-subdev.h
+++ b/drivers/media/pci/intel/ipu6/ipu6-isys-subdev.h
@@ -38,6 +38,8 @@ int ipu6_isys_subdev_enum_mbus_code(struct v4l2_subdev *sd,
 				    struct v4l2_subdev_state *state,
 				    struct v4l2_subdev_mbus_code_enum
 				    *code);
+u32 __ipu6_isys_get_src_stream_by_src_pad(struct v4l2_subdev_state *state,
+					  u32 pad);
 u32 ipu6_isys_get_src_stream_by_src_pad(struct v4l2_subdev *sd, u32 pad);
 int ipu6_isys_subdev_set_routing(struct v4l2_subdev *sd,
 				 struct v4l2_subdev_state *state,
diff --git a/drivers/media/pci/intel/ipu6/ipu6-isys-video.c b/drivers/media/pci/intel/ipu6/ipu6-isys-video.c
index 284002ab1e77..b6f2ef0822a7 100644
--- a/drivers/media/pci/intel/ipu6/ipu6-isys-video.c
+++ b/drivers/media/pci/intel/ipu6/ipu6-isys-video.c
@@ -477,7 +477,7 @@ static int ipu6_isys_fw_pin_cfg(struct ipu6_isys_video *av,
 	int output_pins;
 	u32 src_stream;
 
-	src_stream = ipu6_isys_get_src_stream_by_src_pad(sd, src_pad->index);
+	src_stream = __ipu6_isys_get_src_stream_by_src_pad(state, src_pad->index);
 	fmt = *v4l2_subdev_state_get_format(state, src_pad->index, src_stream);
 	v4l2_crop = *v4l2_subdev_state_get_crop(state, src_pad->index, src_stream);
 
@@ -525,11 +525,11 @@ static int ipu6_isys_fw_pin_cfg(struct ipu6_isys_video *av,
 	return 0;
 }
 
-static int start_stream_firmware(struct ipu6_isys_video *av,
-				 struct ipu6_isys_buffer_list *bl)
+int ipu6_isys_start_stream_firmware(struct ipu6_isys_video *av)
 {
 	struct ipu6_fw_isys_stream_cfg_data_abi *stream_cfg;
 	struct ipu6_fw_isys_frame_buff_set_abi *buf = NULL;
+	struct ipu6_isys_buffer_list bl;
 	struct ipu6_isys_stream *stream = av->stream;
 	struct device *dev = &av->isys->adev->auxdev.dev;
 	struct isys_fw_msgs *msg = NULL;
@@ -537,6 +537,12 @@ static int start_stream_firmware(struct ipu6_isys_video *av,
 	int ret, retout, tout;
 	u16 send_type;
 
+	ret = ipu6_isys_buffer_list_get(stream, &bl);
+	if (ret < 0) {
+		dev_warn(dev, "no buffer available, DRIVER BUG?\n");
+		return ret;
+	}
+
 	msg = ipu6_get_fw_msg_buf(stream);
 	if (!msg)
 		return -ENOMEM;
@@ -592,33 +598,21 @@ static int start_stream_firmware(struct ipu6_isys_video *av,
 	}
 	dev_dbg(dev, "start stream: open complete\n");
 
-	if (bl) {
-		msg = ipu6_get_fw_msg_buf(stream);
-		if (!msg) {
-			ret = -ENOMEM;
-			goto out_put_stream_opened;
-		}
-		buf = &msg->fw_msg.frame;
-		ipu6_isys_buf_to_fw_frame_buf(buf, stream, bl);
-		ipu6_isys_buffer_list_queue(bl,
-					    IPU6_ISYS_BUFFER_LIST_FL_ACTIVE, 0);
+	msg = ipu6_get_fw_msg_buf(stream);
+	if (!msg) {
+		ret = -ENOMEM;
+		goto out_put_stream_opened;
 	}
+	buf = &msg->fw_msg.frame;
+	ipu6_isys_buf_to_fw_frame_buf(buf, stream, &bl);
+	ipu6_isys_buffer_list_queue(&bl, IPU6_ISYS_BUFFER_LIST_FL_ACTIVE, 0);
 
 	reinit_completion(&stream->stream_start_completion);
 
-	if (bl) {
-		send_type = IPU6_FW_ISYS_SEND_TYPE_STREAM_START_AND_CAPTURE;
-		ipu6_fw_isys_dump_frame_buff_set(dev, buf,
-						 stream_cfg->nof_output_pins);
-		ret = ipu6_fw_isys_complex_cmd(av->isys, stream->stream_handle,
-					       buf, msg->dma_addr,
-					       sizeof(*buf), send_type);
-	} else {
-		send_type = IPU6_FW_ISYS_SEND_TYPE_STREAM_START;
-		ret = ipu6_fw_isys_simple_cmd(av->isys, stream->stream_handle,
-					      send_type);
-	}
-
+	send_type = IPU6_FW_ISYS_SEND_TYPE_STREAM_START_AND_CAPTURE;
+	ipu6_fw_isys_dump_frame_buff_set(dev, buf, stream_cfg->nof_output_pins);
+	ret = ipu6_fw_isys_complex_cmd(av->isys, stream->stream_handle, buf,
+				       msg->dma_addr, sizeof(*buf), send_type);
 	if (ret < 0) {
 		dev_err(dev, "can't start streaming (%d)\n", ret);
 		goto out_stream_close;
@@ -666,7 +660,7 @@ static int start_stream_firmware(struct ipu6_isys_video *av,
 	return ret;
 }
 
-static void stop_streaming_firmware(struct ipu6_isys_video *av)
+void ipu6_isys_stop_streaming_firmware(struct ipu6_isys_video *av)
 {
 	struct device *dev = &av->isys->adev->auxdev.dev;
 	struct ipu6_isys_stream *stream = av->stream;
@@ -692,7 +686,7 @@ static void stop_streaming_firmware(struct ipu6_isys_video *av)
 		dev_dbg(dev, "stop stream: complete\n");
 }
 
-static void close_streaming_firmware(struct ipu6_isys_video *av)
+void ipu6_isys_close_streaming_firmware(struct ipu6_isys_video *av)
 {
 	struct ipu6_isys_stream *stream = av->stream;
 	struct device *dev = &av->isys->adev->auxdev.dev;
@@ -990,8 +984,7 @@ static u64 get_stream_mask_by_pipeline(struct ipu6_isys_video *__av)
 	return stream_mask;
 }
 
-int ipu6_isys_video_set_streaming(struct ipu6_isys_video *av, int state,
-				  struct ipu6_isys_buffer_list *bl)
+int ipu6_isys_video_set_streaming(struct ipu6_isys_video *av, int state)
 {
 	struct v4l2_subdev_krouting *routing;
 	struct ipu6_isys_stream *stream = av->stream;
@@ -1021,8 +1014,6 @@ int ipu6_isys_video_set_streaming(struct ipu6_isys_video *av, int state,
 
 	stream_mask = get_stream_mask_by_pipeline(av);
 	if (!state) {
-		stop_streaming_firmware(av);
-
 		/* stop sub-device which connects with video */
 		dev_dbg(dev, "stream off entity %s pad:%d mask:0x%llx\n",
 			sd->name, r_pad->index, stream_mask);
@@ -1031,34 +1022,18 @@ int ipu6_isys_video_set_streaming(struct ipu6_isys_video *av, int state,
 		if (ret)
 			dev_err(dev, "stream off %s failed with %d\n", sd->name,
 				ret);
-
-		close_streaming_firmware(av);
 	} else {
-		ret = start_stream_firmware(av, bl);
-		if (ret) {
-			dev_err(dev, "start stream of firmware failed\n");
-			return ret;
-		}
-
 		/* start sub-device which connects with video */
 		dev_dbg(dev, "stream on %s pad %d mask 0x%llx\n", sd->name,
 			r_pad->index, stream_mask);
 		ret = v4l2_subdev_enable_streams(sd, r_pad->index, stream_mask);
-		if (ret) {
+		if (ret)
 			dev_err(dev, "stream on %s failed with %d\n", sd->name,
 				ret);
-			goto out_media_entity_stop_streaming_firmware;
-		}
 	}
 
 	av->streaming = state;
 
-	return 0;
-
-out_media_entity_stop_streaming_firmware:
-	stop_streaming_firmware(av);
-	close_streaming_firmware(av);
-
 	return ret;
 }
 
diff --git a/drivers/media/pci/intel/ipu6/ipu6-isys-video.h b/drivers/media/pci/intel/ipu6/ipu6-isys-video.h
index 2ff53315d7b9..72d413026d3e 100644
--- a/drivers/media/pci/intel/ipu6/ipu6-isys-video.h
+++ b/drivers/media/pci/intel/ipu6/ipu6-isys-video.h
@@ -104,11 +104,13 @@ extern const struct ipu6_isys_pixelformat ipu6_isys_pfmts_packed[];
 
 const struct ipu6_isys_pixelformat *
 ipu6_isys_get_isys_format(u32 pixelformat, u32 code);
+int ipu6_isys_start_stream_firmware(struct ipu6_isys_video *av);
+void ipu6_isys_stop_streaming_firmware(struct ipu6_isys_video *av);
+void ipu6_isys_close_streaming_firmware(struct ipu6_isys_video *av);
 int ipu6_isys_video_prepare_stream(struct ipu6_isys_video *av,
 				   struct media_entity *source_entity,
 				   int nr_queues);
-int ipu6_isys_video_set_streaming(struct ipu6_isys_video *av, int state,
-				  struct ipu6_isys_buffer_list *bl);
+int ipu6_isys_video_set_streaming(struct ipu6_isys_video *av, int state);
 int ipu6_isys_fw_open(struct ipu6_isys *isys);
 void ipu6_isys_fw_close(struct ipu6_isys *isys);
 int ipu6_isys_setup_video(struct ipu6_isys_video *av,
-- 
2.47.3


^ permalink raw reply related	[flat|nested] 88+ messages in thread

* [PATCH v12 68/86] media: ipu6: Stream number on CSI-2 receiver source pads is always 0
  2026-04-09 20:13 [PATCH v12 00/86] Generic line based metadata support, internal pads Sakari Ailus
                   ` (66 preceding siblings ...)
  2026-04-09 20:14 ` [PATCH v12 67/86] media: ipu6: Move streaming control to CSI-2 receiver driver Sakari Ailus
@ 2026-04-09 20:14 ` Sakari Ailus
  2026-04-09 20:14 ` [PATCH v12 69/86] media: ipu6: Rename misnamed out_free_watermark label in video init Sakari Ailus
                   ` (17 subsequent siblings)
  85 siblings, 0 replies; 88+ messages in thread
From: Sakari Ailus @ 2026-04-09 20:14 UTC (permalink / raw)
  To: linux-media
  Cc: hans, laurent.pinchart, Prabhakar, Kate Hsuan, Dave Stevenson,
	Tommaso Merciai, Benjamin Mugnier, Sylvain Petinot,
	Christophe JAILLET, Julien Massot, Naushir Patuck, Stefan Klug,
	Mirela Rabulea, André Apitzsch, Heimir Thor Sverrisson,
	Kieran Bingham, Mehdi Djait, Ricardo Ribalda Delgado,
	Hans de Goede, Jacopo Mondi, Tomi Valkeinen, David Plowman,
	Yu, Ong Hock, Ng, Khai Wen, Jai Luthra, Rishikesh Donadkar

The stream number on the video nodes' single pad is always 0, thus the
stream number of the CSI-2 receivers' source pads is also 0. Remove the
complexity that is there to come up with 0.

Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
---
 .../media/pci/intel/ipu6/ipu6-isys-video.c    | 49 ++-----------------
 1 file changed, 5 insertions(+), 44 deletions(-)

diff --git a/drivers/media/pci/intel/ipu6/ipu6-isys-video.c b/drivers/media/pci/intel/ipu6/ipu6-isys-video.c
index b6f2ef0822a7..164000985c0d 100644
--- a/drivers/media/pci/intel/ipu6/ipu6-isys-video.c
+++ b/drivers/media/pci/intel/ipu6/ipu6-isys-video.c
@@ -967,66 +967,27 @@ ipu6_isys_query_stream_by_source(struct ipu6_isys *isys, int source, u8 vc)
 	return stream;
 }
 
-static u64 get_stream_mask_by_pipeline(struct ipu6_isys_video *__av)
-{
-	struct media_pipeline *pipeline =
-		media_entity_pipeline(&__av->vdev.entity);
-	unsigned int i;
-	u64 stream_mask = 0;
-
-	for (i = 0; i < NR_OF_CSI2_SRC_PADS; i++) {
-		struct ipu6_isys_video *av = &__av->csi2->av[i];
-
-		if (pipeline == media_entity_pipeline(&av->vdev.entity))
-			stream_mask |= BIT_ULL(av->source_stream);
-	}
-
-	return stream_mask;
-}
-
 int ipu6_isys_video_set_streaming(struct ipu6_isys_video *av, int state)
 {
-	struct v4l2_subdev_krouting *routing;
-	struct ipu6_isys_stream *stream = av->stream;
-	struct v4l2_subdev_state *subdev_state;
 	struct device *dev = &av->isys->adev->auxdev.dev;
 	struct v4l2_subdev *sd;
 	struct media_pad *r_pad;
-	u32 sink_pad, sink_stream;
-	u64 r_stream;
-	u64 stream_mask = 0;
 	int ret = 0;
 
-	dev_dbg(dev, "set stream: %d\n", state);
-
-	sd = &stream->asd->sd;
+	sd = &av->stream->asd->sd;
 	r_pad = media_pad_remote_pad_first(&av->pad);
-	r_stream = ipu6_isys_get_src_stream_by_src_pad(sd, r_pad->index);
-
-	subdev_state = v4l2_subdev_lock_and_get_active_state(sd);
-	routing = &subdev_state->routing;
-	ret = v4l2_subdev_routing_find_opposite_end(routing, r_pad->index,
-						    r_stream, &sink_pad,
-						    &sink_stream);
-	v4l2_subdev_unlock_state(subdev_state);
-	if (ret)
-		return ret;
 
-	stream_mask = get_stream_mask_by_pipeline(av);
 	if (!state) {
 		/* stop sub-device which connects with video */
-		dev_dbg(dev, "stream off entity %s pad:%d mask:0x%llx\n",
-			sd->name, r_pad->index, stream_mask);
-		ret = v4l2_subdev_disable_streams(sd, r_pad->index,
-						  stream_mask);
+		dev_dbg(dev, "stream off %s pad:%d\n", sd->name, r_pad->index);
+		ret = v4l2_subdev_disable_streams(sd, r_pad->index, 1);
 		if (ret)
 			dev_err(dev, "stream off %s failed with %d\n", sd->name,
 				ret);
 	} else {
 		/* start sub-device which connects with video */
-		dev_dbg(dev, "stream on %s pad %d mask 0x%llx\n", sd->name,
-			r_pad->index, stream_mask);
-		ret = v4l2_subdev_enable_streams(sd, r_pad->index, stream_mask);
+		dev_dbg(dev, "stream on %s pad %d\n", sd->name, r_pad->index);
+		ret = v4l2_subdev_enable_streams(sd, r_pad->index, 1);
 		if (ret)
 			dev_err(dev, "stream on %s failed with %d\n", sd->name,
 				ret);
-- 
2.47.3


^ permalink raw reply related	[flat|nested] 88+ messages in thread

* [PATCH v12 69/86] media: ipu6: Rename misnamed out_free_watermark label in video init
  2026-04-09 20:13 [PATCH v12 00/86] Generic line based metadata support, internal pads Sakari Ailus
                   ` (67 preceding siblings ...)
  2026-04-09 20:14 ` [PATCH v12 68/86] media: ipu6: Stream number on CSI-2 receiver source pads is always 0 Sakari Ailus
@ 2026-04-09 20:14 ` Sakari Ailus
  2026-04-09 20:14 ` [PATCH v12 70/86] media: ipu6: Always request a capture ack Sakari Ailus
                   ` (16 subsequent siblings)
  85 siblings, 0 replies; 88+ messages in thread
From: Sakari Ailus @ 2026-04-09 20:14 UTC (permalink / raw)
  To: linux-media
  Cc: hans, laurent.pinchart, Prabhakar, Kate Hsuan, Dave Stevenson,
	Tommaso Merciai, Benjamin Mugnier, Sylvain Petinot,
	Christophe JAILLET, Julien Massot, Naushir Patuck, Stefan Klug,
	Mirela Rabulea, André Apitzsch, Heimir Thor Sverrisson,
	Kieran Bingham, Mehdi Djait, Ricardo Ribalda Delgado,
	Hans de Goede, Jacopo Mondi, Tomi Valkeinen, David Plowman,
	Yu, Ong Hock, Ng, Khai Wen, Jai Luthra, Rishikesh Donadkar

ipu6_isys_video_init() has a label in the error path where it is used to
destroy a mutex. Rename the label as err_mutex_destroy.

Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
---
 drivers/media/pci/intel/ipu6/ipu6-isys-video.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/media/pci/intel/ipu6/ipu6-isys-video.c b/drivers/media/pci/intel/ipu6/ipu6-isys-video.c
index 164000985c0d..eebce7593b3f 100644
--- a/drivers/media/pci/intel/ipu6/ipu6-isys-video.c
+++ b/drivers/media/pci/intel/ipu6/ipu6-isys-video.c
@@ -1206,7 +1206,7 @@ int ipu6_isys_video_init(struct ipu6_isys_video *av)
 
 	ret = ipu6_isys_queue_init(&av->aq);
 	if (ret)
-		goto out_free_watermark;
+		goto out_mutex_destroy;
 
 	av->pad.flags = MEDIA_PAD_FL_SINK | MEDIA_PAD_FL_MUST_CONNECT;
 	ret = media_entity_pads_init(&av->vdev.entity, 1, &av->pad);
@@ -1243,7 +1243,7 @@ int ipu6_isys_video_init(struct ipu6_isys_video *av)
 out_vb2_queue_release:
 	vb2_queue_release(&av->aq.vbq);
 
-out_free_watermark:
+out_mutex_destroy:
 	mutex_destroy(&av->mutex);
 
 	return ret;
-- 
2.47.3


^ permalink raw reply related	[flat|nested] 88+ messages in thread

* [PATCH v12 70/86] media: ipu6: Always request a capture ack
  2026-04-09 20:13 [PATCH v12 00/86] Generic line based metadata support, internal pads Sakari Ailus
                   ` (68 preceding siblings ...)
  2026-04-09 20:14 ` [PATCH v12 69/86] media: ipu6: Rename misnamed out_free_watermark label in video init Sakari Ailus
@ 2026-04-09 20:14 ` Sakari Ailus
  2026-04-09 20:14 ` [PATCH v12 71/86] media: ipu6: Clean up link frequency calculation Sakari Ailus
                   ` (15 subsequent siblings)
  85 siblings, 0 replies; 88+ messages in thread
From: Sakari Ailus @ 2026-04-09 20:14 UTC (permalink / raw)
  To: linux-media
  Cc: hans, laurent.pinchart, Prabhakar, Kate Hsuan, Dave Stevenson,
	Tommaso Merciai, Benjamin Mugnier, Sylvain Petinot,
	Christophe JAILLET, Julien Massot, Naushir Patuck, Stefan Klug,
	Mirela Rabulea, André Apitzsch, Heimir Thor Sverrisson,
	Kieran Bingham, Mehdi Djait, Ricardo Ribalda Delgado,
	Hans de Goede, Jacopo Mondi, Tomi Valkeinen, David Plowman,
	Yu, Ong Hock, Ng, Khai Wen, Jai Luthra, Rishikesh Donadkar

Always request a capture ack from a queued buffer. If streaming is
disabled, no buffers would have been queued in the first place. Remove the
streaming field from struct ipu6_isys_stream as well.

Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
---
 drivers/media/pci/intel/ipu6/ipu6-isys-queue.c | 10 ++--------
 drivers/media/pci/intel/ipu6/ipu6-isys-video.h |  1 -
 2 files changed, 2 insertions(+), 9 deletions(-)

diff --git a/drivers/media/pci/intel/ipu6/ipu6-isys-queue.c b/drivers/media/pci/intel/ipu6/ipu6-isys-queue.c
index 7f24b113338c..13d759b27ca0 100644
--- a/drivers/media/pci/intel/ipu6/ipu6-isys-queue.c
+++ b/drivers/media/pci/intel/ipu6/ipu6-isys-queue.c
@@ -266,10 +266,7 @@ ipu6_isys_buf_to_fw_frame_buf(struct ipu6_fw_isys_frame_buff_set_abi *set,
 	set->send_irq_eof = 0;
 	set->send_resp_eof = 0;
 
-	if (stream->streaming)
-		set->send_irq_capture_ack = 0;
-	else
-		set->send_irq_capture_ack = 1;
+	set->send_irq_capture_ack = 1;
 	set->send_irq_capture_done = 0;
 
 	set->send_resp_capture_ack = 1;
@@ -299,8 +296,6 @@ static int ipu6_isys_stream_start(struct ipu6_isys_video *av)
 	if (ret)
 		return ret;
 
-	stream->streaming = 1;
-
 	do {
 		struct ipu6_fw_isys_frame_buff_set_abi *buf = NULL;
 		struct isys_fw_msgs *msg;
@@ -631,13 +626,12 @@ static void stop_streaming(struct vb2_queue *q)
 	ipu6_isys_update_stream_watermark(av, false);
 
 	mutex_lock(&av->isys->stream_mutex);
-	if (stream->nr_streaming == stream->nr_queues && stream->streaming)
+	if (stream->nr_streaming == stream->nr_queues)
 		ipu6_isys_video_set_streaming(av, 0);
 	list_del(&aq->node);
 	mutex_unlock(&av->isys->stream_mutex);
 
 	stream->nr_streaming--;
-	stream->streaming = 0;
 	mutex_unlock(&stream->mutex);
 
 	ipu6_isys_stream_cleanup(av);
diff --git a/drivers/media/pci/intel/ipu6/ipu6-isys-video.h b/drivers/media/pci/intel/ipu6/ipu6-isys-video.h
index 72d413026d3e..d07c16e79877 100644
--- a/drivers/media/pci/intel/ipu6/ipu6-isys-video.h
+++ b/drivers/media/pci/intel/ipu6/ipu6-isys-video.h
@@ -53,7 +53,6 @@ struct ipu6_isys_stream {
 
 	int nr_queues;	/* Number of capture queues */
 	int nr_streaming;
-	int streaming;	/* Has streaming been really started? */
 	struct list_head queues;
 	struct completion stream_open_completion;
 	struct completion stream_close_completion;
-- 
2.47.3


^ permalink raw reply related	[flat|nested] 88+ messages in thread

* [PATCH v12 71/86] media: ipu6: Clean up link frequency calculation
  2026-04-09 20:13 [PATCH v12 00/86] Generic line based metadata support, internal pads Sakari Ailus
                   ` (69 preceding siblings ...)
  2026-04-09 20:14 ` [PATCH v12 70/86] media: ipu6: Always request a capture ack Sakari Ailus
@ 2026-04-09 20:14 ` Sakari Ailus
  2026-04-09 20:14 ` [PATCH v12 72/86] media: ipu6: Get watermark configuration directly from ipdata Sakari Ailus
                   ` (14 subsequent siblings)
  85 siblings, 0 replies; 88+ messages in thread
From: Sakari Ailus @ 2026-04-09 20:14 UTC (permalink / raw)
  To: linux-media
  Cc: hans, laurent.pinchart, Prabhakar, Kate Hsuan, Dave Stevenson,
	Tommaso Merciai, Benjamin Mugnier, Sylvain Petinot,
	Christophe JAILLET, Julien Massot, Naushir Patuck, Stefan Klug,
	Mirela Rabulea, André Apitzsch, Heimir Thor Sverrisson,
	Kieran Bingham, Mehdi Djait, Ricardo Ribalda Delgado,
	Hans de Goede, Jacopo Mondi, Tomi Valkeinen, David Plowman,
	Yu, Ong Hock, Ng, Khai Wen, Jai Luthra, Rishikesh Donadkar

Handle link_freq <= as a special case and continue calculating the pixel
rate otherwise.

Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
---
 .../media/pci/intel/ipu6/ipu6-isys-video.c    | 37 ++++++++-----------
 1 file changed, 16 insertions(+), 21 deletions(-)

diff --git a/drivers/media/pci/intel/ipu6/ipu6-isys-video.c b/drivers/media/pci/intel/ipu6/ipu6-isys-video.c
index eebce7593b3f..0da9070aeb42 100644
--- a/drivers/media/pci/intel/ipu6/ipu6-isys-video.c
+++ b/drivers/media/pci/intel/ipu6/ipu6-isys-video.c
@@ -750,12 +750,9 @@ void ipu6_isys_configure_stream_watermark(struct ipu6_isys_video *av,
 	struct ipu6_isys_csi2 *csi2 = NULL;
 	struct isys_iwake_watermark *iwake_watermark = &isys->iwake_watermark;
 	struct device *dev = &isys->adev->auxdev.dev;
-	struct v4l2_mbus_framefmt format;
 	struct v4l2_subdev *esd;
 	struct v4l2_control hb = { .id = V4L2_CID_HBLANK, .value = 0 };
-	unsigned int bpp, lanes;
-	s64 link_freq = 0;
-	u64 pixel_rate = 0;
+	s64 link_freq;
 	int ret;
 
 	esd = media_entity_to_v4l2_subdev(source);
@@ -773,28 +770,26 @@ void ipu6_isys_configure_stream_watermark(struct ipu6_isys_video *av,
 
 	csi2 = ipu6_isys_subdev_to_csi2(av->stream->asd);
 	link_freq = ipu6_isys_csi2_get_link_freq(csi2);
-	if (link_freq > 0) {
-		struct v4l2_subdev_state *state =
-			v4l2_subdev_lock_and_get_active_state(&csi2->asd.sd);
-
-		lanes = csi2->nlanes;
-		format = *v4l2_subdev_state_get_format(state, 0,
-						       av->source_stream);
-		bpp = ipu6_isys_mbus_code_to_bpp(format.code);
-		pixel_rate = mul_u64_u32_div(link_freq, lanes * 2, bpp);
-
-		v4l2_subdev_unlock_state(state);
-	}
-
-	av->watermark.pixel_rate = pixel_rate;
-
-	if (!pixel_rate) {
+	if (link_freq <= 0) {
 		mutex_lock(&iwake_watermark->mutex);
 		iwake_watermark->force_iwake_disable = true;
 		mutex_unlock(&iwake_watermark->mutex);
-		dev_warn(dev, "unexpected pixel_rate from %s, disable iwake.\n",
+		dev_warn(dev, "unexpected link_freq from %s, disable iwake\n",
 			 source->name);
+		return;
 	}
+
+	struct v4l2_subdev_state *state;
+	struct v4l2_mbus_framefmt *format;
+	unsigned int bpp;
+
+	state = v4l2_subdev_lock_and_get_active_state(&csi2->asd.sd);
+	format = v4l2_subdev_state_get_format(state, 0, av->source_stream);
+	bpp = ipu6_isys_mbus_code_to_bpp(format->code);
+	v4l2_subdev_unlock_state(state);
+
+	av->watermark.pixel_rate = mul_u64_u32_div(link_freq, csi2->nlanes * 2,
+						   bpp);
 }
 
 static void calculate_stream_datarate(struct ipu6_isys_video *av)
-- 
2.47.3


^ permalink raw reply related	[flat|nested] 88+ messages in thread

* [PATCH v12 72/86] media: ipu6: Get watermark configuration directly from ipdata
  2026-04-09 20:13 [PATCH v12 00/86] Generic line based metadata support, internal pads Sakari Ailus
                   ` (70 preceding siblings ...)
  2026-04-09 20:14 ` [PATCH v12 71/86] media: ipu6: Clean up link frequency calculation Sakari Ailus
@ 2026-04-09 20:14 ` Sakari Ailus
  2026-04-09 20:14 ` [PATCH v12 73/86] media: ipu6: Collect IPU streams into CSI-2 receiver sub-device context Sakari Ailus
                   ` (13 subsequent siblings)
  85 siblings, 0 replies; 88+ messages in thread
From: Sakari Ailus @ 2026-04-09 20:14 UTC (permalink / raw)
  To: linux-media
  Cc: hans, laurent.pinchart, Prabhakar, Kate Hsuan, Dave Stevenson,
	Tommaso Merciai, Benjamin Mugnier, Sylvain Petinot,
	Christophe JAILLET, Julien Massot, Naushir Patuck, Stefan Klug,
	Mirela Rabulea, André Apitzsch, Heimir Thor Sverrisson,
	Kieran Bingham, Mehdi Djait, Ricardo Ribalda Delgado,
	Hans de Goede, Jacopo Mondi, Tomi Valkeinen, David Plowman,
	Yu, Ong Hock, Ng, Khai Wen, Jai Luthra, Rishikesh Donadkar

Instead of passing watermark configuration data around, get it directly
from IPU variant specific static data structure.

Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
---
 drivers/media/pci/intel/ipu6/ipu6-isys-video.c | 12 ++++--------
 drivers/media/pci/intel/ipu6/ipu6-isys-video.h |  2 --
 2 files changed, 4 insertions(+), 10 deletions(-)

diff --git a/drivers/media/pci/intel/ipu6/ipu6-isys-video.c b/drivers/media/pci/intel/ipu6/ipu6-isys-video.c
index 0da9070aeb42..1165d5bc693b 100644
--- a/drivers/media/pci/intel/ipu6/ipu6-isys-video.c
+++ b/drivers/media/pci/intel/ipu6/ipu6-isys-video.c
@@ -759,8 +759,6 @@ void ipu6_isys_configure_stream_watermark(struct ipu6_isys_video *av,
 
 	av->watermark.width = ipu6_isys_get_frame_width(av);
 	av->watermark.height = ipu6_isys_get_frame_height(av);
-	av->watermark.sram_gran_shift = isys->pdata->ipdata->sram_gran_shift;
-	av->watermark.sram_gran_size = isys->pdata->ipdata->sram_gran_size;
 
 	ret = v4l2_g_ctrl(esd->ctrl_handler, &hb);
 	if (!ret && hb.value >= 0)
@@ -799,17 +797,15 @@ static void calculate_stream_datarate(struct ipu6_isys_video *av)
 		ipu6_isys_get_isys_format(ipu6_isys_get_format(av), 0);
 	u32 pages_per_line, pb_bytes_per_line, pixels_per_line, bytes_per_line;
 	u64 line_time_ns, stream_data_rate;
-	u16 shift, size;
-
-	shift = watermark->sram_gran_shift;
-	size = watermark->sram_gran_size;
 
 	pixels_per_line = watermark->width + watermark->hblank;
 	line_time_ns =  div_u64(pixels_per_line * NSEC_PER_SEC,
 				watermark->pixel_rate);
 	bytes_per_line = watermark->width * pfmt->bpp / 8;
-	pages_per_line = DIV_ROUND_UP(bytes_per_line, size);
-	pb_bytes_per_line = pages_per_line << shift;
+	pages_per_line = DIV_ROUND_UP(bytes_per_line,
+				      av->isys->pdata->ipdata->sram_gran_size);
+	pb_bytes_per_line =
+		pages_per_line << av->isys->pdata->ipdata->sram_gran_shift;
 	stream_data_rate = div64_u64(pb_bytes_per_line * 1000, line_time_ns);
 
 	watermark->stream_data_rate = stream_data_rate;
diff --git a/drivers/media/pci/intel/ipu6/ipu6-isys-video.h b/drivers/media/pci/intel/ipu6/ipu6-isys-video.h
index d07c16e79877..80b9d0d001b1 100644
--- a/drivers/media/pci/intel/ipu6/ipu6-isys-video.h
+++ b/drivers/media/pci/intel/ipu6/ipu6-isys-video.h
@@ -72,8 +72,6 @@ struct video_stream_watermark {
 	u32 frame_rate;
 	u64 pixel_rate;
 	u64 stream_data_rate;
-	u16 sram_gran_shift;
-	u16 sram_gran_size;
 	struct list_head stream_node;
 };
 
-- 
2.47.3


^ permalink raw reply related	[flat|nested] 88+ messages in thread

* [PATCH v12 73/86] media: ipu6: Collect IPU streams into CSI-2 receiver sub-device context
  2026-04-09 20:13 [PATCH v12 00/86] Generic line based metadata support, internal pads Sakari Ailus
                   ` (71 preceding siblings ...)
  2026-04-09 20:14 ` [PATCH v12 72/86] media: ipu6: Get watermark configuration directly from ipdata Sakari Ailus
@ 2026-04-09 20:14 ` Sakari Ailus
  2026-04-09 20:14 ` [PATCH v12 74/86] media: ipu6: Start streaming once all queues have started, stop when not Sakari Ailus
                   ` (12 subsequent siblings)
  85 siblings, 0 replies; 88+ messages in thread
From: Sakari Ailus @ 2026-04-09 20:14 UTC (permalink / raw)
  To: linux-media
  Cc: hans, laurent.pinchart, Prabhakar, Kate Hsuan, Dave Stevenson,
	Tommaso Merciai, Benjamin Mugnier, Sylvain Petinot,
	Christophe JAILLET, Julien Massot, Naushir Patuck, Stefan Klug,
	Mirela Rabulea, André Apitzsch, Heimir Thor Sverrisson,
	Kieran Bingham, Mehdi Djait, Ricardo Ribalda Delgado,
	Hans de Goede, Jacopo Mondi, Tomi Valkeinen, David Plowman,
	Yu, Ong Hock, Ng, Khai Wen, Jai Luthra, Rishikesh Donadkar

Collect the IPU streams to the CSI-2 receiver sub-device's context.

The background is that an IPU stream is bound to a CSI-2 virtual channel
but in a V4L2 pipeline there's no such assumption. Therefore a pipeline
may contain multiple virtual channels and so multiple IPU streams, too.

Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
---
 drivers/media/pci/intel/ipu6/ipu6-isys-csi2.c  | 10 +++++++++-
 drivers/media/pci/intel/ipu6/ipu6-isys-csi2.h  |  1 +
 drivers/media/pci/intel/ipu6/ipu6-isys-video.h |  1 +
 3 files changed, 11 insertions(+), 1 deletion(-)

diff --git a/drivers/media/pci/intel/ipu6/ipu6-isys-csi2.c b/drivers/media/pci/intel/ipu6/ipu6-isys-csi2.c
index 93ae5f767cc0..04825cdce7c0 100644
--- a/drivers/media/pci/intel/ipu6/ipu6-isys-csi2.c
+++ b/drivers/media/pci/intel/ipu6/ipu6-isys-csi2.c
@@ -362,10 +362,12 @@ static int ipu6_isys_csi2_enable_streams(struct v4l2_subdev *sd,
 	u64 sink_streams;
 	int ret;
 
+	list_add(&av->csi2_entry, &csi2->av_head);
+
 	ret = ipu6_isys_start_stream_firmware(av);
 	if (ret) {
 		dev_err(sd->dev, "start stream of firmware failed\n");
-		return ret;
+		goto err_del_av;
 	}
 
 	remote_pad = media_pad_remote_pad_first(&sd->entity.pads[CSI2_PAD_SINK]);
@@ -397,6 +399,9 @@ static int ipu6_isys_csi2_enable_streams(struct v4l2_subdev *sd,
 	ipu6_isys_stop_streaming_firmware(av);
 	ipu6_isys_close_streaming_firmware(av);
 
+err_del_av:
+	list_del(&av->csi2_entry);
+
 	return ret;
 }
 
@@ -426,6 +431,8 @@ static int ipu6_isys_csi2_disable_streams(struct v4l2_subdev *sd,
 
 	ipu6_isys_close_streaming_firmware(av);
 
+	list_del(&av->csi2_entry);
+
 	return 0;
 }
 
@@ -571,6 +578,7 @@ int ipu6_isys_csi2_init(struct ipu6_isys_csi2 *csi2,
 	if (ret)
 		goto fail;
 
+	INIT_LIST_HEAD(&csi2->av_head);
 	csi2->asd.source = IPU6_FW_ISYS_STREAM_SRC_CSI2_PORT0 + index;
 	csi2->asd.supported_codes = csi2_supported_codes;
 	snprintf(csi2->asd.sd.name, sizeof(csi2->asd.sd.name),
diff --git a/drivers/media/pci/intel/ipu6/ipu6-isys-csi2.h b/drivers/media/pci/intel/ipu6/ipu6-isys-csi2.h
index ce8eed91065c..bcddd5626531 100644
--- a/drivers/media/pci/intel/ipu6/ipu6-isys-csi2.h
+++ b/drivers/media/pci/intel/ipu6/ipu6-isys-csi2.h
@@ -38,6 +38,7 @@ struct ipu6_isys_csi2 {
 	struct ipu6_isys_subdev asd;
 	struct ipu6_isys *isys;
 	struct ipu6_isys_video av[NR_OF_CSI2_SRC_PADS];
+	struct list_head av_head;
 
 	void __iomem *base;
 	u32 receiver_errors;
diff --git a/drivers/media/pci/intel/ipu6/ipu6-isys-video.h b/drivers/media/pci/intel/ipu6/ipu6-isys-video.h
index 80b9d0d001b1..c1d10a9f44f2 100644
--- a/drivers/media/pci/intel/ipu6/ipu6-isys-video.h
+++ b/drivers/media/pci/intel/ipu6/ipu6-isys-video.h
@@ -77,6 +77,7 @@ struct video_stream_watermark {
 
 struct ipu6_isys_video {
 	struct ipu6_isys_queue aq;
+	struct list_head csi2_entry;
 	/* Serialise access to other fields in the struct. */
 	struct mutex mutex;
 	struct media_pad pad;
-- 
2.47.3


^ permalink raw reply related	[flat|nested] 88+ messages in thread

* [PATCH v12 74/86] media: ipu6: Start streaming once all queues have started, stop when not
  2026-04-09 20:13 [PATCH v12 00/86] Generic line based metadata support, internal pads Sakari Ailus
                   ` (72 preceding siblings ...)
  2026-04-09 20:14 ` [PATCH v12 73/86] media: ipu6: Collect IPU streams into CSI-2 receiver sub-device context Sakari Ailus
@ 2026-04-09 20:14 ` Sakari Ailus
  2026-04-09 20:14 ` [PATCH v12 75/86] media: ipu6: Add lockdep checks for CSI-2 streaming enable and disable Sakari Ailus
                   ` (11 subsequent siblings)
  85 siblings, 0 replies; 88+ messages in thread
From: Sakari Ailus @ 2026-04-09 20:14 UTC (permalink / raw)
  To: linux-media
  Cc: hans, laurent.pinchart, Prabhakar, Kate Hsuan, Dave Stevenson,
	Tommaso Merciai, Benjamin Mugnier, Sylvain Petinot,
	Christophe JAILLET, Julien Massot, Naushir Patuck, Stefan Klug,
	Mirela Rabulea, André Apitzsch, Heimir Thor Sverrisson,
	Kieran Bingham, Mehdi Djait, Ricardo Ribalda Delgado,
	Hans de Goede, Jacopo Mondi, Tomi Valkeinen, David Plowman,
	Yu, Ong Hock, Ng, Khai Wen, Jai Luthra, Rishikesh Donadkar

Start streaming once all buffer queues connected via enabled routes have
been set streaming, similarly stop when the first queue is stopped.

Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
---
 drivers/media/pci/intel/ipu6/ipu6-isys-csi2.c | 45 +++++++++++++++++++
 .../media/pci/intel/ipu6/ipu6-isys-queue.c    |  7 +--
 2 files changed, 46 insertions(+), 6 deletions(-)

diff --git a/drivers/media/pci/intel/ipu6/ipu6-isys-csi2.c b/drivers/media/pci/intel/ipu6/ipu6-isys-csi2.c
index 04825cdce7c0..8deafe38be5d 100644
--- a/drivers/media/pci/intel/ipu6/ipu6-isys-csi2.c
+++ b/drivers/media/pci/intel/ipu6/ipu6-isys-csi2.c
@@ -12,6 +12,7 @@
 #include <linux/io.h>
 #include <linux/minmax.h>
 #include <linux/sprintf.h>
+#include <linux/string_choices.h>
 
 #include <media/media-entity.h>
 #include <media/v4l2-ctrls.h>
@@ -347,6 +348,42 @@ static int ipu6_isys_csi2_set_stream(struct v4l2_subdev *sd,
 	return ret;
 }
 
+static bool ipu6_isys_csi2_streaming_change(struct ipu6_isys_subdev *asd,
+					    struct v4l2_subdev_state *state,
+					    u32 pad, bool enable)
+{
+	u32 streams_enabled = 0, nodes_streaming = 0;
+	struct v4l2_subdev_route *route;
+
+	for_each_active_route(&state->routing, route) {
+		struct media_pad *video_pad =
+			media_pad_remote_pad_unique(&asd->sd.entity.pads[route->source_pad]);
+		struct ipu6_isys_video *av = !video_pad ? NULL :
+			container_of_const(video_pad,
+					   struct ipu6_isys_video, pad);
+
+		if (!av) {
+			dev_dbg(asd->sd.dev,
+				"can't find source pad for \"%s\":%u\n",
+				asd->sd.entity.name, route->source_pad);
+			return false;
+		}
+
+		streams_enabled++;
+		if (av->streaming || (enable && pad == route->source_pad))
+			nodes_streaming++;
+	}
+
+	if (streams_enabled == nodes_streaming) {
+		dev_dbg(asd->sd.dev,
+			"changing streaming state to %s on \"%s\":%u\n",
+			str_enabled_disabled(enable), asd->sd.entity.name, pad);
+		return true;
+	}
+
+	return false;
+}
+
 static int ipu6_isys_csi2_enable_streams(struct v4l2_subdev *sd,
 					 struct v4l2_subdev_state *state,
 					 u32 pad, u64 streams_mask)
@@ -364,6 +401,9 @@ static int ipu6_isys_csi2_enable_streams(struct v4l2_subdev *sd,
 
 	list_add(&av->csi2_entry, &csi2->av_head);
 
+	if (!ipu6_isys_csi2_streaming_change(asd, state, pad, true))
+		return 0;
+
 	ret = ipu6_isys_start_stream_firmware(av);
 	if (ret) {
 		dev_err(sd->dev, "start stream of firmware failed\n");
@@ -409,6 +449,7 @@ static int ipu6_isys_csi2_disable_streams(struct v4l2_subdev *sd,
 					  struct v4l2_subdev_state *state,
 					  u32 pad, u64 streams_mask)
 {
+	struct ipu6_isys_subdev *asd = to_ipu6_isys_subdev(sd);
 	struct media_pad *remote_pad,
 		*vdev_pad = media_pad_remote_pad_unique(&sd->entity.pads[pad]);
 	struct ipu6_isys_video *av =
@@ -416,6 +457,9 @@ static int ipu6_isys_csi2_disable_streams(struct v4l2_subdev *sd,
 	struct v4l2_subdev *remote_sd;
 	u64 sink_streams;
 
+	if (!ipu6_isys_csi2_streaming_change(asd, state, pad, false))
+		goto out_del_csi2_entry;
+
 	sink_streams =
 		v4l2_subdev_state_xlate_streams(state, pad, CSI2_PAD_SINK,
 						&streams_mask);
@@ -431,6 +475,7 @@ static int ipu6_isys_csi2_disable_streams(struct v4l2_subdev *sd,
 
 	ipu6_isys_close_streaming_firmware(av);
 
+out_del_csi2_entry:
 	list_del(&av->csi2_entry);
 
 	return 0;
diff --git a/drivers/media/pci/intel/ipu6/ipu6-isys-queue.c b/drivers/media/pci/intel/ipu6/ipu6-isys-queue.c
index 13d759b27ca0..7df13d330667 100644
--- a/drivers/media/pci/intel/ipu6/ipu6-isys-queue.c
+++ b/drivers/media/pci/intel/ipu6/ipu6-isys-queue.c
@@ -585,14 +585,10 @@ static int start_streaming(struct vb2_queue *q, unsigned int count)
 	ipu6_isys_configure_stream_watermark(av, source_pad->entity);
 	ipu6_isys_update_stream_watermark(av, true);
 
-	if (stream->nr_streaming != stream->nr_queues)
-		goto out;
-
 	ret = ipu6_isys_stream_start(av);
 	if (ret)
 		goto out_stream_start;
 
-out:
 	mutex_unlock(&stream->mutex);
 
 	return 0;
@@ -626,8 +622,7 @@ static void stop_streaming(struct vb2_queue *q)
 	ipu6_isys_update_stream_watermark(av, false);
 
 	mutex_lock(&av->isys->stream_mutex);
-	if (stream->nr_streaming == stream->nr_queues)
-		ipu6_isys_video_set_streaming(av, 0);
+	ipu6_isys_video_set_streaming(av, 0);
 	list_del(&aq->node);
 	mutex_unlock(&av->isys->stream_mutex);
 
-- 
2.47.3


^ permalink raw reply related	[flat|nested] 88+ messages in thread

* [PATCH v12 75/86] media: ipu6: Add lockdep checks for CSI-2 streaming enable and disable
  2026-04-09 20:13 [PATCH v12 00/86] Generic line based metadata support, internal pads Sakari Ailus
                   ` (73 preceding siblings ...)
  2026-04-09 20:14 ` [PATCH v12 74/86] media: ipu6: Start streaming once all queues have started, stop when not Sakari Ailus
@ 2026-04-09 20:14 ` Sakari Ailus
  2026-04-09 20:14 ` [PATCH v12 76/86] media: ipu6: Remove nr_queues and nr_streaming fields in ipu6_isys_stream Sakari Ailus
                   ` (10 subsequent siblings)
  85 siblings, 0 replies; 88+ messages in thread
From: Sakari Ailus @ 2026-04-09 20:14 UTC (permalink / raw)
  To: linux-media
  Cc: hans, laurent.pinchart, Prabhakar, Kate Hsuan, Dave Stevenson,
	Tommaso Merciai, Benjamin Mugnier, Sylvain Petinot,
	Christophe JAILLET, Julien Massot, Naushir Patuck, Stefan Klug,
	Mirela Rabulea, André Apitzsch, Heimir Thor Sverrisson,
	Kieran Bingham, Mehdi Djait, Ricardo Ribalda Delgado,
	Hans de Goede, Jacopo Mondi, Tomi Valkeinen, David Plowman,
	Yu, Ong Hock, Ng, Khai Wen, Jai Luthra, Rishikesh Donadkar

The callbacks for enabling and disabling streams access data serialised
using the isys stream_mutex; add lockdep checks for this.

Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
---
 drivers/media/pci/intel/ipu6/ipu6-isys-csi2.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/drivers/media/pci/intel/ipu6/ipu6-isys-csi2.c b/drivers/media/pci/intel/ipu6/ipu6-isys-csi2.c
index 8deafe38be5d..f37e25063d6d 100644
--- a/drivers/media/pci/intel/ipu6/ipu6-isys-csi2.c
+++ b/drivers/media/pci/intel/ipu6/ipu6-isys-csi2.c
@@ -399,6 +399,8 @@ static int ipu6_isys_csi2_enable_streams(struct v4l2_subdev *sd,
 	u64 sink_streams;
 	int ret;
 
+	lockdep_assert_held(&csi2->isys->stream_mutex);
+
 	list_add(&av->csi2_entry, &csi2->av_head);
 
 	if (!ipu6_isys_csi2_streaming_change(asd, state, pad, true))
@@ -457,6 +459,8 @@ static int ipu6_isys_csi2_disable_streams(struct v4l2_subdev *sd,
 	struct v4l2_subdev *remote_sd;
 	u64 sink_streams;
 
+	lockdep_assert_held(&csi2->isys->stream_mutex);
+
 	if (!ipu6_isys_csi2_streaming_change(asd, state, pad, false))
 		goto out_del_csi2_entry;
 
-- 
2.47.3


^ permalink raw reply related	[flat|nested] 88+ messages in thread

* [PATCH v12 76/86] media: ipu6: Remove nr_queues and nr_streaming fields in ipu6_isys_stream
  2026-04-09 20:13 [PATCH v12 00/86] Generic line based metadata support, internal pads Sakari Ailus
                   ` (74 preceding siblings ...)
  2026-04-09 20:14 ` [PATCH v12 75/86] media: ipu6: Add lockdep checks for CSI-2 streaming enable and disable Sakari Ailus
@ 2026-04-09 20:14 ` Sakari Ailus
  2026-04-09 20:14 ` [PATCH v12 77/86] media: ipu6: Collect enabled stream IDs Sakari Ailus
                   ` (9 subsequent siblings)
  85 siblings, 0 replies; 88+ messages in thread
From: Sakari Ailus @ 2026-04-09 20:14 UTC (permalink / raw)
  To: linux-media
  Cc: hans, laurent.pinchart, Prabhakar, Kate Hsuan, Dave Stevenson,
	Tommaso Merciai, Benjamin Mugnier, Sylvain Petinot,
	Christophe JAILLET, Julien Massot, Naushir Patuck, Stefan Klug,
	Mirela Rabulea, André Apitzsch, Heimir Thor Sverrisson,
	Kieran Bingham, Mehdi Djait, Ricardo Ribalda Delgado,
	Hans de Goede, Jacopo Mondi, Tomi Valkeinen, David Plowman,
	Yu, Ong Hock, Ng, Khai Wen, Jai Luthra, Rishikesh Donadkar

nr_queues and nr_streaming fields were being used to determine whether
streaming was to be started in the upstream sub-device. As we store the
streaming state in the CSI-2 sub-device, there's no longer need for that.
Drop these fields.

Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
---
 drivers/media/pci/intel/ipu6/ipu6-isys-csi2.c |  5 ++++
 drivers/media/pci/intel/ipu6/ipu6-isys-csi2.h |  1 +
 .../media/pci/intel/ipu6/ipu6-isys-queue.c    | 24 +++++++++----------
 .../media/pci/intel/ipu6/ipu6-isys-video.c    | 19 ++++-----------
 .../media/pci/intel/ipu6/ipu6-isys-video.h    |  7 ++----
 5 files changed, 25 insertions(+), 31 deletions(-)

diff --git a/drivers/media/pci/intel/ipu6/ipu6-isys-csi2.c b/drivers/media/pci/intel/ipu6/ipu6-isys-csi2.c
index f37e25063d6d..c2f4ea444e8e 100644
--- a/drivers/media/pci/intel/ipu6/ipu6-isys-csi2.c
+++ b/drivers/media/pci/intel/ipu6/ipu6-isys-csi2.c
@@ -432,6 +432,8 @@ static int ipu6_isys_csi2_enable_streams(struct v4l2_subdev *sd,
 	if (ret)
 		goto err_stop_stream_csi2;
 
+	csi2->streaming = true;
+
 	return 0;
 
 err_stop_stream_csi2:
@@ -452,6 +454,7 @@ static int ipu6_isys_csi2_disable_streams(struct v4l2_subdev *sd,
 					  u32 pad, u64 streams_mask)
 {
 	struct ipu6_isys_subdev *asd = to_ipu6_isys_subdev(sd);
+	struct ipu6_isys_csi2 *csi2 = ipu6_isys_subdev_to_csi2(asd);
 	struct media_pad *remote_pad,
 		*vdev_pad = media_pad_remote_pad_unique(&sd->entity.pads[pad]);
 	struct ipu6_isys_video *av =
@@ -479,6 +482,8 @@ static int ipu6_isys_csi2_disable_streams(struct v4l2_subdev *sd,
 
 	ipu6_isys_close_streaming_firmware(av);
 
+	csi2->streaming = false;
+
 out_del_csi2_entry:
 	list_del(&av->csi2_entry);
 
diff --git a/drivers/media/pci/intel/ipu6/ipu6-isys-csi2.h b/drivers/media/pci/intel/ipu6/ipu6-isys-csi2.h
index bcddd5626531..9178638edd37 100644
--- a/drivers/media/pci/intel/ipu6/ipu6-isys-csi2.h
+++ b/drivers/media/pci/intel/ipu6/ipu6-isys-csi2.h
@@ -44,6 +44,7 @@ struct ipu6_isys_csi2 {
 	u32 receiver_errors;
 	unsigned int nlanes;
 	unsigned int port;
+	bool streaming;
 };
 
 struct ipu6_isys_csi2_timing {
diff --git a/drivers/media/pci/intel/ipu6/ipu6-isys-queue.c b/drivers/media/pci/intel/ipu6/ipu6-isys-queue.c
index 7df13d330667..b7c7ccae0452 100644
--- a/drivers/media/pci/intel/ipu6/ipu6-isys-queue.c
+++ b/drivers/media/pci/intel/ipu6/ipu6-isys-queue.c
@@ -296,6 +296,9 @@ static int ipu6_isys_stream_start(struct ipu6_isys_video *av)
 	if (ret)
 		return ret;
 
+	if (!av->csi2->streaming)
+		return 0;
+
 	do {
 		struct ipu6_fw_isys_frame_buff_set_abi *buf = NULL;
 		struct isys_fw_msgs *msg;
@@ -343,6 +346,7 @@ static void buf_queue(struct vb2_buffer *vb)
 	struct device *dev = &av->isys->adev->auxdev.dev;
 	struct ipu6_fw_isys_frame_buff_set_abi *buf = NULL;
 	struct ipu6_isys_stream *stream = av->stream;
+	struct ipu6_isys_csi2 *csi2;
 	struct ipu6_isys_buffer_list bl;
 	struct isys_fw_msgs *msg;
 	unsigned long flags;
@@ -366,7 +370,8 @@ static void buf_queue(struct vb2_buffer *vb)
 
 	mutex_lock(&stream->mutex);
 
-	if (stream->nr_streaming != stream->nr_queues) {
+	csi2 = ipu6_isys_subdev_to_csi2(stream->asd);
+	if (!csi2->streaming) {
 		dev_dbg(dev, "not streaming yet, adding to incoming\n");
 		goto out;
 	}
@@ -530,7 +535,8 @@ static int start_streaming(struct vb2_queue *q, unsigned int count)
 		ipu6_isys_get_isys_format(ipu6_isys_get_format(av), 0);
 	struct ipu6_isys_stream *stream;
 	struct media_pad *source_pad, *remote_pad;
-	int nr_queues, ret;
+	bool first;
+	int ret;
 
 	dev_dbg(dev, "stream: %s: width %u, height %u, css pixelformat %u\n",
 		av->vdev.name, ipu6_isys_get_frame_width(av),
@@ -550,11 +556,12 @@ static int start_streaming(struct vb2_queue *q, unsigned int count)
 		goto out_return_buffers;
 	}
 
-	ret = ipu6_isys_setup_video(av, remote_pad, source_pad, &nr_queues);
+	ret = ipu6_isys_setup_video(av, remote_pad, source_pad);
 	if (ret < 0) {
 		dev_dbg(dev, "failed to setup video\n");
 		goto out_return_buffers;
 	}
+	first = ret;
 
 	ret = ipu6_isys_link_fmt_validate(aq);
 	if (ret) {
@@ -570,17 +577,12 @@ static int start_streaming(struct vb2_queue *q, unsigned int count)
 
 	stream = av->stream;
 	mutex_lock(&stream->mutex);
-	if (!stream->nr_streaming) {
-		ret = ipu6_isys_video_prepare_stream(av, source_pad->entity,
-						     nr_queues);
+	if (first) {
+		ret = ipu6_isys_video_prepare_stream(av, source_pad->entity);
 		if (ret)
 			goto out_fw_close;
 	}
 
-	stream->nr_streaming++;
-	dev_dbg(dev, "queue %u of %u\n", stream->nr_streaming,
-		stream->nr_queues);
-
 	list_add(&aq->node, &stream->queues);
 	ipu6_isys_configure_stream_watermark(av, source_pad->entity);
 	ipu6_isys_update_stream_watermark(av, true);
@@ -596,7 +598,6 @@ static int start_streaming(struct vb2_queue *q, unsigned int count)
 out_stream_start:
 	ipu6_isys_update_stream_watermark(av, false);
 	list_del(&aq->node);
-	stream->nr_streaming--;
 
 out_fw_close:
 	mutex_unlock(&stream->mutex);
@@ -626,7 +627,6 @@ static void stop_streaming(struct vb2_queue *q)
 	list_del(&aq->node);
 	mutex_unlock(&av->isys->stream_mutex);
 
-	stream->nr_streaming--;
 	mutex_unlock(&stream->mutex);
 
 	ipu6_isys_stream_cleanup(av);
diff --git a/drivers/media/pci/intel/ipu6/ipu6-isys-video.c b/drivers/media/pci/intel/ipu6/ipu6-isys-video.c
index 1165d5bc693b..9d0ed47df280 100644
--- a/drivers/media/pci/intel/ipu6/ipu6-isys-video.c
+++ b/drivers/media/pci/intel/ipu6/ipu6-isys-video.c
@@ -714,16 +714,11 @@ void ipu6_isys_close_streaming_firmware(struct ipu6_isys_video *av)
 }
 
 int ipu6_isys_video_prepare_stream(struct ipu6_isys_video *av,
-				   struct media_entity *source_entity,
-				   int nr_queues)
+				   struct media_entity *source_entity)
 {
 	struct ipu6_isys_stream *stream = av->stream;
 	struct ipu6_isys_csi2 *csi2;
 
-	if (WARN_ON(stream->nr_streaming))
-		return -EINVAL;
-
-	stream->nr_queues = nr_queues;
 	atomic_set(&stream->sequence, 0);
 
 	stream->seq_index = 0;
@@ -1099,7 +1094,7 @@ void ipu6_isys_fw_close(struct ipu6_isys *isys)
 
 int ipu6_isys_setup_video(struct ipu6_isys_video *av,
 			  struct media_pad *remote_pad,
-			  struct media_pad *source_pad, int *nr_queues)
+			  struct media_pad *source_pad)
 {
 	const struct ipu6_isys_pixelformat *pfmt =
 		ipu6_isys_get_isys_format(ipu6_isys_get_format(av), 0);
@@ -1113,16 +1108,11 @@ int ipu6_isys_setup_video(struct ipu6_isys_video *av,
 	struct ipu6_isys_subdev *asd = to_ipu6_isys_subdev(remote_sd);
 	int ret = -EINVAL;
 
-	*nr_queues = 0;
-
 	/* Find the root */
 	state = v4l2_subdev_lock_and_get_active_state(remote_sd);
-	for_each_active_route(&state->routing, r) {
-		(*nr_queues)++;
-
+	for_each_active_route(&state->routing, r)
 		if (r->source_pad == remote_pad->index)
 			route = r;
-	}
 
 	if (!route) {
 		v4l2_subdev_unlock_state(state);
@@ -1150,6 +1140,7 @@ int ipu6_isys_setup_video(struct ipu6_isys_video *av,
 		return ret;
 	}
 
+	pipeline = video_device_pipeline(&av->vdev);
 	ret = video_device_pipeline_alloc_start(&av->vdev);
 	if (ret < 0) {
 		dev_dbg(dev, "media pipeline start failed\n");
@@ -1163,7 +1154,7 @@ int ipu6_isys_setup_video(struct ipu6_isys_video *av,
 		return -EINVAL;
 	}
 
-	return 0;
+	return !pipeline;
 }
 
 /*
diff --git a/drivers/media/pci/intel/ipu6/ipu6-isys-video.h b/drivers/media/pci/intel/ipu6/ipu6-isys-video.h
index c1d10a9f44f2..5dd70175a857 100644
--- a/drivers/media/pci/intel/ipu6/ipu6-isys-video.h
+++ b/drivers/media/pci/intel/ipu6/ipu6-isys-video.h
@@ -51,8 +51,6 @@ struct ipu6_isys_stream {
 	unsigned int nr_output_pins;
 	struct ipu6_isys_subdev *asd;
 
-	int nr_queues;	/* Number of capture queues */
-	int nr_streaming;
 	struct list_head queues;
 	struct completion stream_open_completion;
 	struct completion stream_close_completion;
@@ -106,14 +104,13 @@ int ipu6_isys_start_stream_firmware(struct ipu6_isys_video *av);
 void ipu6_isys_stop_streaming_firmware(struct ipu6_isys_video *av);
 void ipu6_isys_close_streaming_firmware(struct ipu6_isys_video *av);
 int ipu6_isys_video_prepare_stream(struct ipu6_isys_video *av,
-				   struct media_entity *source_entity,
-				   int nr_queues);
+				   struct media_entity *source_entity);
 int ipu6_isys_video_set_streaming(struct ipu6_isys_video *av, int state);
 int ipu6_isys_fw_open(struct ipu6_isys *isys);
 void ipu6_isys_fw_close(struct ipu6_isys *isys);
 int ipu6_isys_setup_video(struct ipu6_isys_video *av,
 			  struct media_pad *remote_pad,
-			  struct media_pad *source_pad, int *nr_queues);
+			  struct media_pad *source_pad);
 int ipu6_isys_video_init(struct ipu6_isys_video *av);
 void ipu6_isys_video_cleanup(struct ipu6_isys_video *av);
 void ipu6_isys_put_stream(struct ipu6_isys_stream *stream);
-- 
2.47.3


^ permalink raw reply related	[flat|nested] 88+ messages in thread

* [PATCH v12 77/86] media: ipu6: Collect enabled stream IDs
  2026-04-09 20:13 [PATCH v12 00/86] Generic line based metadata support, internal pads Sakari Ailus
                   ` (75 preceding siblings ...)
  2026-04-09 20:14 ` [PATCH v12 76/86] media: ipu6: Remove nr_queues and nr_streaming fields in ipu6_isys_stream Sakari Ailus
@ 2026-04-09 20:14 ` Sakari Ailus
  2026-04-09 20:14 ` [PATCH v12 78/86] media: ipu6: Avoid accessing av->streams before streaming Sakari Ailus
                   ` (8 subsequent siblings)
  85 siblings, 0 replies; 88+ messages in thread
From: Sakari Ailus @ 2026-04-09 20:14 UTC (permalink / raw)
  To: linux-media
  Cc: hans, laurent.pinchart, Prabhakar, Kate Hsuan, Dave Stevenson,
	Tommaso Merciai, Benjamin Mugnier, Sylvain Petinot,
	Christophe JAILLET, Julien Massot, Naushir Patuck, Stefan Klug,
	Mirela Rabulea, André Apitzsch, Heimir Thor Sverrisson,
	Kieran Bingham, Mehdi Djait, Ricardo Ribalda Delgado,
	Hans de Goede, Jacopo Mondi, Tomi Valkeinen, David Plowman,
	Yu, Ong Hock, Ng, Khai Wen, Jai Luthra, Rishikesh Donadkar

Collect enable stream IDs as streaming is enabled on video nodes. These
values will be needed once streaming actually starts. This is required for
multiple streams from a single source.

Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
---
 drivers/media/pci/intel/ipu6/ipu6-isys-csi2.c | 27 ++++++++++++-------
 drivers/media/pci/intel/ipu6/ipu6-isys-csi2.h |  1 +
 2 files changed, 19 insertions(+), 9 deletions(-)

diff --git a/drivers/media/pci/intel/ipu6/ipu6-isys-csi2.c b/drivers/media/pci/intel/ipu6/ipu6-isys-csi2.c
index c2f4ea444e8e..77e13644746d 100644
--- a/drivers/media/pci/intel/ipu6/ipu6-isys-csi2.c
+++ b/drivers/media/pci/intel/ipu6/ipu6-isys-csi2.c
@@ -381,6 +381,10 @@ static bool ipu6_isys_csi2_streaming_change(struct ipu6_isys_subdev *asd,
 		return true;
 	}
 
+	dev_dbg(asd->sd.dev, "not setting streaming %s %s (%u/%u)\n",
+		str_enabled_disabled(enable), enable ? "yet" : "anymore",
+		nodes_streaming, streams_enabled);
+
 	return false;
 }
 
@@ -403,6 +407,11 @@ static int ipu6_isys_csi2_enable_streams(struct v4l2_subdev *sd,
 
 	list_add(&av->csi2_entry, &csi2->av_head);
 
+	sink_streams =
+		v4l2_subdev_state_xlate_streams(state, pad, CSI2_PAD_SINK,
+						&streams_mask);
+	csi2->stream_ids |= sink_streams;
+
 	if (!ipu6_isys_csi2_streaming_change(asd, state, pad, true))
 		return 0;
 
@@ -412,13 +421,6 @@ static int ipu6_isys_csi2_enable_streams(struct v4l2_subdev *sd,
 		goto err_del_av;
 	}
 
-	remote_pad = media_pad_remote_pad_first(&sd->entity.pads[CSI2_PAD_SINK]);
-	remote_sd = media_entity_to_v4l2_subdev(remote_pad->entity);
-
-	sink_streams =
-		v4l2_subdev_state_xlate_streams(state, pad, CSI2_PAD_SINK,
-						&streams_mask);
-
 	ret = ipu6_isys_csi2_calc_timing(csi2, &timing, CSI2_ACCINV);
 	if (ret)
 		goto err_stop_stream_firmware;
@@ -427,8 +429,11 @@ static int ipu6_isys_csi2_enable_streams(struct v4l2_subdev *sd,
 	if (ret)
 		goto err_stop_stream_firmware;
 
+	remote_pad = media_pad_remote_pad_first(&sd->entity.pads[CSI2_PAD_SINK]);
+	remote_sd = media_entity_to_v4l2_subdev(remote_pad->entity);
+
 	ret = v4l2_subdev_enable_streams(remote_sd, remote_pad->index,
-					 sink_streams);
+					 csi2->stream_ids);
 	if (ret)
 		goto err_stop_stream_csi2;
 
@@ -444,6 +449,7 @@ static int ipu6_isys_csi2_enable_streams(struct v4l2_subdev *sd,
 	ipu6_isys_close_streaming_firmware(av);
 
 err_del_av:
+	csi2->stream_ids &= ~sink_streams;
 	list_del(&av->csi2_entry);
 
 	return ret;
@@ -471,6 +477,8 @@ static int ipu6_isys_csi2_disable_streams(struct v4l2_subdev *sd,
 		v4l2_subdev_state_xlate_streams(state, pad, CSI2_PAD_SINK,
 						&streams_mask);
 
+	csi2->streaming = false;
+
 	remote_pad = media_pad_remote_pad_first(&sd->entity.pads[CSI2_PAD_SINK]);
 	remote_sd = media_entity_to_v4l2_subdev(remote_pad->entity);
 
@@ -478,7 +486,8 @@ static int ipu6_isys_csi2_disable_streams(struct v4l2_subdev *sd,
 
 	ipu6_isys_csi2_set_stream(sd, NULL, 0, false);
 
-	v4l2_subdev_disable_streams(remote_sd, remote_pad->index, sink_streams);
+	v4l2_subdev_disable_streams(remote_sd, remote_pad->index,
+				    csi2->stream_ids);
 
 	ipu6_isys_close_streaming_firmware(av);
 
diff --git a/drivers/media/pci/intel/ipu6/ipu6-isys-csi2.h b/drivers/media/pci/intel/ipu6/ipu6-isys-csi2.h
index 9178638edd37..5ff7af0ab274 100644
--- a/drivers/media/pci/intel/ipu6/ipu6-isys-csi2.h
+++ b/drivers/media/pci/intel/ipu6/ipu6-isys-csi2.h
@@ -45,6 +45,7 @@ struct ipu6_isys_csi2 {
 	unsigned int nlanes;
 	unsigned int port;
 	bool streaming;
+	u64 stream_ids;
 };
 
 struct ipu6_isys_csi2_timing {
-- 
2.47.3


^ permalink raw reply related	[flat|nested] 88+ messages in thread

* [PATCH v12 78/86] media: ipu6: Avoid accessing av->streams before streaming
  2026-04-09 20:13 [PATCH v12 00/86] Generic line based metadata support, internal pads Sakari Ailus
                   ` (76 preceding siblings ...)
  2026-04-09 20:14 ` [PATCH v12 77/86] media: ipu6: Collect enabled stream IDs Sakari Ailus
@ 2026-04-09 20:14 ` Sakari Ailus
  2026-04-09 20:14 ` [PATCH v12 79/86] media: ipu6: Rework watermark calculation Sakari Ailus
                   ` (7 subsequent siblings)
  85 siblings, 0 replies; 88+ messages in thread
From: Sakari Ailus @ 2026-04-09 20:14 UTC (permalink / raw)
  To: linux-media
  Cc: hans, laurent.pinchart, Prabhakar, Kate Hsuan, Dave Stevenson,
	Tommaso Merciai, Benjamin Mugnier, Sylvain Petinot,
	Christophe JAILLET, Julien Massot, Naushir Patuck, Stefan Klug,
	Mirela Rabulea, André Apitzsch, Heimir Thor Sverrisson,
	Kieran Bingham, Mehdi Djait, Ricardo Ribalda Delgado,
	Hans de Goede, Jacopo Mondi, Tomi Valkeinen, David Plowman,
	Yu, Ong Hock, Ng, Khai Wen, Jai Luthra, Rishikesh Donadkar

Streams will soon be allocated just for the duration of streaming
operation. In this case, obtain the CSI-2 sub-device through av->csi2
which is set up during driver probe.

Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
---
 drivers/media/pci/intel/ipu6/ipu6-isys-video.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/media/pci/intel/ipu6/ipu6-isys-video.c b/drivers/media/pci/intel/ipu6/ipu6-isys-video.c
index 9d0ed47df280..56ed1a4c45d6 100644
--- a/drivers/media/pci/intel/ipu6/ipu6-isys-video.c
+++ b/drivers/media/pci/intel/ipu6/ipu6-isys-video.c
@@ -960,7 +960,7 @@ int ipu6_isys_video_set_streaming(struct ipu6_isys_video *av, int state)
 	struct media_pad *r_pad;
 	int ret = 0;
 
-	sd = &av->stream->asd->sd;
+	sd = &av->csi2->asd.sd;
 	r_pad = media_pad_remote_pad_first(&av->pad);
 
 	if (!state) {
-- 
2.47.3


^ permalink raw reply related	[flat|nested] 88+ messages in thread

* [PATCH v12 79/86] media: ipu6: Rework watermark calculation
  2026-04-09 20:13 [PATCH v12 00/86] Generic line based metadata support, internal pads Sakari Ailus
                   ` (77 preceding siblings ...)
  2026-04-09 20:14 ` [PATCH v12 78/86] media: ipu6: Avoid accessing av->streams before streaming Sakari Ailus
@ 2026-04-09 20:14 ` Sakari Ailus
  2026-04-09 20:14 ` [PATCH v12 80/86] media: ipu6: Rework watermark setting Sakari Ailus
                   ` (6 subsequent siblings)
  85 siblings, 0 replies; 88+ messages in thread
From: Sakari Ailus @ 2026-04-09 20:14 UTC (permalink / raw)
  To: linux-media
  Cc: hans, laurent.pinchart, Prabhakar, Kate Hsuan, Dave Stevenson,
	Tommaso Merciai, Benjamin Mugnier, Sylvain Petinot,
	Christophe JAILLET, Julien Massot, Naushir Patuck, Stefan Klug,
	Mirela Rabulea, André Apitzsch, Heimir Thor Sverrisson,
	Kieran Bingham, Mehdi Djait, Ricardo Ribalda Delgado,
	Hans de Goede, Jacopo Mondi, Tomi Valkeinen, David Plowman,
	Yu, Ong Hock, Ng, Khai Wen, Jai Luthra, Rishikesh Donadkar

Move watermark calculation to ipu6-isys-csi2.c and do the whole thing
as streaming is about to start. There's no need to store all the
information so that it is bound to video nodes.

Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
---
 drivers/media/pci/intel/ipu6/ipu6-isys-csi2.c | 78 +++++++++++++++-
 drivers/media/pci/intel/ipu6/ipu6-isys-csi2.h |  4 +
 .../media/pci/intel/ipu6/ipu6-isys-queue.c    |  5 -
 .../media/pci/intel/ipu6/ipu6-isys-video.c    | 92 -------------------
 .../media/pci/intel/ipu6/ipu6-isys-video.h    | 15 ---
 drivers/media/pci/intel/ipu6/ipu6-isys.c      | 42 ++++-----
 drivers/media/pci/intel/ipu6/ipu6-isys.h      |  2 +-
 7 files changed, 97 insertions(+), 141 deletions(-)

diff --git a/drivers/media/pci/intel/ipu6/ipu6-isys-csi2.c b/drivers/media/pci/intel/ipu6/ipu6-isys-csi2.c
index 77e13644746d..15e965396f4a 100644
--- a/drivers/media/pci/intel/ipu6/ipu6-isys-csi2.c
+++ b/drivers/media/pci/intel/ipu6/ipu6-isys-csi2.c
@@ -233,6 +233,73 @@ void ipu6_isys_csi2_error(struct ipu6_isys_csi2 *csi2)
 	}
 }
 
+static void ipu6_isys_csi2_setup_watermark(struct ipu6_isys_csi2 *csi2,
+					   struct v4l2_subdev_state *csi2_state,
+					   struct v4l2_subdev *remote_sd)
+{
+	struct device *dev = &csi2->isys->adev->auxdev.dev;
+	struct v4l2_control hb = { .id = V4L2_CID_HBLANK, .value = 0 };
+	struct v4l2_subdev_route *route;
+	u32 max_stream_data_rate = 0, hblank = 0;
+	s64 link_freq;
+	int ret;
+
+	ret = v4l2_g_ctrl(remote_sd->ctrl_handler, &hb);
+	if (!ret)
+		hblank = max(0, hb.value);
+
+	link_freq = ipu6_isys_csi2_get_link_freq(csi2);
+	if (link_freq <= 0) {
+		csi2->watermark.force_iwake_disable = true;
+		dev_warn(dev, "unexpected link_freq %lld (source %s)\n",
+			 link_freq, remote_sd->entity.name);
+		ipu6_isys_update_watermark_setting(csi2->isys);
+		return;
+	}
+
+	for_each_active_route(&csi2_state->routing, route) {
+		struct v4l2_mbus_framefmt *fmt;
+
+		fmt = v4l2_subdev_state_get_format(csi2_state, CSI2_PAD_SINK,
+						   route->sink_stream);
+		if (WARN_ON(!fmt))
+			continue;
+
+		u32 bpp = ipu6_isys_mbus_code_to_bpp(fmt->code);
+		u64 pixel_rate = mul_u64_u32_div(link_freq, csi2->nlanes * 2,
+						 bpp);
+		u32 pixels_per_line = fmt->width + hblank;
+		u64 line_time_ns = div_u64(pixels_per_line * NSEC_PER_SEC,
+					   pixel_rate);
+		u32 bytes_per_line = fmt->width * bpp / 8;
+		u32 pages_per_line =
+			DIV_ROUND_UP(bytes_per_line,
+				     csi2->isys->pdata->ipdata->sram_gran_size);
+		u32 pb_bytes_per_line =
+			pages_per_line << csi2->isys->pdata->ipdata->sram_gran_shift;
+		u64 stream_data_rate =
+			div64_u64(pb_bytes_per_line * 1000, line_time_ns);
+
+		dev_dbg(dev, "stream %u:%u -> %u:%u data rate %lld\n",
+			route->sink_pad, route->sink_stream, route->source_pad,
+			route->source_stream, stream_data_rate);
+
+		max_stream_data_rate = max(max_stream_data_rate,
+					   stream_data_rate);
+	}
+
+	csi2->watermark.stream_data_rate = max_stream_data_rate;
+
+	ipu6_isys_update_watermark_setting(csi2->isys);
+}
+
+static void ipu6_isys_csi2_clear_watermark(struct ipu6_isys_csi2 *csi2)
+{
+	csi2->watermark.force_iwake_disable = false;
+	csi2->watermark.stream_data_rate = 0;
+	ipu6_isys_update_watermark_setting(csi2->isys);
+}
+
 static int ipu6_isys_csi2_set_stream(struct v4l2_subdev *sd,
 				     const struct ipu6_isys_csi2_timing *timing,
 				     unsigned int nlanes, int enable)
@@ -415,6 +482,11 @@ static int ipu6_isys_csi2_enable_streams(struct v4l2_subdev *sd,
 	if (!ipu6_isys_csi2_streaming_change(asd, state, pad, true))
 		return 0;
 
+	remote_pad = media_pad_remote_pad_first(&sd->entity.pads[CSI2_PAD_SINK]);
+	remote_sd = media_entity_to_v4l2_subdev(remote_pad->entity);
+
+	ipu6_isys_csi2_setup_watermark(csi2, state, remote_sd);
+
 	ret = ipu6_isys_start_stream_firmware(av);
 	if (ret) {
 		dev_err(sd->dev, "start stream of firmware failed\n");
@@ -429,9 +501,6 @@ static int ipu6_isys_csi2_enable_streams(struct v4l2_subdev *sd,
 	if (ret)
 		goto err_stop_stream_firmware;
 
-	remote_pad = media_pad_remote_pad_first(&sd->entity.pads[CSI2_PAD_SINK]);
-	remote_sd = media_entity_to_v4l2_subdev(remote_pad->entity);
-
 	ret = v4l2_subdev_enable_streams(remote_sd, remote_pad->index,
 					 csi2->stream_ids);
 	if (ret)
@@ -449,6 +518,7 @@ static int ipu6_isys_csi2_enable_streams(struct v4l2_subdev *sd,
 	ipu6_isys_close_streaming_firmware(av);
 
 err_del_av:
+	ipu6_isys_csi2_clear_watermark(csi2);
 	csi2->stream_ids &= ~sink_streams;
 	list_del(&av->csi2_entry);
 
@@ -493,6 +563,8 @@ static int ipu6_isys_csi2_disable_streams(struct v4l2_subdev *sd,
 
 	csi2->streaming = false;
 
+	ipu6_isys_csi2_clear_watermark(csi2);
+
 out_del_csi2_entry:
 	list_del(&av->csi2_entry);
 
diff --git a/drivers/media/pci/intel/ipu6/ipu6-isys-csi2.h b/drivers/media/pci/intel/ipu6/ipu6-isys-csi2.h
index 5ff7af0ab274..fb7cd898008c 100644
--- a/drivers/media/pci/intel/ipu6/ipu6-isys-csi2.h
+++ b/drivers/media/pci/intel/ipu6/ipu6-isys-csi2.h
@@ -44,6 +44,10 @@ struct ipu6_isys_csi2 {
 	u32 receiver_errors;
 	unsigned int nlanes;
 	unsigned int port;
+	struct {
+		u32 stream_data_rate;
+		bool force_iwake_disable;
+	} watermark;
 	bool streaming;
 	u64 stream_ids;
 };
diff --git a/drivers/media/pci/intel/ipu6/ipu6-isys-queue.c b/drivers/media/pci/intel/ipu6/ipu6-isys-queue.c
index b7c7ccae0452..f4c8386ce7d7 100644
--- a/drivers/media/pci/intel/ipu6/ipu6-isys-queue.c
+++ b/drivers/media/pci/intel/ipu6/ipu6-isys-queue.c
@@ -584,8 +584,6 @@ static int start_streaming(struct vb2_queue *q, unsigned int count)
 	}
 
 	list_add(&aq->node, &stream->queues);
-	ipu6_isys_configure_stream_watermark(av, source_pad->entity);
-	ipu6_isys_update_stream_watermark(av, true);
 
 	ret = ipu6_isys_stream_start(av);
 	if (ret)
@@ -596,7 +594,6 @@ static int start_streaming(struct vb2_queue *q, unsigned int count)
 	return 0;
 
 out_stream_start:
-	ipu6_isys_update_stream_watermark(av, false);
 	list_del(&aq->node);
 
 out_fw_close:
@@ -620,8 +617,6 @@ static void stop_streaming(struct vb2_queue *q)
 
 	mutex_lock(&stream->mutex);
 
-	ipu6_isys_update_stream_watermark(av, false);
-
 	mutex_lock(&av->isys->stream_mutex);
 	ipu6_isys_video_set_streaming(av, 0);
 	list_del(&aq->node);
diff --git a/drivers/media/pci/intel/ipu6/ipu6-isys-video.c b/drivers/media/pci/intel/ipu6/ipu6-isys-video.c
index 56ed1a4c45d6..0350d34f3b67 100644
--- a/drivers/media/pci/intel/ipu6/ipu6-isys-video.c
+++ b/drivers/media/pci/intel/ipu6/ipu6-isys-video.c
@@ -738,98 +738,6 @@ int ipu6_isys_video_prepare_stream(struct ipu6_isys_video *av,
 	return 0;
 }
 
-void ipu6_isys_configure_stream_watermark(struct ipu6_isys_video *av,
-					  struct media_entity *source)
-{
-	struct ipu6_isys *isys = av->isys;
-	struct ipu6_isys_csi2 *csi2 = NULL;
-	struct isys_iwake_watermark *iwake_watermark = &isys->iwake_watermark;
-	struct device *dev = &isys->adev->auxdev.dev;
-	struct v4l2_subdev *esd;
-	struct v4l2_control hb = { .id = V4L2_CID_HBLANK, .value = 0 };
-	s64 link_freq;
-	int ret;
-
-	esd = media_entity_to_v4l2_subdev(source);
-
-	av->watermark.width = ipu6_isys_get_frame_width(av);
-	av->watermark.height = ipu6_isys_get_frame_height(av);
-
-	ret = v4l2_g_ctrl(esd->ctrl_handler, &hb);
-	if (!ret && hb.value >= 0)
-		av->watermark.hblank = hb.value;
-	else
-		av->watermark.hblank = 0;
-
-	csi2 = ipu6_isys_subdev_to_csi2(av->stream->asd);
-	link_freq = ipu6_isys_csi2_get_link_freq(csi2);
-	if (link_freq <= 0) {
-		mutex_lock(&iwake_watermark->mutex);
-		iwake_watermark->force_iwake_disable = true;
-		mutex_unlock(&iwake_watermark->mutex);
-		dev_warn(dev, "unexpected link_freq from %s, disable iwake\n",
-			 source->name);
-		return;
-	}
-
-	struct v4l2_subdev_state *state;
-	struct v4l2_mbus_framefmt *format;
-	unsigned int bpp;
-
-	state = v4l2_subdev_lock_and_get_active_state(&csi2->asd.sd);
-	format = v4l2_subdev_state_get_format(state, 0, av->source_stream);
-	bpp = ipu6_isys_mbus_code_to_bpp(format->code);
-	v4l2_subdev_unlock_state(state);
-
-	av->watermark.pixel_rate = mul_u64_u32_div(link_freq, csi2->nlanes * 2,
-						   bpp);
-}
-
-static void calculate_stream_datarate(struct ipu6_isys_video *av)
-{
-	struct video_stream_watermark *watermark = &av->watermark;
-	const struct ipu6_isys_pixelformat *pfmt =
-		ipu6_isys_get_isys_format(ipu6_isys_get_format(av), 0);
-	u32 pages_per_line, pb_bytes_per_line, pixels_per_line, bytes_per_line;
-	u64 line_time_ns, stream_data_rate;
-
-	pixels_per_line = watermark->width + watermark->hblank;
-	line_time_ns =  div_u64(pixels_per_line * NSEC_PER_SEC,
-				watermark->pixel_rate);
-	bytes_per_line = watermark->width * pfmt->bpp / 8;
-	pages_per_line = DIV_ROUND_UP(bytes_per_line,
-				      av->isys->pdata->ipdata->sram_gran_size);
-	pb_bytes_per_line =
-		pages_per_line << av->isys->pdata->ipdata->sram_gran_shift;
-	stream_data_rate = div64_u64(pb_bytes_per_line * 1000, line_time_ns);
-
-	watermark->stream_data_rate = stream_data_rate;
-}
-
-void ipu6_isys_update_stream_watermark(struct ipu6_isys_video *av, bool state)
-{
-	struct isys_iwake_watermark *iwake_watermark =
-		&av->isys->iwake_watermark;
-
-	if (!av->watermark.pixel_rate)
-		return;
-
-	if (state) {
-		calculate_stream_datarate(av);
-		mutex_lock(&iwake_watermark->mutex);
-		list_add(&av->watermark.stream_node,
-			 &iwake_watermark->video_list);
-		mutex_unlock(&iwake_watermark->mutex);
-	} else {
-		av->watermark.stream_data_rate = 0;
-		mutex_lock(&iwake_watermark->mutex);
-		list_del(&av->watermark.stream_node);
-		mutex_unlock(&iwake_watermark->mutex);
-	}
-
-	update_watermark_setting(av->isys);
-}
-
 void ipu6_isys_put_stream(struct ipu6_isys_stream *stream)
 {
 	struct device *dev;
diff --git a/drivers/media/pci/intel/ipu6/ipu6-isys-video.h b/drivers/media/pci/intel/ipu6/ipu6-isys-video.h
index 5dd70175a857..e2a3bc482004 100644
--- a/drivers/media/pci/intel/ipu6/ipu6-isys-video.h
+++ b/drivers/media/pci/intel/ipu6/ipu6-isys-video.h
@@ -63,16 +63,6 @@ struct ipu6_isys_stream {
 	u8 vc;
 };
 
-struct video_stream_watermark {
-	u32 width;
-	u32 height;
-	u32 hblank;
-	u32 frame_rate;
-	u64 pixel_rate;
-	u64 stream_data_rate;
-	struct list_head stream_node;
-};
-
 struct ipu6_isys_video {
 	struct ipu6_isys_queue aq;
 	struct list_head csi2_entry;
@@ -86,7 +76,6 @@ struct ipu6_isys_video {
 	struct ipu6_isys_csi2 *csi2;
 	struct ipu6_isys_stream *stream;
 	unsigned int streaming;
-	struct video_stream_watermark watermark;
 	u32 source_stream;
 	u8 vc;
 	u8 dt;
@@ -119,10 +108,6 @@ ipu6_isys_query_stream_by_handle(struct ipu6_isys *isys, u8 stream_handle);
 struct ipu6_isys_stream *
 ipu6_isys_query_stream_by_source(struct ipu6_isys *isys, int source, u8 vc);
 
-void ipu6_isys_configure_stream_watermark(struct ipu6_isys_video *av,
-					  struct media_entity *source);
-void ipu6_isys_update_stream_watermark(struct ipu6_isys_video *av, bool state);
-
 u32 ipu6_isys_get_format(struct ipu6_isys_video *av);
 u32 ipu6_isys_get_data_size(struct ipu6_isys_video *av);
 u32 ipu6_isys_get_bytes_per_line(struct ipu6_isys_video *av);
diff --git a/drivers/media/pci/intel/ipu6/ipu6-isys.c b/drivers/media/pci/intel/ipu6/ipu6-isys.c
index 1a2d6b107b73..aa892f86d17c 100644
--- a/drivers/media/pci/intel/ipu6/ipu6-isys.c
+++ b/drivers/media/pci/intel/ipu6/ipu6-isys.c
@@ -529,52 +529,47 @@ static void enable_iwake(struct ipu6_isys *isys, bool enable)
 	mutex_unlock(&iwake_watermark->mutex);
 }
 
-void update_watermark_setting(struct ipu6_isys *isys)
+void ipu6_isys_update_watermark_setting(struct ipu6_isys *isys)
 {
-	struct isys_iwake_watermark *iwake_watermark = &isys->iwake_watermark;
 	u32 iwake_threshold, iwake_critical_threshold, page_num;
 	struct device *dev = &isys->adev->auxdev.dev;
 	u32 calc_fill_time_us = 0, ltr = 0, did = 0;
-	struct video_stream_watermark *p_watermark;
 	enum ltr_did_type ltr_did_type;
-	struct list_head *stream_node;
 	u64 isys_pb_datarate_mbs = 0;
 	u32 mem_open_threshold = 0;
 	struct ltr_did ltrdid;
 	u64 threshold_bytes;
 	u32 max_sram_size;
 	u32 shift;
+	bool force_iwake_disable = false;
+
+	lockdep_assert_held(&isys->stream_mutex);
 
 	shift = isys->pdata->ipdata->sram_gran_shift;
 	max_sram_size = isys->pdata->ipdata->max_sram_size;
 
-	mutex_lock(&iwake_watermark->mutex);
-	if (iwake_watermark->force_iwake_disable) {
+	for (unsigned int i = 0; i < isys->pdata->ipdata->csi2.nports; i++) {
+		isys_pb_datarate_mbs +=
+			isys->csi2[i].watermark.stream_data_rate;
+		force_iwake_disable |=
+			isys->csi2[i].watermark.force_iwake_disable;
+	}
+
+	if (force_iwake_disable) {
+		dev_dbg(dev, "watermark: forcing iwake disabled\n");
 		set_iwake_ltrdid(isys, 0, 0, LTR_IWAKE_OFF);
 		set_iwake_register(isys, GDA_IRQ_CRITICAL_THRESHOLD_INDEX,
 				   CRITICAL_THRESHOLD_IWAKE_DISABLE);
-		goto unlock_exit;
-	}
-
-	if (list_empty(&iwake_watermark->video_list)) {
-		isys_pb_datarate_mbs = 0;
-	} else {
-		list_for_each(stream_node, &iwake_watermark->video_list) {
-			p_watermark = list_entry(stream_node,
-						 struct video_stream_watermark,
-						 stream_node);
-			isys_pb_datarate_mbs += p_watermark->stream_data_rate;
-		}
+		return;
 	}
-	mutex_unlock(&iwake_watermark->mutex);
 
 	if (!isys_pb_datarate_mbs) {
+		dev_dbg(dev, "watermark: disabled iwake\n");
 		enable_iwake(isys, false);
 		set_iwake_ltrdid(isys, 0, 0, LTR_IWAKE_OFF);
-		mutex_lock(&iwake_watermark->mutex);
 		set_iwake_register(isys, GDA_IRQ_CRITICAL_THRESHOLD_INDEX,
 				   CRITICAL_THRESHOLD_IWAKE_DISABLE);
-		goto unlock_exit;
+		return;
 	}
 
 	enable_iwake(isys, true);
@@ -609,7 +604,6 @@ void update_watermark_setting(struct ipu6_isys *isys)
 	iwake_threshold = max_t(u32, 1, threshold_bytes >> shift);
 	iwake_threshold = min_t(u32, iwake_threshold, max_sram_size);
 
-	mutex_lock(&iwake_watermark->mutex);
 	if (isys->pdata->ipdata->enhanced_iwake) {
 		set_iwake_register(isys, GDA_IWAKE_THRESHOLD_INDEX,
 				   DEFAULT_IWAKE_THRESHOLD);
@@ -631,7 +625,7 @@ void update_watermark_setting(struct ipu6_isys *isys)
 	iwake_critical_threshold = iwake_threshold +
 		(IS_PIXEL_BUFFER_PAGES - iwake_threshold) / 2;
 
-	dev_dbg(dev, "threshold: %u critical: %u\n", iwake_threshold,
+	dev_dbg(dev, "watermark: threshold: %u critical: %u\n", iwake_threshold,
 		iwake_critical_threshold);
 
 	set_iwake_register(isys, GDA_IRQ_CRITICAL_THRESHOLD_INDEX,
@@ -641,8 +635,6 @@ void update_watermark_setting(struct ipu6_isys *isys)
 	       isys->adev->isp->base + REG_PKGC_PMON_CFG);
 	writel(VAL_PKGC_PMON_CFG_START,
 	       isys->adev->isp->base + REG_PKGC_PMON_CFG);
-unlock_exit:
-	mutex_unlock(&iwake_watermark->mutex);
 }
 
 static void isys_iwake_watermark_init(struct ipu6_isys *isys)
diff --git a/drivers/media/pci/intel/ipu6/ipu6-isys.h b/drivers/media/pci/intel/ipu6/ipu6-isys.h
index 7fb8cb820912..c171e4e053c3 100644
--- a/drivers/media/pci/intel/ipu6/ipu6-isys.h
+++ b/drivers/media/pci/intel/ipu6/ipu6-isys.h
@@ -181,7 +181,7 @@ void ipu6_cleanup_fw_msg_bufs(struct ipu6_isys *isys);
 
 extern const struct v4l2_ioctl_ops ipu6_isys_ioctl_ops;
 
-void update_watermark_setting(struct ipu6_isys *isys);
+void ipu6_isys_update_watermark_setting(struct ipu6_isys *isys);
 
 int ipu6_isys_mcd_phy_set_power(struct ipu6_isys *isys,
 				struct ipu6_isys_csi2_config *cfg,
-- 
2.47.3


^ permalink raw reply related	[flat|nested] 88+ messages in thread

* [PATCH v12 80/86] media: ipu6: Rework watermark setting
  2026-04-09 20:13 [PATCH v12 00/86] Generic line based metadata support, internal pads Sakari Ailus
                   ` (78 preceding siblings ...)
  2026-04-09 20:14 ` [PATCH v12 79/86] media: ipu6: Rework watermark calculation Sakari Ailus
@ 2026-04-09 20:14 ` Sakari Ailus
  2026-04-09 20:14 ` [PATCH v12 81/86] media: ipu6: Bridge the gap between streams in V4L2 and IPU6 firmware Sakari Ailus
                   ` (5 subsequent siblings)
  85 siblings, 0 replies; 88+ messages in thread
From: Sakari Ailus @ 2026-04-09 20:14 UTC (permalink / raw)
  To: linux-media
  Cc: hans, laurent.pinchart, Prabhakar, Kate Hsuan, Dave Stevenson,
	Tommaso Merciai, Benjamin Mugnier, Sylvain Petinot,
	Christophe JAILLET, Julien Massot, Naushir Patuck, Stefan Klug,
	Mirela Rabulea, André Apitzsch, Heimir Thor Sverrisson,
	Kieran Bingham, Mehdi Djait, Ricardo Ribalda Delgado,
	Hans de Goede, Jacopo Mondi, Tomi Valkeinen, David Plowman,
	Yu, Ong Hock, Ng, Khai Wen, Jai Luthra, Rishikesh Donadkar

Remove structs to maintain watermark related configuration, by using the
values where they're obtained, apart from keeping watermark enabled status
in struct ipu6_isys.

Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
---
 drivers/media/pci/intel/ipu6/ipu6-isys.c | 76 ++++++++----------------
 drivers/media/pci/intel/ipu6/ipu6-isys.h | 34 +----------
 2 files changed, 26 insertions(+), 84 deletions(-)

diff --git a/drivers/media/pci/intel/ipu6/ipu6-isys.c b/drivers/media/pci/intel/ipu6/ipu6-isys.c
index aa892f86d17c..04058252ac01 100644
--- a/drivers/media/pci/intel/ipu6/ipu6-isys.c
+++ b/drivers/media/pci/intel/ipu6/ipu6-isys.c
@@ -98,6 +98,27 @@ enum ltr_did_type {
 	LTR_TYPE_MAX
 };
 
+struct ltr_did {
+	union {
+		u32 value;
+		struct {
+			u8 val0;
+			u8 val1;
+			u8 val2;
+			u8 val3;
+		} bits;
+	} lut_ltr;
+	union {
+		u32 value;
+		struct {
+			u8 th0;
+			u8 th1;
+			u8 th2;
+			u8 th3;
+		} bits;
+	} lut_fill_time;
+};
+
 #define ISYS_PM_QOS_VALUE	300
 
 static int isys_isr_one(struct ipu6_bus_device *adev);
@@ -403,20 +424,6 @@ static irqreturn_t isys_isr(struct ipu6_bus_device *adev)
 	return IRQ_HANDLED;
 }
 
-static void get_lut_ltrdid(struct ipu6_isys *isys, struct ltr_did *pltr_did)
-{
-	struct isys_iwake_watermark *iwake_watermark = &isys->iwake_watermark;
-	struct ltr_did ltrdid_default;
-
-	ltrdid_default.lut_ltr.value = LTR_DEFAULT_VALUE;
-	ltrdid_default.lut_fill_time.value = FILL_TIME_DEFAULT_VALUE;
-
-	if (iwake_watermark->ltrdid.lut_ltr.value)
-		*pltr_did = iwake_watermark->ltrdid;
-	else
-		*pltr_did = ltrdid_default;
-}
-
 static int set_iwake_register(struct ipu6_isys *isys, u32 index, u32 value)
 {
 	struct device *dev = &isys->adev->auxdev.dev;
@@ -512,21 +519,14 @@ static void set_iwake_ltrdid(struct ipu6_isys *isys, u16 ltr, u16 did,
  */
 static void enable_iwake(struct ipu6_isys *isys, bool enable)
 {
-	struct isys_iwake_watermark *iwake_watermark = &isys->iwake_watermark;
 	int ret;
 
-	mutex_lock(&iwake_watermark->mutex);
-
-	if (iwake_watermark->iwake_enabled == enable) {
-		mutex_unlock(&iwake_watermark->mutex);
+	if (isys->iwake_watermark_enabled == enable)
 		return;
-	}
 
 	ret = set_iwake_register(isys, GDA_ENABLE_IWAKE_INDEX, enable);
 	if (!ret)
-		iwake_watermark->iwake_enabled = enable;
-
-	mutex_unlock(&iwake_watermark->mutex);
+		isys->iwake_watermark_enabled = enable;
 }
 
 void ipu6_isys_update_watermark_setting(struct ipu6_isys *isys)
@@ -580,7 +580,8 @@ void ipu6_isys_update_watermark_setting(struct ipu6_isys *isys)
 		did = calc_fill_time_us * DEFAULT_DID_RATIO / 100;
 		ltr_did_type = LTR_ENHANNCE_IWAKE;
 	} else {
-		get_lut_ltrdid(isys, &ltrdid);
+		ltrdid.lut_ltr.value = LTR_DEFAULT_VALUE;
+		ltrdid.lut_fill_time.value = FILL_TIME_DEFAULT_VALUE;
 
 		if (calc_fill_time_us <= ltrdid.lut_fill_time.bits.th0)
 			ltr = 0;
@@ -637,30 +638,6 @@ void ipu6_isys_update_watermark_setting(struct ipu6_isys *isys)
 	       isys->adev->isp->base + REG_PKGC_PMON_CFG);
 }
 
-static void isys_iwake_watermark_init(struct ipu6_isys *isys)
-{
-	struct isys_iwake_watermark *iwake_watermark = &isys->iwake_watermark;
-
-	INIT_LIST_HEAD(&iwake_watermark->video_list);
-	mutex_init(&iwake_watermark->mutex);
-
-	iwake_watermark->ltrdid.lut_ltr.value = 0;
-	iwake_watermark->isys = isys;
-	iwake_watermark->iwake_enabled = false;
-	iwake_watermark->force_iwake_disable = false;
-}
-
-static void isys_iwake_watermark_cleanup(struct ipu6_isys *isys)
-{
-	struct isys_iwake_watermark *iwake_watermark = &isys->iwake_watermark;
-
-	mutex_lock(&iwake_watermark->mutex);
-	list_del(&iwake_watermark->video_list);
-	mutex_unlock(&iwake_watermark->mutex);
-
-	mutex_destroy(&iwake_watermark->mutex);
-}
-
 /* The .bound() notifier callback when a match is found */
 static int isys_notifier_bound(struct v4l2_async_notifier *notifier,
 			       struct v4l2_subdev *sd,
@@ -1094,8 +1071,6 @@ static int isys_probe(struct auxiliary_device *auxdev,
 	if (ret < 0)
 		goto out_remove_pkg_dir_shared_buffer;
 
-	isys_iwake_watermark_init(isys);
-
 	if (is_ipu6se(adev->isp->hw_ver))
 		isys->phy_set_power = ipu6_isys_jsl_phy_set_power;
 	else if (is_ipu6ep_mtl(adev->isp->hw_ver))
@@ -1154,7 +1129,6 @@ static void isys_remove(struct auxiliary_device *auxdev)
 	for (i = 0; i < IPU6_ISYS_MAX_STREAMS; i++)
 		mutex_destroy(&isys->streams[i].mutex);
 
-	isys_iwake_watermark_cleanup(isys);
 	mutex_destroy(&isys->stream_mutex);
 	mutex_destroy(&isys->mutex);
 }
diff --git a/drivers/media/pci/intel/ipu6/ipu6-isys.h b/drivers/media/pci/intel/ipu6/ipu6-isys.h
index c171e4e053c3..0689b4485c7f 100644
--- a/drivers/media/pci/intel/ipu6/ipu6-isys.h
+++ b/drivers/media/pci/intel/ipu6/ipu6-isys.h
@@ -60,38 +60,6 @@ struct ipu6_bus_device;
 #define IPU6EP_MTL_LTR_VALUE			1023
 #define IPU6EP_MTL_MIN_MEMOPEN_TH		0xc
 
-struct ltr_did {
-	union {
-		u32 value;
-		struct {
-			u8 val0;
-			u8 val1;
-			u8 val2;
-			u8 val3;
-		} bits;
-	} lut_ltr;
-	union {
-		u32 value;
-		struct {
-			u8 th0;
-			u8 th1;
-			u8 th2;
-			u8 th3;
-		} bits;
-	} lut_fill_time;
-};
-
-struct isys_iwake_watermark {
-	bool iwake_enabled;
-	bool force_iwake_disable;
-	u32 iwake_threshold;
-	u64 isys_pixelbuffer_datarate;
-	struct ltr_did ltrdid;
-	struct mutex mutex; /* protect whole struct */
-	struct ipu6_isys *isys;
-	struct list_head video_list;
-};
-
 struct ipu6_isys_csi2_config {
 	u32 nlanes;
 	u32 port;
@@ -141,6 +109,7 @@ struct ipu6_isys {
 	bool need_reset;
 	bool icache_prefetch;
 	bool csi2_cse_ipc_not_supported;
+	bool iwake_watermark_enabled;
 	unsigned int ref_count;
 	unsigned int stream_opened;
 	unsigned int sensor_type;
@@ -162,7 +131,6 @@ struct ipu6_isys {
 	struct list_head framebuflist;
 	struct list_head framebuflist_fw;
 	struct v4l2_async_notifier notifier;
-	struct isys_iwake_watermark iwake_watermark;
 };
 
 struct isys_fw_msgs {
-- 
2.47.3


^ permalink raw reply related	[flat|nested] 88+ messages in thread

* [PATCH v12 81/86] media: ipu6: Bridge the gap between streams in V4L2 and IPU6 firmware
  2026-04-09 20:13 [PATCH v12 00/86] Generic line based metadata support, internal pads Sakari Ailus
                   ` (79 preceding siblings ...)
  2026-04-09 20:14 ` [PATCH v12 80/86] media: ipu6: Rework watermark setting Sakari Ailus
@ 2026-04-09 20:14 ` Sakari Ailus
  2026-04-09 20:14 ` [PATCH v12 82/86] media: ipu6: Drop {get,put}_streams_opened() Sakari Ailus
                   ` (4 subsequent siblings)
  85 siblings, 0 replies; 88+ messages in thread
From: Sakari Ailus @ 2026-04-09 20:14 UTC (permalink / raw)
  To: linux-media
  Cc: hans, laurent.pinchart, Prabhakar, Kate Hsuan, Dave Stevenson,
	Tommaso Merciai, Benjamin Mugnier, Sylvain Petinot,
	Christophe JAILLET, Julien Massot, Naushir Patuck, Stefan Klug,
	Mirela Rabulea, André Apitzsch, Heimir Thor Sverrisson,
	Kieran Bingham, Mehdi Djait, Ricardo Ribalda Delgado,
	Hans de Goede, Jacopo Mondi, Tomi Valkeinen, David Plowman,
	Yu, Ong Hock, Ng, Khai Wen, Jai Luthra, Rishikesh Donadkar

The stream concept of the IPU6 firmware is aligned with that of the CSI-2,
effectively meaning that a stream equals to a CSI-2 virtual channel. Right
now this means that all streams on a CSI-2 interface are started and
stopped simultaneously, once all related video nodes are set streaming.

Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
---
 drivers/media/pci/intel/ipu6/ipu6-isys-csi2.c |  91 ++--
 drivers/media/pci/intel/ipu6/ipu6-isys-csi2.h |   2 +
 .../media/pci/intel/ipu6/ipu6-isys-queue.c    |  47 +-
 .../media/pci/intel/ipu6/ipu6-isys-video.c    | 403 ++++++++----------
 .../media/pci/intel/ipu6/ipu6-isys-video.h    |  18 +-
 drivers/media/pci/intel/ipu6/ipu6-isys.c      |  47 +-
 drivers/media/pci/intel/ipu6/ipu6-isys.h      |   6 +-
 7 files changed, 249 insertions(+), 365 deletions(-)

diff --git a/drivers/media/pci/intel/ipu6/ipu6-isys-csi2.c b/drivers/media/pci/intel/ipu6/ipu6-isys-csi2.c
index 15e965396f4a..b1cf2c622b01 100644
--- a/drivers/media/pci/intel/ipu6/ipu6-isys-csi2.c
+++ b/drivers/media/pci/intel/ipu6/ipu6-isys-csi2.c
@@ -443,8 +443,8 @@ static bool ipu6_isys_csi2_streaming_change(struct ipu6_isys_subdev *asd,
 
 	if (streams_enabled == nodes_streaming) {
 		dev_dbg(asd->sd.dev,
-			"changing streaming state to %s on \"%s\":%u\n",
-			str_enabled_disabled(enable), asd->sd.entity.name, pad);
+			"changing streaming state to %s on \"%s\"\n",
+			str_enabled_disabled(enable), asd->sd.entity.name);
 		return true;
 	}
 
@@ -467,6 +467,9 @@ static int ipu6_isys_csi2_enable_streams(struct v4l2_subdev *sd,
 		*vdev_pad = media_pad_remote_pad_unique(&sd->entity.pads[pad]);
 	struct ipu6_isys_video *av =
 		container_of_const(vdev_pad, struct ipu6_isys_video, pad);
+	struct v4l2_mbus_frame_desc desc = {
+		.type = V4L2_MBUS_FRAME_DESC_TYPE_CSI2,
+	};
 	u64 sink_streams;
 	int ret;
 
@@ -478,6 +481,7 @@ static int ipu6_isys_csi2_enable_streams(struct v4l2_subdev *sd,
 		v4l2_subdev_state_xlate_streams(state, pad, CSI2_PAD_SINK,
 						&streams_mask);
 	csi2->stream_ids |= sink_streams;
+	av->sink_stream = __ffs(sink_streams);
 
 	if (!ipu6_isys_csi2_streaming_change(asd, state, pad, true))
 		return 0;
@@ -487,7 +491,11 @@ static int ipu6_isys_csi2_enable_streams(struct v4l2_subdev *sd,
 
 	ipu6_isys_csi2_setup_watermark(csi2, state, remote_sd);
 
-	ret = ipu6_isys_start_stream_firmware(av);
+	ret = v4l2_subdev_get_frame_desc(remote_sd, remote_pad->index, &desc);
+	if (ret)
+		goto err_del_av;
+
+	ret = ipu6_isys_alloc_start_streams_firmware(csi2, state, &desc);
 	if (ret) {
 		dev_err(sd->dev, "start stream of firmware failed\n");
 		goto err_del_av;
@@ -514,11 +522,13 @@ static int ipu6_isys_csi2_enable_streams(struct v4l2_subdev *sd,
 	ipu6_isys_csi2_set_stream(sd, NULL, 0, false);
 
 err_stop_stream_firmware:
-	ipu6_isys_stop_streaming_firmware(av);
-	ipu6_isys_close_streaming_firmware(av);
+	ipu6_isys_stop_streams_firmware(csi2);
+	ipu6_isys_close_streams_firmware(csi2);
+	ipu6_isys_free_streams_firmware(csi2);
 
 err_del_av:
 	ipu6_isys_csi2_clear_watermark(csi2);
+	ipu6_isys_csi2_streaming_change(asd, state, pad, false);
 	csi2->stream_ids &= ~sink_streams;
 	list_del(&av->csi2_entry);
 
@@ -540,28 +550,29 @@ static int ipu6_isys_csi2_disable_streams(struct v4l2_subdev *sd,
 
 	lockdep_assert_held(&csi2->isys->stream_mutex);
 
-	if (!ipu6_isys_csi2_streaming_change(asd, state, pad, false))
-		goto out_del_csi2_entry;
-
 	sink_streams =
 		v4l2_subdev_state_xlate_streams(state, pad, CSI2_PAD_SINK,
 						&streams_mask);
 
+	csi2->stream_ids &= ~sink_streams;
+
+	if (!ipu6_isys_csi2_streaming_change(asd, state, pad, false))
+		goto out_del_csi2_entry;
+
 	csi2->streaming = false;
 
 	remote_pad = media_pad_remote_pad_first(&sd->entity.pads[CSI2_PAD_SINK]);
 	remote_sd = media_entity_to_v4l2_subdev(remote_pad->entity);
 
-	ipu6_isys_stop_streaming_firmware(av);
+	ipu6_isys_stop_streams_firmware(csi2);
 
 	ipu6_isys_csi2_set_stream(sd, NULL, 0, false);
 
 	v4l2_subdev_disable_streams(remote_sd, remote_pad->index,
-				    csi2->stream_ids);
+				    csi2->stream_ids | sink_streams);
 
-	ipu6_isys_close_streaming_firmware(av);
-
-	csi2->streaming = false;
+	ipu6_isys_close_streams_firmware(csi2);
+	ipu6_isys_free_streams_firmware(csi2);
 
 	ipu6_isys_csi2_clear_watermark(csi2);
 
@@ -714,6 +725,7 @@ int ipu6_isys_csi2_init(struct ipu6_isys_csi2 *csi2,
 		goto fail;
 
 	INIT_LIST_HEAD(&csi2->av_head);
+	INIT_LIST_HEAD(&csi2->streams);
 	csi2->asd.source = IPU6_FW_ISYS_STREAM_SRC_CSI2_PORT0 + index;
 	csi2->asd.supported_codes = csi2_supported_codes;
 	snprintf(csi2->asd.sd.name, sizeof(csi2->asd.sd.name),
@@ -764,56 +776,3 @@ void ipu6_isys_csi2_eof_event_by_stream(struct ipu6_isys_stream *stream)
 	dev_dbg(dev, "eof_event::csi2-%i sequence: %i\n",
 		csi2->port, frame_sequence);
 }
-
-int ipu6_isys_csi2_get_remote_desc(u32 source_stream,
-				   struct ipu6_isys_csi2 *csi2,
-				   struct media_entity *source_entity,
-				   struct v4l2_mbus_frame_desc_entry *entry)
-{
-	struct v4l2_mbus_frame_desc_entry *desc_entry = NULL;
-	struct device *dev = &csi2->isys->adev->auxdev.dev;
-	struct v4l2_mbus_frame_desc desc;
-	struct v4l2_subdev *source;
-	struct media_pad *pad;
-	unsigned int i;
-	int ret;
-
-	source = media_entity_to_v4l2_subdev(source_entity);
-	if (!source)
-		return -EPIPE;
-
-	pad = media_pad_remote_pad_first(&csi2->asd.pad[CSI2_PAD_SINK]);
-	if (!pad)
-		return -EPIPE;
-
-	ret = v4l2_subdev_call(source, pad, get_frame_desc, pad->index, &desc);
-	if (ret)
-		return ret;
-
-	if (desc.type != V4L2_MBUS_FRAME_DESC_TYPE_CSI2) {
-		dev_err(dev, "Unsupported frame descriptor type\n");
-		return -EINVAL;
-	}
-
-	for (i = 0; i < desc.num_entries; i++) {
-		if (source_stream == desc.entry[i].stream) {
-			desc_entry = &desc.entry[i];
-			break;
-		}
-	}
-
-	if (!desc_entry) {
-		dev_err(dev, "Failed to find stream %u from remote subdev\n",
-			source_stream);
-		return -EINVAL;
-	}
-
-	if (desc_entry->bus.csi2.vc >= NR_OF_CSI2_VC) {
-		dev_err(dev, "invalid vc %d\n", desc_entry->bus.csi2.vc);
-		return -EINVAL;
-	}
-
-	*entry = *desc_entry;
-
-	return 0;
-}
diff --git a/drivers/media/pci/intel/ipu6/ipu6-isys-csi2.h b/drivers/media/pci/intel/ipu6/ipu6-isys-csi2.h
index fb7cd898008c..6caee336da89 100644
--- a/drivers/media/pci/intel/ipu6/ipu6-isys-csi2.h
+++ b/drivers/media/pci/intel/ipu6/ipu6-isys-csi2.h
@@ -39,6 +39,8 @@ struct ipu6_isys_csi2 {
 	struct ipu6_isys *isys;
 	struct ipu6_isys_video av[NR_OF_CSI2_SRC_PADS];
 	struct list_head av_head;
+	struct list_head streams;
+	struct ipu6_isys_stream *streams_by_vc[NR_OF_CSI2_VC];
 
 	void __iomem *base;
 	u32 receiver_errors;
diff --git a/drivers/media/pci/intel/ipu6/ipu6-isys-queue.c b/drivers/media/pci/intel/ipu6/ipu6-isys-queue.c
index f4c8386ce7d7..31df83b9f45f 100644
--- a/drivers/media/pci/intel/ipu6/ipu6-isys-queue.c
+++ b/drivers/media/pci/intel/ipu6/ipu6-isys-queue.c
@@ -286,19 +286,24 @@ ipu6_isys_buf_to_fw_frame_buf(struct ipu6_fw_isys_frame_buff_set_abi *set,
 /* Start streaming for real. The buffer list must be available. */
 static int ipu6_isys_stream_start(struct ipu6_isys_video *av)
 {
-	struct ipu6_isys_stream *stream = av->stream;
-	struct device *dev = &stream->isys->adev->auxdev.dev;
+	struct device *dev = &av->isys->adev->auxdev.dev;
 	struct ipu6_isys_buffer_list bl;
 	int ret;
 
-	guard(mutex)(&stream->isys->stream_mutex);
+	guard(mutex)(&av->isys->stream_mutex);
 	ret = ipu6_isys_video_set_streaming(av, 1);
 	if (ret)
 		return ret;
 
+	if (!av->stream)
+		return 0;
 	if (!av->csi2->streaming)
 		return 0;
 
+	struct ipu6_isys_stream *stream = av->stream;
+
+	guard(mutex)(&stream->mutex);
+
 	do {
 		struct ipu6_fw_isys_frame_buff_set_abi *buf = NULL;
 		struct isys_fw_msgs *msg;
@@ -522,7 +527,6 @@ static void return_buffers(struct ipu6_isys_queue *aq,
 static void ipu6_isys_stream_cleanup(struct ipu6_isys_video *av)
 {
 	video_device_pipeline_stop(&av->vdev);
-	ipu6_isys_put_stream(av->stream);
 	av->stream = NULL;
 }
 
@@ -533,9 +537,7 @@ static int start_streaming(struct vb2_queue *q, unsigned int count)
 	struct device *dev = &av->isys->adev->auxdev.dev;
 	const struct ipu6_isys_pixelformat *pfmt =
 		ipu6_isys_get_isys_format(ipu6_isys_get_format(av), 0);
-	struct ipu6_isys_stream *stream;
 	struct media_pad *source_pad, *remote_pad;
-	bool first;
 	int ret;
 
 	dev_dbg(dev, "stream: %s: width %u, height %u, css pixelformat %u\n",
@@ -556,12 +558,11 @@ static int start_streaming(struct vb2_queue *q, unsigned int count)
 		goto out_return_buffers;
 	}
 
-	ret = ipu6_isys_setup_video(av, remote_pad, source_pad);
-	if (ret < 0) {
-		dev_dbg(dev, "failed to setup video\n");
+	bool has_pipeline = (bool)video_device_pipeline(&av->vdev);
+
+	ret = video_device_pipeline_alloc_start(&av->vdev);
+	if (ret < 0)
 		goto out_return_buffers;
-	}
-	first = ret;
 
 	ret = ipu6_isys_link_fmt_validate(aq);
 	if (ret) {
@@ -575,29 +576,13 @@ static int start_streaming(struct vb2_queue *q, unsigned int count)
 	if (ret)
 		goto out_pipeline_stop;
 
-	stream = av->stream;
-	mutex_lock(&stream->mutex);
-	if (first) {
-		ret = ipu6_isys_video_prepare_stream(av, source_pad->entity);
-		if (ret)
-			goto out_fw_close;
-	}
-
-	list_add(&aq->node, &stream->queues);
-
 	ret = ipu6_isys_stream_start(av);
 	if (ret)
-		goto out_stream_start;
-
-	mutex_unlock(&stream->mutex);
+		goto out_fw_close;
 
 	return 0;
 
-out_stream_start:
-	list_del(&aq->node);
-
 out_fw_close:
-	mutex_unlock(&stream->mutex);
 	ipu6_isys_fw_close(av->isys);
 
 out_pipeline_stop:
@@ -613,17 +598,11 @@ static void stop_streaming(struct vb2_queue *q)
 {
 	struct ipu6_isys_queue *aq = vb2_queue_to_isys_queue(q);
 	struct ipu6_isys_video *av = ipu6_isys_queue_to_video(aq);
-	struct ipu6_isys_stream *stream = av->stream;
-
-	mutex_lock(&stream->mutex);
 
 	mutex_lock(&av->isys->stream_mutex);
 	ipu6_isys_video_set_streaming(av, 0);
-	list_del(&aq->node);
 	mutex_unlock(&av->isys->stream_mutex);
 
-	mutex_unlock(&stream->mutex);
-
 	ipu6_isys_stream_cleanup(av);
 
 	return_buffers(aq, VB2_BUF_STATE_ERROR);
diff --git a/drivers/media/pci/intel/ipu6/ipu6-isys-video.c b/drivers/media/pci/intel/ipu6/ipu6-isys-video.c
index 0350d34f3b67..2344e4a880d6 100644
--- a/drivers/media/pci/intel/ipu6/ipu6-isys-video.c
+++ b/drivers/media/pci/intel/ipu6/ipu6-isys-video.c
@@ -440,37 +440,38 @@ static int link_validate(struct media_link *link)
 	return ret;
 }
 
-static void get_stream_opened(struct ipu6_isys_video *av)
+static void get_stream_opened(struct ipu6_isys *isys)
 {
 	unsigned long flags;
 
-	spin_lock_irqsave(&av->isys->streams_lock, flags);
-	av->isys->stream_opened++;
-	spin_unlock_irqrestore(&av->isys->streams_lock, flags);
+	spin_lock_irqsave(&isys->streams_lock, flags);
+	isys->stream_opened++;
+	spin_unlock_irqrestore(&isys->streams_lock, flags);
 }
 
-static void put_stream_opened(struct ipu6_isys_video *av)
+static void put_stream_opened(struct ipu6_isys *isys)
 {
 	unsigned long flags;
 
-	spin_lock_irqsave(&av->isys->streams_lock, flags);
-	av->isys->stream_opened--;
-	spin_unlock_irqrestore(&av->isys->streams_lock, flags);
+	spin_lock_irqsave(&isys->streams_lock, flags);
+	isys->stream_opened--;
+	spin_unlock_irqrestore(&isys->streams_lock, flags);
 }
 
 static int ipu6_isys_fw_pin_cfg(struct ipu6_isys_video *av,
-				struct ipu6_fw_isys_stream_cfg_data_abi *cfg)
+				struct ipu6_fw_isys_stream_cfg_data_abi *cfg,
+				struct ipu6_isys_stream *stream,
+				struct media_pad *src_pad,
+				struct v4l2_mbus_frame_desc_entry *entry)
 {
-	struct media_pad *src_pad = media_pad_remote_pad_first(&av->pad);
 	struct v4l2_subdev *sd = media_entity_to_v4l2_subdev(src_pad->entity);
 	struct v4l2_subdev_state *state = v4l2_subdev_get_locked_active_state(sd);
 	struct ipu6_fw_isys_input_pin_info_abi *input_pin;
 	struct ipu6_fw_isys_output_pin_info_abi *output_pin;
-	struct ipu6_isys_stream *stream = av->stream;
 	struct ipu6_isys_queue *aq = &av->aq;
-	struct v4l2_mbus_framefmt fmt;
 	const struct ipu6_isys_pixelformat *pfmt =
 		ipu6_isys_get_isys_format(ipu6_isys_get_format(av), 0);
+	struct v4l2_mbus_framefmt *fmt;
 	struct v4l2_rect v4l2_crop;
 	struct ipu6_isys *isys = av->isys;
 	int input_pins = cfg->nof_input_pins++;
@@ -478,13 +479,13 @@ static int ipu6_isys_fw_pin_cfg(struct ipu6_isys_video *av,
 	u32 src_stream;
 
 	src_stream = __ipu6_isys_get_src_stream_by_src_pad(state, src_pad->index);
-	fmt = *v4l2_subdev_state_get_format(state, src_pad->index, src_stream);
+	fmt = v4l2_subdev_state_get_format(state, src_pad->index, src_stream);
 	v4l2_crop = *v4l2_subdev_state_get_crop(state, src_pad->index, src_stream);
 
 	input_pin = &cfg->input_pins[input_pins];
-	input_pin->input_res.width = fmt.width;
-	input_pin->input_res.height = fmt.height;
-	input_pin->dt = av->dt;
+	input_pin->input_res.width = fmt->width;
+	input_pin->input_res.height = fmt->height;
+	input_pin->dt = entry->bus.csi2.dt;
 	input_pin->bits_per_pix = pfmt->bpp_packed;
 	input_pin->mapped_dt = 0x40; /* invalid mipi data type */
 	input_pin->mipi_decompression = 0;
@@ -525,13 +526,15 @@ static int ipu6_isys_fw_pin_cfg(struct ipu6_isys_video *av,
 	return 0;
 }
 
-int ipu6_isys_start_stream_firmware(struct ipu6_isys_video *av)
+static int ipu6_isys_start_stream_firmware(struct ipu6_isys_stream *stream,
+					   struct v4l2_mbus_frame_desc *desc)
 {
 	struct ipu6_fw_isys_stream_cfg_data_abi *stream_cfg;
 	struct ipu6_fw_isys_frame_buff_set_abi *buf = NULL;
 	struct ipu6_isys_buffer_list bl;
-	struct ipu6_isys_stream *stream = av->stream;
-	struct device *dev = &av->isys->adev->auxdev.dev;
+	struct device *dev = &stream->asd->isys->adev->auxdev.dev;
+	struct v4l2_subdev_state *csi2_state =
+		v4l2_subdev_get_locked_active_state(&stream->asd->sd);
 	struct isys_fw_msgs *msg = NULL;
 	struct ipu6_isys_queue *aq;
 	int ret, retout, tout;
@@ -548,17 +551,42 @@ int ipu6_isys_start_stream_firmware(struct ipu6_isys_video *av)
 		return -ENOMEM;
 
 	stream_cfg = &msg->fw_msg.stream;
-	stream_cfg->src = stream->stream_source;
+	stream_cfg->src = stream->asd->source;
 	stream_cfg->vc = stream->vc;
 	stream_cfg->isl_use = 0;
 	stream_cfg->sensor_type = IPU6_FW_ISYS_SENSOR_MODE_NORMAL;
 
 	list_for_each_entry(aq, &stream->queues, node) {
 		struct ipu6_isys_video *__av = ipu6_isys_queue_to_video(aq);
+		struct media_pad *remote_pad =
+			media_pad_remote_pad_first(&__av->pad);
+		u64 source_streams = 1;
+		unsigned int sink_stream =
+			__ffs(v4l2_subdev_state_xlate_streams(csi2_state,
+							      remote_pad->index,
+							      CSI2_PAD_SINK,
+							      &source_streams));
+		struct v4l2_mbus_frame_desc_entry *entry;
+		unsigned int i;
+
+		for (i = 0; i < V4L2_FRAME_DESC_ENTRY_MAX; i++) {
+			entry = &desc->entry[i];
+
+			if (entry->stream == sink_stream)
+				break;
+		}
+
+		if (i == V4L2_FRAME_DESC_ENTRY_MAX) {
+			dev_err(dev, "cannot find frame desc entry for sink stream %u\n",
+				sink_stream);
+			return -EINVAL;
+		}
 
-		ret = ipu6_isys_fw_pin_cfg(__av, stream_cfg);
+		ret = ipu6_isys_fw_pin_cfg(__av, stream_cfg, stream, remote_pad,
+					   entry);
 		if (ret < 0) {
-			ipu6_put_fw_msg_buf(av->isys, (uintptr_t)stream_cfg);
+			ipu6_put_fw_msg_buf(stream->isys,
+					    (uintptr_t)stream_cfg);
 			return ret;
 		}
 	}
@@ -569,22 +597,22 @@ int ipu6_isys_start_stream_firmware(struct ipu6_isys_video *av)
 
 	reinit_completion(&stream->stream_open_completion);
 
-	ret = ipu6_fw_isys_complex_cmd(av->isys, stream->stream_handle,
+	ret = ipu6_fw_isys_complex_cmd(stream->isys, stream->stream_handle,
 				       stream_cfg, msg->dma_addr,
 				       sizeof(*stream_cfg),
 				       IPU6_FW_ISYS_SEND_TYPE_STREAM_OPEN);
 	if (ret < 0) {
 		dev_err(dev, "can't open stream (%d)\n", ret);
-		ipu6_put_fw_msg_buf(av->isys, (uintptr_t)stream_cfg);
+		ipu6_put_fw_msg_buf(stream->isys, (uintptr_t)stream_cfg);
 		return ret;
 	}
 
-	get_stream_opened(av);
+	get_stream_opened(stream->isys);
 
 	tout = wait_for_completion_timeout(&stream->stream_open_completion,
 					   IPU6_FW_CALL_TIMEOUT_JIFFIES);
 
-	ipu6_put_fw_msg_buf(av->isys, (uintptr_t)stream_cfg);
+	ipu6_put_fw_msg_buf(stream->isys, (uintptr_t)stream_cfg);
 
 	if (!tout) {
 		dev_err(dev, "stream open time out\n");
@@ -611,7 +639,7 @@ int ipu6_isys_start_stream_firmware(struct ipu6_isys_video *av)
 
 	send_type = IPU6_FW_ISYS_SEND_TYPE_STREAM_START_AND_CAPTURE;
 	ipu6_fw_isys_dump_frame_buff_set(dev, buf, stream_cfg->nof_output_pins);
-	ret = ipu6_fw_isys_complex_cmd(av->isys, stream->stream_handle, buf,
+	ret = ipu6_fw_isys_complex_cmd(stream->isys, stream->stream_handle, buf,
 				       msg->dma_addr, sizeof(*buf), send_type);
 	if (ret < 0) {
 		dev_err(dev, "can't start streaming (%d)\n", ret);
@@ -637,7 +665,7 @@ int ipu6_isys_start_stream_firmware(struct ipu6_isys_video *av)
 out_stream_close:
 	reinit_completion(&stream->stream_close_completion);
 
-	retout = ipu6_fw_isys_simple_cmd(av->isys,
+	retout = ipu6_fw_isys_simple_cmd(stream->isys,
 					 stream->stream_handle,
 					 IPU6_FW_ISYS_SEND_TYPE_STREAM_CLOSE);
 	if (retout < 0) {
@@ -655,25 +683,25 @@ int ipu6_isys_start_stream_firmware(struct ipu6_isys_video *av)
 		dev_dbg(dev, "stream close complete\n");
 
 out_put_stream_opened:
-	put_stream_opened(av);
+	put_stream_opened(stream->isys);
 
 	return ret;
 }
 
-void ipu6_isys_stop_streaming_firmware(struct ipu6_isys_video *av)
+static int ipu6_isys_stop_streaming_firmware(struct ipu6_isys_stream *stream,
+					     struct v4l2_mbus_frame_desc *desc)
 {
-	struct device *dev = &av->isys->adev->auxdev.dev;
-	struct ipu6_isys_stream *stream = av->stream;
+	struct device *dev = &stream->isys->adev->auxdev.dev;
 	int ret, tout;
 
 	reinit_completion(&stream->stream_stop_completion);
 
-	ret = ipu6_fw_isys_simple_cmd(av->isys, stream->stream_handle,
+	ret = ipu6_fw_isys_simple_cmd(stream->isys, stream->stream_handle,
 				      IPU6_FW_ISYS_SEND_TYPE_STREAM_FLUSH);
 
 	if (ret < 0) {
 		dev_err(dev, "can't stop stream (%d)\n", ret);
-		return;
+		return 0;
 	}
 
 	tout = wait_for_completion_timeout(&stream->stream_stop_completion,
@@ -684,21 +712,24 @@ void ipu6_isys_stop_streaming_firmware(struct ipu6_isys_video *av)
 		dev_warn(dev, "stream stop error: %d\n", stream->error);
 	else
 		dev_dbg(dev, "stop stream: complete\n");
+
+	return 0;
 }
 
-void ipu6_isys_close_streaming_firmware(struct ipu6_isys_video *av)
+static int ipu6_isys_close_streaming_firmware(struct ipu6_isys_stream *stream,
+					      struct v4l2_mbus_frame_desc *desc)
 {
-	struct ipu6_isys_stream *stream = av->stream;
-	struct device *dev = &av->isys->adev->auxdev.dev;
+	struct device *dev = &stream->isys->adev->auxdev.dev;
+	struct ipu6_isys_csi2 *csi2 = ipu6_isys_subdev_to_csi2(stream->asd);
 	int ret, tout;
 
 	reinit_completion(&stream->stream_close_completion);
 
-	ret = ipu6_fw_isys_simple_cmd(av->isys, stream->stream_handle,
+	ret = ipu6_fw_isys_simple_cmd(stream->isys, stream->stream_handle,
 				      IPU6_FW_ISYS_SEND_TYPE_STREAM_CLOSE);
 	if (ret < 0) {
 		dev_err(dev, "can't close stream (%d)\n", ret);
-		return;
+		return 0;
 	}
 
 	tout = wait_for_completion_timeout(&stream->stream_close_completion,
@@ -710,155 +741,158 @@ void ipu6_isys_close_streaming_firmware(struct ipu6_isys_video *av)
 	else
 		dev_dbg(dev, "close stream: complete\n");
 
-	put_stream_opened(av);
+	put_stream_opened(stream->isys);
+
+	scoped_guard(spinlock_irqsave, &stream->isys->power_lock) {
+		stream->isys->streams_by_handle[stream->stream_handle] = NULL;
+		csi2->streams_by_vc[stream->vc] = NULL;
+	}
+
+	return 0;
 }
 
-int ipu6_isys_video_prepare_stream(struct ipu6_isys_video *av,
-				   struct media_entity *source_entity)
+static int call_on_streams(struct ipu6_isys_csi2 *csi2,
+			   int (*start)(struct ipu6_isys_stream *stream,
+					struct v4l2_mbus_frame_desc *desc),
+			   int (*stop)(struct ipu6_isys_stream *stream,
+				       struct v4l2_mbus_frame_desc *desc),
+			   struct ipu6_isys_stream *end,
+			   struct v4l2_mbus_frame_desc *desc)
 {
-	struct ipu6_isys_stream *stream = av->stream;
-	struct ipu6_isys_csi2 *csi2;
-
-	atomic_set(&stream->sequence, 0);
+	struct ipu6_isys_stream *stream;
 
-	stream->seq_index = 0;
-	memset(stream->seq, 0, sizeof(stream->seq));
+	list_for_each_entry(stream, &csi2->streams, csi2_entry) {
+		int ret;
 
-	if (WARN_ON(!list_empty(&stream->queues)))
-		return -EINVAL;
+		if (stream == end)
+			break;
 
-	stream->stream_source = stream->asd->source;
-	csi2 = ipu6_isys_subdev_to_csi2(stream->asd);
-	csi2->receiver_errors = 0;
+		ret = start(stream, desc);
+		if (ret && stop) {
+			call_on_streams(csi2, stop, NULL, stream, desc);
 
-	dev_dbg(&av->isys->adev->auxdev.dev,
-		"prepare stream: external entity %s\n",
-		source_entity->name);
+			return ret;
+		}
+	}
 
 	return 0;
 }
 
-void ipu6_isys_put_stream(struct ipu6_isys_stream *stream)
+void ipu6_isys_free_streams_firmware(struct ipu6_isys_csi2 *csi2)
 {
-	struct device *dev;
-	unsigned int i;
-	unsigned long flags;
-
-	if (!stream) {
-		pr_err("ipu6-isys: no available stream\n");
-		return;
-	}
-
-	dev = &stream->isys->adev->auxdev.dev;
+	struct ipu6_isys_stream *stream, *safe;
 
-	spin_lock_irqsave(&stream->isys->streams_lock, flags);
-	for (i = 0; i < IPU6_ISYS_MAX_STREAMS; i++) {
-		if (&stream->isys->streams[i] == stream) {
-			if (stream->isys->streams_ref_count[i] > 0)
-				stream->isys->streams_ref_count[i]--;
-			else
-				dev_warn(dev, "invalid stream %d\n", i);
-
-			break;
-		}
+	list_for_each_entry_safe(stream, safe, &csi2->streams, csi2_entry) {
+		list_del(&stream->csi2_entry);
+		ida_free(&csi2->isys->streams, stream->stream_handle);
+		kfree(stream);
 	}
-	spin_unlock_irqrestore(&stream->isys->streams_lock, flags);
 }
 
-static struct ipu6_isys_stream *
-ipu6_isys_get_stream(struct ipu6_isys_video *av, struct ipu6_isys_subdev *asd)
+int ipu6_isys_alloc_start_streams_firmware(struct ipu6_isys_csi2 *csi2,
+					   struct v4l2_subdev_state *csi2_state,
+					   struct v4l2_mbus_frame_desc *desc)
 {
-	struct ipu6_isys_stream *stream = NULL;
-	struct ipu6_isys *isys = av->isys;
-	unsigned long flags;
-	unsigned int i;
-	u8 vc = av->vc;
+	struct device *dev = &csi2->isys->adev->auxdev.dev;
+	struct v4l2_subdev_route *route;
+	int ret;
 
-	if (!isys)
-		return NULL;
+	for_each_active_route(&csi2_state->routing, route) {
+		struct media_pad *vdev_pad =
+			media_pad_remote_pad_first(&csi2->asd.pad[route->source_pad]);
+		struct v4l2_mbus_frame_desc_entry *entry = NULL;
+		struct ipu6_isys_stream *stream;
 
-	spin_lock_irqsave(&isys->streams_lock, flags);
-	for (i = 0; i < IPU6_ISYS_MAX_STREAMS; i++) {
-		if (isys->streams_ref_count[i] && isys->streams[i].vc == vc &&
-		    isys->streams[i].asd == asd) {
-			isys->streams_ref_count[i]++;
-			stream = &isys->streams[i];
+		for (unsigned int i = 0; i < desc->num_entries; i++) {
+			if (desc->entry[i].stream != route->sink_stream)
+				continue;
+
+			entry = &desc->entry[i];
 			break;
 		}
-	}
 
-	if (!stream) {
-		for (i = 0; i < IPU6_ISYS_MAX_STREAMS; i++) {
-			if (!isys->streams_ref_count[i]) {
-				isys->streams_ref_count[i]++;
-				stream = &isys->streams[i];
-				stream->vc = vc;
-				stream->asd = asd;
-				break;
-			}
+		if (!entry) {
+			dev_dbg(dev, "cannot find stream %u in frame desc\n",
+				route->sink_stream);
+			ret = -EINVAL;
+			goto err_free_streams;
 		}
-	}
-	spin_unlock_irqrestore(&isys->streams_lock, flags);
 
-	return stream;
-}
+		list_for_each_entry(stream, &csi2->streams, csi2_entry)
+			if (stream->vc == entry->bus.csi2.vc)
+				break;
 
-struct ipu6_isys_stream *
-ipu6_isys_query_stream_by_handle(struct ipu6_isys *isys, u8 stream_handle)
-{
-	unsigned long flags;
-	struct ipu6_isys_stream *stream = NULL;
+		if (list_entry_is_head(stream, &csi2->streams, csi2_entry)) {
+			unsigned long flags;
 
-	if (!isys)
-		return NULL;
+			stream = kzalloc(sizeof(*stream), GFP_KERNEL);
+			if (!stream) {
+				ret = -ENOMEM;
+				goto err_free_streams;
+			}
 
-	if (stream_handle >= IPU6_ISYS_MAX_STREAMS) {
-		dev_err(&isys->adev->auxdev.dev,
-			"stream_handle %d is invalid\n", stream_handle);
-		return NULL;
-	}
+			ret = ida_alloc_max(&csi2->isys->streams,
+					    IPU6_ISYS_MAX_STREAMS - 1,
+					    GFP_KERNEL);
+			if (ret < 0) {
+				kfree(stream);
+				goto err_free_streams;
+			}
 
-	spin_lock_irqsave(&isys->streams_lock, flags);
-	if (isys->streams_ref_count[stream_handle] > 0) {
-		isys->streams_ref_count[stream_handle]++;
-		stream = &isys->streams[stream_handle];
-	}
-	spin_unlock_irqrestore(&isys->streams_lock, flags);
+			stream->stream_handle = ret;
+			mutex_init(&stream->mutex);
+			init_completion(&stream->stream_open_completion);
+			init_completion(&stream->stream_close_completion);
+			init_completion(&stream->stream_start_completion);
+			init_completion(&stream->stream_stop_completion);
+			INIT_LIST_HEAD(&stream->queues);
+			stream->isys = csi2->asd.isys;
+			stream->asd = &csi2->asd;
+			stream->vc = entry->bus.csi2.vc;
+
+			scoped_guard(spinlock_irqsave, &stream->isys->power_lock) {
+				stream->isys->streams_by_handle[stream->stream_handle] =
+					stream;
+				csi2->streams_by_vc[stream->vc] = stream;
+			}
 
-	return stream;
-}
+			list_add(&stream->csi2_entry, &csi2->streams);
+		}
 
-struct ipu6_isys_stream *
-ipu6_isys_query_stream_by_source(struct ipu6_isys *isys, int source, u8 vc)
-{
-	struct ipu6_isys_stream *stream = NULL;
-	unsigned long flags;
-	unsigned int i;
+		struct ipu6_isys_video *av =
+			container_of_const(vdev_pad, struct ipu6_isys_video,
+					   pad);
+		struct ipu6_isys_queue *aq = &av->aq;
 
-	if (!isys)
-		return NULL;
+		list_add(&aq->node, &stream->queues);
 
-	if (source < 0) {
-		dev_err(&isys->adev->auxdev.dev,
-			"query stream with invalid port number\n");
-		return NULL;
+		stream->nr_output_pins++;
+		av->stream = stream;
 	}
 
-	spin_lock_irqsave(&isys->streams_lock, flags);
-	for (i = 0; i < IPU6_ISYS_MAX_STREAMS; i++) {
-		if (!isys->streams_ref_count[i])
-			continue;
+	ret = call_on_streams(csi2, ipu6_isys_start_stream_firmware,
+			      ipu6_isys_stop_streaming_firmware, NULL, desc);
 
-		if (isys->streams[i].stream_source == source &&
-		    isys->streams[i].vc == vc) {
-			stream = &isys->streams[i];
-			isys->streams_ref_count[i]++;
-			break;
-		}
-	}
-	spin_unlock_irqrestore(&isys->streams_lock, flags);
+	if (!ret)
+		return 0;
+
+err_free_streams:
+	ipu6_isys_free_streams_firmware(csi2);
+	ipu6_isys_free_streams_firmware(csi2);
+
+	return ret;
+}
+
+void ipu6_isys_stop_streams_firmware(struct ipu6_isys_csi2 *csi2)
+{
+	call_on_streams(csi2, ipu6_isys_stop_streaming_firmware, NULL, NULL,
+			NULL);
+}
 
-	return stream;
+void ipu6_isys_close_streams_firmware(struct ipu6_isys_csi2 *csi2)
+{
+	call_on_streams(csi2, ipu6_isys_close_streaming_firmware, NULL, NULL,
+			NULL);
 }
 
 int ipu6_isys_video_set_streaming(struct ipu6_isys_video *av, int state)
@@ -1000,71 +1034,6 @@ void ipu6_isys_fw_close(struct ipu6_isys *isys)
 		pm_runtime_put(&isys->adev->auxdev.dev);
 }
 
-int ipu6_isys_setup_video(struct ipu6_isys_video *av,
-			  struct media_pad *remote_pad,
-			  struct media_pad *source_pad)
-{
-	const struct ipu6_isys_pixelformat *pfmt =
-		ipu6_isys_get_isys_format(ipu6_isys_get_format(av), 0);
-	struct device *dev = &av->isys->adev->auxdev.dev;
-	struct v4l2_mbus_frame_desc_entry entry;
-	struct v4l2_subdev_route *route = NULL;
-	struct v4l2_subdev_route *r;
-	struct v4l2_subdev_state *state;
-	struct v4l2_subdev *remote_sd =
-		media_entity_to_v4l2_subdev(remote_pad->entity);
-	struct ipu6_isys_subdev *asd = to_ipu6_isys_subdev(remote_sd);
-	int ret = -EINVAL;
-
-	/* Find the root */
-	state = v4l2_subdev_lock_and_get_active_state(remote_sd);
-	for_each_active_route(&state->routing, r)
-		if (r->source_pad == remote_pad->index)
-			route = r;
-
-	if (!route) {
-		v4l2_subdev_unlock_state(state);
-		dev_dbg(dev, "Failed to find route\n");
-		return -ENODEV;
-	}
-	av->source_stream = route->sink_stream;
-	v4l2_subdev_unlock_state(state);
-
-	ret = ipu6_isys_csi2_get_remote_desc(av->source_stream,
-					     to_ipu6_isys_csi2(asd),
-					     source_pad->entity, &entry);
-	if (ret == -ENOIOCTLCMD) {
-		av->vc = 0;
-		av->dt = ipu6_isys_mbus_code_to_mipi(pfmt->code);
-	} else if (!ret) {
-		dev_dbg(dev, "Framedesc: stream %u, len %u, vc %u, dt %#x\n",
-			entry.stream, entry.length, entry.bus.csi2.vc,
-			entry.bus.csi2.dt);
-
-		av->vc = entry.bus.csi2.vc;
-		av->dt = entry.bus.csi2.dt;
-	} else {
-		dev_err(dev, "failed to get remote frame desc\n");
-		return ret;
-	}
-
-	pipeline = video_device_pipeline(&av->vdev);
-	ret = video_device_pipeline_alloc_start(&av->vdev);
-	if (ret < 0) {
-		dev_dbg(dev, "media pipeline start failed\n");
-		return ret;
-	}
-
-	av->stream = ipu6_isys_get_stream(av, asd);
-	if (!av->stream) {
-		video_device_pipeline_stop(&av->vdev);
-		dev_err(dev, "no available stream for firmware\n");
-		return -EINVAL;
-	}
-
-	return !pipeline;
-}
-
 /*
  * Do everything that's needed to initialise things related to video
  * buffer queue, video node, and the related media entity. The caller
diff --git a/drivers/media/pci/intel/ipu6/ipu6-isys-video.h b/drivers/media/pci/intel/ipu6/ipu6-isys-video.h
index e2a3bc482004..bf837efc8ae4 100644
--- a/drivers/media/pci/intel/ipu6/ipu6-isys-video.h
+++ b/drivers/media/pci/intel/ipu6/ipu6-isys-video.h
@@ -46,12 +46,13 @@ struct ipu6_isys_stream {
 	atomic_t sequence;
 	unsigned int seq_index;
 	struct sequence_info seq[IPU6_ISYS_MAX_PARALLEL_SOF];
-	int stream_source;
 	int stream_handle;
 	unsigned int nr_output_pins;
 	struct ipu6_isys_subdev *asd;
-
 	struct list_head queues;
+	struct list_head csi2_entry;
+	struct list_head isys_entry;
+
 	struct completion stream_open_completion;
 	struct completion stream_close_completion;
 	struct completion stream_start_completion;
@@ -79,6 +80,7 @@ struct ipu6_isys_video {
 	u32 source_stream;
 	u8 vc;
 	u8 dt;
+	u8 sink_stream;
 };
 
 #define ipu6_isys_queue_to_video(__aq) \
@@ -89,11 +91,12 @@ extern const struct ipu6_isys_pixelformat ipu6_isys_pfmts_packed[];
 
 const struct ipu6_isys_pixelformat *
 ipu6_isys_get_isys_format(u32 pixelformat, u32 code);
-int ipu6_isys_start_stream_firmware(struct ipu6_isys_video *av);
-void ipu6_isys_stop_streaming_firmware(struct ipu6_isys_video *av);
-void ipu6_isys_close_streaming_firmware(struct ipu6_isys_video *av);
-int ipu6_isys_video_prepare_stream(struct ipu6_isys_video *av,
-				   struct media_entity *source_entity);
+void ipu6_isys_free_streams_firmware(struct ipu6_isys_csi2 *csi2);
+int ipu6_isys_alloc_start_streams_firmware(struct ipu6_isys_csi2 *csi2,
+					   struct v4l2_subdev_state *state,
+					   struct v4l2_mbus_frame_desc *desc);
+void ipu6_isys_stop_streams_firmware(struct ipu6_isys_csi2 *csi2);
+void ipu6_isys_close_streams_firmware(struct ipu6_isys_csi2 *csi2);
 int ipu6_isys_video_set_streaming(struct ipu6_isys_video *av, int state);
 int ipu6_isys_fw_open(struct ipu6_isys *isys);
 void ipu6_isys_fw_close(struct ipu6_isys *isys);
@@ -102,7 +105,6 @@ int ipu6_isys_setup_video(struct ipu6_isys_video *av,
 			  struct media_pad *source_pad);
 int ipu6_isys_video_init(struct ipu6_isys_video *av);
 void ipu6_isys_video_cleanup(struct ipu6_isys_video *av);
-void ipu6_isys_put_stream(struct ipu6_isys_stream *stream);
 struct ipu6_isys_stream *
 ipu6_isys_query_stream_by_handle(struct ipu6_isys *isys, u8 stream_handle);
 struct ipu6_isys_stream *
diff --git a/drivers/media/pci/intel/ipu6/ipu6-isys.c b/drivers/media/pci/intel/ipu6/ipu6-isys.c
index 04058252ac01..d7e69195c84d 100644
--- a/drivers/media/pci/intel/ipu6/ipu6-isys.c
+++ b/drivers/media/pci/intel/ipu6/ipu6-isys.c
@@ -162,23 +162,6 @@ isys_complete_ext_device_registration(struct ipu6_isys *isys,
 	return ret;
 }
 
-static void isys_stream_init(struct ipu6_isys *isys)
-{
-	u32 i;
-
-	for (i = 0; i < IPU6_ISYS_MAX_STREAMS; i++) {
-		mutex_init(&isys->streams[i].mutex);
-		init_completion(&isys->streams[i].stream_open_completion);
-		init_completion(&isys->streams[i].stream_close_completion);
-		init_completion(&isys->streams[i].stream_start_completion);
-		init_completion(&isys->streams[i].stream_stop_completion);
-		INIT_LIST_HEAD(&isys->streams[i].queues);
-		isys->streams[i].isys = isys;
-		isys->streams[i].stream_handle = i;
-		isys->streams[i].vc = INVALID_VC_ID;
-	}
-}
-
 static void isys_csi2_unregister_subdevices(struct ipu6_isys *isys)
 {
 	const struct ipu6_isys_internal_csi2_pdata *csi2 =
@@ -344,21 +327,15 @@ static void ipu6_isys_csi2_isr(struct ipu6_isys_csi2 *csi2)
 	source = csi2->asd.source;
 	for (i = 0; i < NR_OF_CSI2_VC; i++) {
 		if (status & IPU_CSI_RX_IRQ_FS_VC(i)) {
-			stream = ipu6_isys_query_stream_by_source(csi2->isys,
-								  source, i);
-			if (stream) {
+			stream = csi2->streams_by_vc[i];
+			if (stream)
 				ipu6_isys_csi2_sof_event_by_stream(stream);
-				ipu6_isys_put_stream(stream);
-			}
 		}
 
 		if (status & IPU_CSI_RX_IRQ_FE_VC(i)) {
-			stream = ipu6_isys_query_stream_by_source(csi2->isys,
-								  source, i);
-			if (stream) {
+			stream = csi2->streams_by_vc[i];
+			if (stream)
 				ipu6_isys_csi2_eof_event_by_stream(stream);
-				ipu6_isys_put_stream(stream);
-			}
 		}
 	}
 }
@@ -1011,7 +988,6 @@ static int isys_probe(struct auxiliary_device *auxdev,
 	struct ipu6_device *isp = adev->isp;
 	const struct firmware *fw;
 	struct ipu6_isys *isys;
-	unsigned int i;
 	int ret;
 
 	if (!isp->bus_ready_to_probe)
@@ -1052,7 +1028,7 @@ static int isys_probe(struct auxiliary_device *auxdev,
 
 	dev_set_drvdata(&auxdev->dev, isys);
 
-	isys_stream_init(isys);
+	ida_init(&isys->streams);
 
 	if (!isp->secure_mode) {
 		fw = isp->cpd_fw;
@@ -1097,9 +1073,6 @@ static int isys_probe(struct auxiliary_device *auxdev,
 	if (!isp->secure_mode)
 		release_firmware(adev->fw);
 
-	for (i = 0; i < IPU6_ISYS_MAX_STREAMS; i++)
-		mutex_destroy(&isys->streams[i].mutex);
-
 	mutex_destroy(&isys->mutex);
 	mutex_destroy(&isys->stream_mutex);
 
@@ -1111,7 +1084,8 @@ static void isys_remove(struct auxiliary_device *auxdev)
 	struct ipu6_bus_device *adev = auxdev_to_adev(auxdev);
 	struct ipu6_isys *isys = dev_get_drvdata(&auxdev->dev);
 	struct ipu6_device *isp = adev->isp;
-	unsigned int i;
+
+	ida_destroy(&isys->streams);
 
 	free_fw_msg_bufs(isys);
 
@@ -1126,9 +1100,6 @@ static void isys_remove(struct auxiliary_device *auxdev)
 		release_firmware(adev->fw);
 	}
 
-	for (i = 0; i < IPU6_ISYS_MAX_STREAMS; i++)
-		mutex_destroy(&isys->streams[i].mutex);
-
 	mutex_destroy(&isys->stream_mutex);
 	mutex_destroy(&isys->mutex);
 }
@@ -1209,7 +1180,8 @@ static int isys_isr_one(struct ipu6_bus_device *adev)
 		goto leave;
 	}
 
-	stream = ipu6_isys_query_stream_by_handle(isys, resp->stream_handle);
+	stream = resp->stream_handle < IPU6_ISYS_MAX_STREAMS ?
+		isys->streams_by_handle[resp->stream_handle] : NULL;
 	if (!stream) {
 		dev_err(&adev->auxdev.dev, "stream of stream_handle %u is unused\n",
 			resp->stream_handle);
@@ -1288,7 +1260,6 @@ static int isys_isr_one(struct ipu6_bus_device *adev)
 		break;
 	}
 
-	ipu6_isys_put_stream(stream);
 leave:
 	ipu6_fw_isys_put_resp(isys->fwcom, IPU6_BASE_MSG_RECV_QUEUES);
 	return 0;
diff --git a/drivers/media/pci/intel/ipu6/ipu6-isys.h b/drivers/media/pci/intel/ipu6/ipu6-isys.h
index 0689b4485c7f..8a5086439f21 100644
--- a/drivers/media/pci/intel/ipu6/ipu6-isys.h
+++ b/drivers/media/pci/intel/ipu6/ipu6-isys.h
@@ -4,6 +4,7 @@
 #ifndef IPU6_ISYS_H
 #define IPU6_ISYS_H
 
+#include <linux/idr.h>
 #include <linux/irqreturn.h>
 #include <linux/list.h>
 #include <linux/mutex.h>
@@ -102,8 +103,8 @@ struct ipu6_isys {
 	u32 isr_csi2_bits;
 	u32 csi2_rx_ctrl_cached;
 	spinlock_t streams_lock;
-	struct ipu6_isys_stream streams[IPU6_ISYS_MAX_STREAMS];
-	int streams_ref_count[IPU6_ISYS_MAX_STREAMS];
+	struct ipu6_isys_stream *streams_by_handle[IPU6_ISYS_MAX_STREAMS];
+	struct completion stream_completion;
 	void *fwcom;
 	u32 phy_termcal_val;
 	bool need_reset;
@@ -131,6 +132,7 @@ struct ipu6_isys {
 	struct list_head framebuflist;
 	struct list_head framebuflist_fw;
 	struct v4l2_async_notifier notifier;
+	struct ida streams;
 };
 
 struct isys_fw_msgs {
-- 
2.47.3


^ permalink raw reply related	[flat|nested] 88+ messages in thread

* [PATCH v12 82/86] media: ipu6: Drop {get,put}_streams_opened()
  2026-04-09 20:13 [PATCH v12 00/86] Generic line based metadata support, internal pads Sakari Ailus
                   ` (80 preceding siblings ...)
  2026-04-09 20:14 ` [PATCH v12 81/86] media: ipu6: Bridge the gap between streams in V4L2 and IPU6 firmware Sakari Ailus
@ 2026-04-09 20:14 ` Sakari Ailus
  2026-04-09 20:14 ` [PATCH v12 83/86] media: ipu6: Serialise access to stream pointers by isys stream_lock Sakari Ailus
                   ` (3 subsequent siblings)
  85 siblings, 0 replies; 88+ messages in thread
From: Sakari Ailus @ 2026-04-09 20:14 UTC (permalink / raw)
  To: linux-media
  Cc: hans, laurent.pinchart, Prabhakar, Kate Hsuan, Dave Stevenson,
	Tommaso Merciai, Benjamin Mugnier, Sylvain Petinot,
	Christophe JAILLET, Julien Massot, Naushir Patuck, Stefan Klug,
	Mirela Rabulea, André Apitzsch, Heimir Thor Sverrisson,
	Kieran Bingham, Mehdi Djait, Ricardo Ribalda Delgado,
	Hans de Goede, Jacopo Mondi, Tomi Valkeinen, David Plowman,
	Yu, Ong Hock, Ng, Khai Wen, Jai Luthra, Rishikesh Donadkar

{get,put}_streams_opened() aren't needed anymore. Drop them. This also
requires acquiring isys->stream_mutex for system suspend.

Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
---
 .../media/pci/intel/ipu6/ipu6-isys-video.c    | 39 +++----------------
 drivers/media/pci/intel/ipu6/ipu6-isys.c      |  4 +-
 drivers/media/pci/intel/ipu6/ipu6-isys.h      |  1 -
 3 files changed, 8 insertions(+), 36 deletions(-)

diff --git a/drivers/media/pci/intel/ipu6/ipu6-isys-video.c b/drivers/media/pci/intel/ipu6/ipu6-isys-video.c
index 2344e4a880d6..9eb22e456834 100644
--- a/drivers/media/pci/intel/ipu6/ipu6-isys-video.c
+++ b/drivers/media/pci/intel/ipu6/ipu6-isys-video.c
@@ -440,24 +440,6 @@ static int link_validate(struct media_link *link)
 	return ret;
 }
 
-static void get_stream_opened(struct ipu6_isys *isys)
-{
-	unsigned long flags;
-
-	spin_lock_irqsave(&isys->streams_lock, flags);
-	isys->stream_opened++;
-	spin_unlock_irqrestore(&isys->streams_lock, flags);
-}
-
-static void put_stream_opened(struct ipu6_isys *isys)
-{
-	unsigned long flags;
-
-	spin_lock_irqsave(&isys->streams_lock, flags);
-	isys->stream_opened--;
-	spin_unlock_irqrestore(&isys->streams_lock, flags);
-}
-
 static int ipu6_isys_fw_pin_cfg(struct ipu6_isys_video *av,
 				struct ipu6_fw_isys_stream_cfg_data_abi *cfg,
 				struct ipu6_isys_stream *stream,
@@ -607,8 +589,6 @@ static int ipu6_isys_start_stream_firmware(struct ipu6_isys_stream *stream,
 		return ret;
 	}
 
-	get_stream_opened(stream->isys);
-
 	tout = wait_for_completion_timeout(&stream->stream_open_completion,
 					   IPU6_FW_CALL_TIMEOUT_JIFFIES);
 
@@ -616,21 +596,17 @@ static int ipu6_isys_start_stream_firmware(struct ipu6_isys_stream *stream,
 
 	if (!tout) {
 		dev_err(dev, "stream open time out\n");
-		ret = -ETIMEDOUT;
-		goto out_put_stream_opened;
+		return -ETIMEDOUT;
 	}
 	if (stream->error) {
 		dev_err(dev, "stream open error: %d\n", stream->error);
-		ret = -EIO;
-		goto out_put_stream_opened;
+		return -EIO;
 	}
 	dev_dbg(dev, "start stream: open complete\n");
 
 	msg = ipu6_get_fw_msg_buf(stream);
-	if (!msg) {
-		ret = -ENOMEM;
-		goto out_put_stream_opened;
-	}
+	if (!msg)
+		return -ENOMEM;
 	buf = &msg->fw_msg.frame;
 	ipu6_isys_buf_to_fw_frame_buf(buf, stream, &bl);
 	ipu6_isys_buffer_list_queue(&bl, IPU6_ISYS_BUFFER_LIST_FL_ACTIVE, 0);
@@ -670,7 +646,7 @@ static int ipu6_isys_start_stream_firmware(struct ipu6_isys_stream *stream,
 					 IPU6_FW_ISYS_SEND_TYPE_STREAM_CLOSE);
 	if (retout < 0) {
 		dev_dbg(dev, "can't close stream (%d)\n", retout);
-		goto out_put_stream_opened;
+		return retout;
 	}
 
 	tout = wait_for_completion_timeout(&stream->stream_close_completion,
@@ -682,9 +658,6 @@ static int ipu6_isys_start_stream_firmware(struct ipu6_isys_stream *stream,
 	else
 		dev_dbg(dev, "stream close complete\n");
 
-out_put_stream_opened:
-	put_stream_opened(stream->isys);
-
 	return ret;
 }
 
@@ -741,8 +714,6 @@ static int ipu6_isys_close_streaming_firmware(struct ipu6_isys_stream *stream,
 	else
 		dev_dbg(dev, "close stream: complete\n");
 
-	put_stream_opened(stream->isys);
-
 	scoped_guard(spinlock_irqsave, &stream->isys->power_lock) {
 		stream->isys->streams_by_handle[stream->stream_handle] = NULL;
 		csi2->streams_by_vc[stream->vc] = NULL;
diff --git a/drivers/media/pci/intel/ipu6/ipu6-isys.c b/drivers/media/pci/intel/ipu6/ipu6-isys.c
index d7e69195c84d..fb46ded122fa 100644
--- a/drivers/media/pci/intel/ipu6/ipu6-isys.c
+++ b/drivers/media/pci/intel/ipu6/ipu6-isys.c
@@ -853,8 +853,10 @@ static int isys_suspend(struct device *dev)
 {
 	struct ipu6_isys *isys = dev_get_drvdata(dev);
 
+	guard(mutex)(&isys->stream_mutex);
+
 	/* If stream is open, refuse to suspend */
-	if (isys->stream_opened)
+	if (!ida_is_empty(&isys->streams))
 		return -EBUSY;
 
 	return 0;
diff --git a/drivers/media/pci/intel/ipu6/ipu6-isys.h b/drivers/media/pci/intel/ipu6/ipu6-isys.h
index 8a5086439f21..157b27a8eb6d 100644
--- a/drivers/media/pci/intel/ipu6/ipu6-isys.h
+++ b/drivers/media/pci/intel/ipu6/ipu6-isys.h
@@ -112,7 +112,6 @@ struct ipu6_isys {
 	bool csi2_cse_ipc_not_supported;
 	bool iwake_watermark_enabled;
 	unsigned int ref_count;
-	unsigned int stream_opened;
 	unsigned int sensor_type;
 
 	struct mutex mutex;
-- 
2.47.3


^ permalink raw reply related	[flat|nested] 88+ messages in thread

* [PATCH v12 83/86] media: ipu6: Serialise access to stream pointers by isys stream_lock
  2026-04-09 20:13 [PATCH v12 00/86] Generic line based metadata support, internal pads Sakari Ailus
                   ` (81 preceding siblings ...)
  2026-04-09 20:14 ` [PATCH v12 82/86] media: ipu6: Drop {get,put}_streams_opened() Sakari Ailus
@ 2026-04-09 20:14 ` Sakari Ailus
  2026-04-09 20:14 ` [PATCH v12 84/86] media: ipu6: Move firmware init/cleanup to RPM callbacks Sakari Ailus
                   ` (2 subsequent siblings)
  85 siblings, 0 replies; 88+ messages in thread
From: Sakari Ailus @ 2026-04-09 20:14 UTC (permalink / raw)
  To: linux-media
  Cc: hans, laurent.pinchart, Prabhakar, Kate Hsuan, Dave Stevenson,
	Tommaso Merciai, Benjamin Mugnier, Sylvain Petinot,
	Christophe JAILLET, Julien Massot, Naushir Patuck, Stefan Klug,
	Mirela Rabulea, André Apitzsch, Heimir Thor Sverrisson,
	Kieran Bingham, Mehdi Djait, Ricardo Ribalda Delgado,
	Hans de Goede, Jacopo Mondi, Tomi Valkeinen, David Plowman,
	Yu, Ong Hock, Ng, Khai Wen, Jai Luthra, Rishikesh Donadkar

Re-purpose the unused stream_lock in struct ipu6_isys to serialise access
to streams_by_handle (struct ipu6_isys) and streams_by_vc (struct
ipu6_isys_csi2). Switch to scoped_guard() while at it.

Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
---
 .../media/pci/intel/ipu6/ipu6-isys-video.c    |  6 ++---
 drivers/media/pci/intel/ipu6/ipu6-isys.c      | 23 ++++++++++---------
 2 files changed, 14 insertions(+), 15 deletions(-)

diff --git a/drivers/media/pci/intel/ipu6/ipu6-isys-video.c b/drivers/media/pci/intel/ipu6/ipu6-isys-video.c
index 9eb22e456834..0c3223c4d019 100644
--- a/drivers/media/pci/intel/ipu6/ipu6-isys-video.c
+++ b/drivers/media/pci/intel/ipu6/ipu6-isys-video.c
@@ -714,7 +714,7 @@ static int ipu6_isys_close_streaming_firmware(struct ipu6_isys_stream *stream,
 	else
 		dev_dbg(dev, "close stream: complete\n");
 
-	scoped_guard(spinlock_irqsave, &stream->isys->power_lock) {
+	scoped_guard(spinlock_irqsave, &stream->isys->streams_lock) {
 		stream->isys->streams_by_handle[stream->stream_handle] = NULL;
 		csi2->streams_by_vc[stream->vc] = NULL;
 	}
@@ -794,8 +794,6 @@ int ipu6_isys_alloc_start_streams_firmware(struct ipu6_isys_csi2 *csi2,
 				break;
 
 		if (list_entry_is_head(stream, &csi2->streams, csi2_entry)) {
-			unsigned long flags;
-
 			stream = kzalloc(sizeof(*stream), GFP_KERNEL);
 			if (!stream) {
 				ret = -ENOMEM;
@@ -821,7 +819,7 @@ int ipu6_isys_alloc_start_streams_firmware(struct ipu6_isys_csi2 *csi2,
 			stream->asd = &csi2->asd;
 			stream->vc = entry->bus.csi2.vc;
 
-			scoped_guard(spinlock_irqsave, &stream->isys->power_lock) {
+			scoped_guard(spinlock_irqsave, &stream->isys->streams_lock) {
 				stream->isys->streams_by_handle[stream->stream_handle] =
 					stream;
 				csi2->streams_by_vc[stream->vc] = stream;
diff --git a/drivers/media/pci/intel/ipu6/ipu6-isys.c b/drivers/media/pci/intel/ipu6/ipu6-isys.c
index fb46ded122fa..0c2adfa01034 100644
--- a/drivers/media/pci/intel/ipu6/ipu6-isys.c
+++ b/drivers/media/pci/intel/ipu6/ipu6-isys.c
@@ -311,10 +311,8 @@ static void isys_setup_hw(struct ipu6_isys *isys)
 
 static void ipu6_isys_csi2_isr(struct ipu6_isys_csi2 *csi2)
 {
-	struct ipu6_isys_stream *stream;
 	unsigned int i;
 	u32 status;
-	int source;
 
 	ipu6_isys_register_errors(csi2);
 
@@ -324,17 +322,18 @@ static void ipu6_isys_csi2_isr(struct ipu6_isys_csi2 *csi2)
 	writel(status, csi2->base + CSI_PORT_REG_BASE_IRQ_CSI_SYNC +
 	       CSI_PORT_REG_BASE_IRQ_CLEAR_OFFSET);
 
-	source = csi2->asd.source;
-	for (i = 0; i < NR_OF_CSI2_VC; i++) {
-		if (status & IPU_CSI_RX_IRQ_FS_VC(i)) {
-			stream = csi2->streams_by_vc[i];
-			if (stream)
+	scoped_guard(spinlock, &csi2->isys->streams_lock) {
+		for (i = 0; i < NR_OF_CSI2_VC; i++) {
+			struct ipu6_isys_stream *stream =
+				csi2->streams_by_vc[i];
+
+			if (!stream)
+				continue;
+
+			if (status & IPU_CSI_RX_IRQ_FS_VC(i))
 				ipu6_isys_csi2_sof_event_by_stream(stream);
-		}
 
-		if (status & IPU_CSI_RX_IRQ_FE_VC(i)) {
-			stream = csi2->streams_by_vc[i];
-			if (stream)
+			if (status & IPU_CSI_RX_IRQ_FE_VC(i))
 				ipu6_isys_csi2_eof_event_by_stream(stream);
 		}
 	}
@@ -1176,6 +1175,8 @@ static int isys_isr_one(struct ipu6_bus_device *adev)
 			"FW error resp error %d, details %d\n",
 			resp->error_info.error, resp->error_info.error_details);
 
+	guard(spinlock_irqsave)(&isys->streams_lock);
+
 	if (resp->stream_handle >= IPU6_ISYS_MAX_STREAMS) {
 		dev_err(&adev->auxdev.dev, "bad stream handle %u\n",
 			resp->stream_handle);
-- 
2.47.3


^ permalink raw reply related	[flat|nested] 88+ messages in thread

* [PATCH v12 84/86] media: ipu6: Move firmware init/cleanup to RPM callbacks
  2026-04-09 20:13 [PATCH v12 00/86] Generic line based metadata support, internal pads Sakari Ailus
                   ` (82 preceding siblings ...)
  2026-04-09 20:14 ` [PATCH v12 83/86] media: ipu6: Serialise access to stream pointers by isys stream_lock Sakari Ailus
@ 2026-04-09 20:14 ` Sakari Ailus
  2026-04-09 20:15 ` [PATCH v12 85/86] media: ipu6: Don't track power status, rely on runtime PM Sakari Ailus
  2026-04-09 20:15 ` [PATCH v12 86/86] media: bcm2835-unicam: Support generic raw formats Sakari Ailus
  85 siblings, 0 replies; 88+ messages in thread
From: Sakari Ailus @ 2026-04-09 20:14 UTC (permalink / raw)
  To: linux-media
  Cc: hans, laurent.pinchart, Prabhakar, Kate Hsuan, Dave Stevenson,
	Tommaso Merciai, Benjamin Mugnier, Sylvain Petinot,
	Christophe JAILLET, Julien Massot, Naushir Patuck, Stefan Klug,
	Mirela Rabulea, André Apitzsch, Heimir Thor Sverrisson,
	Kieran Bingham, Mehdi Djait, Ricardo Ribalda Delgado,
	Hans de Goede, Jacopo Mondi, Tomi Valkeinen, David Plowman,
	Yu, Ong Hock, Ng, Khai Wen, Jai Luthra, Rishikesh Donadkar

Move handling firmware initialisation and cleanup away from the rest of
the driver to the runtime PM callbacks. This simplifies the driver,
including removing the ref_count field in struct ipu6_isys.

Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
---
 drivers/media/pci/intel/ipu6/ipu6-isys-csi2.c | 16 +++-
 .../media/pci/intel/ipu6/ipu6-isys-queue.c    | 11 +--
 .../media/pci/intel/ipu6/ipu6-isys-video.c    | 73 -------------------
 drivers/media/pci/intel/ipu6/ipu6-isys.c      | 53 ++++++++++++--
 drivers/media/pci/intel/ipu6/ipu6-isys.h      |  2 -
 5 files changed, 60 insertions(+), 95 deletions(-)

diff --git a/drivers/media/pci/intel/ipu6/ipu6-isys-csi2.c b/drivers/media/pci/intel/ipu6/ipu6-isys-csi2.c
index b1cf2c622b01..1d8f231e3333 100644
--- a/drivers/media/pci/intel/ipu6/ipu6-isys-csi2.c
+++ b/drivers/media/pci/intel/ipu6/ipu6-isys-csi2.c
@@ -11,6 +11,7 @@
 #include <linux/err.h>
 #include <linux/io.h>
 #include <linux/minmax.h>
+#include <linux/pm_runtime.h>
 #include <linux/sprintf.h>
 #include <linux/string_choices.h>
 
@@ -486,6 +487,10 @@ static int ipu6_isys_csi2_enable_streams(struct v4l2_subdev *sd,
 	if (!ipu6_isys_csi2_streaming_change(asd, state, pad, true))
 		return 0;
 
+	ret = pm_runtime_resume_and_get(sd->dev);
+	if (ret < 0)
+		goto err_del_av;
+
 	remote_pad = media_pad_remote_pad_first(&sd->entity.pads[CSI2_PAD_SINK]);
 	remote_sd = media_entity_to_v4l2_subdev(remote_pad->entity);
 
@@ -493,12 +498,12 @@ static int ipu6_isys_csi2_enable_streams(struct v4l2_subdev *sd,
 
 	ret = v4l2_subdev_get_frame_desc(remote_sd, remote_pad->index, &desc);
 	if (ret)
-		goto err_del_av;
+		goto err_runtime_pm_put;
 
 	ret = ipu6_isys_alloc_start_streams_firmware(csi2, state, &desc);
 	if (ret) {
 		dev_err(sd->dev, "start stream of firmware failed\n");
-		goto err_del_av;
+		goto err_runtime_pm_put;
 	}
 
 	ret = ipu6_isys_csi2_calc_timing(csi2, &timing, CSI2_ACCINV);
@@ -526,8 +531,11 @@ static int ipu6_isys_csi2_enable_streams(struct v4l2_subdev *sd,
 	ipu6_isys_close_streams_firmware(csi2);
 	ipu6_isys_free_streams_firmware(csi2);
 
-err_del_av:
+err_runtime_pm_put:
 	ipu6_isys_csi2_clear_watermark(csi2);
+	pm_runtime_put(sd->dev);
+
+err_del_av:
 	ipu6_isys_csi2_streaming_change(asd, state, pad, false);
 	csi2->stream_ids &= ~sink_streams;
 	list_del(&av->csi2_entry);
@@ -576,6 +584,8 @@ static int ipu6_isys_csi2_disable_streams(struct v4l2_subdev *sd,
 
 	ipu6_isys_csi2_clear_watermark(csi2);
 
+	pm_runtime_put(sd->dev);
+
 out_del_csi2_entry:
 	list_del(&av->csi2_entry);
 
diff --git a/drivers/media/pci/intel/ipu6/ipu6-isys-queue.c b/drivers/media/pci/intel/ipu6/ipu6-isys-queue.c
index 31df83b9f45f..b21ceb036617 100644
--- a/drivers/media/pci/intel/ipu6/ipu6-isys-queue.c
+++ b/drivers/media/pci/intel/ipu6/ipu6-isys-queue.c
@@ -572,19 +572,12 @@ static int start_streaming(struct vb2_queue *q, unsigned int count)
 		goto out_pipeline_stop;
 	}
 
-	ret = ipu6_isys_fw_open(av->isys);
-	if (ret)
-		goto out_pipeline_stop;
-
 	ret = ipu6_isys_stream_start(av);
 	if (ret)
-		goto out_fw_close;
+		goto out_pipeline_stop;
 
 	return 0;
 
-out_fw_close:
-	ipu6_isys_fw_close(av->isys);
-
 out_pipeline_stop:
 	ipu6_isys_stream_cleanup(av);
 
@@ -606,8 +599,6 @@ static void stop_streaming(struct vb2_queue *q)
 	ipu6_isys_stream_cleanup(av);
 
 	return_buffers(aq, VB2_BUF_STATE_ERROR);
-
-	ipu6_isys_fw_close(av->isys);
 }
 
 static unsigned int
diff --git a/drivers/media/pci/intel/ipu6/ipu6-isys-video.c b/drivers/media/pci/intel/ipu6/ipu6-isys-video.c
index 0c3223c4d019..1e912b12d508 100644
--- a/drivers/media/pci/intel/ipu6/ipu6-isys-video.c
+++ b/drivers/media/pci/intel/ipu6/ipu6-isys-video.c
@@ -930,79 +930,6 @@ static const struct v4l2_file_operations isys_fops = {
 	.release = vb2_fop_release,
 };
 
-int ipu6_isys_fw_open(struct ipu6_isys *isys)
-{
-	struct ipu6_bus_device *adev = isys->adev;
-	const struct ipu6_isys_internal_pdata *ipdata = isys->pdata->ipdata;
-	int ret;
-
-	ret = pm_runtime_resume_and_get(&adev->auxdev.dev);
-	if (ret < 0)
-		return ret;
-
-	mutex_lock(&isys->mutex);
-
-	if (isys->ref_count++)
-		goto unlock;
-
-	ipu6_configure_spc(adev->isp, &ipdata->hw_variant,
-			   IPU6_CPD_PKG_DIR_ISYS_SERVER_IDX, isys->pdata->base,
-			   adev->pkg_dir, adev->pkg_dir_dma_addr);
-
-	/*
-	 * Buffers could have been left to wrong queue at last closure.
-	 * Move them now back to empty buffer queue.
-	 */
-	ipu6_cleanup_fw_msg_bufs(isys);
-
-	if (isys->fwcom) {
-		/*
-		 * Something went wrong in previous shutdown. As we are now
-		 * restarting isys we can safely delete old context.
-		 */
-		dev_warn(&adev->auxdev.dev, "clearing old context\n");
-		ipu6_fw_isys_cleanup(isys);
-	}
-
-	ret = ipu6_fw_isys_init(isys, ipdata->num_parallel_streams);
-	if (ret < 0)
-		goto out;
-
-unlock:
-	mutex_unlock(&isys->mutex);
-
-	return 0;
-
-out:
-	isys->ref_count--;
-	mutex_unlock(&isys->mutex);
-	pm_runtime_put(&adev->auxdev.dev);
-
-	return ret;
-}
-
-void ipu6_isys_fw_close(struct ipu6_isys *isys)
-{
-	mutex_lock(&isys->mutex);
-
-	isys->ref_count--;
-	if (!isys->ref_count) {
-		ipu6_fw_isys_close(isys);
-		if (isys->fwcom) {
-			isys->need_reset = true;
-			dev_warn(&isys->adev->auxdev.dev,
-				 "failed to close fw isys\n");
-		}
-	}
-
-	mutex_unlock(&isys->mutex);
-
-	if (isys->need_reset)
-		pm_runtime_put_sync(&isys->adev->auxdev.dev);
-	else
-		pm_runtime_put(&isys->adev->auxdev.dev);
-}
-
 /*
  * Do everything that's needed to initialise things related to video
  * buffer queue, video node, and the related media entity. The caller
diff --git a/drivers/media/pci/intel/ipu6/ipu6-isys.c b/drivers/media/pci/intel/ipu6/ipu6-isys.c
index 0c2adfa01034..8258a6dbf43c 100644
--- a/drivers/media/pci/intel/ipu6/ipu6-isys.c
+++ b/drivers/media/pci/intel/ipu6/ipu6-isys.c
@@ -799,6 +799,7 @@ static int isys_runtime_pm_resume(struct device *dev)
 {
 	struct ipu6_bus_device *adev = to_ipu6_bus_device(dev);
 	struct ipu6_isys *isys = ipu6_bus_get_drvdata(adev);
+	const struct ipu6_isys_internal_pdata *ipdata = isys->pdata->ipdata;
 	struct ipu6_device *isp = adev->isp;
 	unsigned long flags;
 	int ret;
@@ -811,7 +812,7 @@ static int isys_runtime_pm_resume(struct device *dev)
 
 	ret = ipu6_buttress_start_tsc_sync(isp);
 	if (ret)
-		return ret;
+		goto err_mmu_hw_cleanup;
 
 	spin_lock_irqsave(&isys->power_lock, flags);
 	isys->power = 1;
@@ -821,7 +822,42 @@ static int isys_runtime_pm_resume(struct device *dev)
 
 	set_iwake_ltrdid(isys, 0, 0, LTR_ISYS_ON);
 
-	return 0;
+	ipu6_configure_spc(adev->isp, &ipdata->hw_variant,
+			   IPU6_CPD_PKG_DIR_ISYS_SERVER_IDX, isys->pdata->base,
+			   adev->pkg_dir, adev->pkg_dir_dma_addr);
+
+	/*
+	 * Buffers could have been left to wrong queue at last closure.
+	 * Move them now back to empty buffer queue.
+	 */
+	ipu6_cleanup_fw_msg_bufs(isys);
+
+	if (isys->fwcom) {
+		/*
+		 * Something went wrong in previous shutdown. As we are now
+		 * restarting isys we can safely delete old context.
+		 */
+		dev_warn(&adev->auxdev.dev, "clearing old context\n");
+		ipu6_fw_isys_cleanup(isys);
+	}
+
+	ret = ipu6_fw_isys_init(isys, ipdata->num_parallel_streams);
+	if (!ret)
+		return 0;
+
+	spin_lock_irqsave(&isys->power_lock, flags);
+	isys->power = 0;
+	spin_unlock_irqrestore(&isys->power_lock, flags);
+
+	isys->phy_termcal_val = 0;
+	cpu_latency_qos_update_request(&isys->pm_qos, PM_QOS_DEFAULT_VALUE);
+
+	set_iwake_ltrdid(isys, 0, 0, LTR_ISYS_OFF);
+
+err_mmu_hw_cleanup:
+	ipu6_mmu_hw_cleanup(adev->mmu);
+
+	return ret;
 }
 
 static int isys_runtime_pm_suspend(struct device *dev)
@@ -829,15 +865,18 @@ static int isys_runtime_pm_suspend(struct device *dev)
 	struct ipu6_bus_device *adev = to_ipu6_bus_device(dev);
 	struct ipu6_isys *isys = dev_get_drvdata(dev);
 	unsigned long flags;
+	int ret = 0;
+
+	ipu6_fw_isys_close(isys);
+	if (isys->fwcom) {
+		dev_warn(&isys->adev->auxdev.dev, "failed to close fw isys\n");
+		ret = -EIO;
+	}
 
 	spin_lock_irqsave(&isys->power_lock, flags);
 	isys->power = 0;
 	spin_unlock_irqrestore(&isys->power_lock, flags);
 
-	mutex_lock(&isys->mutex);
-	isys->need_reset = false;
-	mutex_unlock(&isys->mutex);
-
 	isys->phy_termcal_val = 0;
 	cpu_latency_qos_update_request(&isys->pm_qos, PM_QOS_DEFAULT_VALUE);
 
@@ -845,7 +884,7 @@ static int isys_runtime_pm_suspend(struct device *dev)
 
 	ipu6_mmu_hw_cleanup(adev->mmu);
 
-	return 0;
+	return ret;
 }
 
 static int isys_suspend(struct device *dev)
diff --git a/drivers/media/pci/intel/ipu6/ipu6-isys.h b/drivers/media/pci/intel/ipu6/ipu6-isys.h
index 157b27a8eb6d..c8f9059bc83e 100644
--- a/drivers/media/pci/intel/ipu6/ipu6-isys.h
+++ b/drivers/media/pci/intel/ipu6/ipu6-isys.h
@@ -87,7 +87,6 @@ struct sensor_async_sd {
  *         or optional external library private pointer
  * @phy_termcal_val: the termination calibration value, only used for DWC PHY
  * @need_reset: Isys requires d0i0->i3 transition
- * @ref_count: total number of callers fw open
  * @mutex: serialise access isys video open/release related operations
  * @stream_mutex: serialise stream start and stop, queueing requests
  * @pdata: platform data pointer
@@ -111,7 +110,6 @@ struct ipu6_isys {
 	bool icache_prefetch;
 	bool csi2_cse_ipc_not_supported;
 	bool iwake_watermark_enabled;
-	unsigned int ref_count;
 	unsigned int sensor_type;
 
 	struct mutex mutex;
-- 
2.47.3


^ permalink raw reply related	[flat|nested] 88+ messages in thread

* [PATCH v12 85/86] media: ipu6: Don't track power status, rely on runtime PM
  2026-04-09 20:13 [PATCH v12 00/86] Generic line based metadata support, internal pads Sakari Ailus
                   ` (83 preceding siblings ...)
  2026-04-09 20:14 ` [PATCH v12 84/86] media: ipu6: Move firmware init/cleanup to RPM callbacks Sakari Ailus
@ 2026-04-09 20:15 ` Sakari Ailus
  2026-04-09 20:15 ` [PATCH v12 86/86] media: bcm2835-unicam: Support generic raw formats Sakari Ailus
  85 siblings, 0 replies; 88+ messages in thread
From: Sakari Ailus @ 2026-04-09 20:15 UTC (permalink / raw)
  To: linux-media
  Cc: hans, laurent.pinchart, Prabhakar, Kate Hsuan, Dave Stevenson,
	Tommaso Merciai, Benjamin Mugnier, Sylvain Petinot,
	Christophe JAILLET, Julien Massot, Naushir Patuck, Stefan Klug,
	Mirela Rabulea, André Apitzsch, Heimir Thor Sverrisson,
	Kieran Bingham, Mehdi Djait, Ricardo Ribalda Delgado,
	Hans de Goede, Jacopo Mondi, Tomi Valkeinen, David Plowman,
	Yu, Ong Hock, Ng, Khai Wen, Jai Luthra, Rishikesh Donadkar

Rely on runtime PM suspending and resuming the device and so remove
tracking of power state. Also remove the power_lock spinlock that
serialised firmware initialisation and cleanup with the ISR. This is no
longer necessary as the ISR now runs when the device is in RPM_ACTIVE
state.

Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
---
 drivers/media/pci/intel/ipu6/ipu6-fw-isys.c |  5 ----
 drivers/media/pci/intel/ipu6/ipu6-isys.c    | 31 ++++-----------------
 drivers/media/pci/intel/ipu6/ipu6-isys.h    |  5 ----
 3 files changed, 6 insertions(+), 35 deletions(-)

diff --git a/drivers/media/pci/intel/ipu6/ipu6-fw-isys.c b/drivers/media/pci/intel/ipu6/ipu6-fw-isys.c
index 62ed92ff1d30..e239905f899c 100644
--- a/drivers/media/pci/intel/ipu6/ipu6-fw-isys.c
+++ b/drivers/media/pci/intel/ipu6/ipu6-fw-isys.c
@@ -137,7 +137,6 @@ int ipu6_fw_isys_close(struct ipu6_isys *isys)
 {
 	struct device *dev = &isys->adev->auxdev.dev;
 	int retry = IPU6_ISYS_CLOSE_RETRY;
-	unsigned long flags;
 	void *fwcom;
 	int ret;
 
@@ -147,11 +146,9 @@ int ipu6_fw_isys_close(struct ipu6_isys *isys)
 	 * to SP icache.
 	 * spinlock to wait the interrupt handler to be finished
 	 */
-	spin_lock_irqsave(&isys->power_lock, flags);
 	ret = ipu6_fw_com_close(isys->fwcom);
 	fwcom = isys->fwcom;
 	isys->fwcom = NULL;
-	spin_unlock_irqrestore(&isys->power_lock, flags);
 	if (ret)
 		dev_err(dev, "Device close failure: %d\n", ret);
 
@@ -164,9 +161,7 @@ int ipu6_fw_isys_close(struct ipu6_isys *isys)
 
 	if (ret) {
 		dev_err(dev, "Device release time out %d\n", ret);
-		spin_lock_irqsave(&isys->power_lock, flags);
 		isys->fwcom = fwcom;
-		spin_unlock_irqrestore(&isys->power_lock, flags);
 	}
 
 	return ret;
diff --git a/drivers/media/pci/intel/ipu6/ipu6-isys.c b/drivers/media/pci/intel/ipu6/ipu6-isys.c
index 8258a6dbf43c..eac0d696754c 100644
--- a/drivers/media/pci/intel/ipu6/ipu6-isys.c
+++ b/drivers/media/pci/intel/ipu6/ipu6-isys.c
@@ -345,12 +345,11 @@ static irqreturn_t isys_isr(struct ipu6_bus_device *adev)
 	void __iomem *base = isys->pdata->base;
 	u32 status_sw, status_csi;
 	u32 ctrl0_status, ctrl0_clear;
+	int pm_status;
 
-	spin_lock(&isys->power_lock);
-	if (!isys->power) {
-		spin_unlock(&isys->power_lock);
-		return IRQ_NONE;
-	}
+	pm_status = pm_runtime_get_if_active(&adev->auxdev.dev);
+	if (!pm_status)
+		return 0;
 
 	ctrl0_status = isys->pdata->ipdata->csi2.ctrl0_irq_status;
 	ctrl0_clear = isys->pdata->ipdata->csi2.ctrl0_irq_clear;
@@ -395,7 +394,8 @@ static irqreturn_t isys_isr(struct ipu6_bus_device *adev)
 
 	writel(ISYS_UNISPART_IRQS, base + IPU6_REG_ISYS_UNISPART_IRQ_MASK);
 
-	spin_unlock(&isys->power_lock);
+	if (pm_status > 0)
+		pm_runtime_put(&adev->auxdev.dev);
 
 	return IRQ_HANDLED;
 }
@@ -801,7 +801,6 @@ static int isys_runtime_pm_resume(struct device *dev)
 	struct ipu6_isys *isys = ipu6_bus_get_drvdata(adev);
 	const struct ipu6_isys_internal_pdata *ipdata = isys->pdata->ipdata;
 	struct ipu6_device *isp = adev->isp;
-	unsigned long flags;
 	int ret;
 
 	ret = ipu6_mmu_hw_init(adev->mmu);
@@ -814,10 +813,6 @@ static int isys_runtime_pm_resume(struct device *dev)
 	if (ret)
 		goto err_mmu_hw_cleanup;
 
-	spin_lock_irqsave(&isys->power_lock, flags);
-	isys->power = 1;
-	spin_unlock_irqrestore(&isys->power_lock, flags);
-
 	isys_setup_hw(isys);
 
 	set_iwake_ltrdid(isys, 0, 0, LTR_ISYS_ON);
@@ -845,10 +840,6 @@ static int isys_runtime_pm_resume(struct device *dev)
 	if (!ret)
 		return 0;
 
-	spin_lock_irqsave(&isys->power_lock, flags);
-	isys->power = 0;
-	spin_unlock_irqrestore(&isys->power_lock, flags);
-
 	isys->phy_termcal_val = 0;
 	cpu_latency_qos_update_request(&isys->pm_qos, PM_QOS_DEFAULT_VALUE);
 
@@ -864,7 +855,6 @@ static int isys_runtime_pm_suspend(struct device *dev)
 {
 	struct ipu6_bus_device *adev = to_ipu6_bus_device(dev);
 	struct ipu6_isys *isys = dev_get_drvdata(dev);
-	unsigned long flags;
 	int ret = 0;
 
 	ipu6_fw_isys_close(isys);
@@ -873,10 +863,6 @@ static int isys_runtime_pm_suspend(struct device *dev)
 		ret = -EIO;
 	}
 
-	spin_lock_irqsave(&isys->power_lock, flags);
-	isys->power = 0;
-	spin_unlock_irqrestore(&isys->power_lock, flags);
-
 	isys->phy_termcal_val = 0;
 	cpu_latency_qos_update_request(&isys->pm_qos, PM_QOS_DEFAULT_VALUE);
 
@@ -1053,8 +1039,6 @@ static int isys_probe(struct auxiliary_device *auxdev,
 	isys->sensor_type = isys->pdata->ipdata->sensor_type_start;
 
 	spin_lock_init(&isys->streams_lock);
-	spin_lock_init(&isys->power_lock);
-	isys->power = 0;
 	isys->phy_termcal_val = 0;
 
 	mutex_init(&isys->mutex);
@@ -1189,9 +1173,6 @@ static int isys_isr_one(struct ipu6_bus_device *adev)
 	u32 index;
 	u64 ts;
 
-	if (!isys->fwcom)
-		return 1;
-
 	resp = ipu6_fw_isys_get_resp(isys->fwcom, IPU6_BASE_MSG_RECV_QUEUES);
 	if (!resp)
 		return 1;
diff --git a/drivers/media/pci/intel/ipu6/ipu6-isys.h b/drivers/media/pci/intel/ipu6/ipu6-isys.h
index c8f9059bc83e..8755d80e8fcf 100644
--- a/drivers/media/pci/intel/ipu6/ipu6-isys.h
+++ b/drivers/media/pci/intel/ipu6/ipu6-isys.h
@@ -77,9 +77,6 @@ struct sensor_async_sd {
  * @media_dev: Media device
  * @v4l2_dev: V4L2 device
  * @adev: ISYS bus device
- * @power: Is ISYS powered on or not?
- * @isr_bits: Which bits does the ISR handle?
- * @power_lock: Serialise access to power (power state in general)
  * @csi2_rx_ctrl_cached: cached shared value between all CSI2 receivers
  * @streams_lock: serialise access to streams
  * @streams: streams per firmware stream ID
@@ -97,8 +94,6 @@ struct ipu6_isys {
 	struct v4l2_device v4l2_dev;
 	struct ipu6_bus_device *adev;
 
-	int power;
-	spinlock_t power_lock;
 	u32 isr_csi2_bits;
 	u32 csi2_rx_ctrl_cached;
 	spinlock_t streams_lock;
-- 
2.47.3


^ permalink raw reply related	[flat|nested] 88+ messages in thread

* [PATCH v12 86/86] media: bcm2835-unicam: Support generic raw formats
  2026-04-09 20:13 [PATCH v12 00/86] Generic line based metadata support, internal pads Sakari Ailus
                   ` (84 preceding siblings ...)
  2026-04-09 20:15 ` [PATCH v12 85/86] media: ipu6: Don't track power status, rely on runtime PM Sakari Ailus
@ 2026-04-09 20:15 ` Sakari Ailus
  85 siblings, 0 replies; 88+ messages in thread
From: Sakari Ailus @ 2026-04-09 20:15 UTC (permalink / raw)
  To: linux-media
  Cc: hans, laurent.pinchart, Prabhakar, Kate Hsuan, Dave Stevenson,
	Tommaso Merciai, Benjamin Mugnier, Sylvain Petinot,
	Christophe JAILLET, Julien Massot, Naushir Patuck, Stefan Klug,
	Mirela Rabulea, André Apitzsch, Heimir Thor Sverrisson,
	Kieran Bingham, Mehdi Djait, Ricardo Ribalda Delgado,
	Hans de Goede, Jacopo Mondi, Tomi Valkeinen, David Plowman,
	Yu, Ong Hock, Ng, Khai Wen, Jai Luthra, Rishikesh Donadkar

Add support for 8-bit unpacked and 10-, 12- and 14-bit packed generic raw
formats.

Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
---
 .../media/platform/broadcom/bcm2835-unicam.c  | 27 +++++++++++++++++++
 1 file changed, 27 insertions(+)

diff --git a/drivers/media/platform/broadcom/bcm2835-unicam.c b/drivers/media/platform/broadcom/bcm2835-unicam.c
index 38afdf5a32ba..74a6c4820a67 100644
--- a/drivers/media/platform/broadcom/bcm2835-unicam.c
+++ b/drivers/media/platform/broadcom/bcm2835-unicam.c
@@ -452,6 +452,33 @@ static const struct unicam_format_info unicam_image_formats[] = {
 		.csi_dt		= MIPI_CSI2_DT_RAW14,
 		.unpack		= UNICAM_PUM_UNPACK14,
 	}, {
+	/* Generic raw formats */
+		.fourcc		= V4L2_PIX_FMT_RAW_8,
+		.code		= MEDIA_BUS_FMT_RAW_8,
+		.depth		= 8,
+		.csi_dt		= MIPI_CSI2_DT_RAW8,
+	}, {
+		.fourcc		= V4L2_PIX_FMT_RAW_CSI2_10,
+		.unpacked_fourcc = V4L2_PIX_FMT_RAW_16,
+		.code		= MEDIA_BUS_FMT_RAW_10,
+		.depth		= 10,
+		.csi_dt		= MIPI_CSI2_DT_RAW10,
+		.unpack		= UNICAM_PUM_UNPACK10,
+	}, {
+		.fourcc		= V4L2_PIX_FMT_RAW_CSI2_12,
+		.unpacked_fourcc = V4L2_PIX_FMT_RAW_16,
+		.code		= MEDIA_BUS_FMT_RAW_12,
+		.depth		= 12,
+		.csi_dt		= MIPI_CSI2_DT_RAW12,
+		.unpack		= UNICAM_PUM_UNPACK12,
+	}, {
+		.fourcc		= V4L2_PIX_FMT_RAW_CSI2_14,
+		.unpacked_fourcc = V4L2_PIX_FMT_RAW_16,
+		.code		= MEDIA_BUS_FMT_RAW_14,
+		.depth		= 14,
+		.csi_dt		= MIPI_CSI2_DT_RAW14,
+		.unpack		= UNICAM_PUM_UNPACK14,
+	}, {
 	/* 16 bit Bayer formats could be supported. */
 
 	/* Greyscale formats */
-- 
2.47.3


^ permalink raw reply related	[flat|nested] 88+ messages in thread

* Re: [PATCH v12 27/86] media: uapi: Add V4L2_CID_BINNING control for binning configuration
  2026-04-09 20:14 ` [PATCH v12 27/86] media: uapi: Add V4L2_CID_BINNING control for binning configuration Sakari Ailus
@ 2026-04-14 15:55   ` Jacopo Mondi
  0 siblings, 0 replies; 88+ messages in thread
From: Jacopo Mondi @ 2026-04-14 15:55 UTC (permalink / raw)
  To: Sakari Ailus
  Cc: linux-media, hans, laurent.pinchart, Prabhakar, Kate Hsuan,
	Dave Stevenson, Tommaso Merciai, Benjamin Mugnier,
	Sylvain Petinot, Christophe JAILLET, Julien Massot,
	Naushir Patuck, Stefan Klug, Mirela Rabulea, André Apitzsch,
	Heimir Thor Sverrisson, Kieran Bingham, Mehdi Djait,
	Ricardo Ribalda Delgado, Hans de Goede, Jacopo Mondi,
	Tomi Valkeinen, David Plowman, Yu, Ong Hock, Ng, Khai Wen,
	Jai Luthra, Rishikesh Donadkar

On Thu, Apr 09, 2026 at 11:14:02PM +0300, Sakari Ailus wrote:
> Add V4L2_CID_BINNING control for configuring binning and enumerating a

Seems like the control is now named V4L2_CID_BINNING_FACTORS ?
Also applies to the patch subject

Have I missed something ?
$ git grep CID_BINNING include/
include/uapi/linux/v4l2-controls.h:#define V4L2_CID_BINNING_FACTORS             (V4L2_CID_IMAGE_SOURCE_CLASS_BASE + 13)

> camera sensor's binning capabilities. The control combines horizontal and
> vertical binning into a single control as the two are generally related.
>
> New drivers should use this control to configure binning.
>
> Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
> Reviewed-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
> Reviewed-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
> ---
>  .../media/drivers/camera-sensor.rst           | 12 ++++++++
>  .../media/v4l/ext-ctrls-image-source.rst      | 30 +++++++++++++++++++
>  drivers/media/v4l2-core/v4l2-ctrls-defs.c     |  2 ++
>  include/uapi/linux/v4l2-controls.h            |  2 ++
>  4 files changed, 46 insertions(+)
>
> diff --git a/Documentation/userspace-api/media/drivers/camera-sensor.rst b/Documentation/userspace-api/media/drivers/camera-sensor.rst
> index d8ba809486c5..12f075379bc8 100644
> --- a/Documentation/userspace-api/media/drivers/camera-sensor.rst
> +++ b/Documentation/userspace-api/media/drivers/camera-sensor.rst
> @@ -120,6 +120,18 @@ values programmed by the register sequences. The default values of these
>  controls shall be 0 (disabled). Especially these controls shall not be inverted,
>  independently of the sensor's mounting rotation.
>
> +Binning
> +-------
> +
> +Binning has traditionally been configured using :ref:`the compose selection
> +rectangle <v4l2-selection-targets-table>`. The :ref:`V4L2_CID_BINNING

This needs to be updated as well ?

> +<image_source_control_binning_factors>` control is also available for binning
> +configuration and users should use it when it's available. Drivers supporting
> +the control shall also support the compose rectangle, albeit the rectangle may
> +be read-only when the control is present.
> +
> +Binning isn't affected by flipping.
> +
>  .. _media_using_camera_sensor_drivers_embedded_data:
>
>  Embedded data
> diff --git a/Documentation/userspace-api/media/v4l/ext-ctrls-image-source.rst b/Documentation/userspace-api/media/v4l/ext-ctrls-image-source.rst
> index 490cd16186cd..0ef76b02a6e1 100644
> --- a/Documentation/userspace-api/media/v4l/ext-ctrls-image-source.rst
> +++ b/Documentation/userspace-api/media/v4l/ext-ctrls-image-source.rst
> @@ -160,3 +160,33 @@ Image Source Control IDs
>      interface for metadata streams. The control is used in conjunction with
>      :ref:`generic metadata formats <media-bus-format-generic-meta>` formats to
>      specify the layout of the data.
> +
> +.. _image_source_control_binning_factors:
> +
> +``V4L2_CID_BINNING_FACTORS (integer menu)``
> +
> +    This control determines horizontal and vertical binning factors. Binning
> +    combines several horizontal, vertical or both pixel values into a single
> +    pixel. It is a way to scale an image. Binning typically produces fairly good
> +    quality output.
> +
> +    Determines both horizontal and vertical binning factors for a camera
> +    sensor. The values are encoded in the following way:
> +
> +.. flat-table::
> +    :header-rows:  1
> +    :stub-columns: 0
> +
> +    * - Bits
> +      - Synopsis
> +    * - 48--63
> +      - Horizontal binning numerator.
> +    * - 32--47
> +      - Horizontal binning denominator.
> +    * - 16--31
> +      - Vertical binning numerator.
> +    * - 0--15
> +      - Vertical binning denominator.
> +
> +For instance, a value of ``0x0001000300020003`` indicates binning by 3
> +(horizontally) * 3/2 (vertically).
> diff --git a/drivers/media/v4l2-core/v4l2-ctrls-defs.c b/drivers/media/v4l2-core/v4l2-ctrls-defs.c
> index 4618252d24f2..fee343667b69 100644
> --- a/drivers/media/v4l2-core/v4l2-ctrls-defs.c
> +++ b/drivers/media/v4l2-core/v4l2-ctrls-defs.c
> @@ -1160,6 +1160,7 @@ const char *v4l2_ctrl_get_name(u32 id)
>  	case V4L2_CID_CFA_PATTERN:		return "Color Filter Array Pattern";
>  	case V4L2_CID_CFA_PATTERN_FLIP:		return "CFA Pattern Flip";
>  	case V4L2_CID_METADATA_LAYOUT:		return "Metadata Layout";
> +	case V4L2_CID_BINNING_FACTORS:		return "Binning Factors";
>
>  	/* Image processing controls */
>  	/* Keep the order of the 'case's the same as in v4l2-controls.h! */
> @@ -1438,6 +1439,7 @@ void v4l2_ctrl_fill(u32 id, const char **name, enum v4l2_ctrl_type *type,
>  	case V4L2_CID_HDR_SENSOR_MODE:
>  		*type = V4L2_CTRL_TYPE_MENU;
>  		break;
> +	case V4L2_CID_BINNING_FACTORS:
>  	case V4L2_CID_LINK_FREQ:
>  		*type = V4L2_CTRL_TYPE_INTEGER_MENU;
>  		break;
> diff --git a/include/uapi/linux/v4l2-controls.h b/include/uapi/linux/v4l2-controls.h
> index 1bf6d298e3c4..5496b1664432 100644
> --- a/include/uapi/linux/v4l2-controls.h
> +++ b/include/uapi/linux/v4l2-controls.h
> @@ -1249,6 +1249,8 @@ enum v4l2_jpeg_chroma_subsampling {
>
>  #define V4L2_CID_METADATA_LAYOUT		(V4L2_CID_IMAGE_SOURCE_CLASS_BASE + 12)
>
> +#define V4L2_CID_BINNING_FACTORS		(V4L2_CID_IMAGE_SOURCE_CLASS_BASE + 13)
> +
>  /* Image processing controls */
>
>  #define V4L2_CID_IMAGE_PROC_CLASS_BASE		(V4L2_CTRL_CLASS_IMAGE_PROC | 0x900)
> --
> 2.47.3
>
>

^ permalink raw reply	[flat|nested] 88+ messages in thread

end of thread, other threads:[~2026-04-14 15:55 UTC | newest]

Thread overview: 88+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-04-09 20:13 [PATCH v12 00/86] Generic line based metadata support, internal pads Sakari Ailus
2026-04-09 20:13 ` [PATCH v12 01/86] media: mc: Add INTERNAL pad flag Sakari Ailus
2026-04-09 20:13 ` [PATCH v12 02/86] media: uapi: Add generic CSI-2 raw pixelformats Sakari Ailus
2026-04-09 20:13 ` [PATCH v12 03/86] media: uapi: Add new media bus codes for generic raw formats Sakari Ailus
2026-04-09 20:13 ` [PATCH v12 04/86] media: uapi: Add V4L2_CID_CONFIG_MODEL control Sakari Ailus
2026-04-09 20:13 ` [PATCH v12 05/86] media: uapi: Add V4L2_CID_CFA_PATTERN for describing color patterns Sakari Ailus
2026-04-09 20:13 ` [PATCH v12 06/86] media: Documentation: Reference CFA pattern control in pixelformat docs Sakari Ailus
2026-04-09 20:13 ` [PATCH v12 07/86] media: Documentation: Reference CFA_PATTERN control in raw mbus docs Sakari Ailus
2026-04-09 20:13 ` [PATCH v12 08/86] media: v4l: uapi: Add a control for color pattern flipping effect Sakari Ailus
2026-04-09 20:13 ` [PATCH v12 09/86] media: Documentation: Reference flipping controls in raw format docs Sakari Ailus
2026-04-09 20:13 ` [PATCH v12 10/86] media: Documentation: Document raw mbus codes and CFA for cameras Sakari Ailus
2026-04-09 20:13 ` [PATCH v12 11/86] media: uapi: Add V4L2_CID_METADATA_LAYOUT control Sakari Ailus
2026-04-09 20:13 ` [PATCH v12 12/86] media: Documentation: Refer to metadata layout in metadata documentation Sakari Ailus
2026-04-09 20:13 ` [PATCH v12 13/86] media: Documentation: v4l: Document internal sink pads Sakari Ailus
2026-04-09 20:13 ` [PATCH v12 14/86] media: Documentation: Document embedded data guidelines for camera sensors Sakari Ailus
2026-04-09 20:13 ` [PATCH v12 15/86] media: Documentation: Document non-CCS use of CCS embedded data layout Sakari Ailus
2026-04-09 20:13 ` [PATCH v12 16/86] media: uapi: Correct generic CSI-2 metadata format 4cc Sakari Ailus
2026-04-09 20:13 ` [PATCH v12 17/86] Revert "media: uapi: v4l: Don't expose generic metadata formats to userspace" Sakari Ailus
2026-04-09 20:13 ` [PATCH v12 18/86] media: v4l: Add V4L2_SUBDEV_ROUTE_FL_IMMUTABLE sub-device routing flag Sakari Ailus
2026-04-09 20:13 ` [PATCH v12 19/86] media: v4l: Add V4L2_SUBDEV_ROUTE_FL_STATIC " Sakari Ailus
2026-04-09 20:13 ` [PATCH v12 20/86] media: Documentation: There are either immutable or mutable routes Sakari Ailus
2026-04-09 20:13 ` [PATCH v12 21/86] media: Documentation: Document IMMUTABLE and STATIC route flags Sakari Ailus
2026-04-09 20:13 ` [PATCH v12 22/86] media: Documentation: Add subdev configuration models, raw sensor model Sakari Ailus
2026-04-09 20:13 ` [PATCH v12 23/86] media: v4l2-subdev: Prevent accessing internal pads without STREAMS cap Sakari Ailus
2026-04-09 20:13 ` [PATCH v12 24/86] media: Documentation: Add scaling and post-scaler crop for common raw Sakari Ailus
2026-04-09 20:14 ` [PATCH v12 25/86] media: uapi: Add MIPI CCS configuration model Sakari Ailus
2026-04-09 20:14 ` [PATCH v12 26/86] media: uapi: Add V4L2_SUBDEV_CLIENT_CAP_COMMON_RAW_SENSOR Sakari Ailus
2026-04-09 20:14 ` [PATCH v12 27/86] media: uapi: Add V4L2_CID_BINNING control for binning configuration Sakari Ailus
2026-04-14 15:55   ` Jacopo Mondi
2026-04-09 20:14 ` [PATCH v12 28/86] media: uapi: Add controls for sub-sampling configuration Sakari Ailus
2026-04-09 20:14 ` [PATCH v12 29/86] media: v4l2-mc: Add v4l2_subdev_sensor_fll_llp_set() Sakari Ailus
2026-04-09 20:14 ` [PATCH v12 30/86] media: Documentation: Add binning and sub-sampling controls Sakari Ailus
2026-04-09 20:14 ` [PATCH v12 31/86] media: v4l2-subdev: Set STATIC route flag if IMMUTABLE route flag is set Sakari Ailus
2026-04-09 20:14 ` [PATCH v12 32/86] media: uapi: v4l: subdev: Enable streams API Sakari Ailus
2026-04-09 20:14 ` [PATCH v12 33/86] media: uapi: Add new controls for camera sensor FLL and LLP Sakari Ailus
2026-04-09 20:14 ` [PATCH v12 34/86] media: uapi: Add binning factor helper macros Sakari Ailus
2026-04-09 20:14 ` [PATCH v12 35/86] media: Documentation: Document frame controls for common raw sensor model Sakari Ailus
2026-04-09 20:14 ` [PATCH v12 36/86] media: v4l2-ctrl: Improve v4l2_ctrl_g_ctrl{,int64} documentation Sakari Ailus
2026-04-09 20:14 ` [PATCH v12 37/86] media: Documentation: Add sub-device internal pads example Sakari Ailus
2026-04-09 20:14 ` [PATCH v12 38/86] media: Documentation: Document streaming behaviour for common raw cameras Sakari Ailus
2026-04-09 20:14 ` [PATCH v12 39/86] media: Documentation: Add a note on Bayer raw mbus codes Sakari Ailus
2026-04-09 20:14 ` [PATCH v12 40/86] media: v4l2-subdev: Add generic raw formats to v4l2_subdev_get_frame_desc Sakari Ailus
2026-04-09 20:14 ` [PATCH v12 41/86] media: uapi: Add generic CSI-2 raw pixelformats for 16, 20, 24 and 28 bpp Sakari Ailus
2026-04-09 20:14 ` [PATCH v12 42/86] media: uapi: Add more media bus codes for generic raw formats Sakari Ailus
2026-04-09 20:14 ` [PATCH v12 43/86] media: uapi: ccs: Add metadata layout for MIPI CCS embedded data Sakari Ailus
2026-04-09 20:14 ` [PATCH v12 44/86] media: ccs: Add support for generic raw mbus codes Sakari Ailus
2026-04-09 20:14 ` [PATCH v12 45/86] media: ccs: Add support for embedded data stream Sakari Ailus
2026-04-09 20:14 ` [PATCH v12 46/86] media: Documentation: ccs: Document routing Sakari Ailus
2026-04-09 20:14 ` [PATCH v12 47/86] media: ccs: Add IMMUTABLE and STATIC route flags Sakari Ailus
2026-04-09 20:14 ` [PATCH v12 48/86] media: uapi: Add metadata layout for ov2740 embedded data Sakari Ailus
2026-04-09 20:14 ` [PATCH v12 49/86] media: ov2740: Add support for " Sakari Ailus
2026-04-09 20:14 ` [PATCH v12 50/86] media: ov2740: Add support for generic raw formats Sakari Ailus
2026-04-09 20:14 ` [PATCH v12 51/86] media: ov2740: Add metadata layout control Sakari Ailus
2026-04-09 20:14 ` [PATCH v12 52/86] media: ov2740: Add support for G_SELECTION IOCTL Sakari Ailus
2026-04-09 20:14 ` [PATCH v12 53/86] media: ov2740: Add support for FLL and LLP controls Sakari Ailus
2026-04-09 20:14 ` [PATCH v12 54/86] media: ov2740: Signal common raw sensor model support Sakari Ailus
2026-04-09 20:14 ` [PATCH v12 55/86] media: ov2740: Add IMMUTABLE and STATIC route flags Sakari Ailus
2026-04-09 20:14 ` [PATCH v12 56/86] media: imx219: Add internal pads, routes for common raw sensor model Sakari Ailus
2026-04-09 20:14 ` [PATCH v12 57/86] media: imx219: Add image stream Sakari Ailus
2026-04-09 20:14 ` [PATCH v12 58/86] media: imx219: Report internal routes to userspace Sakari Ailus
2026-04-09 20:14 ` [PATCH v12 59/86] media: imx219: Report streams using frame descriptors Sakari Ailus
2026-04-09 20:14 ` [PATCH v12 60/86] media: imx219: Add embedded data support Sakari Ailus
2026-04-09 20:14 ` [PATCH v12 61/86] media: imx219: Add support for generic raw formats Sakari Ailus
2026-04-09 20:14 ` [PATCH v12 62/86] media: imx219: Add V4L2_CID_BINNING_FACTORS Sakari Ailus
2026-04-09 20:14 ` [PATCH v12 63/86] media: imx219: Allow configuring cropping and binning through CRSM Sakari Ailus
2026-04-09 20:14 ` [PATCH v12 64/86] media: imx219: Support LINE_LENGTH_PIXELS and FRAME_LENGTH_LINES controls Sakari Ailus
2026-04-09 20:14 ` [PATCH v12 65/86] media: ipu6: Add support for raw CFA-agnostic formats Sakari Ailus
2026-04-09 20:14 ` [PATCH v12 66/86] media: ipu6: Use VALIDATE_LATE flag to postpone V4L2 format validation Sakari Ailus
2026-04-09 20:14 ` [PATCH v12 67/86] media: ipu6: Move streaming control to CSI-2 receiver driver Sakari Ailus
2026-04-09 20:14 ` [PATCH v12 68/86] media: ipu6: Stream number on CSI-2 receiver source pads is always 0 Sakari Ailus
2026-04-09 20:14 ` [PATCH v12 69/86] media: ipu6: Rename misnamed out_free_watermark label in video init Sakari Ailus
2026-04-09 20:14 ` [PATCH v12 70/86] media: ipu6: Always request a capture ack Sakari Ailus
2026-04-09 20:14 ` [PATCH v12 71/86] media: ipu6: Clean up link frequency calculation Sakari Ailus
2026-04-09 20:14 ` [PATCH v12 72/86] media: ipu6: Get watermark configuration directly from ipdata Sakari Ailus
2026-04-09 20:14 ` [PATCH v12 73/86] media: ipu6: Collect IPU streams into CSI-2 receiver sub-device context Sakari Ailus
2026-04-09 20:14 ` [PATCH v12 74/86] media: ipu6: Start streaming once all queues have started, stop when not Sakari Ailus
2026-04-09 20:14 ` [PATCH v12 75/86] media: ipu6: Add lockdep checks for CSI-2 streaming enable and disable Sakari Ailus
2026-04-09 20:14 ` [PATCH v12 76/86] media: ipu6: Remove nr_queues and nr_streaming fields in ipu6_isys_stream Sakari Ailus
2026-04-09 20:14 ` [PATCH v12 77/86] media: ipu6: Collect enabled stream IDs Sakari Ailus
2026-04-09 20:14 ` [PATCH v12 78/86] media: ipu6: Avoid accessing av->streams before streaming Sakari Ailus
2026-04-09 20:14 ` [PATCH v12 79/86] media: ipu6: Rework watermark calculation Sakari Ailus
2026-04-09 20:14 ` [PATCH v12 80/86] media: ipu6: Rework watermark setting Sakari Ailus
2026-04-09 20:14 ` [PATCH v12 81/86] media: ipu6: Bridge the gap between streams in V4L2 and IPU6 firmware Sakari Ailus
2026-04-09 20:14 ` [PATCH v12 82/86] media: ipu6: Drop {get,put}_streams_opened() Sakari Ailus
2026-04-09 20:14 ` [PATCH v12 83/86] media: ipu6: Serialise access to stream pointers by isys stream_lock Sakari Ailus
2026-04-09 20:14 ` [PATCH v12 84/86] media: ipu6: Move firmware init/cleanup to RPM callbacks Sakari Ailus
2026-04-09 20:15 ` [PATCH v12 85/86] media: ipu6: Don't track power status, rely on runtime PM Sakari Ailus
2026-04-09 20:15 ` [PATCH v12 86/86] media: bcm2835-unicam: Support generic raw formats Sakari Ailus

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox