mirror of https://github.com/torvalds/linux.git
[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:
commit
d7aa60d966
|
|
@ -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]
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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>;
|
||||
};
|
||||
};
|
||||
};
|
||||
...
|
||||
|
|
@ -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>;
|
||||
};
|
||||
};
|
||||
|
|
@ -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 = <®_3p3v>;
|
||||
AVDD-supply = <®_1p8v>;
|
||||
DVDD-supply = <®_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>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
|
@ -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 = <®_3p3v>;
|
||||
AVDD-supply = <®_1p8v>;
|
||||
DVDD-supply = <®_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 = <®_3p3v>;
|
||||
AVDD-supply = <®_1p8v>;
|
||||
DVDD-supply = <®_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 = <®_3p3v>;
|
||||
AVDD-supply = <®_1p8v>;
|
||||
DVDD-supply = <®_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>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
|
@ -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>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
...
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
|
@ -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>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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 = <®_1v2>;
|
||||
|
||||
ports {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
port@1 {
|
||||
reg = <1>;
|
||||
|
||||
csiphy1_ep: endpoint {
|
||||
data-lanes = <0 2>;
|
||||
remote-endpoint = <&sensor_ep>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
|
@ -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>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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>;
|
||||
};
|
||||
};
|
||||
};
|
||||
...
|
||||
|
|
@ -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>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
|
@ -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>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
|
@ -16,6 +16,7 @@ description: |-
|
|||
properties:
|
||||
compatible:
|
||||
oneOf:
|
||||
- const: rockchip,rk3288-vdec
|
||||
- const: rockchip,rk3399-vdec
|
||||
- const: rockchip,rk3576-vdec
|
||||
- const: rockchip,rk3588-vdec
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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>;
|
||||
};
|
||||
};
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -27,3 +27,4 @@ Video4Linux devices
|
|||
v4l2-common
|
||||
v4l2-tveeprom
|
||||
v4l2-jpeg
|
||||
v4l2-isp
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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`
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
|
|||
59
MAINTAINERS
59
MAINTAINERS
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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];
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
/*============================================================================*/
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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 = {
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 = {
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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 */ }
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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 |
|
||||
|
|
|
|||
|
|
@ -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 |
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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/
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
},
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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
Loading…
Reference in New Issue