media updates for v6.11-rc1

-----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCAAdFiEE+QmuaPwR3wnBdVwACF8+vY7k4RUFAmaXfCQACgkQCF8+vY7k
 4RWuBg/+NRAVuzYW3AQPIaggajTGHfkk6WCTCVgQQZFCDqphS6YtgfXUJ8qO5YXk
 ZieGu+g2081BFehzcZxcaSo9pFWyqX1fjUU2sjFwRDSl9NRctsjvKE9J1DVKCsMW
 QU5yOYyBJmoVugj4YCH7Yga8OElZAWperxJidV4AmFkX93OwZDZl+wNKuSTmG/lX
 ju+Z6yzv0DN0WvgL8+LlZ2k5tpx+kAld07FFwQM54MPI9CBWyQjogGyro/1S6ymh
 WAbwbEMCvGSvGhi4issMMOK2mpmh2EAKCXBMWF5bXNOLuFWrU9TtCBr6AITKDvn7
 btQNpa8GApO+GehEQtWOX5WgZp2ypwCrMUtiwftPOtF4Z8Tl7MJfn4u6wWCxj4cy
 67HbOgWRZQRIzyUSF8vay6PeMrh8jYi+unWuOxGpnzilno1nV2hTzh4n1we15qIn
 8pnNSbtgrJCvrIgtATYjP1FWgjBxwuNIpFGxo2ly+hgbu6COLZFfg0Oju3FBdOF1
 ZxGkp1SaxcKeuFa6kbATj7y2dAjtre8drB9RfJY1C97Ta+C9ws4jBytVHbceA7u+
 GJfAis2CEStLPpe3ND9n0ekeB/qSPcgGC2HLQR7L1u30Kx75T4I49HF0lcKev9gK
 oTRUPvZu/bI6NmSRwYYY7jo1rox5ffftJ2ZICeQaluV2dbOMUc8=
 =7nBb
 -----END PGP SIGNATURE-----

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

Pull media updates from Mauro Carvalho Chehab:

 - New sensor drivers: gc05a2, gc08a3 and imx283

 - New serializer/deserializer drivers: max96714 and max96717

 - New JPEG encoder driver: e5010

 - Support for Raspberry Pi PiSP Backend (BE) ISP driver

 - Old documentation for av7110 driver removed, as a new version was
   added as Documentation/userspace-api/media/dvb/legacy*.rst

 - atompisp: Linux firmwares are now available, so drop firmware-related
   task from TODO and update firmware logic

 - The imx258 driver has gained several improvements

 - wave5 driver has gained support for HEVC decoding

 - em28xx gained support for MyGica UTV3

 - av7110 budget-patch driver removed

 - Lots of other cleanups, improvements and fixes

* tag 'media/v6.11-1' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media: (301 commits)
  media: raspberrypi: Switch to remove_new
  media: uapi: pisp_be_config: Add extra config fields
  media: uapi: pisp_be_config: Re-sort pisp_be_tiles_config
  media: uapi: pisp_common: Capitalize all macros
  media: uapi: pisp_common: Add 32 bpp format test
  media: uapi: pisp_be_config: Drop BIT() from uAPI
  media: stm32: dcmipp: correct error handling in dcmipp_create_subdevs
  media: atomisp: Fix spelling mistakes in sh_css_sp.c
  media: atomisp: Fix spelling mistake in ia_css_debug.c
  media: atomisp: Fix spelling mistake in hmm_bo.c
  media: atomisp: Fix spelling mistake in ia_css_eed1_8.host.c
  media: atomisp: Fix spelling mistake in sh_css_internal.h
  media: atomisp: Fix spelling mistake "pipline" -> "pipeline"
  media: atomisp: Remove unused GPIO related defines and APIs
  media: atomisp: Replace COMPILATION_ERROR_IF() by static_assert()
  media: atomisp: Clean up unused macros from math_support.h
  media: atomisp: csi2-bridge: Add DMI quirk for OV5693 on Xiaomi Mipad2
  media: atomisp: Update TODO
  media: atomisp: Prefix firmware paths with "intel/ipu/"
  media: atomisp: Remove firmware_name module parameter
  ...
This commit is contained in:
Linus Torvalds 2024-07-17 18:30:10 -07:00
commit b1bc554e00
405 changed files with 22013 additions and 10240 deletions

View File

@ -438,3 +438,11 @@ EM28xx cards list
- MyGica iGrabber
- em2860
- 1f4d:1abe
* - 106
- Hauppauge USB QuadHD ATSC
- em28274
- 2040:846d
* - 107
- MyGica UTV3 Analog USB2.0 TV Box
- em2860
- eb1a:2860

View File

@ -135,16 +135,16 @@ sensor ov2740 on Lenovo X1 Yoga laptop.
.. code-block:: none
media-ctl -l "\"ov2740 14-0036\":0 -> \"Intel IPU6 CSI2 1\":0[1]"
media-ctl -l "\"Intel IPU6 CSI2 1\":1 -> \"Intel IPU6 ISYS Capture 0\":0[5]"
media-ctl -l "\"Intel IPU6 CSI2 1\":2 -> \"Intel IPU6 ISYS Capture 1\":0[5]"
media-ctl -l "\"Intel IPU6 CSI2 1\":1 -> \"Intel IPU6 ISYS Capture 0\":0[1]"
media-ctl -l "\"Intel IPU6 CSI2 1\":2 -> \"Intel IPU6 ISYS Capture 1\":0[1]"
# set routing
media-ctl -v -R "\"Intel IPU6 CSI2 1\" [0/0->1/0[1],0/1->2/1[1]]"
media-ctl -R "\"Intel IPU6 CSI2 1\" [0/0->1/0[1],0/1->2/1[1]]"
media-ctl -v "\"Intel IPU6 CSI2 1\":0/0 [fmt:SGRBG10/1932x1092]"
media-ctl -v "\"Intel IPU6 CSI2 1\":0/1 [fmt:GENERIC_8/97x1]"
media-ctl -v "\"Intel IPU6 CSI2 1\":1/0 [fmt:SGRBG10/1932x1092]"
media-ctl -v "\"Intel IPU6 CSI2 1\":2/1 [fmt:GENERIC_8/97x1]"
media-ctl -V "\"Intel IPU6 CSI2 1\":0/0 [fmt:SGRBG10/1932x1092]"
media-ctl -V "\"Intel IPU6 CSI2 1\":0/1 [fmt:GENERIC_8/97x1]"
media-ctl -V "\"Intel IPU6 CSI2 1\":1/0 [fmt:SGRBG10/1932x1092]"
media-ctl -V "\"Intel IPU6 CSI2 1\":2/1 [fmt:GENERIC_8/97x1]"
CAPTURE_DEV=$(media-ctl -e "Intel IPU6 ISYS Capture 0")
./yavta --data-prefix -c100 -n5 -I -s1932x1092 --file=/tmp/frame-#.bin \

View File

@ -0,0 +1,20 @@
digraph board {
rankdir=TB
n00000001 [label="{{<port0> 0 | <port1> 1 | <port2> 2 | <port7> 7} | pispbe\n | {<port3> 3 | <port4> 4 | <port5> 5 | <port6> 6}}", shape=Mrecord, style=filled, fillcolor=green]
n00000001:port3 -> n0000001c [style=bold]
n00000001:port4 -> n00000022 [style=bold]
n00000001:port5 -> n00000028 [style=bold]
n00000001:port6 -> n0000002e [style=bold]
n0000000a [label="pispbe-input\n/dev/video0", shape=box, style=filled, fillcolor=yellow]
n0000000a -> n00000001:port0 [style=bold]
n00000010 [label="pispbe-tdn_input\n/dev/video1", shape=box, style=filled, fillcolor=yellow]
n00000010 -> n00000001:port1 [style=bold]
n00000016 [label="pispbe-stitch_input\n/dev/video2", shape=box, style=filled, fillcolor=yellow]
n00000016 -> n00000001:port2 [style=bold]
n0000001c [label="pispbe-output0\n/dev/video3", shape=box, style=filled, fillcolor=yellow]
n00000022 [label="pispbe-output1\n/dev/video4", shape=box, style=filled, fillcolor=yellow]
n00000028 [label="pispbe-tdn_output\n/dev/video5", shape=box, style=filled, fillcolor=yellow]
n0000002e [label="pispbe-stitch_output\n/dev/video6", shape=box, style=filled, fillcolor=yellow]
n00000034 [label="pispbe-config\n/dev/video7", shape=box, style=filled, fillcolor=yellow]
n00000034 -> n00000001:port7 [style=bold]
}

View File

@ -0,0 +1,109 @@
.. SPDX-License-Identifier: GPL-2.0
=========================================================
Raspberry Pi PiSP Back End Memory-to-Memory ISP (pisp-be)
=========================================================
The PiSP Back End
=================
The PiSP Back End is a memory-to-memory Image Signal Processor (ISP) which reads
image data from DRAM memory and performs image processing as specified by the
application through the parameters in a configuration buffer, before writing
pixel data back to memory through two distinct output channels.
The ISP registers and programming model are documented in the `Raspberry Pi
Image Signal Processor (PiSP) Specification document`_
The PiSP Back End ISP processes images in tiles. The handling of image
tessellation and the computation of low-level configuration parameters is
realized by a free software library called `libpisp
<https://github.com/raspberrypi/libpisp>`_.
The full image processing pipeline, which involves capturing RAW Bayer data from
an image sensor through a MIPI CSI-2 compatible capture interface, storing them
in DRAM memory and processing them in the PiSP Back End to obtain images usable
by an application is implemented in `libcamera <https://libcamera.org>`_ as
part of the Raspberry Pi platform support.
The pisp-be driver
==================
The Raspberry Pi PiSP Back End (pisp-be) driver is located under
drivers/media/platform/raspberrypi/pisp-be. It uses the `V4L2 API` to register
a number of video capture and output devices, the `V4L2 subdev API` to register
a subdevice for the ISP that connects the video devices in a single media graph
realized using the `Media Controller (MC) API`.
The media topology registered by the `pisp-be` driver is represented below:
.. _pips-be-topology:
.. kernel-figure:: raspberrypi-pisp-be.dot
:alt: Diagram of the default media pipeline topology
:align: center
The media graph registers the following video device nodes:
- pispbe-input: output device for images to be submitted to the ISP for
processing.
- pispbe-tdn_input: output device for temporal denoise.
- pispbe-stitch_input: output device for image stitching (HDR).
- pispbe-output0: first capture device for processed images.
- pispbe-output1: second capture device for processed images.
- pispbe-tdn_output: capture device for temporal denoise.
- pispbe-stitch_output: capture device for image stitching (HDR).
- pispbe-config: output device for ISP configuration parameters.
pispbe-input
------------
Images to be processed by the ISP are queued to the `pispbe-input` output device
node. For a list of image formats supported as input to the ISP refer to the
`Raspberry Pi Image Signal Processor (PiSP) Specification document`_.
pispbe-tdn_input, pispbe-tdn_output
-----------------------------------
The `pispbe-tdn_input` output video device receives images to be processed by
the temporal denoise block which are captured from the `pispbe-tdn_output`
capture video device. Userspace is responsible for maintaining queues on both
devices, and ensuring that buffers completed on the output are queued to the
input.
pispbe-stitch_input, pispbe-stitch_output
-----------------------------------------
To realize HDR (high dynamic range) image processing the image stitching and
tonemapping blocks are used. The `pispbe-stitch_output` writes images to memory
and the `pispbe-stitch_input` receives the previously written frame to process
it along with the current input image. Userspace is responsible for maintaining
queues on both devices, and ensuring that buffers completed on the output are
queued to the input.
pispbe-output0, pispbe-output1
------------------------------
The two capture devices write to memory the pixel data as processed by the ISP.
pispbe-config
-------------
The `pispbe-config` output video devices receives a buffer of configuration
parameters that define the desired image processing to be performed by the ISP.
The format of the ISP configuration parameter is defined by
:c:type:`pisp_be_tiles_config` C structure and the meaning of each parameter is
described in the `Raspberry Pi Image Signal Processor (PiSP) Specification
document`_.
ISP configuration
=================
The ISP configuration is described solely by the content of the parameters
buffer. The only parameter that userspace needs to configure using the V4L2 API
is the image format on the output and capture video devices for validation of
the content of the parameters buffer.
.. _Raspberry Pi Image Signal Processor (PiSP) Specification document: https://datasheets.raspberrypi.com/camera/raspberry-pi-image-signal-processor-specification.pdf

View File

@ -97,4 +97,6 @@ Tuner number Card name
89 Sony BTF-PG472Z PAL/SECAM
90 Sony BTF-PK467Z NTSC-M-JP
91 Sony BTF-PB463Z NTSC-M
92 Silicon Labs Si2157 tuner
93 Tena TNF931D-DFDR1
============ =====================================================

View File

@ -23,6 +23,7 @@ Video4Linux (V4L) driver-specific documentation
omap4_camera
philips
qcom_camss
raspberrypi-pisp-be
rcar-fdp1
rkisp1
saa7134

View File

@ -302,6 +302,15 @@ all configurable using the following module options:
- 0: forbid hints
- 1: allow hints
- supports_requests:
specifies if the device should support the Request API. There are
three possible values, default is 1:
- 0: no request
- 1: supports requests
- 2: requires requests
Taken together, all these module options allow you to precisely customize
the driver behavior and test your application with all sorts of permutations.
It is also very suitable to emulate hardware that is not yet available, e.g.
@ -313,10 +322,10 @@ Video Capture
This is probably the most frequently used feature. The video capture device
can be configured by using the module options num_inputs, input_types and
ccs_cap_mode (see section 1 for more detailed information), but by default
four inputs are configured: a webcam, a TV tuner, an S-Video and an HDMI
input, one input for each input type. Those are described in more detail
below.
ccs_cap_mode (see "Configuring the driver" for more detailed information),
but by default four inputs are configured: a webcam, a TV tuner, an S-Video
and an HDMI input, one input for each input type. Those are described in more
detail below.
Special attention has been given to the rate at which new frames become
available. The jitter will be around 1 jiffie (that depends on the HZ
@ -434,10 +443,10 @@ Video Output
------------
The video output device can be configured by using the module options
num_outputs, output_types and ccs_out_mode (see section 1 for more detailed
information), but by default two outputs are configured: an S-Video and an
HDMI input, one output for each output type. Those are described in more detail
below.
num_outputs, output_types and ccs_out_mode (see "Configuring the driver"
for more detailed information), but by default two outputs are configured:
an S-Video and an HDMI input, one output for each output type. Those are
described in more detail below.
Like with video capture the framerate is also exact in the long term.
@ -1011,11 +1020,6 @@ Digital Video Controls
affects the reported colorspace since DVI_D outputs will always use
sRGB.
- Display Present:
sets the presence of a "display" on the HDMI output. This affects
the tx_edid_present, tx_hotplug and tx_rxsense controls.
FM Radio Receiver Controls
~~~~~~~~~~~~~~~~~~~~~~~~~~
@ -1130,35 +1134,34 @@ Metadata Capture Controls
if set, then the generated metadata stream contains Source Clock information.
Video, VBI and RDS Looping
--------------------------
The vivid driver supports looping of video output to video input, VBI output
to VBI input and RDS output to RDS input. For video/VBI looping this emulates
as if a cable was hooked up between the output and input connector. So video
and VBI looping is only supported between S-Video and HDMI inputs and outputs.
VBI is only valid for S-Video as it makes no sense for HDMI.
Video, Sliced VBI and HDMI CEC Looping
--------------------------------------
Since radio is wireless this looping always happens if the radio receiver
frequency is close to the radio transmitter frequency. In that case the radio
transmitter will 'override' the emulated radio stations.
Video Looping functionality is supported for devices created by the same
vivid driver instance, as well as across multiple instances of the vivid driver.
The vivid driver supports looping of video and Sliced VBI data between an S-Video output
and an S-Video input. It also supports looping of video and HDMI CEC data between an
HDMI output and an HDMI input.
Looping is currently supported only between devices created by the same
vivid driver instance.
To enable looping, set the 'HDMI/S-Video XXX-N Is Connected To' control(s) to select
whether an input uses the Test Pattern Generator, or is disconnected, or is connected
to an output. An input can be connected to an output from any vivid instance.
The inputs and outputs are numbered XXX-N where XXX is the vivid instance number
(see module option n_devs). If there is only one vivid instance (the default), then
XXX will be 000. And N is the Nth S-Video/HDMI input or output of that instance.
If vivid is loaded without module options, then you can connect the S-Video 000-0 input
to the S-Video 000-0 output, or the HDMI 000-0 input to the HDMI 000-0 output.
This is the equivalent of connecting or disconnecting a cable between an input and an
output in a physical device.
If an 'HDMI/S-Video XXX-N Is Connected To' control selected an output, then the video
output will be looped to the video input provided that:
Video and Sliced VBI looping
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- the currently selected input matches the input indicated by the control name.
The way to enable video/VBI looping is currently fairly crude. A 'Loop Video'
control is available in the "Vivid" control class of the video
capture and VBI capture devices. When checked the video looping will be enabled.
Once enabled any video S-Video or HDMI input will show a static test pattern
until the video output has started. At that time the video output will be
looped to the video input provided that:
- the input type matches the output type. So the HDMI input cannot receive
video from the S-Video output.
- in the vivid instance of the output connector, the currently selected output matches
the output indicated by the control's value.
- the video resolution of the video input must match that of the video output.
So it is not possible to loop a 50 Hz (720x576) S-Video output to a 60 Hz
@ -1185,6 +1188,8 @@ looped to the video input provided that:
"DV Timings Signal Mode" for the HDMI input should be configured so that a
valid signal is passed to the video input.
If any condition is not valid, then the 'Noise' test pattern is shown.
The framerates do not have to match, although this might change in the future.
By default you will see the OSD text superimposed on top of the looped video.
@ -1198,17 +1203,26 @@ and WSS (50 Hz formats) VBI data is looped. Teletext VBI data is not looped.
Radio & RDS Looping
~~~~~~~~~~~~~~~~~~~
-------------------
As mentioned in section 6 the radio receiver emulates stations are regular
frequency intervals. Depending on the frequency of the radio receiver a
signal strength value is calculated (this is returned by VIDIOC_G_TUNER).
However, it will also look at the frequency set by the radio transmitter and
if that results in a higher signal strength than the settings of the radio
transmitter will be used as if it was a valid station. This also includes
the RDS data (if any) that the transmitter 'transmits'. This is received
faithfully on the receiver side. Note that when the driver is loaded the
frequencies of the radio receiver and transmitter are not identical, so
The vivid driver supports looping of RDS output to RDS input.
Since radio is wireless this looping always happens if the radio receiver
frequency is close to the radio transmitter frequency. In that case the radio
transmitter will 'override' the emulated radio stations.
RDS looping is currently supported only between devices created by the same
vivid driver instance.
As mentioned in the "Radio Receiver" section, the radio receiver emulates
stations at regular frequency intervals. Depending on the frequency of the
radio receiver a signal strength value is calculated (this is returned by
VIDIOC_G_TUNER). However, it will also look at the frequency set by the radio
transmitter and if that results in a higher signal strength than the settings
of the radio transmitter will be used as if it was a valid station. This also
includes the RDS data (if any) that the transmitter 'transmits'. This is
received faithfully on the receiver side. Note that when the driver is loaded
the frequencies of the radio receiver and transmitter are not identical, so
initially no looping takes place.
@ -1218,8 +1232,8 @@ Cropping, Composing, Scaling
This driver supports cropping, composing and scaling in any combination. Normally
which features are supported can be selected through the Vivid controls,
but it is also possible to hardcode it when the module is loaded through the
ccs_cap_mode and ccs_out_mode module options. See section 1 on the details of
these module options.
ccs_cap_mode and ccs_out_mode module options. See "Configuring the driver" on
the details of these module options.
This allows you to test your application for all these variations.
@ -1260,7 +1274,8 @@ is set, then the alpha component is only used for the color red and set to
The driver has to be configured to support the multiplanar formats. By default
the driver instances are single-planar. This can be changed by setting the
multiplanar module option, see section 1 for more details on that option.
multiplanar module option, see "Configuring the driver" for more details on that
option.
If the driver instance is using the multiplanar formats/API, then the first
single planar format (YUYV) and the multiplanar NV16M and NV61M formats the
@ -1270,74 +1285,6 @@ data_offset to be non-zero, so this is a useful feature for testing applications
Video output will also honor any data_offset that the application set.
Capture Overlay
---------------
Note: capture overlay support is implemented primarily to test the existing
V4L2 capture overlay API. In practice few if any GPUs support such overlays
anymore, and neither are they generally needed anymore since modern hardware
is so much more capable. By setting flag 0x10000 in the node_types module
option the vivid driver will create a simple framebuffer device that can be
used for testing this API. Whether this API should be used for new drivers is
questionable.
This driver has support for a destructive capture overlay with bitmap clipping
and list clipping (up to 16 rectangles) capabilities. Overlays are not
supported for multiplanar formats. It also honors the struct v4l2_window field
setting: if it is set to FIELD_TOP or FIELD_BOTTOM and the capture setting is
FIELD_ALTERNATE, then only the top or bottom fields will be copied to the overlay.
The overlay only works if you are also capturing at that same time. This is a
vivid limitation since it copies from a buffer to the overlay instead of
filling the overlay directly. And if you are not capturing, then no buffers
are available to fill.
In addition, the pixelformat of the capture format and that of the framebuffer
must be the same for the overlay to work. Otherwise VIDIOC_OVERLAY will return
an error.
In order to really see what it going on you will need to create two vivid
instances: the first with a framebuffer enabled. You configure the capture
overlay of the second instance to use the framebuffer of the first, then
you start capturing in the second instance. For the first instance you setup
the output overlay for the video output, turn on video looping and capture
to see the blended framebuffer overlay that's being written to by the second
instance. This setup would require the following commands:
.. code-block:: none
$ sudo modprobe vivid n_devs=2 node_types=0x10101,0x1
$ v4l2-ctl -d1 --find-fb
/dev/fb1 is the framebuffer associated with base address 0x12800000
$ sudo v4l2-ctl -d2 --set-fbuf fb=1
$ v4l2-ctl -d1 --set-fbuf fb=1
$ v4l2-ctl -d0 --set-fmt-video=pixelformat='AR15'
$ v4l2-ctl -d1 --set-fmt-video-out=pixelformat='AR15'
$ v4l2-ctl -d2 --set-fmt-video=pixelformat='AR15'
$ v4l2-ctl -d0 -i2
$ v4l2-ctl -d2 -i2
$ v4l2-ctl -d2 -c horizontal_movement=4
$ v4l2-ctl -d1 --overlay=1
$ v4l2-ctl -d0 -c loop_video=1
$ v4l2-ctl -d2 --stream-mmap --overlay=1
And from another console:
.. code-block:: none
$ v4l2-ctl -d1 --stream-out-mmap
And yet another console:
.. code-block:: none
$ qv4l2
and start streaming.
As you can see, this is not for the faint of heart...
Output Overlay
--------------
@ -1405,8 +1352,6 @@ Just as a reminder and in no particular order:
- Add ARGB888 overlay support: better testing of the alpha channel
- Improve pixel aspect support in the tpg code by passing a real v4l2_fract
- Use per-queue locks and/or per-device locks to improve throughput
- Add support to loop from a specific output to a specific input across
vivid instances
- The SDR radio should use the same 'frequencies' for stations as the normal
radio receiver, and give back noise if the frequency doesn't match up with
a station frequency

View File

@ -0,0 +1,112 @@
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
# Copyright (c) 2023 MediaTek Inc.
%YAML 1.2
---
$id: http://devicetree.org/schemas/media/i2c/galaxycore,gc05a2.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: GalaxyCore gc05a2 1/5" 5M Pixel MIPI CSI-2 sensor
maintainers:
- Zhi Mao <zhi.mao@mediatek.com>
description:
The gc05a2 is a raw image sensor with an MIPI CSI-2 image data
interface and CCI (I2C compatible) control bus. The output format
is raw Bayer.
properties:
compatible:
const: galaxycore,gc05a2
reg:
maxItems: 1
clocks:
maxItems: 1
dovdd-supply: true
avdd-supply: true
dvdd-supply: true
reset-gpios:
description: Reference to the GPIO connected to the RESETB pin.
maxItems: 1
port:
$ref: /schemas/graph.yaml#/$defs/port-base
additionalProperties: false
description:
Output port node, single endpoint describing the CSI-2 transmitter.
properties:
endpoint:
$ref: /schemas/media/video-interfaces.yaml#
unevaluatedProperties: false
properties:
data-lanes:
oneOf:
- items:
- const: 1
- const: 2
- const: 3
- const: 4
- items:
- const: 1
- const: 2
link-frequencies: true
required:
- data-lanes
- link-frequencies
required:
- endpoint
required:
- compatible
- reg
- clocks
- dovdd-supply
- avdd-supply
- dvdd-supply
- reset-gpios
- port
additionalProperties: false
examples:
- |
#include <dt-bindings/gpio/gpio.h>
i2c {
#address-cells = <1>;
#size-cells = <0>;
sensor@37 {
compatible = "galaxycore,gc05a2";
reg = <0x37>;
clocks = <&gc05a2_clk>;
reset-gpios = <&pio 21 GPIO_ACTIVE_LOW>;
avdd-supply = <&gc05a2_avdd>;
dovdd-supply = <&gc05a2_dovdd>;
dvdd-supply = <&gc05a2_dvdd>;
port {
sensor_out: endpoint {
data-lanes = <1 2>;
link-frequencies = /bits/ 64 <448000000 224000000>;
remote-endpoint = <&seninf_csi_port_1_in>;
};
};
};
};
...

View File

@ -0,0 +1,112 @@
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
# Copyright (c) 2023 MediaTek Inc.
%YAML 1.2
---
$id: http://devicetree.org/schemas/media/i2c/galaxycore,gc08a3.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: GalaxyCore gc08a3 1/4" 8M Pixel MIPI CSI-2 sensor
maintainers:
- Zhi Mao <zhi.mao@mediatek.com>
description:
The gc08a3 is a raw image sensor with an MIPI CSI-2 image data
interface and CCI (I2C compatible) control bus. The output format
is raw Bayer.
properties:
compatible:
const: galaxycore,gc08a3
reg:
maxItems: 1
clocks:
maxItems: 1
dovdd-supply: true
avdd-supply: true
dvdd-supply: true
reset-gpios:
description: Reference to the GPIO connected to the RESETB pin.
maxItems: 1
port:
$ref: /schemas/graph.yaml#/$defs/port-base
additionalProperties: false
description:
Output port node, single endpoint describing the CSI-2 transmitter.
properties:
endpoint:
$ref: /schemas/media/video-interfaces.yaml#
unevaluatedProperties: false
properties:
data-lanes:
oneOf:
- items:
- const: 1
- const: 2
- const: 3
- const: 4
- items:
- const: 1
- const: 2
link-frequencies: true
required:
- data-lanes
- link-frequencies
required:
- endpoint
required:
- compatible
- reg
- clocks
- dovdd-supply
- avdd-supply
- dvdd-supply
- reset-gpios
- port
additionalProperties: false
examples:
- |
#include <dt-bindings/gpio/gpio.h>
i2c {
#address-cells = <1>;
#size-cells = <0>;
sensor@31 {
compatible = "galaxycore,gc08a3";
reg = <0x31>;
clocks = <&gc08a3_clk>;
reset-gpios = <&pio 19 GPIO_ACTIVE_LOW>;
avdd-supply = <&gc08a3_avdd>;
dovdd-supply = <&gc08a3_dovdd>;
dvdd-supply = <&gc08a3_dvdd>;
port {
sensor_out: endpoint {
data-lanes = <1 2 3 4>;
link-frequencies = /bits/ 64 <336000000 207000000>;
remote-endpoint = <&seninf_csi_port_0_in>;
};
};
};
};
...

View File

@ -0,0 +1,174 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
# Copyright (C) 2024 Collabora Ltd.
%YAML 1.2
---
$id: http://devicetree.org/schemas/media/i2c/maxim,max96714.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Maxim MAX96714 GMSL2 to CSI-2 Deserializer
maintainers:
- Julien Massot <julien.massot@collabora.com>
description:
The MAX96714 deserializer converts GMSL2 serial inputs into MIPI
CSI-2 D-PHY formatted output. The device allows the GMSL2 link to
simultaneously transmit bidirectional control-channel data while forward
video transmissions are in progress. The MAX96714 can connect to one
remotely located serializer using industry-standard coax or STP
interconnects. The device cans operate in pixel or tunnel mode. In pixel mode
the MAX96714 can select individual video stream, while the tunnel mode forward all
the MIPI data received by the serializer.
The GMSL2 serial link operates at a fixed rate of 3Gbps or 6Gbps in the
forward direction and 187.5Mbps in the reverse direction.
MAX96714F only supports a fixed rate of 3Gbps in the forward direction.
properties:
compatible:
oneOf:
- const: maxim,max96714f
- items:
- enum:
- maxim,max96714
- const: maxim,max96714f
reg:
maxItems: 1
powerdown-gpios:
maxItems: 1
description:
Specifier for the GPIO connected to the PWDNB pin.
ports:
$ref: /schemas/graph.yaml#/properties/ports
properties:
port@0:
$ref: /schemas/graph.yaml#/properties/port
unevaluatedProperties: false
description: GMSL Input
properties:
endpoint:
$ref: /schemas/media/video-interfaces.yaml#
unevaluatedProperties: false
description:
Endpoint for GMSL2-Link port.
port@1:
$ref: /schemas/graph.yaml#/$defs/port-base
unevaluatedProperties: false
description: CSI-2 Output port
properties:
endpoint:
$ref: /schemas/media/video-interfaces.yaml#
unevaluatedProperties: false
properties:
data-lanes:
minItems: 1
maxItems: 4
lane-polarities:
minItems: 1
maxItems: 5
link-frequencies:
maxItems: 1
required:
- data-lanes
required:
- port@1
i2c-gate:
$ref: /schemas/i2c/i2c-gate.yaml
unevaluatedProperties: false
description:
The MAX96714 will pass through and forward the I2C requests from the
incoming I2C bus over the GMSL2 link. Therefore it supports an i2c-gate
subnode to configure a serializer.
port0-poc-supply:
description: Regulator providing Power over Coax for the GMSL port
required:
- compatible
- reg
- ports
additionalProperties: false
examples:
- |
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/media/video-interfaces.h>
i2c {
#address-cells = <1>;
#size-cells = <0>;
deserializer@28 {
compatible = "maxim,max96714f";
reg = <0x28>;
powerdown-gpios = <&main_gpio0 37 GPIO_ACTIVE_LOW>;
ports {
#address-cells = <1>;
#size-cells = <0>;
port@0 {
reg = <0>;
max96714_gmsl_in: endpoint {
remote-endpoint = <&max96917f_gmsl_out>;
};
};
port@1 {
reg = <1>;
max96714_csi_out: endpoint {
data-lanes = <1 2 3 4>;
link-frequencies = /bits/ 64 <400000000>;
remote-endpoint = <&csi_in>;
};
};
};
i2c-gate {
#address-cells = <1>;
#size-cells = <0>;
serializer@40 {
compatible = "maxim,max96717f";
reg = <0x40>;
gpio-controller;
#gpio-cells = <2>;
#clock-cells = <0>;
ports {
#address-cells = <1>;
#size-cells = <0>;
port@0 {
reg = <0>;
max96717f_csi_in: endpoint {
data-lanes = <1 2>;
lane-polarities = <1 0 1>;
remote-endpoint = <&sensor_out>;
};
};
port@1 {
reg = <1>;
max96917f_gmsl_out: endpoint {
remote-endpoint = <&max96714_gmsl_in>;
};
};
};
};
};
};
};
...

View File

@ -0,0 +1,157 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
# Copyright (C) 2024 Collabora Ltd.
%YAML 1.2
---
$id: http://devicetree.org/schemas/media/i2c/maxim,max96717.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: MAX96717 CSI-2 to GMSL2 Serializer
maintainers:
- Julien Massot <julien.massot@collabora.com>
description:
The MAX96717 serializer converts MIPI CSI-2 D-PHY formatted input
into GMSL2 serial outputs. The device allows the GMSL2 link to
simultaneously transmit bidirectional control-channel data while forward
video transmissions are in progress. The MAX96717 can connect to one
remotely located deserializer using industry-standard coax or STP
interconnects. The device cans operate in pixel or tunnel mode. In pixel mode
the MAX96717 can select the MIPI datatype, while the tunnel mode forward all the MIPI
data received by the serializer.
The MAX96717 supports Reference Over Reverse (channel),
to generate a clock output for the sensor from the GMSL reverse channel.
The GMSL2 serial link operates at a fixed rate of 3Gbps or 6Gbps in the
forward direction and 187.5Mbps in the reverse direction.
MAX96717F only supports a fixed rate of 3Gbps in the forward direction.
properties:
compatible:
oneOf:
- const: maxim,max96717f
- items:
- enum:
- maxim,max96717
- const: maxim,max96717f
'#gpio-cells':
const: 2
description:
First cell is the GPIO pin number, second cell is the flags. The GPIO pin
number must be in range of [0, 10].
gpio-controller: true
'#clock-cells':
const: 0
reg:
maxItems: 1
ports:
$ref: /schemas/graph.yaml#/properties/ports
properties:
port@0:
$ref: /schemas/graph.yaml#/$defs/port-base
unevaluatedProperties: false
description: CSI-2 Input port
properties:
endpoint:
$ref: /schemas/media/video-interfaces.yaml#
unevaluatedProperties: false
properties:
data-lanes:
minItems: 1
maxItems: 4
lane-polarities:
minItems: 1
maxItems: 5
required:
- data-lanes
port@1:
$ref: /schemas/graph.yaml#/properties/port
unevaluatedProperties: false
description: GMSL Output port
required:
- port@1
i2c-gate:
$ref: /schemas/i2c/i2c-gate.yaml
unevaluatedProperties: false
description:
The MAX96717 will forward the I2C requests from the
incoming GMSL2 link. Therefore, it supports an i2c-gate
subnode to configure a sensor.
required:
- compatible
- reg
- ports
additionalProperties: false
examples:
- |
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/media/video-interfaces.h>
i2c {
#address-cells = <1>;
#size-cells = <0>;
serializer: serializer@40 {
compatible = "maxim,max96717f";
reg = <0x40>;
gpio-controller;
#gpio-cells = <2>;
#clock-cells = <0>;
ports {
#address-cells = <1>;
#size-cells = <0>;
port@0 {
reg = <0>;
max96717f_csi_in: endpoint {
data-lanes = <1 2 3 4>;
remote-endpoint = <&sensor_out>;
};
};
port@1 {
reg = <1>;
max96917f_gmsl_out: endpoint {
remote-endpoint = <&deser_gmsl_in>;
};
};
};
i2c-gate {
#address-cells = <1>;
#size-cells = <0>;
sensor@10 {
compatible = "st,st-vgxy61";
reg = <0x10>;
reset-gpios = <&serializer 0 GPIO_ACTIVE_LOW>;
clocks = <&serializer>;
VCORE-supply = <&v1v2>;
VDDIO-supply = <&v1v8>;
VANA-supply = <&v2v8>;
port {
sensor_out: endpoint {
data-lanes = <1 2 3 4>;
remote-endpoint = <&max96717f_csi_in>;
};
};
};
};
};
};
...

View File

@ -1,7 +1,7 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/media/i2c/imx258.yaml#
$id: http://devicetree.org/schemas/media/i2c/sony,imx258.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Sony IMX258 13 Mpixel CMOS Digital Image Sensor
@ -13,11 +13,16 @@ description: |-
IMX258 is a diagonal 5.867mm (Type 1/3.06) 13 Mega-pixel CMOS active pixel
type stacked image sensor with a square pixel array of size 4208 x 3120. It
is programmable through I2C interface. Image data is sent through MIPI
CSI-2.
CSI-2. The sensor exists in two different models, a standard variant
(IMX258) and a variant with phase detection autofocus (IMX258-PDAF).
The camera module does not expose the model through registers, so the
exact model needs to be specified.
properties:
compatible:
const: sony,imx258
enum:
- sony,imx258
- sony,imx258-pdaf
assigned-clocks: true
assigned-clock-parents: true

View File

@ -0,0 +1,107 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
# Copyright (C) 2024 Ideas on Board Oy
%YAML 1.2
---
$id: http://devicetree.org/schemas/media/i2c/sony,imx283.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Sony IMX283 Sensor
maintainers:
- Kieran Bingham <kieran.bingham@ideasonboard.com>
- Umang Jain <umang.jain@ideasonboard.com>
description:
IMX283 sensor is a Sony CMOS active pixel digital image sensor with an active
array size of 5472H x 3648V. It is programmable through I2C interface. The
I2C client address is fixed to 0x1a as per sensor data sheet. Image data is
sent through MIPI CSI-2.
properties:
compatible:
const: sony,imx283
reg:
maxItems: 1
clocks:
description: Clock frequency from 6 to 24 MHz.
maxItems: 1
vadd-supply:
description: Analog power supply (2.9V)
vdd1-supply:
description: Interface power supply (1.8V)
vdd2-supply:
description: Digital power supply (1.2V)
reset-gpios:
description: Sensor reset (XCLR) GPIO
maxItems: 1
port:
$ref: /schemas/graph.yaml#/$defs/port-base
additionalProperties: false
properties:
endpoint:
$ref: /schemas/media/video-interfaces.yaml#
unevaluatedProperties: false
properties:
data-lanes:
anyOf:
- items:
- const: 1
- const: 2
- const: 3
- const: 4
link-frequencies: true
required:
- data-lanes
- link-frequencies
required:
- endpoint
required:
- compatible
- reg
- clocks
- port
additionalProperties: false
examples:
- |
i2c {
#address-cells = <1>;
#size-cells = <0>;
camera@1a {
compatible = "sony,imx283";
reg = <0x1a>;
clocks = <&imx283_clk>;
assigned-clocks = <&imx283_clk>;
assigned-clock-parents = <&imx283_clk_parent>;
assigned-clock-rates = <12000000>;
vadd-supply = <&camera_vadd_2v9>;
vdd1-supply = <&camera_vdd1_1v8>;
vdd2-supply = <&camera_vdd2_1v2>;
port {
imx283: endpoint {
remote-endpoint = <&cam>;
data-lanes = <1 2 3 4>;
link-frequencies = /bits/ 64 <360000000>;
};
};
};
};
...

View File

@ -0,0 +1,75 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/media/img,e5010-jpeg-enc.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Imagination E5010 JPEG Encoder
maintainers:
- Devarsh Thakkar <devarsht@ti.com>
description: |
The E5010 is a JPEG encoder from Imagination Technologies implemented on
TI's AM62A SoC. It is capable of real time encoding of YUV420 and YUV422
inputs to JPEG and M-JPEG. It supports baseline JPEG Encoding up to
8Kx8K resolution.
properties:
compatible:
oneOf:
- items:
- const: ti,am62a-jpeg-enc
- const: img,e5010-jpeg-enc
- const: img,e5010-jpeg-enc
reg:
items:
- description: The E5010 core register region
- description: The E5010 mmu register region
reg-names:
items:
- const: core
- const: mmu
power-domains:
maxItems: 1
resets:
maxItems: 1
clocks:
maxItems: 1
interrupts:
maxItems: 1
required:
- compatible
- reg
- reg-names
- interrupts
- clocks
additionalProperties: false
examples:
- |
#include <dt-bindings/soc/ti,sci_pm_domain.h>
#include <dt-bindings/interrupt-controller/arm-gic.h>
#include <dt-bindings/interrupt-controller/irq.h>
soc {
#address-cells = <2>;
#size-cells = <2>;
jpeg-encoder@fd20000 {
compatible = "img,e5010-jpeg-enc";
reg = <0x00 0xfd20000 0x00 0x100>,
<0x00 0xfd20200 0x00 0x200>;
reg-names = "core", "mmu";
clocks = <&k3_clks 201 0>;
power-domains = <&k3_pds 201 TI_SCI_PD_EXCLUSIVE>;
interrupts = <GIC_SPI 98 IRQ_TYPE_LEVEL_HIGH>;
};
};

View File

@ -23,6 +23,7 @@ properties:
oneOf:
- enum:
- mediatek,mt8183-mdp3-rdma
- mediatek,mt8188-mdp3-rdma
- mediatek,mt8195-mdp3-rdma
- mediatek,mt8195-vdo1-rdma
- items:

View File

@ -0,0 +1,55 @@
# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
%YAML 1.2
---
$id: http://devicetree.org/schemas/media/mediatek,mt7622-cir.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: MediaTek Consumer Infrared Receiver on-SoC Controller
maintainers:
- Sean Wang <sean.wang@mediatek.com>
allOf:
- $ref: rc.yaml#
properties:
compatible:
enum:
- mediatek,mt7622-cir
- mediatek,mt7623-cir
reg:
maxItems: 1
interrupts:
maxItems: 1
clocks:
maxItems: 2
clock-names:
items:
- const: clk
- const: bus
required:
- reg
- interrupts
- clocks
- clock-names
unevaluatedProperties: false
examples:
- |
#include <dt-bindings/clock/mt2701-clk.h>
#include <dt-bindings/interrupt-controller/arm-gic.h>
ir@10013000 {
compatible = "mediatek,mt7623-cir";
reg = <0x10013000 0x1000>;
interrupts = <GIC_SPI 87 IRQ_TYPE_LEVEL_LOW>;
clocks = <&infracfg CLK_INFRA_IRRX>, <&topckgen CLK_TOP_AXI_SEL>;
clock-names = "clk", "bus";
linux,rc-map-name = "rc-rc6-mce";
};

View File

@ -1,28 +0,0 @@
Device-Tree bindings for Mediatek consumer IR controller
found in Mediatek SoC family
Required properties:
- compatible : Should be
"mediatek,mt7623-cir": for MT7623 SoC
"mediatek,mt7622-cir": for MT7622 SoC
- clocks : list of clock specifiers, corresponding to
entries in clock-names property;
- clock-names : should contain
- "clk" entries: for MT7623 SoC
- "clk", "bus" entries: for MT7622 SoC
- interrupts : should contain IR IRQ number;
- reg : should contain IO map address for IR.
Optional properties:
- linux,rc-map-name : see rc.txt file in the same directory.
Example:
cir: cir@10013000 {
compatible = "mediatek,mt7623-cir";
reg = <0 0x10013000 0 0x1000>;
interrupts = <GIC_SPI 87 IRQ_TYPE_LEVEL_LOW>;
clocks = <&infracfg CLK_INFRA_IRRX>;
clock-names = "clk";
linux,rc-map-name = "rc-rc6-mce";
};

View File

@ -18,7 +18,9 @@ allOf:
properties:
compatible:
const: qcom,msm8996-venus
enum:
- qcom,msm8996-venus
- qcom,msm8998-venus
power-domains:
maxItems: 1

View File

@ -0,0 +1,63 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/media/raspberrypi,pispbe.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Raspberry Pi PiSP Image Signal Processor (ISP) Back End
maintainers:
- Raspberry Pi Kernel Maintenance <kernel-list@raspberrypi.com>
- Jacopo Mondi <jacopo.mondi@ideasonboard.com>
description: |
The Raspberry Pi PiSP Image Signal Processor (ISP) Back End is an image
processor that fetches images in Bayer or Grayscale format from DRAM memory
in tiles and produces images consumable by applications.
The full ISP documentation is available at
https://datasheets.raspberrypi.com/camera/raspberry-pi-image-signal-processor-specification.pdf
properties:
compatible:
items:
- enum:
- brcm,bcm2712-pispbe
- const: raspberrypi,pispbe
reg:
maxItems: 1
interrupts:
maxItems: 1
clocks:
maxItems: 1
iommus:
maxItems: 1
required:
- compatible
- reg
- interrupts
- clocks
additionalProperties: false
examples:
- |
#include <dt-bindings/interrupt-controller/arm-gic.h>
soc {
#address-cells = <2>;
#size-cells = <2>;
isp@880000 {
compatible = "brcm,bcm2712-pispbe", "raspberrypi,pispbe";
reg = <0x10 0x00880000 0x0 0x4000>;
interrupts = <GIC_SPI 72 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&firmware_clocks 7>;
iommus = <&iommu2>;
};
};

View File

@ -103,6 +103,7 @@ properties:
- rc-msi-digivox-iii
- rc-msi-tvanywhere
- rc-msi-tvanywhere-plus
- rc-mygica-utv3
- rc-nebula
- rc-nec-terratec-cinergy-xs
- rc-norwood

View File

@ -24,6 +24,7 @@ properties:
- enum:
- rockchip,rk3228-rga
- rockchip,rk3568-rga
- rockchip,rk3588-rga
- const: rockchip,rk3288-rga
reg:

View File

@ -26,3 +26,4 @@ Video4Linux devices
v4l2-tuner
v4l2-common
v4l2-tveeprom
v4l2-jpeg

View File

@ -0,0 +1,10 @@
.. SPDX-License-Identifier: GPL-2.0
V4L2 JPEG header related functions and data structures
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.. kernel-doc:: include/media/v4l2-jpeg.h
:internal:
.. kernel-doc:: drivers/media/v4l2-core/v4l2-jpeg.c
:export:

View File

@ -35,6 +35,6 @@ For more details see the file COPYING in the source distribution of Linux.
max2175
npcm-video
omap3isp-uapi
st-vgxy61
thp7312
uvcvideo
vgxy61

View File

@ -971,8 +971,8 @@ FWHT Flags
- ``horizontal_scale``
- Horizontal scaling factor.
* - __u8
- ``vertical_scaling factor``
- Vertical scale.
- ``vertical_scale``
- Vertical scaling factor.
* - __u8
- ``version``
- Bitstream version.

View File

@ -1653,6 +1653,20 @@ enum v4l2_mpeg_video_h264_hierarchical_coding_type -
Quantization parameter for a P frame for FWHT. Valid range: from 1
to 31.
``V4L2_CID_MPEG_VIDEO_AVERAGE_QP (integer)``
This read-only control returns the average QP value of the currently
encoded frame. The value applies to the last dequeued capture buffer
(VIDIOC_DQBUF). Its valid range depends on the encoding format and parameters.
For H264, its valid range is from 0 to 51.
For HEVC, its valid range is from 0 to 51 for 8 bit and
from 0 to 63 for 10 bit.
For H263 and MPEG4, its valid range is from 1 to 31.
For VP8, its valid range is from 0 to 127.
For VP9, its valid range is from 0 to 255.
If the codec's MIN_QP and MAX_QP are set, then the QP will meet both requirements.
Codecs need to always use the specified range, rather then a HW custom range.
Applicable to encoders
.. raw:: latex
\normalsize

View File

@ -15,6 +15,7 @@ These formats are used for the :ref:`metadata` interface only.
metafmt-d4xx
metafmt-generic
metafmt-intel-ipu3
metafmt-pisp-be
metafmt-rkisp1
metafmt-uvc
metafmt-vivid

View File

@ -0,0 +1,56 @@
.. SPDX-License-Identifier: GPL-2.0
.. _v4l2-meta-fmt-rpi-be-cfg:
************************
V4L2_META_FMT_RPI_BE_CFG
************************
Raspberry Pi PiSP Back End configuration format
===============================================
The Raspberry Pi PiSP Back End memory-to-memory image signal processor is
configured by userspace by providing a buffer of configuration parameters
to the `pispbe-config` output video device node using the
:c:type:`v4l2_meta_format` interface.
The PiSP Back End processes images in tiles, and its configuration requires
specifying two different sets of parameters by populating the members of
:c:type:`pisp_be_tiles_config` defined in the ``pisp_be_config.h`` header file.
The `Raspberry Pi PiSP technical specification
<https://datasheets.raspberrypi.com/camera/raspberry-pi-image-signal-processor-specification.pdf>`_
provide detailed description of the ISP back end configuration and programming
model.
Global configuration data
-------------------------
The global configuration data describe how the pixels in a particular image are
to be processed and is therefore shared across all the tiles of the image. So
for example, LSC (Lens Shading Correction) or Denoise parameters would be common
across all tiles from the same frame.
Global configuration data are passed to the ISP by populating the member of
:c:type:`pisp_be_config`.
Tile parameters
---------------
As the ISP processes images in tiles, each set of tiles parameters describe how
a single tile in an image is going to be processed. A single set of tile
parameters consist of 160 bytes of data and to process a batch of tiles several
sets of tiles parameters are required.
Tiles parameters are passed to the ISP by populating the member of
``pisp_tile`` and the ``num_tiles`` fields of :c:type:`pisp_be_tiles_config`.
Raspberry Pi PiSP Back End uAPI data types
==========================================
This section describes the data types exposed to userspace by the Raspberry Pi
PiSP Back End. The section is informative only, for a detailed description of
each field refer to the `Raspberry Pi PiSP technical specification
<https://datasheets.raspberrypi.com/camera/raspberry-pi-image-signal-processor-specification.pdf>`_.
.. kernel-doc:: include/uapi/linux/media/raspberrypi/pisp_be_config.h

View File

@ -20,6 +20,7 @@ orders. See also `the Wikipedia article on Bayer filter
:maxdepth: 1
pixfmt-srggb8
pixfmt-srggb8-pisp-comp
pixfmt-srggb10
pixfmt-srggb10p
pixfmt-srggb10alaw8

View File

@ -996,6 +996,60 @@ arranged in little endian order.
\normalsize
16 Bits Per Component
=====================
These formats store an RGB triplet in six bytes, with 16 bits per component
stored in memory in little endian byte order. They are named based on the order
of the RGB components as stored in memory. For instance, RGB48 stores R\
:sub:`7:0` and R\ :sub:`15:8` in bytes 0 and 1 respectively. This differs from
the DRM format nomenclature that instead uses the order of components as seen in
the 48-bits little endian word.
.. raw:: latex
\small
.. flat-table:: RGB Formats With 16 Bits Per Component
:header-rows: 1
* - Identifier
- Code
- Byte 0
- Byte 1
- Byte 2
- Byte 3
- Byte 4
- Byte 5
* .. _V4L2-PIX-FMT-BGR48:
- ``V4L2_PIX_FMT_BGR48``
- 'BGR6'
- B\ :sub:`7-0`
- B\ :sub:`15-8`
- G\ :sub:`7-0`
- G\ :sub:`15-8`
- R\ :sub:`7-0`
- R\ :sub:`15-8`
* .. _V4L2-PIX-FMT-RGB48:
- ``V4L2_PIX_FMT_RGB48``
- 'RGB6'
- R\ :sub:`7-0`
- R\ :sub:`15-8`
- G\ :sub:`7-0`
- G\ :sub:`15-8`
- B\ :sub:`7-0`
- B\ :sub:`15-8`
.. raw:: latex
\normalsize
Deprecated RGB Formats
======================

View File

@ -0,0 +1,74 @@
.. SPDX-License-Identifier: GFDL-1.1-no-invariants-or-later
.. _v4l2-pix-fmt-pisp-comp1-rggb:
.. _v4l2-pix-fmt-pisp-comp1-grbg:
.. _v4l2-pix-fmt-pisp-comp1-gbrg:
.. _v4l2-pix-fmt-pisp-comp1-bggr:
.. _v4l2-pix-fmt-pisp-comp1-mono:
.. _v4l2-pix-fmt-pisp-comp2-rggb:
.. _v4l2-pix-fmt-pisp-comp2-grbg:
.. _v4l2-pix-fmt-pisp-comp2-gbrg:
.. _v4l2-pix-fmt-pisp-comp2-bggr:
.. _v4l2-pix-fmt-pisp-comp2-mono:
**************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************
V4L2_PIX_FMT_PISP_COMP1_RGGB ('PC1R'), V4L2_PIX_FMT_PISP_COMP1_GRBG ('PC1G'), V4L2_PIX_FMT_PISP_COMP1_GBRG ('PC1g'), V4L2_PIX_FMT_PISP_COMP1_BGGR ('PC1B), V4L2_PIX_FMT_PISP_COMP1_MONO ('PC1M'), V4L2_PIX_FMT_PISP_COMP2_RGGB ('PC2R'), V4L2_PIX_FMT_PISP_COMP2_GRBG ('PC2G'), V4L2_PIX_FMT_PISP_COMP2_GBRG ('PC2g'), V4L2_PIX_FMT_PISP_COMP2_BGGR ('PC2B), V4L2_PIX_FMT_PISP_COMP2_MONO ('PC2M')
**************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************
================================================
Raspberry Pi PiSP compressed 8-bit Bayer formats
================================================
Description
===========
The Raspberry Pi ISP (PiSP) uses a family of three fixed-rate compressed Bayer
formats. A black-level offset may be subtracted to improve compression
efficiency; the nominal black level and amount of offset must be signalled out
of band. Each scanline is padded to a multiple of 8 pixels wide, and each block
of 8 horizontally-contiguous pixels is coded using 8 bytes.
Mode 1 uses a quantization and delta-based coding scheme which preserves up to
12 significant bits. Mode 2 is a simple sqrt-like companding scheme with 6 PWL
chords, preserving up to 12 significant bits. Mode 3 combines both companding
(with 4 chords) and the delta scheme, preserving up to 14 significant bits.
The remainder of this description applies to Modes 1 and 3.
Each block of 8 pixels is separated into even and odd phases of 4 pixels,
coded independently by 32-bit words at successive locations in memory.
The two LS bits of each 32-bit word give its "quantization mode".
In quantization mode 0, the lowest 321 quantization levels are multiples of
FSD/4096 and the remaining levels are successive multiples of FSD/2048.
Quantization modes 1 and 2 use linear quantization with step sizes of
FSD/1024 and FSD/512 respectively. Each of the four pixels is quantized
independently, with rounding to the nearest level.
In quantization mode 2 where the middle two samples have quantized values
(q1,q2) both in the range [384..511], they are coded using 9 bits for q1
followed by 7 bits for (q2 & 127). Otherwise, for quantization modes
0, 1 and 2: a 9-bit field encodes MIN(q1,q2) which must be in the range
[0..511] and a 7-bit field encodes (q2-q1+64) which must be in [0..127].
Each of the outer samples (q0,q3) is encoded using a 7-bit field based
on its inner neighbour q1 or q2. In quantization mode 2 where the inner
sample has a quantized value in the range [448..511], the field value is
(q0-384). Otherwise for quantization modes 0, 1 and 2: The outer sample
is encoded as (q0-MAX(0,q1-64)). q3 is likewise coded based on q2.
Each of these values must be in the range [0..127]. All these fields
of 2, 9, 7, 7, 7 bits respectively are packed in little-endian order
to give a 32-bit word with LE byte order.
Quantization mode 3 has a "7.5-bit" escape, used when none of the above
encodings will fit. Each pixel value is quantized to the nearest of 176
levels, where the lowest 95 levels are multiples of FSD/256 and the
remaining levels are multiples of FSD/128 (level 175 represents values
very close to FSD and may require saturating arithmetic to decode).
Each pair of quantized pixels (q0,q1) or (q2,q3) is jointly coded
by a 15-bit field: 2816*(q0>>4) + 16*q1 + (q0&15).
Three fields of 2, 15, 15 bits are packed in LE order {15,15,2}.
An implementation of a software decoder of compressed formats is available
in `Raspberry Pi camera applications code base
<https://github.com/raspberrypi/rpicam-apps/blob/main/image/dng.cpp>`_.

View File

@ -209,3 +209,7 @@ are often referred to as greyscale formats.
For Y012 and Y12 formats, Y012 places its data in the 12 high bits, with
padding zeros in the 4 low bits, in contrast to the Y12 format, which has
its padding located in the most significant bits of the 16 bit word.
The 'P' variations of the Y10, Y12 and Y14 formats are packed according to
the RAW10, RAW12 and RAW14 packing scheme as defined by the MIPI CSI-2
specification.

View File

@ -9190,6 +9190,20 @@ S: Maintained
F: Documentation/devicetree/bindings/media/i2c/galaxycore,gc0308.yaml
F: drivers/media/i2c/gc0308.c
GALAXYCORE GC05a2 CAMERA SENSOR DRIVER
M: Zhi Mao <zhi.mao@mediatek.com>
L: linux-media@vger.kernel.org
S: Maintained
F: Documentation/devicetree/bindings/media/i2c/galaxycore,gc05a2.yaml
F: drivers/media/i2c/gc05a2.c
GALAXYCORE GC08A3 CAMERA SENSOR DRIVER
M: Zhi Mao <zhi.mao@mediatek.com>
L: linux-media@vger.kernel.org
S: Maintained
F: Documentation/devicetree/bindings/media/i2c/galaxycore,gc08a3.yaml
F: drivers/media/i2c/gc08a3.c
GALAXYCORE GC2145 SENSOR DRIVER
M: Alain Volmat <alain.volmat@foss.st.com>
L: linux-media@vger.kernel.org
@ -10872,6 +10886,13 @@ S: Maintained
F: Documentation/devicetree/bindings/auxdisplay/img,ascii-lcd.yaml
F: drivers/auxdisplay/img-ascii-lcd.c
IMGTEC JPEG ENCODER DRIVER
M: Devarsh Thakkar <devarsht@ti.com>
L: linux-media@vger.kernel.org
S: Supported
F: Documentation/devicetree/bindings/media/img,e5010-jpeg-enc.yaml
F: drivers/media/platform/imagination/e5010*
IMGTEC IR DECODER DRIVER
S: Orphan
F: drivers/media/rc/img-ir/
@ -13632,6 +13653,20 @@ S: Maintained
F: Documentation/devicetree/bindings/media/i2c/maxim,max96712.yaml
F: drivers/staging/media/max96712/max96712.c
MAX96714 GMSL2 DESERIALIZER DRIVER
M: Julien Massot <julien.massot@collabora.com>
L: linux-media@vger.kernel.org
S: Maintained
F: Documentation/devicetree/bindings/media/i2c/maxim,max96714.yaml
F: drivers/media/i2c/max96714.c
MAX96717 GMSL2 SERIALIZER DRIVER
M: Julien Massot <julien.massot@collabora.com>
L: linux-media@vger.kernel.org
S: Maintained
F: Documentation/devicetree/bindings/media/i2c/maxim,max96717.yaml
F: drivers/media/i2c/max96717.c
MAX9860 MONO AUDIO VOICE CODEC DRIVER
M: Peter Rosin <peda@axentia.se>
L: alsa-devel@alsa-project.org (moderated for non-subscribers)
@ -18948,6 +18983,15 @@ L: linux-edac@vger.kernel.org
S: Maintained
F: drivers/ras/amd/fmpm.c
RASPBERRY PI PISP BACK END
M: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
L: Raspberry Pi Kernel Maintenance <kernel-list@raspberrypi.com>
L: linux-media@vger.kernel.org
S: Maintained
F: Documentation/devicetree/bindings/media/raspberrypi,pispbe.yaml
F: drivers/media/platform/raspberrypi/pisp_be/
F: include/uapi/linux/media/raspberrypi/
RC-CORE / LIRC FRAMEWORK
M: Sean Young <sean@mess.org>
L: linux-media@vger.kernel.org
@ -20898,7 +20942,6 @@ F: include/uapi/rdma/rdma_user_rxe.h
SOFTLOGIC 6x10 MPEG CODEC
M: Bluecherry Maintainers <maintainers@bluecherrydvr.com>
M: Anton Sviridenko <anton@corp.bluecherry.net>
M: Andrey Utkin <andrey_utkin@fastmail.com>
M: Ismael Luceno <ismael@iodev.co.uk>
L: linux-media@vger.kernel.org
@ -20994,7 +21037,7 @@ M: Sakari Ailus <sakari.ailus@linux.intel.com>
L: linux-media@vger.kernel.org
S: Maintained
T: git git://linuxtv.org/media_tree.git
F: Documentation/devicetree/bindings/media/i2c/imx258.yaml
F: Documentation/devicetree/bindings/media/i2c/sony,imx258.yaml
F: drivers/media/i2c/imx258.c
SONY IMX274 SENSOR DRIVER
@ -21005,6 +21048,15 @@ T: git git://linuxtv.org/media_tree.git
F: Documentation/devicetree/bindings/media/i2c/sony,imx274.yaml
F: drivers/media/i2c/imx274.c
SONY IMX283 SENSOR DRIVER
M: Kieran Bingham <kieran.bingham@ideasonboard.com>
M: Umang Jain <umang.jain@ideasonboard.com>
L: linux-media@vger.kernel.org
S: Maintained
T: git git://linuxtv.org/media_tree.git
F: Documentation/devicetree/bindings/media/i2c/sony,imx283.yaml
F: drivers/media/i2c/imx283.c
SONY IMX290 SENSOR DRIVER
M: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
L: linux-media@vger.kernel.org
@ -21381,8 +21433,8 @@ L: linux-media@vger.kernel.org
S: Maintained
T: git git://linuxtv.org/media_tree.git
F: Documentation/devicetree/bindings/media/i2c/st,st-vgxy61.yaml
F: Documentation/userspace-api/media/drivers/st-vgxy61.rst
F: drivers/media/i2c/st-vgxy61.c
F: Documentation/userspace-api/media/drivers/vgxy61.rst
F: drivers/media/i2c/vgxy61.c
ST VL53L0X ToF RANGER(I2C) IIO DRIVER
M: Song Qiang <songqiang1304521@gmail.com>
@ -23108,7 +23160,6 @@ F: tools/testing/selftests/turbostat/
TW5864 VIDEO4LINUX DRIVER
M: Bluecherry Maintainers <maintainers@bluecherrydvr.com>
M: Anton Sviridenko <anton@corp.bluecherry.net>
M: Andrey Utkin <andrey.utkin@corp.bluecherry.net>
M: Andrey Utkin <andrey_utkin@fastmail.com>
L: linux-media@vger.kernel.org
@ -23725,7 +23776,7 @@ F: drivers/media/i2c/mt*
F: drivers/media/i2c/og*
F: drivers/media/i2c/ov*
F: drivers/media/i2c/s5*
F: drivers/media/i2c/st-vgxy61.c
F: drivers/media/i2c/vgxy61.c
VF610 NAND DRIVER
M: Stefan Agner <stefan@agner.ch>

View File

@ -839,7 +839,7 @@ static int smscore_configure_board(struct smscore_device_t *coredev)
mtu_msg.x_msg_header.msg_flags = 0;
mtu_msg.x_msg_header.msg_type = MSG_SMS_SET_MAX_TX_MSG_LEN_REQ;
mtu_msg.x_msg_header.msg_length = sizeof(mtu_msg);
mtu_msg.msg_data[0] = board->mtu;
mtu_msg.msg_data = board->mtu;
coredev->sendrequest_handler(coredev->context, &mtu_msg,
sizeof(mtu_msg));
@ -852,7 +852,7 @@ static int smscore_configure_board(struct smscore_device_t *coredev)
SMS_INIT_MSG(&crys_msg.x_msg_header,
MSG_SMS_NEW_CRYSTAL_REQ,
sizeof(crys_msg));
crys_msg.msg_data[0] = board->crystal;
crys_msg.msg_data = board->crystal;
coredev->sendrequest_handler(coredev->context, &crys_msg,
sizeof(crys_msg));
@ -1306,7 +1306,7 @@ static int smscore_init_device(struct smscore_device_t *coredev, int mode)
msg = (struct sms_msg_data *)SMS_ALIGN_ADDRESS(buffer);
SMS_INIT_MSG(&msg->x_msg_header, MSG_SMS_INIT_DEVICE_REQ,
sizeof(struct sms_msg_data));
msg->msg_data[0] = mode;
msg->msg_data = mode;
rc = smscore_sendrequest_and_wait(coredev, msg,
msg->x_msg_header. msg_length,
@ -1394,7 +1394,7 @@ int smscore_set_device_mode(struct smscore_device_t *coredev, int mode)
SMS_INIT_MSG(&msg->x_msg_header, MSG_SMS_INIT_DEVICE_REQ,
sizeof(struct sms_msg_data));
msg->msg_data[0] = mode;
msg->msg_data = mode;
rc = smscore_sendrequest_and_wait(
coredev, msg, msg->x_msg_header.msg_length,
@ -1554,7 +1554,7 @@ void smscore_onresponse(struct smscore_device_t *coredev,
struct sms_msg_data *validity = (struct sms_msg_data *) phdr;
pr_debug("MSG_SMS_DATA_VALIDITY_RES, checksum = 0x%x\n",
validity->msg_data[0]);
validity->msg_data);
complete(&coredev->data_validity_done);
break;
}

View File

@ -616,7 +616,7 @@ struct sms_msg_hdr {
struct sms_msg_data {
struct sms_msg_hdr x_msg_header;
u32 msg_data[1];
u32 msg_data;
};
struct sms_msg_data2 {
@ -666,7 +666,7 @@ struct sms_firmware {
u32 check_sum;
u32 length;
u32 start_address;
u8 payload[1];
u8 payload[];
};
/* statistics information returned as response for
@ -1042,20 +1042,6 @@ struct sms_srvm_signal_status {
u32 request_id;
};
struct sms_i2c_req {
u32 device_address; /* I2c device address */
u32 write_count; /* number of bytes to write */
u32 read_count; /* number of bytes to read */
u8 Data[1];
};
struct sms_i2c_res {
u32 status; /* non-zero value in case of failure */
u32 read_count; /* number of bytes read */
u8 Data[1];
};
struct smscore_config_gpio {
#define SMS_GPIO_DIRECTION_INPUT 0
#define SMS_GPIO_DIRECTION_OUTPUT 1

View File

@ -689,7 +689,7 @@ static int smsdvb_start_feed(struct dvb_demux_feed *feed)
pid_msg.x_msg_header.msg_flags = 0;
pid_msg.x_msg_header.msg_type = MSG_SMS_ADD_PID_FILTER_REQ;
pid_msg.x_msg_header.msg_length = sizeof(pid_msg);
pid_msg.msg_data[0] = feed->pid;
pid_msg.msg_data = feed->pid;
return smsclient_sendrequest(client->smsclient,
&pid_msg, sizeof(pid_msg));
@ -711,7 +711,7 @@ static int smsdvb_stop_feed(struct dvb_demux_feed *feed)
pid_msg.x_msg_header.msg_flags = 0;
pid_msg.x_msg_header.msg_type = MSG_SMS_REMOVE_PID_FILTER_REQ;
pid_msg.x_msg_header.msg_length = sizeof(pid_msg);
pid_msg.msg_data[0] = feed->pid;
pid_msg.msg_data = feed->pid;
return smsclient_sendrequest(client->smsclient,
&pid_msg, sizeof(pid_msg));

View File

@ -20,11 +20,12 @@ void smsendian_handle_tx_message(void *buffer)
struct sms_msg_data *msg = buffer;
int i;
int msg_words;
u32 *msg_data = &msg->msg_data;
switch (msg->x_msg_header.msg_type) {
case MSG_SMS_DATA_DOWNLOAD_REQ:
{
msg->msg_data[0] = le32_to_cpu((__force __le32)(msg->msg_data[0]));
msg->msg_data = le32_to_cpu((__force __le32)(msg->msg_data));
break;
}
@ -33,7 +34,7 @@ void smsendian_handle_tx_message(void *buffer)
sizeof(struct sms_msg_hdr))/4;
for (i = 0; i < msg_words; i++)
msg->msg_data[i] = le32_to_cpu((__force __le32)msg->msg_data[i]);
msg_data[i] = le32_to_cpu((__force __le32)msg_data[i]);
break;
}
@ -66,11 +67,12 @@ void smsendian_handle_rx_message(void *buffer)
default:
{
u32 *msg_data = &msg->msg_data;
msg_words = (msg->x_msg_header.msg_length -
sizeof(struct sms_msg_hdr))/4;
for (i = 0; i < msg_words; i++)
msg->msg_data[i] = le32_to_cpu((__force __le32)msg->msg_data[i]);
msg_data[i] = le32_to_cpu((__force __le32)msg_data[i]);
break;
}

View File

@ -180,4 +180,5 @@ const struct uvc_format_desc *uvc_format_by_guid(const u8 guid[16])
}
EXPORT_SYMBOL_GPL(uvc_format_by_guid);
MODULE_DESCRIPTION("USB Video Class common code");
MODULE_LICENSE("GPL");

View File

@ -199,7 +199,6 @@ module_param(debug, int, 0644);
})
static void __vb2_queue_cancel(struct vb2_queue *q);
static void __enqueue_in_driver(struct vb2_buffer *vb);
static const char *vb2_state_name(enum vb2_buffer_state s)
{

View File

@ -19,6 +19,7 @@
/* ------------------------------------------------------------------ */
MODULE_AUTHOR("Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]");
MODULE_DESCRIPTION("Videobuf2 helper library for simple DVB cards");
MODULE_LICENSE("GPL");
/* ------------------------------------------------------------------ */

View File

@ -25,6 +25,7 @@
#include "au8522_priv.h"
MODULE_AUTHOR("Devin Heitmueller");
MODULE_DESCRIPTION("Auvitek AU8522 QAM/8VSB demodulator driver and video decoder");
MODULE_LICENSE("GPL");
static int au8522_analog_debug;

View File

@ -32,11 +32,6 @@ MODULE_PARM_DESC(buggy_sfn_workaround, "Enable work-around for buggy SFNs (defau
__func__, ##arg); \
} while (0)
struct i2c_device {
struct i2c_adapter *i2c_adap;
u8 i2c_addr;
};
struct dib7000p_state {
struct dvb_frontend demod;
struct dib7000p_config cfg;

View File

@ -976,13 +976,6 @@ static struct drx_aud_data drxj_default_aud_data_g = {
/*-----------------------------------------------------------------------------
STRUCTURES
----------------------------------------------------------------------------*/
struct drxjeq_stat {
u16 eq_mse;
u8 eq_mode;
u8 eq_ctrl;
u8 eq_stat;
};
/* HI command */
struct drxj_hi_cmd {
u16 cmd;

View File

@ -1854,5 +1854,6 @@ error:
return NULL;
}
EXPORT_SYMBOL_GPL(mb86a16_attach);
MODULE_DESCRIPTION("Fujitsu MB86A16 DVB-S/DSS DC Receiver driver");
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Manu Abraham");

View File

@ -168,7 +168,7 @@ struct MBIN_FILE_HEADER_T {
struct MBIN_FILE_T {
struct MBIN_FILE_HEADER_T header;
u8 data[1];
u8 data[];
};
struct MBIN_SEGMENT_HEADER_T {
@ -179,7 +179,7 @@ struct MBIN_SEGMENT_HEADER_T {
struct MBIN_SEGMENT_T {
struct MBIN_SEGMENT_HEADER_T header;
u8 data[1];
u8 data[];
};
enum MXL_CMD_TYPE_E { MXL_CMD_WRITE = 0, MXL_CMD_READ };

View File

@ -748,6 +748,22 @@ static int stv090x_write_reg(struct stv090x_state *state, unsigned int reg, u8 d
return stv090x_write_regs(state, reg, &tmp, 1);
}
static inline void stv090x_tuner_i2c_lock(struct stv090x_state *state)
{
if (state->config->tuner_i2c_lock)
state->config->tuner_i2c_lock(&state->frontend, 1);
else
mutex_lock(&state->internal->tuner_lock);
}
static inline void stv090x_tuner_i2c_unlock(struct stv090x_state *state)
{
if (state->config->tuner_i2c_lock)
state->config->tuner_i2c_lock(&state->frontend, 0);
else
mutex_unlock(&state->internal->tuner_lock);
}
static int stv090x_i2c_gate_ctrl(struct stv090x_state *state, int enable)
{
u32 reg;
@ -761,12 +777,8 @@ static int stv090x_i2c_gate_ctrl(struct stv090x_state *state, int enable)
* In case of any error, the lock is unlocked and exit within the
* relevant operations themselves.
*/
if (enable) {
if (state->config->tuner_i2c_lock)
state->config->tuner_i2c_lock(&state->frontend, 1);
else
mutex_lock(&state->internal->tuner_lock);
}
if (enable)
stv090x_tuner_i2c_lock(state);
reg = STV090x_READ_DEMOD(state, I2CRPT);
if (enable) {
@ -782,20 +794,13 @@ static int stv090x_i2c_gate_ctrl(struct stv090x_state *state, int enable)
goto err;
}
if (!enable) {
if (state->config->tuner_i2c_lock)
state->config->tuner_i2c_lock(&state->frontend, 0);
else
mutex_unlock(&state->internal->tuner_lock);
}
if (!enable)
stv090x_tuner_i2c_unlock(state);
return 0;
err:
dprintk(FE_ERROR, 1, "I/O error");
if (state->config->tuner_i2c_lock)
state->config->tuner_i2c_lock(&state->frontend, 0);
else
mutex_unlock(&state->internal->tuner_lock);
stv090x_tuner_i2c_unlock(state);
return -1;
}

View File

@ -119,11 +119,6 @@ struct stv {
u8 vth[6];
};
struct sinit_table {
u16 address;
u8 data;
};
struct slookup {
s16 value;
u32 reg_value;

View File

@ -70,6 +70,26 @@ config VIDEO_GC0308
To compile this driver as a module, choose M here: the
module will be called gc0308.
config VIDEO_GC05A2
tristate "GalaxyCore gc05a2 sensor support"
select V4L2_CCI_I2C
help
This is a Video4Linux2 sensor driver for the GalaxyCore gc05a2
camera.
To compile this driver as a module, choose M here: the
module will be called gc05a2.
config VIDEO_GC08A3
tristate "GalaxyCore gc08a3 sensor support"
select V4L2_CCI_I2C
help
This is a Video4Linux2 sensor driver for the GalaxyCore gc08a3
camera.
To compile this driver as a module, choose M here: the
module will be called gc08a3.
config VIDEO_GC2145
select V4L2_CCI_I2C
tristate "GalaxyCore GC2145 sensor support"
@ -139,6 +159,7 @@ config VIDEO_IMX219
config VIDEO_IMX258
tristate "Sony IMX258 sensor support"
select V4L2_CCI_I2C
help
This is a Video4Linux2 sensor driver for the Sony
IMX258 camera.
@ -153,6 +174,16 @@ config VIDEO_IMX274
This is a V4L2 sensor driver for the Sony IMX274
CMOS image sensor.
config VIDEO_IMX283
tristate "Sony IMX283 sensor support"
select V4L2_CCI_I2C
help
This is a V4L2 sensor driver for the Sony IMX283
CMOS image sensor.
To compile this driver as a module, choose M here: the
module will be called imx283.
config VIDEO_IMX290
tristate "Sony IMX290 sensor support"
select REGMAP_I2C
@ -659,7 +690,7 @@ config VIDEO_S5K6A3
This is a V4L2 sensor driver for Samsung S5K6A3 raw
camera sensor.
config VIDEO_ST_VGXY61
config VIDEO_VGXY61
tristate "ST VGXY61 sensor support"
select V4L2_CCI_I2C
depends on OF && GPIOLIB
@ -679,6 +710,7 @@ config VIDEO_THP7312
tristate "THine THP7312 support"
depends on I2C
select FW_LOADER
select FW_UPLOAD
select MEDIA_CONTROLLER
select V4L2_CCI_I2C
select V4L2_FWNODE
@ -1575,6 +1607,40 @@ config VIDEO_DS90UB960
Device driver for the Texas Instruments DS90UB960
FPD-Link III Deserializer and DS90UB9702 FPD-Link IV Deserializer.
config VIDEO_MAX96714
tristate "Maxim MAX96714 GMSL2 deserializer"
depends on OF && I2C && VIDEO_DEV
select I2C_MUX
select MEDIA_CONTROLLER
select GPIOLIB
select V4L2_CCI_I2C
select V4L2_FWNODE
select VIDEO_V4L2_SUBDEV_API
help
Device driver for the Maxim MAX96714 GMSL2 Deserializer.
MAX96714 deserializers convert a GMSL2 input to MIPI CSI-2
output.
To compile this driver as a module, choose M here: the
module will be called max96714.
config VIDEO_MAX96717
tristate "Maxim MAX96717 GMSL2 Serializer support"
depends on OF && I2C && VIDEO_DEV && COMMON_CLK
select I2C_MUX
select MEDIA_CONTROLLER
select GPIOLIB
select V4L2_CCI_I2C
select V4L2_FWNODE
select VIDEO_V4L2_SUBDEV_API
help
Device driver for the Maxim MAX96717 GMSL2 Serializer.
MAX96717 serializers convert video on a MIPI CSI-2
input to a GMSL2 output.
To compile this driver as a module, choose M here: the
module will be called max96717.
endmenu
endif # VIDEO_DEV

View File

@ -38,6 +38,8 @@ obj-$(CONFIG_VIDEO_DW9768) += dw9768.o
obj-$(CONFIG_VIDEO_DW9807_VCM) += dw9807-vcm.o
obj-$(CONFIG_VIDEO_ET8EK8) += et8ek8/
obj-$(CONFIG_VIDEO_GC0308) += gc0308.o
obj-$(CONFIG_VIDEO_GC05A2) += gc05a2.o
obj-$(CONFIG_VIDEO_GC08A3) += gc08a3.o
obj-$(CONFIG_VIDEO_GC2145) += gc2145.o
obj-$(CONFIG_VIDEO_HI556) += hi556.o
obj-$(CONFIG_VIDEO_HI846) += hi846.o
@ -48,6 +50,7 @@ obj-$(CONFIG_VIDEO_IMX214) += imx214.o
obj-$(CONFIG_VIDEO_IMX219) += imx219.o
obj-$(CONFIG_VIDEO_IMX258) += imx258.o
obj-$(CONFIG_VIDEO_IMX274) += imx274.o
obj-$(CONFIG_VIDEO_IMX283) += imx283.o
obj-$(CONFIG_VIDEO_IMX290) += imx290.o
obj-$(CONFIG_VIDEO_IMX296) += imx296.o
obj-$(CONFIG_VIDEO_IMX319) += imx319.o
@ -64,6 +67,8 @@ obj-$(CONFIG_VIDEO_LM3646) += lm3646.o
obj-$(CONFIG_VIDEO_M52790) += m52790.o
obj-$(CONFIG_VIDEO_MAX9271_LIB) += max9271.o
obj-$(CONFIG_VIDEO_MAX9286) += max9286.o
obj-$(CONFIG_VIDEO_MAX96714) += max96714.o
obj-$(CONFIG_VIDEO_MAX96717) += max96717.o
obj-$(CONFIG_VIDEO_ML86V7667) += ml86v7667.o
obj-$(CONFIG_VIDEO_MSP3400) += msp3400.o
obj-$(CONFIG_VIDEO_MT9M001) += mt9m001.o
@ -124,7 +129,6 @@ obj-$(CONFIG_VIDEO_SAA717X) += saa717x.o
obj-$(CONFIG_VIDEO_SAA7185) += saa7185.o
obj-$(CONFIG_VIDEO_SONY_BTF_MPX) += sony-btf-mpx.o
obj-$(CONFIG_VIDEO_ST_MIPID02) += st-mipid02.o
obj-$(CONFIG_VIDEO_ST_VGXY61) += st-vgxy61.o
obj-$(CONFIG_VIDEO_TC358743) += tc358743.o
obj-$(CONFIG_VIDEO_TC358746) += tc358746.o
obj-$(CONFIG_VIDEO_TDA1997X) += tda1997x.o
@ -148,6 +152,7 @@ obj-$(CONFIG_VIDEO_TW9910) += tw9910.o
obj-$(CONFIG_VIDEO_UDA1342) += uda1342.o
obj-$(CONFIG_VIDEO_UPD64031A) += upd64031a.o
obj-$(CONFIG_VIDEO_UPD64083) += upd64083.o
obj-$(CONFIG_VIDEO_VGXY61) += vgxy61.o
obj-$(CONFIG_VIDEO_VP27SMPX) += vp27smpx.o
obj-$(CONFIG_VIDEO_VPX3220) += vpx3220.o
obj-$(CONFIG_VIDEO_WM8739) += wm8739.o

View File

@ -114,7 +114,7 @@ static void adv748x_afe_fill_format(struct adv748x_afe *afe,
{
memset(fmt, 0, sizeof(*fmt));
fmt->code = MEDIA_BUS_FMT_UYVY8_2X8;
fmt->code = MEDIA_BUS_FMT_UYVY8_1X16;
fmt->colorspace = V4L2_COLORSPACE_SMPTE170M;
fmt->field = V4L2_FIELD_ALTERNATE;
@ -337,7 +337,7 @@ static int adv748x_afe_enum_mbus_code(struct v4l2_subdev *sd,
if (code->index != 0)
return -EINVAL;
code->code = MEDIA_BUS_FMT_UYVY8_2X8;
code->code = MEDIA_BUS_FMT_UYVY8_1X16;
return 0;
}

View File

@ -6,7 +6,6 @@
*/
#include <linux/module.h>
#include <linux/mutex.h>
#include <media/v4l2-ctrls.h>
#include <media/v4l2-device.h>
@ -14,6 +13,15 @@
#include "adv748x.h"
static const unsigned int adv748x_csi2_txa_fmts[] = {
MEDIA_BUS_FMT_UYVY8_1X16,
MEDIA_BUS_FMT_RGB888_1X24,
};
static const unsigned int adv748x_csi2_txb_fmts[] = {
MEDIA_BUS_FMT_UYVY8_1X16,
};
int adv748x_csi2_set_virtual_channel(struct adv748x_csi2 *tx, unsigned int vc)
{
return tx_write(tx, ADV748X_CSI_VC_REF, vc << ADV748X_CSI_VC_REF_SHIFT);
@ -59,7 +67,33 @@ static int adv748x_csi2_register_link(struct adv748x_csi2 *tx,
/* -----------------------------------------------------------------------------
* v4l2_subdev_internal_ops
*
*/
static int adv748x_csi2_init_state(struct v4l2_subdev *sd,
struct v4l2_subdev_state *state)
{
static const struct v4l2_mbus_framefmt adv748x_csi2_default_fmt = {
.width = 1280,
.height = 720,
.code = MEDIA_BUS_FMT_UYVY8_1X16,
.colorspace = V4L2_COLORSPACE_SRGB,
.field = V4L2_FIELD_NONE,
.ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT,
.quantization = V4L2_QUANTIZATION_DEFAULT,
.xfer_func = V4L2_XFER_FUNC_DEFAULT,
};
struct v4l2_mbus_framefmt *fmt;
fmt = v4l2_subdev_state_get_format(state, ADV748X_CSI2_SINK);
*fmt = adv748x_csi2_default_fmt;
fmt = v4l2_subdev_state_get_format(state, ADV748X_CSI2_SOURCE);
*fmt = adv748x_csi2_default_fmt;
return 0;
}
/*
* We use the internal registered operation to be able to ensure that our
* incremental subdevices (not connected in the forward path) can be registered
* against the resulting video path and media device.
@ -109,6 +143,7 @@ static int adv748x_csi2_registered(struct v4l2_subdev *sd)
}
static const struct v4l2_subdev_internal_ops adv748x_csi2_internal_ops = {
.init_state = adv748x_csi2_init_state,
.registered = adv748x_csi2_registered,
};
@ -139,78 +174,82 @@ static const struct v4l2_subdev_video_ops adv748x_csi2_video_ops = {
* But we must support setting the pad formats for format propagation.
*/
static struct v4l2_mbus_framefmt *
adv748x_csi2_get_pad_format(struct v4l2_subdev *sd,
struct v4l2_subdev_state *sd_state,
unsigned int pad, u32 which)
static int adv748x_csi2_enum_mbus_code(struct v4l2_subdev *sd,
struct v4l2_subdev_state *sd_state,
struct v4l2_subdev_mbus_code_enum *code)
{
struct adv748x_csi2 *tx = adv748x_sd_to_csi2(sd);
const unsigned int *codes = is_txa(tx) ?
adv748x_csi2_txa_fmts :
adv748x_csi2_txb_fmts;
size_t num_fmts = is_txa(tx) ? ARRAY_SIZE(adv748x_csi2_txa_fmts)
: ARRAY_SIZE(adv748x_csi2_txb_fmts);
if (which == V4L2_SUBDEV_FORMAT_TRY)
return v4l2_subdev_state_get_format(sd_state, pad);
/*
* The format available on the source pad is the one applied on the sink
* pad.
*/
if (code->pad == ADV748X_CSI2_SOURCE) {
struct v4l2_mbus_framefmt *fmt;
return &tx->format;
}
if (code->index)
return -EINVAL;
static int adv748x_csi2_get_format(struct v4l2_subdev *sd,
struct v4l2_subdev_state *sd_state,
struct v4l2_subdev_format *sdformat)
{
struct adv748x_csi2 *tx = adv748x_sd_to_csi2(sd);
struct adv748x_state *state = tx->state;
struct v4l2_mbus_framefmt *mbusformat;
fmt = v4l2_subdev_state_get_format(sd_state, ADV748X_CSI2_SINK);
code->code = fmt->code;
mbusformat = adv748x_csi2_get_pad_format(sd, sd_state, sdformat->pad,
sdformat->which);
if (!mbusformat)
return 0;
}
if (code->index >= num_fmts)
return -EINVAL;
mutex_lock(&state->mutex);
sdformat->format = *mbusformat;
mutex_unlock(&state->mutex);
code->code = codes[code->index];
return 0;
}
static bool adv748x_csi2_is_fmt_supported(struct adv748x_csi2 *tx, u32 code)
{
const unsigned int *codes = is_txa(tx) ?
adv748x_csi2_txa_fmts :
adv748x_csi2_txb_fmts;
size_t num_fmts = is_txa(tx) ? ARRAY_SIZE(adv748x_csi2_txa_fmts)
: ARRAY_SIZE(adv748x_csi2_txb_fmts);
for (unsigned int i = 0; i < num_fmts; i++) {
if (codes[i] == code)
return true;
}
return false;
}
static int adv748x_csi2_set_format(struct v4l2_subdev *sd,
struct v4l2_subdev_state *sd_state,
struct v4l2_subdev_format *sdformat)
{
struct adv748x_csi2 *tx = adv748x_sd_to_csi2(sd);
struct adv748x_state *state = tx->state;
struct v4l2_mbus_framefmt *mbusformat;
int ret = 0;
mbusformat = adv748x_csi2_get_pad_format(sd, sd_state, sdformat->pad,
sdformat->which);
if (!mbusformat)
return -EINVAL;
if (sdformat->pad == ADV748X_CSI2_SOURCE)
return v4l2_subdev_get_fmt(sd, sd_state, sdformat);
mutex_lock(&state->mutex);
if (sdformat->pad == ADV748X_CSI2_SOURCE) {
const struct v4l2_mbus_framefmt *sink_fmt;
sink_fmt = adv748x_csi2_get_pad_format(sd, sd_state,
ADV748X_CSI2_SINK,
sdformat->which);
if (!sink_fmt) {
ret = -EINVAL;
goto unlock;
}
sdformat->format = *sink_fmt;
}
/*
* Make sure the format is supported, if not default it to
* UYVY8 as it's supported by both TXes.
*/
if (!adv748x_csi2_is_fmt_supported(tx, sdformat->format.code))
sdformat->format.code = MEDIA_BUS_FMT_UYVY8_1X16;
mbusformat = v4l2_subdev_state_get_format(sd_state, sdformat->pad);
*mbusformat = sdformat->format;
unlock:
mutex_unlock(&state->mutex);
/* Propagate format to the source pad. */
mbusformat = v4l2_subdev_state_get_format(sd_state, ADV748X_CSI2_SOURCE);
*mbusformat = sdformat->format;
return ret;
return 0;
}
static int adv748x_csi2_get_mbus_config(struct v4l2_subdev *sd, unsigned int pad,
@ -228,7 +267,8 @@ static int adv748x_csi2_get_mbus_config(struct v4l2_subdev *sd, unsigned int pad
}
static const struct v4l2_subdev_pad_ops adv748x_csi2_pad_ops = {
.get_fmt = adv748x_csi2_get_format,
.enum_mbus_code = adv748x_csi2_enum_mbus_code,
.get_fmt = v4l2_subdev_get_fmt,
.set_fmt = adv748x_csi2_set_format,
.get_mbus_config = adv748x_csi2_get_mbus_config,
};
@ -320,6 +360,11 @@ int adv748x_csi2_init(struct adv748x_state *state, struct adv748x_csi2 *tx)
if (ret)
goto err_cleanup_subdev;
tx->sd.state_lock = &state->mutex;
ret = v4l2_subdev_init_finalize(&tx->sd);
if (ret)
goto err_free_ctrl;
ret = v4l2_async_register_subdev(&tx->sd);
if (ret)
goto err_free_ctrl;

View File

@ -75,7 +75,6 @@ enum adv748x_csi2_pads {
struct adv748x_csi2 {
struct adv748x_state *state;
struct v4l2_mbus_framefmt format;
unsigned int page;
unsigned int port;
unsigned int num_lanes;

View File

@ -62,11 +62,6 @@ MODULE_LICENSE("GPL v2");
**********************************************************************
*/
struct i2c_reg_value {
unsigned char reg;
unsigned char value;
};
struct adv7511_state_edid {
/* total number of blocks */
u32 blocks;

View File

@ -403,21 +403,22 @@ static int alvium_get_bcrm_vers(struct alvium_dev *alvium)
static int alvium_get_fw_version(struct alvium_dev *alvium)
{
struct device *dev = &alvium->i2c_client->dev;
u64 spec, maj, min, pat;
int ret = 0;
u64 val;
int ret;
ret = alvium_read(alvium, REG_BCRM_DEVICE_FW_SPEC_VERSION_R,
&spec, &ret);
ret = alvium_read(alvium, REG_BCRM_DEVICE_FW_MAJOR_VERSION_R,
&maj, &ret);
ret = alvium_read(alvium, REG_BCRM_DEVICE_FW_MINOR_VERSION_R,
&min, &ret);
ret = alvium_read(alvium, REG_BCRM_DEVICE_FW_PATCH_VERSION_R,
&pat, &ret);
ret = alvium_read(alvium, REG_BCRM_DEVICE_FW, &val, NULL);
if (ret)
return ret;
dev_info(dev, "fw version: %llu.%llu.%llu.%llu\n", spec, maj, min, pat);
dev_info(dev, "fw version: %02u.%02u.%04u.%08x\n",
(u8)((val & BCRM_DEVICE_FW_SPEC_MASK) >>
BCRM_DEVICE_FW_SPEC_SHIFT),
(u8)((val & BCRM_DEVICE_FW_MAJOR_MASK) >>
BCRM_DEVICE_FW_MAJOR_SHIFT),
(u16)((val & BCRM_DEVICE_FW_MINOR_MASK) >>
BCRM_DEVICE_FW_MINOR_SHIFT),
(u32)((val & BCRM_DEVICE_FW_PATCH_MASK) >>
BCRM_DEVICE_FW_PATCH_SHIFT));
return 0;
}
@ -1188,6 +1189,20 @@ static int alvium_set_frame_rate(struct alvium_dev *alvium, u64 fr)
struct device *dev = &alvium->i2c_client->dev;
int ret;
ret = alvium_write_hshake(alvium, REG_BCRM_ACQUISITION_FRAME_RATE_EN_RW,
1);
if (ret) {
dev_err(dev, "Fail to set acquisition frame rate enable reg\n");
return ret;
}
ret = alvium_write_hshake(alvium, REG_BCRM_FRAME_START_TRIGGER_MODE_RW,
0);
if (ret) {
dev_err(dev, "Fail to set frame start trigger mode reg\n");
return ret;
}
ret = alvium_write_hshake(alvium, REG_BCRM_ACQUISITION_FRAME_RATE_RW,
fr);
if (ret) {
@ -1707,6 +1722,27 @@ alvium_code_to_pixfmt(struct alvium_dev *alvium, u32 code)
return &alvium->alvium_csi2_fmt[0];
}
static int alvium_enum_frame_size(struct v4l2_subdev *sd,
struct v4l2_subdev_state *state,
struct v4l2_subdev_frame_size_enum *fse)
{
struct alvium_dev *alvium = sd_to_alvium(sd);
const struct alvium_pixfmt *alvium_csi2_fmt;
if (fse->index)
return -EINVAL;
alvium_csi2_fmt = alvium_code_to_pixfmt(alvium, fse->code);
if (fse->code != alvium_csi2_fmt->code)
return -EINVAL;
fse->min_width = alvium->img_min_width;
fse->max_width = alvium->img_max_width;
fse->min_height = alvium->img_min_height;
fse->max_height = alvium->img_max_height;
return 0;
}
static int alvium_set_mode(struct alvium_dev *alvium,
struct v4l2_subdev_state *state)
{
@ -1962,7 +1998,7 @@ static int alvium_g_volatile_ctrl(struct v4l2_ctrl *ctrl)
int val;
switch (ctrl->id) {
case V4L2_CID_GAIN:
case V4L2_CID_ANALOGUE_GAIN:
val = alvium_get_gain(alvium);
if (val < 0)
return val;
@ -1994,7 +2030,7 @@ static int alvium_s_ctrl(struct v4l2_ctrl *ctrl)
return 0;
switch (ctrl->id) {
case V4L2_CID_GAIN:
case V4L2_CID_ANALOGUE_GAIN:
ret = alvium_set_ctrl_gain(alvium, ctrl->val);
break;
case V4L2_CID_AUTOGAIN:
@ -2123,7 +2159,7 @@ static int alvium_ctrl_init(struct alvium_dev *alvium)
if (alvium->avail_ft.gain) {
ctrls->gain = v4l2_ctrl_new_std(hdl, ops,
V4L2_CID_GAIN,
V4L2_CID_ANALOGUE_GAIN,
alvium->min_gain,
alvium->max_gain,
alvium->inc_gain,
@ -2214,6 +2250,7 @@ static const struct v4l2_subdev_video_ops alvium_video_ops = {
static const struct v4l2_subdev_pad_ops alvium_pad_ops = {
.enum_mbus_code = alvium_enum_mbus_code,
.enum_frame_size = alvium_enum_frame_size,
.get_fmt = v4l2_subdev_get_fmt,
.set_fmt = alvium_set_fmt,
.get_selection = alvium_get_selection,

View File

@ -31,10 +31,7 @@
#define REG_BCRM_REG_ADDR_R CCI_REG16(0x0014)
#define REG_BCRM_FEATURE_INQUIRY_R REG_BCRM_V4L2_64BIT(0x0008)
#define REG_BCRM_DEVICE_FW_SPEC_VERSION_R REG_BCRM_V4L2_8BIT(0x0010)
#define REG_BCRM_DEVICE_FW_MAJOR_VERSION_R REG_BCRM_V4L2_8BIT(0x0011)
#define REG_BCRM_DEVICE_FW_MINOR_VERSION_R REG_BCRM_V4L2_16BIT(0x0012)
#define REG_BCRM_DEVICE_FW_PATCH_VERSION_R REG_BCRM_V4L2_32BIT(0x0014)
#define REG_BCRM_DEVICE_FW REG_BCRM_V4L2_64BIT(0x0010)
#define REG_BCRM_WRITE_HANDSHAKE_RW REG_BCRM_V4L2_8BIT(0x0018)
/* Streaming Control Registers */
@ -66,7 +63,7 @@
#define REG_BCRM_ACQUISITION_FRAME_RATE_MIN_R REG_BCRM_V4L2_64BIT(0x0098)
#define REG_BCRM_ACQUISITION_FRAME_RATE_MAX_R REG_BCRM_V4L2_64BIT(0x00a0)
#define REG_BCRM_ACQUISITION_FRAME_RATE_INC_R REG_BCRM_V4L2_64BIT(0x00a8)
#define REG_BCRM_ACQUISITION_FRAME_RATE_ENABLE_RW REG_BCRM_V4L2_8BIT(0x00b0)
#define REG_BCRM_ACQUISITION_FRAME_RATE_EN_RW REG_BCRM_V4L2_8BIT(0x00b0)
#define REG_BCRM_FRAME_START_TRIGGER_MODE_RW REG_BCRM_V4L2_8BIT(0x00b4)
#define REG_BCRM_FRAME_START_TRIGGER_SOURCE_RW REG_BCRM_V4L2_8BIT(0x00b8)
@ -205,6 +202,15 @@
#define ALVIUM_LP2HS_DELAY_MS 100
#define BCRM_DEVICE_FW_MAJOR_MASK GENMASK_ULL(15, 8)
#define BCRM_DEVICE_FW_MAJOR_SHIFT 8
#define BCRM_DEVICE_FW_MINOR_MASK GENMASK_ULL(31, 16)
#define BCRM_DEVICE_FW_MINOR_SHIFT 16
#define BCRM_DEVICE_FW_PATCH_MASK GENMASK_ULL(63, 32)
#define BCRM_DEVICE_FW_PATCH_SHIFT 32
#define BCRM_DEVICE_FW_SPEC_MASK GENMASK_ULL(7, 0)
#define BCRM_DEVICE_FW_SPEC_SHIFT 0
enum alvium_bcrm_mode {
ALVIUM_BCM_MODE,
ALVIUM_GENCP_MODE,

View File

@ -115,11 +115,6 @@ static inline struct dw9768 *sd_to_dw9768(struct v4l2_subdev *subdev)
return container_of(subdev, struct dw9768, sd);
}
struct regval_list {
u8 reg_num;
u8 value;
};
struct dw9768_aac_mode_ot_multi {
u32 aac_mode_enum;
u32 ot_multi_base100;

1359
drivers/media/i2c/gc05a2.c Normal file

File diff suppressed because it is too large Load Diff

1339
drivers/media/i2c/gc08a3.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -68,8 +68,7 @@
#define GC2145_DPHY_CLK_DELAY BIT(4)
#define GC2145_DPHY_LANE0_DELAY BIT(5)
#define GC2145_DPHY_LANE1_DELAY BIT(6)
#define GC2145_REG_FIFO_FULL_LVL_LOW CCI_REG8(0x04)
#define GC2145_REG_FIFO_FULL_LVL_HIGH CCI_REG8(0x05)
#define GC2145_REG_FIFO_FULL_LVL CCI_REG16_LE(0x04)
#define GC2145_REG_FIFO_MODE CCI_REG8(0x06)
#define GC2145_FIFO_MODE_READ_GATE BIT(3)
#define GC2145_FIFO_MODE_MIPI_CLK_MODULE BIT(7)
@ -79,8 +78,7 @@
#define GC2145_CSI2_MODE_MIPI_EN BIT(4)
#define GC2145_CSI2_MODE_EN BIT(7)
#define GC2145_REG_MIPI_DT CCI_REG8(0x11)
#define GC2145_REG_LWC_LOW CCI_REG8(0x12)
#define GC2145_REG_LWC_HIGH CCI_REG8(0x13)
#define GC2145_REG_LWC CCI_REG16_LE(0x12)
#define GC2145_REG_DPHY_MODE CCI_REG8(0x15)
#define GC2145_DPHY_MODE_TRIGGER_PROG BIT(4)
#define GC2145_REG_FIFO_GATE_MODE CCI_REG8(0x17)
@ -542,45 +540,82 @@ static const struct gc2145_mode supported_modes[] = {
/**
* struct gc2145_format - GC2145 pixel format description
* @code: media bus (MBUS) associated code
* @colorspace: V4L2 colorspace
* @datatype: MIPI CSI2 data type
* @output_fmt: GC2145 output format
* @switch_bit: GC2145 first/second switch
* @row_col_switch: GC2145 switch row and/or column
*/
struct gc2145_format {
unsigned int code;
unsigned int colorspace;
unsigned char datatype;
unsigned char output_fmt;
bool switch_bit;
unsigned char row_col_switch;
};
/* All supported formats */
static const struct gc2145_format supported_formats[] = {
{
.code = MEDIA_BUS_FMT_UYVY8_1X16,
.colorspace = V4L2_COLORSPACE_SRGB,
.datatype = MIPI_CSI2_DT_YUV422_8B,
.output_fmt = 0x00,
},
{
.code = MEDIA_BUS_FMT_VYUY8_1X16,
.colorspace = V4L2_COLORSPACE_SRGB,
.datatype = MIPI_CSI2_DT_YUV422_8B,
.output_fmt = 0x01,
},
{
.code = MEDIA_BUS_FMT_YUYV8_1X16,
.colorspace = V4L2_COLORSPACE_SRGB,
.datatype = MIPI_CSI2_DT_YUV422_8B,
.output_fmt = 0x02,
},
{
.code = MEDIA_BUS_FMT_YVYU8_1X16,
.colorspace = V4L2_COLORSPACE_SRGB,
.datatype = MIPI_CSI2_DT_YUV422_8B,
.output_fmt = 0x03,
},
{
.code = MEDIA_BUS_FMT_RGB565_1X16,
.colorspace = V4L2_COLORSPACE_SRGB,
.datatype = MIPI_CSI2_DT_RGB565,
.output_fmt = 0x06,
.switch_bit = true,
},
{
.code = MEDIA_BUS_FMT_SGRBG8_1X8,
.colorspace = V4L2_COLORSPACE_RAW,
.datatype = MIPI_CSI2_DT_RAW8,
.output_fmt = 0x17,
.row_col_switch = GC2145_SYNC_MODE_COL_SWITCH,
},
{
.code = MEDIA_BUS_FMT_SRGGB8_1X8,
.colorspace = V4L2_COLORSPACE_RAW,
.datatype = MIPI_CSI2_DT_RAW8,
.output_fmt = 0x17,
.row_col_switch = GC2145_SYNC_MODE_COL_SWITCH | GC2145_SYNC_MODE_ROW_SWITCH,
},
{
.code = MEDIA_BUS_FMT_SBGGR8_1X8,
.colorspace = V4L2_COLORSPACE_RAW,
.datatype = MIPI_CSI2_DT_RAW8,
.output_fmt = 0x17,
.row_col_switch = 0,
},
{
.code = MEDIA_BUS_FMT_SGBRG8_1X8,
.colorspace = V4L2_COLORSPACE_RAW,
.datatype = MIPI_CSI2_DT_RAW8,
.output_fmt = 0x17,
.row_col_switch = GC2145_SYNC_MODE_ROW_SWITCH,
},
};
struct gc2145_ctrls {
@ -641,7 +676,8 @@ gc2145_get_format_code(struct gc2145 *gc2145, u32 code)
static void gc2145_update_pad_format(struct gc2145 *gc2145,
const struct gc2145_mode *mode,
struct v4l2_mbus_framefmt *fmt, u32 code)
struct v4l2_mbus_framefmt *fmt, u32 code,
u32 colorspace)
{
fmt->code = code;
fmt->width = mode->width;
@ -663,7 +699,8 @@ static int gc2145_init_state(struct v4l2_subdev *sd,
/* Initialize pad format */
format = v4l2_subdev_state_get_format(state, 0);
gc2145_update_pad_format(gc2145, &supported_modes[0], format,
MEDIA_BUS_FMT_RGB565_1X16);
MEDIA_BUS_FMT_RGB565_1X16,
V4L2_COLORSPACE_SRGB);
/* Initialize crop rectangle. */
crop = v4l2_subdev_state_get_crop(state, 0);
@ -754,7 +791,13 @@ static int gc2145_set_pad_format(struct v4l2_subdev *sd,
width, height,
fmt->format.width, fmt->format.height);
gc2145_update_pad_format(gc2145, mode, &fmt->format, gc2145_fmt->code);
/* In RAW mode, VGA is not possible so use 720p instead */
if (gc2145_fmt->colorspace == V4L2_COLORSPACE_RAW &&
mode == &supported_modes[GC2145_MODE_640X480])
mode = &supported_modes[GC2145_MODE_1280X720];
gc2145_update_pad_format(gc2145, mode, &fmt->format, gc2145_fmt->code,
gc2145_fmt->colorspace);
framefmt = v4l2_subdev_state_get_format(sd_state, fmt->pad);
if (fmt->which == V4L2_SUBDEV_FORMAT_ACTIVE) {
gc2145->mode = mode;
@ -811,9 +854,12 @@ static int gc2145_config_mipi_mode(struct gc2145 *gc2145,
* For RAW8, LWC = image width
* For RAW10, LWC = image width * 1.25
*/
lwc = gc2145->mode->width * 2;
cci_write(gc2145->regmap, GC2145_REG_LWC_HIGH, lwc >> 8, &ret);
cci_write(gc2145->regmap, GC2145_REG_LWC_LOW, lwc & 0xff, &ret);
if (gc2145_format->colorspace != V4L2_COLORSPACE_RAW)
lwc = gc2145->mode->width * 2;
else
lwc = gc2145->mode->width;
cci_write(gc2145->regmap, GC2145_REG_LWC, lwc, &ret);
/*
* Adjust the MIPI FIFO Full Level
@ -821,21 +867,25 @@ static int gc2145_config_mipi_mode(struct gc2145 *gc2145,
* 1280x720 / 1600x1200 (aka no scaler) non RAW: 0x0001
* 1600x1200 RAW: 0x0190
*/
if (gc2145->mode->width == 1280 || gc2145->mode->width == 1600)
fifo_full_lvl = 0x0001;
else
if (gc2145_format->colorspace != V4L2_COLORSPACE_RAW) {
if (gc2145->mode->width == 1280 || gc2145->mode->width == 1600)
fifo_full_lvl = 0x0001;
else
fifo_full_lvl = 0x0190;
} else {
fifo_full_lvl = 0x0190;
}
cci_write(gc2145->regmap, GC2145_REG_FIFO_FULL_LVL_HIGH,
fifo_full_lvl >> 8, &ret);
cci_write(gc2145->regmap, GC2145_REG_FIFO_FULL_LVL_LOW,
fifo_full_lvl & 0xff, &ret);
cci_write(gc2145->regmap, GC2145_REG_FIFO_FULL_LVL,
fifo_full_lvl, &ret);
/*
* Set the FIFO gate mode / MIPI wdiv set:
* 0xf1 in case of RAW mode and 0xf0 otherwise
*/
cci_write(gc2145->regmap, GC2145_REG_FIFO_GATE_MODE, 0xf0, &ret);
cci_write(gc2145->regmap, GC2145_REG_FIFO_GATE_MODE,
gc2145_format->colorspace == V4L2_COLORSPACE_RAW ?
0xf1 : 0xf0, &ret);
/* Set the MIPI data type */
cci_write(gc2145->regmap, GC2145_REG_MIPI_DT,
@ -883,6 +933,10 @@ static int gc2145_start_streaming(struct gc2145 *gc2145,
GC2145_BYPASS_MODE_SWITCH,
gc2145_format->switch_bit ? GC2145_BYPASS_MODE_SWITCH
: 0, &ret);
cci_update_bits(gc2145->regmap, GC2145_REG_SYNC_MODE,
GC2145_SYNC_MODE_COL_SWITCH |
GC2145_SYNC_MODE_ROW_SWITCH,
gc2145_format->row_col_switch, &ret);
if (ret) {
dev_err(&client->dev, "%s failed to write regs\n", __func__);
goto err_rpm_put;

View File

@ -1851,7 +1851,7 @@ static int hi846_get_selection(struct v4l2_subdev *sd,
mutex_lock(&hi846->mutex);
switch (sel->which) {
case V4L2_SUBDEV_FORMAT_TRY:
v4l2_subdev_state_get_crop(sd_state, sel->pad);
sel->r = *v4l2_subdev_state_get_crop(sd_state, sel->pad);
break;
case V4L2_SUBDEV_FORMAT_ACTIVE:
sel->r = hi846->cur_mode->crop;

View File

@ -162,8 +162,8 @@ static const struct cci_reg_sequence imx219_common_regs[] = {
{ IMX219_REG_MODE_SELECT, 0x00 }, /* Mode Select */
/* To Access Addresses 3000-5fff, send the following commands */
{ CCI_REG8(0x30eb), 0x0c },
{ CCI_REG8(0x30eb), 0x05 },
{ CCI_REG8(0x30eb), 0x0c },
{ CCI_REG8(0x300a), 0xff },
{ CCI_REG8(0x300b), 0xff },
{ CCI_REG8(0x30eb), 0x05 },

File diff suppressed because it is too large Load Diff

1612
drivers/media/i2c/imx283.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -542,14 +542,13 @@ static int imx412_update_controls(struct imx412 *imx412,
*/
static int imx412_update_exp_gain(struct imx412 *imx412, u32 exposure, u32 gain)
{
u32 lpfr, shutter;
u32 lpfr;
int ret;
lpfr = imx412->vblank + imx412->cur_mode->height;
shutter = lpfr - exposure;
dev_dbg(imx412->dev, "Set exp %u, analog gain %u, shutter %u, lpfr %u",
exposure, gain, shutter, lpfr);
dev_dbg(imx412->dev, "Set exp %u, analog gain %u, lpfr %u",
exposure, gain, lpfr);
ret = imx412_write_reg(imx412, IMX412_REG_HOLD, 1, 1);
if (ret)
@ -559,7 +558,7 @@ static int imx412_update_exp_gain(struct imx412 *imx412, u32 exposure, u32 gain)
if (ret)
goto error_release_group_hold;
ret = imx412_write_reg(imx412, IMX412_REG_EXPOSURE_CIT, 2, shutter);
ret = imx412_write_reg(imx412, IMX412_REG_EXPOSURE_CIT, 2, exposure);
if (ret)
goto error_release_group_hold;

View File

@ -175,14 +175,6 @@ MODULE_LICENSE("GPL");
* mga_dev : represents one ks0127 chip.
****************************************************************************/
struct adjust {
int contrast;
int bright;
int hue;
int ugain;
int vgain;
};
struct ks0127 {
struct v4l2_subdev sd;
v4l2_std_id norm;

View File

@ -19,7 +19,6 @@
#include <linux/i2c.h>
#include <linux/i2c-mux.h>
#include <linux/module.h>
#include <linux/mutex.h>
#include <linux/of_graph.h>
#include <linux/regulator/consumer.h>
#include <linux/slab.h>
@ -198,12 +197,6 @@ struct max9286_priv {
struct v4l2_ctrl *pixelrate_ctrl;
unsigned int pixelrate;
struct v4l2_mbus_framefmt fmt[MAX9286_N_SINKS];
struct v4l2_fract interval;
/* Protects controls and fmt structures */
struct mutex mutex;
unsigned int nsources;
unsigned int source_mask;
unsigned int route_mask;
@ -576,11 +569,14 @@ static void max9286_set_video_format(struct max9286_priv *priv,
MAX9286_INVVS | MAX9286_HVSRC_D14);
}
static void max9286_set_fsync_period(struct max9286_priv *priv)
static void max9286_set_fsync_period(struct max9286_priv *priv,
struct v4l2_subdev_state *state)
{
const struct v4l2_fract *interval;
u32 fsync;
if (!priv->interval.numerator || !priv->interval.denominator) {
interval = v4l2_subdev_state_get_interval(state, MAX9286_SRC_PAD);
if (!interval->numerator || !interval->denominator) {
/*
* Special case, a null interval enables automatic FRAMESYNC
* mode. FRAMESYNC is taken from the slowest link.
@ -596,8 +592,8 @@ static void max9286_set_fsync_period(struct max9286_priv *priv)
* The FRAMESYNC generator is configured with a period expressed as a
* number of PCLK periods.
*/
fsync = div_u64((u64)priv->pixelrate * priv->interval.numerator,
priv->interval.denominator);
fsync = div_u64((u64)priv->pixelrate * interval->numerator,
interval->denominator);
dev_dbg(&priv->client->dev, "fsync period %u (pclk %u)\n", fsync,
priv->pixelrate);
@ -788,22 +784,25 @@ static void max9286_v4l2_notifier_unregister(struct max9286_priv *priv)
static int max9286_s_stream(struct v4l2_subdev *sd, int enable)
{
struct max9286_priv *priv = sd_to_max9286(sd);
struct v4l2_subdev_state *state;
struct max9286_source *source;
unsigned int i;
bool sync = false;
int ret;
int ret = 0;
state = v4l2_subdev_lock_and_get_active_state(sd);
if (enable) {
const struct v4l2_mbus_framefmt *format;
/*
* Get the format from the first used sink pad, as all sink
* formats must be identical.
* Get the format from the source pad, as all formats must be
* identical.
*/
format = &priv->fmt[__ffs(priv->bound_sources)];
format = v4l2_subdev_state_get_format(state, MAX9286_SRC_PAD);
max9286_set_video_format(priv, format);
max9286_set_fsync_period(priv);
max9286_set_fsync_period(priv, state);
/*
* The frame sync between cameras is transmitted across the
@ -816,12 +815,12 @@ static int max9286_s_stream(struct v4l2_subdev *sd, int enable)
for_each_source(priv, source) {
ret = v4l2_subdev_call(source->sd, video, s_stream, 1);
if (ret)
return ret;
goto unlock;
}
ret = max9286_check_video_links(priv);
if (ret)
return ret;
goto unlock;
/*
* Wait until frame synchronization is locked.
@ -842,7 +841,8 @@ static int max9286_s_stream(struct v4l2_subdev *sd, int enable)
if (!sync) {
dev_err(&priv->client->dev,
"Failed to get frame synchronization\n");
return -EXDEV; /* Invalid cross-device link */
ret = -EXDEV; /* Invalid cross-device link */
goto unlock;
}
/*
@ -865,26 +865,21 @@ static int max9286_s_stream(struct v4l2_subdev *sd, int enable)
max9286_i2c_mux_close(priv);
}
return 0;
unlock:
v4l2_subdev_unlock_state(state);
return ret;
}
static int max9286_get_frame_interval(struct v4l2_subdev *sd,
struct v4l2_subdev_state *sd_state,
struct v4l2_subdev_frame_interval *interval)
{
struct max9286_priv *priv = sd_to_max9286(sd);
/*
* FIXME: Implement support for V4L2_SUBDEV_FORMAT_TRY, using the V4L2
* subdev active state API.
*/
if (interval->which != V4L2_SUBDEV_FORMAT_ACTIVE)
return -EINVAL;
if (interval->pad != MAX9286_SRC_PAD)
return -EINVAL;
interval->interval = priv->interval;
interval->interval = *v4l2_subdev_state_get_interval(sd_state,
interval->pad);
return 0;
}
@ -893,19 +888,11 @@ static int max9286_set_frame_interval(struct v4l2_subdev *sd,
struct v4l2_subdev_state *sd_state,
struct v4l2_subdev_frame_interval *interval)
{
struct max9286_priv *priv = sd_to_max9286(sd);
/*
* FIXME: Implement support for V4L2_SUBDEV_FORMAT_TRY, using the V4L2
* subdev active state API.
*/
if (interval->which != V4L2_SUBDEV_FORMAT_ACTIVE)
return -EINVAL;
if (interval->pad != MAX9286_SRC_PAD)
return -EINVAL;
priv->interval = interval->interval;
*v4l2_subdev_state_get_interval(sd_state,
interval->pad) = interval->interval;
return 0;
}
@ -914,39 +901,28 @@ static int max9286_enum_mbus_code(struct v4l2_subdev *sd,
struct v4l2_subdev_state *sd_state,
struct v4l2_subdev_mbus_code_enum *code)
{
if (code->pad || code->index > 0)
if (code->pad || code->index >= ARRAY_SIZE(max9286_formats))
return -EINVAL;
code->code = MEDIA_BUS_FMT_UYVY8_1X16;
code->code = max9286_formats[code->index].code;
return 0;
}
static struct v4l2_mbus_framefmt *
max9286_get_pad_format(struct max9286_priv *priv,
struct v4l2_subdev_state *sd_state,
unsigned int pad, u32 which)
{
switch (which) {
case V4L2_SUBDEV_FORMAT_TRY:
return v4l2_subdev_state_get_format(sd_state, pad);
case V4L2_SUBDEV_FORMAT_ACTIVE:
return &priv->fmt[pad];
default:
return NULL;
}
}
static int max9286_set_fmt(struct v4l2_subdev *sd,
struct v4l2_subdev_state *sd_state,
struct v4l2_subdev_state *state,
struct v4l2_subdev_format *format)
{
struct max9286_priv *priv = sd_to_max9286(sd);
struct v4l2_mbus_framefmt *cfg_fmt;
struct max9286_source *source;
unsigned int i;
/*
* Disable setting format on the source pad: format is propagated
* from the sinks.
*/
if (format->pad == MAX9286_SRC_PAD)
return -EINVAL;
return v4l2_subdev_get_fmt(sd, state, format);
/* Validate the format. */
for (i = 0; i < ARRAY_SIZE(max9286_formats); ++i) {
@ -957,42 +933,17 @@ static int max9286_set_fmt(struct v4l2_subdev *sd,
if (i == ARRAY_SIZE(max9286_formats))
format->format.code = max9286_formats[0].code;
cfg_fmt = max9286_get_pad_format(priv, sd_state, format->pad,
format->which);
if (!cfg_fmt)
return -EINVAL;
mutex_lock(&priv->mutex);
*cfg_fmt = format->format;
mutex_unlock(&priv->mutex);
return 0;
}
static int max9286_get_fmt(struct v4l2_subdev *sd,
struct v4l2_subdev_state *sd_state,
struct v4l2_subdev_format *format)
{
struct max9286_priv *priv = sd_to_max9286(sd);
struct v4l2_mbus_framefmt *cfg_fmt;
unsigned int pad = format->pad;
/*
* Multiplexed Stream Support: Support link validation by returning the
* format of the first bound link. All links must have the same format,
* as we do not support mixing and matching of cameras connected to the
* max9286.
* Apply the same format on all the other pad as all links must have the
* same format.
*/
if (pad == MAX9286_SRC_PAD)
pad = __ffs(priv->bound_sources);
for_each_source(priv, source) {
unsigned int index = to_index(priv, source);
cfg_fmt = max9286_get_pad_format(priv, sd_state, pad, format->which);
if (!cfg_fmt)
return -EINVAL;
*v4l2_subdev_state_get_format(state, index) = format->format;
}
mutex_lock(&priv->mutex);
format->format = *cfg_fmt;
mutex_unlock(&priv->mutex);
*v4l2_subdev_state_get_format(state, MAX9286_SRC_PAD) = format->format;
return 0;
}
@ -1003,7 +954,7 @@ static const struct v4l2_subdev_video_ops max9286_video_ops = {
static const struct v4l2_subdev_pad_ops max9286_pad_ops = {
.enum_mbus_code = max9286_enum_mbus_code,
.get_fmt = max9286_get_fmt,
.get_fmt = v4l2_subdev_get_fmt,
.set_fmt = max9286_set_fmt,
.get_frame_interval = max9286_get_frame_interval,
.set_frame_interval = max9286_set_frame_interval,
@ -1025,26 +976,29 @@ static const struct v4l2_mbus_framefmt max9286_default_format = {
.xfer_func = V4L2_XFER_FUNC_DEFAULT,
};
static void max9286_init_format(struct v4l2_mbus_framefmt *fmt)
static int max9286_init_state(struct v4l2_subdev *sd,
struct v4l2_subdev_state *state)
{
*fmt = max9286_default_format;
}
struct v4l2_fract *interval;
static int max9286_open(struct v4l2_subdev *subdev, struct v4l2_subdev_fh *fh)
{
struct v4l2_mbus_framefmt *format;
unsigned int i;
for (unsigned int i = 0; i < MAX9286_N_PADS; i++)
*v4l2_subdev_state_get_format(state, i) = max9286_default_format;
for (i = 0; i < MAX9286_N_SINKS; i++) {
format = v4l2_subdev_state_get_format(fh->state, i);
max9286_init_format(format);
}
/*
* Special case: a null interval enables automatic FRAMESYNC mode.
*
* FRAMESYNC is taken from the slowest link. See register 0x01
* configuration.
*/
interval = v4l2_subdev_state_get_interval(state, MAX9286_SRC_PAD);
interval->numerator = 0;
interval->denominator = 0;
return 0;
}
static const struct v4l2_subdev_internal_ops max9286_subdev_internal_ops = {
.open = max9286_open,
.init_state = max9286_init_state,
};
static const struct media_entity_operations max9286_media_ops = {
@ -1079,10 +1033,6 @@ static int max9286_v4l2_register(struct max9286_priv *priv)
}
/* Configure V4L2 for the MAX9286 itself */
for (i = 0; i < MAX9286_N_SINKS; i++)
max9286_init_format(&priv->fmt[i]);
v4l2_i2c_subdev_init(&priv->sd, priv->client, &max9286_subdev_ops);
priv->sd.internal_ops = &max9286_subdev_internal_ops;
priv->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
@ -1109,14 +1059,21 @@ static int max9286_v4l2_register(struct max9286_priv *priv)
if (ret)
goto err_async;
priv->sd.state_lock = priv->ctrls.lock;
ret = v4l2_subdev_init_finalize(&priv->sd);
if (ret)
goto err_async;
ret = v4l2_async_register_subdev(&priv->sd);
if (ret < 0) {
dev_err(dev, "Unable to register subdevice\n");
goto err_async;
goto err_subdev;
}
return 0;
err_subdev:
v4l2_subdev_cleanup(&priv->sd);
err_async:
v4l2_ctrl_handler_free(&priv->ctrls);
max9286_v4l2_notifier_unregister(priv);
@ -1126,6 +1083,7 @@ err_async:
static void max9286_v4l2_unregister(struct max9286_priv *priv)
{
v4l2_subdev_cleanup(&priv->sd);
v4l2_ctrl_handler_free(&priv->ctrls);
v4l2_async_unregister_subdev(&priv->sd);
max9286_v4l2_notifier_unregister(priv);
@ -1182,7 +1140,6 @@ static int max9286_setup(struct max9286_priv *priv)
max9286_write(priv, 0x69, (0xf & ~priv->route_mask));
max9286_set_video_format(priv, &max9286_default_format);
max9286_set_fsync_period(priv);
cfg = max9286_read(priv, 0x1c);
if (cfg < 0)
@ -1629,8 +1586,6 @@ static int max9286_probe(struct i2c_client *client)
if (!priv)
return -ENOMEM;
mutex_init(&priv->mutex);
priv->client = client;
/* GPIO values default to high */

1024
drivers/media/i2c/max96714.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,927 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Maxim GMSL2 Serializer Driver
*
* Copyright (C) 2024 Collabora Ltd.
*/
#include <linux/bitfield.h>
#include <linux/clk.h>
#include <linux/clk-provider.h>
#include <linux/delay.h>
#include <linux/fwnode.h>
#include <linux/gpio/driver.h>
#include <linux/i2c-mux.h>
#include <linux/i2c.h>
#include <linux/regmap.h>
#include <media/v4l2-cci.h>
#include <media/v4l2-fwnode.h>
#include <media/v4l2-subdev.h>
#define MAX96717_DEVICE_ID 0xbf
#define MAX96717F_DEVICE_ID 0xc8
#define MAX96717_PORTS 2
#define MAX96717_PAD_SINK 0
#define MAX96717_PAD_SOURCE 1
#define MAX96717_DEFAULT_CLKOUT_RATE 24000000UL
/* DEV */
#define MAX96717_REG3 CCI_REG8(0x3)
#define MAX96717_RCLKSEL GENMASK(1, 0)
#define RCLKSEL_REF_PLL CCI_REG8(0x3)
#define MAX96717_REG6 CCI_REG8(0x6)
#define RCLKEN BIT(5)
#define MAX96717_DEV_ID CCI_REG8(0xd)
#define MAX96717_DEV_REV CCI_REG8(0xe)
#define MAX96717_DEV_REV_MASK GENMASK(3, 0)
/* VID_TX Z */
#define MAX96717_VIDEO_TX2 CCI_REG8(0x112)
#define MAX96717_VIDEO_PCLKDET BIT(7)
/* GPIO */
#define MAX96717_NUM_GPIO 11
#define MAX96717_GPIO_REG_A(gpio) CCI_REG8(0x2be + (gpio) * 3)
#define MAX96717_GPIO_OUT BIT(4)
#define MAX96717_GPIO_IN BIT(3)
#define MAX96717_GPIO_RX_EN BIT(2)
#define MAX96717_GPIO_TX_EN BIT(1)
#define MAX96717_GPIO_OUT_DIS BIT(0)
/* FRONTTOP */
/* MAX96717 only have CSI port 'B' */
#define MAX96717_FRONTOP0 CCI_REG8(0x308)
#define MAX96717_START_PORT_B BIT(5)
/* MIPI_RX */
#define MAX96717_MIPI_RX1 CCI_REG8(0x331)
#define MAX96717_MIPI_LANES_CNT GENMASK(5, 4)
#define MAX96717_MIPI_RX2 CCI_REG8(0x332) /* phy1 Lanes map */
#define MAX96717_PHY2_LANES_MAP GENMASK(7, 4)
#define MAX96717_MIPI_RX3 CCI_REG8(0x333) /* phy2 Lanes map */
#define MAX96717_PHY1_LANES_MAP GENMASK(3, 0)
#define MAX96717_MIPI_RX4 CCI_REG8(0x334) /* phy1 lane polarities */
#define MAX96717_PHY1_LANES_POL GENMASK(6, 4)
#define MAX96717_MIPI_RX5 CCI_REG8(0x335) /* phy2 lane polarities */
#define MAX96717_PHY2_LANES_POL GENMASK(2, 0)
/* MIPI_RX_EXT */
#define MAX96717_MIPI_RX_EXT11 CCI_REG8(0x383)
#define MAX96717_TUN_MODE BIT(7)
/* REF_VTG */
#define REF_VTG0 CCI_REG8(0x3f0)
#define REFGEN_PREDEF_EN BIT(6)
#define REFGEN_PREDEF_FREQ_MASK GENMASK(5, 4)
#define REFGEN_PREDEF_FREQ_ALT BIT(3)
#define REFGEN_RST BIT(1)
#define REFGEN_EN BIT(0)
/* MISC */
#define PIO_SLEW_1 CCI_REG8(0x570)
struct max96717_priv {
struct i2c_client *client;
struct regmap *regmap;
struct i2c_mux_core *mux;
struct v4l2_mbus_config_mipi_csi2 mipi_csi2;
struct v4l2_subdev sd;
struct media_pad pads[MAX96717_PORTS];
struct v4l2_async_notifier notifier;
struct v4l2_subdev *source_sd;
u16 source_sd_pad;
u64 enabled_source_streams;
u8 pll_predef_index;
struct clk_hw clk_hw;
struct gpio_chip gpio_chip;
};
static inline struct max96717_priv *sd_to_max96717(struct v4l2_subdev *sd)
{
return container_of(sd, struct max96717_priv, sd);
}
static inline struct max96717_priv *clk_hw_to_max96717(struct clk_hw *hw)
{
return container_of(hw, struct max96717_priv, clk_hw);
}
static int max96717_i2c_mux_select(struct i2c_mux_core *mux, u32 chan)
{
return 0;
}
static int max96717_i2c_mux_init(struct max96717_priv *priv)
{
priv->mux = i2c_mux_alloc(priv->client->adapter, &priv->client->dev,
1, 0, I2C_MUX_LOCKED | I2C_MUX_GATE,
max96717_i2c_mux_select, NULL);
if (!priv->mux)
return -ENOMEM;
return i2c_mux_add_adapter(priv->mux, 0, 0);
}
static inline int max96717_start_csi(struct max96717_priv *priv, bool start)
{
return cci_update_bits(priv->regmap, MAX96717_FRONTOP0,
MAX96717_START_PORT_B,
start ? MAX96717_START_PORT_B : 0, NULL);
}
static int max96717_gpiochip_get(struct gpio_chip *gpiochip,
unsigned int offset)
{
struct max96717_priv *priv = gpiochip_get_data(gpiochip);
u64 val;
int ret;
ret = cci_read(priv->regmap, MAX96717_GPIO_REG_A(offset),
&val, NULL);
if (ret)
return ret;
if (val & MAX96717_GPIO_OUT_DIS)
return !!(val & MAX96717_GPIO_IN);
else
return !!(val & MAX96717_GPIO_OUT);
}
static void max96717_gpiochip_set(struct gpio_chip *gpiochip,
unsigned int offset, int value)
{
struct max96717_priv *priv = gpiochip_get_data(gpiochip);
cci_update_bits(priv->regmap, MAX96717_GPIO_REG_A(offset),
MAX96717_GPIO_OUT, MAX96717_GPIO_OUT, NULL);
}
static int max96717_gpio_get_direction(struct gpio_chip *gpiochip,
unsigned int offset)
{
struct max96717_priv *priv = gpiochip_get_data(gpiochip);
u64 val;
int ret;
ret = cci_read(priv->regmap, MAX96717_GPIO_REG_A(offset), &val, NULL);
if (ret < 0)
return ret;
return !!(val & MAX96717_GPIO_OUT_DIS);
}
static int max96717_gpio_direction_out(struct gpio_chip *gpiochip,
unsigned int offset, int value)
{
struct max96717_priv *priv = gpiochip_get_data(gpiochip);
return cci_update_bits(priv->regmap, MAX96717_GPIO_REG_A(offset),
MAX96717_GPIO_OUT_DIS | MAX96717_GPIO_OUT,
value ? MAX96717_GPIO_OUT : 0, NULL);
}
static int max96717_gpio_direction_in(struct gpio_chip *gpiochip,
unsigned int offset)
{
struct max96717_priv *priv = gpiochip_get_data(gpiochip);
return cci_update_bits(priv->regmap, MAX96717_GPIO_REG_A(offset),
MAX96717_GPIO_OUT_DIS, MAX96717_GPIO_OUT_DIS,
NULL);
}
static int max96717_gpiochip_probe(struct max96717_priv *priv)
{
struct device *dev = &priv->client->dev;
struct gpio_chip *gc = &priv->gpio_chip;
int i, ret = 0;
gc->label = dev_name(dev);
gc->parent = dev;
gc->owner = THIS_MODULE;
gc->ngpio = MAX96717_NUM_GPIO;
gc->base = -1;
gc->can_sleep = true;
gc->get_direction = max96717_gpio_get_direction;
gc->direction_input = max96717_gpio_direction_in;
gc->direction_output = max96717_gpio_direction_out;
gc->set = max96717_gpiochip_set;
gc->get = max96717_gpiochip_get;
gc->of_gpio_n_cells = 2;
/* Disable GPIO forwarding */
for (i = 0; i < gc->ngpio; i++)
cci_update_bits(priv->regmap, MAX96717_GPIO_REG_A(i),
MAX96717_GPIO_RX_EN | MAX96717_GPIO_TX_EN,
0, &ret);
if (ret)
return ret;
ret = devm_gpiochip_add_data(dev, gc, priv);
if (ret) {
dev_err(dev, "Unable to create gpio_chip\n");
return ret;
}
return 0;
}
static int _max96717_set_routing(struct v4l2_subdev *sd,
struct v4l2_subdev_state *state,
struct v4l2_subdev_krouting *routing)
{
static const struct v4l2_mbus_framefmt format = {
.width = 1280,
.height = 1080,
.code = MEDIA_BUS_FMT_Y8_1X8,
.field = V4L2_FIELD_NONE,
};
int ret;
ret = v4l2_subdev_routing_validate(sd, routing,
V4L2_SUBDEV_ROUTING_ONLY_1_TO_1);
if (ret)
return ret;
ret = v4l2_subdev_set_routing_with_fmt(sd, state, routing, &format);
if (ret)
return ret;
return 0;
}
static int max96717_set_routing(struct v4l2_subdev *sd,
struct v4l2_subdev_state *state,
enum v4l2_subdev_format_whence which,
struct v4l2_subdev_krouting *routing)
{
struct max96717_priv *priv = sd_to_max96717(sd);
if (which == V4L2_SUBDEV_FORMAT_ACTIVE && priv->enabled_source_streams)
return -EBUSY;
return _max96717_set_routing(sd, state, routing);
}
static int max96717_set_fmt(struct v4l2_subdev *sd,
struct v4l2_subdev_state *state,
struct v4l2_subdev_format *format)
{
struct max96717_priv *priv = sd_to_max96717(sd);
struct v4l2_mbus_framefmt *fmt;
u64 stream_source_mask;
if (format->which == V4L2_SUBDEV_FORMAT_ACTIVE &&
priv->enabled_source_streams)
return -EBUSY;
/* No transcoding, source and sink formats must match. */
if (format->pad == MAX96717_PAD_SOURCE)
return v4l2_subdev_get_fmt(sd, state, format);
/* Set sink format */
fmt = v4l2_subdev_state_get_format(state, format->pad, format->stream);
if (!fmt)
return -EINVAL;
*fmt = format->format;
/* Propagate to source format */
fmt = v4l2_subdev_state_get_opposite_stream_format(state, format->pad,
format->stream);
if (!fmt)
return -EINVAL;
*fmt = format->format;
stream_source_mask = BIT(format->stream);
return v4l2_subdev_state_xlate_streams(state, MAX96717_PAD_SOURCE,
MAX96717_PAD_SINK,
&stream_source_mask);
}
static int max96717_init_state(struct v4l2_subdev *sd,
struct v4l2_subdev_state *state)
{
struct v4l2_subdev_route routes[] = {
{
.sink_pad = MAX96717_PAD_SINK,
.sink_stream = 0,
.source_pad = MAX96717_PAD_SOURCE,
.source_stream = 0,
.flags = V4L2_SUBDEV_ROUTE_FL_ACTIVE,
},
};
struct v4l2_subdev_krouting routing = {
.num_routes = ARRAY_SIZE(routes),
.routes = routes,
};
return _max96717_set_routing(sd, state, &routing);
}
static bool max96717_pipe_pclkdet(struct max96717_priv *priv)
{
u64 val = 0;
cci_read(priv->regmap, MAX96717_VIDEO_TX2, &val, NULL);
return val & MAX96717_VIDEO_PCLKDET;
}
static int max96717_log_status(struct v4l2_subdev *sd)
{
struct max96717_priv *priv = sd_to_max96717(sd);
struct device *dev = &priv->client->dev;
dev_info(dev, "Serializer: max96717\n");
dev_info(dev, "Pipe: pclkdet:%d\n", max96717_pipe_pclkdet(priv));
return 0;
}
static int max96717_enable_streams(struct v4l2_subdev *sd,
struct v4l2_subdev_state *state, u32 pad,
u64 streams_mask)
{
struct max96717_priv *priv = sd_to_max96717(sd);
struct device *dev = &priv->client->dev;
u64 sink_streams;
int ret;
sink_streams = v4l2_subdev_state_xlate_streams(state,
MAX96717_PAD_SOURCE,
MAX96717_PAD_SINK,
&streams_mask);
if (!priv->enabled_source_streams)
max96717_start_csi(priv, true);
ret = v4l2_subdev_enable_streams(priv->source_sd, priv->source_sd_pad,
sink_streams);
if (ret) {
dev_err(dev, "Fail to start streams:%llu on remote subdev\n",
sink_streams);
goto stop_csi;
}
priv->enabled_source_streams |= streams_mask;
return 0;
stop_csi:
if (!priv->enabled_source_streams)
max96717_start_csi(priv, false);
return ret;
}
static int max96717_disable_streams(struct v4l2_subdev *sd,
struct v4l2_subdev_state *state, u32 pad,
u64 streams_mask)
{
struct max96717_priv *priv = sd_to_max96717(sd);
u64 sink_streams;
/*
* Stop the CSI receiver first then the source,
* otherwise the device may become unresponsive
* while holding the I2C bus low.
*/
priv->enabled_source_streams &= ~streams_mask;
if (!priv->enabled_source_streams)
max96717_start_csi(priv, false);
sink_streams = v4l2_subdev_state_xlate_streams(state,
MAX96717_PAD_SOURCE,
MAX96717_PAD_SINK,
&streams_mask);
return v4l2_subdev_disable_streams(priv->source_sd, priv->source_sd_pad,
sink_streams);
}
static const struct v4l2_subdev_pad_ops max96717_pad_ops = {
.enable_streams = max96717_enable_streams,
.disable_streams = max96717_disable_streams,
.set_routing = max96717_set_routing,
.get_fmt = v4l2_subdev_get_fmt,
.set_fmt = max96717_set_fmt,
};
static const struct v4l2_subdev_core_ops max96717_subdev_core_ops = {
.log_status = max96717_log_status,
};
static const struct v4l2_subdev_internal_ops max96717_internal_ops = {
.init_state = max96717_init_state,
};
static const struct v4l2_subdev_ops max96717_subdev_ops = {
.core = &max96717_subdev_core_ops,
.pad = &max96717_pad_ops,
};
static const struct media_entity_operations max96717_entity_ops = {
.link_validate = v4l2_subdev_link_validate,
};
static int max96717_notify_bound(struct v4l2_async_notifier *notifier,
struct v4l2_subdev *source_subdev,
struct v4l2_async_connection *asd)
{
struct max96717_priv *priv = sd_to_max96717(notifier->sd);
struct device *dev = &priv->client->dev;
int ret;
ret = media_entity_get_fwnode_pad(&source_subdev->entity,
source_subdev->fwnode,
MEDIA_PAD_FL_SOURCE);
if (ret < 0) {
dev_err(dev, "Failed to find pad for %s\n",
source_subdev->name);
return ret;
}
priv->source_sd = source_subdev;
priv->source_sd_pad = ret;
ret = media_create_pad_link(&source_subdev->entity, priv->source_sd_pad,
&priv->sd.entity, 0,
MEDIA_LNK_FL_ENABLED |
MEDIA_LNK_FL_IMMUTABLE);
if (ret) {
dev_err(dev, "Unable to link %s:%u -> %s:0\n",
source_subdev->name, priv->source_sd_pad,
priv->sd.name);
return ret;
}
return 0;
}
static const struct v4l2_async_notifier_operations max96717_notify_ops = {
.bound = max96717_notify_bound,
};
static int max96717_v4l2_notifier_register(struct max96717_priv *priv)
{
struct device *dev = &priv->client->dev;
struct v4l2_async_connection *asd;
struct fwnode_handle *ep_fwnode;
int ret;
ep_fwnode = fwnode_graph_get_endpoint_by_id(dev_fwnode(dev),
MAX96717_PAD_SINK, 0, 0);
if (!ep_fwnode) {
dev_err(dev, "No graph endpoint\n");
return -ENODEV;
}
v4l2_async_subdev_nf_init(&priv->notifier, &priv->sd);
asd = v4l2_async_nf_add_fwnode_remote(&priv->notifier, ep_fwnode,
struct v4l2_async_connection);
fwnode_handle_put(ep_fwnode);
if (IS_ERR(asd)) {
dev_err(dev, "Failed to add subdev: %ld", PTR_ERR(asd));
v4l2_async_nf_cleanup(&priv->notifier);
return PTR_ERR(asd);
}
priv->notifier.ops = &max96717_notify_ops;
ret = v4l2_async_nf_register(&priv->notifier);
if (ret) {
dev_err(dev, "Failed to register subdev_notifier");
v4l2_async_nf_cleanup(&priv->notifier);
return ret;
}
return 0;
}
static int max96717_subdev_init(struct max96717_priv *priv)
{
struct device *dev = &priv->client->dev;
int ret;
v4l2_i2c_subdev_init(&priv->sd, priv->client, &max96717_subdev_ops);
priv->sd.internal_ops = &max96717_internal_ops;
priv->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE | V4L2_SUBDEV_FL_STREAMS;
priv->sd.entity.function = MEDIA_ENT_F_VID_IF_BRIDGE;
priv->sd.entity.ops = &max96717_entity_ops;
priv->pads[MAX96717_PAD_SINK].flags = MEDIA_PAD_FL_SINK;
priv->pads[MAX96717_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE;
ret = media_entity_pads_init(&priv->sd.entity, 2, priv->pads);
if (ret)
return dev_err_probe(dev, ret, "Failed to init pads\n");
ret = v4l2_subdev_init_finalize(&priv->sd);
if (ret) {
dev_err_probe(dev, ret,
"v4l2 subdev init finalized failed\n");
goto err_entity_cleanup;
}
ret = max96717_v4l2_notifier_register(priv);
if (ret) {
dev_err_probe(dev, ret,
"v4l2 subdev notifier register failed\n");
goto err_free_state;
}
ret = v4l2_async_register_subdev(&priv->sd);
if (ret) {
dev_err_probe(dev, ret, "v4l2_async_register_subdev error\n");
goto err_unreg_notif;
}
return 0;
err_unreg_notif:
v4l2_async_nf_unregister(&priv->notifier);
v4l2_async_nf_cleanup(&priv->notifier);
err_free_state:
v4l2_subdev_cleanup(&priv->sd);
err_entity_cleanup:
media_entity_cleanup(&priv->sd.entity);
return ret;
}
static void max96717_subdev_uninit(struct max96717_priv *priv)
{
v4l2_async_unregister_subdev(&priv->sd);
v4l2_async_nf_unregister(&priv->notifier);
v4l2_async_nf_cleanup(&priv->notifier);
v4l2_subdev_cleanup(&priv->sd);
media_entity_cleanup(&priv->sd.entity);
}
struct max96717_pll_predef_freq {
unsigned long freq;
bool is_alt;
u8 val;
};
static const struct max96717_pll_predef_freq max96717_predef_freqs[] = {
{ 13500000, true, 0 }, { 19200000, false, 0 },
{ 24000000, true, 1 }, { 27000000, false, 1 },
{ 37125000, false, 2 }, { 74250000, false, 3 },
};
static unsigned long
max96717_clk_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
{
struct max96717_priv *priv = clk_hw_to_max96717(hw);
return max96717_predef_freqs[priv->pll_predef_index].freq;
}
static unsigned int max96717_clk_find_best_index(struct max96717_priv *priv,
unsigned long rate)
{
unsigned int i, idx;
unsigned long diff_new, diff_old;
diff_old = U32_MAX;
idx = 0;
for (i = 0; i < ARRAY_SIZE(max96717_predef_freqs); i++) {
diff_new = abs(rate - max96717_predef_freqs[i].freq);
if (diff_new < diff_old) {
diff_old = diff_new;
idx = i;
}
}
return idx;
}
static long max96717_clk_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *parent_rate)
{
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);
if (rate != max96717_predef_freqs[idx].freq) {
dev_warn(dev, "Request CLK freq:%lu, found CLK freq:%lu\n",
rate, max96717_predef_freqs[idx].freq);
}
return max96717_predef_freqs[idx].freq;
}
static int max96717_clk_set_rate(struct clk_hw *hw, unsigned long rate,
unsigned long parent_rate)
{
struct max96717_priv *priv = clk_hw_to_max96717(hw);
unsigned int val, idx;
int ret = 0;
idx = max96717_clk_find_best_index(priv, rate);
val = FIELD_PREP(REFGEN_PREDEF_FREQ_MASK,
max96717_predef_freqs[idx].val);
if (max96717_predef_freqs[idx].is_alt)
val |= REFGEN_PREDEF_FREQ_ALT;
val |= REFGEN_RST | REFGEN_PREDEF_EN;
cci_write(priv->regmap, REF_VTG0, val, &ret);
cci_update_bits(priv->regmap, REF_VTG0, REFGEN_RST | REFGEN_EN,
REFGEN_EN, &ret);
if (ret)
return ret;
priv->pll_predef_index = idx;
return 0;
}
static int max96717_clk_prepare(struct clk_hw *hw)
{
struct max96717_priv *priv = clk_hw_to_max96717(hw);
return cci_update_bits(priv->regmap, MAX96717_REG6, RCLKEN,
RCLKEN, NULL);
}
static void max96717_clk_unprepare(struct clk_hw *hw)
{
struct max96717_priv *priv = clk_hw_to_max96717(hw);
cci_update_bits(priv->regmap, MAX96717_REG6, RCLKEN, 0, NULL);
}
static const struct clk_ops max96717_clk_ops = {
.prepare = max96717_clk_prepare,
.unprepare = max96717_clk_unprepare,
.set_rate = max96717_clk_set_rate,
.recalc_rate = max96717_clk_recalc_rate,
.round_rate = max96717_clk_round_rate,
};
static int max96717_register_clkout(struct max96717_priv *priv)
{
struct device *dev = &priv->client->dev;
struct clk_init_data init = { .ops = &max96717_clk_ops };
int ret;
init.name = kasprintf(GFP_KERNEL, "max96717.%s.clk_out",
dev_name(dev));
if (!init.name)
return -ENOMEM;
/* RCLKSEL Reference PLL output */
ret = cci_update_bits(priv->regmap, MAX96717_REG3, MAX96717_RCLKSEL,
MAX96717_RCLKSEL, NULL);
/* MFP4 fastest slew rate */
cci_update_bits(priv->regmap, PIO_SLEW_1, BIT(5) | BIT(4), 0, &ret);
if (ret)
goto free_init_name;
priv->clk_hw.init = &init;
/* Initialize to 24 MHz */
ret = max96717_clk_set_rate(&priv->clk_hw,
MAX96717_DEFAULT_CLKOUT_RATE, 0);
if (ret < 0)
goto free_init_name;
ret = devm_clk_hw_register(dev, &priv->clk_hw);
kfree(init.name);
if (ret)
return dev_err_probe(dev, ret, "Cannot register clock HW\n");
ret = devm_of_clk_add_hw_provider(dev, of_clk_hw_simple_get,
&priv->clk_hw);
if (ret)
return dev_err_probe(dev, ret,
"Cannot add OF clock provider\n");
return 0;
free_init_name:
kfree(init.name);
return ret;
}
static int max96717_init_csi_lanes(struct max96717_priv *priv)
{
struct v4l2_mbus_config_mipi_csi2 *mipi = &priv->mipi_csi2;
unsigned long lanes_used = 0;
unsigned int nlanes, lane, val = 0;
int ret;
nlanes = mipi->num_data_lanes;
ret = cci_update_bits(priv->regmap, MAX96717_MIPI_RX1,
MAX96717_MIPI_LANES_CNT,
FIELD_PREP(MAX96717_MIPI_LANES_CNT,
nlanes - 1), NULL);
/* lanes polarity */
for (lane = 0; lane < nlanes + 1; lane++) {
if (!mipi->lane_polarities[lane])
continue;
/* Clock lane */
if (lane == 0)
val |= BIT(2);
else if (lane < 3)
val |= BIT(lane - 1);
else
val |= BIT(lane);
}
cci_update_bits(priv->regmap, MAX96717_MIPI_RX5,
MAX96717_PHY2_LANES_POL,
FIELD_PREP(MAX96717_PHY2_LANES_POL, val), &ret);
cci_update_bits(priv->regmap, MAX96717_MIPI_RX4,
MAX96717_PHY1_LANES_POL,
FIELD_PREP(MAX96717_PHY1_LANES_POL,
val >> 3), &ret);
/* lanes mapping */
for (lane = 0, val = 0; lane < nlanes; lane++) {
val |= (mipi->data_lanes[lane] - 1) << (lane * 2);
lanes_used |= BIT(mipi->data_lanes[lane] - 1);
}
/*
* Unused lanes need to be mapped as well to not have
* the same lanes mapped twice.
*/
for (; lane < 4; lane++) {
unsigned int idx = find_first_zero_bit(&lanes_used, 4);
val |= idx << (lane * 2);
lanes_used |= BIT(idx);
}
cci_update_bits(priv->regmap, MAX96717_MIPI_RX3,
MAX96717_PHY1_LANES_MAP,
FIELD_PREP(MAX96717_PHY1_LANES_MAP, val), &ret);
return cci_update_bits(priv->regmap, MAX96717_MIPI_RX2,
MAX96717_PHY2_LANES_MAP,
FIELD_PREP(MAX96717_PHY2_LANES_MAP, val >> 4),
&ret);
}
static int max96717_hw_init(struct max96717_priv *priv)
{
struct device *dev = &priv->client->dev;
u64 dev_id, val;
int ret;
ret = cci_read(priv->regmap, MAX96717_DEV_ID, &dev_id, NULL);
if (ret)
return dev_err_probe(dev, ret,
"Fail to read the device id\n");
if (dev_id != MAX96717_DEVICE_ID && dev_id != MAX96717F_DEVICE_ID)
return dev_err_probe(dev, -EOPNOTSUPP,
"Unsupported device id got %x\n", (u8)dev_id);
ret = cci_read(priv->regmap, MAX96717_DEV_REV, &val, NULL);
if (ret)
return dev_err_probe(dev, ret,
"Fail to read device revision");
dev_dbg(dev, "Found %x (rev %lx)\n", (u8)dev_id,
(u8)val & MAX96717_DEV_REV_MASK);
ret = cci_read(priv->regmap, MAX96717_MIPI_RX_EXT11, &val, NULL);
if (ret)
return dev_err_probe(dev, ret,
"Fail to read mipi rx extension");
if (!(val & MAX96717_TUN_MODE))
return dev_err_probe(dev, -EOPNOTSUPP,
"Only supporting tunnel mode");
return max96717_init_csi_lanes(priv);
}
static int max96717_parse_dt(struct max96717_priv *priv)
{
struct device *dev = &priv->client->dev;
struct v4l2_fwnode_endpoint vep = {
.bus_type = V4L2_MBUS_CSI2_DPHY
};
struct fwnode_handle *ep_fwnode;
unsigned char num_data_lanes;
int ret;
ep_fwnode = fwnode_graph_get_endpoint_by_id(dev_fwnode(dev),
MAX96717_PAD_SINK, 0, 0);
if (!ep_fwnode)
return dev_err_probe(dev, -ENOENT, "no endpoint found\n");
ret = v4l2_fwnode_endpoint_parse(ep_fwnode, &vep);
fwnode_handle_put(ep_fwnode);
if (ret < 0)
return dev_err_probe(dev, ret, "Failed to parse sink endpoint");
num_data_lanes = vep.bus.mipi_csi2.num_data_lanes;
if (num_data_lanes < 1 || num_data_lanes > 4)
return dev_err_probe(dev, -EINVAL,
"Invalid data lanes must be 1 to 4\n");
memcpy(&priv->mipi_csi2, &vep.bus.mipi_csi2, sizeof(priv->mipi_csi2));
return 0;
}
static int max96717_probe(struct i2c_client *client)
{
struct device *dev = &client->dev;
struct max96717_priv *priv;
int ret;
priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
if (!priv)
return -ENOMEM;
priv->client = client;
priv->regmap = devm_cci_regmap_init_i2c(client, 16);
if (IS_ERR(priv->regmap)) {
ret = PTR_ERR(priv->regmap);
return dev_err_probe(dev, ret, "Failed to init regmap\n");
}
ret = max96717_parse_dt(priv);
if (ret)
return dev_err_probe(dev, ret, "Failed to parse the dt\n");
ret = max96717_hw_init(priv);
if (ret)
return dev_err_probe(dev, ret,
"Failed to initialize the hardware\n");
ret = max96717_gpiochip_probe(priv);
if (ret)
return dev_err_probe(&client->dev, ret,
"Failed to init gpiochip\n");
ret = max96717_register_clkout(priv);
if (ret)
return dev_err_probe(dev, ret, "Failed to register clkout\n");
ret = max96717_subdev_init(priv);
if (ret)
return dev_err_probe(dev, ret,
"Failed to initialize v4l2 subdev\n");
ret = max96717_i2c_mux_init(priv);
if (ret) {
dev_err_probe(dev, ret, "failed to add remote i2c adapter\n");
max96717_subdev_uninit(priv);
}
return ret;
}
static void max96717_remove(struct i2c_client *client)
{
struct v4l2_subdev *sd = i2c_get_clientdata(client);
struct max96717_priv *priv = sd_to_max96717(sd);
max96717_subdev_uninit(priv);
i2c_mux_del_adapters(priv->mux);
}
static const struct of_device_id max96717_of_ids[] = {
{ .compatible = "maxim,max96717f" },
{ }
};
MODULE_DEVICE_TABLE(of, max96717_of_ids);
static struct i2c_driver max96717_i2c_driver = {
.driver = {
.name = "max96717",
.of_match_table = max96717_of_ids,
},
.probe = max96717_probe,
.remove = max96717_remove,
};
module_i2c_driver(max96717_i2c_driver);
MODULE_DESCRIPTION("Maxim GMSL2 MAX96717 Serializer Driver");
MODULE_AUTHOR("Julien Massot <julien.massot@collabora.com>");
MODULE_LICENSE("GPL");

View File

@ -971,7 +971,7 @@ static int ov2680_v4l2_register(struct ov2680_dev *sensor)
if (ret < 0)
return ret;
v4l2_ctrl_handler_init(hdl, 5);
v4l2_ctrl_handler_init(hdl, 11);
hdl->lock = &sensor->lock;

View File

@ -1360,24 +1360,21 @@ static int ov5647_parse_dt(struct ov5647 *sensor, struct device_node *np)
struct v4l2_fwnode_endpoint bus_cfg = {
.bus_type = V4L2_MBUS_CSI2_DPHY,
};
struct device_node *ep;
struct device_node *ep __free(device_node) =
of_graph_get_endpoint_by_regs(np, 0, -1);
int ret;
ep = of_graph_get_endpoint_by_regs(np, 0, -1);
if (!ep)
return -EINVAL;
ret = v4l2_fwnode_endpoint_parse(of_fwnode_handle(ep), &bus_cfg);
if (ret)
goto out;
return ret;
sensor->clock_ncont = bus_cfg.bus.mipi_csi2.flags &
V4L2_MBUS_CSI2_NONCONTINUOUS_CLOCK;
out:
of_node_put(ep);
return ret;
return 0;
}
static int ov5647_probe(struct i2c_client *client)

View File

@ -141,7 +141,6 @@ struct ov5693_device {
struct gpio_desc *reset;
struct gpio_desc *powerdown;
struct gpio_desc *privacy_led;
struct regulator_bulk_data supplies[OV5693_NUM_SUPPLIES];
struct clk *xvclk;
@ -657,7 +656,6 @@ static int ov5693_sensor_init(struct ov5693_device *ov5693)
static void ov5693_sensor_powerdown(struct ov5693_device *ov5693)
{
gpiod_set_value_cansleep(ov5693->privacy_led, 0);
gpiod_set_value_cansleep(ov5693->reset, 1);
gpiod_set_value_cansleep(ov5693->powerdown, 1);
@ -687,7 +685,6 @@ static int ov5693_sensor_powerup(struct ov5693_device *ov5693)
gpiod_set_value_cansleep(ov5693->powerdown, 0);
gpiod_set_value_cansleep(ov5693->reset, 0);
gpiod_set_value_cansleep(ov5693->privacy_led, 1);
usleep_range(5000, 7500);
@ -1201,13 +1198,6 @@ static int ov5693_configure_gpios(struct ov5693_device *ov5693)
return PTR_ERR(ov5693->powerdown);
}
ov5693->privacy_led = devm_gpiod_get_optional(ov5693->dev, "privacy-led",
GPIOD_OUT_LOW);
if (IS_ERR(ov5693->privacy_led)) {
dev_err(ov5693->dev, "Error fetching privacy-led GPIO\n");
return PTR_ERR(ov5693->privacy_led);
}
return 0;
}

View File

@ -212,11 +212,6 @@
* structure
*/
struct regval_list {
unsigned char reg_num;
unsigned char value;
};
struct tw9910_scale_ctrl {
char *name;
unsigned short width;

View File

@ -95,4 +95,5 @@ static struct i2c_driver uda1342_driver = {
module_i2c_driver(uda1342_driver);
MODULE_DESCRIPTION("Philips UDA1342 audio codec driver");
MODULE_LICENSE("GPL v2");

View File

@ -1878,7 +1878,7 @@ static const struct dev_pm_ops vgxy61_pm_ops = {
static struct i2c_driver vgxy61_i2c_driver = {
.driver = {
.name = "st-vgxy61",
.name = "vgxy61",
.of_match_table = vgxy61_dt_ids,
.pm = &vgxy61_pm_ops,
},

View File

@ -300,8 +300,8 @@ static irqreturn_t bt878_irq(int irq, void *dev_id)
}
if (astat & BT878_ARISCI) {
bt->finished_block = (stat & BT878_ARISCS) >> 28;
if (bt->tasklet.callback)
tasklet_schedule(&bt->tasklet);
if (bt->bh_work.func)
queue_work(system_bh_wq, &bt->bh_work);
break;
}
count++;
@ -478,8 +478,8 @@ static int bt878_probe(struct pci_dev *dev, const struct pci_device_id *pci_id)
btwrite(0, BT878_AINT_MASK);
bt878_num++;
if (!bt->tasklet.func)
tasklet_disable(&bt->tasklet);
if (!bt->bh_work.func)
disable_work_sync(&bt->bh_work);
return 0;
@ -563,4 +563,5 @@ static void __exit bt878_cleanup_module(void)
module_init(bt878_init_module);
module_exit(bt878_cleanup_module);
MODULE_DESCRIPTION("DVB/ATSC Support for bt878 based TV cards");
MODULE_LICENSE("GPL");

View File

@ -14,6 +14,7 @@
#include <linux/sched.h>
#include <linux/spinlock.h>
#include <linux/mutex.h>
#include <linux/workqueue.h>
#include "bt848.h"
#include "bttv.h"
@ -120,7 +121,7 @@ struct bt878 {
dma_addr_t risc_dma;
u32 risc_pos;
struct tasklet_struct tasklet;
struct work_struct bh_work;
int shutdown;
};

View File

@ -39,9 +39,9 @@ DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
#define IF_FREQUENCYx6 217 /* 6 * 36.16666666667MHz */
static void dvb_bt8xx_task(struct tasklet_struct *t)
static void dvb_bt8xx_work(struct work_struct *t)
{
struct bt878 *bt = from_tasklet(bt, t, tasklet);
struct bt878 *bt = from_work(bt, t, bh_work);
struct dvb_bt8xx_card *card = dev_get_drvdata(&bt->adapter->dev);
dprintk("%d\n", card->bt->finished_block);
@ -782,7 +782,7 @@ static int dvb_bt8xx_load_card(struct dvb_bt8xx_card *card, u32 type)
goto err_disconnect_frontend;
}
tasklet_setup(&card->bt->tasklet, dvb_bt8xx_task);
INIT_WORK(&card->bt->bh_work, dvb_bt8xx_work);
frontend_init(card, type);
@ -922,7 +922,7 @@ static void dvb_bt8xx_remove(struct bttv_sub_device *sub)
dprintk("dvb_bt8xx: unloading card%d\n", card->bttv_nr);
bt878_stop(card->bt);
tasklet_kill(&card->bt->tasklet);
cancel_work_sync(&card->bt->bh_work);
dvb_net_release(&card->dvbnet);
card->demux.dmx.remove_frontend(&card->demux.dmx, &card->fe_mem);
card->demux.dmx.remove_frontend(&card->demux.dmx, &card->fe_hw);

View File

@ -258,7 +258,7 @@ struct cx18_scb {
struct cx18_mailbox ppu2epu_mb;
struct cx18_mdl_ack cpu_mdl_ack[CX18_MAX_STREAMS][CX18_MAX_MDL_ACKS];
struct cx18_mdl_ent cpu_mdl[1];
struct cx18_mdl_ent cpu_mdl[];
};
void cx18_init_scb(struct cx18 *cx);

View File

@ -298,7 +298,7 @@ struct ddb_link {
spinlock_t lock; /* lock link access */
struct mutex flash_mutex; /* lock flash access */
struct ddb_lnb lnb;
struct tasklet_struct tasklet;
struct work_struct bh_work;
struct ddb_ids ids;
spinlock_t temp_lock; /* lock temp chip access */

View File

@ -43,28 +43,46 @@
* becoming apparent in the future.
*
* Do not add an entry for a sensor that is not actually supported.
*
* Please keep the list sorted by ACPI HID.
*/
static const struct ipu_sensor_config ipu_supported_sensors[] = {
/* Himax HM11B1 */
IPU_SENSOR_CONFIG("HIMX11B1", 1, 384000000),
/* Himax HM2170 */
IPU_SENSOR_CONFIG("HIMX2170", 1, 384000000),
/* Himax HM2172 */
IPU_SENSOR_CONFIG("HIMX2172", 1, 384000000),
/* GalaxyCore GC0310 */
IPU_SENSOR_CONFIG("INT0310", 0),
/* Omnivision OV5693 */
IPU_SENSOR_CONFIG("INT33BE", 1, 419200000),
/* Omnivision OV2740 */
IPU_SENSOR_CONFIG("INT3474", 1, 180000000),
/* Omnivision OV8865 */
IPU_SENSOR_CONFIG("INT347A", 1, 360000000),
/* Omnivision OV7251 */
IPU_SENSOR_CONFIG("INT347E", 1, 319200000),
/* Hynix Hi-556 */
IPU_SENSOR_CONFIG("INT3537", 1, 437000000),
/* Omnivision OV01A10 / OV01A1S */
IPU_SENSOR_CONFIG("OVTI01A0", 1, 400000000),
IPU_SENSOR_CONFIG("OVTI01AS", 1, 400000000),
/* Omnivision OV02C10 */
IPU_SENSOR_CONFIG("OVTI02C1", 1, 400000000),
/* Omnivision OV02E10 */
IPU_SENSOR_CONFIG("OVTI02E1", 1, 360000000),
/* Omnivision OV08A10 */
IPU_SENSOR_CONFIG("OVTI08A1", 1, 500000000),
/* Omnivision OV08x40 */
IPU_SENSOR_CONFIG("OVTI08F4", 1, 400000000),
/* Omnivision OV13B10 */
IPU_SENSOR_CONFIG("OVTI13B1", 1, 560000000),
IPU_SENSOR_CONFIG("OVTIDB10", 1, 560000000),
/* Omnivision OV2680 */
IPU_SENSOR_CONFIG("OVTI2680", 1, 331200000),
/* Omnivision ov8856 */
/* Omnivision OV8856 */
IPU_SENSOR_CONFIG("OVTI8856", 3, 180000000, 360000000, 720000000),
/* Omnivision ov2740 */
IPU_SENSOR_CONFIG("INT3474", 1, 180000000),
/* Hynix hi556 */
IPU_SENSOR_CONFIG("INT3537", 1, 437000000),
/* Omnivision ov13b10 */
IPU_SENSOR_CONFIG("OVTIDB10", 1, 560000000),
/* GalaxyCore GC0310 */
IPU_SENSOR_CONFIG("INT0310", 0),
/* Omnivision ov01a10 */
IPU_SENSOR_CONFIG("OVTI01A0", 1, 400000000),
};
static const struct ipu_property_names prop_names = {

View File

@ -163,8 +163,8 @@ int ipu6_buttress_ipc_reset(struct ipu6_device *isp,
writel(ENTRY, isp->base + ipc->csr_out);
break;
default:
dev_warn_ratelimited(&isp->pdev->dev,
"Unexpected CSR 0x%x\n", val);
dev_dbg_ratelimited(&isp->pdev->dev,
"Unexpected CSR 0x%x\n", val);
break;
}
} while (retries--);

View File

@ -345,42 +345,61 @@ static int ipu6_isys_csi2_set_stream(struct v4l2_subdev *sd,
return ret;
}
static int set_stream(struct v4l2_subdev *sd, int enable)
static int ipu6_isys_csi2_enable_streams(struct v4l2_subdev *sd,
struct v4l2_subdev_state *state,
u32 pad, u64 streams_mask)
{
struct ipu6_isys_subdev *asd = to_ipu6_isys_subdev(sd);
struct ipu6_isys_csi2 *csi2 = to_ipu6_isys_csi2(asd);
struct device *dev = &csi2->isys->adev->auxdev.dev;
struct ipu6_isys_csi2_timing timing = { };
unsigned int nlanes;
struct v4l2_subdev *remote_sd;
struct media_pad *remote_pad;
u64 sink_streams;
int ret;
dev_dbg(dev, "csi2 stream %s callback\n", enable ? "on" : "off");
remote_pad = media_pad_remote_pad_first(&sd->entity.pads[CSI2_PAD_SINK]);
remote_sd = media_entity_to_v4l2_subdev(remote_pad->entity);
if (!enable) {
csi2->stream_count--;
if (csi2->stream_count)
return 0;
ipu6_isys_csi2_set_stream(sd, &timing, 0, enable);
return 0;
}
if (csi2->stream_count) {
csi2->stream_count++;
return 0;
}
nlanes = csi2->nlanes;
sink_streams = v4l2_subdev_state_xlate_streams(state, CSI2_PAD_SRC,
CSI2_PAD_SINK,
&streams_mask);
ret = ipu6_isys_csi2_calc_timing(csi2, &timing, CSI2_ACCINV);
if (ret)
return ret;
ret = ipu6_isys_csi2_set_stream(sd, &timing, nlanes, enable);
ret = ipu6_isys_csi2_set_stream(sd, &timing, csi2->nlanes, true);
if (ret)
return ret;
csi2->stream_count++;
ret = v4l2_subdev_enable_streams(remote_sd, remote_pad->index,
sink_streams);
if (ret) {
ipu6_isys_csi2_set_stream(sd, NULL, 0, false);
return ret;
}
return 0;
}
static int ipu6_isys_csi2_disable_streams(struct v4l2_subdev *sd,
struct v4l2_subdev_state *state,
u32 pad, u64 streams_mask)
{
struct v4l2_subdev *remote_sd;
struct media_pad *remote_pad;
u64 sink_streams;
sink_streams = v4l2_subdev_state_xlate_streams(state, CSI2_PAD_SRC,
CSI2_PAD_SINK,
&streams_mask);
remote_pad = media_pad_remote_pad_first(&sd->entity.pads[CSI2_PAD_SINK]);
remote_sd = media_entity_to_v4l2_subdev(remote_pad->entity);
ipu6_isys_csi2_set_stream(sd, NULL, 0, false);
v4l2_subdev_disable_streams(remote_sd, remote_pad->index, sink_streams);
return 0;
}
@ -475,10 +494,6 @@ static int ipu6_isys_csi2_get_sel(struct v4l2_subdev *sd,
return ret;
}
static const struct v4l2_subdev_video_ops csi2_sd_video_ops = {
.s_stream = set_stream,
};
static const struct v4l2_subdev_pad_ops csi2_sd_pad_ops = {
.get_fmt = v4l2_subdev_get_fmt,
.set_fmt = ipu6_isys_subdev_set_fmt,
@ -486,11 +501,12 @@ static const struct v4l2_subdev_pad_ops csi2_sd_pad_ops = {
.set_selection = ipu6_isys_csi2_set_sel,
.enum_mbus_code = ipu6_isys_subdev_enum_mbus_code,
.set_routing = ipu6_isys_subdev_set_routing,
.enable_streams = ipu6_isys_csi2_enable_streams,
.disable_streams = ipu6_isys_csi2_disable_streams,
};
static const struct v4l2_subdev_ops csi2_sd_ops = {
.core = &csi2_sd_core_ops,
.video = &csi2_sd_video_ops,
.pad = &csi2_sd_pad_ops,
};
@ -631,33 +647,3 @@ int ipu6_isys_csi2_get_remote_desc(u32 source_stream,
return 0;
}
void ipu6_isys_set_csi2_streams_status(struct ipu6_isys_video *av, bool status)
{
struct ipu6_isys_stream *stream = av->stream;
struct v4l2_subdev *sd = &stream->asd->sd;
struct v4l2_subdev_state *state;
struct media_pad *r_pad;
unsigned int i;
u32 r_stream;
r_pad = media_pad_remote_pad_first(&av->pad);
r_stream = ipu6_isys_get_src_stream_by_src_pad(sd, r_pad->index);
state = v4l2_subdev_lock_and_get_active_state(sd);
for (i = 0; i < state->stream_configs.num_configs; i++) {
struct v4l2_subdev_stream_config *cfg =
&state->stream_configs.configs[i];
if (cfg->pad == r_pad->index && r_stream == cfg->stream) {
dev_dbg(&av->isys->adev->auxdev.dev,
"%s: pad:%u, stream:%u, status:%u\n",
sd->entity.name, r_pad->index, r_stream,
status);
cfg->enabled = status;
}
}
v4l2_subdev_unlock_state(state);
}

View File

@ -45,7 +45,6 @@ struct ipu6_isys_csi2 {
u32 receiver_errors;
unsigned int nlanes;
unsigned int port;
unsigned int stream_count;
};
struct ipu6_isys_csi2_timing {
@ -77,6 +76,5 @@ int ipu6_isys_csi2_get_remote_desc(u32 source_stream,
struct ipu6_isys_csi2 *csi2,
struct media_entity *source_entity,
struct v4l2_mbus_frame_desc_entry *entry);
void ipu6_isys_set_csi2_streams_status(struct ipu6_isys_video *av, bool status);
#endif /* IPU6_ISYS_CSI2_H */

View File

@ -551,7 +551,6 @@ static int start_streaming(struct vb2_queue *q, unsigned int count)
stream->nr_queues);
list_add(&aq->node, &stream->queues);
ipu6_isys_set_csi2_streams_status(av, true);
ipu6_isys_configure_stream_watermark(av, true);
ipu6_isys_update_stream_watermark(av, true);
@ -598,8 +597,6 @@ static void stop_streaming(struct vb2_queue *q)
struct ipu6_isys_video *av = ipu6_isys_queue_to_video(aq);
struct ipu6_isys_stream *stream = av->stream;
ipu6_isys_set_csi2_streams_status(av, false);
mutex_lock(&stream->mutex);
ipu6_isys_update_stream_watermark(av, false);

View File

@ -990,9 +990,7 @@ int ipu6_isys_video_set_streaming(struct ipu6_isys_video *av, int state,
struct v4l2_subdev_state *subdev_state;
struct device *dev = &av->isys->adev->auxdev.dev;
struct v4l2_subdev *sd;
struct v4l2_subdev *ssd;
struct media_pad *r_pad;
struct media_pad *s_pad;
u32 sink_pad, sink_stream;
u64 r_stream;
u64 stream_mask = 0;
@ -1003,7 +1001,6 @@ int ipu6_isys_video_set_streaming(struct ipu6_isys_video *av, int state,
if (WARN(!stream->source_entity, "No source entity for stream\n"))
return -ENODEV;
ssd = media_entity_to_v4l2_subdev(stream->source_entity);
sd = &stream->asd->sd;
r_pad = media_pad_remote_pad_first(&av->pad);
r_stream = ipu6_isys_get_src_stream_by_src_pad(sd, r_pad->index);
@ -1017,27 +1014,15 @@ int ipu6_isys_video_set_streaming(struct ipu6_isys_video *av, int state,
if (ret)
return ret;
s_pad = media_pad_remote_pad_first(&stream->asd->pad[sink_pad]);
stream_mask = get_stream_mask_by_pipeline(av);
if (!state) {
stop_streaming_firmware(av);
/* stop external sub-device now. */
dev_dbg(dev, "disable streams 0x%llx of %s\n", stream_mask,
ssd->name);
ret = v4l2_subdev_disable_streams(ssd, s_pad->index,
stream_mask);
if (ret) {
dev_err(dev, "disable streams of %s failed with %d\n",
ssd->name, ret);
return ret;
}
/* stop sub-device which connects with video */
dev_dbg(dev, "stream off entity %s pad:%d\n", sd->name,
r_pad->index);
ret = v4l2_subdev_call(sd, video, s_stream, state);
dev_dbg(dev, "stream off entity %s pad:%d mask:0x%llx\n",
sd->name, r_pad->index, stream_mask);
ret = v4l2_subdev_disable_streams(sd, r_pad->index,
stream_mask);
if (ret) {
dev_err(dev, "stream off %s failed with %d\n", sd->name,
ret);
@ -1052,34 +1037,20 @@ int ipu6_isys_video_set_streaming(struct ipu6_isys_video *av, int state,
}
/* start sub-device which connects with video */
dev_dbg(dev, "stream on %s pad %d\n", sd->name, r_pad->index);
ret = v4l2_subdev_call(sd, video, s_stream, state);
dev_dbg(dev, "stream on %s pad %d mask 0x%llx\n", sd->name,
r_pad->index, stream_mask);
ret = v4l2_subdev_enable_streams(sd, r_pad->index, stream_mask);
if (ret) {
dev_err(dev, "stream on %s failed with %d\n", sd->name,
ret);
goto out_media_entity_stop_streaming_firmware;
}
/* start external sub-device now. */
dev_dbg(dev, "enable streams 0x%llx of %s\n", stream_mask,
ssd->name);
ret = v4l2_subdev_enable_streams(ssd, s_pad->index,
stream_mask);
if (ret) {
dev_err(dev,
"enable streams 0x%llx of %s failed with %d\n",
stream_mask, stream->source_entity->name, ret);
goto out_media_entity_stop_streaming;
}
}
av->streaming = state;
return 0;
out_media_entity_stop_streaming:
v4l2_subdev_disable_streams(sd, r_pad->index, BIT(r_stream));
out_media_entity_stop_streaming_firmware:
stop_streaming_firmware(av);

View File

@ -126,6 +126,8 @@ struct mei_csi {
struct v4l2_ctrl_handler ctrl_handler;
struct v4l2_ctrl *freq_ctrl;
struct v4l2_ctrl *privacy_ctrl;
/* lock for v4l2 controls */
struct mutex ctrl_lock;
unsigned int remote_pad;
/* start streaming or not */
int streaming;
@ -136,9 +138,6 @@ struct mei_csi {
u32 nr_of_lanes;
/* frequency of the CSI-2 link */
u64 link_freq;
/* privacy status */
enum ivsc_privacy_status status;
};
static const struct v4l2_mbus_framefmt mei_csi_format_mbus_default = {
@ -190,7 +189,11 @@ static int mei_csi_send(struct mei_csi *csi, u8 *buf, size_t len)
/* command response status */
ret = csi->cmd_response.status;
if (ret) {
if (ret == -1) {
/* notify privacy on instead of reporting error */
ret = 0;
v4l2_ctrl_s_ctrl(csi->privacy_ctrl, 1);
} else if (ret) {
ret = -EINVAL;
goto out;
}
@ -265,10 +268,9 @@ static void mei_csi_rx(struct mei_cl_device *cldev)
switch (notif.cmd_id) {
case CSI_PRIVACY_NOTIF:
if (notif.cont.cont < CSI_PRIVACY_MAX) {
csi->status = notif.cont.cont;
v4l2_ctrl_s_ctrl(csi->privacy_ctrl, csi->status);
}
if (notif.cont.cont < CSI_PRIVACY_MAX)
v4l2_ctrl_s_ctrl(csi->privacy_ctrl,
notif.cont.cont == CSI_PRIVACY_ON);
break;
case CSI_SET_OWNER:
case CSI_SET_CONF:
@ -559,11 +561,13 @@ static int mei_csi_init_controls(struct mei_csi *csi)
u32 max;
int ret;
mutex_init(&csi->ctrl_lock);
ret = v4l2_ctrl_handler_init(&csi->ctrl_handler, 2);
if (ret)
return ret;
csi->ctrl_handler.lock = &csi->lock;
csi->ctrl_handler.lock = &csi->ctrl_lock;
max = ARRAY_SIZE(link_freq_menu_items) - 1;
csi->freq_ctrl = v4l2_ctrl_new_int_menu(&csi->ctrl_handler,
@ -755,6 +759,7 @@ err_entity:
err_ctrl_handler:
v4l2_ctrl_handler_free(&csi->ctrl_handler);
mutex_destroy(&csi->ctrl_lock);
v4l2_async_nf_unregister(&csi->notifier);
v4l2_async_nf_cleanup(&csi->notifier);
@ -774,6 +779,7 @@ static void mei_csi_remove(struct mei_cl_device *cldev)
v4l2_async_nf_unregister(&csi->notifier);
v4l2_async_nf_cleanup(&csi->notifier);
v4l2_ctrl_handler_free(&csi->ctrl_handler);
mutex_destroy(&csi->ctrl_lock);
v4l2_async_unregister_subdev(&csi->subdev);
v4l2_subdev_cleanup(&csi->subdev);
media_entity_cleanup(&csi->subdev.entity);

View File

@ -371,33 +371,6 @@ int ivtv_msleep_timeout(unsigned int msecs, int intr)
return 0;
}
/* Release ioremapped memory */
static void ivtv_iounmap(struct ivtv *itv)
{
if (itv == NULL)
return;
/* Release registers memory */
if (itv->reg_mem != NULL) {
IVTV_DEBUG_INFO("releasing reg_mem\n");
iounmap(itv->reg_mem);
itv->reg_mem = NULL;
}
/* Release io memory */
if (itv->has_cx23415 && itv->dec_mem != NULL) {
IVTV_DEBUG_INFO("releasing dec_mem\n");
iounmap(itv->dec_mem);
}
itv->dec_mem = NULL;
/* Release io memory */
if (itv->enc_mem != NULL) {
IVTV_DEBUG_INFO("releasing enc_mem\n");
iounmap(itv->enc_mem);
itv->enc_mem = NULL;
}
}
/* Hauppauge card? get values from tveeprom */
void ivtv_read_eeprom(struct ivtv *itv, struct tveeprom *tv)
{
@ -833,7 +806,7 @@ static int ivtv_setup_pci(struct ivtv *itv, struct pci_dev *pdev,
IVTV_DEBUG_INFO("Enabling pci device\n");
if (pci_enable_device(pdev)) {
if (pcim_enable_device(pdev)) {
IVTV_ERR("Can't enable device!\n");
return -EIO;
}
@ -841,24 +814,24 @@ static int ivtv_setup_pci(struct ivtv *itv, struct pci_dev *pdev,
IVTV_ERR("No suitable DMA available.\n");
return -EIO;
}
if (!request_mem_region(itv->base_addr, IVTV_ENCODER_SIZE, "ivtv encoder")) {
if (!devm_request_mem_region(&pdev->dev, itv->base_addr,
IVTV_ENCODER_SIZE, "ivtv encoder")) {
IVTV_ERR("Cannot request encoder memory region.\n");
return -EIO;
}
if (!request_mem_region(itv->base_addr + IVTV_REG_OFFSET,
IVTV_REG_SIZE, "ivtv registers")) {
if (!devm_request_mem_region(&pdev->dev,
itv->base_addr + IVTV_REG_OFFSET,
IVTV_REG_SIZE, "ivtv registers")) {
IVTV_ERR("Cannot request register memory region.\n");
release_mem_region(itv->base_addr, IVTV_ENCODER_SIZE);
return -EIO;
}
if (itv->has_cx23415 &&
!request_mem_region(itv->base_addr + IVTV_DECODER_OFFSET,
IVTV_DECODER_SIZE, "ivtv decoder")) {
!devm_request_mem_region(&pdev->dev,
itv->base_addr + IVTV_DECODER_OFFSET,
IVTV_DECODER_SIZE, "ivtv decoder")) {
IVTV_ERR("Cannot request decoder memory region.\n");
release_mem_region(itv->base_addr, IVTV_ENCODER_SIZE);
release_mem_region(itv->base_addr + IVTV_REG_OFFSET, IVTV_REG_SIZE);
return -EIO;
}
@ -870,11 +843,6 @@ static int ivtv_setup_pci(struct ivtv *itv, struct pci_dev *pdev,
pci_read_config_word(pdev, PCI_COMMAND, &cmd);
if (!(cmd & PCI_COMMAND_MASTER)) {
IVTV_ERR("Bus Mastering is not enabled\n");
if (itv->has_cx23415)
release_mem_region(itv->base_addr + IVTV_DECODER_OFFSET,
IVTV_DECODER_SIZE);
release_mem_region(itv->base_addr, IVTV_ENCODER_SIZE);
release_mem_region(itv->base_addr + IVTV_REG_OFFSET, IVTV_REG_SIZE);
return -ENXIO;
}
}
@ -1033,37 +1001,37 @@ static int ivtv_probe(struct pci_dev *pdev, const struct pci_device_id *pci_id)
/* PCI Device Setup */
retval = ivtv_setup_pci(itv, pdev, pci_id);
if (retval == -EIO)
if (retval == -EIO || retval == -ENXIO)
goto free_worker;
if (retval == -ENXIO)
goto free_mem;
/* map io memory */
IVTV_DEBUG_INFO("attempting ioremap at 0x%llx len 0x%08x\n",
(u64)itv->base_addr + IVTV_ENCODER_OFFSET, IVTV_ENCODER_SIZE);
itv->enc_mem = ioremap(itv->base_addr + IVTV_ENCODER_OFFSET,
IVTV_ENCODER_SIZE);
itv->enc_mem = devm_ioremap(&pdev->dev,
itv->base_addr + IVTV_ENCODER_OFFSET,
IVTV_ENCODER_SIZE);
if (!itv->enc_mem) {
IVTV_ERR("ioremap failed. Can't get a window into CX23415/6 encoder memory\n");
IVTV_ERR("Each capture card with a CX23415/6 needs 8 MB of vmalloc address space for this window\n");
IVTV_ERR("Check the output of 'grep Vmalloc /proc/meminfo'\n");
IVTV_ERR("Use the vmalloc= kernel command line option to set VmallocTotal to a larger value\n");
retval = -ENOMEM;
goto free_mem;
goto free_worker;
}
if (itv->has_cx23415) {
IVTV_DEBUG_INFO("attempting ioremap at 0x%llx len 0x%08x\n",
(u64)itv->base_addr + IVTV_DECODER_OFFSET, IVTV_DECODER_SIZE);
itv->dec_mem = ioremap(itv->base_addr + IVTV_DECODER_OFFSET,
IVTV_DECODER_SIZE);
itv->dec_mem = devm_ioremap(&pdev->dev,
itv->base_addr + IVTV_DECODER_OFFSET,
IVTV_DECODER_SIZE);
if (!itv->dec_mem) {
IVTV_ERR("ioremap failed. Can't get a window into CX23415 decoder memory\n");
IVTV_ERR("Each capture card with a CX23415 needs 8 MB of vmalloc address space for this window\n");
IVTV_ERR("Check the output of 'grep Vmalloc /proc/meminfo'\n");
IVTV_ERR("Use the vmalloc= kernel command line option to set VmallocTotal to a larger value\n");
retval = -ENOMEM;
goto free_mem;
goto free_worker;
}
}
else {
@ -1073,26 +1041,27 @@ static int ivtv_probe(struct pci_dev *pdev, const struct pci_device_id *pci_id)
/* map registers memory */
IVTV_DEBUG_INFO("attempting ioremap at 0x%llx len 0x%08x\n",
(u64)itv->base_addr + IVTV_REG_OFFSET, IVTV_REG_SIZE);
itv->reg_mem =
ioremap(itv->base_addr + IVTV_REG_OFFSET, IVTV_REG_SIZE);
itv->reg_mem = devm_ioremap(&pdev->dev,
itv->base_addr + IVTV_REG_OFFSET,
IVTV_REG_SIZE);
if (!itv->reg_mem) {
IVTV_ERR("ioremap failed. Can't get a window into CX23415/6 register space\n");
IVTV_ERR("Each capture card with a CX23415/6 needs 64 kB of vmalloc address space for this window\n");
IVTV_ERR("Check the output of 'grep Vmalloc /proc/meminfo'\n");
IVTV_ERR("Use the vmalloc= kernel command line option to set VmallocTotal to a larger value\n");
retval = -ENOMEM;
goto free_io;
goto free_worker;
}
retval = ivtv_gpio_init(itv);
if (retval)
goto free_io;
goto free_worker;
/* active i2c */
IVTV_DEBUG_INFO("activating i2c...\n");
if (init_ivtv_i2c(itv)) {
IVTV_ERR("Could not initialize i2c\n");
goto free_io;
goto free_worker;
}
if (itv->card->hw_all & IVTV_HW_TVEEPROM) {
@ -1277,13 +1246,6 @@ free_irq:
free_i2c:
v4l2_ctrl_handler_free(&itv->cxhdl.hdl);
exit_ivtv_i2c(itv);
free_io:
ivtv_iounmap(itv);
free_mem:
release_mem_region(itv->base_addr, IVTV_ENCODER_SIZE);
release_mem_region(itv->base_addr + IVTV_REG_OFFSET, IVTV_REG_SIZE);
if (itv->has_cx23415)
release_mem_region(itv->base_addr + IVTV_DECODER_OFFSET, IVTV_DECODER_SIZE);
free_worker:
kthread_stop(itv->irq_worker_task);
err:
@ -1439,14 +1401,7 @@ static void ivtv_remove(struct pci_dev *pdev)
exit_ivtv_i2c(itv);
free_irq(itv->pdev->irq, (void *)itv);
ivtv_iounmap(itv);
release_mem_region(itv->base_addr, IVTV_ENCODER_SIZE);
release_mem_region(itv->base_addr + IVTV_REG_OFFSET, IVTV_REG_SIZE);
if (itv->has_cx23415)
release_mem_region(itv->base_addr + IVTV_DECODER_OFFSET, IVTV_DECODER_SIZE);
pci_disable_device(itv->pdev);
for (i = 0; i < IVTV_VBI_FRAMES; i++)
kfree(itv->vbi.sliced_mpeg_data[i]);

View File

@ -21,6 +21,7 @@
#include "ivtv-ioctl.h"
#include "ivtv-cards.h"
#include "ivtv-firmware.h"
#include <linux/lockdep.h>
#include <media/v4l2-event.h>
#include <media/i2c/saa7115.h>
@ -190,12 +191,27 @@ static void ivtv_update_pgm_info(struct ivtv *itv)
itv->pgm_info_write_idx = (itv->pgm_info_write_idx + i) % itv->pgm_info_num;
}
static void ivtv_schedule(struct ivtv_stream *s)
{
struct ivtv *itv = s->itv;
DEFINE_WAIT(wait);
lockdep_assert_held(&itv->serialize_lock);
mutex_unlock(&itv->serialize_lock);
prepare_to_wait(&s->waitq, &wait, TASK_INTERRUPTIBLE);
/* New buffers might have become free before we were added to the waitqueue */
if (!s->q_free.buffers)
schedule();
finish_wait(&s->waitq, &wait);
mutex_lock(&itv->serialize_lock);
}
static struct ivtv_buffer *ivtv_get_buffer(struct ivtv_stream *s, int non_block, int *err)
{
struct ivtv *itv = s->itv;
struct ivtv_stream *s_vbi = &itv->streams[IVTV_ENC_STREAM_TYPE_VBI];
struct ivtv_buffer *buf;
DEFINE_WAIT(wait);
*err = 0;
while (1) {
@ -258,13 +274,7 @@ static struct ivtv_buffer *ivtv_get_buffer(struct ivtv_stream *s, int non_block,
}
/* wait for more data to arrive */
mutex_unlock(&itv->serialize_lock);
prepare_to_wait(&s->waitq, &wait, TASK_INTERRUPTIBLE);
/* New buffers might have become available before we were added to the waitqueue */
if (!s->q_full.buffers)
schedule();
finish_wait(&s->waitq, &wait);
mutex_lock(&itv->serialize_lock);
ivtv_schedule(s);
if (signal_pending(current)) {
/* return if a signal was received */
IVTV_DEBUG_INFO("User stopped %s\n", s->name);
@ -533,6 +543,25 @@ int ivtv_start_decoding(struct ivtv_open_id *id, int speed)
return 0;
}
static int ivtv_schedule_dma(struct ivtv_stream *s)
{
struct ivtv *itv = s->itv;
int got_sig;
DEFINE_WAIT(wait);
lockdep_assert_held(&itv->serialize_lock);
mutex_unlock(&itv->serialize_lock);
prepare_to_wait(&itv->dma_waitq, &wait, TASK_INTERRUPTIBLE);
while (!(got_sig = signal_pending(current)) &&
test_bit(IVTV_F_S_DMA_PENDING, &s->s_flags))
schedule();
finish_wait(&itv->dma_waitq, &wait);
mutex_lock(&itv->serialize_lock);
return got_sig;
}
static ssize_t ivtv_write(struct file *filp, const char __user *user_buf, size_t count, loff_t *pos)
{
struct ivtv_open_id *id = fh2id(filp->private_data);
@ -544,7 +573,6 @@ static ssize_t ivtv_write(struct file *filp, const char __user *user_buf, size_t
int bytes_written = 0;
int mode;
int rc;
DEFINE_WAIT(wait);
IVTV_DEBUG_HI_FILE("write %zd bytes to %s\n", count, s->name);
@ -618,13 +646,7 @@ retry:
break;
if (filp->f_flags & O_NONBLOCK)
return -EAGAIN;
mutex_unlock(&itv->serialize_lock);
prepare_to_wait(&s->waitq, &wait, TASK_INTERRUPTIBLE);
/* New buffers might have become free before we were added to the waitqueue */
if (!s->q_free.buffers)
schedule();
finish_wait(&s->waitq, &wait);
mutex_lock(&itv->serialize_lock);
ivtv_schedule(s);
if (signal_pending(current)) {
IVTV_DEBUG_INFO("User stopped %s\n", s->name);
return -EINTR;
@ -674,20 +696,10 @@ retry:
if (test_bit(IVTV_F_S_NEEDS_DATA, &s->s_flags)) {
if (s->q_full.length >= itv->dma_data_req_size) {
int got_sig;
if (mode == OUT_YUV)
ivtv_yuv_setup_stream_frame(itv);
mutex_unlock(&itv->serialize_lock);
prepare_to_wait(&itv->dma_waitq, &wait, TASK_INTERRUPTIBLE);
while (!(got_sig = signal_pending(current)) &&
test_bit(IVTV_F_S_DMA_PENDING, &s->s_flags)) {
schedule();
}
finish_wait(&itv->dma_waitq, &wait);
mutex_lock(&itv->serialize_lock);
if (got_sig) {
if (ivtv_schedule_dma(s)) {
IVTV_DEBUG_INFO("User interrupted %s\n", s->name);
return -EINTR;
}

View File

@ -131,6 +131,8 @@ int ivtv_udma_setup(struct ivtv *itv, unsigned long ivtv_dest_addr,
/* Fill SG List with new values */
if (ivtv_udma_fill_sg_list(dma, &user_dma, 0) < 0) {
IVTV_DEBUG_WARN("%s: could not allocate bounce buffers for highmem userspace buffers\n",
__func__);
unpin_user_pages(dma->map, dma->page_count);
dma->page_count = 0;
return -ENOMEM;
@ -139,6 +141,12 @@ int ivtv_udma_setup(struct ivtv *itv, unsigned long ivtv_dest_addr,
/* Map SG List */
dma->SG_length = dma_map_sg(&itv->pdev->dev, dma->SGlist,
dma->page_count, DMA_TO_DEVICE);
if (!dma->SG_length) {
IVTV_DEBUG_WARN("%s: DMA map error, SG_length is 0\n", __func__);
unpin_user_pages(dma->map, dma->page_count);
dma->page_count = 0;
return -EINVAL;
}
/* Fill SG Array with new values */
ivtv_udma_fill_sg_array (dma, ivtv_dest_addr, 0, -1);

View File

@ -114,6 +114,12 @@ static int ivtv_yuv_prep_user_dma(struct ivtv *itv, struct ivtv_user_dma *dma,
}
dma->SG_length = dma_map_sg(&itv->pdev->dev, dma->SGlist,
dma->page_count, DMA_TO_DEVICE);
if (!dma->SG_length) {
IVTV_DEBUG_WARN("%s: DMA map error, SG_length is 0\n", __func__);
unpin_user_pages(dma->map, dma->page_count);
dma->page_count = 0;
return -EINVAL;
}
/* Fill SG Array with new values */
ivtv_udma_fill_sg_array(dma, y_buffer_offset, uv_buffer_offset, y_size);

View File

@ -104,6 +104,7 @@ MODULE_PARM_DESC(osd_xres,
"\t\t\tdefault 640");
MODULE_AUTHOR("Kevin Thayer, Chris Kennedy, Hans Verkuil, John Harvey, Ian Armstrong");
MODULE_DESCRIPTION("Conexant cx23415 framebuffer support");
MODULE_LICENSE("GPL");
/* --------------------------------------------------------------------- */
@ -281,10 +282,10 @@ static int ivtvfb_prep_dec_dma_to_device(struct ivtv *itv,
/* Map User DMA */
if (ivtv_udma_setup(itv, ivtv_dest_addr, userbuf, size_in_bytes) <= 0) {
mutex_unlock(&itv->udma.lock);
IVTVFB_WARN("ivtvfb_prep_dec_dma_to_device, Error with pin_user_pages: %d bytes, %d pages returned\n",
size_in_bytes, itv->udma.page_count);
IVTVFB_WARN("%s, Error in ivtv_udma_setup: %d bytes, %d pages returned\n",
__func__, size_in_bytes, itv->udma.page_count);
/* pin_user_pages must have failed completely */
/* pin_user_pages or DMA must have failed completely */
return -EIO;
}

View File

@ -116,7 +116,7 @@ static irqreturn_t hopper_irq_handler(int irq, void *dev_id)
if (stat & MANTIS_INT_RISCI) {
dprintk(MANTIS_DEBUG, 0, "<%s>", label[8]);
mantis->busy_block = (stat & MANTIS_INT_RISCSTAT) >> 28;
tasklet_schedule(&mantis->tasklet);
queue_work(system_bh_wq, &mantis->bh_work);
}
if (stat & MANTIS_INT_I2CDONE) {
dprintk(MANTIS_DEBUG, 0, "<%s>", label[9]);

View File

@ -125,7 +125,7 @@ static irqreturn_t mantis_irq_handler(int irq, void *dev_id)
if (stat & MANTIS_INT_RISCI) {
dprintk(MANTIS_DEBUG, 0, "<%s>", label[8]);
mantis->busy_block = (stat & MANTIS_INT_RISCSTAT) >> 28;
tasklet_schedule(&mantis->tasklet);
queue_work(system_bh_wq, &mantis->bh_work);
}
if (stat & MANTIS_INT_I2CDONE) {
dprintk(MANTIS_DEBUG, 0, "<%s>", label[9]);

View File

@ -125,7 +125,7 @@ struct mantis_pci {
__le32 *risc_cpu;
dma_addr_t risc_dma;
struct tasklet_struct tasklet;
struct work_struct bh_work;
spinlock_t intmask_lock;
struct i2c_adapter adapter;

View File

@ -200,9 +200,9 @@ void mantis_dma_stop(struct mantis_pci *mantis)
}
void mantis_dma_xfer(struct tasklet_struct *t)
void mantis_dma_xfer(struct work_struct *t)
{
struct mantis_pci *mantis = from_tasklet(mantis, t, tasklet);
struct mantis_pci *mantis = from_work(mantis, t, bh_work);
struct mantis_hwconfig *config = mantis->hwconfig;
while (mantis->last_block != mantis->busy_block) {

View File

@ -13,6 +13,6 @@ extern int mantis_dma_init(struct mantis_pci *mantis);
extern int mantis_dma_exit(struct mantis_pci *mantis);
extern void mantis_dma_start(struct mantis_pci *mantis);
extern void mantis_dma_stop(struct mantis_pci *mantis);
extern void mantis_dma_xfer(struct tasklet_struct *t);
extern void mantis_dma_xfer(struct work_struct *t);
#endif /* __MANTIS_DMA_H */

View File

@ -105,7 +105,7 @@ static int mantis_dvb_start_feed(struct dvb_demux_feed *dvbdmxfeed)
if (mantis->feeds == 1) {
dprintk(MANTIS_DEBUG, 1, "mantis start feed & dma");
mantis_dma_start(mantis);
tasklet_enable(&mantis->tasklet);
enable_and_queue_work(system_bh_wq, &mantis->bh_work);
}
return mantis->feeds;
@ -125,7 +125,7 @@ static int mantis_dvb_stop_feed(struct dvb_demux_feed *dvbdmxfeed)
mantis->feeds--;
if (mantis->feeds == 0) {
dprintk(MANTIS_DEBUG, 1, "mantis stop feed and dma");
tasklet_disable(&mantis->tasklet);
disable_work_sync(&mantis->bh_work);
mantis_dma_stop(mantis);
}
@ -205,8 +205,8 @@ int mantis_dvb_init(struct mantis_pci *mantis)
}
dvb_net_init(&mantis->dvb_adapter, &mantis->dvbnet, &mantis->demux.dmx);
tasklet_setup(&mantis->tasklet, mantis_dma_xfer);
tasklet_disable(&mantis->tasklet);
INIT_WORK(&mantis->bh_work, mantis_dma_xfer);
disable_work_sync(&mantis->bh_work);
if (mantis->hwconfig) {
result = config->frontend_init(mantis, mantis->fe);
if (result < 0) {
@ -235,7 +235,7 @@ int mantis_dvb_init(struct mantis_pci *mantis)
/* Error conditions .. */
err5:
tasklet_kill(&mantis->tasklet);
cancel_work_sync(&mantis->bh_work);
dvb_net_release(&mantis->dvbnet);
if (mantis->fe) {
dvb_unregister_frontend(mantis->fe);
@ -273,7 +273,7 @@ int mantis_dvb_exit(struct mantis_pci *mantis)
dvb_frontend_detach(mantis->fe);
}
tasklet_kill(&mantis->tasklet);
cancel_work_sync(&mantis->bh_work);
dvb_net_release(&mantis->dvbnet);
mantis->demux.dmx.remove_frontend(&mantis->demux.dmx, &mantis->fe_mem);

View File

@ -50,9 +50,9 @@ DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
/* nGene interrupt handler **************************************************/
/****************************************************************************/
static void event_tasklet(struct tasklet_struct *t)
static void event_bh_work(struct work_struct *t)
{
struct ngene *dev = from_tasklet(dev, t, event_tasklet);
struct ngene *dev = from_work(dev, t, event_bh_work);
while (dev->EventQueueReadIndex != dev->EventQueueWriteIndex) {
struct EVENT_BUFFER Event =
@ -68,9 +68,9 @@ static void event_tasklet(struct tasklet_struct *t)
}
}
static void demux_tasklet(struct tasklet_struct *t)
static void demux_bh_work(struct work_struct *t)
{
struct ngene_channel *chan = from_tasklet(chan, t, demux_tasklet);
struct ngene_channel *chan = from_work(chan, t, demux_bh_work);
struct device *pdev = &chan->dev->pci_dev->dev;
struct SBufferHeader *Cur = chan->nextBuffer;
@ -204,7 +204,7 @@ static irqreturn_t irq_handler(int irq, void *dev_id)
dev->EventQueueOverflowFlag = 1;
}
dev->EventBuffer->EventStatus &= ~0x80;
tasklet_schedule(&dev->event_tasklet);
queue_work(system_bh_wq, &dev->event_bh_work);
rc = IRQ_HANDLED;
}
@ -217,8 +217,8 @@ static irqreturn_t irq_handler(int irq, void *dev_id)
ngeneBuffer.SR.Flags & 0xC0) == 0x80) {
dev->channel[i].nextBuffer->
ngeneBuffer.SR.Flags |= 0x40;
tasklet_schedule(
&dev->channel[i].demux_tasklet);
queue_work(system_bh_wq,
&dev->channel[i].demux_bh_work);
rc = IRQ_HANDLED;
}
}
@ -1181,7 +1181,7 @@ static void ngene_init(struct ngene *dev)
struct device *pdev = &dev->pci_dev->dev;
int i;
tasklet_setup(&dev->event_tasklet, event_tasklet);
INIT_WORK(&dev->event_bh_work, event_bh_work);
memset_io(dev->iomem + 0xc000, 0x00, 0x220);
memset_io(dev->iomem + 0xc400, 0x00, 0x100);
@ -1395,7 +1395,7 @@ static void release_channel(struct ngene_channel *chan)
if (chan->running)
set_transfer(chan, 0);
tasklet_kill(&chan->demux_tasklet);
cancel_work_sync(&chan->demux_bh_work);
if (chan->ci_dev) {
dvb_unregister_device(chan->ci_dev);
@ -1445,7 +1445,7 @@ static int init_channel(struct ngene_channel *chan)
struct ngene_info *ni = dev->card_info;
int io = ni->io_type[nr];
tasklet_setup(&chan->demux_tasklet, demux_tasklet);
INIT_WORK(&chan->demux_bh_work, demux_bh_work);
chan->users = 0;
chan->type = io;
chan->mode = chan->type; /* for now only one mode */
@ -1649,7 +1649,7 @@ void ngene_remove(struct pci_dev *pdev)
struct ngene *dev = pci_get_drvdata(pdev);
int i;
tasklet_kill(&dev->event_tasklet);
cancel_work_sync(&dev->event_bh_work);
for (i = MAX_STREAM - 1; i >= 0; i--)
release_channel(&dev->channel[i]);
if (dev->ci.en)

View File

@ -16,6 +16,7 @@
#include <linux/scatterlist.h>
#include <linux/dvb/frontend.h>
#include <linux/workqueue.h>
#include <media/dmxdev.h>
#include <media/dvbdev.h>
@ -621,7 +622,7 @@ struct ngene_channel {
int users;
struct video_device *v4l_dev;
struct dvb_device *ci_dev;
struct tasklet_struct demux_tasklet;
struct work_struct demux_bh_work;
struct SBufferHeader *nextBuffer;
enum KSSTATE State;
@ -717,7 +718,7 @@ struct ngene {
struct EVENT_BUFFER EventQueue[EVENT_QUEUE_SIZE];
int EventQueueOverflowCount;
int EventQueueOverflowFlag;
struct tasklet_struct event_tasklet;
struct work_struct event_bh_work;
struct EVENT_BUFFER *EventBuffer;
int EventQueueWriteIndex;
int EventQueueReadIndex;

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