[GIT PULL for v6.19] media updates

-----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCgAdFiEE+QmuaPwR3wnBdVwACF8+vY7k4RUFAmktWxIACgkQCF8+vY7k
 4RXGuQ/9EhcMfiHQ8fu1/AIPDZl5WGMNkHaBi84Y6Q9CroxdZwNsX8NQtk0caVyQ
 nDyshL3APBTeMOiAxxxkIe/LMNBJMpah5Dprg3Lk/G6+4soEDHhD5+PRJFwGhgYQ
 qa6Z8TpABxvGPNBVhyLgPnPznFsiRc9HzXYxQc+7mQENzioUWaRW93510Jq7vutl
 wmkBI5TQVGOU3wlc4tDTpkQcMy2CMZygRwUXcDXfw3sC+OxWUSB6EsDKoQ6Y30s7
 VqRibO48eQK1k9L39xGs14yEZeIyj0sBRXZ2cCvdQWpZUoDy4UERLepqpw2iF4CU
 Cr15VEp7cdB8RF0d/Y3AQBS08KXsyiR4x1TfGqiCllfP0DjX+AXA0aW8m1ofAAhq
 CJ8wR13oOVsDWeYBO39nYp4SG5y9B9BslXXFS6HCN52txlTL10+W1kpSJnzGzMo9
 oBXAD0TNyko+MVB9OBMkdQB8h8UDA5Y4jDR1OLwWGCGhO6TTYcFbERdy1gvLsz76
 ARsC4uF/EU5rS92UvcE6FPp6E0RRXCuOUFa9vqBO8XiL1Z+vft5IUIeqlj5v4dKf
 67WwXmmOcm5e59l9m6lf4qkYnILgQQr5rFd20e1F2QpFl1QrncEVJJdDU2+akD8c
 h/n6FhrkFrGXFzeqfmd/ZMvF8uU3u5j/fyt5wNEkc28fVz7WPxw=
 =y7ej
 -----END PGP SIGNATURE-----

Merge tag 'media/v6.19-1' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media

Pull media updates from Mauro Carvalho Chehab:

 - New drivers:
    - Mali-C55 ISP
    - Rockchip VICAP (RKCIF)
    - RKVDEC HEVC Decoder
    - Renesas RZV2H IVC
    - Sony IMX111 CMOS sensor driver

 - Removed STi C8SECTPFE Driver

 - Added a V4L2 ISP generic framework

 - Usual set of cleanup, fixes and driver improvements

* tag 'media/v6.19-1' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media: (249 commits)
  media: rockchip: rkcif: add support for rk3568 vicap mipi capture
  media: rockchip: rkcif: add support for rk3568 vicap dvp capture
  media: rockchip: rkcif: add support for px30 vip dvp capture
  media: rockchip: rkcif: add abstraction for dma blocks
  media: rockchip: rkcif: add abstraction for interface and crop blocks
  media: rockchip: add driver for the rockchip camera interface
  media: dt-bindings: add rockchip rk3568 vicap
  media: dt-bindings: add rockchip px30 vip
  media: dt-bindings: video-interfaces: add defines for sampling modes
  Documentation: admin-guide: media: add rockchip camera interface
  media: mali-c55: Mark pm handlers as __maybe_unused
  media: mali-c55: Assert ISP blocks size correctness
  media: v4l2-isp: Rename block_info to block_type_info
  MAINTAINERS: Add entry for rzv2h-ivc driver
  media: platform: Add Renesas Input Video Control block driver
  dt-bindings: media: Add bindings for the RZ/V2H(P) IVC block
  Documentation: media: mali-c55: Document the mali-c55 parameter setting
  media: platform: Add mali-c55 parameters video node
  media: uapi: Add parameters structs to mali-c55-config.h
  media: mali-c55: Add image formats for Mali-C55 parameters buffer
  ...
This commit is contained in:
Linus Torvalds 2025-12-04 08:15:19 -08:00
commit d7aa60d966
310 changed files with 22135 additions and 4828 deletions

View File

@ -0,0 +1,19 @@
digraph board {
rankdir=TB
n00000001 [label="{{} | mali-c55 tpg\n/dev/v4l-subdev0 | {<port0> 0}}", shape=Mrecord, style=filled, fillcolor=green]
n00000001:port0 -> n00000003:port0 [style=dashed]
n00000003 [label="{{<port0> 0} | mali-c55 isp\n/dev/v4l-subdev1 | {<port1> 1 | <port2> 2}}", shape=Mrecord, style=filled, fillcolor=green]
n00000003:port1 -> n00000007:port0 [style=bold]
n00000003:port2 -> n00000007:port2 [style=bold]
n00000003:port1 -> n0000000b:port0 [style=bold]
n00000007 [label="{{<port0> 0 | <port2> 2} | mali-c55 resizer fr\n/dev/v4l-subdev2 | {<port1> 1}}", shape=Mrecord, style=filled, fillcolor=green]
n00000007:port1 -> n0000000e [style=bold]
n0000000b [label="{{<port0> 0} | mali-c55 resizer ds\n/dev/v4l-subdev3 | {<port1> 1}}", shape=Mrecord, style=filled, fillcolor=green]
n0000000b:port1 -> n00000012 [style=bold]
n0000000e [label="mali-c55 fr\n/dev/video0", shape=box, style=filled, fillcolor=yellow]
n00000012 [label="mali-c55 ds\n/dev/video1", shape=box, style=filled, fillcolor=yellow]
n00000022 [label="{{<port0> 0} | csi2-rx\n/dev/v4l-subdev4 | {<port1> 1}}", shape=Mrecord, style=filled, fillcolor=green]
n00000022:port1 -> n00000003:port0
n00000027 [label="{{} | imx415 1-001a\n/dev/v4l-subdev5 | {<port0> 0}}", shape=Mrecord, style=filled, fillcolor=green]
n00000027:port0 -> n00000022:port0 [style=bold]
}

View File

@ -0,0 +1,413 @@
.. SPDX-License-Identifier: GPL-2.0
==========================================
ARM Mali-C55 Image Signal Processor driver
==========================================
Introduction
============
This file documents the driver for ARM's Mali-C55 Image Signal Processor. The
driver is located under drivers/media/platform/arm/mali-c55.
The Mali-C55 ISP receives data in either raw Bayer format or RGB/YUV format from
sensors through either a parallel interface or a memory bus before processing it
and outputting it through an internal DMA engine. Two output pipelines are
possible (though one may not be fitted, depending on the implementation). These
are referred to as "Full resolution" and "Downscale", but the naming is historic
and both pipes are capable of cropping/scaling operations. The full resolution
pipe is also capable of outputting RAW data, bypassing much of the ISP's
processing. The downscale pipe cannot output RAW data. An integrated test
pattern generator can be used to drive the ISP and produce image data in the
absence of a connected camera sensor. The driver module is named mali_c55, and
is enabled through the CONFIG_VIDEO_MALI_C55 config option.
The driver implements V4L2, Media Controller and V4L2 Subdevice interfaces and
expects camera sensors connected to the ISP to have V4L2 subdevice interfaces.
Mali-C55 ISP hardware
=====================
A high level functional view of the Mali-C55 ISP is presented below. The ISP
takes input from either a live source or through a DMA engine for memory input,
depending on the SoC integration.::
+---------+ +----------+ +--------+
| Sensor |--->| CSI-2 Rx | "Full Resolution" | DMA |
+---------+ +----------+ |\ Output +--->| Writer |
| | \ | +--------+
| | \ +----------+ +------+---> Streaming I/O
+------------+ +------->| | | | |
| | | |-->| Mali-C55 |--+
| DMA Reader |--------------->| | | ISP | |
| | | / | | | +---> Streaming I/O
+------------+ | / +----------+ | |
|/ +------+
| +--------+
+--->| DMA |
"Downscaled" | Writer |
Output +--------+
Media Controller Topology
=========================
An example of the ISP's topology (as implemented in a system with an IMX415
camera sensor and generic CSI-2 receiver) is below:
.. kernel-figure:: mali-c55-graph.dot
:alt: mali-c55-graph.dot
:align: center
The driver has 4 V4L2 subdevices:
- `mali_c55 isp`: Responsible for configuring input crop and color space
conversion
- `mali_c55 tpg`: The test pattern generator, emulating a camera sensor.
- `mali_c55 resizer fr`: The Full-Resolution pipe resizer
- `mali_c55 resizer ds`: The Downscale pipe resizer
The driver has 3 V4L2 video devices:
- `mali-c55 fr`: The full-resolution pipe's capture device
- `mali-c55 ds`: The downscale pipe's capture device
- `mali-c55 3a stats`: The 3A statistics capture device
Frame sequences are synchronised across to two capture devices, meaning if one
pipe is started later than the other the sequence numbers returned in its
buffers will match those of the other pipe rather than starting from zero.
Idiosyncrasies
--------------
**mali-c55 isp**
The `mali-c55 isp` subdevice has a single sink pad to which all sources of data
should be connected. The active source is selected by enabling the appropriate
media link and disabling all others. The ISP has two source pads, reflecting the
different paths through which it can internally route data. Tap points within
the ISP allow users to divert data to avoid processing by some or all of the
hardware's processing steps. The diagram below is intended only to highlight how
the bypassing works and is not a true reflection of those processing steps; for
a high-level functional block diagram see ARM's developer page for the
ISP [3]_::
+--------------------------------------------------------------+
| Possible Internal ISP Data Routes |
| +------------+ +----------+ +------------+ |
+---+ | | | | | Colour | +---+
| 0 |--+-->| Processing |->| Demosaic |->| Space |--->| 1 |
+---+ | | | | | | Conversion | +---+
| | +------------+ +----------+ +------------+ |
| | +---+
| +---------------------------------------------------| 2 |
| +---+
| |
+--------------------------------------------------------------+
.. flat-table::
:header-rows: 1
* - Pad
- Direction
- Purpose
* - 0
- sink
- Data input, connected to the TPG and camera sensors
* - 1
- source
- RGB/YUV data, connected to the FR and DS V4L2 subdevices
* - 2
- source
- RAW bayer data, connected to the FR V4L2 subdevices
The ISP is limited to both input and output resolutions between 640x480 and
8192x8192, and this is reflected in the ISP and resizer subdevice's .set_fmt()
operations.
**mali-c55 resizer fr**
The `mali-c55 resizer fr` subdevice has two _sink_ pads to reflect the different
insertion points in the hardware (either RAW or demosaiced data):
.. flat-table::
:header-rows: 1
* - Pad
- Direction
- Purpose
* - 0
- sink
- Data input connected to the ISP's demosaiced stream.
* - 1
- source
- Data output connected to the capture video device
* - 2
- sink
- Data input connected to the ISP's raw data stream
The data source in use is selected through the routing API; two routes each of a
single stream are available:
.. flat-table::
:header-rows: 1
* - Sink Pad
- Source Pad
- Purpose
* - 0
- 1
- Demosaiced data route
* - 2
- 1
- Raw data route
If the demosaiced route is active then the FR pipe is only capable of output
in RGB/YUV formats. If the raw route is active then the output reflects the
input (which may be either Bayer or RGB/YUV data).
Using the driver to capture video
=================================
Using the media controller APIs we can configure the input source and ISP to
capture images in a variety of formats. In the examples below, configuring the
media graph is done with the v4l-utils [1]_ package's media-ctl utility.
Capturing the images is done with yavta [2]_.
Configuring the input source
----------------------------
The first step is to set the input source that we wish by enabling the correct
media link. Using the example topology above, we can select the TPG as follows:
.. code-block:: none
media-ctl -l "'lte-csi2-rx':1->'mali-c55 isp':0[0]"
media-ctl -l "'mali-c55 tpg':0->'mali-c55 isp':0[1]"
Configuring which video devices will stream data
------------------------------------------------
The driver will wait for all video devices to have their VIDIOC_STREAMON ioctl
called before it tells the sensor to start streaming. To facilitate this we need
to enable links to the video devices that we want to use. In the example below
we enable the links to both of the image capture video devices
.. code-block:: none
media-ctl -l "'mali-c55 resizer fr':1->'mali-c55 fr':0[1]"
media-ctl -l "'mali-c55 resizer ds':1->'mali-c55 ds':0[1]"
Capturing bayer data from the source and processing to RGB/YUV
--------------------------------------------------------------
To capture 1920x1080 bayer data from the source and push it through the ISP's
full processing pipeline, we configure the data formats appropriately on the
source, ISP and resizer subdevices and set the FR resizer's routing to select
processed data. The media bus format on the resizer's source pad will be either
RGB121212_1X36 or YUV10_1X30, depending on whether you want to capture RGB or
YUV. The ISP's debayering block outputs RGB data natively, setting the source
pad format to YUV10_1X30 enables the colour space conversion block.
In this example we target RGB565 output, so select RGB121212_1X36 as the resizer
source pad's format:
.. code-block:: none
# Set formats on the TPG and ISP
media-ctl -V "'mali-c55 tpg':0[fmt:SRGGB20_1X20/1920x1080]"
media-ctl -V "'mali-c55 isp':0[fmt:SRGGB20_1X20/1920x1080]"
media-ctl -V "'mali-c55 isp':1[fmt:SRGGB20_1X20/1920x1080]"
# Set routing on the FR resizer
media-ctl -R "'mali-c55 resizer fr'[0/0->1/0[1],2/0->1/0[0]]"
# Set format on the resizer, must be done AFTER the routing.
media-ctl -V "'mali-c55 resizer fr':1[fmt:RGB121212_1X36/1920x1080]"
The downscale output can also be used to stream data at the same time. In this
case since only processed data can be captured through the downscale output no
routing need be set:
.. code-block:: none
# Set format on the resizer
media-ctl -V "'mali-c55 resizer ds':1[fmt:RGB121212_1X36/1920x1080]"
Following which images can be captured from both the FR and DS output's video
devices (simultaneously, if desired):
.. code-block:: none
yavta -f RGB565 -s 1920x1080 -c10 /dev/video0
yavta -f RGB565 -s 1920x1080 -c10 /dev/video1
Cropping the image
~~~~~~~~~~~~~~~~~~
Both the full resolution and downscale pipes can crop to a minimum resolution of
640x480. To crop the image simply configure the resizer's sink pad's crop and
compose rectangles and set the format on the video device:
.. code-block:: none
media-ctl -V "'mali-c55 resizer fr':0[fmt:RGB121212_1X36/1920x1080 crop:(480,270)/640x480 compose:(0,0)/640x480]"
media-ctl -V "'mali-c55 resizer fr':1[fmt:RGB121212_1X36/640x480]"
yavta -f RGB565 -s 640x480 -c10 /dev/video0
Downscaling the image
~~~~~~~~~~~~~~~~~~~~~
Both the full resolution and downscale pipes can downscale the image by up to 8x
provided the minimum 640x480 output resolution is adhered to. For the best image
result the scaling ratio for each direction should be the same. To configure
scaling we use the compose rectangle on the resizer's sink pad:
.. code-block:: none
media-ctl -V "'mali-c55 resizer fr':0[fmt:RGB121212_1X36/1920x1080 crop:(0,0)/1920x1080 compose:(0,0)/640x480]"
media-ctl -V "'mali-c55 resizer fr':1[fmt:RGB121212_1X36/640x480]"
yavta -f RGB565 -s 640x480 -c10 /dev/video0
Capturing images in YUV formats
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
If we need to output YUV data rather than RGB the color space conversion block
needs to be active, which is achieved by setting MEDIA_BUS_FMT_YUV10_1X30 on the
resizer's source pad. We can then configure a capture format like NV12 (here in
its multi-planar variant)
.. code-block:: none
media-ctl -V "'mali-c55 resizer fr':1[fmt:YUV10_1X30/1920x1080]"
yavta -f NV12M -s 1920x1080 -c10 /dev/video0
Capturing RGB data from the source and processing it with the resizers
----------------------------------------------------------------------
The Mali-C55 ISP can work with sensors capable of outputting RGB data. In this
case although none of the image quality blocks would be used it can still
crop/scale the data in the usual way. For this reason RGB data input to the ISP
still goes through the ISP subdevice's pad 1 to the resizer.
To achieve this, the ISP's sink pad's format is set to
MEDIA_BUS_FMT_RGB202020_1X60 - this reflects the format that data must be in to
work with the ISP. Converting the camera sensor's output to that format is the
responsibility of external hardware.
In this example we ask the test pattern generator to give us RGB data instead of
bayer.
.. code-block:: none
media-ctl -V "'mali-c55 tpg':0[fmt:RGB202020_1X60/1920x1080]"
media-ctl -V "'mali-c55 isp':0[fmt:RGB202020_1X60/1920x1080]"
Cropping or scaling the data can be done in exactly the same way as outlined
earlier.
Capturing raw data from the source and outputting it unmodified
-----------------------------------------------------------------
The ISP can additionally capture raw data from the source and output it on the
full resolution pipe only, completely unmodified. In this case the downscale
pipe can still process the data normally and be used at the same time.
To configure raw bypass the FR resizer's subdevice's routing table needs to be
configured, followed by formats in the appropriate places:
.. code-block:: none
media-ctl -R "'mali-c55 resizer fr'[0/0->1/0[0],2/0->1/0[1]]"
media-ctl -V "'mali-c55 isp':0[fmt:RGB202020_1X60/1920x1080]"
media-ctl -V "'mali-c55 resizer fr':2[fmt:RGB202020_1X60/1920x1080]"
media-ctl -V "'mali-c55 resizer fr':1[fmt:RGB202020_1X60/1920x1080]"
# Set format on the video device and stream
yavta -f RGB565 -s 1920x1080 -c10 /dev/video0
.. _mali-c55-3a-stats:
Capturing ISP Statistics
========================
The ISP is capable of producing statistics for consumption by image processing
algorithms running in userspace. These statistics can be captured by queueing
buffers to the `mali-c55 3a stats` V4L2 Device whilst the ISP is streaming. Only
the :ref:`V4L2_META_FMT_MALI_C55_STATS <v4l2-meta-fmt-mali-c55-stats>`
format is supported, so no format-setting need be done:
.. code-block:: none
# We assume the media graph has been configured to support RGB565 capture
# from the mali-c55 fr V4L2 Device, which is at /dev/video0. The statistics
# V4L2 device is at /dev/video3
yavta -f RGB565 -s 1920x1080 -c32 /dev/video0 && \
yavta -c10 -F /dev/video3
The layout of the buffer is described by :c:type:`mali_c55_stats_buffer`,
but broadly statistics are generated to support three image processing
algorithms; AEXP (Auto-Exposure), AWB (Auto-White Balance) and AF (Auto-Focus).
These stats can be drawn from various places in the Mali C55 ISP pipeline, known
as "tap points". This high-level block diagram is intended to explain where in
the processing flow the statistics can be drawn from::
+--> AEXP-2 +----> AEXP-1 +--> AF-0
| +----> AF-1 |
| | |
+---------+ | +--------------+ | +--------------+ |
| Input +-+-->+ Digital Gain +---+-->+ Black Level +---+---+
+---------+ +--------------+ +--------------+ |
+-----------------------------------------------------------------+
|
| +--------------+ +---------+ +----------------+
+-->| Sinter Noise +-+ White +--+--->| Lens Shading +--+---------------+
| Reduction | | Balance | | | | | |
+--------------+ +---------+ | +----------------+ | |
+---> AEXP-0 (A) +--> AEXP-0 (B) |
+--------------------------------------------------------------------------+
|
| +----------------+ +--------------+ +----------------+
+-->| Tone mapping +-+--->| Demosaicing +->+ Purple Fringe +-+-----------+
| | | +--------------+ | Correction | | |
+----------------+ +-> AEXP-IRIDIX +----------------+ +---> AWB-0 |
+----------------------------------------------------------------------------+
| +-------------+ +-------------+
+------------------->| Colour +---+--->| Output |
| Correction | | | Pipelines |
+-------------+ | +-------------+
+--> AWB-1
By default all statistics are drawn from the 0th tap point for each algorithm;
I.E. AEXP statistics from AEXP-0 (A), AWB statistics from AWB-0 and AF
statistics from AF-0. This is configurable for AEXP and AWB statsistics through
programming the ISP's parameters.
.. _mali-c55-3a-params:
Programming ISP Parameters
==========================
The ISP can be programmed with various parameters from userspace to apply to the
hardware before and during video stream. This allows userspace to dynamically
change values such as black level, white balance and lens shading gains and so
on.
The buffer format and how to populate it are described by the
:ref:`V4L2_META_FMT_MALI_C55_PARAMS <v4l2-meta-fmt-mali-c55-params>` format,
which should be set as the data format for the `mali-c55 3a params` video node.
References
==========
.. [1] https://git.linuxtv.org/v4l-utils.git/
.. [2] https://git.ideasonboard.org/yavta.git
.. [3] https://developer.arm.com/Processors/Mali-C55

View File

@ -18,8 +18,6 @@ am437x-vpfe TI AM437x VPFE
aspeed-video Aspeed AST2400 and AST2500
atmel-isc ATMEL Image Sensor Controller (ISC)
atmel-isi ATMEL Image Sensor Interface (ISI)
c8sectpfe SDR platform devices
c8sectpfe SDR platform devices
cafe_ccic Marvell 88ALP01 (Cafe) CMOS Camera Controller
cdns-csi2rx Cadence MIPI-CSI2 RX Controller
cdns-csi2tx Cadence MIPI-CSI2 TX Controller

View File

@ -0,0 +1,8 @@
digraph board {
rankdir=TB
n00000001 [label="{{<port0> 0} | rkcif-dvp0\n/dev/v4l-subdev0 | {<port1> 1}}", shape=Mrecord, style=filled, fillcolor=green]
n00000001:port1 -> n00000004
n00000004 [label="rkcif-dvp0-id0\n/dev/video0", shape=box, style=filled, fillcolor=yellow]
n00000025 [label="{{} | it6801 2-0048\n/dev/v4l-subdev1 | {<port0> 0}}", shape=Mrecord, style=filled, fillcolor=green]
n00000025:port0 -> n00000001:port0
}

View File

@ -0,0 +1,79 @@
.. SPDX-License-Identifier: GPL-2.0
=========================================
Rockchip Camera Interface (CIF)
=========================================
Introduction
============
The Rockchip Camera Interface (CIF) is featured in many Rockchip SoCs in
different variants.
The different variants are combinations of common building blocks, such as
* INTERFACE blocks of different types, namely
* the Digital Video Port (DVP, a parallel data interface)
* the interface block for the MIPI CSI-2 receiver
* CROP units
* MIPI CSI-2 receiver (not available on all variants): This unit is referred
to as MIPI CSI HOST in the Rockchip documentation.
Technically, it is a separate hardware block, but it is strongly coupled to
the CIF and therefore included here.
* MUX units (not available on all variants) that pass the video data to an
image signal processor (ISP)
* SCALE units (not available on all variants)
* DMA engines that transfer video data into system memory using a
double-buffering mechanism called ping-pong mode
* Support for four streams per INTERFACE block (not available on all
variants), e.g., for MIPI CSI-2 Virtual Channels (VCs)
This document describes the different variants of the CIF, their hardware
layout, as well as their representation in the media controller centric rkcif
device driver, which is located under drivers/media/platform/rockchip/rkcif.
Variants
========
Rockchip PX30 Video Input Processor (VIP)
-----------------------------------------
The PX30 Video Input Processor (VIP) features a digital video port that accepts
parallel video data or BT.656.
Since these protocols do not feature multiple streams, the VIP has one DMA
engine that transfers the input video data into system memory.
The rkcif driver represents this hardware variant by exposing one V4L2 subdevice
(the DVP INTERFACE/CROP block) and one V4L2 device (the DVP DMA engine).
Rockchip RK3568 Video Capture (VICAP)
-------------------------------------
The RK3568 Video Capture (VICAP) unit features a digital video port and a MIPI
CSI-2 receiver that can receive video data independently.
The DVP accepts parallel video data, BT.656 and BT.1120.
Since the BT.1120 protocol may feature more than one stream, the RK3568 VICAP
DVP features four DMA engines that can capture different streams.
Similarly, the RK3568 VICAP MIPI CSI-2 receiver features four DMA engines to
handle different Virtual Channels (VCs).
The rkcif driver represents this hardware variant by exposing up the following
V4L2 subdevices:
* rkcif-dvp0: INTERFACE/CROP block for the DVP
and the following video devices:
* rkcif-dvp0-id0: The support for multiple streams on the DVP is not yet
implemented, as it is hard to find test hardware. Thus, this video device
represents the first DMA engine of the RK3568 DVP.
.. kernel-figure:: rkcif-rk3568-vicap.dot
:alt: Topology of the RK3568 Video Capture (VICAP) unit
:align: center

View File

@ -19,12 +19,14 @@ Video4Linux (V4L) driver-specific documentation
ipu3
ipu6-isys
ivtv
mali-c55
mgb4
omap3isp
philips
qcom_camss
raspberrypi-pisp-be
rcar-fdp1
rkcif
rkisp1
raspberrypi-rp1-cfe
saa7134

View File

@ -0,0 +1,86 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/media/arm,mali-c55.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: ARM Mali-C55 Image Signal Processor
maintainers:
- Daniel Scally <dan.scally@ideasonboard.com>
- Jacopo Mondi <jacopo.mondi@ideasonboard.com>
properties:
compatible:
const: arm,mali-c55
reg:
maxItems: 1
interrupts:
maxItems: 1
clocks:
items:
- description: ISP Video Clock
- description: ISP AXI clock
- description: ISP AHB-lite clock
clock-names:
items:
- const: vclk
- const: aclk
- const: hclk
resets:
items:
- description: vclk domain reset
- description: aclk domain reset
- description: hclk domain reset
reset-names:
items:
- const: vresetn
- const: aresetn
- const: hresetn
port:
$ref: /schemas/graph.yaml#/properties/port
description: Input parallel video bus
properties:
endpoint:
$ref: /schemas/graph.yaml#/properties/endpoint
required:
- compatible
- reg
- interrupts
- clocks
- clock-names
- resets
- reset-names
- port
additionalProperties: false
examples:
- |
#include <dt-bindings/interrupt-controller/arm-gic.h>
isp@400000 {
compatible = "arm,mali-c55";
reg = <0x400000 0x200000>;
clocks = <&clk 0>, <&clk 1>, <&clk 2>;
clock-names = "vclk", "aclk", "hclk";
resets = <&resets 0>, <&resets 1>, <&resets 2>;
reset-names = "vresetn", "aresetn", "hresetn";
interrupts = <GIC_SPI 861 IRQ_TYPE_EDGE_RISING>;
port {
isp_in: endpoint {
remote-endpoint = <&csi2_rx_out>;
};
};
};
...

View File

@ -0,0 +1,89 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/media/i2c/dongwoon,dw9719.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Dongwoon Anatech DW9719 Voice Coil Motor (VCM) Controller
maintainers:
- André Apitzsch <git@apitzsch.eu>
description:
The Dongwoon DW9718S/9719/9761 is a single 10-bit digital-to-analog converter
with 100 mA output current sink capability, designed for linear control of
voice coil motors (VCM) in camera lenses. This chip provides a Smart Actuator
Control (SAC) mode intended for driving voice coil lenses in camera modules.
properties:
compatible:
enum:
- dongwoon,dw9718s
- dongwoon,dw9719
- dongwoon,dw9761
- dongwoon,dw9800k
reg:
maxItems: 1
vdd-supply:
description: VDD power supply
dongwoon,sac-mode:
description: |
Slew Rate Control mode to use: direct, LSC (Linear Slope Control) or
SAC1-SAC6 (Smart Actuator Control).
$ref: /schemas/types.yaml#/definitions/uint32
enum:
- 0 # Direct mode
- 1 # LSC mode
- 2 # SAC1 mode (operation time# 0.32 x Tvib)
- 3 # SAC2 mode (operation time# 0.48 x Tvib)
- 4 # SAC3 mode (operation time# 0.72 x Tvib)
- 5 # SAC4 mode (operation time# 1.20 x Tvib)
- 6 # SAC5 mode (operation time# 1.64 x Tvib)
- 7 # SAC6 mode (operation time# 1.88 x Tvib)
default: 4
dongwoon,vcm-prescale:
description:
Indication of VCM switching frequency dividing rate select.
$ref: /schemas/types.yaml#/definitions/uint32
required:
- compatible
- reg
- vdd-supply
allOf:
- if:
properties:
compatible:
contains:
const: dongwoon,dw9718s
then:
properties:
dongwoon,vcm-prescale:
description:
The final frequency is 10 MHz divided by (value + 2).
maximum: 15
default: 0
additionalProperties: false
examples:
- |
i2c {
#address-cells = <1>;
#size-cells = <0>;
actuator@c {
compatible = "dongwoon,dw9718s";
reg = <0x0c>;
vdd-supply = <&pm8937_l17>;
dongwoon,sac-mode = <4>;
dongwoon,vcm-prescale = <0>;
};
};

View File

@ -0,0 +1,162 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/media/i2c/nxp,tda19971.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: NXP TDA1997x HDMI receiver
maintainers:
- Frank Li <Frank.Li@nxp.com>
description: |
The TDA19971/73 are HDMI video receivers.
The TDA19971 Video port output pins can be used as follows:
- RGB 8bit per color (24 bits total): R[11:4] B[11:4] G[11:4]
- YUV444 8bit per color (24 bits total): Y[11:4] Cr[11:4] Cb[11:4]
- YUV422 semi-planar 8bit per component (16 bits total): Y[11:4] CbCr[11:4]
- YUV422 semi-planar 10bit per component (20 bits total): Y[11:2] CbCr[11:2]
- YUV422 semi-planar 12bit per component (24 bits total): - Y[11:0] CbCr[11:0]
- YUV422 BT656 8bit per component (8 bits total): YCbCr[11:4] (2-cycles)
- YUV422 BT656 10bit per component (10 bits total): YCbCr[11:2] (2-cycles)
- YUV422 BT656 12bit per component (12 bits total): YCbCr[11:0] (2-cycles)
The TDA19973 Video port output pins can be used as follows:
- RGB 12bit per color (36 bits total): R[11:0] B[11:0] G[11:0]
- YUV444 12bit per color (36 bits total): Y[11:0] Cb[11:0] Cr[11:0]
- YUV422 semi-planar 12bit per component (24 bits total): Y[11:0] CbCr[11:0]
- YUV422 BT656 12bit per component (12 bits total): YCbCr[11:0] (2-cycles)
The Video port output pins are mapped via 4-bit 'pin groups' allowing
for a variety of connection possibilities including swapping pin order within
pin groups. The video_portcfg device-tree property consists of register mapping
pairs which map a chip-specific VP output register to a 4-bit pin group. If
the pin group needs to be bit-swapped you can use the *_S pin-group defines.
properties:
compatible:
enum:
- nxp,tda19971
- nxp,tda19973
reg:
maxItems: 1
interrupts:
maxItems: 1
DOVDD-supply: true
DVDD-supply: true
AVDD-supply: true
'#sound-dai-cells':
const: 0
port:
$ref: /schemas/graph.yaml#/$defs/port-base
unevaluatedProperties: false
properties:
endpoint:
$ref: /schemas/media/video-interfaces.yaml#
unevaluatedProperties: false
nxp,vidout-portcfg:
$ref: /schemas/types.yaml#/definitions/uint32-matrix
minItems: 1
maxItems: 4
items:
items:
- description: Video Port control registers index.
maximum: 8
minimum: 0
- description: pin(pinswapped) groups
description:
array of pairs mapping VP output pins to pin groups.
nxp,audout-format:
enum:
- i2s
- spdif
nxp,audout-width:
$ref: /schemas/types.yaml#/definitions/uint32
enum: [8, 16, 24, 32]
description:
width of audio output data bus.
nxp,audout-layout:
$ref: /schemas/types.yaml#/definitions/uint32
enum: [0, 1]
description:
data layout (0=AP0 used, 1=AP0/AP1/AP2/AP3 used).
nxp,audout-mclk-fs:
$ref: /schemas/types.yaml#/definitions/uint32
description:
Multiplication factor between stream rate and codec mclk.
required:
- compatible
- reg
- interrupts
- DOVDD-supply
- AVDD-supply
- DVDD-supply
additionalProperties: false
examples:
- |
#include <dt-bindings/interrupt-controller/irq.h>
#include <dt-bindings/media/tda1997x.h>
i2c {
#address-cells = <1>;
#size-cells = <0>;
hdmi-receiver@48 {
compatible = "nxp,tda19971";
reg = <0x48>;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_tda1997x>;
interrupt-parent = <&gpio1>;
interrupts = <7 IRQ_TYPE_LEVEL_LOW>;
DOVDD-supply = <&reg_3p3v>;
AVDD-supply = <&reg_1p8v>;
DVDD-supply = <&reg_1p8v>;
/* audio */
#sound-dai-cells = <0>;
nxp,audout-format = "i2s";
nxp,audout-layout = <0>;
nxp,audout-width = <16>;
nxp,audout-mclk-fs = <128>;
/*
* The 8bpp YUV422 semi-planar mode outputs CbCr[11:4]
* and Y[11:4] across 16bits in the same pixclk cycle.
*/
nxp,vidout-portcfg =
/* Y[11:8]<->VP[15:12]<->CSI_DATA[19:16] */
< TDA1997X_VP24_V15_12 TDA1997X_G_Y_11_8 >,
/* Y[7:4]<->VP[11:08]<->CSI_DATA[15:12] */
< TDA1997X_VP24_V11_08 TDA1997X_G_Y_7_4 >,
/* CbCc[11:8]<->VP[07:04]<->CSI_DATA[11:8] */
< TDA1997X_VP24_V07_04 TDA1997X_R_CR_CBCR_11_8 >,
/* CbCr[7:4]<->VP[03:00]<->CSI_DATA[7:4] */
< TDA1997X_VP24_V03_00 TDA1997X_R_CR_CBCR_7_4 >;
port {
endpoint {
remote-endpoint = <&ipu1_csi0_mux_from_parallel_sensor>;
bus-width = <16>;
hsync-active = <1>;
vsync-active = <1>;
data-active = <1>;
};
};
};
};

View File

@ -1,178 +0,0 @@
Device-Tree bindings for the NXP TDA1997x HDMI receiver
The TDA19971/73 are HDMI video receivers.
The TDA19971 Video port output pins can be used as follows:
- RGB 8bit per color (24 bits total): R[11:4] B[11:4] G[11:4]
- YUV444 8bit per color (24 bits total): Y[11:4] Cr[11:4] Cb[11:4]
- YUV422 semi-planar 8bit per component (16 bits total): Y[11:4] CbCr[11:4]
- YUV422 semi-planar 10bit per component (20 bits total): Y[11:2] CbCr[11:2]
- YUV422 semi-planar 12bit per component (24 bits total): - Y[11:0] CbCr[11:0]
- YUV422 BT656 8bit per component (8 bits total): YCbCr[11:4] (2-cycles)
- YUV422 BT656 10bit per component (10 bits total): YCbCr[11:2] (2-cycles)
- YUV422 BT656 12bit per component (12 bits total): YCbCr[11:0] (2-cycles)
The TDA19973 Video port output pins can be used as follows:
- RGB 12bit per color (36 bits total): R[11:0] B[11:0] G[11:0]
- YUV444 12bit per color (36 bits total): Y[11:0] Cb[11:0] Cr[11:0]
- YUV422 semi-planar 12bit per component (24 bits total): Y[11:0] CbCr[11:0]
- YUV422 BT656 12bit per component (12 bits total): YCbCr[11:0] (2-cycles)
The Video port output pins are mapped via 4-bit 'pin groups' allowing
for a variety of connection possibilities including swapping pin order within
pin groups. The video_portcfg device-tree property consists of register mapping
pairs which map a chip-specific VP output register to a 4-bit pin group. If
the pin group needs to be bit-swapped you can use the *_S pin-group defines.
Required Properties:
- compatible :
- "nxp,tda19971" for the TDA19971
- "nxp,tda19973" for the TDA19973
- reg : I2C slave address
- interrupts : The interrupt number
- DOVDD-supply : Digital I/O supply
- DVDD-supply : Digital Core supply
- AVDD-supply : Analog supply
- nxp,vidout-portcfg : array of pairs mapping VP output pins to pin groups.
Optional Properties:
- nxp,audout-format : DAI bus format: "i2s" or "spdif".
- nxp,audout-width : width of audio output data bus (1-4).
- nxp,audout-layout : data layout (0=AP0 used, 1=AP0/AP1/AP2/AP3 used).
- nxp,audout-mclk-fs : Multiplication factor between stream rate and codec
mclk.
The port node shall contain one endpoint child node for its digital
output video port, in accordance with the video interface bindings defined in
Documentation/devicetree/bindings/media/video-interfaces.txt.
Optional Endpoint Properties:
The following three properties are defined in video-interfaces.txt and
are valid for the output parallel bus endpoint:
- hsync-active: Horizontal synchronization polarity. Defaults to active high.
- vsync-active: Vertical synchronization polarity. Defaults to active high.
- data-active: Data polarity. Defaults to active high.
Examples:
- VP[15:0] connected to IMX6 CSI_DATA[19:4] for 16bit YUV422
16bit I2S layout0 with a 128*fs clock (A_WS, AP0, A_CLK pins)
hdmi-receiver@48 {
compatible = "nxp,tda19971";
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_tda1997x>;
reg = <0x48>;
interrupt-parent = <&gpio1>;
interrupts = <7 IRQ_TYPE_LEVEL_LOW>;
DOVDD-supply = <&reg_3p3v>;
AVDD-supply = <&reg_1p8v>;
DVDD-supply = <&reg_1p8v>;
/* audio */
#sound-dai-cells = <0>;
nxp,audout-format = "i2s";
nxp,audout-layout = <0>;
nxp,audout-width = <16>;
nxp,audout-mclk-fs = <128>;
/*
* The 8bpp YUV422 semi-planar mode outputs CbCr[11:4]
* and Y[11:4] across 16bits in the same pixclk cycle.
*/
nxp,vidout-portcfg =
/* Y[11:8]<->VP[15:12]<->CSI_DATA[19:16] */
< TDA1997X_VP24_V15_12 TDA1997X_G_Y_11_8 >,
/* Y[7:4]<->VP[11:08]<->CSI_DATA[15:12] */
< TDA1997X_VP24_V11_08 TDA1997X_G_Y_7_4 >,
/* CbCc[11:8]<->VP[07:04]<->CSI_DATA[11:8] */
< TDA1997X_VP24_V07_04 TDA1997X_R_CR_CBCR_11_8 >,
/* CbCr[7:4]<->VP[03:00]<->CSI_DATA[7:4] */
< TDA1997X_VP24_V03_00 TDA1997X_R_CR_CBCR_7_4 >;
port {
tda1997x_to_ipu1_csi0_mux: endpoint {
remote-endpoint = <&ipu1_csi0_mux_from_parallel_sensor>;
bus-width = <16>;
hsync-active = <1>;
vsync-active = <1>;
data-active = <1>;
};
};
};
- VP[15:8] connected to IMX6 CSI_DATA[19:12] for 8bit BT656
16bit I2S layout0 with a 128*fs clock (A_WS, AP0, A_CLK pins)
hdmi-receiver@48 {
compatible = "nxp,tda19971";
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_tda1997x>;
reg = <0x48>;
interrupt-parent = <&gpio1>;
interrupts = <7 IRQ_TYPE_LEVEL_LOW>;
DOVDD-supply = <&reg_3p3v>;
AVDD-supply = <&reg_1p8v>;
DVDD-supply = <&reg_1p8v>;
/* audio */
#sound-dai-cells = <0>;
nxp,audout-format = "i2s";
nxp,audout-layout = <0>;
nxp,audout-width = <16>;
nxp,audout-mclk-fs = <128>;
/*
* The 8bpp YUV422 semi-planar mode outputs CbCr[11:4]
* and Y[11:4] across 16bits in the same pixclk cycle.
*/
nxp,vidout-portcfg =
/* Y[11:8]<->VP[15:12]<->CSI_DATA[19:16] */
< TDA1997X_VP24_V15_12 TDA1997X_G_Y_11_8 >,
/* Y[7:4]<->VP[11:08]<->CSI_DATA[15:12] */
< TDA1997X_VP24_V11_08 TDA1997X_G_Y_7_4 >,
/* CbCc[11:8]<->VP[07:04]<->CSI_DATA[11:8] */
< TDA1997X_VP24_V07_04 TDA1997X_R_CR_CBCR_11_8 >,
/* CbCr[7:4]<->VP[03:00]<->CSI_DATA[7:4] */
< TDA1997X_VP24_V03_00 TDA1997X_R_CR_CBCR_7_4 >;
port {
tda1997x_to_ipu1_csi0_mux: endpoint {
remote-endpoint = <&ipu1_csi0_mux_from_parallel_sensor>;
bus-width = <16>;
hsync-active = <1>;
vsync-active = <1>;
data-active = <1>;
};
};
};
- VP[15:8] connected to IMX6 CSI_DATA[19:12] for 8bit BT656
16bit I2S layout0 with a 128*fs clock (A_WS, AP0, A_CLK pins)
hdmi-receiver@48 {
compatible = "nxp,tda19971";
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_tda1997x>;
reg = <0x48>;
interrupt-parent = <&gpio1>;
interrupts = <7 IRQ_TYPE_LEVEL_LOW>;
DOVDD-supply = <&reg_3p3v>;
AVDD-supply = <&reg_1p8v>;
DVDD-supply = <&reg_1p8v>;
/* audio */
#sound-dai-cells = <0>;
nxp,audout-format = "i2s";
nxp,audout-layout = <0>;
nxp,audout-width = <16>;
nxp,audout-mclk-fs = <128>;
/*
* The 8bpp BT656 mode outputs YCbCr[11:4] across 8bits over
* 2 pixclk cycles.
*/
nxp,vidout-portcfg =
/* YCbCr[11:8]<->VP[15:12]<->CSI_DATA[19:16] */
< TDA1997X_VP24_V15_12 TDA1997X_R_CR_CBCR_11_8 >,
/* YCbCr[7:4]<->VP[11:08]<->CSI_DATA[15:12] */
< TDA1997X_VP24_V11_08 TDA1997X_R_CR_CBCR_7_4 >,
port {
tda1997x_to_ipu1_csi0_mux: endpoint {
remote-endpoint = <&ipu1_csi0_mux_from_parallel_sensor>;
bus-width = <16>;
hsync-active = <1>;
vsync-active = <1>;
data-active = <1>;
};
};
};

View File

@ -0,0 +1,105 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/media/i2c/sony,imx111.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Sony IMX111 8MP CMOS Digital Image Sensor
maintainers:
- Svyatoslav Ryhel <clamor95@gmail.com>
description:
IMX111 sensor is a Sony CMOS active pixel digital image sensor with an active
array size of 2464H x 3280V. It is programmable through I2C interface. Image
data is sent through MIPI CSI-2, through 1 or 2 lanes.
allOf:
- $ref: /schemas/media/video-interface-devices.yaml#
- $ref: /schemas/nvmem/nvmem-consumer.yaml#
properties:
compatible:
const: sony,imx111
reg:
maxItems: 1
clocks:
description: EXTCLK with possible frequency from 6 to 54 MHz
maxItems: 1
reset-gpios:
maxItems: 1
iovdd-supply:
description: Digital IO power supply (1.8V)
dvdd-supply:
description: Digital power supply (1.2V)
avdd-supply:
description: Analog power supply (2.7V)
port:
additionalProperties: false
$ref: /schemas/graph.yaml#/$defs/port-base
properties:
endpoint:
$ref: /schemas/media/video-interfaces.yaml#
unevaluatedProperties: false
required:
- data-lanes
- link-frequencies
required:
- endpoint
required:
- compatible
- reg
- clocks
- port
unevaluatedProperties: false
examples:
- |
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/media/video-interfaces.h>
i2c {
#address-cells = <1>;
#size-cells = <0>;
camera@10 {
compatible = "sony,imx111";
reg = <0x10>;
clocks = <&imx111_clk>;
iovdd-supply = <&camera_vddio_1v8>;
dvdd-supply = <&camera_vddd_1v2>;
avdd-supply = <&camera_vdda_2v7>;
orientation = <1>;
rotation = <90>;
nvmem = <&eeprom>;
flash-leds = <&led>;
lens-focus = <&vcm>;
reset-gpios = <&gpio 84 GPIO_ACTIVE_LOW>;
port {
imx111_output: endpoint {
data-lanes = <1 2>;
link-frequencies = /bits/ 64 <542400000>;
remote-endpoint = <&csi_input>;
};
};
};
};
...

View File

@ -25,7 +25,11 @@ allOf:
properties:
compatible:
const: st,vd55g1
enum:
- st,vd55g1
- st,vd65g4
description:
VD55G1 is the monochrome variant, while VD65G4 is the color one.
reg:
maxItems: 1

View File

@ -1,157 +0,0 @@
* Texas Instruments TVP5150 and TVP5151 video decoders
The TVP5150 and TVP5151 are video decoders that convert baseband NTSC and PAL
(and also SECAM in the TVP5151 case) video signals to either 8-bit 4:2:2 YUV
with discrete syncs or 8-bit ITU-R BT.656 with embedded syncs output formats.
Required Properties:
====================
- compatible: Value must be "ti,tvp5150".
- reg: I2C slave address.
Optional Properties:
====================
- pdn-gpios: Phandle for the GPIO connected to the PDN pin, if any.
- reset-gpios: Phandle for the GPIO connected to the RESETB pin, if any.
The device node must contain one 'port' child node per device physical input
and output port, in accordance with the video interface bindings defined in
Documentation/devicetree/bindings/media/video-interfaces.txt. The port nodes
are numbered as follows
Name Type Port
--------------------------------------
AIP1A sink 0
AIP1B sink 1
Y-OUT src 2
The device node must contain at least one sink port and the src port. Each input
port must be linked to an endpoint defined in [1]. The port/connector layout is
as follows
tvp-5150 port@0 (AIP1A)
endpoint@0 -----------> Comp0-Con port
endpoint@1 ------+----> Svideo-Con port
tvp-5150 port@1 (AIP1B) |
endpoint@1 ------+
endpoint@0 -----------> Comp1-Con port
tvp-5150 port@2
endpoint (video bitstream output at YOUT[0-7] parallel bus)
Required Endpoint Properties for parallel synchronization on output port:
=========================================================================
- hsync-active: Active state of the HSYNC signal. Must be <1> (HIGH).
- vsync-active: Active state of the VSYNC signal. Must be <1> (HIGH).
- field-even-active: Field signal level during the even field data
transmission. Must be <0>.
Note: Do not specify any of these properties if you want to use the embedded
BT.656 synchronization.
Optional Connector Properties:
==============================
- sdtv-standards: Set the possible signals to which the hardware tries to lock
instead of using the autodetection mechanism. Please look at
[1] for more information.
[1] Documentation/devicetree/bindings/display/connector/analog-tv-connector.yaml.
Example - three input sources:
#include <dt-bindings/display/sdtv-standards.h>
comp_connector_0 {
compatible = "composite-video-connector";
label = "Composite0";
sdtv-standards = <SDTV_STD_PAL_M>; /* limit to pal-m signals */
port {
composite0_to_tvp5150: endpoint {
remote-endpoint = <&tvp5150_to_composite0>;
};
};
};
comp_connector_1 {
compatible = "composite-video-connector";
label = "Composite1";
sdtv-standards = <SDTV_STD_NTSC_M>; /* limit to ntsc-m signals */
port {
composite1_to_tvp5150: endpoint {
remote-endpoint = <&tvp5150_to_composite1>;
};
};
};
svideo_connector {
compatible = "svideo-connector";
label = "S-Video";
port {
#address-cells = <1>;
#size-cells = <0>;
svideo_luma_to_tvp5150: endpoint@0 {
reg = <0>;
remote-endpoint = <&tvp5150_to_svideo_luma>;
};
svideo_chroma_to_tvp5150: endpoint@1 {
reg = <1>;
remote-endpoint = <&tvp5150_to_svideo_chroma>;
};
};
};
&i2c2 {
tvp5150@5c {
compatible = "ti,tvp5150";
reg = <0x5c>;
pdn-gpios = <&gpio4 30 GPIO_ACTIVE_LOW>;
reset-gpios = <&gpio6 7 GPIO_ACTIVE_LOW>;
#address-cells = <1>;
#size-cells = <0>;
port@0 {
#address-cells = <1>;
#size-cells = <0>;
reg = <0>;
tvp5150_to_composite0: endpoint@0 {
reg = <0>;
remote-endpoint = <&composite0_to_tvp5150>;
};
tvp5150_to_svideo_luma: endpoint@1 {
reg = <1>;
remote-endpoint = <&svideo_luma_to_tvp5150>;
};
};
port@1 {
#address-cells = <1>;
#size-cells = <0>;
reg = <1>;
tvp5150_to_composite1: endpoint@0 {
reg = <0>;
remote-endpoint = <&composite1_to_tvp5150>;
};
tvp5150_to_svideo_chroma: endpoint@1 {
reg = <1>;
remote-endpoint = <&svideo_chroma_to_tvp5150>;
};
};
port@2 {
reg = <2>;
tvp5150_1: endpoint {
remote-endpoint = <&ccdc_ep>;
};
};
};
};

View File

@ -0,0 +1,133 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/media/i2c/ti,tvp5150.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Texas Instruments TVP5150 and TVP5151 video decoders
maintainers:
- Frank Li <Frank.Li@nxp.com>
description:
The TVP5150 and TVP5151 are video decoders that convert baseband NTSC and PAL
(and also SECAM in the TVP5151 case) video signals to either 8-bit 4:2:2 YUV
with discrete syncs or 8-bit ITU-R BT.656 with embedded syncs output formats.
properties:
compatible:
const: ti,tvp5150
reg:
maxItems: 1
pdn-gpios:
maxItems: 1
reset-gpios:
maxItems: 1
'#address-cells':
const: 1
'#size-cells':
const: 0
port@0:
$ref: /schemas/graph.yaml#/$defs/port-base
unevaluatedProperties: false
description:
sink port node, AIP1A
properties:
endpoint:
$ref: /schemas/media/video-interfaces.yaml#
unevaluatedProperties: false
port@1:
$ref: /schemas/graph.yaml#/$defs/port-base
unevaluatedProperties: false
description:
sink port node, AIP1B
properties:
endpoint:
$ref: /schemas/media/video-interfaces.yaml#
unevaluatedProperties: false
port@2:
$ref: /schemas/graph.yaml#/$defs/port-base
unevaluatedProperties: false
description:
source port node, Y-OUT
properties:
endpoint:
$ref: /schemas/media/video-interfaces.yaml#
unevaluatedProperties: false
required:
- compatible
- reg
- port@2
additionalProperties: false
examples:
- |
#include <dt-bindings/display/sdtv-standards.h>
#include <dt-bindings/gpio/gpio.h>
i2c {
#address-cells = <1>;
#size-cells = <0>;
bridge@5c {
compatible = "ti,tvp5150";
reg = <0x5c>;
pdn-gpios = <&gpio4 30 GPIO_ACTIVE_LOW>;
reset-gpios = <&gpio6 7 GPIO_ACTIVE_LOW>;
#address-cells = <1>;
#size-cells = <0>;
port@0 {
#address-cells = <1>;
#size-cells = <0>;
reg = <0>;
endpoint@0 {
reg = <0>;
remote-endpoint = <&composite0_to_tvp5150>;
};
endpoint@1 {
reg = <1>;
remote-endpoint = <&svideo_luma_to_tvp5150>;
};
};
port@1 {
#address-cells = <1>;
#size-cells = <0>;
reg = <1>;
endpoint@0 {
reg = <0>;
remote-endpoint = <&composite1_to_tvp5150>;
};
endpoint@1 {
reg = <1>;
remote-endpoint = <&svideo_chroma_to_tvp5150>;
};
};
port@2 {
reg = <2>;
endpoint {
remote-endpoint = <&ccdc_ep>;
};
};
};
};

View File

@ -22,6 +22,7 @@ properties:
- fsl,imx8mn-isi
- fsl,imx8mp-isi
- fsl,imx8ulp-isi
- fsl,imx91-isi
- fsl,imx93-isi
reg:
@ -66,7 +67,6 @@ required:
- interrupts
- clocks
- clock-names
- fsl,blk-ctrl
- ports
allOf:
@ -77,6 +77,7 @@ allOf:
enum:
- fsl,imx8mn-isi
- fsl,imx8ulp-isi
- fsl,imx91-isi
- fsl,imx93-isi
then:
properties:
@ -109,6 +110,16 @@ allOf:
- port@0
- port@1
- if:
properties:
compatible:
not:
contains:
const: fsl,imx91-isi
then:
required:
- fsl,blk-ctrl
additionalProperties: false
examples:

View File

@ -0,0 +1,254 @@
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/media/qcom,msm8939-camss.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Qualcomm MSM8939 Camera Subsystem (CAMSS)
maintainers:
- Vincent Knecht <vincent.knecht@mailoo.org>
description:
The CAMSS IP is a CSI decoder and ISP present on Qualcomm platforms
properties:
compatible:
const: qcom,msm8939-camss
reg:
maxItems: 11
reg-names:
items:
- const: csiphy0
- const: csiphy0_clk_mux
- const: csiphy1
- const: csiphy1_clk_mux
- const: csid0
- const: csid1
- const: ispif
- const: csi_clk_mux
- const: vfe0
- const: csid2
- const: vfe0_vbif
clocks:
maxItems: 24
clock-names:
items:
- const: top_ahb
- const: ispif_ahb
- const: csiphy0_timer
- const: csiphy1_timer
- const: csi0_ahb
- const: csi0
- const: csi0_phy
- const: csi0_pix
- const: csi0_rdi
- const: csi1_ahb
- const: csi1
- const: csi1_phy
- const: csi1_pix
- const: csi1_rdi
- const: ahb
- const: vfe0
- const: csi_vfe0
- const: vfe_ahb
- const: vfe_axi
- const: csi2_ahb
- const: csi2
- const: csi2_phy
- const: csi2_pix
- const: csi2_rdi
interrupts:
maxItems: 7
interrupt-names:
items:
- const: csiphy0
- const: csiphy1
- const: csid0
- const: csid1
- const: ispif
- const: vfe0
- const: csid2
iommus:
maxItems: 1
power-domains:
items:
- description: VFE GDSC - Video Front End, Global Distributed Switch
Controller.
vdda-supply:
description:
Definition of the regulator used as 1.2V analog power supply.
ports:
$ref: /schemas/graph.yaml#/properties/ports
description:
CSI input ports.
patternProperties:
"^port@[0-1]$":
$ref: /schemas/graph.yaml#/$defs/port-base
unevaluatedProperties: false
description:
Input port for receiving CSI data.
properties:
endpoint:
$ref: video-interfaces.yaml#
unevaluatedProperties: false
properties:
data-lanes:
minItems: 1
maxItems: 4
bus-type:
enum:
- 4 # MEDIA_BUS_TYPE_CSI2_DPHY
required:
- data-lanes
required:
- compatible
- reg
- reg-names
- clocks
- clock-names
- interrupts
- interrupt-names
- iommus
- power-domains
- vdda-supply
- ports
additionalProperties: false
examples:
- |
#include <dt-bindings/interrupt-controller/arm-gic.h>
#include <dt-bindings/clock/qcom,gcc-msm8939.h>
isp@1b0ac00 {
compatible = "qcom,msm8939-camss";
reg = <0x01b0ac00 0x200>,
<0x01b00030 0x4>,
<0x01b0b000 0x200>,
<0x01b00038 0x4>,
<0x01b08000 0x100>,
<0x01b08400 0x100>,
<0x01b0a000 0x500>,
<0x01b00020 0x10>,
<0x01b10000 0x1000>,
<0x01b08800 0x100>,
<0x01b40000 0x200>;
reg-names = "csiphy0",
"csiphy0_clk_mux",
"csiphy1",
"csiphy1_clk_mux",
"csid0",
"csid1",
"ispif",
"csi_clk_mux",
"vfe0",
"csid2",
"vfe0_vbif";
clocks = <&gcc GCC_CAMSS_TOP_AHB_CLK>,
<&gcc GCC_CAMSS_ISPIF_AHB_CLK>,
<&gcc GCC_CAMSS_CSI0PHYTIMER_CLK>,
<&gcc GCC_CAMSS_CSI1PHYTIMER_CLK>,
<&gcc GCC_CAMSS_CSI0_AHB_CLK>,
<&gcc GCC_CAMSS_CSI0_CLK>,
<&gcc GCC_CAMSS_CSI0PHY_CLK>,
<&gcc GCC_CAMSS_CSI0PIX_CLK>,
<&gcc GCC_CAMSS_CSI0RDI_CLK>,
<&gcc GCC_CAMSS_CSI1_AHB_CLK>,
<&gcc GCC_CAMSS_CSI1_CLK>,
<&gcc GCC_CAMSS_CSI1PHY_CLK>,
<&gcc GCC_CAMSS_CSI1PIX_CLK>,
<&gcc GCC_CAMSS_CSI1RDI_CLK>,
<&gcc GCC_CAMSS_AHB_CLK>,
<&gcc GCC_CAMSS_VFE0_CLK>,
<&gcc GCC_CAMSS_CSI_VFE0_CLK>,
<&gcc GCC_CAMSS_VFE_AHB_CLK>,
<&gcc GCC_CAMSS_VFE_AXI_CLK>,
<&gcc GCC_CAMSS_CSI2_AHB_CLK>,
<&gcc GCC_CAMSS_CSI2_CLK>,
<&gcc GCC_CAMSS_CSI2PHY_CLK>,
<&gcc GCC_CAMSS_CSI2PIX_CLK>,
<&gcc GCC_CAMSS_CSI2RDI_CLK>;
clock-names = "top_ahb",
"ispif_ahb",
"csiphy0_timer",
"csiphy1_timer",
"csi0_ahb",
"csi0",
"csi0_phy",
"csi0_pix",
"csi0_rdi",
"csi1_ahb",
"csi1",
"csi1_phy",
"csi1_pix",
"csi1_rdi",
"ahb",
"vfe0",
"csi_vfe0",
"vfe_ahb",
"vfe_axi",
"csi2_ahb",
"csi2",
"csi2_phy",
"csi2_pix",
"csi2_rdi";
interrupts = <GIC_SPI 78 IRQ_TYPE_EDGE_RISING>,
<GIC_SPI 79 IRQ_TYPE_EDGE_RISING>,
<GIC_SPI 51 IRQ_TYPE_EDGE_RISING>,
<GIC_SPI 52 IRQ_TYPE_EDGE_RISING>,
<GIC_SPI 55 IRQ_TYPE_EDGE_RISING>,
<GIC_SPI 57 IRQ_TYPE_EDGE_RISING>,
<GIC_SPI 153 IRQ_TYPE_EDGE_RISING>;
interrupt-names = "csiphy0",
"csiphy1",
"csid0",
"csid1",
"ispif",
"vfe0",
"csid2";
iommus = <&apps_iommu 3>;
power-domains = <&gcc VFE_GDSC>;
vdda-supply = <&reg_1v2>;
ports {
#address-cells = <1>;
#size-cells = <0>;
port@1 {
reg = <1>;
csiphy1_ep: endpoint {
data-lanes = <0 2>;
remote-endpoint = <&sensor_ep>;
};
};
};
};

View File

@ -0,0 +1,375 @@
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/media/qcom,sm8650-camss.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Qualcomm SM8650 Camera Subsystem (CAMSS)
maintainers:
- Vladimir Zapolskiy <vladimir.zapolskiy@linaro.org>
description:
The CAMSS IP is a CSI decoder and ISP present on Qualcomm platforms.
properties:
compatible:
const: qcom,sm8650-camss
reg:
maxItems: 17
reg-names:
items:
- const: csid_wrapper
- const: csid0
- const: csid1
- const: csid2
- const: csid_lite0
- const: csid_lite1
- const: csiphy0
- const: csiphy1
- const: csiphy2
- const: csiphy3
- const: csiphy4
- const: csiphy5
- const: vfe0
- const: vfe1
- const: vfe2
- const: vfe_lite0
- const: vfe_lite1
clocks:
maxItems: 33
clock-names:
items:
- const: camnoc_axi
- const: cpas_ahb
- const: cpas_fast_ahb
- const: cpas_vfe0
- const: cpas_vfe1
- const: cpas_vfe2
- const: cpas_vfe_lite
- const: csid
- const: csiphy0
- const: csiphy0_timer
- const: csiphy1
- const: csiphy1_timer
- const: csiphy2
- const: csiphy2_timer
- const: csiphy3
- const: csiphy3_timer
- const: csiphy4
- const: csiphy4_timer
- const: csiphy5
- const: csiphy5_timer
- const: csiphy_rx
- const: gcc_axi_hf
- const: qdss_debug_xo
- const: vfe0
- const: vfe0_fast_ahb
- const: vfe1
- const: vfe1_fast_ahb
- const: vfe2
- const: vfe2_fast_ahb
- const: vfe_lite
- const: vfe_lite_ahb
- const: vfe_lite_cphy_rx
- const: vfe_lite_csid
interrupts:
maxItems: 16
interrupt-names:
items:
- const: csid0
- const: csid1
- const: csid2
- const: csid_lite0
- const: csid_lite1
- const: csiphy0
- const: csiphy1
- const: csiphy2
- const: csiphy3
- const: csiphy4
- const: csiphy5
- const: vfe0
- const: vfe1
- const: vfe2
- const: vfe_lite0
- const: vfe_lite1
interconnects:
maxItems: 2
interconnect-names:
items:
- const: ahb
- const: hf_mnoc
iommus:
maxItems: 3
power-domains:
items:
- description: IFE0 GDSC - Image Front End, Global Distributed Switch Controller.
- description: IFE1 GDSC - Image Front End, Global Distributed Switch Controller.
- description: IFE2 GDSC - Image Front End, Global Distributed Switch Controller.
- description: Titan GDSC - Titan ISP Block, Global Distributed Switch Controller.
power-domain-names:
items:
- const: ife0
- const: ife1
- const: ife2
- const: top
ports:
$ref: /schemas/graph.yaml#/properties/ports
description:
CSI input ports.
patternProperties:
"^port@[0-5]$":
$ref: /schemas/graph.yaml#/$defs/port-base
unevaluatedProperties: false
description:
Input port for receiving CSI data from a CSIPHY.
properties:
endpoint:
$ref: video-interfaces.yaml#
unevaluatedProperties: false
properties:
data-lanes:
minItems: 1
maxItems: 4
bus-type:
enum:
- 1 # MEDIA_BUS_TYPE_CSI2_CPHY
- 4 # MEDIA_BUS_TYPE_CSI2_DPHY
required:
- data-lanes
vdd-csiphy01-0p9-supply:
description:
Phandle to a 0.9V regulator supply to CSIPHY0 and CSIPHY1 IP blocks.
vdd-csiphy01-1p2-supply:
description:
Phandle to a 1.2V regulator supply to CSIPHY0 and CSIPHY1 IP blocks.
vdd-csiphy24-0p9-supply:
description:
Phandle to a 0.9V regulator supply to CSIPHY2 and CSIPHY4 IP blocks.
vdd-csiphy24-1p2-supply:
description:
Phandle to a 1.2V regulator supply to CSIPHY2 and CSIPHY4 IP blocks.
vdd-csiphy35-0p9-supply:
description:
Phandle to a 0.9V regulator supply to CSIPHY3 and CSIPHY5 IP blocks.
vdd-csiphy35-1p2-supply:
description:
Phandle to a 1.2V regulator supply to CSIPHY3 and CSIPHY5 IP blocks.
required:
- compatible
- reg
- reg-names
- clocks
- clock-names
- interconnects
- interconnect-names
- interrupts
- interrupt-names
- iommus
- power-domains
- power-domain-names
additionalProperties: false
examples:
- |
#include <dt-bindings/clock/qcom,sm8650-camcc.h>
#include <dt-bindings/clock/qcom,sm8650-gcc.h>
#include <dt-bindings/interconnect/qcom,sm8650-rpmh.h>
#include <dt-bindings/interrupt-controller/arm-gic.h>
soc {
#address-cells = <2>;
#size-cells = <2>;
isp@acb6000 {
compatible = "qcom,sm8650-camss";
reg = <0 0x0acb6000 0 0x1000>,
<0 0x0acb8000 0 0x1000>,
<0 0x0acba000 0 0x1000>,
<0 0x0acbc000 0 0x1000>,
<0 0x0accb000 0 0x1000>,
<0 0x0acd0000 0 0x1000>,
<0 0x0ace4000 0 0x2000>,
<0 0x0ace6000 0 0x2000>,
<0 0x0ace8000 0 0x2000>,
<0 0x0acea000 0 0x2000>,
<0 0x0acec000 0 0x2000>,
<0 0x0acee000 0 0x2000>,
<0 0x0ac62000 0 0xf000>,
<0 0x0ac71000 0 0xf000>,
<0 0x0ac80000 0 0xf000>,
<0 0x0accc000 0 0x2000>,
<0 0x0acd1000 0 0x2000>;
reg-names = "csid_wrapper",
"csid0",
"csid1",
"csid2",
"csid_lite0",
"csid_lite1",
"csiphy0",
"csiphy1",
"csiphy2",
"csiphy3",
"csiphy4",
"csiphy5",
"vfe0",
"vfe1",
"vfe2",
"vfe_lite0",
"vfe_lite1";
clocks = <&camcc CAM_CC_CAMNOC_AXI_RT_CLK>,
<&camcc CAM_CC_CPAS_AHB_CLK>,
<&camcc CAM_CC_CPAS_FAST_AHB_CLK>,
<&camcc CAM_CC_CPAS_IFE_0_CLK>,
<&camcc CAM_CC_CPAS_IFE_1_CLK>,
<&camcc CAM_CC_CPAS_IFE_2_CLK>,
<&camcc CAM_CC_CPAS_IFE_LITE_CLK>,
<&camcc CAM_CC_CSID_CLK>,
<&camcc CAM_CC_CSIPHY0_CLK>,
<&camcc CAM_CC_CSI0PHYTIMER_CLK>,
<&camcc CAM_CC_CSI1PHYTIMER_CLK>,
<&camcc CAM_CC_CSIPHY1_CLK>,
<&camcc CAM_CC_CSI2PHYTIMER_CLK>,
<&camcc CAM_CC_CSIPHY2_CLK>,
<&camcc CAM_CC_CSI3PHYTIMER_CLK>,
<&camcc CAM_CC_CSIPHY3_CLK>,
<&camcc CAM_CC_CSI4PHYTIMER_CLK>,
<&camcc CAM_CC_CSIPHY4_CLK>,
<&camcc CAM_CC_CSI5PHYTIMER_CLK>,
<&camcc CAM_CC_CSIPHY5_CLK>,
<&camcc CAM_CC_CSID_CSIPHY_RX_CLK>,
<&gcc GCC_CAMERA_HF_AXI_CLK>,
<&camcc CAM_CC_QDSS_DEBUG_XO_CLK>,
<&camcc CAM_CC_IFE_0_CLK>,
<&camcc CAM_CC_IFE_0_FAST_AHB_CLK>,
<&camcc CAM_CC_IFE_1_CLK>,
<&camcc CAM_CC_IFE_1_FAST_AHB_CLK>,
<&camcc CAM_CC_IFE_2_CLK>,
<&camcc CAM_CC_IFE_2_FAST_AHB_CLK>,
<&camcc CAM_CC_IFE_LITE_CLK>,
<&camcc CAM_CC_IFE_LITE_AHB_CLK>,
<&camcc CAM_CC_IFE_LITE_CPHY_RX_CLK>,
<&camcc CAM_CC_IFE_LITE_CSID_CLK>;
clock-names = "camnoc_axi",
"cpas_ahb",
"cpas_fast_ahb",
"cpas_vfe0",
"cpas_vfe1",
"cpas_vfe2",
"cpas_vfe_lite",
"csid",
"csiphy0",
"csiphy0_timer",
"csiphy1",
"csiphy1_timer",
"csiphy2",
"csiphy2_timer",
"csiphy3",
"csiphy3_timer",
"csiphy4",
"csiphy4_timer",
"csiphy5",
"csiphy5_timer",
"csiphy_rx",
"gcc_axi_hf",
"qdss_debug_xo",
"vfe0",
"vfe0_fast_ahb",
"vfe1",
"vfe1_fast_ahb",
"vfe2",
"vfe2_fast_ahb",
"vfe_lite",
"vfe_lite_ahb",
"vfe_lite_cphy_rx",
"vfe_lite_csid";
interrupts = <GIC_SPI 601 IRQ_TYPE_EDGE_RISING>,
<GIC_SPI 603 IRQ_TYPE_EDGE_RISING>,
<GIC_SPI 431 IRQ_TYPE_EDGE_RISING>,
<GIC_SPI 605 IRQ_TYPE_EDGE_RISING>,
<GIC_SPI 376 IRQ_TYPE_EDGE_RISING>,
<GIC_SPI 477 IRQ_TYPE_EDGE_RISING>,
<GIC_SPI 478 IRQ_TYPE_EDGE_RISING>,
<GIC_SPI 479 IRQ_TYPE_EDGE_RISING>,
<GIC_SPI 448 IRQ_TYPE_EDGE_RISING>,
<GIC_SPI 122 IRQ_TYPE_EDGE_RISING>,
<GIC_SPI 89 IRQ_TYPE_EDGE_RISING>,
<GIC_SPI 602 IRQ_TYPE_EDGE_RISING>,
<GIC_SPI 604 IRQ_TYPE_EDGE_RISING>,
<GIC_SPI 688 IRQ_TYPE_EDGE_RISING>,
<GIC_SPI 606 IRQ_TYPE_EDGE_RISING>,
<GIC_SPI 377 IRQ_TYPE_EDGE_RISING>;
interrupt-names = "csid0",
"csid1",
"csid2",
"csid_lite0",
"csid_lite1",
"csiphy0",
"csiphy1",
"csiphy2",
"csiphy3",
"csiphy4",
"csiphy5",
"vfe0",
"vfe1",
"vfe2",
"vfe_lite0",
"vfe_lite1";
interconnects = <&gem_noc MASTER_APPSS_PROC 0
&config_noc SLAVE_CAMERA_CFG 0>,
<&mmss_noc MASTER_CAMNOC_HF 0
&mc_virt SLAVE_EBI1 0>;
interconnect-names = "ahb", "hf_mnoc";
iommus = <&apps_smmu 0x800 0x20>,
<&apps_smmu 0x18a0 0x40>,
<&apps_smmu 0x1860 0x00>;
power-domains = <&camcc CAM_CC_IFE_0_GDSC>,
<&camcc CAM_CC_IFE_1_GDSC>,
<&camcc CAM_CC_IFE_2_GDSC>,
<&camcc CAM_CC_TITAN_TOP_GDSC>;
power-domain-names = "ife0", "ife1", "ife2", "top";
vdd-csiphy01-0p9-supply = <&vreg_0p9>;
vdd-csiphy01-1p2-supply = <&vreg_1p2>;
ports {
#address-cells = <1>;
#size-cells = <0>;
port@1 {
reg = <1>;
csiphy1_ep: endpoint {
data-lanes = <0 1>;
remote-endpoint = <&camera_sensor>;
};
};
};
};
};

View File

@ -124,7 +124,7 @@ properties:
vdd-csiphy-1p2-supply:
description:
Phandle to 1.8V regulator supply to a PHY.
Phandle to 1.2V regulator supply to a PHY.
ports:
$ref: /schemas/graph.yaml#/properties/ports

View File

@ -0,0 +1,103 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/media/renesas,r9a09g057-ivc.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Renesas RZ/V2H(P) Input Video Control Block
maintainers:
- Daniel Scally <dan.scally@ideasonboard.com>
description:
The IVC block is a module that takes video frames from memory and feeds them
to the Image Signal Processor for processing.
properties:
compatible:
const: renesas,r9a09g057-ivc # RZ/V2H(P)
reg:
maxItems: 1
interrupts:
maxItems: 1
clocks:
items:
- description: Input Video Control block register access clock
- description: Video input data AXI bus clock
- description: ISP system clock
clock-names:
items:
- const: reg
- const: axi
- const: isp
power-domains:
maxItems: 1
resets:
items:
- description: Input Video Control block register access reset
- description: Video input data AXI bus reset
- description: ISP core reset
reset-names:
items:
- const: reg
- const: axi
- const: isp
port:
$ref: /schemas/graph.yaml#/properties/port
description: Output parallel video bus
properties:
endpoint:
$ref: /schemas/graph.yaml#/properties/endpoint
required:
- compatible
- reg
- interrupts
- clocks
- clock-names
- power-domains
- resets
- reset-names
- port
additionalProperties: false
examples:
- |
#include <dt-bindings/clock/renesas,r9a09g057-cpg.h>
#include <dt-bindings/interrupt-controller/arm-gic.h>
isp-input@16040000 {
compatible = "renesas,r9a09g057-ivc";
reg = <0x16040000 0x230>;
clocks = <&cpg CPG_MOD 0xe3>,
<&cpg CPG_MOD 0xe4>,
<&cpg CPG_MOD 0xe5>;
clock-names = "reg", "axi", "isp";
power-domains = <&cpg>;
resets = <&cpg 0xd4>,
<&cpg 0xd1>,
<&cpg 0xd3>;
reset-names = "reg", "axi", "isp";
interrupts = <GIC_SPI 861 IRQ_TYPE_EDGE_RISING>;
port {
ivc_out: endpoint {
remote-endpoint = <&isp_in>;
};
};
};
...

View File

@ -0,0 +1,124 @@
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/media/rockchip,px30-vip.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Rockchip PX30 Video Input Processor (VIP)
maintainers:
- Mehdi Djait <mehdi.djait@linux.intel.com>
- Michael Riesch <michael.riesch@collabora.com>
description:
The Rockchip PX30 Video Input Processor (VIP) receives the data from a camera
sensor or CCIR656 encoder and transfers it into system main memory by AXI bus.
properties:
compatible:
const: rockchip,px30-vip
reg:
maxItems: 1
interrupts:
maxItems: 1
clocks:
items:
- description: ACLK
- description: HCLK
- description: PCLK
clock-names:
items:
- const: aclk
- const: hclk
- const: pclk
resets:
items:
- description: AXI
- description: AHB
- description: PCLK IN
reset-names:
items:
- const: axi
- const: ahb
- const: pclkin
power-domains:
maxItems: 1
ports:
$ref: /schemas/graph.yaml#/properties/ports
properties:
port@0:
$ref: /schemas/graph.yaml#/$defs/port-base
unevaluatedProperties: false
description: input port on the parallel interface
properties:
endpoint:
$ref: video-interfaces.yaml#
unevaluatedProperties: false
properties:
bus-type:
enum:
- 5 # MEDIA_BUS_TYPE_PARALLEL
- 6 # MEDIA_BUS_TYPE_BT656
required:
- bus-type
required:
- port@0
required:
- compatible
- reg
- interrupts
- clocks
- ports
additionalProperties: false
examples:
- |
#include <dt-bindings/clock/px30-cru.h>
#include <dt-bindings/interrupt-controller/arm-gic.h>
#include <dt-bindings/media/video-interfaces.h>
#include <dt-bindings/power/px30-power.h>
soc {
#address-cells = <2>;
#size-cells = <2>;
video-capture@ff490000 {
compatible = "rockchip,px30-vip";
reg = <0x0 0xff490000 0x0 0x200>;
interrupts = <GIC_SPI 69 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&cru ACLK_CIF>, <&cru HCLK_CIF>, <&cru PCLK_CIF>;
clock-names = "aclk", "hclk", "pclk";
power-domains = <&power PX30_PD_VI>;
resets = <&cru SRST_CIF_A>, <&cru SRST_CIF_H>, <&cru SRST_CIF_PCLKIN>;
reset-names = "axi", "ahb", "pclkin";
ports {
#address-cells = <1>;
#size-cells = <0>;
port@0 {
reg = <0>;
cif_in: endpoint {
remote-endpoint = <&tw9900_out>;
bus-type = <MEDIA_BUS_TYPE_BT656>;
};
};
};
};
};

View File

@ -0,0 +1,172 @@
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/media/rockchip,rk3568-vicap.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Rockchip RK3568 Video Capture (VICAP)
maintainers:
- Michael Riesch <michael.riesch@collabora.com>
description:
The Rockchip RK3568 Video Capture (VICAP) block features a digital video
port (DVP, a parallel video interface) and a MIPI CSI-2 port. It receives
the data from camera sensors, video decoders, or other companion ICs and
transfers it into system main memory by AXI bus.
properties:
compatible:
const: rockchip,rk3568-vicap
reg:
maxItems: 1
interrupts:
maxItems: 1
clocks:
items:
- description: ACLK
- description: HCLK
- description: DCLK
- description: ICLK
clock-names:
items:
- const: aclk
- const: hclk
- const: dclk
- const: iclk
iommus:
maxItems: 1
resets:
items:
- description: ARST
- description: HRST
- description: DRST
- description: PRST
- description: IRST
reset-names:
items:
- const: arst
- const: hrst
- const: drst
- const: prst
- const: irst
rockchip,grf:
$ref: /schemas/types.yaml#/definitions/phandle
description: Phandle to general register file used for video input block control.
power-domains:
maxItems: 1
ports:
$ref: /schemas/graph.yaml#/properties/ports
properties:
port@0:
$ref: /schemas/graph.yaml#/$defs/port-base
unevaluatedProperties: false
description: The digital video port (DVP, a parallel video interface).
properties:
endpoint:
$ref: video-interfaces.yaml#
unevaluatedProperties: false
properties:
bus-type:
enum:
- 5 # MEDIA_BUS_TYPE_PARALLEL
- 6 # MEDIA_BUS_TYPE_BT656
rockchip,dvp-clk-delay:
$ref: /schemas/types.yaml#/definitions/uint32
default: 0
minimum: 0
maximum: 127
description:
Delay the DVP path clock input to align the sampling phase,
only valid in dual edge sampling mode. Delay is zero by
default and can be adjusted optionally.
required:
- bus-type
port@1:
$ref: /schemas/graph.yaml#/properties/port
description: Port connected to the MIPI CSI-2 receiver output.
properties:
endpoint:
$ref: video-interfaces.yaml#
unevaluatedProperties: false
required:
- compatible
- reg
- interrupts
- clocks
- ports
additionalProperties: false
examples:
- |
#include <dt-bindings/clock/rk3568-cru.h>
#include <dt-bindings/interrupt-controller/arm-gic.h>
#include <dt-bindings/interrupt-controller/irq.h>
#include <dt-bindings/power/rk3568-power.h>
#include <dt-bindings/media/video-interfaces.h>
soc {
#address-cells = <2>;
#size-cells = <2>;
vicap: video-capture@fdfe0000 {
compatible = "rockchip,rk3568-vicap";
reg = <0x0 0xfdfe0000 0x0 0x200>;
interrupts = <GIC_SPI 146 IRQ_TYPE_LEVEL_HIGH>;
assigned-clocks = <&cru DCLK_VICAP>;
assigned-clock-rates = <300000000>;
clocks = <&cru ACLK_VICAP>, <&cru HCLK_VICAP>,
<&cru DCLK_VICAP>, <&cru ICLK_VICAP_G>;
clock-names = "aclk", "hclk", "dclk", "iclk";
iommus = <&vicap_mmu>;
power-domains = <&power RK3568_PD_VI>;
resets = <&cru SRST_A_VICAP>, <&cru SRST_H_VICAP>,
<&cru SRST_D_VICAP>, <&cru SRST_P_VICAP>,
<&cru SRST_I_VICAP>;
reset-names = "arst", "hrst", "drst", "prst", "irst";
rockchip,grf = <&grf>;
ports {
#address-cells = <1>;
#size-cells = <0>;
vicap_dvp: port@0 {
reg = <0>;
vicap_dvp_input: endpoint {
bus-type = <MEDIA_BUS_TYPE_BT656>;
bus-width = <16>;
pclk-sample = <MEDIA_PCLK_SAMPLE_DUAL_EDGE>;
remote-endpoint = <&it6801_output>;
};
};
vicap_mipi: port@1 {
reg = <1>;
vicap_mipi_input: endpoint {
remote-endpoint = <&csi_output>;
};
};
};
};
};

View File

@ -16,6 +16,7 @@ description: |-
properties:
compatible:
oneOf:
- const: rockchip,rk3288-vdec
- const: rockchip,rk3399-vdec
- const: rockchip,rk3576-vdec
- const: rockchip,rk3588-vdec

View File

@ -8,7 +8,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
title: Synopsys DesignWare HDMI RX Controller
maintainers:
- Shreeya Patel <shreeya.patel@collabora.com>
- Dmitry Osipenko <dmitry.osipenko@collabora.com>
description:
Synopsys DesignWare HDMI Input Controller preset on RK3588 SoCs

View File

@ -1,88 +0,0 @@
STMicroelectronics STi c8sectpfe binding
============================================
This document describes the c8sectpfe device bindings that is used to get transport
stream data into the SoC on the TS pins, and into DDR for further processing.
It is typically used in conjunction with one or more demodulator and tuner devices
which converts from the RF to digital domain. Demodulators and tuners are usually
located on an external DVB frontend card connected to SoC TS input pins.
Currently 7 TS input (tsin) channels are supported on the stih407 family SoC.
Required properties (controller (parent) node):
- compatible : Should be "stih407-c8sectpfe"
- reg : Address and length of register sets for each device in
"reg-names"
- reg-names : The names of the register addresses corresponding to the
registers filled in "reg":
- c8sectpfe: c8sectpfe registers
- c8sectpfe-ram: c8sectpfe internal sram
- clocks : phandle list of c8sectpfe clocks
- clock-names : should be "c8sectpfe"
See: Documentation/devicetree/bindings/clock/clock-bindings.txt
- pinctrl-names : a pinctrl state named tsin%d-serial or tsin%d-parallel (where %d is tsin-num)
must be defined for each tsin child node.
- pinctrl-0 : phandle referencing pin configuration for this tsin configuration
See: Documentation/devicetree/bindings/pinctrl/pinctrl-bindings.txt
Required properties (tsin (child) node):
- tsin-num : tsin id of the InputBlock (must be between 0 to 6)
- i2c-bus : phandle to the I2C bus DT node which the demodulators & tuners on this tsin channel are connected.
- reset-gpios : reset gpio for this tsin channel.
Optional properties (tsin (child) node):
- invert-ts-clk : Bool property to control sense of ts input clock (data stored on falling edge of clk).
- serial-not-parallel : Bool property to configure input bus width (serial on ts_data<7>).
- async-not-sync : Bool property to control if data is received in asynchronous mode
(all bits/bytes with ts_valid or ts_packet asserted are valid).
- dvb-card : Describes the NIM card connected to this tsin channel.
Example:
/* stih410 SoC b2120 + b2004a + stv0367-pll(NIMB) + stv0367-tda18212 (NIMA) DT example) */
c8sectpfe@8a20000 {
compatible = "st,stih407-c8sectpfe";
reg = <0x08a20000 0x10000>, <0x08a00000 0x4000>;
reg-names = "stfe", "stfe-ram";
interrupts = <GIC_SPI 34 IRQ_TYPE_NONE>, <GIC_SPI 35 IRQ_TYPE_NONE>;
interrupt-names = "stfe-error-irq", "stfe-idle-irq";
pinctrl-0 = <&pinctrl_tsin0_serial>;
pinctrl-1 = <&pinctrl_tsin0_parallel>;
pinctrl-2 = <&pinctrl_tsin3_serial>;
pinctrl-3 = <&pinctrl_tsin4_serial_alt3>;
pinctrl-4 = <&pinctrl_tsin5_serial_alt1>;
pinctrl-names = "tsin0-serial",
"tsin0-parallel",
"tsin3-serial",
"tsin4-serial",
"tsin5-serial";
clocks = <&clk_s_c0_flexgen CLK_PROC_STFE>;
clock-names = "c8sectpfe";
/* tsin0 is TSA on NIMA */
tsin0: port@0 {
tsin-num = <0>;
serial-not-parallel;
i2c-bus = <&ssc2>;
reset-gpios = <&pio15 4 GPIO_ACTIVE_HIGH>;
dvb-card = <STV0367_TDA18212_NIMA_1>;
};
tsin3: port@3 {
tsin-num = <3>;
serial-not-parallel;
i2c-bus = <&ssc3>;
reset-gpios = <&pio15 7 GPIO_ACTIVE_HIGH>;
dvb-card = <STV0367_TDA18212_NIMB_1>;
};
};

View File

@ -95,7 +95,7 @@ properties:
- 6 # BT.656
- 7 # DPI
description:
Data bus type.
Data bus type. See include/dt-bindings/media/video-interfaces.h.
bus-width:
$ref: /schemas/types.yaml#/definitions/uint32
@ -229,7 +229,7 @@ properties:
Imaging. The length of the array must be the same length as the
data-lanes property. If the line-orders property is omitted, the value
shall be interpreted as 0 (ABC). This property is valid for CSI-2 C-PHY
busses only.
busses only. See include/dt-bindings/media/video-interfaces.h.
strobe:
$ref: /schemas/types.yaml#/definitions/uint32

View File

@ -27,3 +27,4 @@ Video4Linux devices
v4l2-common
v4l2-tveeprom
v4l2-jpeg
v4l2-isp

View File

@ -0,0 +1,49 @@
.. SPDX-License-Identifier: GPL-2.0
V4L2 generic ISP parameters and statistics support
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Design rationale
================
ISP configuration parameters and statistics are processed and collected by
drivers and exchanged with userspace through data types that usually
reflect the ISP peripheral registers layout.
Each ISP driver defines its own metadata output format for parameters and
a metadata capture format for statistics. The buffer layout is realized by a
set of C structures that reflects the registers layout. The number and types
of C structures is fixed by the format definition and becomes part of the Linux
kernel uAPI/uABI interface.
Because of the hard requirement of backward compatibility when extending the
user API/ABI interface, modifying an ISP driver capture or output metadata
format after it has been accepted by mainline is very hard if not impossible.
It generally happens, in fact, that after the first accepted revision of an ISP
driver the buffers layout need to be modified, either to support new hardware
blocks, to fix bugs or to support different revisions of the hardware.
Each of these situations would require defining a new metadata format, making it
really hard to maintain and extend drivers and requiring userspace to use
the correct format depending on the kernel revision in use.
V4L2 ISP configuration parameters
=================================
For these reasons, Video4Linux2 defines generic types for ISP configuration
parameters and statistics. Drivers are still expected to define their own
formats for their metadata output and capture nodes, but the buffers layout can
be defined using the extensible and versioned types defined by
include/uapi/linux/media/v4l2-isp.h.
Drivers are expected to provide the definitions of their supported ISP blocks
and the expected maximum size of a buffer.
For driver developers a set of helper functions to assist them with validation
of the buffer received from userspace is available in
drivers/media/v4l2-core/v4l2-isp.c
V4L2 ISP support driver documentation
=====================================
.. kernel-doc:: include/media/v4l2-isp.h

View File

@ -32,6 +32,7 @@ For more details see the file COPYING in the source distribution of Linux.
cx2341x-uapi
dw100
imx-uapi
mali-c55
max2175
npcm-video
omap3isp-uapi

View File

@ -0,0 +1,55 @@
.. SPDX-License-Identifier: GPL-2.0-only
Arm Mali-C55 ISP driver
=======================
The Arm Mali-C55 ISP driver implements a single driver-specific control:
``V4L2_CID_MALI_C55_CAPABILITIES (bitmask)``
Detail the capabilities of the ISP by giving detail about the fitted blocks.
.. flat-table:: Bitmask meaning definitions
:header-rows: 1
:widths: 2 4 8
* - Bit
- Macro
- Meaning
* - 0
- MALI_C55_PONG
- Pong configuration space is fitted in the ISP
* - 1
- MALI_C55_WDR
- WDR Framestitch, offset and gain is fitted in the ISP
* - 2
- MALI_C55_COMPRESSION
- Temper compression is fitted in the ISP
* - 3
- MALI_C55_TEMPER
- Temper is fitted in the ISP
* - 4
- MALI_C55_SINTER_LITE
- Sinter Lite is fitted in the ISP instead of the full Sinter version
* - 5
- MALI_C55_SINTER
- Sinter is fitted in the ISP
* - 6
- MALI_C55_IRIDIX_LTM
- Iridix local tone mappine is fitted in the ISP
* - 7
- MALI_C55_IRIDIX_GTM
- Iridix global tone mapping is fitted in the ISP
* - 8
- MALI_C55_CNR
- Colour noise reduction is fitted in the ISP
* - 9
- MALI_C55_FRSCALER
- The full resolution pipe scaler is fitted in the ISP
* - 10
- MALI_C55_DS_PIPE
- The downscale pipe is fitted in the ISP
The Mali-C55 ISP can be configured in a number of ways to include or exclude
blocks which may not be necessary. This control provides a way for the
driver to communicate to userspace which of the blocks are fitted in the
design.

View File

@ -13,6 +13,7 @@ These formats are used for the :ref:`metadata` interface only.
.. toctree::
:maxdepth: 1
metafmt-arm-mali-c55
metafmt-c3-isp
metafmt-d4xx
metafmt-generic
@ -25,3 +26,4 @@ These formats are used for the :ref:`metadata` interface only.
metafmt-vivid
metafmt-vsp1-hgo
metafmt-vsp1-hgt
v4l2-isp

View File

@ -0,0 +1,84 @@
.. SPDX-License-Identifier: GPL-2.0
.. _v4l2-meta-fmt-mali-c55-params:
.. _v4l2-meta-fmt-mali-c55-stats:
*****************************************************************************
V4L2_META_FMT_MALI_C55_STATS ('C55S'), V4L2_META_FMT_MALI_C55_PARAMS ('C55P')
*****************************************************************************
3A Statistics
=============
The ISP device collects different statistics over an input bayer frame. Those
statistics can be obtained by userspace from the
:ref:`mali-c55 3a stats <mali-c55-3a-stats>` metadata capture video node, using
the :c:type:`v4l2_meta_format` interface. The buffer contains a single instance
of the C structure :c:type:`mali_c55_stats_buffer` defined in
``mali-c55-config.h``, so the structure can be obtained from the buffer by:
.. code-block:: C
struct mali_c55_stats_buffer *stats =
(struct mali_c55_stats_buffer *)buf;
For details of the statistics see :c:type:`mali_c55_stats_buffer`.
Configuration Parameters
========================
The configuration parameters are passed to the :ref:`mali-c55 3a params
<mali-c55-3a-params>` metadata output video node, using the
:c:type:`v4l2_meta_format` interface. Rather than a single struct containing
sub-structs for each configurable area of the ISP, parameters for the Mali-C55
use the v4l2-isp parameters system, through which groups of parameters are
defined as distinct structs or "blocks" which may be added to the data member of
:c:type:`v4l2_isp_params_buffer`. Userspace is responsible for populating the
data member with the blocks that need to be configured by the driver. Each
block-specific struct embeds :c:type:`v4l2_isp_params_block_header` as its first
member and userspace must populate the type member with a value from
:c:type:`mali_c55_param_block_type`.
.. code-block:: c
struct v4l2_isp_params_buffer *params =
(struct v4l2_isp_params_buffer *)buffer;
params->version = MALI_C55_PARAM_BUFFER_V1;
params->data_size = 0;
void *data = (void *)params->data;
struct mali_c55_params_awb_gains *gains =
(struct mali_c55_params_awb_gains *)data;
gains->header.type = MALI_C55_PARAM_BLOCK_AWB_GAINS;
gains->header.flags |= V4L2_ISP_PARAMS_FL_BLOCK_ENABLE;
gains->header.size = sizeof(struct mali_c55_params_awb_gains);
gains->gain00 = 256;
gains->gain00 = 256;
gains->gain00 = 256;
gains->gain00 = 256;
data += sizeof(struct mali_c55_params_awb_gains);
params->data_size += sizeof(struct mali_c55_params_awb_gains);
struct mali_c55_params_sensor_off_preshading *blc =
(struct mali_c55_params_sensor_off_preshading *)data;
blc->header.type = MALI_C55_PARAM_BLOCK_SENSOR_OFFS;
blc->header.flags |= V4L2_ISP_PARAMS_FL_BLOCK_ENABLE;
blc->header.size = sizeof(struct mali_c55_params_sensor_off_preshading);
blc->chan00 = 51200;
blc->chan01 = 51200;
blc->chan10 = 51200;
blc->chan11 = 51200;
params->data_size += sizeof(struct mali_c55_params_sensor_off_preshading);
Arm Mali-C55 uAPI data types
============================
.. kernel-doc:: include/uapi/linux/media/arm/mali-c55-config.h

View File

@ -2225,6 +2225,174 @@ The following table list existing packed 48bit wide RGB formats.
\endgroup
The following table list existing packed 60bit wide RGB formats.
.. tabularcolumns:: |p{4.0cm}|p{0.7cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|
.. _v4l2-mbus-pixelcode-rgb-60:
.. raw:: latex
\begingroup
\tiny
\setlength{\tabcolsep}{2pt}
.. flat-table:: 60bit RGB formats
:header-rows: 3
:stub-columns: 0
:widths: 36 7 3 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
* - Identifier
- Code
-
- :cspan:`31` Data organization
* -
-
- Bit
-
-
-
-
- 59
- 58
- 57
- 56
- 55
- 54
- 53
- 52
- 51
- 50
- 49
- 48
- 47
- 46
- 45
- 44
- 43
- 42
- 41
- 40
- 39
- 38
- 37
- 36
- 35
- 34
- 33
- 32
* -
-
-
- 31
- 30
- 29
- 28
- 27
- 26
- 25
- 24
- 23
- 22
- 21
- 20
- 19
- 18
- 17
- 16
- 15
- 14
- 13
- 12
- 11
- 10
- 9
- 8
- 7
- 6
- 5
- 4
- 3
- 2
- 1
- 0
* .. _MEDIA-BUS-FMT-RGB202020-1X60:
- MEDIA_BUS_FMT_RGB202020_1X60
- 0x1026
-
-
-
-
-
- r\ :sub:`19`
- r\ :sub:`18`
- r\ :sub:`17`
- r\ :sub:`16`
- r\ :sub:`15`
- r\ :sub:`14`
- r\ :sub:`13`
- r\ :sub:`12`
- r\ :sub:`11`
- r\ :sub:`10`
- r\ :sub:`9`
- r\ :sub:`8`
- r\ :sub:`7`
- r\ :sub:`6`
- r\ :sub:`5`
- r\ :sub:`4`
- r\ :sub:`3`
- r\ :sub:`2`
- r\ :sub:`1`
- r\ :sub:`0`
- g\ :sub:`19`
- g\ :sub:`18`
- g\ :sub:`17`
- g\ :sub:`16`
- g\ :sub:`15`
- g\ :sub:`14`
- g\ :sub:`13`
- g\ :sub:`12`
* -
-
-
- g\ :sub:`11`
- g\ :sub:`10`
- g\ :sub:`9`
- g\ :sub:`8`
- g\ :sub:`7`
- g\ :sub:`6`
- g\ :sub:`5`
- g\ :sub:`4`
- g\ :sub:`3`
- g\ :sub:`2`
- g\ :sub:`1`
- g\ :sub:`0`
- b\ :sub:`19`
- b\ :sub:`18`
- b\ :sub:`17`
- b\ :sub:`16`
- b\ :sub:`15`
- b\ :sub:`14`
- b\ :sub:`13`
- b\ :sub:`12`
- b\ :sub:`11`
- b\ :sub:`10`
- b\ :sub:`9`
- b\ :sub:`8`
- b\ :sub:`7`
- b\ :sub:`6`
- b\ :sub:`5`
- b\ :sub:`4`
- b\ :sub:`3`
- b\ :sub:`2`
- b\ :sub:`1`
- b\ :sub:`0`
.. raw:: latex
\endgroup
On LVDS buses, usually each sample is transferred serialized in seven
time slots per pixel clock, on three (18-bit) or four (24-bit) or five (30-bit)
differential data pairs at the same time. The remaining bits are used
@ -2649,7 +2817,7 @@ organization is given as an example for the first pixel only.
\tiny
\setlength{\tabcolsep}{2pt}
.. tabularcolumns:: |p{6.0cm}|p{0.7cm}|p{0.3cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|
.. tabularcolumns:: |p{6.0cm}|p{0.7cm}|p{0.3cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|
.. _v4l2-mbus-pixelcode-bayer:
@ -2662,10 +2830,14 @@ organization is given as an example for the first pixel only.
* - Identifier
- Code
-
- :cspan:`15` Data organization
- :cspan:`19` Data organization
* -
-
- Bit
- 19
- 18
- 17
- 16
- 15
- 14
- 13
@ -2695,6 +2867,10 @@ organization is given as an example for the first pixel only.
-
-
-
-
-
-
-
- b\ :sub:`7`
- b\ :sub:`6`
- b\ :sub:`5`
@ -2716,6 +2892,10 @@ organization is given as an example for the first pixel only.
-
-
-
-
-
-
-
- g\ :sub:`7`
- g\ :sub:`6`
- g\ :sub:`5`
@ -2737,6 +2917,10 @@ organization is given as an example for the first pixel only.
-
-
-
-
-
-
-
- g\ :sub:`7`
- g\ :sub:`6`
- g\ :sub:`5`
@ -2758,6 +2942,10 @@ organization is given as an example for the first pixel only.
-
-
-
-
-
-
-
- r\ :sub:`7`
- r\ :sub:`6`
- r\ :sub:`5`
@ -2779,6 +2967,10 @@ organization is given as an example for the first pixel only.
-
-
-
-
-
-
-
- b\ :sub:`7`
- b\ :sub:`6`
- b\ :sub:`5`
@ -2800,6 +2992,10 @@ organization is given as an example for the first pixel only.
-
-
-
-
-
-
-
- g\ :sub:`7`
- g\ :sub:`6`
- g\ :sub:`5`
@ -2821,6 +3017,10 @@ organization is given as an example for the first pixel only.
-
-
-
-
-
-
-
- g\ :sub:`7`
- g\ :sub:`6`
- g\ :sub:`5`
@ -2842,6 +3042,10 @@ organization is given as an example for the first pixel only.
-
-
-
-
-
-
-
- r\ :sub:`7`
- r\ :sub:`6`
- r\ :sub:`5`
@ -2863,6 +3067,10 @@ organization is given as an example for the first pixel only.
-
-
-
-
-
-
-
- b\ :sub:`7`
- b\ :sub:`6`
- b\ :sub:`5`
@ -2884,6 +3092,10 @@ organization is given as an example for the first pixel only.
-
-
-
-
-
-
-
- g\ :sub:`7`
- g\ :sub:`6`
- g\ :sub:`5`
@ -2905,6 +3117,10 @@ organization is given as an example for the first pixel only.
-
-
-
-
-
-
-
- g\ :sub:`7`
- g\ :sub:`6`
- g\ :sub:`5`
@ -2926,6 +3142,10 @@ organization is given as an example for the first pixel only.
-
-
-
-
-
-
-
- r\ :sub:`7`
- r\ :sub:`6`
- r\ :sub:`5`
@ -2947,6 +3167,10 @@ organization is given as an example for the first pixel only.
-
-
-
-
-
-
-
- 0
- 0
- 0
@ -2966,6 +3190,10 @@ organization is given as an example for the first pixel only.
-
-
-
-
-
-
-
- b\ :sub:`7`
- b\ :sub:`6`
- b\ :sub:`5`
@ -2987,6 +3215,10 @@ organization is given as an example for the first pixel only.
-
-
-
-
-
-
-
- b\ :sub:`7`
- b\ :sub:`6`
- b\ :sub:`5`
@ -3006,6 +3238,10 @@ organization is given as an example for the first pixel only.
-
-
-
-
-
-
-
- 0
- 0
- 0
@ -3027,6 +3263,10 @@ organization is given as an example for the first pixel only.
-
-
-
-
-
-
-
- b\ :sub:`9`
- b\ :sub:`8`
- b\ :sub:`7`
@ -3046,6 +3286,10 @@ organization is given as an example for the first pixel only.
-
-
-
-
-
-
-
- b\ :sub:`1`
- b\ :sub:`0`
- 0
@ -3067,6 +3311,10 @@ organization is given as an example for the first pixel only.
-
-
-
-
-
-
-
- b\ :sub:`1`
- b\ :sub:`0`
- 0
@ -3086,6 +3334,10 @@ organization is given as an example for the first pixel only.
-
-
-
-
-
-
-
- b\ :sub:`9`
- b\ :sub:`8`
- b\ :sub:`7`
@ -3105,6 +3357,10 @@ organization is given as an example for the first pixel only.
-
-
-
-
-
-
-
- b\ :sub:`9`
- b\ :sub:`8`
- b\ :sub:`7`
@ -3126,6 +3382,10 @@ organization is given as an example for the first pixel only.
-
-
-
-
-
-
-
- g\ :sub:`9`
- g\ :sub:`8`
- g\ :sub:`7`
@ -3147,6 +3407,10 @@ organization is given as an example for the first pixel only.
-
-
-
-
-
-
-
- g\ :sub:`9`
- g\ :sub:`8`
- g\ :sub:`7`
@ -3168,6 +3432,10 @@ organization is given as an example for the first pixel only.
-
-
-
-
-
-
-
- r\ :sub:`9`
- r\ :sub:`8`
- r\ :sub:`7`
@ -3187,6 +3455,10 @@ organization is given as an example for the first pixel only.
-
-
-
-
-
-
-
- b\ :sub:`11`
- b\ :sub:`10`
- b\ :sub:`9`
@ -3208,6 +3480,10 @@ organization is given as an example for the first pixel only.
-
-
-
-
-
-
-
- g\ :sub:`11`
- g\ :sub:`10`
- g\ :sub:`9`
@ -3229,6 +3505,10 @@ organization is given as an example for the first pixel only.
-
-
-
-
-
-
-
- g\ :sub:`11`
- g\ :sub:`10`
- g\ :sub:`9`
@ -3250,6 +3530,10 @@ organization is given as an example for the first pixel only.
-
-
-
-
-
-
-
- r\ :sub:`11`
- r\ :sub:`10`
- r\ :sub:`9`
@ -3269,6 +3553,10 @@ organization is given as an example for the first pixel only.
-
-
-
-
-
-
-
- b\ :sub:`13`
- b\ :sub:`12`
- b\ :sub:`11`
@ -3290,6 +3578,10 @@ organization is given as an example for the first pixel only.
-
-
-
-
-
-
-
- g\ :sub:`13`
- g\ :sub:`12`
- g\ :sub:`11`
@ -3311,6 +3603,10 @@ organization is given as an example for the first pixel only.
-
-
-
-
-
-
-
- g\ :sub:`13`
- g\ :sub:`12`
- g\ :sub:`11`
@ -3332,6 +3628,10 @@ organization is given as an example for the first pixel only.
-
-
-
-
-
-
-
- r\ :sub:`13`
- r\ :sub:`12`
- r\ :sub:`11`
@ -3351,6 +3651,10 @@ organization is given as an example for the first pixel only.
- MEDIA_BUS_FMT_SBGGR16_1X16
- 0x301d
-
-
-
-
-
- b\ :sub:`15`
- b\ :sub:`14`
- b\ :sub:`13`
@ -3372,6 +3676,10 @@ organization is given as an example for the first pixel only.
- MEDIA_BUS_FMT_SGBRG16_1X16
- 0x301e
-
-
-
-
-
- g\ :sub:`15`
- g\ :sub:`14`
- g\ :sub:`13`
@ -3393,6 +3701,10 @@ organization is given as an example for the first pixel only.
- MEDIA_BUS_FMT_SGRBG16_1X16
- 0x301f
-
-
-
-
-
- g\ :sub:`15`
- g\ :sub:`14`
- g\ :sub:`13`
@ -3414,6 +3726,110 @@ organization is given as an example for the first pixel only.
- MEDIA_BUS_FMT_SRGGB16_1X16
- 0x3020
-
-
-
-
-
- r\ :sub:`15`
- r\ :sub:`14`
- r\ :sub:`13`
- r\ :sub:`12`
- r\ :sub:`11`
- r\ :sub:`10`
- r\ :sub:`9`
- r\ :sub:`8`
- r\ :sub:`7`
- r\ :sub:`6`
- r\ :sub:`5`
- r\ :sub:`4`
- r\ :sub:`3`
- r\ :sub:`2`
- r\ :sub:`1`
- r\ :sub:`0`
* .. _MEDIA-BUS-FMT-SBGGR20-1X20:
- MEDIA_BUS_FMT_SBGGR20_1X20
- 0x3021
-
- b\ :sub:`19`
- b\ :sub:`18`
- b\ :sub:`17`
- b\ :sub:`16`
- b\ :sub:`15`
- b\ :sub:`14`
- b\ :sub:`13`
- b\ :sub:`12`
- b\ :sub:`11`
- b\ :sub:`10`
- b\ :sub:`9`
- b\ :sub:`8`
- b\ :sub:`7`
- b\ :sub:`6`
- b\ :sub:`5`
- b\ :sub:`4`
- b\ :sub:`3`
- b\ :sub:`2`
- b\ :sub:`1`
- b\ :sub:`0`
* .. _MEDIA-BUS-FMT-SGBRG20-1X20:
- MEDIA_BUS_FMT_SGBRG20_1X20
- 0x3022
-
- g\ :sub:`19`
- g\ :sub:`18`
- g\ :sub:`17`
- g\ :sub:`16`
- g\ :sub:`15`
- g\ :sub:`14`
- g\ :sub:`13`
- g\ :sub:`12`
- g\ :sub:`11`
- g\ :sub:`10`
- g\ :sub:`9`
- g\ :sub:`8`
- g\ :sub:`7`
- g\ :sub:`6`
- g\ :sub:`5`
- g\ :sub:`4`
- g\ :sub:`3`
- g\ :sub:`2`
- g\ :sub:`1`
- g\ :sub:`0`
* .. _MEDIA-BUS-FMT-SGRBG20-1X20:
- MEDIA_BUS_FMT_SGRBG20_1X20
- 0x3023
-
- g\ :sub:`19`
- g\ :sub:`18`
- g\ :sub:`17`
- g\ :sub:`16`
- g\ :sub:`15`
- g\ :sub:`14`
- g\ :sub:`13`
- g\ :sub:`12`
- g\ :sub:`11`
- g\ :sub:`10`
- g\ :sub:`9`
- g\ :sub:`8`
- g\ :sub:`7`
- g\ :sub:`6`
- g\ :sub:`5`
- g\ :sub:`4`
- g\ :sub:`3`
- g\ :sub:`2`
- g\ :sub:`1`
- g\ :sub:`0`
* .. _MEDIA-BUS-FMT-SRGGB20-1X20:
- MEDIA_BUS_FMT_SRGGB20_1X20
- 0x3024
-
- r\ :sub:`19`
- r\ :sub:`18`
- r\ :sub:`17`
- r\ :sub:`16`
- r\ :sub:`15`
- r\ :sub:`14`
- r\ :sub:`13`

View File

@ -0,0 +1,67 @@
.. SPDX-License-Identifier: GFDL-1.1-no-invariants-or-later
.. _v4l2-isp:
************************
Generic V4L2 ISP formats
************************
Generic ISP formats are metadata formats that define a mechanism to pass ISP
parameters and statistics between userspace and drivers in V4L2 buffers. They
are designed to allow extending them in a backward-compatible way.
ISP parameters
==============
The generic ISP configuration parameters format is realized by a defining a
single C structure that contains a header, followed by a binary buffer where
userspace programs a variable number of ISP configuration data block, one for
each supported ISP feature.
The :c:type:`v4l2_isp_params_buffer` structure defines the buffer header which
is followed by a binary buffer of ISP configuration data. Userspace shall
correctly populate the buffer header with the generic parameters format version
and with the size (in bytes) of the binary data buffer where it will store the
ISP blocks configuration.
Each *ISP configuration block* is preceded by an header implemented by the
:c:type:`v4l2_isp_params_block_header` structure, followed by the configuration
parameters for that specific block, defined by the ISP driver specific data
types.
Userspace applications are responsible for correctly populating each block's
header fields (type, flags and size) and the block-specific parameters.
ISP block enabling, disabling and configuration
-----------------------------------------------
When userspace wants to configure and enable an ISP block it shall fully
populate the block configuration and set the V4L2_ISP_PARAMS_FL_BLOCK_ENABLE
bit in the block header's `flags` field.
When userspace simply wants to disable an ISP block the
V4L2_ISP_PARAMS_FL_BLOCK_DISABLE bit should be set in block header's `flags`
field. Drivers accept a configuration parameters block with no additional
data after the header in this case.
If the configuration of an already active ISP block has to be updated,
userspace shall fully populate the ISP block parameters and omit setting the
V4L2_ISP_PARAMS_FL_BLOCK_ENABLE and V4L2_ISP_PARAMS_FL_BLOCK_DISABLE bits in the
header's `flags` field.
Setting both the V4L2_ISP_PARAMS_FL_BLOCK_ENABLE and
V4L2_ISP_PARAMS_FL_BLOCK_DISABLE bits in the flags field is not allowed and
returns an error.
Extension to the parameters format can be implemented by adding new blocks
definition without invalidating the existing ones.
ISP statistics
==============
Support for generic statistics format is not yet implemented in Video4Linux2.
V4L2 ISP uAPI data types
========================
.. kernel-doc:: include/uapi/linux/media/v4l2-isp.h

View File

@ -54,7 +54,7 @@ are invoked.
- ``count``
- The number of buffers to be removed with indices 'index' until 'index + count - 1'.
All buffers in this range must be valid and in DEQUEUED state.
:ref:`VIDIOC_REMOVE_BUFS` will always check the validity of ``type`, if it is
:ref:`VIDIOC_REMOVE_BUFS` will always check the validity of ``type``, if it is
invalid it returns ``EINVAL`` error code.
If count is set to 0 :ref:`VIDIOC_REMOVE_BUFS` will do nothing and return 0.
* - __u32

View File

@ -2106,6 +2106,20 @@ F: drivers/gpu/drm/ci/xfails/panfrost*
F: drivers/gpu/drm/panfrost/
F: include/uapi/drm/panfrost_drm.h
ARM MALI-C55 ISP DRIVER
M: Daniel Scally <dan.scally@ideasonboard.com>
M: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
L: linux-media@vger.kernel.org
S: Maintained
T: git git://linuxtv.org/media_tree.git
F: Documentation/admin-guide/media/mali-c55-graph.dot
F: Documentation/admin-guide/media/mali-c55.rst
F: Documentation/devicetree/bindings/media/arm,mali-c55.yaml
F: Documentation/userspace-api/media/drivers/mali-c55.rst
F: Documentation/userspace-api/media/v4l/metafmt-arm-mali-c55.rst
F: drivers/media/platform/arm/mali-c55/
F: include/uapi/linux/media/arm/mali-c55-config.h
ARM MALI PANTHOR DRM DRIVER
M: Boris Brezillon <boris.brezillon@collabora.com>
M: Steven Price <steven.price@arm.com>
@ -3443,7 +3457,6 @@ F: drivers/clocksource/clksrc_st_lpc.c
F: drivers/cpufreq/sti-cpufreq.c
F: drivers/dma/st_fdma*
F: drivers/i2c/busses/i2c-st.c
F: drivers/media/platform/st/sti/c8sectpfe/
F: drivers/media/rc/st_rc.c
F: drivers/mmc/host/sdhci-st.c
F: drivers/phy/st/phy-miphy28lp.c
@ -7483,7 +7496,7 @@ F: Documentation/devicetree/bindings/media/i2c/dongwoon,dw9714.yaml
F: drivers/media/i2c/dw9714.c
DONGWOON DW9719 LENS VOICE COIL DRIVER
M: Daniel Scally <djrscally@gmail.com>
M: Daniel Scally <dan.scally@ideasonboard.com>
L: linux-media@vger.kernel.org
S: Maintained
T: git git://linuxtv.org/media.git
@ -12622,7 +12635,7 @@ INTEL IPU3 CSI-2 CIO2 DRIVER
M: Yong Zhi <yong.zhi@intel.com>
M: Sakari Ailus <sakari.ailus@linux.intel.com>
M: Bingbu Cao <bingbu.cao@intel.com>
M: Dan Scally <djrscally@gmail.com>
M: Dan Scally <dan.scally@ideasonboard.com>
R: Tianshu Qiu <tian.shu.qiu@intel.com>
L: linux-media@vger.kernel.org
S: Maintained
@ -15545,6 +15558,8 @@ F: drivers/media/pci/ddbridge/*
MEDIA DRIVERS FOR FREESCALE IMX
M: Steve Longerbeam <slongerbeam@gmail.com>
M: Philipp Zabel <p.zabel@pengutronix.de>
R: Frank Li <Frank.Li@nxp.com>
L: imx@lists.linux.dev
L: linux-media@vger.kernel.org
S: Maintained
T: git git://linuxtv.org/media.git
@ -15559,6 +15574,8 @@ M: Rui Miguel Silva <rmfrfs@gmail.com>
M: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
M: Martin Kepplinger <martin.kepplinger@puri.sm>
R: Purism Kernel Team <kernel@puri.sm>
R: Frank Li <Frank.Li@nxp.com>
L: imx@lists.linux.dev
L: linux-media@vger.kernel.org
S: Maintained
T: git git://linuxtv.org/media.git
@ -19034,10 +19051,9 @@ T: git git://linuxtv.org/media.git
F: drivers/media/i2c/ov08d10.c
OMNIVISION OV08X40 SENSOR DRIVER
M: Jason Chen <jason.z.chen@intel.com>
M: Jimmy Su <jimmy.su@intel.com>
L: linux-media@vger.kernel.org
S: Maintained
T: git git://linuxtv.org/media.git
F: drivers/media/i2c/ov08x40.c
F: Documentation/devicetree/bindings/media/i2c/ovti,ov08x40.yaml
@ -19130,7 +19146,7 @@ F: Documentation/devicetree/bindings/media/i2c/ovti,ov5675.yaml
F: drivers/media/i2c/ov5675.c
OMNIVISION OV5693 SENSOR DRIVER
M: Daniel Scally <djrscally@gmail.com>
M: Daniel Scally <dan.scally@ideasonboard.com>
L: linux-media@vger.kernel.org
S: Maintained
T: git git://linuxtv.org/media.git
@ -21976,6 +21992,13 @@ S: Maintained
F: Documentation/devicetree/bindings/net/renesas,rzv2h-gbeth.yaml
F: drivers/net/ethernet/stmicro/stmmac/dwmac-renesas-gbeth.c
RENESAS RZ/V2H(P) INPUT VIDEO CONTROL BLOCK DRIVER
M: Daniel Scally <dan.scally@ideasonboard.com>
L: linux-media@vger.kernel.org
S: Maintained
F: Documentation/devicetree/bindings/media/renesas,r9a09g057-ivc.yaml
F: drivers/media/platform/renesas/rzv2h-ivc/
RENESAS RZ/V2H(P) RSPI DRIVER
M: Fabrizio Castro <fabrizio.castro.jz@renesas.com>
L: linux-spi@vger.kernel.org
@ -22282,6 +22305,16 @@ S: Maintained
F: Documentation/devicetree/bindings/net/can/rockchip,rk3568v2-canfd.yaml
F: drivers/net/can/rockchip/
ROCKCHIP CAMERA INTERFACE (RKCIF) DRIVER
M: Mehdi Djait <mehdi.djait@linux.intel.com>
M: Michael Riesch <michael.riesch@collabora.com>
L: linux-media@vger.kernel.org
S: Maintained
F: Documentation/admin-guide/media/rkcif*
F: Documentation/devicetree/bindings/media/rockchip,px30-vip.yaml
F: Documentation/devicetree/bindings/media/rockchip,rk3568-vicap.yaml
F: drivers/media/platform/rockchip/rkcif/
ROCKCHIP CRYPTO DRIVERS
M: Corentin Labbe <clabbe@baylibre.com>
L: linux-crypto@vger.kernel.org
@ -24973,7 +25006,7 @@ F: drivers/net/pcs/pcs-xpcs.h
F: include/linux/pcs/pcs-xpcs.h
SYNOPSYS DESIGNWARE HDMI RX CONTROLLER DRIVER
M: Shreeya Patel <shreeya.patel@collabora.com>
M: Dmitry Osipenko <dmitry.osipenko@collabora.com>
L: linux-media@vger.kernel.org
L: kernel@collabora.com
S: Maintained
@ -25166,7 +25199,7 @@ L: linux-media@vger.kernel.org
S: Maintained
W: https://linuxtv.org
Q: http://patchwork.linuxtv.org/project/linux-media/list/
F: Documentation/devicetree/bindings/media/i2c/nxp,tda1997x.txt
F: Documentation/devicetree/bindings/media/i2c/nxp,tda19971.yaml
F: drivers/media/i2c/tda1997x.*
TDA827x MEDIA DRIVER
@ -26934,6 +26967,16 @@ F: drivers/media/i2c/vd55g1.c
F: drivers/media/i2c/vd56g3.c
F: drivers/media/i2c/vgxy61.c
V4L2 GENERIC ISP PARAMETERS AND STATISTIC FORMATS
M: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
L: linux-media@vger.kernel.org
S: Maintained
F: Documentation/driver-api/media/v4l2-isp.rst
F: Documentation/userspace-api/media/v4l/v4l2-isp.rst
F: drivers/media/v4l2-core/v4l2-isp.c
F: include/media/v4l2-isp.h
F: include/uapi/linux/media/v4l2-isp.h
VF610 NAND DRIVER
M: Stefan Agner <stefan@agner.ch>
L: linux-mtd@lists.infradead.org

View File

@ -421,6 +421,7 @@ static int __init cec_devnode_init(void)
ret = bus_register(&cec_bus_type);
if (ret < 0) {
debugfs_remove_recursive(top_cec_dir);
unregister_chrdev_region(cec_dev_t, CEC_NUM_DEVICES);
pr_warn("cec: bus_register failed\n");
return -EIO;

View File

@ -186,11 +186,11 @@ static ssize_t fops_write(struct file *file, const char __user *data, size_t cou
struct saa7146_dev *dev = video_drvdata(file);
int ret;
if (vdev->vfl_type != VFL_TYPE_VBI || !dev->ext_vv_data->vbi_fops.write)
if (vdev->vfl_type != VFL_TYPE_VBI || !dev->ext_vv_data->vbi_write)
return -EINVAL;
if (mutex_lock_interruptible(vdev->lock))
return -ERESTARTSYS;
ret = dev->ext_vv_data->vbi_fops.write(file, data, count, ppos);
ret = dev->ext_vv_data->vbi_write(file, data, count, ppos);
mutex_unlock(vdev->lock);
return ret;
}

View File

@ -28,7 +28,7 @@ void sms_ir_event(struct smscore_device_t *coredev, const char *buf, int len)
for (i = 0; i < len >> 2; i++) {
struct ir_raw_event ev = {
.duration = abs(samples[i]),
.pulse = (samples[i] > 0) ? false : true
.pulse = samples[i] <= 0
};
ir_raw_event_store(coredev->ir.dev, &ev);

View File

@ -258,6 +258,7 @@ static void *vb2_dc_alloc(struct vb2_buffer *vb,
if (ret) {
dev_err(dev, "dma alloc of size %lu failed\n", size);
put_device(buf->dev);
kfree(buf);
return ERR_PTR(-ENOMEM);
}

View File

@ -1414,8 +1414,8 @@ int dvb_dmxdev_init(struct dmxdev *dmxdev, struct dvb_adapter *dvb_adapter)
if (dmxdev->demux->open(dmxdev->demux) < 0)
return -EUSERS;
dmxdev->filter = vmalloc(array_size(sizeof(struct dmxdev_filter),
dmxdev->filternum));
dmxdev->filter = vmalloc_array(dmxdev->filternum,
sizeof(struct dmxdev_filter));
if (!dmxdev->filter)
return -ENOMEM;

View File

@ -785,7 +785,7 @@ static int dvb_ca_en50221_read_data(struct dvb_ca_private *ca, int slot,
* be written.
* @bytes_write: Size of ebuf.
* @size_write_flag: A flag on Command Register which says whether the link size
* information will be writen or not.
* information will be written or not.
*
* return: Number of bytes written, or < 0 on error.
*/

View File

@ -744,7 +744,8 @@ static int dmx_ts_feed_start_filtering(struct dmx_ts_feed *ts_feed)
return -ENODEV;
}
if ((ret = demux->start_feed(feed)) < 0) {
ret = demux->start_feed(feed);
if (ret < 0) {
mutex_unlock(&demux->mutex);
return ret;
}
@ -797,7 +798,8 @@ static int dvbdmx_allocate_ts_feed(struct dmx_demux *dmx,
if (mutex_lock_interruptible(&demux->mutex))
return -ERESTARTSYS;
if (!(feed = dvb_dmx_feed_alloc(demux))) {
feed = dvb_dmx_feed_alloc(demux);
if (!feed) {
mutex_unlock(&demux->mutex);
return -EBUSY;
}
@ -817,7 +819,8 @@ static int dvbdmx_allocate_ts_feed(struct dmx_demux *dmx,
(*ts_feed)->stop_filtering = dmx_ts_feed_stop_filtering;
(*ts_feed)->set = dmx_ts_feed_set;
if (!(feed->filter = dvb_dmx_filter_alloc(demux))) {
feed->filter = dvb_dmx_filter_alloc(demux);
if (!feed->filter) {
feed->state = DMX_STATE_FREE;
mutex_unlock(&demux->mutex);
return -EBUSY;
@ -923,7 +926,8 @@ static void prepare_secfilters(struct dvb_demux_feed *dvbdmxfeed)
struct dmx_section_filter *sf;
u8 mask, mode, doneq;
if (!(f = dvbdmxfeed->filter))
f = dvbdmxfeed->filter;
if (!f)
return;
do {
sf = &f->filter;
@ -970,7 +974,8 @@ static int dmx_section_feed_start_filtering(struct dmx_section_feed *feed)
prepare_secfilters(dvbdmxfeed);
if ((ret = dvbdmx->start_feed(dvbdmxfeed)) < 0) {
ret = dvbdmx->start_feed(dvbdmxfeed);
if (ret < 0) {
mutex_unlock(&dvbdmx->mutex);
return ret;
}
@ -1057,7 +1062,8 @@ static int dvbdmx_allocate_section_feed(struct dmx_demux *demux,
if (mutex_lock_interruptible(&dvbdmx->mutex))
return -ERESTARTSYS;
if (!(dvbdmxfeed = dvb_dmx_feed_alloc(dvbdmx))) {
dvbdmxfeed = dvb_dmx_feed_alloc(dvbdmx);
if (!dvbdmxfeed) {
mutex_unlock(&dvbdmx->mutex);
return -EBUSY;
}
@ -1223,7 +1229,7 @@ static int dvbdmx_disconnect_frontend(struct dmx_demux *demux)
return 0;
}
static int dvbdmx_get_pes_pids(struct dmx_demux *demux, u16 * pids)
static int dvbdmx_get_pes_pids(struct dmx_demux *demux, u16 *pids)
{
struct dvb_demux *dvbdemux = (struct dvb_demux *)demux;
@ -1238,14 +1244,14 @@ int dvb_dmx_init(struct dvb_demux *dvbdemux)
dvbdemux->cnt_storage = NULL;
dvbdemux->users = 0;
dvbdemux->filter = vmalloc(array_size(sizeof(struct dvb_demux_filter),
dvbdemux->filternum));
dvbdemux->filter = vmalloc_array(dvbdemux->filternum,
sizeof(struct dvb_demux_filter));
if (!dvbdemux->filter)
return -ENOMEM;
dvbdemux->feed = vmalloc(array_size(sizeof(struct dvb_demux_feed),
dvbdemux->feednum));
dvbdemux->feed = vmalloc_array(dvbdemux->feednum,
sizeof(struct dvb_demux_feed));
if (!dvbdemux->feed) {
vfree(dvbdemux->filter);
dvbdemux->filter = NULL;

View File

@ -37,10 +37,11 @@
void dvb_ringbuffer_init(struct dvb_ringbuffer *rbuf, void *data, size_t len)
{
rbuf->pread=rbuf->pwrite=0;
rbuf->data=data;
rbuf->size=len;
rbuf->error=0;
rbuf->pread = 0;
rbuf->pwrite = 0;
rbuf->data = data;
rbuf->size = len;
rbuf->error = 0;
init_waitqueue_head(&rbuf->queue);
@ -235,7 +236,7 @@ ssize_t dvb_ringbuffer_write_user(struct dvb_ringbuffer *rbuf,
return len;
}
ssize_t dvb_ringbuffer_pkt_write(struct dvb_ringbuffer *rbuf, u8* buf, size_t len)
ssize_t dvb_ringbuffer_pkt_write(struct dvb_ringbuffer *rbuf, u8 *buf, size_t len)
{
int status;
ssize_t oldpwrite = rbuf->pwrite;
@ -245,7 +246,8 @@ ssize_t dvb_ringbuffer_pkt_write(struct dvb_ringbuffer *rbuf, u8* buf, size_t le
DVB_RINGBUFFER_WRITE_BYTE(rbuf, PKT_READY);
status = dvb_ringbuffer_write(rbuf, buf, len);
if (status < 0) rbuf->pwrite = oldpwrite;
if (status < 0)
rbuf->pwrite = oldpwrite;
return status;
}
@ -258,8 +260,10 @@ ssize_t dvb_ringbuffer_pkt_read_user(struct dvb_ringbuffer *rbuf, size_t idx,
pktlen = rbuf->data[idx] << 8;
pktlen |= rbuf->data[(idx + 1) % rbuf->size];
if (offset > pktlen) return -EINVAL;
if ((offset + len) > pktlen) len = pktlen - offset;
if (offset > pktlen)
return -EINVAL;
if ((offset + len) > pktlen)
len = pktlen - offset;
idx = (idx + DVB_RINGBUFFER_PKTHDRSIZE + offset) % rbuf->size;
todo = len;
@ -278,7 +282,7 @@ ssize_t dvb_ringbuffer_pkt_read_user(struct dvb_ringbuffer *rbuf, size_t idx,
}
ssize_t dvb_ringbuffer_pkt_read(struct dvb_ringbuffer *rbuf, size_t idx,
int offset, u8* buf, size_t len)
int offset, u8 *buf, size_t len)
{
size_t todo;
size_t split;
@ -286,8 +290,10 @@ ssize_t dvb_ringbuffer_pkt_read(struct dvb_ringbuffer *rbuf, size_t idx,
pktlen = rbuf->data[idx] << 8;
pktlen |= rbuf->data[(idx + 1) % rbuf->size];
if (offset > pktlen) return -EINVAL;
if ((offset + len) > pktlen) len = pktlen - offset;
if (offset > pktlen)
return -EINVAL;
if ((offset + len) > pktlen)
len = pktlen - offset;
idx = (idx + DVB_RINGBUFFER_PKTHDRSIZE + offset) % rbuf->size;
todo = len;
@ -309,7 +315,7 @@ void dvb_ringbuffer_pkt_dispose(struct dvb_ringbuffer *rbuf, size_t idx)
rbuf->data[(idx + 2) % rbuf->size] = PKT_DISPOSED;
// clean up disposed packets
while(dvb_ringbuffer_avail(rbuf) > DVB_RINGBUFFER_PKTHDRSIZE) {
while (dvb_ringbuffer_avail(rbuf) > DVB_RINGBUFFER_PKTHDRSIZE) {
if (DVB_RINGBUFFER_PEEK(rbuf, 2) == PKT_DISPOSED) {
pktlen = DVB_RINGBUFFER_PEEK(rbuf, 0) << 8;
pktlen |= DVB_RINGBUFFER_PEEK(rbuf, 1);
@ -321,14 +327,14 @@ void dvb_ringbuffer_pkt_dispose(struct dvb_ringbuffer *rbuf, size_t idx)
}
}
ssize_t dvb_ringbuffer_pkt_next(struct dvb_ringbuffer *rbuf, size_t idx, size_t* pktlen)
ssize_t dvb_ringbuffer_pkt_next(struct dvb_ringbuffer *rbuf, size_t idx, size_t *pktlen)
{
int consumed;
int curpktlen;
int curpktstatus;
if (idx == -1) {
idx = rbuf->pread;
idx = rbuf->pread;
} else {
curpktlen = rbuf->data[idx] << 8;
curpktlen |= rbuf->data[(idx + 1) % rbuf->size];
@ -339,7 +345,7 @@ ssize_t dvb_ringbuffer_pkt_next(struct dvb_ringbuffer *rbuf, size_t idx, size_t*
if (consumed < 0)
consumed += rbuf->size;
while((dvb_ringbuffer_avail(rbuf) - consumed) > DVB_RINGBUFFER_PKTHDRSIZE) {
while ((dvb_ringbuffer_avail(rbuf) - consumed) > DVB_RINGBUFFER_PKTHDRSIZE) {
curpktlen = rbuf->data[idx] << 8;
curpktlen |= rbuf->data[(idx + 1) % rbuf->size];

View File

@ -571,8 +571,8 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev,
MKDEV(DVB_MAJOR, minor),
dvbdev, "dvb%d.%s%d", adap->num, dnames[type], id);
if (IS_ERR(clsdev)) {
pr_err("%s: failed to create device dvb%d.%s%d (%ld)\n",
__func__, adap->num, dnames[type], id, PTR_ERR(clsdev));
pr_err("%s: failed to create device dvb%d.%s%d (%pe)\n",
__func__, adap->num, dnames[type], id, clsdev);
if (new_node) {
list_del(&new_node->list_head);
kfree(dvbdevfops);

View File

@ -1936,7 +1936,8 @@ static void cxd2841er_read_ber(struct dvb_frontend *fe)
{
struct dtv_frontend_properties *p = &fe->dtv_property_cache;
struct cxd2841er_priv *priv = fe->demodulator_priv;
u32 ret, bit_error = 0, bit_count = 0;
u32 bit_error = 0, bit_count = 0;
int ret;
dev_dbg(&priv->i2c->dev, "%s()\n", __func__);
switch (p->delivery_system) {

View File

@ -1270,7 +1270,7 @@ static const u16 nicam_presc_table_val[43] = {
TODO: check ignoring single/multimaster is ok for AUD access ?
*/
#define DRXJ_ISAUDWRITE(addr) (((((addr)>>16)&1) == 1) ? true : false)
#define DRXJ_ISAUDWRITE(addr) ((((addr) >> 16) & 1) == 1)
#define DRXJ_DAP_AUDTRIF_TIMEOUT 80 /* millisec */
/*============================================================================*/

View File

@ -6324,8 +6324,7 @@ static int drxk_set_parameters(struct dvb_frontend *fe)
case SYS_DVBC_ANNEX_C:
if (!state->m_has_dvbc)
return -EINVAL;
state->m_itut_annex_c = (delsys == SYS_DVBC_ANNEX_C) ?
true : false;
state->m_itut_annex_c = delsys == SYS_DVBC_ANNEX_C;
if (state->m_itut_annex_c)
setoperation_mode(state, OM_QAM_ITU_C);
else

View File

@ -124,7 +124,6 @@ static int i2c_read_demod_bytes(struct lgdt330x_state *state,
/* Software reset */
static int lgdt3302_sw_reset(struct lgdt330x_state *state)
{
u8 ret;
u8 reset[] = {
IRQ_MASK,
/*
@ -133,6 +132,7 @@ static int lgdt3302_sw_reset(struct lgdt330x_state *state)
*/
0x00
};
int ret;
ret = i2c_write_demod_bytes(state,
reset, sizeof(reset));
@ -147,11 +147,11 @@ static int lgdt3302_sw_reset(struct lgdt330x_state *state)
static int lgdt3303_sw_reset(struct lgdt330x_state *state)
{
u8 ret;
u8 reset[] = {
0x02,
0x00 /* bit 0 is active low software reset */
};
int ret;
ret = i2c_write_demod_bytes(state,
reset, sizeof(reset));

View File

@ -694,8 +694,7 @@ static int mn88443x_probe(struct i2c_client *client)
chip->mclk = devm_clk_get(dev, "mclk");
if (IS_ERR(chip->mclk) && !conf) {
dev_err(dev, "Failed to request mclk: %ld\n",
PTR_ERR(chip->mclk));
dev_err(dev, "Failed to request mclk: %pe\n", chip->mclk);
return PTR_ERR(chip->mclk);
}
@ -709,8 +708,8 @@ static int mn88443x_probe(struct i2c_client *client)
chip->reset_gpio = devm_gpiod_get_optional(dev, "reset",
GPIOD_OUT_HIGH);
if (IS_ERR(chip->reset_gpio)) {
dev_err(dev, "Failed to request reset_gpio: %ld\n",
PTR_ERR(chip->reset_gpio));
dev_err(dev, "Failed to request reset_gpio: %pe\n",
chip->reset_gpio);
return PTR_ERR(chip->reset_gpio);
}

View File

@ -137,6 +137,16 @@ config VIDEO_HI847
To compile this driver as a module, choose M here: the
module will be called hi847.
config VIDEO_IMX111
tristate "Sony IMX111 sensor support"
select V4L2_CCI_I2C
help
This is a V4L2 sensor driver for the Sony IMX111 camera
sensors.
To compile this driver as a module, choose M here: the
module will be called imx111.
config VIDEO_IMX208
tristate "Sony IMX208 sensor support"
help
@ -471,7 +481,7 @@ config VIDEO_OV2735
tristate "OmniVision OV2735 sensor support"
select V4L2_CCI_I2C
help
This is a Video4Linux2 sensor driver for the Sony
This is a Video4Linux2 sensor driver for the OmniVision
OV2735 camera.
To compile this driver as a module, choose M here: the

View File

@ -46,6 +46,7 @@ obj-$(CONFIG_VIDEO_HI556) += hi556.o
obj-$(CONFIG_VIDEO_HI846) += hi846.o
obj-$(CONFIG_VIDEO_HI847) += hi847.o
obj-$(CONFIG_VIDEO_I2C) += video-i2c.o
obj-$(CONFIG_VIDEO_IMX111) += imx111.o
obj-$(CONFIG_VIDEO_IMX208) += imx208.o
obj-$(CONFIG_VIDEO_IMX214) += imx214.o
obj-$(CONFIG_VIDEO_IMX219) += imx219.o

View File

@ -3670,7 +3670,7 @@ static int adv76xx_probe(struct i2c_client *client)
err = media_entity_pads_init(&sd->entity, state->source_pad + 1,
state->pads);
if (err)
goto err_work_queues;
goto err_i2c;
/* Configure regmaps */
err = configure_regmaps(state);
@ -3711,8 +3711,6 @@ static int adv76xx_probe(struct i2c_client *client)
err_entity:
media_entity_cleanup(&sd->entity);
err_work_queues:
cancel_delayed_work(&state->delayed_work_enable_hotplug);
err_i2c:
adv76xx_unregister_clients(state);
err_hdl:

View File

@ -2699,6 +2699,7 @@ static int adv7842_cp_log_status(struct v4l2_subdev *sd)
/* CP block */
struct adv7842_state *state = to_state(sd);
struct v4l2_dv_timings timings;
int temp;
u8 reg_io_0x02 = io_read(sd, 0x02);
u8 reg_io_0x21 = io_read(sd, 0x21);
u8 reg_rep_0x77 = rep_read(sd, 0x77);
@ -2821,8 +2822,9 @@ static int adv7842_cp_log_status(struct v4l2_subdev *sd)
(((reg_io_0x02 >> 2) & 0x01) ^ (reg_io_0x02 & 0x01)) ?
"(16-235)" : "(0-255)",
(reg_io_0x02 & 0x08) ? "enabled" : "disabled");
temp = cp_read(sd, 0xf4) >> 4;
v4l2_info(sd, "Color space conversion: %s\n",
csc_coeff_sel_rb[cp_read(sd, 0xf4) >> 4]);
temp < 0 ? "" : csc_coeff_sel_rb[temp]);
if (!is_digital_input(sd))
return 0;
@ -2852,8 +2854,9 @@ static int adv7842_cp_log_status(struct v4l2_subdev *sd)
hdmi_read(sd, 0x5f));
v4l2_info(sd, "AV Mute: %s\n",
(hdmi_read(sd, 0x04) & 0x40) ? "on" : "off");
temp = hdmi_read(sd, 0x0b) >> 6;
v4l2_info(sd, "Deep color mode: %s\n",
deep_color_mode_txt[hdmi_read(sd, 0x0b) >> 6]);
temp < 0 ? "" : deep_color_mode_txt[temp]);
adv7842_log_infoframes(sd);
@ -3466,8 +3469,8 @@ static struct i2c_client *adv7842_dummy_client(struct v4l2_subdev *sd, const cha
cp = i2c_new_dummy_device(client->adapter, io_read(sd, io_reg) >> 1);
if (IS_ERR(cp)) {
v4l2_err(sd, "register %s on i2c addr 0x%x failed with %ld\n",
desc, addr, PTR_ERR(cp));
v4l2_err(sd, "register %s on i2c addr 0x%x failed with %pe\n",
desc, addr, cp);
cp = NULL;
}
@ -3626,7 +3629,7 @@ static int adv7842_probe(struct i2c_client *client)
err = media_entity_pads_init(&sd->entity, ADV7842_PAD_SOURCE + 1,
state->pads);
if (err)
goto err_work_queues;
goto err_i2c;
err = adv7842_core_init(sd);
if (err)
@ -3647,8 +3650,6 @@ static int adv7842_probe(struct i2c_client *client)
err_entity:
media_entity_cleanup(&sd->entity);
err_work_queues:
cancel_delayed_work(&state->delayed_work_enable_hotplug);
err_i2c:
adv7842_unregister_clients(sd);
err_hdl:

View File

@ -1109,8 +1109,8 @@ static int ar0521_probe(struct i2c_client *client)
ar0521_supply_names[cnt]);
if (IS_ERR(supply)) {
dev_info(dev, "no %s regulator found: %li\n",
ar0521_supply_names[cnt], PTR_ERR(supply));
dev_info(dev, "no %s regulator found: %pe\n",
ar0521_supply_names[cnt], supply);
return PTR_ERR(supply);
}
sensor->supplies[cnt] = supply;

View File

@ -3237,8 +3237,8 @@ static int ccs_probe(struct i2c_client *client)
dev_info(&client->dev, "no clock defined, continuing...\n");
sensor->ext_clk = NULL;
} else if (IS_ERR(sensor->ext_clk)) {
dev_err(&client->dev, "could not get clock (%ld)\n",
PTR_ERR(sensor->ext_clk));
dev_err(&client->dev, "could not get clock (%pe)\n",
sensor->ext_clk);
return -EPROBE_DEFER;
}
@ -3294,8 +3294,8 @@ static int ccs_probe(struct i2c_client *client)
sensor->regmap = devm_cci_regmap_init_i2c(client, 16);
if (IS_ERR(sensor->regmap)) {
dev_err(&client->dev, "can't initialise CCI (%ld)\n",
PTR_ERR(sensor->regmap));
dev_err(&client->dev, "can't initialise CCI (%pe)\n",
sensor->regmap);
return PTR_ERR(sensor->regmap);
}

View File

@ -622,7 +622,7 @@ static int ub913_v4l2_notifier_register(struct ub913_data *priv)
fwnode_handle_put(ep_fwnode);
if (IS_ERR(asd)) {
dev_err(dev, "Failed to add subdev: %ld", PTR_ERR(asd));
dev_err(dev, "Failed to add subdev: %pe", asd);
v4l2_async_nf_cleanup(&priv->notifier);
return PTR_ERR(asd);
}

View File

@ -776,7 +776,7 @@ static int ub953_v4l2_notifier_register(struct ub953_data *priv)
fwnode_handle_put(ep_fwnode);
if (IS_ERR(asd)) {
dev_err(dev, "Failed to add subdev: %ld", PTR_ERR(asd));
dev_err(dev, "Failed to add subdev: %pe", asd);
v4l2_async_nf_cleanup(&priv->notifier);
return PTR_ERR(asd);
}
@ -1023,15 +1023,17 @@ static unsigned long ub953_clkout_recalc_rate(struct clk_hw *hw,
return rate;
}
static long ub953_clkout_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *parent_rate)
static int ub953_clkout_determine_rate(struct clk_hw *hw,
struct clk_rate_request *req)
{
struct ub953_data *priv = container_of(hw, struct ub953_data, clkout_clk_hw);
struct ub953_clkout_data clkout_data;
ub953_calc_clkout_params(priv, rate, &clkout_data);
ub953_calc_clkout_params(priv, req->rate, &clkout_data);
return clkout_data.rate;
req->rate = clkout_data.rate;
return 0;
}
static int ub953_clkout_set_rate(struct clk_hw *hw, unsigned long rate,
@ -1050,7 +1052,7 @@ static int ub953_clkout_set_rate(struct clk_hw *hw, unsigned long rate,
static const struct clk_ops ub953_clkout_ops = {
.recalc_rate = ub953_clkout_recalc_rate,
.round_rate = ub953_clkout_round_rate,
.determine_rate = ub953_clkout_determine_rate,
.set_rate = ub953_clkout_set_rate,
};

View File

@ -23,6 +23,25 @@
#define DW9719_CTRL_STEPS 16
#define DW9719_CTRL_DELAY_US 1000
#define DW9718S_PD CCI_REG8(0)
#define DW9718S_CONTROL CCI_REG8(1)
#define DW9718S_CONTROL_SW_LINEAR BIT(0)
#define DW9718S_CONTROL_SAC_SHIFT 1
#define DW9718S_CONTROL_SAC_MASK 0x7
#define DW9718S_CONTROL_OCP_DISABLE BIT(4)
#define DW9718S_CONTROL_UVLO_DISABLE BIT(5)
#define DW9718S_DEFAULT_SAC 4
#define DW9718S_VCM_CURRENT CCI_REG16(2)
#define DW9718S_SW CCI_REG8(4)
#define DW9718S_SW_VCM_FREQ_MASK 0xF
#define DW9718S_DEFAULT_VCM_FREQ 0
#define DW9718S_SACT CCI_REG8(5)
#define DW9718S_SACT_PERIOD_8_8MS 0x19
#define DW9719_INFO CCI_REG8(0)
#define DW9719_ID 0xF1
#define DW9761_ID 0xF4
@ -49,12 +68,17 @@
#define DW9761_VCM_PRELOAD CCI_REG8(8)
#define DW9761_DEFAULT_VCM_PRELOAD 0x73
#define DW9800K_DEFAULT_SAC 1
#define DW9800K_MODE_SAC_SHIFT 6
#define DW9800K_DEFAULT_VCM_FREQ 0x10
#define to_dw9719_device(x) container_of(x, struct dw9719_device, sd)
enum dw9719_model {
DW9718S,
DW9719,
DW9761,
DW9800K,
};
struct dw9719_device {
@ -75,26 +99,55 @@ struct dw9719_device {
static int dw9719_power_down(struct dw9719_device *dw9719)
{
u32 reg_pwr = dw9719->model == DW9718S ? DW9718S_PD : DW9719_CONTROL;
/*
* Worth engaging the internal SHUTDOWN mode especially due to the
* regulator being potentially shared with other devices.
*/
if (cci_write(dw9719->regmap, reg_pwr, DW9719_SHUTDOWN, NULL))
dev_err(dw9719->dev, "Error writing to power register\n");
return regulator_disable(dw9719->regulator);
}
static int dw9719_power_up(struct dw9719_device *dw9719, bool detect)
{
u32 reg_pwr = dw9719->model == DW9718S ? DW9718S_PD : DW9719_CONTROL;
u64 val;
int ret;
int err;
ret = regulator_enable(dw9719->regulator);
if (ret)
return ret;
/* Jiggle SCL pin to wake up device */
cci_write(dw9719->regmap, DW9719_CONTROL, DW9719_SHUTDOWN, &ret);
fsleep(100);
cci_write(dw9719->regmap, DW9719_CONTROL, DW9719_STANDBY, &ret);
/* Need 100us to transit from SHUTDOWN to STANDBY */
fsleep(100);
/*
* Need 100us to transition from SHUTDOWN to STANDBY.
* Jiggle the SCL pin to wake up the device (even when the regulator is
* shared) and wait double the time to be sure, as 100us is not enough
* at least on the DW9718S as found on the motorola-nora smartphone,
* then retry the write.
*/
cci_write(dw9719->regmap, reg_pwr, DW9719_STANDBY, NULL);
/* the jiggle is expected to fail, don't even log that as error */
fsleep(200);
cci_write(dw9719->regmap, reg_pwr, DW9719_STANDBY, &ret);
if (detect) {
/* These models do not have an INFO register */
switch (dw9719->model) {
case DW9718S:
dw9719->sac_mode = DW9718S_DEFAULT_SAC;
dw9719->vcm_freq = DW9718S_DEFAULT_VCM_FREQ;
goto props;
case DW9800K:
dw9719->sac_mode = DW9800K_DEFAULT_SAC;
dw9719->vcm_freq = DW9800K_DEFAULT_VCM_FREQ;
goto props;
default:
break;
}
ret = cci_read(dw9719->regmap, DW9719_INFO, &val, NULL);
if (ret < 0)
return ret;
@ -118,23 +171,52 @@ static int dw9719_power_up(struct dw9719_device *dw9719, bool detect)
return -ENXIO;
}
props:
/* Optional indication of SAC mode select */
device_property_read_u32(dw9719->dev, "dongwoon,sac-mode",
&dw9719->sac_mode);
/* Optional indication of VCM frequency */
device_property_read_u32(dw9719->dev, "dongwoon,vcm-freq",
err = device_property_read_u32(dw9719->dev, "dongwoon,vcm-freq",
&dw9719->vcm_freq);
if (err == 0)
dev_warn(dw9719->dev, "dongwoon,vcm-freq property is deprecated, please use dongwoon,vcm-prescale\n");
/* Optional indication of VCM prescale */
device_property_read_u32(dw9719->dev, "dongwoon,vcm-prescale",
&dw9719->vcm_freq);
}
cci_write(dw9719->regmap, DW9719_CONTROL, DW9719_ENABLE_RINGING, &ret);
cci_write(dw9719->regmap, DW9719_MODE, dw9719->mode_low_bits |
(dw9719->sac_mode << DW9719_MODE_SAC_SHIFT), &ret);
cci_write(dw9719->regmap, DW9719_VCM_FREQ, dw9719->vcm_freq, &ret);
if (dw9719->model == DW9761)
switch (dw9719->model) {
case DW9800K:
cci_write(dw9719->regmap, DW9719_CONTROL, DW9719_ENABLE_RINGING, &ret);
cci_write(dw9719->regmap, DW9719_MODE,
dw9719->sac_mode << DW9800K_MODE_SAC_SHIFT, &ret);
cci_write(dw9719->regmap, DW9719_VCM_FREQ, dw9719->vcm_freq, &ret);
break;
case DW9718S:
/* Datasheet says [OCP/UVLO] should be disabled below 2.5V */
dw9719->sac_mode &= DW9718S_CONTROL_SAC_MASK;
cci_write(dw9719->regmap, DW9718S_CONTROL,
DW9718S_CONTROL_SW_LINEAR |
(dw9719->sac_mode << DW9718S_CONTROL_SAC_SHIFT) |
DW9718S_CONTROL_OCP_DISABLE |
DW9718S_CONTROL_UVLO_DISABLE, &ret);
cci_write(dw9719->regmap, DW9718S_SACT,
DW9718S_SACT_PERIOD_8_8MS, &ret);
cci_write(dw9719->regmap, DW9718S_SW,
dw9719->vcm_freq & DW9718S_SW_VCM_FREQ_MASK, &ret);
break;
case DW9761:
cci_write(dw9719->regmap, DW9761_VCM_PRELOAD,
DW9761_DEFAULT_VCM_PRELOAD, &ret);
fallthrough;
case DW9719:
cci_write(dw9719->regmap, DW9719_CONTROL, DW9719_ENABLE_RINGING, &ret);
cci_write(dw9719->regmap, DW9719_MODE, dw9719->mode_low_bits |
(dw9719->sac_mode << DW9719_MODE_SAC_SHIFT), &ret);
cci_write(dw9719->regmap, DW9719_VCM_FREQ, dw9719->vcm_freq, &ret);
}
if (ret)
dw9719_power_down(dw9719);
@ -144,7 +226,9 @@ static int dw9719_power_up(struct dw9719_device *dw9719, bool detect)
static int dw9719_t_focus_abs(struct dw9719_device *dw9719, s32 value)
{
return cci_write(dw9719->regmap, DW9719_VCM_CURRENT, value, NULL);
u32 reg = dw9719->model == DW9718S ? DW9718S_VCM_CURRENT
: DW9719_VCM_CURRENT;
return cci_write(dw9719->regmap, reg, value, NULL);
}
static int dw9719_set_ctrl(struct v4l2_ctrl *ctrl)
@ -229,7 +313,7 @@ static int dw9719_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
static int dw9719_close(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
{
pm_runtime_put(sd->dev);
pm_runtime_put_autosuspend(sd->dev);
return 0;
}
@ -275,6 +359,8 @@ static int dw9719_probe(struct i2c_client *client)
if (!dw9719)
return -ENOMEM;
dw9719->model = (enum dw9719_model)(uintptr_t)i2c_get_match_data(client);
dw9719->regmap = devm_cci_regmap_init_i2c(client, 8);
if (IS_ERR(dw9719->regmap))
return PTR_ERR(dw9719->regmap);
@ -353,12 +439,14 @@ static void dw9719_remove(struct i2c_client *client)
pm_runtime_set_suspended(&client->dev);
}
static const struct i2c_device_id dw9719_id_table[] = {
{ "dw9719" },
{ "dw9761" },
static const struct of_device_id dw9719_of_table[] = {
{ .compatible = "dongwoon,dw9718s", .data = (const void *)DW9718S },
{ .compatible = "dongwoon,dw9719", .data = (const void *)DW9719 },
{ .compatible = "dongwoon,dw9761", .data = (const void *)DW9761 },
{ .compatible = "dongwoon,dw9800k", .data = (const void *)DW9800K },
{ }
};
MODULE_DEVICE_TABLE(i2c, dw9719_id_table);
MODULE_DEVICE_TABLE(of, dw9719_of_table);
static DEFINE_RUNTIME_DEV_PM_OPS(dw9719_pm_ops, dw9719_suspend, dw9719_resume,
NULL);
@ -367,10 +455,10 @@ static struct i2c_driver dw9719_i2c_driver = {
.driver = {
.name = "dw9719",
.pm = pm_sleep_ptr(&dw9719_pm_ops),
.of_match_table = dw9719_of_table,
},
.probe = dw9719_probe,
.remove = dw9719_remove,
.id_table = dw9719_id_table,
};
module_i2c_driver(dw9719_i2c_driver);

1610
drivers/media/i2c/imx111.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -1014,8 +1014,6 @@ static int imx214_ctrls_init(struct imx214 *imx214)
V4L2_CID_LINK_FREQ,
imx214->bus_cfg.nr_of_link_frequencies - 1,
0, imx214->bus_cfg.link_frequencies);
if (imx214->link_freq)
imx214->link_freq->flags |= V4L2_CTRL_FLAG_READ_ONLY;
/*
* WARNING!
@ -1038,9 +1036,6 @@ static int imx214_ctrls_init(struct imx214 *imx214)
imx214->hblank = v4l2_ctrl_new_std(ctrl_hdlr, &imx214_ctrl_ops,
V4L2_CID_HBLANK, hblank, hblank,
1, hblank);
if (imx214->hblank)
imx214->hblank->flags |= V4L2_CTRL_FLAG_READ_ONLY;
exposure_max = mode->vts_def - IMX214_EXPOSURE_OFFSET;
exposure_def = min(exposure_max, IMX214_EXPOSURE_DEFAULT);
imx214->exposure = v4l2_ctrl_new_std(ctrl_hdlr, &imx214_ctrl_ops,
@ -1060,13 +1055,9 @@ static int imx214_ctrls_init(struct imx214 *imx214)
imx214->hflip = v4l2_ctrl_new_std(ctrl_hdlr, &imx214_ctrl_ops,
V4L2_CID_HFLIP, 0, 1, 1, 0);
if (imx214->hflip)
imx214->hflip->flags |= V4L2_CTRL_FLAG_MODIFY_LAYOUT;
imx214->vflip = v4l2_ctrl_new_std(ctrl_hdlr, &imx214_ctrl_ops,
V4L2_CID_VFLIP, 0, 1, 1, 0);
if (imx214->vflip)
imx214->vflip->flags |= V4L2_CTRL_FLAG_MODIFY_LAYOUT;
v4l2_ctrl_cluster(2, &imx214->hflip);
@ -1106,6 +1097,12 @@ static int imx214_ctrls_init(struct imx214 *imx214)
return ret;
}
/* Now that the controls have been properly created, set their flags. */
imx214->link_freq->flags |= V4L2_CTRL_FLAG_READ_ONLY;
imx214->hblank->flags |= V4L2_CTRL_FLAG_READ_ONLY;
imx214->hflip->flags |= V4L2_CTRL_FLAG_MODIFY_LAYOUT;
imx214->vflip->flags |= V4L2_CTRL_FLAG_MODIFY_LAYOUT;
ret = imx214_pll_update(imx214);
if (ret < 0) {
v4l2_ctrl_handler_free(ctrl_hdlr);

View File

@ -68,6 +68,7 @@
#define IMX219_EXPOSURE_STEP 1
#define IMX219_EXPOSURE_DEFAULT 0x640
#define IMX219_EXPOSURE_MAX 65535
#define IMX219_EXPOSURE_OFFSET 4
/* V_TIMING internal */
#define IMX219_REG_FRM_LENGTH_A CCI_REG16(0x0160)
@ -409,24 +410,14 @@ static void imx219_get_binning(struct v4l2_subdev_state *state, u8 *bin_h,
u32 hbin = crop->width / format->width;
u32 vbin = crop->height / format->height;
*bin_h = IMX219_BINNING_NONE;
*bin_v = IMX219_BINNING_NONE;
/*
* Use analog binning only if both dimensions are binned, as it crops
* the other dimension.
*/
if (hbin == 2 && vbin == 2) {
*bin_h = IMX219_BINNING_X2_ANALOG;
*bin_v = IMX219_BINNING_X2_ANALOG;
return;
} else {
*bin_h = IMX219_BINNING_NONE;
*bin_v = IMX219_BINNING_NONE;
}
if (hbin == 2)
*bin_h = IMX219_BINNING_X2;
if (vbin == 2)
*bin_v = IMX219_BINNING_X2;
}
static inline u32 imx219_get_rate_factor(struct v4l2_subdev_state *state)
@ -460,13 +451,17 @@ static int imx219_set_ctrl(struct v4l2_ctrl *ctrl)
int exposure_max, exposure_def;
/* Update max exposure while meeting expected vblanking */
exposure_max = format->height + ctrl->val - 4;
exposure_max = format->height + ctrl->val - IMX219_EXPOSURE_OFFSET;
exposure_def = (exposure_max < IMX219_EXPOSURE_DEFAULT) ?
exposure_max : IMX219_EXPOSURE_DEFAULT;
__v4l2_ctrl_modify_range(imx219->exposure,
imx219->exposure->minimum,
exposure_max, imx219->exposure->step,
exposure_def);
exposure_max : IMX219_EXPOSURE_DEFAULT;
ret = __v4l2_ctrl_modify_range(imx219->exposure,
imx219->exposure->minimum,
exposure_max,
imx219->exposure->step,
exposure_def);
if (ret)
return ret;
}
/*
@ -585,9 +580,9 @@ static int imx219_init_controls(struct imx219 *imx219)
IMX219_LLP_MIN - mode->width,
IMX219_LLP_MAX - mode->width, 1,
IMX219_LLP_MIN - mode->width);
exposure_max = mode->fll_def - 4;
exposure_max = mode->fll_def - IMX219_EXPOSURE_OFFSET;
exposure_def = (exposure_max < IMX219_EXPOSURE_DEFAULT) ?
exposure_max : IMX219_EXPOSURE_DEFAULT;
exposure_max : IMX219_EXPOSURE_DEFAULT;
imx219->exposure = v4l2_ctrl_new_std(ctrl_hdlr, &imx219_ctrl_ops,
V4L2_CID_EXPOSURE,
IMX219_EXPOSURE_MIN, exposure_max,
@ -856,8 +851,9 @@ static int imx219_set_pad_format(struct v4l2_subdev *sd,
const struct imx219_mode *mode;
struct v4l2_mbus_framefmt *format;
struct v4l2_rect *crop;
u8 bin_h, bin_v;
u8 bin_h, bin_v, binning;
u32 prev_line_len;
int ret;
format = v4l2_subdev_state_get_format(state, 0);
prev_line_len = format->width + imx219->hblank->val;
@ -877,9 +873,12 @@ static int imx219_set_pad_format(struct v4l2_subdev *sd,
bin_h = min(IMX219_PIXEL_ARRAY_WIDTH / format->width, 2U);
bin_v = min(IMX219_PIXEL_ARRAY_HEIGHT / format->height, 2U);
/* Ensure bin_h and bin_v are same to avoid 1:2 or 2:1 stretching */
binning = min(bin_h, bin_v);
crop = v4l2_subdev_state_get_crop(state, 0);
crop->width = format->width * bin_h;
crop->height = format->height * bin_v;
crop->width = format->width * binning;
crop->height = format->height * binning;
crop->left = (IMX219_NATIVE_WIDTH - crop->width) / 2;
crop->top = (IMX219_NATIVE_HEIGHT - crop->height) / 2;
@ -890,19 +889,28 @@ static int imx219_set_pad_format(struct v4l2_subdev *sd,
int pixel_rate;
/* Update limits and set FPS to default */
__v4l2_ctrl_modify_range(imx219->vblank, IMX219_VBLANK_MIN,
IMX219_FLL_MAX - mode->height, 1,
ret = __v4l2_ctrl_modify_range(imx219->vblank, IMX219_VBLANK_MIN,
IMX219_FLL_MAX - mode->height, 1,
mode->fll_def - mode->height);
if (ret)
return ret;
ret = __v4l2_ctrl_s_ctrl(imx219->vblank,
mode->fll_def - mode->height);
__v4l2_ctrl_s_ctrl(imx219->vblank,
mode->fll_def - mode->height);
if (ret)
return ret;
/* Update max exposure while meeting expected vblanking */
exposure_max = mode->fll_def - 4;
exposure_max = mode->fll_def - IMX219_EXPOSURE_OFFSET;
exposure_def = (exposure_max < IMX219_EXPOSURE_DEFAULT) ?
exposure_max : IMX219_EXPOSURE_DEFAULT;
__v4l2_ctrl_modify_range(imx219->exposure,
imx219->exposure->minimum,
exposure_max, imx219->exposure->step,
exposure_def);
exposure_max : IMX219_EXPOSURE_DEFAULT;
ret = __v4l2_ctrl_modify_range(imx219->exposure,
imx219->exposure->minimum,
exposure_max,
imx219->exposure->step,
exposure_def);
if (ret)
return ret;
/*
* With analog binning the default minimum line length of 3448
@ -913,9 +921,12 @@ static int imx219_set_pad_format(struct v4l2_subdev *sd,
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;
__v4l2_ctrl_modify_range(imx219->hblank, llp_min - mode->width,
IMX219_LLP_MAX - mode->width, 1,
llp_min - mode->width);
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;
/*
* Retain PPL setting from previous mode so that the
* line time does not change on a mode change.
@ -924,13 +935,17 @@ static int imx219_set_pad_format(struct v4l2_subdev *sd,
* mode width subtracted.
*/
hblank = prev_line_len - mode->width;
__v4l2_ctrl_s_ctrl(imx219->hblank, hblank);
ret = __v4l2_ctrl_s_ctrl(imx219->hblank, hblank);
if (ret)
return ret;
/* Scale the pixel rate based on the mode specific factor */
pixel_rate = imx219_get_pixel_rate(imx219) *
imx219_get_rate_factor(state);
__v4l2_ctrl_modify_range(imx219->pixel_rate, pixel_rate,
pixel_rate, 1, pixel_rate);
ret = __v4l2_ctrl_modify_range(imx219->pixel_rate, pixel_rate,
pixel_rate, 1, pixel_rate);
if (ret)
return ret;
}
return 0;
@ -979,9 +994,7 @@ static int imx219_init_state(struct v4l2_subdev *sd,
},
};
imx219_set_pad_format(sd, state, &fmt);
return 0;
return imx219_set_pad_format(sd, state, &fmt);
}
static const struct v4l2_subdev_video_ops imx219_video_ops = {

View File

@ -2034,8 +2034,7 @@ static int imx274_probe(struct i2c_client *client)
/* initialize regmap */
imx274->regmap = devm_regmap_init_i2c(client, &imx274_regmap_config);
if (IS_ERR(imx274->regmap)) {
dev_err(dev,
"regmap init failed: %ld\n", PTR_ERR(imx274->regmap));
dev_err(dev, "regmap init failed: %pe\n", imx274->regmap);
ret = -ENODEV;
goto err_regmap;
}

View File

@ -35,6 +35,7 @@
/* Lines per frame */
#define IMX335_REG_VMAX CCI_REG24_LE(0x3030)
#define IMX335_REG_HMAX CCI_REG16_LE(0x3034)
#define IMX335_REG_OPB_SIZE_V CCI_REG8(0x304c)
#define IMX335_REG_ADBIT CCI_REG8(0x3050)
@ -42,10 +43,13 @@
#define IMX335_REG_SHUTTER CCI_REG24_LE(0x3058)
#define IMX335_EXPOSURE_MIN 1
#define IMX335_EXPOSURE_OFFSET 9
#define IMX335_SHUTTER_MIN 9
#define IMX335_SHUTTER_MIN_BINNED 17
#define IMX335_EXPOSURE_STEP 1
#define IMX335_EXPOSURE_DEFAULT 0x0648
#define IMX335_REG_AREA2_WIDTH_1 CCI_REG16_LE(0x3072)
#define IMX335_REG_AREA3_ST_ADR_1 CCI_REG16_LE(0x3074)
#define IMX335_REG_AREA3_WIDTH_1 CCI_REG16_LE(0x3076)
@ -56,6 +60,9 @@
#define IMX335_AGAIN_STEP 1
#define IMX335_AGAIN_DEFAULT 0
/* Vertical flip */
#define IMX335_REG_VREVERSE CCI_REG8(0x304f)
#define IMX335_REG_TPG_TESTCLKEN CCI_REG8(0x3148)
#define IMX335_REG_INCLKSEL1 CCI_REG16_LE(0x314c)
@ -121,12 +128,19 @@
#define IMX335_NUM_DATA_LANES 4
/* IMX335 native and active pixel array size. */
#define IMX335_NATIVE_WIDTH 2616U
#define IMX335_NATIVE_HEIGHT 1964U
#define IMX335_PIXEL_ARRAY_LEFT 12U
#define IMX335_PIXEL_ARRAY_TOP 12U
#define IMX335_PIXEL_ARRAY_WIDTH 2592U
#define IMX335_PIXEL_ARRAY_HEIGHT 1944U
static const struct v4l2_rect imx335_native_area = {
.top = 0,
.left = 0,
.width = 2696,
.height = 2044,
};
static const struct v4l2_rect imx335_active_area = {
.top = 50,
.left = 36,
.width = 2624,
.height = 1944,
};
/**
* struct imx335_reg_list - imx335 sensor register list
@ -144,8 +158,14 @@ static const char * const imx335_supply_name[] = {
"dvdd", /* Digital Core (1.2V) supply */
};
enum imx335_scan_mode {
IMX335_ALL_PIXEL,
IMX335_2_2_BINNING,
};
/**
* struct imx335_mode - imx335 sensor mode structure
* @scan_mode: Configuration scan mode (All pixel / 2x2Binning)
* @width: Frame width
* @height: Frame height
* @code: Format code
@ -155,8 +175,11 @@ static const char * const imx335_supply_name[] = {
* @vblank_max: Maximum vertical blanking in lines
* @pclk: Sensor pixel clock
* @reg_list: Register list for sensor mode
* @vflip_normal: Register list vflip (normal readout)
* @vflip_inverted: Register list vflip (inverted readout)
*/
struct imx335_mode {
enum imx335_scan_mode scan_mode;
u32 width;
u32 height;
u32 code;
@ -166,6 +189,8 @@ struct imx335_mode {
u32 vblank_max;
u64 pclk;
struct imx335_reg_list reg_list;
struct imx335_reg_list vflip_normal;
struct imx335_reg_list vflip_inverted;
};
/**
@ -183,12 +208,12 @@ struct imx335_mode {
* @pclk_ctrl: Pointer to pixel clock control
* @hblank_ctrl: Pointer to horizontal blanking control
* @vblank_ctrl: Pointer to vertical blanking control
* @vflip: Pointer to vertical flip control
* @exp_ctrl: Pointer to exposure control
* @again_ctrl: Pointer to analog gain control
* @vblank: Vertical blanking in lines
* @lane_mode: Mode for number of connected data lanes
* @cur_mode: Pointer to current selected sensor mode
* @mutex: Mutex for serializing sensor controls
* @link_freq_bitmap: Menu bitmap for link_freq_ctrl
* @cur_mbus_code: Currently selected media bus format code
*/
@ -207,6 +232,7 @@ struct imx335 {
struct v4l2_ctrl *pclk_ctrl;
struct v4l2_ctrl *hblank_ctrl;
struct v4l2_ctrl *vblank_ctrl;
struct v4l2_ctrl *vflip;
struct {
struct v4l2_ctrl *exp_ctrl;
struct v4l2_ctrl *again_ctrl;
@ -214,7 +240,6 @@ struct imx335 {
u32 vblank;
u32 lane_mode;
const struct imx335_mode *cur_mode;
struct mutex mutex;
unsigned long link_freq_bitmap;
u32 cur_mbus_code;
};
@ -252,17 +277,37 @@ static const int imx335_tpg_val[] = {
};
/* Sensor mode registers */
static const struct cci_reg_sequence mode_2592x1940_regs[] = {
static const struct cci_reg_sequence mode_2592x1944_regs[] = {
{ IMX335_REG_MODE_SELECT, IMX335_MODE_STANDBY },
{ IMX335_REG_MASTER_MODE, 0x00 },
{ IMX335_REG_WINMODE, 0x04 },
{ IMX335_REG_HMAX, 550 },
{ IMX335_REG_HTRIMMING_START, 48 },
{ IMX335_REG_HNUM, 2592 },
{ IMX335_REG_Y_OUT_SIZE, 1944 },
{ IMX335_REG_AREA3_ST_ADR_1, 176 },
{ IMX335_REG_AREA2_WIDTH_1, 40 },
{ IMX335_REG_AREA3_WIDTH_1, 3928 },
{ IMX335_REG_OPB_SIZE_V, 0 },
{ IMX335_REG_XVS_XHS_DRV, 0x00 },
};
static const struct cci_reg_sequence mode_1312x972_regs[] = {
{ IMX335_REG_MODE_SELECT, IMX335_MODE_STANDBY },
{ IMX335_REG_MASTER_MODE, 0x00 },
{ IMX335_REG_WINMODE, 0x01 },
{ IMX335_REG_HMAX, 275 },
{ IMX335_REG_HTRIMMING_START, 48 },
{ IMX335_REG_HNUM, 2600 },
{ IMX335_REG_Y_OUT_SIZE, 972 },
{ IMX335_REG_AREA2_WIDTH_1, 48 },
{ IMX335_REG_AREA3_WIDTH_1, 3936 },
{ IMX335_REG_OPB_SIZE_V, 0 },
{ IMX335_REG_XVS_XHS_DRV, 0x00 },
{ CCI_REG8(0x3300), 1 }, /* TCYCLE */
{ CCI_REG8(0x3199), 0x30 }, /* HADD/VADD */
};
static const struct cci_reg_sequence imx335_common_regs[] = {
{ CCI_REG8(0x3288), 0x21 },
{ CCI_REG8(0x328a), 0x02 },
{ CCI_REG8(0x3414), 0x05 },
@ -333,16 +378,92 @@ static const struct cci_reg_sequence mode_2592x1940_regs[] = {
{ CCI_REG8(0x3a00), 0x00 },
};
static const struct cci_reg_sequence raw10_framefmt_regs[] = {
{ IMX335_REG_ADBIT, 0x00 },
{ IMX335_REG_MDBIT, 0x00 },
{ IMX335_REG_ADBIT1, 0x1ff },
static const struct cci_reg_sequence mode_2592x1944_vflip_normal[] = {
{ IMX335_REG_AREA3_ST_ADR_1, 176 },
/* Undocumented V-Flip related registers on Page 55 of datasheet. */
{ CCI_REG8(0x3081), 0x02, },
{ CCI_REG8(0x3083), 0x02, },
{ CCI_REG16_LE(0x30b6), 0x00 },
{ CCI_REG16_LE(0x3116), 0x08 },
};
static const struct cci_reg_sequence raw12_framefmt_regs[] = {
{ IMX335_REG_ADBIT, 0x01 },
{ IMX335_REG_MDBIT, 0x01 },
{ IMX335_REG_ADBIT1, 0x47 },
static const struct cci_reg_sequence mode_2592x1944_vflip_inverted[] = {
{ IMX335_REG_AREA3_ST_ADR_1, 4112 },
/* Undocumented V-Flip related registers on Page 55 of datasheet. */
{ CCI_REG8(0x3081), 0xfe, },
{ CCI_REG8(0x3083), 0xfe, },
{ CCI_REG16_LE(0x30b6), 0x1fa },
{ CCI_REG16_LE(0x3116), 0x002 },
};
static const struct cci_reg_sequence mode_1312x972_vflip_normal[] = {
{ IMX335_REG_AREA3_ST_ADR_1, 176 },
/* Undocumented */
{ CCI_REG8(0x3078), 0x04 },
{ CCI_REG8(0x3079), 0xfd },
{ CCI_REG8(0x307a), 0x04 },
{ CCI_REG8(0x307b), 0xfe },
{ CCI_REG8(0x307c), 0x04 },
{ CCI_REG8(0x307d), 0xfb },
{ CCI_REG8(0x307e), 0x04 },
{ CCI_REG8(0x307f), 0x02 },
{ CCI_REG8(0x3080), 0x04 },
{ CCI_REG8(0x3081), 0xfd },
{ CCI_REG8(0x3082), 0x04 },
{ CCI_REG8(0x3083), 0xfe },
{ CCI_REG8(0x3084), 0x04 },
{ CCI_REG8(0x3085), 0xfb },
{ CCI_REG8(0x3086), 0x04 },
{ CCI_REG8(0x3087), 0x02 },
{ CCI_REG8(0x30a4), 0x77 },
{ CCI_REG8(0x30a8), 0x20 },
{ CCI_REG8(0x30a9), 0x00 },
{ CCI_REG8(0x30ac), 0x08 },
{ CCI_REG8(0x30ad), 0x08 },
{ CCI_REG8(0x30b0), 0x20 },
{ CCI_REG8(0x30b1), 0x00 },
{ CCI_REG8(0x30b4), 0x10 },
{ CCI_REG8(0x30b5), 0x10 },
{ CCI_REG16_LE(0x30b6), 0x00 },
{ CCI_REG16_LE(0x3112), 0x10 },
{ CCI_REG16_LE(0x3116), 0x10 },
};
static const struct cci_reg_sequence mode_1312x972_vflip_inverted[] = {
{ IMX335_REG_AREA3_ST_ADR_1, 4112 },
/* Undocumented */
{ CCI_REG8(0x3078), 0x04 },
{ CCI_REG8(0x3079), 0xfd },
{ CCI_REG8(0x307a), 0x04 },
{ CCI_REG8(0x307b), 0xfe },
{ CCI_REG8(0x307c), 0x04 },
{ CCI_REG8(0x307d), 0xfb },
{ CCI_REG8(0x307e), 0x04 },
{ CCI_REG8(0x307f), 0x02 },
{ CCI_REG8(0x3080), 0xfc },
{ CCI_REG8(0x3081), 0x05 },
{ CCI_REG8(0x3082), 0xfc },
{ CCI_REG8(0x3083), 0x02 },
{ CCI_REG8(0x3084), 0xfc },
{ CCI_REG8(0x3085), 0x03 },
{ CCI_REG8(0x3086), 0xfc },
{ CCI_REG8(0x3087), 0xfe },
{ CCI_REG8(0x30a4), 0x77 },
{ CCI_REG8(0x30a8), 0x20 },
{ CCI_REG8(0x30a9), 0x00 },
{ CCI_REG8(0x30ac), 0x08 },
{ CCI_REG8(0x30ad), 0x78 },
{ CCI_REG8(0x30b0), 0x20 },
{ CCI_REG8(0x30b1), 0x00 },
{ CCI_REG8(0x30b4), 0x10 },
{ CCI_REG8(0x30b5), 0x70 },
{ CCI_REG16_LE(0x30b6), 0x01f2 },
{ CCI_REG16_LE(0x3112), 0x10 },
{ CCI_REG16_LE(0x3116), 0x02 },
};
static const struct cci_reg_sequence mipi_data_rate_1188Mbps[] = {
@ -407,17 +528,49 @@ static const u32 imx335_mbus_codes[] = {
};
/* Supported sensor mode configurations */
static const struct imx335_mode supported_mode = {
.width = 2592,
.height = 1944,
.hblank = 342,
.vblank = 2556,
.vblank_min = 2556,
.vblank_max = 133060,
.pclk = 396000000,
.reg_list = {
.num_of_regs = ARRAY_SIZE(mode_2592x1940_regs),
.regs = mode_2592x1940_regs,
static const struct imx335_mode supported_modes[] = {
{
.scan_mode = IMX335_ALL_PIXEL,
.width = 2592,
.height = 1944,
.hblank = 342,
.vblank = 2556,
.vblank_min = 2556,
.vblank_max = 133060,
.pclk = 396000000,
.reg_list = {
.num_of_regs = ARRAY_SIZE(mode_2592x1944_regs),
.regs = mode_2592x1944_regs,
},
.vflip_normal = {
.num_of_regs = ARRAY_SIZE(mode_2592x1944_vflip_normal),
.regs = mode_2592x1944_vflip_normal,
},
.vflip_inverted = {
.num_of_regs = ARRAY_SIZE(mode_2592x1944_vflip_inverted),
.regs = mode_2592x1944_vflip_inverted,
}
}, {
.scan_mode = IMX335_2_2_BINNING,
.width = 1312,
.height = 972,
.hblank = 155,
.vblank = 3528,
.vblank_min = 3528,
.vblank_max = 133060,
.pclk = 396000000,
.reg_list = {
.num_of_regs = ARRAY_SIZE(mode_1312x972_regs),
.regs = mode_1312x972_regs,
},
.vflip_normal = {
.num_of_regs = ARRAY_SIZE(mode_1312x972_vflip_normal),
.regs = mode_1312x972_vflip_normal,
},
.vflip_inverted = {
.num_of_regs = ARRAY_SIZE(mode_1312x972_vflip_inverted),
.regs = mode_1312x972_vflip_inverted,
},
},
};
@ -449,7 +602,8 @@ static int imx335_update_controls(struct imx335 *imx335,
if (ret)
return ret;
ret = __v4l2_ctrl_s_ctrl(imx335->hblank_ctrl, mode->hblank);
ret = __v4l2_ctrl_modify_range(imx335->hblank_ctrl, mode->hblank,
mode->hblank, 1, mode->hblank);
if (ret)
return ret;
@ -492,6 +646,19 @@ static int imx335_update_exp_gain(struct imx335 *imx335, u32 exposure, u32 gain)
return ret;
}
static int imx335_update_vertical_flip(struct imx335 *imx335, u32 vflip)
{
const struct imx335_reg_list * const vflip_regs =
vflip ? &imx335->cur_mode->vflip_inverted :
&imx335->cur_mode->vflip_normal;
int ret = 0;
cci_multi_reg_write(imx335->cci, vflip_regs->regs,
vflip_regs->num_of_regs, &ret);
return cci_write(imx335->cci, IMX335_REG_VREVERSE, vflip, &ret);
}
static int imx335_update_test_pattern(struct imx335 *imx335, u32 pattern_index)
{
int ret = 0;
@ -553,18 +720,22 @@ static int imx335_set_ctrl(struct v4l2_ctrl *ctrl)
/* Propagate change of current control to all related controls */
if (ctrl->id == V4L2_CID_VBLANK) {
u32 shutter_min = IMX335_SHUTTER_MIN;
u32 lpfr;
imx335->vblank = imx335->vblank_ctrl->val;
lpfr = imx335->vblank + imx335->cur_mode->height;
dev_dbg(imx335->dev, "Received vblank %u, new lpfr %u\n",
imx335->vblank,
imx335->vblank + imx335->cur_mode->height);
imx335->vblank, lpfr);
if (imx335->cur_mode->scan_mode == IMX335_2_2_BINNING)
shutter_min = IMX335_SHUTTER_MIN_BINNED;
ret = __v4l2_ctrl_modify_range(imx335->exp_ctrl,
IMX335_EXPOSURE_MIN,
imx335->vblank +
imx335->cur_mode->height -
IMX335_EXPOSURE_OFFSET,
1, IMX335_EXPOSURE_DEFAULT);
lpfr - shutter_min, 1,
IMX335_EXPOSURE_DEFAULT);
if (ret)
return ret;
}
@ -593,6 +764,10 @@ static int imx335_set_ctrl(struct v4l2_ctrl *ctrl)
ret = imx335_update_exp_gain(imx335, exposure, analog_gain);
break;
case V4L2_CID_VFLIP:
ret = imx335_update_vertical_flip(imx335, ctrl->val);
break;
case V4L2_CID_TEST_PATTERN:
ret = imx335_update_test_pattern(imx335, ctrl->val);
@ -660,17 +835,16 @@ static int imx335_enum_frame_size(struct v4l2_subdev *sd,
struct imx335 *imx335 = to_imx335(sd);
u32 code;
/* Only a single supported_mode available. */
if (fsize->index > 0)
if (fsize->index >= ARRAY_SIZE(supported_modes))
return -EINVAL;
code = imx335_get_format_code(imx335, fsize->code);
if (fsize->code != code)
return -EINVAL;
fsize->min_width = supported_mode.width;
fsize->min_width = supported_modes[fsize->index].width;
fsize->max_width = fsize->min_width;
fsize->min_height = supported_mode.height;
fsize->min_height = supported_modes[fsize->index].height;
fsize->max_height = fsize->min_height;
return 0;
@ -697,36 +871,6 @@ static void imx335_fill_pad_format(struct imx335 *imx335,
fmt->format.xfer_func = V4L2_XFER_FUNC_NONE;
}
/**
* imx335_get_pad_format() - Get subdevice pad format
* @sd: pointer to imx335 V4L2 sub-device structure
* @sd_state: V4L2 sub-device configuration
* @fmt: V4L2 sub-device format need to be set
*
* Return: 0 if successful, error code otherwise.
*/
static int imx335_get_pad_format(struct v4l2_subdev *sd,
struct v4l2_subdev_state *sd_state,
struct v4l2_subdev_format *fmt)
{
struct imx335 *imx335 = to_imx335(sd);
mutex_lock(&imx335->mutex);
if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
struct v4l2_mbus_framefmt *framefmt;
framefmt = v4l2_subdev_state_get_format(sd_state, fmt->pad);
fmt->format = *framefmt;
} else {
imx335_fill_pad_format(imx335, imx335->cur_mode, fmt);
}
mutex_unlock(&imx335->mutex);
return 0;
}
/**
* imx335_set_pad_format() - Set subdevice pad format
* @sd: pointer to imx335 V4L2 sub-device structure
@ -740,12 +884,16 @@ static int imx335_set_pad_format(struct v4l2_subdev *sd,
struct v4l2_subdev_format *fmt)
{
struct imx335 *imx335 = to_imx335(sd);
struct v4l2_mbus_framefmt *format;
const struct imx335_mode *mode;
struct v4l2_rect *crop;
int i, ret = 0;
mutex_lock(&imx335->mutex);
mode = v4l2_find_nearest_size(supported_modes,
ARRAY_SIZE(supported_modes),
width, height,
fmt->format.width, fmt->format.height);
mode = &supported_mode;
for (i = 0; i < ARRAY_SIZE(imx335_mbus_codes); i++) {
if (imx335_mbus_codes[i] == fmt->format.code)
imx335->cur_mbus_code = imx335_mbus_codes[i];
@ -753,19 +901,25 @@ static int imx335_set_pad_format(struct v4l2_subdev *sd,
imx335_fill_pad_format(imx335, mode, fmt);
if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
struct v4l2_mbus_framefmt *framefmt;
format = v4l2_subdev_state_get_format(sd_state, fmt->pad);
*format = fmt->format;
framefmt = v4l2_subdev_state_get_format(sd_state, fmt->pad);
*framefmt = fmt->format;
} else {
crop = v4l2_subdev_state_get_crop(sd_state, fmt->pad);
crop->width = fmt->format.width;
crop->height = fmt->format.height;
if (mode->scan_mode == IMX335_2_2_BINNING) {
crop->width *= 2;
crop->height *= 2;
}
crop->left = (imx335_native_area.width - crop->width) / 2;
crop->top = (imx335_native_area.height - crop->height) / 2;
if (fmt->which == V4L2_SUBDEV_FORMAT_ACTIVE) {
ret = imx335_update_controls(imx335, mode);
if (!ret)
imx335->cur_mode = mode;
}
mutex_unlock(&imx335->mutex);
return ret;
}
@ -783,14 +937,12 @@ static int imx335_init_state(struct v4l2_subdev *sd,
struct v4l2_subdev_format fmt = { 0 };
fmt.which = sd_state ? V4L2_SUBDEV_FORMAT_TRY : V4L2_SUBDEV_FORMAT_ACTIVE;
imx335_fill_pad_format(imx335, &supported_mode, &fmt);
imx335_fill_pad_format(imx335, &supported_modes[0], &fmt);
mutex_lock(&imx335->mutex);
__v4l2_ctrl_modify_range(imx335->link_freq_ctrl, 0,
__fls(imx335->link_freq_bitmap),
~(imx335->link_freq_bitmap),
__ffs(imx335->link_freq_bitmap));
mutex_unlock(&imx335->mutex);
return imx335_set_pad_format(sd, sd_state, &fmt);
}
@ -808,22 +960,18 @@ static int imx335_get_selection(struct v4l2_subdev *sd,
struct v4l2_subdev_selection *sel)
{
switch (sel->target) {
case V4L2_SEL_TGT_NATIVE_SIZE:
sel->r.top = 0;
sel->r.left = 0;
sel->r.width = IMX335_NATIVE_WIDTH;
sel->r.height = IMX335_NATIVE_HEIGHT;
case V4L2_SEL_TGT_CROP:
sel->r = *v4l2_subdev_state_get_crop(sd_state, 0);
return 0;
case V4L2_SEL_TGT_CROP:
case V4L2_SEL_TGT_NATIVE_SIZE:
sel->r = imx335_native_area;
return 0;
case V4L2_SEL_TGT_CROP_DEFAULT:
case V4L2_SEL_TGT_CROP_BOUNDS:
sel->r.top = IMX335_PIXEL_ARRAY_TOP;
sel->r.left = IMX335_PIXEL_ARRAY_LEFT;
sel->r.width = IMX335_PIXEL_ARRAY_WIDTH;
sel->r.height = IMX335_PIXEL_ARRAY_HEIGHT;
sel->r = imx335_active_area;
return 0;
}
@ -832,39 +980,65 @@ static int imx335_get_selection(struct v4l2_subdev *sd,
static int imx335_set_framefmt(struct imx335 *imx335)
{
switch (imx335->cur_mbus_code) {
case MEDIA_BUS_FMT_SRGGB10_1X10:
return cci_multi_reg_write(imx335->cci, raw10_framefmt_regs,
ARRAY_SIZE(raw10_framefmt_regs),
NULL);
/*
* In the all-pixel scan mode the AD conversion shall match the output
* bit width requested.
*
* However, when 2/2 binning is enabled, the AD conversion is always
* 10-bit, so we ensure ADBIT is clear and ADBIT1 is assigned 0x1ff.
* That's as much as the documentation gives us...
*/
int ret = 0;
u8 bpp = imx335->cur_mbus_code == MEDIA_BUS_FMT_SRGGB10_1X10 ? 10 : 12;
u8 ad_conv = bpp;
case MEDIA_BUS_FMT_SRGGB12_1X12:
return cci_multi_reg_write(imx335->cci, raw12_framefmt_regs,
ARRAY_SIZE(raw12_framefmt_regs),
NULL);
/* Start with the output mode */
cci_write(imx335->cci, IMX335_REG_MDBIT, bpp == 12, &ret);
/* Enforce 10 bit AD on binning modes */
if (imx335->cur_mode->scan_mode == IMX335_2_2_BINNING)
ad_conv = 10;
/* AD Conversion configuration */
if (ad_conv == 10) {
cci_write(imx335->cci, IMX335_REG_ADBIT, 0x00, &ret);
cci_write(imx335->cci, IMX335_REG_ADBIT1, 0x1ff, &ret);
} else { /* 12 bit AD Conversion */
cci_write(imx335->cci, IMX335_REG_ADBIT, 0x01, &ret);
cci_write(imx335->cci, IMX335_REG_ADBIT1, 0x47, &ret);
}
return -EINVAL;
return ret;
}
/**
* imx335_start_streaming() - Start sensor stream
* @imx335: pointer to imx335 device
* imx335_enable_streams() - Enable sensor streams
* @sd: V4L2 subdevice
* @state: V4L2 subdevice state
* @pad: The pad to enable
* @streams_mask: Bitmask of streams to enable
*
* Return: 0 if successful, error code otherwise.
*/
static int imx335_start_streaming(struct imx335 *imx335)
static int imx335_enable_streams(struct v4l2_subdev *sd,
struct v4l2_subdev_state *state, u32 pad,
u64 streams_mask)
{
struct imx335 *imx335 = to_imx335(sd);
const struct imx335_reg_list *reg_list;
int ret;
ret = pm_runtime_resume_and_get(imx335->dev);
if (ret < 0)
return ret;
/* Setup PLL */
reg_list = &link_freq_reglist[__ffs(imx335->link_freq_bitmap)];
ret = cci_multi_reg_write(imx335->cci, reg_list->regs,
reg_list->num_of_regs, NULL);
if (ret) {
dev_err(imx335->dev, "%s failed to set plls\n", __func__);
return ret;
goto err_rpm_put;
}
/* Write sensor mode registers */
@ -873,27 +1047,35 @@ static int imx335_start_streaming(struct imx335 *imx335)
reg_list->num_of_regs, NULL);
if (ret) {
dev_err(imx335->dev, "fail to write initial registers\n");
return ret;
goto err_rpm_put;
}
/* Write sensor common registers */
ret = cci_multi_reg_write(imx335->cci, imx335_common_regs,
ARRAY_SIZE(imx335_common_regs), NULL);
if (ret) {
dev_err(imx335->dev, "fail to write initial registers\n");
goto err_rpm_put;
}
ret = imx335_set_framefmt(imx335);
if (ret) {
dev_err(imx335->dev, "%s failed to set frame format: %d\n",
__func__, ret);
return ret;
goto err_rpm_put;
}
/* Configure lanes */
ret = cci_write(imx335->cci, IMX335_REG_LANEMODE,
imx335->lane_mode, NULL);
if (ret)
return ret;
goto err_rpm_put;
/* Setup handler will write actual exposure and gain */
ret = __v4l2_ctrl_handler_setup(imx335->sd.ctrl_handler);
if (ret) {
dev_err(imx335->dev, "fail to setup handler\n");
return ret;
goto err_rpm_put;
}
/* Start streaming */
@ -901,62 +1083,39 @@ static int imx335_start_streaming(struct imx335 *imx335)
IMX335_MODE_STREAMING, NULL);
if (ret) {
dev_err(imx335->dev, "fail to start streaming\n");
return ret;
goto err_rpm_put;
}
/* Initial regulator stabilization period */
usleep_range(18000, 20000);
return 0;
err_rpm_put:
pm_runtime_put(imx335->dev);
return ret;
}
/**
* imx335_stop_streaming() - Stop sensor stream
* @imx335: pointer to imx335 device
* imx335_disable_streams() - Disable sensor streams
* @sd: V4L2 subdevice
* @state: V4L2 subdevice state
* @pad: The pad to disable
* @streams_mask: Bitmask of streams to disable
*
* Return: 0 if successful, error code otherwise.
*/
static int imx335_stop_streaming(struct imx335 *imx335)
{
return cci_write(imx335->cci, IMX335_REG_MODE_SELECT,
IMX335_MODE_STANDBY, NULL);
}
/**
* imx335_set_stream() - Enable sensor streaming
* @sd: pointer to imx335 subdevice
* @enable: set to enable sensor streaming
*
* Return: 0 if successful, error code otherwise.
*/
static int imx335_set_stream(struct v4l2_subdev *sd, int enable)
static int imx335_disable_streams(struct v4l2_subdev *sd,
struct v4l2_subdev_state *state, u32 pad,
u64 streams_mask)
{
struct imx335 *imx335 = to_imx335(sd);
int ret;
mutex_lock(&imx335->mutex);
if (enable) {
ret = pm_runtime_resume_and_get(imx335->dev);
if (ret)
goto error_unlock;
ret = imx335_start_streaming(imx335);
if (ret)
goto error_power_off;
} else {
imx335_stop_streaming(imx335);
pm_runtime_put(imx335->dev);
}
mutex_unlock(&imx335->mutex);
return 0;
error_power_off:
ret = cci_write(imx335->cci, IMX335_REG_MODE_SELECT,
IMX335_MODE_STANDBY, NULL);
pm_runtime_put(imx335->dev);
error_unlock:
mutex_unlock(&imx335->mutex);
return ret;
}
@ -1009,8 +1168,8 @@ static int imx335_parse_hw_config(struct imx335 *imx335)
imx335->reset_gpio = devm_gpiod_get_optional(imx335->dev, "reset",
GPIOD_OUT_HIGH);
if (IS_ERR(imx335->reset_gpio)) {
dev_err(imx335->dev, "failed to get reset gpio %ld\n",
PTR_ERR(imx335->reset_gpio));
dev_err(imx335->dev, "failed to get reset gpio %pe\n",
imx335->reset_gpio);
return PTR_ERR(imx335->reset_gpio);
}
@ -1076,7 +1235,7 @@ static int imx335_parse_hw_config(struct imx335 *imx335)
/* V4l2 subdevice ops */
static const struct v4l2_subdev_video_ops imx335_video_ops = {
.s_stream = imx335_set_stream,
.s_stream = v4l2_subdev_s_stream_helper,
};
static const struct v4l2_subdev_pad_ops imx335_pad_ops = {
@ -1084,8 +1243,10 @@ static const struct v4l2_subdev_pad_ops imx335_pad_ops = {
.enum_frame_size = imx335_enum_frame_size,
.get_selection = imx335_get_selection,
.set_selection = imx335_get_selection,
.get_fmt = imx335_get_pad_format,
.get_fmt = v4l2_subdev_get_fmt,
.set_fmt = imx335_set_pad_format,
.enable_streams = imx335_enable_streams,
.disable_streams = imx335_disable_streams,
};
static const struct v4l2_subdev_ops imx335_subdev_ops = {
@ -1167,7 +1328,7 @@ static int imx335_init_controls(struct imx335 *imx335)
struct v4l2_ctrl_handler *ctrl_hdlr = &imx335->ctrl_handler;
const struct imx335_mode *mode = imx335->cur_mode;
struct v4l2_fwnode_device_properties props;
u32 lpfr;
u32 lpfr, shutter_min;
int ret;
ret = v4l2_fwnode_device_parse(imx335->dev, &props);
@ -1175,20 +1336,20 @@ static int imx335_init_controls(struct imx335 *imx335)
return ret;
/* v4l2_fwnode_device_properties can add two more controls */
ret = v4l2_ctrl_handler_init(ctrl_hdlr, 9);
ret = v4l2_ctrl_handler_init(ctrl_hdlr, 10);
if (ret)
return ret;
/* Serialize controls with sensor device */
ctrl_hdlr->lock = &imx335->mutex;
/* Initialize exposure and gain */
lpfr = mode->vblank + mode->height;
shutter_min = IMX335_SHUTTER_MIN;
if (mode->scan_mode == IMX335_2_2_BINNING)
shutter_min = IMX335_SHUTTER_MIN_BINNED;
imx335->exp_ctrl = v4l2_ctrl_new_std(ctrl_hdlr,
&imx335_ctrl_ops,
V4L2_CID_EXPOSURE,
IMX335_EXPOSURE_MIN,
lpfr - IMX335_EXPOSURE_OFFSET,
lpfr - shutter_min,
IMX335_EXPOSURE_STEP,
IMX335_EXPOSURE_DEFAULT);
@ -1210,6 +1371,13 @@ static int imx335_init_controls(struct imx335 *imx335)
v4l2_ctrl_cluster(2, &imx335->exp_ctrl);
imx335->vflip = v4l2_ctrl_new_std(ctrl_hdlr,
&imx335_ctrl_ops,
V4L2_CID_VFLIP,
0, 1, 1, 0);
if (imx335->vflip)
imx335->vflip->flags |= V4L2_CTRL_FLAG_MODIFY_LAYOUT;
imx335->vblank_ctrl = v4l2_ctrl_new_std(ctrl_hdlr,
&imx335_ctrl_ops,
V4L2_CID_VBLANK,
@ -1294,12 +1462,10 @@ static int imx335_probe(struct i2c_client *client)
return ret;
}
mutex_init(&imx335->mutex);
ret = imx335_power_on(imx335->dev);
if (ret) {
dev_err(imx335->dev, "failed to power-on the sensor\n");
goto error_mutex_destroy;
return ret;
}
/* Check module identity */
@ -1310,7 +1476,7 @@ static int imx335_probe(struct i2c_client *client)
}
/* Set default mode to max resolution */
imx335->cur_mode = &supported_mode;
imx335->cur_mode = &supported_modes[0];
imx335->cur_mbus_code = imx335_mbus_codes[0];
imx335->vblank = imx335->cur_mode->vblank;
@ -1332,11 +1498,18 @@ static int imx335_probe(struct i2c_client *client)
goto error_handler_free;
}
imx335->sd.state_lock = imx335->ctrl_handler.lock;
ret = v4l2_subdev_init_finalize(&imx335->sd);
if (ret < 0) {
dev_err(imx335->dev, "subdev init error\n");
goto error_media_entity;
}
ret = v4l2_async_register_subdev_sensor(&imx335->sd);
if (ret < 0) {
dev_err(imx335->dev,
"failed to register async subdev: %d\n", ret);
goto error_media_entity;
goto error_subdev_cleanup;
}
pm_runtime_set_active(imx335->dev);
@ -1345,14 +1518,14 @@ static int imx335_probe(struct i2c_client *client)
return 0;
error_subdev_cleanup:
v4l2_subdev_cleanup(&imx335->sd);
error_media_entity:
media_entity_cleanup(&imx335->sd.entity);
error_handler_free:
v4l2_ctrl_handler_free(imx335->sd.ctrl_handler);
error_power_off:
imx335_power_off(imx335->dev);
error_mutex_destroy:
mutex_destroy(&imx335->mutex);
return ret;
}
@ -1366,9 +1539,9 @@ static int imx335_probe(struct i2c_client *client)
static void imx335_remove(struct i2c_client *client)
{
struct v4l2_subdev *sd = i2c_get_clientdata(client);
struct imx335 *imx335 = to_imx335(sd);
v4l2_async_unregister_subdev(sd);
v4l2_subdev_cleanup(sd);
media_entity_cleanup(&sd->entity);
v4l2_ctrl_handler_free(sd->ctrl_handler);
@ -1376,8 +1549,6 @@ static void imx335_remove(struct i2c_client *client)
if (!pm_runtime_status_suspended(&client->dev))
imx335_power_off(&client->dev);
pm_runtime_set_suspended(&client->dev);
mutex_destroy(&imx335->mutex);
}
static const struct dev_pm_ops imx335_pm_ops = {

View File

@ -927,8 +927,8 @@ static int imx412_parse_hw_config(struct imx412 *imx412)
imx412->reset_gpio = devm_gpiod_get_optional(imx412->dev, "reset",
GPIOD_OUT_LOW);
if (IS_ERR(imx412->reset_gpio)) {
dev_err(imx412->dev, "failed to get reset gpio %ld\n",
PTR_ERR(imx412->reset_gpio));
dev_err(imx412->dev, "failed to get reset gpio %pe\n",
imx412->reset_gpio);
return PTR_ERR(imx412->reset_gpio);
}

View File

@ -751,8 +751,8 @@ static int max9286_v4l2_notifier_register(struct max9286_priv *priv)
mas = v4l2_async_nf_add_fwnode(&priv->notifier, source->fwnode,
struct max9286_asd);
if (IS_ERR(mas)) {
dev_err(dev, "Failed to add subdev for source %u: %ld",
i, PTR_ERR(mas));
dev_err(dev, "Failed to add subdev for source %u: %pe",
i, mas);
v4l2_async_nf_cleanup(&priv->notifier);
return PTR_ERR(mas);
}

View File

@ -650,7 +650,7 @@ static int max96717_v4l2_notifier_register(struct max96717_priv *priv)
fwnode_handle_put(ep_fwnode);
if (IS_ERR(asd)) {
dev_err(dev, "Failed to add subdev: %ld", PTR_ERR(asd));
dev_err(dev, "Failed to add subdev: %pe", asd);
v4l2_async_nf_cleanup(&priv->notifier);
return PTR_ERR(asd);
}
@ -782,21 +782,23 @@ static unsigned int max96717_clk_find_best_index(struct max96717_priv *priv,
return idx;
}
static long max96717_clk_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *parent_rate)
static int max96717_clk_determine_rate(struct clk_hw *hw,
struct clk_rate_request *req)
{
struct max96717_priv *priv = clk_hw_to_max96717(hw);
struct device *dev = &priv->client->dev;
unsigned int idx;
idx = max96717_clk_find_best_index(priv, rate);
idx = max96717_clk_find_best_index(priv, req->rate);
if (rate != max96717_predef_freqs[idx].freq) {
if (req->rate != max96717_predef_freqs[idx].freq) {
dev_warn(dev, "Request CLK freq:%lu, found CLK freq:%lu\n",
rate, max96717_predef_freqs[idx].freq);
req->rate, max96717_predef_freqs[idx].freq);
}
return max96717_predef_freqs[idx].freq;
req->rate = max96717_predef_freqs[idx].freq;
return 0;
}
static int max96717_clk_set_rate(struct clk_hw *hw, unsigned long rate,
@ -847,7 +849,7 @@ static const struct clk_ops max96717_clk_ops = {
.unprepare = max96717_clk_unprepare,
.set_rate = max96717_clk_set_rate,
.recalc_rate = max96717_clk_recalc_rate,
.round_rate = max96717_clk_round_rate,
.determine_rate = max96717_clk_determine_rate,
};
static int max96717_register_clkout(struct max96717_priv *priv)

View File

@ -596,6 +596,8 @@ int msp3400c_thread(void *data)
"carrier2 val: %5d / %s\n", val, cd[i].name);
}
if (max1 < 0 || max1 > 3)
goto restart;
/* program the msp3400 according to the results */
state->main = msp3400c_carrier_detect_main[max1].cdo;
switch (max1) {

View File

@ -1286,8 +1286,8 @@ static int mt9m111_probe(struct i2c_client *client)
mt9m111->regulator = devm_regulator_get(&client->dev, "vdd");
if (IS_ERR(mt9m111->regulator)) {
dev_err(&client->dev, "regulator not found: %ld\n",
PTR_ERR(mt9m111->regulator));
dev_err(&client->dev, "regulator not found: %pe\n",
mt9m111->regulator);
return PTR_ERR(mt9m111->regulator);
}

View File

@ -1139,24 +1139,24 @@ static int mt9v111_probe(struct i2c_client *client)
mt9v111->oe = devm_gpiod_get_optional(&client->dev, "enable",
GPIOD_OUT_LOW);
if (IS_ERR(mt9v111->oe)) {
dev_err(&client->dev, "Unable to get GPIO \"enable\": %ld\n",
PTR_ERR(mt9v111->oe));
dev_err(&client->dev, "Unable to get GPIO \"enable\": %pe\n",
mt9v111->oe);
return PTR_ERR(mt9v111->oe);
}
mt9v111->standby = devm_gpiod_get_optional(&client->dev, "standby",
GPIOD_OUT_HIGH);
if (IS_ERR(mt9v111->standby)) {
dev_err(&client->dev, "Unable to get GPIO \"standby\": %ld\n",
PTR_ERR(mt9v111->standby));
dev_err(&client->dev, "Unable to get GPIO \"standby\": %pe\n",
mt9v111->standby);
return PTR_ERR(mt9v111->standby);
}
mt9v111->reset = devm_gpiod_get_optional(&client->dev, "reset",
GPIOD_OUT_LOW);
if (IS_ERR(mt9v111->reset)) {
dev_err(&client->dev, "Unable to get GPIO \"reset\": %ld\n",
PTR_ERR(mt9v111->reset));
dev_err(&client->dev, "Unable to get GPIO \"reset\": %pe\n",
mt9v111->reset);
return PTR_ERR(mt9v111->reset);
}

View File

@ -174,7 +174,7 @@ static const struct reg_sequence sensor_1928x1092_30fps_setting[] = {
{0x3816, 0x01},
{0x3817, 0x01},
{0x3820, 0xb0},
{0x3820, 0xa0},
{0x3821, 0x00},
{0x3822, 0x80},
{0x3823, 0x08},
@ -385,6 +385,8 @@ struct ov02c10 {
struct v4l2_ctrl *vblank;
struct v4l2_ctrl *hblank;
struct v4l2_ctrl *exposure;
struct v4l2_ctrl *hflip;
struct v4l2_ctrl *vflip;
struct clk *img_clk;
struct gpio_desc *reset;
@ -462,6 +464,16 @@ static int ov02c10_set_ctrl(struct v4l2_ctrl *ctrl)
ret = ov02c10_test_pattern(ov02c10, ctrl->val);
break;
case V4L2_CID_HFLIP:
cci_update_bits(ov02c10->regmap, OV02C10_ROTATE_CONTROL,
BIT(3), ov02c10->hflip->val << 3, &ret);
break;
case V4L2_CID_VFLIP:
cci_update_bits(ov02c10->regmap, OV02C10_ROTATE_CONTROL,
BIT(4), ov02c10->vflip->val << 4, &ret);
break;
default:
ret = -EINVAL;
break;
@ -485,7 +497,7 @@ static int ov02c10_init_controls(struct ov02c10 *ov02c10)
s64 exposure_max, h_blank, pixel_rate;
int ret;
v4l2_ctrl_handler_init(ctrl_hdlr, 10);
v4l2_ctrl_handler_init(ctrl_hdlr, 12);
ov02c10->link_freq = v4l2_ctrl_new_int_menu(ctrl_hdlr,
&ov02c10_ctrl_ops,
@ -536,6 +548,17 @@ static int ov02c10_init_controls(struct ov02c10 *ov02c10)
exposure_max,
OV02C10_EXPOSURE_STEP,
exposure_max);
ov02c10->hflip = v4l2_ctrl_new_std(ctrl_hdlr, &ov02c10_ctrl_ops,
V4L2_CID_HFLIP, 0, 1, 1, 0);
if (ov02c10->hflip)
ov02c10->hflip->flags |= V4L2_CTRL_FLAG_MODIFY_LAYOUT;
ov02c10->vflip = v4l2_ctrl_new_std(ctrl_hdlr, &ov02c10_ctrl_ops,
V4L2_CID_VFLIP, 0, 1, 1, 0);
if (ov02c10->vflip)
ov02c10->vflip->flags |= V4L2_CTRL_FLAG_MODIFY_LAYOUT;
v4l2_ctrl_new_std_menu_items(ctrl_hdlr, &ov02c10_ctrl_ops,
V4L2_CID_TEST_PATTERN,
ARRAY_SIZE(ov02c10_test_pattern_menu) - 1,

View File

@ -1693,6 +1693,7 @@ static DEFINE_RUNTIME_DEV_PM_OPS(ov13b10_pm_ops, ov13b10_suspend,
static const struct acpi_device_id ov13b10_acpi_ids[] = {
{"OVTIDB10"},
{"OVTI13B1"},
{"OMNI13B1"}, /* ASUS ROG Flow Z13 (GZ302) uses this ACPI ID */
{ /* sentinel */ }
};

View File

@ -1184,8 +1184,8 @@ static int ov5675_get_hwcfg(struct ov5675 *ov5675)
ov5675->xvclk = devm_v4l2_sensor_clk_get(dev, NULL);
if (IS_ERR(ov5675->xvclk))
return dev_err_probe(dev, PTR_ERR(ov5675->xvclk),
"failed to get xvclk: %ld\n",
PTR_ERR(ov5675->xvclk));
"failed to get xvclk: %pe\n",
ov5675->xvclk);
xvclk_rate = clk_get_rate(ov5675->xvclk);
if (xvclk_rate != OV5675_XVCLK_19_2) {

View File

@ -1292,8 +1292,8 @@ static int ov5693_probe(struct i2c_client *client)
ov5693->xvclk = devm_v4l2_sensor_clk_get(&client->dev, "xvclk");
if (IS_ERR(ov5693->xvclk))
return dev_err_probe(&client->dev, PTR_ERR(ov5693->xvclk),
"failed to get xvclk: %ld\n",
PTR_ERR(ov5693->xvclk));
"failed to get xvclk: %pe\n",
ov5693->xvclk);
xvclk_rate = clk_get_rate(ov5693->xvclk);
if (xvclk_rate != OV5693_XVCLK_FREQ)

View File

@ -1129,8 +1129,8 @@ static int ov9282_parse_hw_config(struct ov9282 *ov9282)
ov9282->reset_gpio = devm_gpiod_get_optional(ov9282->dev, "reset",
GPIOD_OUT_LOW);
if (IS_ERR(ov9282->reset_gpio)) {
dev_err(ov9282->dev, "failed to get reset gpio %ld",
PTR_ERR(ov9282->reset_gpio));
dev_err(ov9282->dev, "failed to get reset gpio %pe",
ov9282->reset_gpio);
return PTR_ERR(ov9282->reset_gpio);
}

View File

@ -1357,8 +1357,8 @@ static int rj54n1_probe(struct i2c_client *client)
rj54n1->pwup_gpio = gpiod_get_optional(&client->dev, "powerup",
GPIOD_OUT_LOW);
if (IS_ERR(rj54n1->pwup_gpio)) {
dev_info(&client->dev, "Unable to get GPIO \"powerup\": %ld\n",
PTR_ERR(rj54n1->pwup_gpio));
dev_info(&client->dev, "Unable to get GPIO \"powerup\": %pe\n",
rj54n1->pwup_gpio);
ret = PTR_ERR(rj54n1->pwup_gpio);
goto err_clk_put;
}
@ -1366,8 +1366,8 @@ static int rj54n1_probe(struct i2c_client *client)
rj54n1->enable_gpio = gpiod_get_optional(&client->dev, "enable",
GPIOD_OUT_LOW);
if (IS_ERR(rj54n1->enable_gpio)) {
dev_info(&client->dev, "Unable to get GPIO \"enable\": %ld\n",
PTR_ERR(rj54n1->enable_gpio));
dev_info(&client->dev, "Unable to get GPIO \"enable\": %pe\n",
rj54n1->enable_gpio);
ret = PTR_ERR(rj54n1->enable_gpio);
goto err_gpio_put;
}

View File

@ -747,8 +747,8 @@ static int mipid02_parse_rx_ep(struct mipid02_dev *bridge)
of_node_put(ep_node);
if (IS_ERR(asd)) {
dev_err(&client->dev, "fail to register asd to notifier %ld",
PTR_ERR(asd));
dev_err(&client->dev, "fail to register asd to notifier %pe",
asd);
return PTR_ERR(asd);
}
bridge->notifier.ops = &mipid02_notifier_ops;

View File

@ -1222,14 +1222,16 @@ tc358746_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
return tc358746->pll_rate / (prediv * postdiv);
}
static long tc358746_mclk_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *parent_rate)
static int tc358746_mclk_determine_rate(struct clk_hw *hw,
struct clk_rate_request *req)
{
struct tc358746 *tc358746 = clk_hw_to_tc358746(hw);
*parent_rate = tc358746->pll_rate;
req->best_parent_rate = tc358746->pll_rate;
return tc358746_find_mclk_settings(tc358746, rate);
req->rate = tc358746_find_mclk_settings(tc358746, req->rate);
return 0;
}
static int tc358746_mclk_set_rate(struct clk_hw *hw, unsigned long rate,
@ -1246,7 +1248,7 @@ static const struct clk_ops tc358746_mclk_ops = {
.enable = tc358746_mclk_enable,
.disable = tc358746_mclk_disable,
.recalc_rate = tc358746_recalc_rate,
.round_rate = tc358746_mclk_round_rate,
.determine_rate = tc358746_mclk_determine_rate,
.set_rate = tc358746_mclk_set_rate,
};

View File

@ -2797,7 +2797,6 @@ static int tda1997x_probe(struct i2c_client *client)
err_free_handler:
v4l2_ctrl_handler_free(&state->hdl);
err_free_mutex:
cancel_delayed_work(&state->delayed_work_enable_hpd);
mutex_destroy(&state->page_lock);
mutex_destroy(&state->lock);
tda1997x_set_power(state, 0);

View File

@ -29,9 +29,11 @@
/* Register Map */
#define VD55G1_REG_MODEL_ID CCI_REG32_LE(0x0000)
#define VD55G1_MODEL_ID 0x53354731
#define VD55G1_MODEL_ID_VD55G1 0x53354731 /* Mono */
#define VD55G1_MODEL_ID_VD65G4 0x53354733 /* RGB */
#define VD55G1_REG_REVISION CCI_REG16_LE(0x0004)
#define VD55G1_REVISION_CCB 0x2020
#define VD55G1_REVISION_BAYER 0x3030
#define VD55G1_REG_FWPATCH_REVISION CCI_REG16_LE(0x0012)
#define VD55G1_REG_FWPATCH_START_ADDR CCI_REG8(0x2000)
#define VD55G1_REG_SYSTEM_FSM CCI_REG8(0x001c)
@ -39,7 +41,8 @@
#define VD55G1_SYSTEM_FSM_SW_STBY 0x02
#define VD55G1_SYSTEM_FSM_STREAMING 0x03
#define VD55G1_REG_BOOT CCI_REG8(0x0200)
#define VD55G1_BOOT_PATCH_SETUP 2
#define VD55G1_BOOT_BOOT 1
#define VD55G1_BOOT_PATCH_AND_BOOT 2
#define VD55G1_REG_STBY CCI_REG8(0x0201)
#define VD55G1_STBY_START_STREAM 1
#define VD55G1_REG_STREAMING CCI_REG8(0x0202)
@ -132,7 +135,10 @@
#define VD55G1_MIPI_RATE_MIN (250 * MEGA)
#define VD55G1_MIPI_RATE_MAX (1200 * MEGA)
static const u8 patch_array[] = {
#define VD55G1_MODEL_ID_NAME(id) \
((id) == VD55G1_MODEL_ID_VD55G1 ? "vd55g1" : "vd65g4")
static const u8 vd55g1_patch_array[] = {
0x44, 0x03, 0x09, 0x02, 0xe6, 0x01, 0x42, 0x00, 0xea, 0x01, 0x42, 0x00,
0xf0, 0x01, 0x42, 0x00, 0xe6, 0x01, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
@ -466,22 +472,24 @@ struct vd55g1_mode {
u32 height;
};
struct vd55g1_fmt_desc {
u32 code;
u8 bpp;
u8 data_type;
static const u32 vd55g1_mbus_formats_mono[] = {
MEDIA_BUS_FMT_Y8_1X8,
MEDIA_BUS_FMT_Y10_1X10,
};
static const struct vd55g1_fmt_desc vd55g1_mbus_codes[] = {
/* Format order is : no flip, hflip, vflip, both */
static const u32 vd55g1_mbus_formats_bayer[][4] = {
{
.code = MEDIA_BUS_FMT_Y8_1X8,
.bpp = 8,
.data_type = MIPI_CSI2_DT_RAW8,
MEDIA_BUS_FMT_SRGGB8_1X8,
MEDIA_BUS_FMT_SGRBG8_1X8,
MEDIA_BUS_FMT_SGBRG8_1X8,
MEDIA_BUS_FMT_SBGGR8_1X8,
},
{
.code = MEDIA_BUS_FMT_Y10_1X10,
.bpp = 10,
.data_type = MIPI_CSI2_DT_RAW10,
MEDIA_BUS_FMT_SRGGB10_1X10,
MEDIA_BUS_FMT_SGRBG10_1X10,
MEDIA_BUS_FMT_SGBRG10_1X10,
MEDIA_BUS_FMT_SBGGR10_1X10,
},
};
@ -524,6 +532,7 @@ struct vd55g1_vblank_limits {
struct vd55g1 {
struct device *dev;
unsigned int id;
struct v4l2_subdev sd;
struct media_pad pad;
struct regulator_bulk_data supplies[ARRAY_SIZE(vd55g1_supply_name)];
@ -572,27 +581,78 @@ static inline struct vd55g1 *ctrl_to_vd55g1(struct v4l2_ctrl *ctrl)
return to_vd55g1(sd);
}
static const struct vd55g1_fmt_desc *vd55g1_get_fmt_desc(struct vd55g1 *sensor,
u32 code)
static unsigned int vd55g1_get_fmt_bpp(u32 code)
{
unsigned int i;
switch (code) {
case MEDIA_BUS_FMT_Y8_1X8:
case MEDIA_BUS_FMT_SRGGB8_1X8:
case MEDIA_BUS_FMT_SGRBG8_1X8:
case MEDIA_BUS_FMT_SGBRG8_1X8:
case MEDIA_BUS_FMT_SBGGR8_1X8:
default:
return 8;
for (i = 0; i < ARRAY_SIZE(vd55g1_mbus_codes); i++) {
if (vd55g1_mbus_codes[i].code == code)
return &vd55g1_mbus_codes[i];
case MEDIA_BUS_FMT_Y10_1X10:
case MEDIA_BUS_FMT_SRGGB10_1X10:
case MEDIA_BUS_FMT_SGRBG10_1X10:
case MEDIA_BUS_FMT_SGBRG10_1X10:
case MEDIA_BUS_FMT_SBGGR10_1X10:
return 10;
}
}
static unsigned int vd55g1_get_fmt_data_type(u32 code)
{
switch (code) {
case MEDIA_BUS_FMT_Y8_1X8:
case MEDIA_BUS_FMT_SRGGB8_1X8:
case MEDIA_BUS_FMT_SGRBG8_1X8:
case MEDIA_BUS_FMT_SGBRG8_1X8:
case MEDIA_BUS_FMT_SBGGR8_1X8:
default:
return MIPI_CSI2_DT_RAW8;
case MEDIA_BUS_FMT_Y10_1X10:
case MEDIA_BUS_FMT_SRGGB10_1X10:
case MEDIA_BUS_FMT_SGRBG10_1X10:
case MEDIA_BUS_FMT_SGBRG10_1X10:
case MEDIA_BUS_FMT_SBGGR10_1X10:
return MIPI_CSI2_DT_RAW10;
}
}
static u32 vd55g1_get_fmt_code(struct vd55g1 *sensor, u32 code)
{
unsigned int i, j;
if (sensor->id == VD55G1_MODEL_ID_VD55G1)
return code;
for (i = 0; i < ARRAY_SIZE(vd55g1_mbus_formats_bayer); i++) {
for (j = 0; j < ARRAY_SIZE(vd55g1_mbus_formats_bayer[i]); j++) {
if (vd55g1_mbus_formats_bayer[i][j] == code)
goto adapt_bayer_pattern;
}
}
dev_warn(sensor->dev, "Unsupported mbus format\n");
return code;
adapt_bayer_pattern:
j = 0;
/* In first init_state() call, controls might not be initialized yet */
if (sensor->hflip_ctrl && sensor->vflip_ctrl) {
j = (sensor->hflip_ctrl->val ? 1 : 0) +
(sensor->vflip_ctrl->val ? 2 : 0);
}
/* Should never happen */
dev_warn(sensor->dev, "Unsupported code %d. default to 8 bpp\n", code);
return &vd55g1_mbus_codes[0];
return vd55g1_mbus_formats_bayer[i][j];
}
static s32 vd55g1_get_pixel_rate(struct vd55g1 *sensor,
struct v4l2_mbus_framefmt *format)
{
return sensor->mipi_rate /
vd55g1_get_fmt_desc(sensor, format->code)->bpp;
return sensor->mipi_rate / vd55g1_get_fmt_bpp(format->code);
}
static unsigned int vd55g1_get_hblank_min(struct vd55g1 *sensor,
@ -605,7 +665,7 @@ static unsigned int vd55g1_get_hblank_min(struct vd55g1 *sensor,
/* MIPI required time */
mipi_req_line_time = (crop->width *
vd55g1_get_fmt_desc(sensor, format->code)->bpp +
vd55g1_get_fmt_bpp(format->code) +
VD55G1_MIPI_MARGIN) /
(sensor->mipi_rate / MEGA);
mipi_req_line_length = mipi_req_line_time * sensor->pixel_clock /
@ -887,7 +947,7 @@ static void vd55g1_update_pad_fmt(struct vd55g1 *sensor,
const struct vd55g1_mode *mode, u32 code,
struct v4l2_mbus_framefmt *fmt)
{
fmt->code = code;
fmt->code = vd55g1_get_fmt_code(sensor, code);
fmt->width = mode->width;
fmt->height = mode->height;
fmt->colorspace = V4L2_COLORSPACE_RAW;
@ -951,10 +1011,9 @@ static int vd55g1_set_framefmt(struct vd55g1 *sensor,
int ret = 0;
vd55g1_write(sensor, VD55G1_REG_FORMAT_CTRL,
vd55g1_get_fmt_desc(sensor, format->code)->bpp, &ret);
vd55g1_get_fmt_bpp(format->code), &ret);
vd55g1_write(sensor, VD55G1_REG_OIF_IMG_CTRL,
vd55g1_get_fmt_desc(sensor, format->code)->data_type,
&ret);
vd55g1_get_fmt_data_type(format->code), &ret);
switch (crop->width / format->width) {
case 1:
@ -1114,26 +1173,45 @@ static int vd55g1_patch(struct vd55g1 *sensor)
u64 patch;
int ret = 0;
vd55g1_write_array(sensor, VD55G1_REG_FWPATCH_START_ADDR,
sizeof(patch_array), patch_array, &ret);
vd55g1_write(sensor, VD55G1_REG_BOOT, VD55G1_BOOT_PATCH_SETUP, &ret);
vd55g1_poll_reg(sensor, VD55G1_REG_BOOT, 0, &ret);
if (ret) {
dev_err(sensor->dev, "Failed to apply patch\n");
return ret;
/* vd55g1 needs a patch while vd65g4 does not */
if (sensor->id == VD55G1_MODEL_ID_VD55G1) {
vd55g1_write_array(sensor, VD55G1_REG_FWPATCH_START_ADDR,
sizeof(vd55g1_patch_array),
vd55g1_patch_array, &ret);
vd55g1_write(sensor, VD55G1_REG_BOOT,
VD55G1_BOOT_PATCH_AND_BOOT, &ret);
vd55g1_poll_reg(sensor, VD55G1_REG_BOOT, 0, &ret);
if (ret) {
dev_err(sensor->dev, "Failed to apply patch\n");
return ret;
}
vd55g1_read(sensor, VD55G1_REG_FWPATCH_REVISION, &patch, &ret);
if (patch != (VD55G1_FWPATCH_REVISION_MAJOR << 8) +
VD55G1_FWPATCH_REVISION_MINOR) {
dev_err(sensor->dev, "Bad patch version expected %d.%d got %d.%d\n",
VD55G1_FWPATCH_REVISION_MAJOR,
VD55G1_FWPATCH_REVISION_MINOR,
(u8)(patch >> 8), (u8)(patch & 0xff));
return -ENODEV;
}
dev_dbg(sensor->dev, "patch %d.%d applied\n",
(u8)(patch >> 8), (u8)(patch & 0xff));
} else {
vd55g1_write(sensor, VD55G1_REG_BOOT, VD55G1_BOOT_BOOT, &ret);
vd55g1_poll_reg(sensor, VD55G1_REG_BOOT, 0, &ret);
if (ret) {
dev_err(sensor->dev, "Failed to boot\n");
return ret;
}
}
vd55g1_read(sensor, VD55G1_REG_FWPATCH_REVISION, &patch, &ret);
if (patch != (VD55G1_FWPATCH_REVISION_MAJOR << 8) +
VD55G1_FWPATCH_REVISION_MINOR) {
dev_err(sensor->dev, "Bad patch version expected %d.%d got %d.%d\n",
VD55G1_FWPATCH_REVISION_MAJOR,
VD55G1_FWPATCH_REVISION_MINOR,
(u8)(patch >> 8), (u8)(patch & 0xff));
return -ENODEV;
ret = vd55g1_wait_state(sensor, VD55G1_SYSTEM_FSM_SW_STBY, NULL);
if (ret) {
dev_err(sensor->dev, "Sensor waiting after boot failed\n");
return ret;
}
dev_dbg(sensor->dev, "patch %d.%d applied\n",
(u8)(patch >> 8), (u8)(patch & 0xff));
return 0;
}
@ -1165,10 +1243,19 @@ static int vd55g1_enum_mbus_code(struct v4l2_subdev *sd,
struct v4l2_subdev_state *sd_state,
struct v4l2_subdev_mbus_code_enum *code)
{
if (code->index >= ARRAY_SIZE(vd55g1_mbus_codes))
return -EINVAL;
struct vd55g1 *sensor = to_vd55g1(sd);
u32 base_code;
code->code = vd55g1_mbus_codes[code->index].code;
if (sensor->id == VD55G1_MODEL_ID_VD55G1) {
if (code->index >= ARRAY_SIZE(vd55g1_mbus_formats_mono))
return -EINVAL;
base_code = vd55g1_mbus_formats_mono[code->index];
} else {
if (code->index >= ARRAY_SIZE(vd55g1_mbus_formats_bayer))
return -EINVAL;
base_code = vd55g1_mbus_formats_bayer[code->index][0];
}
code->code = vd55g1_get_fmt_code(sensor, base_code);
return 0;
}
@ -1275,7 +1362,7 @@ static int vd55g1_init_state(struct v4l2_subdev *sd,
return ret;
vd55g1_update_pad_fmt(sensor, &vd55g1_supported_modes[VD55G1_MODE_DEF],
vd55g1_mbus_codes[VD55G1_MBUS_CODE_DEF].code,
vd55g1_get_fmt_code(sensor, VD55G1_MBUS_CODE_DEF),
&fmt.format);
return vd55g1_set_pad_fmt(sd, sd_state, &fmt);
@ -1285,9 +1372,16 @@ static int vd55g1_enum_frame_size(struct v4l2_subdev *sd,
struct v4l2_subdev_state *sd_state,
struct v4l2_subdev_frame_size_enum *fse)
{
struct vd55g1 *sensor = to_vd55g1(sd);
u32 code;
if (fse->index >= ARRAY_SIZE(vd55g1_supported_modes))
return -EINVAL;
code = vd55g1_get_fmt_code(sensor, fse->code);
if (fse->code != code)
return -EINVAL;
fse->min_width = vd55g1_supported_modes[fse->index].width;
fse->max_width = fse->min_width;
fse->min_height = vd55g1_supported_modes[fse->index].height;
@ -1463,8 +1557,12 @@ static int vd55g1_init_ctrls(struct vd55g1 *sensor)
/* Flip cluster */
sensor->hflip_ctrl = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_HFLIP,
0, 1, 1, 0);
if (sensor->hflip_ctrl)
sensor->hflip_ctrl->flags |= V4L2_CTRL_FLAG_MODIFY_LAYOUT;
sensor->vflip_ctrl = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_VFLIP,
0, 1, 1, 0);
if (sensor->vflip_ctrl)
sensor->vflip_ctrl->flags |= V4L2_CTRL_FLAG_MODIFY_LAYOUT;
v4l2_ctrl_cluster(2, &sensor->hflip_ctrl);
/* Exposition cluster */
@ -1548,26 +1646,34 @@ static int vd55g1_init_ctrls(struct vd55g1 *sensor)
static int vd55g1_detect(struct vd55g1 *sensor)
{
u64 device_rev;
u64 id;
unsigned int dt_id = (uintptr_t)device_get_match_data(sensor->dev);
u64 rev, id;
int ret;
ret = vd55g1_read(sensor, VD55G1_REG_MODEL_ID, &id, NULL);
if (ret)
return ret;
if (id != VD55G1_MODEL_ID) {
dev_warn(sensor->dev, "Unsupported sensor id %x\n", (u32)id);
if (id != VD55G1_MODEL_ID_VD55G1 && id != VD55G1_MODEL_ID_VD65G4) {
dev_warn(sensor->dev, "Unsupported sensor id 0x%x\n",
(u32)id);
return -ENODEV;
}
if (id != dt_id) {
dev_err(sensor->dev, "Probed sensor %s and device tree definition (%s) mismatch",
VD55G1_MODEL_ID_NAME(id), VD55G1_MODEL_ID_NAME(dt_id));
return -ENODEV;
}
sensor->id = id;
ret = vd55g1_read(sensor, VD55G1_REG_REVISION, &device_rev, NULL);
ret = vd55g1_read(sensor, VD55G1_REG_REVISION, &rev, NULL);
if (ret)
return ret;
if (device_rev != VD55G1_REVISION_CCB) {
dev_err(sensor->dev, "Unsupported sensor revision (0x%x)\n",
(u16)device_rev);
if ((id == VD55G1_MODEL_ID_VD55G1 && rev != VD55G1_REVISION_CCB) &&
(id == VD55G1_MODEL_ID_VD65G4 && rev != VD55G1_REVISION_BAYER)) {
dev_err(sensor->dev, "Unsupported sensor revision 0x%x for sensor %s\n",
(u16)rev, VD55G1_MODEL_ID_NAME(id));
return -ENODEV;
}
@ -1616,13 +1722,6 @@ static int vd55g1_power_on(struct device *dev)
goto disable_clock;
}
ret = vd55g1_wait_state(sensor, VD55G1_SYSTEM_FSM_SW_STBY, NULL);
if (ret) {
dev_err(dev, "Sensor waiting after patch failed %d\n",
ret);
goto disable_clock;
}
return 0;
disable_clock:
@ -1934,7 +2033,8 @@ static void vd55g1_remove(struct i2c_client *client)
}
static const struct of_device_id vd55g1_dt_ids[] = {
{ .compatible = "st,vd55g1" },
{ .compatible = "st,vd55g1", .data = (void *)VD55G1_MODEL_ID_VD55G1 },
{ .compatible = "st,vd65g4", .data = (void *)VD55G1_MODEL_ID_VD65G4 },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, vd55g1_dt_ids);

View File

@ -79,6 +79,8 @@ static const struct ipu_sensor_config ipu_supported_sensors[] = {
IPU_SENSOR_CONFIG("OVTI02C1", 1, 400000000),
/* Omnivision OV02E10 */
IPU_SENSOR_CONFIG("OVTI02E1", 1, 360000000),
/* Omnivision ov05c10 */
IPU_SENSOR_CONFIG("OVTI05C1", 1, 480000000),
/* Omnivision OV08A10 */
IPU_SENSOR_CONFIG("OVTI08A1", 1, 500000000),
/* Omnivision OV08x40 */
@ -90,6 +92,8 @@ static const struct ipu_sensor_config ipu_supported_sensors[] = {
IPU_SENSOR_CONFIG("OVTI2680", 1, 331200000),
/* Omnivision OV8856 */
IPU_SENSOR_CONFIG("OVTI8856", 3, 180000000, 360000000, 720000000),
/* Sony IMX471 */
IPU_SENSOR_CONFIG("SONY471A", 1, 200000000),
/* Toshiba T4KA3 */
IPU_SENSOR_CONFIG("XMCC0003", 1, 321468000),
};
@ -563,8 +567,8 @@ static void ipu_bridge_instantiate_vcm_work(struct work_struct *work)
vcm_client = i2c_acpi_new_device_by_fwnode(acpi_fwnode_handle(adev),
1, &data->board_info);
if (IS_ERR(vcm_client)) {
dev_err(data->sensor, "Error instantiating VCM client: %ld\n",
PTR_ERR(vcm_client));
dev_err(data->sensor, "Error instantiating VCM client: %pe\n",
vcm_client);
goto out_pm_put;
}

View File

@ -314,8 +314,8 @@ static int cio2_csi2_calc_timing(struct cio2_device *cio2, struct cio2_queue *q,
src_pad = media_entity_remote_source_pad_unique(&q->subdev.entity);
if (IS_ERR(src_pad)) {
dev_err(dev, "can't get source pad of %s (%ld)\n",
q->subdev.name, PTR_ERR(src_pad));
dev_err(dev, "can't get source pad of %s (%pe)\n",
q->subdev.name, src_pad);
return PTR_ERR(src_pad);
}

View File

@ -42,6 +42,10 @@ static const u32 csi2_supported_codes[] = {
MEDIA_BUS_FMT_SGBRG8_1X8,
MEDIA_BUS_FMT_SGRBG8_1X8,
MEDIA_BUS_FMT_SRGGB8_1X8,
MEDIA_BUS_FMT_Y8_1X8,
MEDIA_BUS_FMT_Y10_1X10,
MEDIA_BUS_FMT_Y12_1X12,
MEDIA_BUS_FMT_Y16_1X16,
MEDIA_BUS_FMT_META_8,
MEDIA_BUS_FMT_META_10,
MEDIA_BUS_FMT_META_12,
@ -87,8 +91,8 @@ s64 ipu6_isys_csi2_get_link_freq(struct ipu6_isys_csi2 *csi2)
src_pad = media_entity_remote_source_pad_unique(&csi2->asd.sd.entity);
if (IS_ERR(src_pad)) {
dev_err(&csi2->isys->adev->auxdev.dev,
"can't get source pad of %s (%ld)\n",
csi2->asd.sd.name, PTR_ERR(src_pad));
"can't get source pad of %s (%pe)\n",
csi2->asd.sd.name, src_pad);
return PTR_ERR(src_pad);
}

View File

@ -25,24 +25,28 @@ unsigned int ipu6_isys_mbus_code_to_bpp(u32 code)
case MEDIA_BUS_FMT_RGB565_1X16:
case MEDIA_BUS_FMT_UYVY8_1X16:
case MEDIA_BUS_FMT_YUYV8_1X16:
case MEDIA_BUS_FMT_Y16_1X16:
case MEDIA_BUS_FMT_META_16:
return 16;
case MEDIA_BUS_FMT_SBGGR12_1X12:
case MEDIA_BUS_FMT_SGBRG12_1X12:
case MEDIA_BUS_FMT_SGRBG12_1X12:
case MEDIA_BUS_FMT_SRGGB12_1X12:
case MEDIA_BUS_FMT_Y12_1X12:
case MEDIA_BUS_FMT_META_12:
return 12;
case MEDIA_BUS_FMT_SBGGR10_1X10:
case MEDIA_BUS_FMT_SGBRG10_1X10:
case MEDIA_BUS_FMT_SGRBG10_1X10:
case MEDIA_BUS_FMT_SRGGB10_1X10:
case MEDIA_BUS_FMT_Y10_1X10:
case MEDIA_BUS_FMT_META_10:
return 10;
case MEDIA_BUS_FMT_SBGGR8_1X8:
case MEDIA_BUS_FMT_SGBRG8_1X8:
case MEDIA_BUS_FMT_SGRBG8_1X8:
case MEDIA_BUS_FMT_SRGGB8_1X8:
case MEDIA_BUS_FMT_Y8_1X8:
case MEDIA_BUS_FMT_META_8:
return 8;
default:
@ -65,21 +69,25 @@ unsigned int ipu6_isys_mbus_code_to_mipi(u32 code)
case MEDIA_BUS_FMT_SGBRG16_1X16:
case MEDIA_BUS_FMT_SGRBG16_1X16:
case MEDIA_BUS_FMT_SRGGB16_1X16:
case MEDIA_BUS_FMT_Y16_1X16:
return MIPI_CSI2_DT_RAW16;
case MEDIA_BUS_FMT_SBGGR12_1X12:
case MEDIA_BUS_FMT_SGBRG12_1X12:
case MEDIA_BUS_FMT_SGRBG12_1X12:
case MEDIA_BUS_FMT_SRGGB12_1X12:
case MEDIA_BUS_FMT_Y12_1X12:
return MIPI_CSI2_DT_RAW12;
case MEDIA_BUS_FMT_SBGGR10_1X10:
case MEDIA_BUS_FMT_SGBRG10_1X10:
case MEDIA_BUS_FMT_SGRBG10_1X10:
case MEDIA_BUS_FMT_SRGGB10_1X10:
case MEDIA_BUS_FMT_Y10_1X10:
return MIPI_CSI2_DT_RAW10;
case MEDIA_BUS_FMT_SBGGR8_1X8:
case MEDIA_BUS_FMT_SGBRG8_1X8:
case MEDIA_BUS_FMT_SGRBG8_1X8:
case MEDIA_BUS_FMT_SRGGB8_1X8:
case MEDIA_BUS_FMT_Y8_1X8:
return MIPI_CSI2_DT_RAW8;
case MEDIA_BUS_FMT_META_8:
case MEDIA_BUS_FMT_META_10:
@ -96,15 +104,23 @@ unsigned int ipu6_isys_mbus_code_to_mipi(u32 code)
bool ipu6_isys_is_bayer_format(u32 code)
{
switch (ipu6_isys_mbus_code_to_mipi(code)) {
case MIPI_CSI2_DT_RAW8:
case MIPI_CSI2_DT_RAW10:
case MIPI_CSI2_DT_RAW12:
case MIPI_CSI2_DT_RAW14:
case MIPI_CSI2_DT_RAW16:
case MIPI_CSI2_DT_RAW20:
case MIPI_CSI2_DT_RAW24:
case MIPI_CSI2_DT_RAW28:
switch (code) {
case MEDIA_BUS_FMT_SBGGR8_1X8:
case MEDIA_BUS_FMT_SGBRG8_1X8:
case MEDIA_BUS_FMT_SGRBG8_1X8:
case MEDIA_BUS_FMT_SRGGB8_1X8:
case MEDIA_BUS_FMT_SBGGR10_1X10:
case MEDIA_BUS_FMT_SGBRG10_1X10:
case MEDIA_BUS_FMT_SGRBG10_1X10:
case MEDIA_BUS_FMT_SRGGB10_1X10:
case MEDIA_BUS_FMT_SBGGR12_1X12:
case MEDIA_BUS_FMT_SGBRG12_1X12:
case MEDIA_BUS_FMT_SGRBG12_1X12:
case MEDIA_BUS_FMT_SRGGB12_1X12:
case MEDIA_BUS_FMT_SRGGB16_1X16:
case MEDIA_BUS_FMT_SGRBG16_1X16:
case MEDIA_BUS_FMT_SGBRG16_1X16:
case MEDIA_BUS_FMT_SBGGR16_1X16:
return true;
default:
return false;

View File

@ -77,6 +77,20 @@ const struct ipu6_isys_pixelformat ipu6_isys_pfmts[] = {
IPU6_FW_ISYS_FRAME_FORMAT_RAW10 },
{ V4L2_PIX_FMT_SRGGB10P, 10, 10, MEDIA_BUS_FMT_SRGGB10_1X10,
IPU6_FW_ISYS_FRAME_FORMAT_RAW10 },
{ V4L2_PIX_FMT_GREY, 8, 8, MEDIA_BUS_FMT_Y8_1X8,
IPU6_FW_ISYS_FRAME_FORMAT_RAW8 },
{ V4L2_PIX_FMT_Y10, 16, 10, MEDIA_BUS_FMT_Y10_1X10,
IPU6_FW_ISYS_FRAME_FORMAT_RAW16 },
{ V4L2_PIX_FMT_Y12, 16, 12, MEDIA_BUS_FMT_Y12_1X12,
IPU6_FW_ISYS_FRAME_FORMAT_RAW16 },
{ V4L2_PIX_FMT_Y16, 16, 16, MEDIA_BUS_FMT_Y16_1X16,
IPU6_FW_ISYS_FRAME_FORMAT_RAW16 },
{ V4L2_PIX_FMT_Y10P, 10, 10, MEDIA_BUS_FMT_Y10_1X10,
IPU6_FW_ISYS_FRAME_FORMAT_RAW10 },
{ V4L2_PIX_FMT_Y12P, 12, 12, MEDIA_BUS_FMT_Y12_1X12,
IPU6_FW_ISYS_FRAME_FORMAT_RAW12 },
{ V4L2_PIX_FMT_UYVY, 16, 16, MEDIA_BUS_FMT_UYVY8_1X16,
IPU6_FW_ISYS_FRAME_FORMAT_UYVY},
{ V4L2_PIX_FMT_YUYV, 16, 16, MEDIA_BUS_FMT_YUYV8_1X16,

View File

@ -414,10 +414,11 @@ static int mei_ace_setup_dev_link(struct mei_ace *ace)
/* setup link between mei_ace and mei_csi */
ace->csi_link = device_link_add(csi_dev, dev, DL_FLAG_PM_RUNTIME |
DL_FLAG_RPM_ACTIVE | DL_FLAG_STATELESS);
put_device(csi_dev);
if (!ace->csi_link) {
ret = -EINVAL;
dev_err(dev, "failed to link to %s\n", dev_name(csi_dev));
goto err_put;
goto err;
}
ace->csi_dev = csi_dev;
@ -522,7 +523,6 @@ static void mei_ace_remove(struct mei_cl_device *cldev)
cancel_work_sync(&ace->work);
device_link_del(ace->csi_link);
put_device(ace->csi_dev);
pm_runtime_disable(&cldev->dev);
pm_runtime_set_suspended(&cldev->dev);

View File

@ -17,6 +17,7 @@
#include <linux/iio/triggered_buffer.h>
#include <linux/pci.h>
#include <linux/dma/amd_xdma.h>
#include <linux/types.h>
#include "mgb4_core.h"
#include "mgb4_trigger.h"
@ -90,13 +91,13 @@ static irqreturn_t trigger_handler(int irq, void *p)
struct trigger_data *st = iio_priv(indio_dev);
struct {
u32 data;
s64 ts __aligned(8);
aligned_s64 ts;
} scan = { };
scan.data = mgb4_read_reg(&st->mgbdev->video, 0xA0);
mgb4_write_reg(&st->mgbdev->video, 0xA0, scan.data);
iio_push_to_buffers_with_timestamp(indio_dev, &scan, pf->timestamp);
iio_push_to_buffers_with_ts(indio_dev, &scan, sizeof(scan), pf->timestamp);
iio_trigger_notify_done(indio_dev->trig);
mgb4_write_reg(&st->mgbdev->video, 0xB4, 1U << 11);

View File

@ -64,10 +64,10 @@ static const struct mgb4_i2c_kv gmsl_i2c[] = {
static const struct v4l2_dv_timings_cap video_timings_cap = {
.type = V4L2_DV_BT_656_1120,
.bt = {
.min_width = 320,
.min_width = 240,
.max_width = 4096,
.min_height = 240,
.max_height = 2160,
.max_height = 4096,
.min_pixelclock = 1843200, /* 320 x 240 x 24Hz */
.max_pixelclock = 530841600, /* 4096 x 2160 x 60Hz */
.standards = V4L2_DV_BT_STD_CEA861 | V4L2_DV_BT_STD_DMT |

View File

@ -44,10 +44,10 @@ static const struct mgb4_i2c_kv fpdl3_i2c[] = {
static const struct v4l2_dv_timings_cap video_timings_cap = {
.type = V4L2_DV_BT_656_1120,
.bt = {
.min_width = 320,
.min_width = 240,
.max_width = 4096,
.min_height = 240,
.max_height = 2160,
.max_height = 4096,
.min_pixelclock = 1843200, /* 320 x 240 x 24Hz */
.max_pixelclock = 530841600, /* 4096 x 2160 x 60Hz */
.standards = V4L2_DV_BT_STD_CEA861 | V4L2_DV_BT_STD_DMT |

View File

@ -639,7 +639,7 @@ static int pt1_init_tables(struct pt1 *pt1)
if (!pt1_nr_tables)
return 0;
tables = vmalloc(array_size(pt1_nr_tables, sizeof(struct pt1_table)));
tables = vmalloc_array(pt1_nr_tables, sizeof(struct pt1_table));
if (tables == NULL)
return -ENOMEM;

View File

@ -65,6 +65,7 @@ config VIDEO_MUX
source "drivers/media/platform/allegro-dvt/Kconfig"
source "drivers/media/platform/amlogic/Kconfig"
source "drivers/media/platform/amphion/Kconfig"
source "drivers/media/platform/arm/Kconfig"
source "drivers/media/platform/aspeed/Kconfig"
source "drivers/media/platform/atmel/Kconfig"
source "drivers/media/platform/broadcom/Kconfig"

View File

@ -8,6 +8,7 @@
obj-y += allegro-dvt/
obj-y += amlogic/
obj-y += amphion/
obj-y += arm/
obj-y += aspeed/
obj-y += atmel/
obj-y += broadcom/

View File

@ -177,6 +177,7 @@ struct allegro_dev {
*/
unsigned long channel_user_ids;
struct list_head channels;
struct mutex channels_lock;
};
static const struct regmap_config allegro_regmap_config = {
@ -198,6 +199,7 @@ static const struct regmap_config allegro_sram_config = {
};
struct allegro_channel {
struct kref ref;
struct allegro_dev *dev;
struct v4l2_fh fh;
struct v4l2_ctrl_handler ctrl_handler;
@ -430,33 +432,55 @@ static unsigned long allegro_next_user_id(struct allegro_dev *dev)
}
static struct allegro_channel *
allegro_find_channel_by_user_id(struct allegro_dev *dev,
unsigned int user_id)
allegro_ref_get_channel_by_user_id(struct allegro_dev *dev,
unsigned int user_id)
{
struct allegro_channel *channel;
guard(mutex)(&dev->channels_lock);
list_for_each_entry(channel, &dev->channels, list) {
if (channel->user_id == user_id)
return channel;
if (channel->user_id == user_id) {
if (kref_get_unless_zero(&channel->ref))
return channel;
break;
}
}
return ERR_PTR(-EINVAL);
}
static struct allegro_channel *
allegro_find_channel_by_channel_id(struct allegro_dev *dev,
unsigned int channel_id)
allegro_ref_get_channel_by_channel_id(struct allegro_dev *dev,
unsigned int channel_id)
{
struct allegro_channel *channel;
guard(mutex)(&dev->channels_lock);
list_for_each_entry(channel, &dev->channels, list) {
if (channel->mcu_channel_id == channel_id)
return channel;
if (channel->mcu_channel_id == channel_id) {
if (kref_get_unless_zero(&channel->ref))
return channel;
break;
}
}
return ERR_PTR(-EINVAL);
}
static void allegro_free_channel(struct kref *ref)
{
struct allegro_channel *channel = container_of(ref, struct allegro_channel, ref);
kfree(channel);
}
static int allegro_ref_put_channel(struct allegro_channel *channel)
{
return kref_put(&channel->ref, allegro_free_channel);
}
static inline bool channel_exists(struct allegro_channel *channel)
{
return channel->mcu_channel_id != -1;
@ -831,6 +855,20 @@ static int allegro_mbox_write(struct allegro_mbox *mbox,
return err;
}
static unsigned int allegro_mbox_get_available(struct allegro_mbox *mbox)
{
struct regmap *sram = mbox->dev->sram;
unsigned int head, tail;
regmap_read(sram, mbox->head, &head);
regmap_read(sram, mbox->tail, &tail);
if (tail >= head)
return tail - head;
else
return mbox->size - (head - tail);
}
static ssize_t allegro_mbox_read(struct allegro_mbox *mbox,
u32 *dst, size_t nbyte)
{
@ -839,11 +877,15 @@ static ssize_t allegro_mbox_read(struct allegro_mbox *mbox,
u16 type;
} __attribute__ ((__packed__)) *header;
struct regmap *sram = mbox->dev->sram;
unsigned int head;
unsigned int available, head;
ssize_t size;
size_t body_no_wrap;
int stride = regmap_get_reg_stride(sram);
available = allegro_mbox_get_available(mbox);
if (available < sizeof(*header))
return -EAGAIN;
regmap_read(sram, mbox->head, &head);
if (head > mbox->size)
return -EIO;
@ -857,6 +899,8 @@ static ssize_t allegro_mbox_read(struct allegro_mbox *mbox,
return -EIO;
if (size > nbyte)
return -EINVAL;
if (size > available)
return -EAGAIN;
/*
* The message might wrap within the mailbox. If the message does not
@ -916,26 +960,27 @@ static int allegro_mbox_send(struct allegro_mbox *mbox, void *msg)
* allegro_mbox_notify() - Notify the mailbox about a new message
* @mbox: The allegro_mbox to notify
*/
static void allegro_mbox_notify(struct allegro_mbox *mbox)
static int allegro_mbox_notify(struct allegro_mbox *mbox)
{
struct allegro_dev *dev = mbox->dev;
union mcu_msg_response *msg;
ssize_t size;
u32 *tmp;
int err;
msg = kmalloc(sizeof(*msg), GFP_KERNEL);
if (!msg)
return;
return -ENOMEM;
msg->header.version = dev->fw_info->mailbox_version;
tmp = kmalloc(mbox->size, GFP_KERNEL);
if (!tmp)
if (!tmp) {
err = -ENOMEM;
goto out;
}
size = allegro_mbox_read(mbox, tmp, mbox->size);
if (size < 0)
err = allegro_mbox_read(mbox, tmp, mbox->size);
if (err < 0)
goto out;
err = allegro_decode_mail(msg, tmp);
@ -947,6 +992,8 @@ static void allegro_mbox_notify(struct allegro_mbox *mbox)
out:
kfree(tmp);
kfree(msg);
return err;
}
static int allegro_encoder_buffer_init(struct allegro_dev *dev,
@ -2124,7 +2171,7 @@ static void allegro_channel_finish_frame(struct allegro_channel *channel,
state = VB2_BUF_STATE_DONE;
v4l2_m2m_buf_copy_metadata(src_buf, dst_buf, false);
v4l2_m2m_buf_copy_metadata(src_buf, dst_buf);
if (msg->is_idr)
dst_buf->flags |= V4L2_BUF_FLAG_KEYFRAME;
else
@ -2163,7 +2210,7 @@ allegro_handle_create_channel(struct allegro_dev *dev,
int err = 0;
struct create_channel_param param;
channel = allegro_find_channel_by_user_id(dev, msg->user_id);
channel = allegro_ref_get_channel_by_user_id(dev, msg->user_id);
if (IS_ERR(channel)) {
v4l2_warn(&dev->v4l2_dev,
"received %s for unknown user %d\n",
@ -2230,6 +2277,7 @@ allegro_handle_create_channel(struct allegro_dev *dev,
out:
channel->error = err;
complete(&channel->completion);
allegro_ref_put_channel(channel);
/* Handled successfully, error is passed via channel->error */
return 0;
@ -2241,7 +2289,7 @@ allegro_handle_destroy_channel(struct allegro_dev *dev,
{
struct allegro_channel *channel;
channel = allegro_find_channel_by_channel_id(dev, msg->channel_id);
channel = allegro_ref_get_channel_by_channel_id(dev, msg->channel_id);
if (IS_ERR(channel)) {
v4l2_err(&dev->v4l2_dev,
"received %s for unknown channel %d\n",
@ -2254,6 +2302,7 @@ allegro_handle_destroy_channel(struct allegro_dev *dev,
"user %d: vcu destroyed channel %d\n",
channel->user_id, channel->mcu_channel_id);
complete(&channel->completion);
allegro_ref_put_channel(channel);
return 0;
}
@ -2264,7 +2313,7 @@ allegro_handle_encode_frame(struct allegro_dev *dev,
{
struct allegro_channel *channel;
channel = allegro_find_channel_by_channel_id(dev, msg->channel_id);
channel = allegro_ref_get_channel_by_channel_id(dev, msg->channel_id);
if (IS_ERR(channel)) {
v4l2_err(&dev->v4l2_dev,
"received %s for unknown channel %d\n",
@ -2274,6 +2323,7 @@ allegro_handle_encode_frame(struct allegro_dev *dev,
}
allegro_channel_finish_frame(channel, msg);
allegro_ref_put_channel(channel);
return 0;
}
@ -2329,7 +2379,10 @@ static irqreturn_t allegro_irq_thread(int irq, void *data)
if (!dev->mbox_status)
return IRQ_NONE;
allegro_mbox_notify(dev->mbox_status);
while (allegro_mbox_get_available(dev->mbox_status) > 0) {
if (allegro_mbox_notify(dev->mbox_status))
break;
}
return IRQ_HANDLED;
}
@ -2602,8 +2655,14 @@ static int allegro_create_channel(struct allegro_channel *channel)
allegro_mcu_send_create_channel(dev, channel);
time_left = wait_for_completion_timeout(&channel->completion,
msecs_to_jiffies(5000));
if (time_left == 0)
if (time_left == 0) {
v4l2_warn(&dev->v4l2_dev,
"user %d: timeout while creating channel\n",
channel->user_id);
channel->error = -ETIMEDOUT;
}
if (channel->error)
goto err;
@ -3050,6 +3109,8 @@ static int allegro_open(struct file *file)
if (!channel)
return -ENOMEM;
kref_init(&channel->ref);
v4l2_fh_init(&channel->fh, vdev);
init_completion(&channel->completion);
@ -3216,7 +3277,10 @@ static int allegro_open(struct file *file)
goto error;
}
list_add(&channel->list, &dev->channels);
scoped_guard(mutex, &dev->channels_lock) {
list_add(&channel->list, &dev->channels);
}
v4l2_fh_add(&channel->fh, file);
allegro_channel_adjust(channel);
@ -3232,17 +3296,20 @@ static int allegro_open(struct file *file)
static int allegro_release(struct file *file)
{
struct allegro_channel *channel = file_to_channel(file);
struct allegro_dev *dev = channel->dev;
v4l2_m2m_ctx_release(channel->fh.m2m_ctx);
list_del(&channel->list);
scoped_guard(mutex, &dev->channels_lock) {
list_del(&channel->list);
}
v4l2_ctrl_handler_free(&channel->ctrl_handler);
v4l2_fh_del(&channel->fh, file);
v4l2_fh_exit(&channel->fh);
kfree(channel);
allegro_ref_put_channel(channel);
return 0;
}
@ -3333,8 +3400,6 @@ static int allegro_s_fmt_vid_cap(struct file *file, void *fh,
return err;
vq = v4l2_m2m_get_vq(channel->fh.m2m_ctx, f->type);
if (!vq)
return -EINVAL;
if (vb2_is_busy(vq))
return -EBUSY;
@ -3836,6 +3901,7 @@ static int allegro_probe(struct platform_device *pdev)
dev->plat_dev = pdev;
init_completion(&dev->init_complete);
INIT_LIST_HEAD(&dev->channels);
mutex_init(&dev->channels_lock);
mutex_init(&dev->lock);

View File

@ -10,6 +10,7 @@ config VIDEO_C3_ISP
select VIDEO_V4L2_SUBDEV_API
select VIDEOBUF2_DMA_CONTIG
select VIDEOBUF2_VMALLOC
select V4L2_ISP
help
Video4Linux2 driver for Amlogic C3 ISP pipeline.
The C3 ISP is used for processing raw images and

View File

@ -3,11 +3,13 @@
* Copyright (C) 2024 Amlogic, Inc. All rights reserved
*/
#include <linux/build_bug.h>
#include <linux/cleanup.h>
#include <linux/media/amlogic/c3-isp-config.h>
#include <linux/pm_runtime.h>
#include <media/v4l2-ioctl.h>
#include <media/v4l2-isp.h>
#include <media/v4l2-mc.h>
#include <media/videobuf2-vmalloc.h>
@ -51,11 +53,6 @@ union c3_isp_params_block {
typedef void (*c3_isp_block_handler)(struct c3_isp_device *isp,
const union c3_isp_params_block *block);
struct c3_isp_params_handler {
size_t size;
c3_isp_block_handler handler;
};
#define to_c3_isp_params_buffer(vbuf) \
container_of(vbuf, struct c3_isp_params_buffer, vb)
@ -523,41 +520,37 @@ static void c3_isp_params_cfg_blc(struct c3_isp_device *isp,
ISP_TOP_BEO_CTRL_BLC_EN);
}
static const struct c3_isp_params_handler c3_isp_params_handlers[] = {
[C3_ISP_PARAMS_BLOCK_AWB_GAINS] = {
.size = sizeof(struct c3_isp_params_awb_gains),
.handler = c3_isp_params_cfg_awb_gains,
},
[C3_ISP_PARAMS_BLOCK_AWB_CONFIG] = {
.size = sizeof(struct c3_isp_params_awb_config),
.handler = c3_isp_params_cfg_awb_config,
},
[C3_ISP_PARAMS_BLOCK_AE_CONFIG] = {
.size = sizeof(struct c3_isp_params_ae_config),
.handler = c3_isp_params_cfg_ae_config,
},
[C3_ISP_PARAMS_BLOCK_AF_CONFIG] = {
.size = sizeof(struct c3_isp_params_af_config),
.handler = c3_isp_params_cfg_af_config,
},
[C3_ISP_PARAMS_BLOCK_PST_GAMMA] = {
.size = sizeof(struct c3_isp_params_pst_gamma),
.handler = c3_isp_params_cfg_pst_gamma,
},
[C3_ISP_PARAMS_BLOCK_CCM] = {
.size = sizeof(struct c3_isp_params_ccm),
.handler = c3_isp_params_cfg_ccm,
},
[C3_ISP_PARAMS_BLOCK_CSC] = {
.size = sizeof(struct c3_isp_params_csc),
.handler = c3_isp_params_cfg_csc,
},
[C3_ISP_PARAMS_BLOCK_BLC] = {
.size = sizeof(struct c3_isp_params_blc),
.handler = c3_isp_params_cfg_blc,
},
static const c3_isp_block_handler c3_isp_params_handlers[] = {
[C3_ISP_PARAMS_BLOCK_AWB_GAINS] = c3_isp_params_cfg_awb_gains,
[C3_ISP_PARAMS_BLOCK_AWB_CONFIG] = c3_isp_params_cfg_awb_config,
[C3_ISP_PARAMS_BLOCK_AE_CONFIG] = c3_isp_params_cfg_ae_config,
[C3_ISP_PARAMS_BLOCK_AF_CONFIG] = c3_isp_params_cfg_af_config,
[C3_ISP_PARAMS_BLOCK_PST_GAMMA] = c3_isp_params_cfg_pst_gamma,
[C3_ISP_PARAMS_BLOCK_CCM] = c3_isp_params_cfg_ccm,
[C3_ISP_PARAMS_BLOCK_CSC] = c3_isp_params_cfg_csc,
[C3_ISP_PARAMS_BLOCK_BLC] = c3_isp_params_cfg_blc,
};
#define C3_ISP_PARAMS_BLOCK_INFO(block, data) \
[C3_ISP_PARAMS_BLOCK_ ## block] = { \
.size = sizeof(struct c3_isp_params_ ## data), \
}
static const struct v4l2_isp_params_block_type_info
c3_isp_params_block_types_info[] = {
C3_ISP_PARAMS_BLOCK_INFO(AWB_GAINS, awb_gains),
C3_ISP_PARAMS_BLOCK_INFO(AWB_CONFIG, awb_config),
C3_ISP_PARAMS_BLOCK_INFO(AE_CONFIG, ae_config),
C3_ISP_PARAMS_BLOCK_INFO(AF_CONFIG, af_config),
C3_ISP_PARAMS_BLOCK_INFO(PST_GAMMA, pst_gamma),
C3_ISP_PARAMS_BLOCK_INFO(CCM, ccm),
C3_ISP_PARAMS_BLOCK_INFO(CSC, csc),
C3_ISP_PARAMS_BLOCK_INFO(BLC, blc),
};
static_assert(ARRAY_SIZE(c3_isp_params_handlers) ==
ARRAY_SIZE(c3_isp_params_block_types_info));
static void c3_isp_params_cfg_blocks(struct c3_isp_params *params)
{
struct c3_isp_params_cfg *config = params->buff->cfg;
@ -568,14 +561,14 @@ static void c3_isp_params_cfg_blocks(struct c3_isp_params *params)
/* Walk the list of parameter blocks and process them */
while (block_offset < config->data_size) {
const struct c3_isp_params_handler *block_handler;
const union c3_isp_params_block *block;
c3_isp_block_handler block_handler;
block = (const union c3_isp_params_block *)
&config->data[block_offset];
block_handler = &c3_isp_params_handlers[block->header.type];
block_handler->handler(params->isp, block);
block_handler = c3_isp_params_handlers[block->header.type];
block_handler(params->isp, block);
block_offset += block->header.size;
}
@ -771,26 +764,15 @@ static int c3_isp_params_vb2_buf_prepare(struct vb2_buffer *vb)
struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
struct c3_isp_params_buffer *buf = to_c3_isp_params_buffer(vbuf);
struct c3_isp_params *params = vb2_get_drv_priv(vb->vb2_queue);
struct c3_isp_params_cfg *cfg = buf->cfg;
struct c3_isp_params_cfg *usr_cfg = vb2_plane_vaddr(vb, 0);
size_t payload_size = vb2_get_plane_payload(vb, 0);
size_t header_size = offsetof(struct c3_isp_params_cfg, data);
size_t block_offset = 0;
size_t cfg_size;
struct c3_isp_params_cfg *cfg = buf->cfg;
int ret;
/* Payload size can't be greater than the destination buffer size */
if (payload_size > params->vfmt.fmt.meta.buffersize) {
dev_dbg(params->isp->dev,
"Payload size is too large: %zu\n", payload_size);
return -EINVAL;
}
/* Payload size can't be smaller than the header size */
if (payload_size < header_size) {
dev_dbg(params->isp->dev,
"Payload size is too small: %zu\n", payload_size);
return -EINVAL;
}
ret = v4l2_isp_params_validate_buffer_size(params->isp->dev, vb,
params->vfmt.fmt.meta.buffersize);
if (ret)
return ret;
/*
* Use the internal scratch buffer to avoid userspace modifying
@ -798,70 +780,10 @@ static int c3_isp_params_vb2_buf_prepare(struct vb2_buffer *vb)
*/
memcpy(cfg, usr_cfg, payload_size);
/* Only v0 is supported at the moment */
if (cfg->version != C3_ISP_PARAMS_BUFFER_V0) {
dev_dbg(params->isp->dev,
"Invalid params buffer version: %u\n", cfg->version);
return -EINVAL;
}
/* Validate the size reported in the parameter buffer header */
cfg_size = header_size + cfg->data_size;
if (cfg_size != payload_size) {
dev_dbg(params->isp->dev,
"Data size %zu and payload size %zu are different\n",
cfg_size, payload_size);
return -EINVAL;
}
/* Walk the list of parameter blocks and validate them */
cfg_size = cfg->data_size;
while (cfg_size >= sizeof(struct c3_isp_params_block_header)) {
const struct c3_isp_params_block_header *block;
const struct c3_isp_params_handler *handler;
block = (struct c3_isp_params_block_header *)
&cfg->data[block_offset];
if (block->type >= ARRAY_SIZE(c3_isp_params_handlers)) {
dev_dbg(params->isp->dev,
"Invalid params block type\n");
return -EINVAL;
}
if (block->size > cfg_size) {
dev_dbg(params->isp->dev,
"Block size is greater than cfg size\n");
return -EINVAL;
}
if ((block->flags & (C3_ISP_PARAMS_BLOCK_FL_ENABLE |
C3_ISP_PARAMS_BLOCK_FL_DISABLE)) ==
(C3_ISP_PARAMS_BLOCK_FL_ENABLE |
C3_ISP_PARAMS_BLOCK_FL_DISABLE)) {
dev_dbg(params->isp->dev,
"Invalid parameters block flags\n");
return -EINVAL;
}
handler = &c3_isp_params_handlers[block->type];
if (block->size != handler->size) {
dev_dbg(params->isp->dev,
"Invalid params block size\n");
return -EINVAL;
}
block_offset += block->size;
cfg_size -= block->size;
}
if (cfg_size) {
dev_dbg(params->isp->dev,
"Unexpected data after the params buffer end\n");
return -EINVAL;
}
return 0;
return v4l2_isp_params_validate_buffer(params->isp->dev, vb,
(struct v4l2_isp_params_buffer *)cfg,
c3_isp_params_block_types_info,
ARRAY_SIZE(c3_isp_params_block_types_info));
}
static int c3_isp_params_vb2_buf_init(struct vb2_buffer *vb)

View File

@ -632,13 +632,8 @@ static int vidioc_s_fmt_cap(struct file *file, void *priv, struct v4l2_format *f
static int vidioc_g_fmt(struct file *file, void *priv, struct v4l2_format *f)
{
struct ge2d_ctx *ctx = file_to_ge2d_ctx(file);
struct vb2_queue *vq;
struct ge2d_frame *frm;
vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, f->type);
if (!vq)
return -EINVAL;
frm = get_frame(ctx, f->type);
f->fmt.pix = frm->pix_fmt;

View File

@ -532,8 +532,6 @@ static int vdec_s_fmt_common(struct vpu_inst *inst, struct v4l2_format *f)
return -EINVAL;
q = v4l2_m2m_get_vq(inst->fh.m2m_ctx, f->type);
if (!q)
return -EINVAL;
if (vb2_is_busy(q))
return -EBUSY;
@ -823,7 +821,7 @@ static int vdec_frame_decoded(struct vpu_inst *inst, void *arg)
vbuf = &vpu_buf->m2m_buf.vb;
src_buf = vdec_get_src_buffer(inst, info->consumed_count);
if (src_buf) {
v4l2_m2m_buf_copy_metadata(src_buf, vbuf, true);
v4l2_m2m_buf_copy_metadata(src_buf, vbuf);
if (info->consumed_count) {
v4l2_m2m_src_buf_remove(inst->fh.m2m_ctx);
vpu_set_buffer_state(src_buf, VPU_BUF_STATE_IDLE);

View File

@ -223,8 +223,6 @@ static int venc_s_fmt(struct file *file, void *fh, struct v4l2_format *f)
struct v4l2_pix_format_mplane *pix_mp = &f->fmt.pix_mp;
q = v4l2_m2m_get_vq(inst->fh.m2m_ctx, f->type);
if (!q)
return -EINVAL;
if (vb2_is_busy(q))
return -EBUSY;
@ -790,7 +788,7 @@ static int venc_get_one_encoded_frame(struct vpu_inst *inst,
src_buf = vpu_find_buf_by_sequence(inst, inst->out_format.type, frame->info.frame_id);
if (src_buf) {
v4l2_m2m_buf_copy_metadata(src_buf, vbuf, true);
v4l2_m2m_buf_copy_metadata(src_buf, vbuf);
vpu_set_buffer_state(src_buf, VPU_BUF_STATE_IDLE);
v4l2_m2m_src_buf_remove_by_buf(inst->fh.m2m_ctx, src_buf);
v4l2_m2m_buf_done(src_buf, VB2_BUF_STATE_DONE);

View File

@ -10,7 +10,7 @@
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/of_reserved_mem.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/types.h>
@ -542,47 +542,30 @@ const struct vpu_core_resources *vpu_get_resource(struct vpu_inst *inst)
static int vpu_core_parse_dt(struct vpu_core *core, struct device_node *np)
{
struct device_node *node;
struct resource res;
int ret;
if (of_count_phandle_with_args(np, "memory-region", NULL) < 2) {
dev_err(core->dev, "need 2 memory-region for boot and rpc\n");
return -ENODEV;
ret = of_reserved_mem_region_to_resource(np, 0, &res);
if (ret) {
dev_err(core->dev, "Cannot get boot-region\n");
return ret;
}
node = of_parse_phandle(np, "memory-region", 0);
if (!node) {
dev_err(core->dev, "boot-region of_parse_phandle error\n");
return -ENODEV;
}
if (of_address_to_resource(node, 0, &res)) {
dev_err(core->dev, "boot-region of_address_to_resource error\n");
of_node_put(node);
return -EINVAL;
}
core->fw.phys = res.start;
core->fw.length = resource_size(&res);
of_node_put(node);
ret = of_reserved_mem_region_to_resource(np, 1, &res);
if (ret) {
dev_err(core->dev, "Cannot get rpc-region\n");
return ret;
}
node = of_parse_phandle(np, "memory-region", 1);
if (!node) {
dev_err(core->dev, "rpc-region of_parse_phandle error\n");
return -ENODEV;
}
if (of_address_to_resource(node, 0, &res)) {
dev_err(core->dev, "rpc-region of_address_to_resource error\n");
of_node_put(node);
return -EINVAL;
}
core->rpc.phys = res.start;
core->rpc.length = resource_size(&res);
if (core->rpc.length < core->res->rpc_size + core->res->fwlog_size) {
dev_err(core->dev, "the rpc-region <%pad, 0x%x> is not enough\n",
&core->rpc.phys, core->rpc.length);
of_node_put(node);
return -EINVAL;
}
@ -594,7 +577,6 @@ static int vpu_core_parse_dt(struct vpu_core *core, struct device_node *np)
if (ret != VPU_CORE_MEMORY_UNCACHED) {
dev_err(core->dev, "rpc region<%pad, 0x%x> isn't uncached\n",
&core->rpc.phys, core->rpc.length);
of_node_put(node);
return -EINVAL;
}
@ -606,8 +588,6 @@ static int vpu_core_parse_dt(struct vpu_core *core, struct device_node *np)
core->act.length = core->rpc.length - core->res->rpc_size - core->log.length;
core->rpc.length = core->res->rpc_size;
of_node_put(node);
return 0;
}

View File

@ -175,31 +175,6 @@ static void vpu_remove(struct platform_device *pdev)
mutex_destroy(&vpu->lock);
}
static int __maybe_unused vpu_runtime_resume(struct device *dev)
{
return 0;
}
static int __maybe_unused vpu_runtime_suspend(struct device *dev)
{
return 0;
}
static int __maybe_unused vpu_resume(struct device *dev)
{
return 0;
}
static int __maybe_unused vpu_suspend(struct device *dev)
{
return 0;
}
static const struct dev_pm_ops vpu_pm_ops = {
SET_RUNTIME_PM_OPS(vpu_runtime_suspend, vpu_runtime_resume, NULL)
SET_SYSTEM_SLEEP_PM_OPS(vpu_suspend, vpu_resume)
};
static struct vpu_resources imx8qxp_res = {
.plat_type = IMX8QXP,
.mreg_base = 0x40000000,
@ -231,7 +206,6 @@ static struct platform_driver amphion_vpu_driver = {
.driver = {
.name = "amphion-vpu",
.of_match_table = vpu_dt_match,
.pm = &vpu_pm_ops,
},
};

View File

@ -1337,22 +1337,18 @@ static int vpu_malone_insert_scode_vc1_g_seq(struct malone_scode_t *scode)
{
if (!scode->inst->total_input_count)
return 0;
if (vpu_vb_is_codecconfig(to_vb2_v4l2_buffer(scode->vb)))
scode->need_data = 0;
return 0;
}
static int vpu_malone_insert_scode_vc1_g_pic(struct malone_scode_t *scode)
{
struct vb2_v4l2_buffer *vbuf;
u8 nal_hdr[MALONE_VC1_NAL_HEADER_LEN];
u32 *data = NULL;
int ret;
vbuf = to_vb2_v4l2_buffer(scode->vb);
data = vb2_plane_vaddr(scode->vb, 0);
if (scode->inst->total_input_count == 0 || vpu_vb_is_codecconfig(vbuf))
if (scode->inst->total_input_count == 0)
return 0;
if (MALONE_VC1_CONTAIN_NAL(*data))
return 0;
@ -1373,8 +1369,6 @@ static int vpu_malone_insert_scode_vc1_l_seq(struct malone_scode_t *scode)
int size = 0;
u8 rcv_seqhdr[MALONE_VC1_RCV_SEQ_HEADER_LEN];
if (vpu_vb_is_codecconfig(to_vb2_v4l2_buffer(scode->vb)))
scode->need_data = 0;
if (scode->inst->total_input_count)
return 0;
scode->need_data = 0;
@ -1560,7 +1554,7 @@ static int vpu_malone_input_frame_data(struct vpu_malone_str_buffer __iomem *str
scode.vb = vb;
scode.wptr = wptr;
scode.need_data = 1;
if (vbuf->sequence == 0 || vpu_vb_is_codecconfig(vbuf))
if (vbuf->sequence == 0)
ret = vpu_malone_insert_scode(&scode, SCODE_SEQUENCE);
if (ret < 0)
@ -1596,7 +1590,7 @@ static int vpu_malone_input_frame_data(struct vpu_malone_str_buffer __iomem *str
* This module is currently only supported for the H264 and HEVC formats,
* for other formats, vpu_malone_add_scode() will return 0.
*/
if ((disp_imm || low_latency) && !vpu_vb_is_codecconfig(vbuf)) {
if (disp_imm || low_latency) {
ret = vpu_malone_add_scode(inst->core->iface,
inst->id,
&inst->stream_buffer,
@ -1643,7 +1637,6 @@ int vpu_malone_input_frame(struct vpu_shared_addr *shared,
struct vpu_inst *inst, struct vb2_buffer *vb)
{
struct vpu_dec_ctrl *hc = shared->priv;
struct vb2_v4l2_buffer *vbuf;
struct vpu_malone_str_buffer __iomem *str_buf = hc->str_buf[inst->id];
u32 disp_imm = hc->codec_param[inst->id].disp_imm;
u32 size;
@ -1657,16 +1650,6 @@ int vpu_malone_input_frame(struct vpu_shared_addr *shared,
return ret;
size = ret;
/*
* if buffer only contain codec data, and the timestamp is invalid,
* don't put the invalid timestamp to resync
* merge the data to next frame
*/
vbuf = to_vb2_v4l2_buffer(vb);
if (vpu_vb_is_codecconfig(vbuf)) {
inst->extra_size += size;
return 0;
}
if (inst->extra_size) {
size += inst->extra_size;
inst->extra_size = 0;

Some files were not shown because too many files have changed in this diff Show More