media updates for v6.13-rc1

-----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCAAdFiEE+QmuaPwR3wnBdVwACF8+vY7k4RUFAmc8Q80ACgkQCF8+vY7k
 4RX+3g//dMBSmu3uC9OiXyfw3aB8w62RMeieRxSVPMdkiacUm1J8HyzHnXPXIUn3
 tfBT9E/YbeFZ+PlrOXRDUi1i8jmN47VuwRe01rxxF/FdlYknC2eGH3Ug9DW90VBh
 wmZ1kSjyjizwDkKAm+Jc2xynTaX+iInJ4Kzp9RStDZPuaqj2Qzd1qVRk2FJwAYRh
 5dTpi0W1PexjxQXDIcnHi/tPapGLSP5PnrunrAJR0tYfp60wrKMaxTO36yJzbnDP
 MxkF8A+9dWtePRqoPWxPIvnOVu/+Twc730xkQp62qPvwEM2HZRtU7cgQFlWos6p/
 ijK2i6sAQslMhQ9oIyKlO7HpXX60rjE3XtdzEtGxBq6DyIqx1riN+OqJB2C4Cdsr
 2qUET8aTIisPURw1ecNAbthvLt8tljBe08/eX0GYaWFjALJx3Pds23ahH8hw295N
 o3SY5NaGmO9Tg6HzYLSwfBmxgGpWDuRic6PDCVKok5mS5D1+uV/tu8fQFiNiFNVe
 Okufjvo7HtZ3+rWR90b/Udpz/lBB/dceppnUX2iKevrG190VHxEwJ2pQKkfdH9ha
 LUZQajikiv5rbGxKIGrjrCnjrJ24TC2vCSPhkgOb1r91LUY4RUV61c3hZbH73rzQ
 2Ykwvmy+gpE4GEYiJRfSR6KlXdBruMa5FToLUHEK0uBMSlG5k7Q=
 =25BS
 -----END PGP SIGNATURE-----

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

Pull media updates from Mauro Carvalho Chehab:

 - removal of the old omap4iss media driver

 - mantis: remove orphan mantis_core.h

 - add support for Raspberypi CFE

 - uvc driver got a co-maintainer

 - main media tree moved to git://linuxtv.org/media.git

 - lots of driver cleanups, updates and fixes

* tag 'media/v6.13-1' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media: (233 commits)
  docs: media: update location of the media patches
  MAINTAINERS: update location of media main tree
  media: MAINTAINERS: Add Hans de Goede as USB VIDEO CLASS co-maintainer
  media: platform: samsung: s5p-jpeg: Remove deadcode
  media: qcom: camss: Add MSM8953 resources
  media: dt-bindings: Add qcom,msm8953-camss
  media: qcom: camss: implement pm domain ops for VFE v4.1
  media: platform: exynos4-is: Fix an OF node reference leak in fimc_md_is_isp_available
  media: adv7180: Also check for "adi,force-bt656-4"
  media: dt-bindings: adv7180: Document 'adi,force-bt656-4'
  media: mgb4: Fix inconsistent input/output alignment in loopback mode
  media: replace obsolete hans.verkuil@cisco.com alias
  Documentation: media: improve V4L2_CID_MIN_BUFFERS_FOR_*, doc
  media: vicodec: add V4L2_CID_MIN_BUFFERS_FOR_* controls
  media: atomisp: Add check for rgby_data memory allocation failure
  media: atomisp: remove redundant re-checking of err
  media: atomisp: Fix spelling errors reported by codespell
  media: atomisp: Remove License information boilerplate
  media: atomisp: Fix typos in comment
  media: atomisp: hmm_bo: Fix spelling errors in hmm_bo.h
  ...
This commit is contained in:
Linus Torvalds 2024-11-20 14:01:15 -08:00
commit 9f5a6a1fe6
1058 changed files with 9809 additions and 17215 deletions

View File

@ -37,6 +37,7 @@ Alexei Avshalom Lazar <quic_ailizaro@quicinc.com> <ailizaro@codeaurora.org>
Alexei Starovoitov <ast@kernel.org> <alexei.starovoitov@gmail.com> Alexei Starovoitov <ast@kernel.org> <alexei.starovoitov@gmail.com>
Alexei Starovoitov <ast@kernel.org> <ast@fb.com> Alexei Starovoitov <ast@kernel.org> <ast@fb.com>
Alexei Starovoitov <ast@kernel.org> <ast@plumgrid.com> Alexei Starovoitov <ast@kernel.org> <ast@plumgrid.com>
Alexey Klimov <alexey.klimov@linaro.org> <klimov.linux@gmail.com>
Alexey Makhalov <alexey.amakhalov@broadcom.com> <amakhalov@vmware.com> Alexey Makhalov <alexey.amakhalov@broadcom.com> <amakhalov@vmware.com>
Alex Elder <elder@kernel.org> Alex Elder <elder@kernel.org>
Alex Elder <elder@kernel.org> <aelder@sgi.com> Alex Elder <elder@kernel.org> <aelder@sgi.com>
@ -251,6 +252,8 @@ Guru Das Srinagesh <quic_gurus@quicinc.com> <gurus@codeaurora.org>
Gustavo Padovan <gustavo@las.ic.unicamp.br> Gustavo Padovan <gustavo@las.ic.unicamp.br>
Gustavo Padovan <padovan@profusion.mobi> Gustavo Padovan <padovan@profusion.mobi>
Hanjun Guo <guohanjun@huawei.com> <hanjun.guo@linaro.org> Hanjun Guo <guohanjun@huawei.com> <hanjun.guo@linaro.org>
Hans Verkuil <hverkuil@xs4all.nl> <hansverk@cisco.com>
Hans Verkuil <hverkuil@xs4all.nl> <hverkuil-cisco@xs4all.nl>
Heiko Carstens <hca@linux.ibm.com> <h.carstens@de.ibm.com> Heiko Carstens <hca@linux.ibm.com> <h.carstens@de.ibm.com>
Heiko Carstens <hca@linux.ibm.com> <heiko.carstens@de.ibm.com> Heiko Carstens <hca@linux.ibm.com> <heiko.carstens@de.ibm.com>
Heiko Stuebner <heiko@sntech.de> <heiko.stuebner@bqreaders.com> Heiko Stuebner <heiko@sntech.de> <heiko.stuebner@bqreaders.com>
@ -269,6 +272,7 @@ Jack Pham <quic_jackp@quicinc.com> <jackp@codeaurora.org>
Jaegeuk Kim <jaegeuk@kernel.org> <jaegeuk@google.com> Jaegeuk Kim <jaegeuk@kernel.org> <jaegeuk@google.com>
Jaegeuk Kim <jaegeuk@kernel.org> <jaegeuk.kim@samsung.com> Jaegeuk Kim <jaegeuk@kernel.org> <jaegeuk.kim@samsung.com>
Jaegeuk Kim <jaegeuk@kernel.org> <jaegeuk@motorola.com> Jaegeuk Kim <jaegeuk@kernel.org> <jaegeuk@motorola.com>
Jai Luthra <jai.luthra@linux.dev> <j-luthra@ti.com>
Jakub Kicinski <kuba@kernel.org> <jakub.kicinski@netronome.com> Jakub Kicinski <kuba@kernel.org> <jakub.kicinski@netronome.com>
James Bottomley <jejb@mulgrave.(none)> James Bottomley <jejb@mulgrave.(none)>
James Bottomley <jejb@titanic.il.steeleye.com> James Bottomley <jejb@titanic.il.steeleye.com>

View File

@ -15,7 +15,7 @@ Please notice, however, that, if:
you should use the main media development tree ``master`` branch: you should use the main media development tree ``master`` branch:
https://git.linuxtv.org/media_tree.git/ https://git.linuxtv.org/media.git/
In this case, you may find some useful information at the In this case, you may find some useful information at the
`LinuxTv wiki pages <https://linuxtv.org/wiki>`_: `LinuxTv wiki pages <https://linuxtv.org/wiki>`_:

View File

@ -1,62 +0,0 @@
.. SPDX-License-Identifier: GPL-2.0
OMAP4 ISS Driver
================
Author: Sergio Aguirre <sergio.a.aguirre@gmail.com>
Copyright (C) 2012, Texas Instruments
Introduction
------------
The OMAP44XX family of chips contains the Imaging SubSystem (a.k.a. ISS),
Which contains several components that can be categorized in 3 big groups:
- Interfaces (2 Interfaces: CSI2-A & CSI2-B/CCP2)
- ISP (Image Signal Processor)
- SIMCOP (Still Image Coprocessor)
For more information, please look in [#f1]_ for latest version of:
"OMAP4430 Multimedia Device Silicon Revision 2.x"
As of Revision AB, the ISS is described in detail in section 8.
This driver is supporting **only** the CSI2-A/B interfaces for now.
It makes use of the Media Controller framework [#f2]_, and inherited most of the
code from OMAP3 ISP driver (found under drivers/media/platform/ti/omap3isp/\*),
except that it doesn't need an IOMMU now for ISS buffers memory mapping.
Supports usage of MMAP buffers only (for now).
Tested platforms
----------------
- OMAP4430SDP, w/ ES2.1 GP & SEVM4430-CAM-V1-0 (Contains IMX060 & OV5640, in
which only the last one is supported, outputting YUV422 frames).
- TI Blaze MDP, w/ OMAP4430 ES2.2 EMU (Contains 1 IMX060 & 2 OV5650 sensors, in
which only the OV5650 are supported, outputting RAW10 frames).
- PandaBoard, Rev. A2, w/ OMAP4430 ES2.1 GP & OV adapter board, tested with
following sensors:
* OV5640
* OV5650
- Tested on mainline kernel:
http://git.kernel.org/?p=linux/kernel/git/torvalds/linux.git;a=summary
Tag: v3.3 (commit c16fa4f2ad19908a47c63d8fa436a1178438c7e7)
File list
---------
drivers/staging/media/omap4iss/
include/linux/platform_data/media/omap4iss.h
References
----------
.. [#f1] http://focus.ti.com/general/docs/wtbu/wtbudocumentcenter.tsp?navigationId=12037&templateId=6123#62
.. [#f2] http://lwn.net/Articles/420485/

View File

@ -0,0 +1,27 @@
digraph board {
rankdir=TB
n00000001 [label="{{<port0> 0} | csi2\n/dev/v4l-subdev0 | {<port1> 1 | <port2> 2 | <port3> 3 | <port4> 4}}", shape=Mrecord, style=filled, fillcolor=green]
n00000001:port1 -> n00000011 [style=dashed]
n00000001:port1 -> n00000007:port0
n00000001:port2 -> n00000015
n00000001:port2 -> n00000007:port0 [style=dashed]
n00000001:port3 -> n00000019 [style=dashed]
n00000001:port3 -> n00000007:port0 [style=dashed]
n00000001:port4 -> n0000001d [style=dashed]
n00000001:port4 -> n00000007:port0 [style=dashed]
n00000007 [label="{{<port0> 0 | <port1> 1} | pisp-fe\n/dev/v4l-subdev1 | {<port2> 2 | <port3> 3 | <port4> 4}}", shape=Mrecord, style=filled, fillcolor=green]
n00000007:port2 -> n00000021
n00000007:port3 -> n00000025 [style=dashed]
n00000007:port4 -> n00000029
n0000000d [label="{imx219 6-0010\n/dev/v4l-subdev2 | {<port0> 0}}", shape=Mrecord, style=filled, fillcolor=green]
n0000000d:port0 -> n00000001:port0 [style=bold]
n00000011 [label="rp1-cfe-csi2-ch0\n/dev/video0", shape=box, style=filled, fillcolor=yellow]
n00000015 [label="rp1-cfe-csi2-ch1\n/dev/video1", shape=box, style=filled, fillcolor=yellow]
n00000019 [label="rp1-cfe-csi2-ch2\n/dev/video2", shape=box, style=filled, fillcolor=yellow]
n0000001d [label="rp1-cfe-csi2-ch3\n/dev/video3", shape=box, style=filled, fillcolor=yellow]
n00000021 [label="rp1-cfe-fe-image0\n/dev/video4", shape=box, style=filled, fillcolor=yellow]
n00000025 [label="rp1-cfe-fe-image1\n/dev/video5", shape=box, style=filled, fillcolor=yellow]
n00000029 [label="rp1-cfe-fe-stats\n/dev/video6", shape=box, style=filled, fillcolor=yellow]
n0000002d [label="rp1-cfe-fe-config\n/dev/video7", shape=box, style=filled, fillcolor=yellow]
n0000002d -> n00000007:port1
}

View File

@ -0,0 +1,78 @@
.. SPDX-License-Identifier: GPL-2.0
============================================
Raspberry Pi PiSP Camera Front End (rp1-cfe)
============================================
The PiSP Camera Front End
=========================
The PiSP Camera Front End (CFE) is a module which combines a CSI-2 receiver with
a simple ISP, called the Front End (FE).
The CFE has four DMA engines and can write frames from four separate streams
received from the CSI-2 to the memory. One of those streams can also be routed
directly to the FE, which can do minimal image processing, write two versions
(e.g. non-scaled and downscaled versions) of the received frames to memory and
provide statistics of the received frames.
The FE registers are documented in the `Raspberry Pi Image Signal Processor
(ISP) Specification document
<https://datasheets.raspberrypi.com/camera/raspberry-pi-image-signal-processor-specification.pdf>`_,
and example code for FE can be found in `libpisp
<https://github.com/raspberrypi/libpisp>`_.
The rp1-cfe driver
==================
The Raspberry Pi PiSP Camera Front End (rp1-cfe) driver is located under
drivers/media/platform/raspberrypi/rp1-cfe. It uses the `V4L2 API` to register
a number of video capture and output devices, the `V4L2 subdev API` to register
subdevices for the CSI-2 received and the FE that connects the video devices in
a single media graph realized using the `Media Controller (MC) API`.
The media topology registered by the `rp1-cfe` driver, in this particular
example connected to an imx219 sensor, is the following one:
.. _rp1-cfe-topology:
.. kernel-figure:: raspberrypi-rp1-cfe.dot
:alt: Diagram of an example media pipeline topology
:align: center
The media graph contains the following video device nodes:
- rp1-cfe-csi2-ch0: capture device for the first CSI-2 stream
- rp1-cfe-csi2-ch1: capture device for the second CSI-2 stream
- rp1-cfe-csi2-ch2: capture device for the third CSI-2 stream
- rp1-cfe-csi2-ch3: capture device for the fourth CSI-2 stream
- rp1-cfe-fe-image0: capture device for the first FE output
- rp1-cfe-fe-image1: capture device for the second FE output
- rp1-cfe-fe-stats: capture device for the FE statistics
- rp1-cfe-fe-config: output device for FE configuration
rp1-cfe-csi2-chX
----------------
The rp1-cfe-csi2-chX capture devices are normal V4L2 capture devices which
can be used to capture video frames or metadata received from the CSI-2.
rp1-cfe-fe-image0, rp1-cfe-fe-image1
------------------------------------
The rp1-cfe-fe-image0 and rp1-cfe-fe-image1 capture devices are used to write
the processed frames to memory.
rp1-cfe-fe-stats
----------------
The format of the FE statistics buffer is defined by
:c:type:`pisp_statistics` C structure and the meaning of each parameter is
described in the `PiSP specification` document.
rp1-cfe-fe-config
-----------------
The format of the FE configuration buffer is defined by
:c:type:`pisp_fe_config` C structure and the meaning of each parameter is
described in the `PiSP specification` document.

View File

@ -67,7 +67,7 @@ Changes / Fixes
Please mail to linux-media AT vger.kernel.org unified diffs against Please mail to linux-media AT vger.kernel.org unified diffs against
the linux media git tree: the linux media git tree:
https://git.linuxtv.org/media_tree.git/ https://git.linuxtv.org/media.git/
This is done by committing a patch at a clone of the git tree and This is done by committing a patch at a clone of the git tree and
submitting the patch using ``git send-email``. Don't forget to submitting the patch using ``git send-email``. Don't forget to

View File

@ -20,12 +20,12 @@ Video4Linux (V4L) driver-specific documentation
ivtv ivtv
mgb4 mgb4
omap3isp omap3isp
omap4_camera
philips philips
qcom_camss qcom_camss
raspberrypi-pisp-be raspberrypi-pisp-be
rcar-fdp1 rcar-fdp1
rkisp1 rkisp1
raspberrypi-rp1-cfe
saa7134 saa7134
si470x si470x
si4713 si4713

View File

@ -39,6 +39,12 @@ properties:
maxItems: 1 maxItems: 1
adv,force-bt656-4: adv,force-bt656-4:
deprecated: true
description:
Indicates that the output is a BT.656-4 compatible stream.
type: boolean
adi,force-bt656-4:
description: description:
Indicates that the output is a BT.656-4 compatible stream. Indicates that the output is a BT.656-4 compatible stream.
type: boolean type: boolean

View File

@ -28,12 +28,6 @@ properties:
items: items:
- description: Reference to the mclk clock. - description: Reference to the mclk clock.
assigned-clocks:
maxItems: 1
assigned-clock-rates:
maxItems: 1
reset-gpios: reset-gpios:
description: Reference to the GPIO connected to the RESETB pin. Active low. description: Reference to the GPIO connected to the RESETB pin. Active low.
maxItems: 1 maxItems: 1
@ -82,8 +76,6 @@ required:
- compatible - compatible
- reg - reg
- clocks - clocks
- assigned-clocks
- assigned-clock-rates
- vddio-supply - vddio-supply
- vdda-supply - vdda-supply
- vddd-supply - vddd-supply
@ -105,8 +97,6 @@ examples:
pinctrl-names = "default"; pinctrl-names = "default";
pinctrl-0 = <&pinctrl_csi1>; pinctrl-0 = <&pinctrl_csi1>;
clocks = <&clk 0>; clocks = <&clk 0>;
assigned-clocks = <&clk 0>;
assigned-clock-rates = <25000000>;
vdda-supply = <&reg_camera_vdda>; vdda-supply = <&reg_camera_vdda>;
vddd-supply = <&reg_camera_vddd>; vddd-supply = <&reg_camera_vddd>;
vddio-supply = <&reg_camera_vddio>; vddio-supply = <&reg_camera_vddio>;

View File

@ -25,7 +25,10 @@ description: |
properties: properties:
compatible: compatible:
const: maxim,max96712 items:
- enum:
- maxim,max96712
- maxim,max96724
reg: reg:
description: I2C device address description: I2C device address

View File

@ -0,0 +1,120 @@
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
# Copyright (c) 2024 Linaro Ltd.
%YAML 1.2
---
$id: http://devicetree.org/schemas/media/i2c/ovti,ov08x40.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Omnivision OV08X40 CMOS Sensor
maintainers:
- Bryan O'Donoghue <bryan.odonoghue@linaro.org>
description: |
The Omnivision OV08X40 is a 9.2 megapixel, CMOS image sensor which supports:
- Automatic black level calibration (ABLC)
- Programmable controls for frame rate, mirror and flip, binning, cropping
and windowing
- Output formats 10-bit 4C RGB RAW, 10-bit Bayer RAW
- 4-lane MIPI D-PHY TX @ 1 Gbps per lane
- 2-lane MPIP D-PHY TX @ 2 Gbps per lane
- Dynamic defect pixel cancellation
- Standard SCCB command interface
allOf:
- $ref: /schemas/media/video-interface-devices.yaml#
properties:
compatible:
const: ovti,ov08x40
reg:
maxItems: 1
clocks:
maxItems: 1
avdd-supply:
description: Analogue circuit voltage supply.
dovdd-supply:
description: I/O circuit voltage supply.
dvdd-supply:
description: Digital circuit voltage supply.
reset-gpios:
description: Active low GPIO connected to XSHUTDOWN pad of the sensor.
port:
$ref: /schemas/graph.yaml#/$defs/port-base
additionalProperties: false
properties:
endpoint:
$ref: /schemas/media/video-interfaces.yaml#
additionalProperties: false
properties:
data-lanes:
oneOf:
- items:
- const: 1
- const: 2
- items:
- const: 1
- const: 2
- const: 3
- const: 4
link-frequencies: true
remote-endpoint: true
required:
- data-lanes
- link-frequencies
- remote-endpoint
required:
- compatible
- reg
- clocks
- port
unevaluatedProperties: false
examples:
- |
#include <dt-bindings/gpio/gpio.h>
i2c {
#address-cells = <1>;
#size-cells = <0>;
ov08x40: camera@36 {
compatible = "ovti,ov08x40";
reg = <0x36>;
reset-gpios = <&tlmm 111 GPIO_ACTIVE_LOW>;
pinctrl-names = "default";
pinctrl-0 = <&cam_rgb_defaultt>;
clocks = <&ov08x40_clk>;
assigned-clocks = <&ov08x40_clk>;
assigned-clock-parents = <&ov08x40_clk_parent>;
assigned-clock-rates = <19200000>;
avdd-supply = <&vreg_l7b_2p8>;
dvdd-supply = <&vreg_l7b_1p8>;
dovdd-supply = <&vreg_l3m_1p8>;
port {
ov08x40_ep: endpoint {
remote-endpoint = <&csiphy4_ep>;
data-lanes = <1 2 3 4>;
link-frequencies = /bits/ 64 <400000000>;
};
};
};
};
...

View File

@ -20,12 +20,6 @@ properties:
items: items:
- description: XVCLK Clock - description: XVCLK Clock
assigned-clocks:
maxItems: 1
assigned-clock-rates:
maxItems: 1
dvdd-supply: dvdd-supply:
description: Digital Domain Power Supply description: Digital Domain Power Supply
@ -68,8 +62,6 @@ required:
- compatible - compatible
- reg - reg
- clocks - clocks
- assigned-clocks
- assigned-clock-rates
- dvdd-supply - dvdd-supply
- dovdd-supply - dovdd-supply
- port - port
@ -93,9 +85,6 @@ examples:
avdd-supply = <&ov5648_avdd>; avdd-supply = <&ov5648_avdd>;
dovdd-supply = <&ov5648_dovdd>; dovdd-supply = <&ov5648_dovdd>;
clocks = <&ov5648_xvclk 0>; clocks = <&ov5648_xvclk 0>;
assigned-clocks = <&ov5648_xvclk 0>;
assigned-clock-rates = <24000000>;
ov5648_out: port { ov5648_out: port {
ov5648_out_mipi_csi2: endpoint { ov5648_out_mipi_csi2: endpoint {

View File

@ -20,12 +20,6 @@ properties:
items: items:
- description: EXTCLK Clock - description: EXTCLK Clock
assigned-clocks:
maxItems: 1
assigned-clock-rates:
maxItems: 1
dvdd-supply: dvdd-supply:
description: Digital Domain Power Supply description: Digital Domain Power Supply
@ -68,8 +62,6 @@ required:
- compatible - compatible
- reg - reg
- clocks - clocks
- assigned-clocks
- assigned-clock-rates
- dvdd-supply - dvdd-supply
- avdd-supply - avdd-supply
- dovdd-supply - dovdd-supply
@ -94,8 +86,6 @@ examples:
pinctrl-0 = <&csi_mclk_pin>; pinctrl-0 = <&csi_mclk_pin>;
clocks = <&ccu CLK_CSI_MCLK>; clocks = <&ccu CLK_CSI_MCLK>;
assigned-clocks = <&ccu CLK_CSI_MCLK>;
assigned-clock-rates = <24000000>;
avdd-supply = <&reg_ov8865_avdd>; avdd-supply = <&reg_ov8865_avdd>;
dovdd-supply = <&reg_ov8865_dovdd>; dovdd-supply = <&reg_ov8865_dovdd>;

View File

@ -27,10 +27,6 @@ properties:
description: I2C address description: I2C address
maxItems: 1 maxItems: 1
assigned-clocks: true
assigned-clock-parents: true
assigned-clock-rates: true
clocks: clocks:
description: Clock frequency from 6 to 27MHz description: Clock frequency from 6 to 27MHz
maxItems: 1 maxItems: 1
@ -87,10 +83,6 @@ examples:
reg = <0x60>; reg = <0x60>;
clocks = <&ov9282_clk>; clocks = <&ov9282_clk>;
assigned-clocks = <&ov9282_clk>;
assigned-clock-parents = <&ov9282_clk_parent>;
assigned-clock-rates = <24000000>;
port { port {
ov9282: endpoint { ov9282: endpoint {
remote-endpoint = <&cam>; remote-endpoint = <&cam>;

View File

@ -24,10 +24,6 @@ properties:
- sony,imx258 - sony,imx258
- sony,imx258-pdaf - sony,imx258-pdaf
assigned-clocks: true
assigned-clock-parents: true
assigned-clock-rates: true
clocks: clocks:
description: description:
Clock frequency from 6 to 27 MHz. Clock frequency from 6 to 27 MHz.
@ -125,9 +121,6 @@ examples:
reg = <0x6c>; reg = <0x6c>;
clocks = <&imx258_clk>; clocks = <&imx258_clk>;
assigned-clocks = <&imx258_clk>;
assigned-clock-rates = <19200000>;
port { port {
endpoint { endpoint {
remote-endpoint = <&csi1_ep>; remote-endpoint = <&csi1_ep>;

View File

@ -24,10 +24,6 @@ properties:
description: I2C address description: I2C address
maxItems: 1 maxItems: 1
assigned-clocks: true
assigned-clock-parents: true
assigned-clock-rates: true
clocks: clocks:
description: Clock frequency from 6 to 27 MHz, 37.125MHz, 74.25MHz description: Clock frequency from 6 to 27 MHz, 37.125MHz, 74.25MHz
maxItems: 1 maxItems: 1
@ -74,10 +70,6 @@ examples:
reg = <0x1a>; reg = <0x1a>;
clocks = <&imx334_clk>; clocks = <&imx334_clk>;
assigned-clocks = <&imx334_clk>;
assigned-clock-parents = <&imx334_clk_parent>;
assigned-clock-rates = <24000000>;
port { port {
imx334: endpoint { imx334: endpoint {
remote-endpoint = <&cam>; remote-endpoint = <&cam>;

View File

@ -24,10 +24,6 @@ properties:
description: I2C address description: I2C address
maxItems: 1 maxItems: 1
assigned-clocks: true
assigned-clock-parents: true
assigned-clock-rates: true
clocks: clocks:
description: Clock frequency from 6 to 27 MHz, 37.125MHz, 74.25MHz description: Clock frequency from 6 to 27 MHz, 37.125MHz, 74.25MHz
maxItems: 1 maxItems: 1
@ -86,10 +82,6 @@ examples:
reg = <0x1a>; reg = <0x1a>;
clocks = <&imx335_clk>; clocks = <&imx335_clk>;
assigned-clocks = <&imx335_clk>;
assigned-clock-parents = <&imx335_clk_parent>;
assigned-clock-rates = <24000000>;
avdd-supply = <&camera_vdda_2v9>; avdd-supply = <&camera_vdda_2v9>;
ovdd-supply = <&camera_vddo_1v8>; ovdd-supply = <&camera_vddo_1v8>;
dvdd-supply = <&camera_vddd_1v2>; dvdd-supply = <&camera_vddd_1v2>;

View File

@ -26,10 +26,6 @@ properties:
description: I2C address description: I2C address
maxItems: 1 maxItems: 1
assigned-clocks: true
assigned-clock-parents: true
assigned-clock-rates: true
clocks: clocks:
description: Clock frequency 6MHz, 12MHz, 18MHz, 24MHz or 27MHz description: Clock frequency 6MHz, 12MHz, 18MHz, 24MHz or 27MHz
maxItems: 1 maxItems: 1
@ -86,10 +82,6 @@ examples:
reg = <0x1a>; reg = <0x1a>;
clocks = <&imx412_clk>; clocks = <&imx412_clk>;
assigned-clocks = <&imx412_clk>;
assigned-clock-parents = <&imx412_clk_parent>;
assigned-clock-rates = <24000000>;
port { port {
imx412: endpoint { imx412: endpoint {
remote-endpoint = <&cam>; remote-endpoint = <&cam>;

View File

@ -0,0 +1,322 @@
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/media/qcom,msm8953-camss.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Qualcomm MSM8953 Camera Subsystem (CAMSS)
maintainers:
- Barnabas Czeman <barnabas.czeman@mainlining.org>
description:
The CAMSS IP is a CSI decoder and ISP present on Qualcomm platforms
properties:
compatible:
const: qcom,msm8953-camss
clocks:
minItems: 30
maxItems: 30
clock-names:
items:
- const: ahb
- const: csi0
- const: csi0_ahb
- const: csi0_phy
- const: csi0_pix
- const: csi0_rdi
- const: csi1
- const: csi1_ahb
- const: csi1_phy
- const: csi1_pix
- const: csi1_rdi
- const: csi2
- const: csi2_ahb
- const: csi2_phy
- const: csi2_pix
- const: csi2_rdi
- const: csi_vfe0
- const: csi_vfe1
- const: csiphy0_timer
- const: csiphy1_timer
- const: csiphy2_timer
- const: ispif_ahb
- const: micro_ahb
- const: top_ahb
- const: vfe0
- const: vfe0_ahb
- const: vfe0_axi
- const: vfe1
- const: vfe1_ahb
- const: vfe1_axi
interrupts:
minItems: 9
maxItems: 9
interrupt-names:
items:
- const: csid0
- const: csid1
- const: csid2
- const: csiphy0
- const: csiphy1
- const: csiphy2
- const: ispif
- const: vfe0
- const: vfe1
iommus:
maxItems: 1
power-domains:
items:
- description: VFE0 GDSC - Video Front End, Global Distributed Switch Controller.
- description: VFE1 GDSC - Video Front End, Global Distributed Switch Controller.
power-domain-names:
items:
- const: vfe0
- const: vfe1
ports:
$ref: /schemas/graph.yaml#/properties/ports
description:
CSI input ports.
properties:
port@0:
$ref: /schemas/graph.yaml#/$defs/port-base
unevaluatedProperties: false
description:
Input port for receiving CSI data.
properties:
endpoint:
$ref: video-interfaces.yaml#
unevaluatedProperties: false
properties:
data-lanes:
description:
An array of physical data lanes indexes.
Position of an entry determines the logical
lane number, while the value of an entry
indicates physical lane index. Lane swapping
is supported. Physical lane indexes;
0, 2, 3, 4.
minItems: 1
maxItems: 4
required:
- data-lanes
port@1:
$ref: /schemas/graph.yaml#/$defs/port-base
unevaluatedProperties: false
description:
Input port for receiving CSI data.
properties:
endpoint:
$ref: video-interfaces.yaml#
unevaluatedProperties: false
properties:
data-lanes:
minItems: 1
maxItems: 4
required:
- data-lanes
port@2:
$ref: /schemas/graph.yaml#/$defs/port-base
unevaluatedProperties: false
description:
Input port for receiving CSI data.
properties:
endpoint:
$ref: video-interfaces.yaml#
unevaluatedProperties: false
properties:
data-lanes:
minItems: 1
maxItems: 4
required:
- data-lanes
reg:
minItems: 13
maxItems: 13
reg-names:
items:
- const: csi_clk_mux
- const: csid0
- const: csid1
- const: csid2
- const: csiphy0
- const: csiphy0_clk_mux
- const: csiphy1
- const: csiphy1_clk_mux
- const: csiphy2
- const: csiphy2_clk_mux
- const: ispif
- const: vfe0
- const: vfe1
vdda-supply:
description:
Definition of the regulator used as analog power supply.
required:
- compatible
- reg
- reg-names
- clocks
- clock-names
- interrupts
- interrupt-names
- iommus
- power-domains
- power-domain-names
- vdda-supply
additionalProperties: false
examples:
- |
#include <dt-bindings/interrupt-controller/arm-gic.h>
#include <dt-bindings/clock/qcom,gcc-msm8953.h>
camss: camss@1b00020 {
compatible = "qcom,msm8953-camss";
reg = <0x1b00020 0x10>,
<0x1b30000 0x100>,
<0x1b30400 0x100>,
<0x1b30800 0x100>,
<0x1b34000 0x1000>,
<0x1b00030 0x4>,
<0x1b35000 0x1000>,
<0x1b00038 0x4>,
<0x1b36000 0x1000>,
<0x1b00040 0x4>,
<0x1b31000 0x500>,
<0x1b10000 0x1000>,
<0x1b14000 0x1000>;
reg-names = "csi_clk_mux",
"csid0",
"csid1",
"csid2",
"csiphy0",
"csiphy0_clk_mux",
"csiphy1",
"csiphy1_clk_mux",
"csiphy2",
"csiphy2_clk_mux",
"ispif",
"vfe0",
"vfe1";
clocks = <&gcc GCC_CAMSS_AHB_CLK>,
<&gcc GCC_CAMSS_CSI0_CLK>,
<&gcc GCC_CAMSS_CSI0_AHB_CLK>,
<&gcc GCC_CAMSS_CSI0PHY_CLK>,
<&gcc GCC_CAMSS_CSI0PIX_CLK>,
<&gcc GCC_CAMSS_CSI0RDI_CLK>,
<&gcc GCC_CAMSS_CSI1_CLK>,
<&gcc GCC_CAMSS_CSI1_AHB_CLK>,
<&gcc GCC_CAMSS_CSI1PHY_CLK>,
<&gcc GCC_CAMSS_CSI1PIX_CLK>,
<&gcc GCC_CAMSS_CSI1RDI_CLK>,
<&gcc GCC_CAMSS_CSI2_CLK>,
<&gcc GCC_CAMSS_CSI2_AHB_CLK>,
<&gcc GCC_CAMSS_CSI2PHY_CLK>,
<&gcc GCC_CAMSS_CSI2PIX_CLK>,
<&gcc GCC_CAMSS_CSI2RDI_CLK>,
<&gcc GCC_CAMSS_CSI_VFE0_CLK>,
<&gcc GCC_CAMSS_CSI_VFE1_CLK>,
<&gcc GCC_CAMSS_CSI0PHYTIMER_CLK>,
<&gcc GCC_CAMSS_CSI1PHYTIMER_CLK>,
<&gcc GCC_CAMSS_CSI2PHYTIMER_CLK>,
<&gcc GCC_CAMSS_ISPIF_AHB_CLK>,
<&gcc GCC_CAMSS_MICRO_AHB_CLK>,
<&gcc GCC_CAMSS_TOP_AHB_CLK>,
<&gcc GCC_CAMSS_VFE0_CLK>,
<&gcc GCC_CAMSS_VFE0_AHB_CLK>,
<&gcc GCC_CAMSS_VFE0_AXI_CLK>,
<&gcc GCC_CAMSS_VFE1_CLK>,
<&gcc GCC_CAMSS_VFE1_AHB_CLK>,
<&gcc GCC_CAMSS_VFE1_AXI_CLK>;
clock-names = "ahb",
"csi0",
"csi0_ahb",
"csi0_phy",
"csi0_pix",
"csi0_rdi",
"csi1",
"csi1_ahb",
"csi1_phy",
"csi1_pix",
"csi1_rdi",
"csi2",
"csi2_ahb",
"csi2_phy",
"csi2_pix",
"csi2_rdi",
"csi_vfe0",
"csi_vfe1",
"csiphy0_timer",
"csiphy1_timer",
"csiphy2_timer",
"ispif_ahb",
"micro_ahb",
"top_ahb",
"vfe0",
"vfe0_ahb",
"vfe0_axi",
"vfe1",
"vfe1_ahb",
"vfe1_axi";
interrupts = <GIC_SPI 51 IRQ_TYPE_EDGE_RISING>,
<GIC_SPI 52 IRQ_TYPE_EDGE_RISING>,
<GIC_SPI 153 IRQ_TYPE_EDGE_RISING>,
<GIC_SPI 78 IRQ_TYPE_EDGE_RISING>,
<GIC_SPI 79 IRQ_TYPE_EDGE_RISING>,
<GIC_SPI 315 IRQ_TYPE_EDGE_RISING>,
<GIC_SPI 55 IRQ_TYPE_EDGE_RISING>,
<GIC_SPI 57 IRQ_TYPE_EDGE_RISING>,
<GIC_SPI 29 IRQ_TYPE_EDGE_RISING>;
interrupt-names = "csid0",
"csid1",
"csid2",
"csiphy0",
"csiphy1",
"csiphy2",
"ispif",
"vfe0",
"vfe1";
iommus = <&apps_iommu 0x14>;
power-domains = <&gcc VFE0_GDSC>,
<&gcc VFE1_GDSC>;
power-domain-names = "vfe0", "vfe1";
vdda-supply = <&reg_2v8>;
ports {
#address-cells = <1>;
#size-cells = <0>;
};
};

View File

@ -0,0 +1,93 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/media/raspberrypi,rp1-cfe.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Raspberry Pi PiSP Camera Front End
maintainers:
- Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
- Raspberry Pi Kernel Maintenance <kernel-list@raspberrypi.com>
description: |
The Raspberry Pi PiSP Camera Front End is a module in Raspberrypi 5's RP1 I/O
controller, that contains:
- MIPI D-PHY
- MIPI CSI-2 receiver
- Simple image processor (called PiSP Front End, or FE)
The FE documentation is available at:
https://datasheets.raspberrypi.com/camera/raspberry-pi-image-signal-processor-specification.pdf
The PHY and CSI-2 receiver part have no public documentation.
properties:
compatible:
items:
- const: raspberrypi,rp1-cfe
reg:
items:
- description: CSI-2 registers
- description: D-PHY registers
- description: MIPI CFG (a simple top-level mux) registers
- description: FE registers
interrupts:
maxItems: 1
clocks:
maxItems: 1
port:
$ref: /schemas/graph.yaml#/$defs/port-base
additionalProperties: false
description: CSI-2 RX Port
properties:
endpoint:
$ref: video-interfaces.yaml#
unevaluatedProperties: false
properties:
data-lanes:
minItems: 1
maxItems: 4
required:
- data-lanes
required:
- compatible
- reg
- interrupts
- clocks
additionalProperties: false
examples:
- |
rp1 {
#address-cells = <2>;
#size-cells = <2>;
csi@110000 {
compatible = "raspberrypi,rp1-cfe";
reg = <0xc0 0x40110000 0x0 0x100>,
<0xc0 0x40114000 0x0 0x100>,
<0xc0 0x40120000 0x0 0x100>,
<0xc0 0x40124000 0x0 0x1000>;
interrupts = <42>;
clocks = <&rp1_clocks>;
port {
csi_ep: endpoint {
remote-endpoint = <&cam_endpoint>;
data-lanes = <1 2>;
};
};
};
};

View File

@ -32,6 +32,7 @@ properties:
- renesas,r8a77990-csi2 # R-Car E3 - renesas,r8a77990-csi2 # R-Car E3
- renesas,r8a779a0-csi2 # R-Car V3U - renesas,r8a779a0-csi2 # R-Car V3U
- renesas,r8a779g0-csi2 # R-Car V4H - renesas,r8a779g0-csi2 # R-Car V4H
- renesas,r8a779h0-csi2 # R-Car V4M
reg: reg:
maxItems: 1 maxItems: 1

View File

@ -22,6 +22,8 @@ properties:
- enum: - enum:
- renesas,r8a779a0-isp # V3U - renesas,r8a779a0-isp # V3U
- renesas,r8a779g0-isp # V4H - renesas,r8a779g0-isp # V4H
- renesas,r8a779h0-isp # V4M
- const: renesas,rcar-gen4-isp # Generic R-Car Gen4
reg: reg:
maxItems: 1 maxItems: 1
@ -116,7 +118,7 @@ examples:
#include <dt-bindings/power/r8a779a0-sysc.h> #include <dt-bindings/power/r8a779a0-sysc.h>
isp1: isp@fed20000 { isp1: isp@fed20000 {
compatible = "renesas,r8a779a0-isp"; compatible = "renesas,r8a779a0-isp", "renesas,rcar-gen4-isp";
reg = <0xfed20000 0x10000>; reg = <0xfed20000 0x10000>;
interrupts = <GIC_SPI 155 IRQ_TYPE_LEVEL_HIGH>; interrupts = <GIC_SPI 155 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&cpg CPG_MOD 613>; clocks = <&cpg CPG_MOD 613>;

View File

@ -13,7 +13,7 @@ description: |
CSI_RX_IF section. CSI_RX_IF section.
maintainers: maintainers:
- Jai Luthra <j-luthra@ti.com> - Jai Luthra <jai.luthra@linux.dev>
properties: properties:
compatible: compatible:

View File

@ -81,10 +81,10 @@ restart when the system is resumed. This requires coordination between the
camera sensor and the rest of the camera pipeline. Bridge drivers are camera sensor and the rest of the camera pipeline. Bridge drivers are
responsible for this coordination, and instruct camera sensors to stop and responsible for this coordination, and instruct camera sensors to stop and
restart streaming by calling the appropriate subdev operations restart streaming by calling the appropriate subdev operations
(``.s_stream()``, ``.enable_streams()`` or ``.disable_streams()``). Camera (``.enable_streams()`` or ``.disable_streams()``). Camera sensor drivers shall
sensor drivers shall therefore **not** keep track of the streaming state to therefore **not** keep track of the streaming state to stop streaming in the PM
stop streaming in the PM suspend handler and restart it in the resume handler. suspend handler and restart it in the resume handler. Drivers should in general
Drivers should in general not implement the system PM handlers. not implement the system PM handlers.
Camera sensor drivers shall **not** implement the subdev ``.s_power()`` Camera sensor drivers shall **not** implement the subdev ``.s_power()``
operation, as it is deprecated. While this operation is implemented in some operation, as it is deprecated. While this operation is implemented in some

View File

@ -98,21 +98,6 @@ The IPU6 driver exports its own DMA operations. The IPU6 driver will update the
page table entries for each DMA operation and invalidate the MMU TLB after each page table entries for each DMA operation and invalidate the MMU TLB after each
unmap and free. unmap and free.
.. code-block:: none
const struct dma_map_ops ipu6_dma_ops = {
.alloc = ipu6_dma_alloc,
.free = ipu6_dma_free,
.mmap = ipu6_dma_mmap,
.map_sg = ipu6_dma_map_sg,
.unmap_sg = ipu6_dma_unmap_sg,
...
};
.. Note:: IPU6 MMU works behind IOMMU so for each IPU6 DMA ops, driver will call
generic PCI DMA ops to ask IOMMU to do the additional mapping if VT-d
enabled.
Firmware file format Firmware file format
==================== ====================

View File

@ -49,11 +49,14 @@ Link frequency
The :ref:`V4L2_CID_LINK_FREQ <v4l2-cid-link-freq>` control is used to tell the The :ref:`V4L2_CID_LINK_FREQ <v4l2-cid-link-freq>` control is used to tell the
receiver the frequency of the bus (i.e. it is not the same as the symbol rate). receiver the frequency of the bus (i.e. it is not the same as the symbol rate).
``.s_stream()`` callback ``.enable_streams()`` and ``.disable_streams()`` callbacks
^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The struct struct v4l2_subdev_video_ops->s_stream() callback is used by the The struct v4l2_subdev_pad_ops->enable_streams() and struct
receiver driver to control the transmitter driver's streaming state. v4l2_subdev_pad_ops->disable_streams() callbacks are used by the receiver driver
to control the transmitter driver's streaming state. These callbacks may not be
called directly, but by using ``v4l2_subdev_enable_streams()`` and
``v4l2_subdev_disable_streams()``.
CSI-2 transmitter drivers CSI-2 transmitter drivers
@ -127,7 +130,7 @@ Stopping the transmitter
^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^
A transmitter stops sending the stream of images as a result of A transmitter stops sending the stream of images as a result of
calling the ``.s_stream()`` callback. Some transmitters may stop the calling the ``.disable_streams()`` callback. Some transmitters may stop the
stream at a frame boundary whereas others stop immediately, stream at a frame boundary whereas others stop immediately,
effectively leaving the current frame unfinished. The receiver driver effectively leaving the current frame unfinished. The receiver driver
should not make assumptions either way, but function properly in both should not make assumptions either way, but function properly in both

View File

@ -27,7 +27,7 @@ Arguments
File descriptor returned by open(). File descriptor returned by open().
``duty_cycle`` ``duty_cycle``
Duty cicle, describing the pulse width in percent (from 1 to 99) of Duty cycle, describing the pulse width in percent (from 1 to 99) of
the total cycle. Values 0 and 100 are reserved. the total cycle. Values 0 and 100 are reserved.
Description Description

View File

@ -290,13 +290,15 @@ Control IDs
This is a read-only control that can be read by the application and This is a read-only control that can be read by the application and
used as a hint to determine the number of CAPTURE buffers to pass to used as a hint to determine the number of CAPTURE buffers to pass to
REQBUFS. The value is the minimum number of CAPTURE buffers that is REQBUFS. The value is the minimum number of CAPTURE buffers that is
necessary for hardware to work. necessary for hardware to work. This control is required for stateful
decoders.
``V4L2_CID_MIN_BUFFERS_FOR_OUTPUT`` ``(integer)`` ``V4L2_CID_MIN_BUFFERS_FOR_OUTPUT`` ``(integer)``
This is a read-only control that can be read by the application and This is a read-only control that can be read by the application and
used as a hint to determine the number of OUTPUT buffers to pass to used as a hint to determine the number of OUTPUT buffers to pass to
REQBUFS. The value is the minimum number of OUTPUT buffers that is REQBUFS. The value is the minimum number of OUTPUT buffers that is
necessary for hardware to work. necessary for hardware to work. This control is required for stateful
encoders.
.. _v4l2-alpha-component: .. _v4l2-alpha-component:

View File

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

View File

@ -0,0 +1,39 @@
.. SPDX-License-Identifier: GPL-2.0
.. _v4l2-meta-fmt-rpi-fe-cfg:
************************
V4L2_META_FMT_RPI_FE_CFG
************************
Raspberry Pi PiSP Front End configuration format
================================================
The Raspberry Pi PiSP Front End image signal processor is configured by
userspace by providing a buffer of configuration parameters to the
`rp1-cfe-fe-config` output video device node using the
:c:type:`v4l2_meta_format` interface.
The `Raspberry Pi PiSP technical specification
<https://datasheets.raspberrypi.com/camera/raspberry-pi-image-signal-processor-specification.pdf>`_
provide detailed description of the Front End configuration and programming
model.
.. _v4l2-meta-fmt-rpi-fe-stats:
**************************
V4L2_META_FMT_RPI_FE_STATS
**************************
Raspberry Pi PiSP Front End statistics format
=============================================
The Raspberry Pi PiSP Front End image signal processor provides statistics data
by writing to a buffer provided via the `rp1-cfe-fe-stats` capture video device
node using the
:c:type:`v4l2_meta_format` interface.
The `Raspberry Pi PiSP technical specification
<https://datasheets.raspberrypi.com/camera/raspberry-pi-image-signal-processor-specification.pdf>`_
provide detailed description of the Front End configuration and programming
model.

View File

@ -0,0 +1,73 @@
.. SPDX-License-Identifier: GFDL-1.1-no-invariants-or-later
.. _V4L2-PIX-FMT-Y16I:
**************************
V4L2_PIX_FMT_Y16I ('Y16I')
**************************
Interleaved grey-scale image, e.g. from a stereo-pair
Description
===========
This is a grey-scale image with a depth of 16 bits per pixel, but with pixels
from 2 sources interleaved and unpacked. Each pixel is stored in a 16-bit word
in the little-endian order. The first pixel is from the left source.
**Pixel unpacked representation.**
Left/Right pixels 16-bit unpacked - 16-bit for each interleaved pixel.
.. flat-table::
:header-rows: 0
:stub-columns: 0
* - Y'\ :sub:`0L[7:0]`
- Y'\ :sub:`0L[15:8]`
- Y'\ :sub:`0R[7:0]`
- Y'\ :sub:`0R[15:8]`
**Byte Order.**
Each cell is one byte.
.. flat-table::
:header-rows: 0
:stub-columns: 0
* - start + 0:
- Y'\ :sub:`00Llow`
- Y'\ :sub:`00Lhigh`
- Y'\ :sub:`00Rlow`
- Y'\ :sub:`00Rhigh`
- Y'\ :sub:`01Llow`
- Y'\ :sub:`01Lhigh`
- Y'\ :sub:`01Rlow`
- Y'\ :sub:`01Rhigh`
* - start + 8:
- Y'\ :sub:`10Llow`
- Y'\ :sub:`10Lhigh`
- Y'\ :sub:`10Rlow`
- Y'\ :sub:`10Rhigh`
- Y'\ :sub:`11Llow`
- Y'\ :sub:`11Lhigh`
- Y'\ :sub:`11Rlow`
- Y'\ :sub:`11Rhigh`
* - start + 16:
- Y'\ :sub:`20Llow`
- Y'\ :sub:`20Lhigh`
- Y'\ :sub:`20Rlow`
- Y'\ :sub:`20Rhigh`
- Y'\ :sub:`21Llow`
- Y'\ :sub:`21Lhigh`
- Y'\ :sub:`21Rlow`
- Y'\ :sub:`21Rhigh`
* - start + 24:
- Y'\ :sub:`30Llow`
- Y'\ :sub:`30Lhigh`
- Y'\ :sub:`30Rlow`
- Y'\ :sub:`30Rhigh`
- Y'\ :sub:`31Llow`
- Y'\ :sub:`31Lhigh`
- Y'\ :sub:`31Rlow`
- Y'\ :sub:`31Rhigh`

View File

@ -86,6 +86,16 @@ the ``mbus_code`` field is handled differently:
- ``index`` - ``index``
- Number of the format in the enumeration, set by the application. - Number of the format in the enumeration, set by the application.
This is in no way related to the ``pixelformat`` field. This is in no way related to the ``pixelformat`` field.
When the index is ORed with ``V4L2_FMTDESC_FLAG_ENUM_ALL`` the
driver clears the flag and enumerates all the possible formats,
ignoring any limitations from the current configuration. Drivers
which do not support this flag always return an ``EINVAL``
error code without clearing this flag.
Formats enumerated when using ``V4L2_FMTDESC_FLAG_ENUM_ALL`` flag
shouldn't be used when calling :c:func:`VIDIOC_ENUM_FRAMESIZES`
or :c:func:`VIDIOC_ENUM_FRAMEINTERVALS`.
``V4L2_FMTDESC_FLAG_ENUM_ALL`` should only be used by drivers that
can return different format list depending on this flag.
* - __u32 * - __u32
- ``type`` - ``type``
- Type of the data stream, set by the application. Only these types - Type of the data stream, set by the application. Only these types
@ -234,6 +244,12 @@ the ``mbus_code`` field is handled differently:
valid. The buffer consists of ``height`` lines, each having ``width`` valid. The buffer consists of ``height`` lines, each having ``width``
Data Units of data and the offset (in bytes) between the beginning of Data Units of data and the offset (in bytes) between the beginning of
each two consecutive lines is ``bytesperline``. each two consecutive lines is ``bytesperline``.
* - ``V4L2_FMTDESC_FLAG_ENUM_ALL``
- 0x80000000
- When the applications ORs ``index`` with ``V4L2_FMTDESC_FLAG_ENUM_ALL`` flag
the driver enumerates all the possible pixel formats without taking care
of any already set configuration. Drivers which do not support this flag,
always return ``EINVAL`` without clearing this flag.
Return Value Return Value
============ ============

View File

@ -269,5 +269,6 @@ image.
pixfmt-yuv-luma pixfmt-yuv-luma
pixfmt-y8i pixfmt-y8i
pixfmt-y12i pixfmt-y12i
pixfmt-y16i
pixfmt-uv8 pixfmt-uv8
pixfmt-m420 pixfmt-m420

View File

@ -217,6 +217,7 @@ replace define V4L2_FMT_FLAG_CSC_YCBCR_ENC fmtdesc-flags
replace define V4L2_FMT_FLAG_CSC_HSV_ENC fmtdesc-flags replace define V4L2_FMT_FLAG_CSC_HSV_ENC fmtdesc-flags
replace define V4L2_FMT_FLAG_CSC_QUANTIZATION fmtdesc-flags replace define V4L2_FMT_FLAG_CSC_QUANTIZATION fmtdesc-flags
replace define V4L2_FMT_FLAG_META_LINE_BASED fmtdesc-flags replace define V4L2_FMT_FLAG_META_LINE_BASED fmtdesc-flags
replace define V4L2_FMTDESC_FLAG_ENUM_ALL fmtdesc-flags
# V4L2 timecode types # V4L2 timecode types
replace define V4L2_TC_TYPE_24FPS timecode-type replace define V4L2_TC_TYPE_24FPS timecode-type

File diff suppressed because it is too large Load Diff

View File

@ -438,6 +438,6 @@ static void __exit cec_devnode_exit(void)
subsys_initcall(cec_devnode_init); subsys_initcall(cec_devnode_init);
module_exit(cec_devnode_exit) module_exit(cec_devnode_exit)
MODULE_AUTHOR("Hans Verkuil <hans.verkuil@cisco.com>"); MODULE_AUTHOR("Hans Verkuil <hansverk@cisco.com>");
MODULE_DESCRIPTION("Device node registration for cec drivers"); MODULE_DESCRIPTION("Device node registration for cec drivers");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");

View File

@ -99,7 +99,7 @@ config CEC_TEGRA
config CEC_SECO config CEC_SECO
tristate "SECO Boards HDMI CEC driver" tristate "SECO Boards HDMI CEC driver"
depends on X86 || COMPILE_TEST depends on X86 || (COMPILE_TEST && HAS_IOPORT)
depends on PCI && DMI depends on PCI && DMI
select CEC_CORE select CEC_CORE
select CEC_NOTIFIER select CEC_NOTIFIER

View File

@ -279,7 +279,7 @@ MODULE_DEVICE_TABLE(of, cec_gpio_match);
static struct platform_driver cec_gpio_pdrv = { static struct platform_driver cec_gpio_pdrv = {
.probe = cec_gpio_probe, .probe = cec_gpio_probe,
.remove_new = cec_gpio_remove, .remove = cec_gpio_remove,
.driver = { .driver = {
.name = "cec-gpio", .name = "cec-gpio",
.of_match_table = cec_gpio_match, .of_match_table = cec_gpio_match,
@ -288,6 +288,6 @@ static struct platform_driver cec_gpio_pdrv = {
module_platform_driver(cec_gpio_pdrv); module_platform_driver(cec_gpio_pdrv);
MODULE_AUTHOR("Hans Verkuil <hans.verkuil@cisco.com>"); MODULE_AUTHOR("Hans Verkuil <hansverk@cisco.com>");
MODULE_LICENSE("GPL v2"); MODULE_LICENSE("GPL v2");
MODULE_DESCRIPTION("CEC GPIO driver"); MODULE_DESCRIPTION("CEC GPIO driver");

View File

@ -582,7 +582,7 @@ MODULE_DEVICE_TABLE(platform, cros_ec_cec_id);
static struct platform_driver cros_ec_cec_driver = { static struct platform_driver cros_ec_cec_driver = {
.probe = cros_ec_cec_probe, .probe = cros_ec_cec_probe,
.remove_new = cros_ec_cec_remove, .remove = cros_ec_cec_remove,
.driver = { .driver = {
.name = DRV_NAME, .name = DRV_NAME,
.pm = &cros_ec_cec_pm_ops, .pm = &cros_ec_cec_pm_ops,

View File

@ -778,7 +778,7 @@ MODULE_DEVICE_TABLE(of, meson_ao_cec_g12a_of_match);
static struct platform_driver meson_ao_cec_g12a_driver = { static struct platform_driver meson_ao_cec_g12a_driver = {
.probe = meson_ao_cec_g12a_probe, .probe = meson_ao_cec_g12a_probe,
.remove_new = meson_ao_cec_g12a_remove, .remove = meson_ao_cec_g12a_remove,
.driver = { .driver = {
.name = "meson-ao-cec-g12a", .name = "meson-ao-cec-g12a",
.of_match_table = of_match_ptr(meson_ao_cec_g12a_of_match), .of_match_table = of_match_ptr(meson_ao_cec_g12a_of_match),

View File

@ -714,7 +714,7 @@ MODULE_DEVICE_TABLE(of, meson_ao_cec_of_match);
static struct platform_driver meson_ao_cec_driver = { static struct platform_driver meson_ao_cec_driver = {
.probe = meson_ao_cec_probe, .probe = meson_ao_cec_probe,
.remove_new = meson_ao_cec_remove, .remove = meson_ao_cec_remove,
.driver = { .driver = {
.name = "meson-ao-cec", .name = "meson-ao-cec",
.of_match_table = meson_ao_cec_of_match, .of_match_table = meson_ao_cec_of_match,

View File

@ -294,7 +294,7 @@ MODULE_DEVICE_TABLE(of, s5p_cec_match);
static struct platform_driver s5p_cec_pdrv = { static struct platform_driver s5p_cec_pdrv = {
.probe = s5p_cec_probe, .probe = s5p_cec_probe,
.remove_new = s5p_cec_remove, .remove = s5p_cec_remove,
.driver = { .driver = {
.name = CEC_NAME, .name = CEC_NAME,
.of_match_table = s5p_cec_match, .of_match_table = s5p_cec_match,

View File

@ -778,7 +778,7 @@ static struct platform_driver secocec_driver = {
.pm = SECOCEC_PM_OPS, .pm = SECOCEC_PM_OPS,
}, },
.probe = secocec_probe, .probe = secocec_probe,
.remove_new = secocec_remove, .remove = secocec_remove,
}; };
module_platform_driver(secocec_driver); module_platform_driver(secocec_driver);

View File

@ -383,7 +383,7 @@ MODULE_DEVICE_TABLE(of, stih_cec_match);
static struct platform_driver stih_cec_pdrv = { static struct platform_driver stih_cec_pdrv = {
.probe = stih_cec_probe, .probe = stih_cec_probe,
.remove_new = stih_cec_remove, .remove = stih_cec_remove,
.driver = { .driver = {
.name = CEC_NAME, .name = CEC_NAME,
.of_match_table = stih_cec_match, .of_match_table = stih_cec_match,

View File

@ -361,7 +361,7 @@ MODULE_DEVICE_TABLE(of, stm32_cec_of_match);
static struct platform_driver stm32_cec_driver = { static struct platform_driver stm32_cec_driver = {
.probe = stm32_cec_probe, .probe = stm32_cec_probe,
.remove_new = stm32_cec_remove, .remove = stm32_cec_remove,
.driver = { .driver = {
.name = CEC_NAME, .name = CEC_NAME,
.of_match_table = stm32_cec_of_match, .of_match_table = stm32_cec_of_match,

View File

@ -465,7 +465,7 @@ static struct platform_driver tegra_cec_driver = {
.of_match_table = tegra_cec_of_match, .of_match_table = tegra_cec_of_match,
}, },
.probe = tegra_cec_probe, .probe = tegra_cec_probe,
.remove_new = tegra_cec_remove, .remove = tegra_cec_remove,
#ifdef CONFIG_PM #ifdef CONFIG_PM
.suspend = tegra_cec_suspend, .suspend = tegra_cec_suspend,

View File

@ -407,8 +407,6 @@ const struct vb2_ops vbi_qops = {
.buf_cleanup = buf_cleanup, .buf_cleanup = buf_cleanup,
.start_streaming = start_streaming, .start_streaming = start_streaming,
.stop_streaming = stop_streaming, .stop_streaming = stop_streaming,
.wait_prepare = vb2_ops_wait_prepare,
.wait_finish = vb2_ops_wait_finish,
}; };
/* ------------------------------------------------------------------ */ /* ------------------------------------------------------------------ */

View File

@ -681,8 +681,6 @@ const struct vb2_ops video_qops = {
.buf_cleanup = buf_cleanup, .buf_cleanup = buf_cleanup,
.start_streaming = start_streaming, .start_streaming = start_streaming,
.stop_streaming = stop_streaming, .stop_streaming = stop_streaming,
.wait_prepare = vb2_ops_wait_prepare,
.wait_finish = vb2_ops_wait_finish,
}; };
/********************************************************************************/ /********************************************************************************/

View File

@ -398,8 +398,6 @@ void smsdvb_debugfs_release(struct smsdvb_client_t *client)
void smsdvb_debugfs_register(void) void smsdvb_debugfs_register(void)
{ {
struct dentry *d;
/* /*
* FIXME: This was written to debug Siano USB devices. So, it creates * FIXME: This was written to debug Siano USB devices. So, it creates
* the debugfs node under <debugfs>/usb. * the debugfs node under <debugfs>/usb.
@ -410,12 +408,7 @@ void smsdvb_debugfs_register(void)
* node for sdio-based boards, but this may need some logic at sdio * node for sdio-based boards, but this may need some logic at sdio
* subsystem. * subsystem.
*/ */
d = debugfs_create_dir("smsdvb", usb_debug_root); smsdvb_debugfs_usb_root = debugfs_create_dir("smsdvb", usb_debug_root);
if (IS_ERR_OR_NULL(d)) {
pr_err("Couldn't create sysfs node for smsdvb\n");
return;
}
smsdvb_debugfs_usb_root = d;
} }
void smsdvb_debugfs_unregister(void) void smsdvb_debugfs_unregister(void)

View File

@ -96,6 +96,10 @@ static const struct uvc_format_desc uvc_fmts[] = {
.guid = UVC_GUID_FORMAT_RGBP, .guid = UVC_GUID_FORMAT_RGBP,
.fcc = V4L2_PIX_FMT_RGB565, .fcc = V4L2_PIX_FMT_RGB565,
}, },
{
.guid = UVC_GUID_FORMAT_D3DFMT_R5G6B5,
.fcc = V4L2_PIX_FMT_RGB565,
},
{ {
.guid = UVC_GUID_FORMAT_BGR3, .guid = UVC_GUID_FORMAT_BGR3,
.fcc = V4L2_PIX_FMT_BGR24, .fcc = V4L2_PIX_FMT_BGR24,
@ -120,6 +124,10 @@ static const struct uvc_format_desc uvc_fmts[] = {
.guid = UVC_GUID_FORMAT_Y12I, .guid = UVC_GUID_FORMAT_Y12I,
.fcc = V4L2_PIX_FMT_Y12I, .fcc = V4L2_PIX_FMT_Y12I,
}, },
{
.guid = UVC_GUID_FORMAT_Y16I,
.fcc = V4L2_PIX_FMT_Y16I,
},
{ {
.guid = UVC_GUID_FORMAT_Z16, .guid = UVC_GUID_FORMAT_Z16,
.fcc = V4L2_PIX_FMT_Z16, .fcc = V4L2_PIX_FMT_Z16,

View File

@ -2037,7 +2037,10 @@ static int __vb2_wait_for_done_vb(struct vb2_queue *q, int nonblocking)
* become ready or for streamoff. Driver's lock is released to * become ready or for streamoff. Driver's lock is released to
* allow streamoff or qbuf to be called while waiting. * allow streamoff or qbuf to be called while waiting.
*/ */
if (q->ops->wait_prepare)
call_void_qop(q, wait_prepare, q); call_void_qop(q, wait_prepare, q);
else if (q->lock)
mutex_unlock(q->lock);
/* /*
* All locks have been released, it is safe to sleep now. * All locks have been released, it is safe to sleep now.
@ -2047,12 +2050,16 @@ static int __vb2_wait_for_done_vb(struct vb2_queue *q, int nonblocking)
!list_empty(&q->done_list) || !q->streaming || !list_empty(&q->done_list) || !q->streaming ||
q->error); q->error);
if (q->ops->wait_finish)
call_void_qop(q, wait_finish, q);
else if (q->lock)
mutex_lock(q->lock);
q->waiting_in_dqbuf = 0;
/* /*
* We need to reevaluate both conditions again after reacquiring * We need to reevaluate both conditions again after reacquiring
* the locks or return an error if one occurred. * the locks or return an error if one occurred.
*/ */
call_void_qop(q, wait_finish, q);
q->waiting_in_dqbuf = 0;
if (ret) { if (ret) {
dprintk(q, 1, "sleep was interrupted\n"); dprintk(q, 1, "sleep was interrupted\n");
return ret; return ret;
@ -2324,7 +2331,7 @@ int vb2_core_streamon(struct vb2_queue *q, unsigned int type)
} }
if (q_num_bufs < q->min_queued_buffers) { if (q_num_bufs < q->min_queued_buffers) {
dprintk(q, 1, "need at least %u queued buffers\n", dprintk(q, 1, "need at least %u allocated buffers\n",
q->min_queued_buffers); q->min_queued_buffers);
return -EINVAL; return -EINVAL;
} }
@ -2646,6 +2653,14 @@ int vb2_core_queue_init(struct vb2_queue *q)
if (WARN_ON(q->min_reqbufs_allocation > q->max_num_buffers)) if (WARN_ON(q->min_reqbufs_allocation > q->max_num_buffers))
return -EINVAL; return -EINVAL;
/* Either both or none are set */
if (WARN_ON(!q->ops->wait_prepare ^ !q->ops->wait_finish))
return -EINVAL;
/* Warn if q->lock is NULL and no custom wait_prepare is provided */
if (WARN_ON(!q->lock && !q->ops->wait_prepare))
return -EINVAL;
INIT_LIST_HEAD(&q->queued_list); INIT_LIST_HEAD(&q->queued_list);
INIT_LIST_HEAD(&q->done_list); INIT_LIST_HEAD(&q->done_list);
spin_lock_init(&q->done_lock); spin_lock_init(&q->done_lock);
@ -3205,10 +3220,17 @@ static int vb2_thread(void *data)
continue; continue;
prequeue--; prequeue--;
} else { } else {
if (!threadio->stop) {
if (q->ops->wait_finish)
call_void_qop(q, wait_finish, q); call_void_qop(q, wait_finish, q);
if (!threadio->stop) else if (q->lock)
mutex_lock(q->lock);
ret = vb2_core_dqbuf(q, &index, NULL, 0); ret = vb2_core_dqbuf(q, &index, NULL, 0);
if (q->ops->wait_prepare)
call_void_qop(q, wait_prepare, q); call_void_qop(q, wait_prepare, q);
else if (q->lock)
mutex_unlock(q->lock);
}
dprintk(q, 5, "file io: vb2_dqbuf result: %d\n", ret); dprintk(q, 5, "file io: vb2_dqbuf result: %d\n", ret);
if (!ret) if (!ret)
vb = vb2_get_buffer(q, index); vb = vb2_get_buffer(q, index);
@ -3220,12 +3242,19 @@ static int vb2_thread(void *data)
if (vb->state != VB2_BUF_STATE_ERROR) if (vb->state != VB2_BUF_STATE_ERROR)
if (threadio->fnc(vb, threadio->priv)) if (threadio->fnc(vb, threadio->priv))
break; break;
call_void_qop(q, wait_finish, q);
if (copy_timestamp) if (copy_timestamp)
vb->timestamp = ktime_get_ns(); vb->timestamp = ktime_get_ns();
if (!threadio->stop) if (!threadio->stop) {
if (q->ops->wait_finish)
call_void_qop(q, wait_finish, q);
else if (q->lock)
mutex_lock(q->lock);
ret = vb2_core_qbuf(q, vb, NULL, NULL); ret = vb2_core_qbuf(q, vb, NULL, NULL);
if (q->ops->wait_prepare)
call_void_qop(q, wait_prepare, q); call_void_qop(q, wait_prepare, q);
else if (q->lock)
mutex_unlock(q->lock);
}
if (ret || threadio->stop) if (ret || threadio->stop)
break; break;
} }

View File

@ -231,7 +231,7 @@ static int vb2_fill_vb2_v4l2_buffer(struct vb2_buffer *vb, struct v4l2_buffer *b
break; break;
} }
/* Fill in driver-provided information for OUTPUT types */ /* Fill in user-provided information for OUTPUT types */
if (V4L2_TYPE_IS_OUTPUT(b->type)) { if (V4L2_TYPE_IS_OUTPUT(b->type)) {
/* /*
* Will have to go up to b->length when API starts * Will have to go up to b->length when API starts

View File

@ -729,7 +729,7 @@ static int bcm3510_init_cold(struct bcm3510_state *st)
int ret; int ret;
bcm3510_register_value v; bcm3510_register_value v;
/* read Acquisation Processor status register and check it is not in RUN mode */ /* read Acquisition Processor status register and check it is not in RUN mode */
if ((ret = bcm3510_readB(st,0xa2,&v)) < 0) if ((ret = bcm3510_readB(st,0xa2,&v)) < 0)
return ret; return ret;
if (v.APSTAT1_a2.RUN) { if (v.APSTAT1_a2.RUN) {

View File

@ -78,7 +78,7 @@ MODULE_PARM_DESC(debug, "turn on debugging (default: 0)");
#define SOC_8090_P1G_11R1 0x86 #define SOC_8090_P1G_11R1 0x86
#define SOC_8090_P1G_21R1 0x8e #define SOC_8090_P1G_21R1 0x8e
/* else use thos ones to check */ /* else use those ones to check */
#define P1A_B 0x0 #define P1A_B 0x0
#define P1C 0x1 #define P1C 0x1
#define P1D_E_F 0x3 #define P1D_E_F 0x3
@ -1574,7 +1574,7 @@ static int dib0090_reset(struct dvb_frontend *fe)
if (((state->identity.version & 0x1f) >= P1D_E_F) || (state->identity.in_soc)) if (((state->identity.version & 0x1f) >= P1D_E_F) || (state->identity.in_soc))
dib0090_set_EFUSE(state); dib0090_set_EFUSE(state);
/* Congigure in function of the crystal */ /* Configure in function of the crystal */
if (state->config->force_crystal_mode != 0) if (state->config->force_crystal_mode != 0)
dib0090_write_reg(state, 0x14, dib0090_write_reg(state, 0x14,
state->config->force_crystal_mode & 3); state->config->force_crystal_mode & 3);

View File

@ -640,7 +640,7 @@ static int dib3000mb_read_ber(struct dvb_frontend* fe, u32 *ber)
return 0; return 0;
} }
/* see dib3000-watch dvb-apps for exact calcuations of signal_strength and snr */ /* see dib3000-watch dvb-apps for exact calculations of signal_strength and snr */
static int dib3000mb_read_signal_strength(struct dvb_frontend* fe, u16 *strength) static int dib3000mb_read_signal_strength(struct dvb_frontend* fe, u16 *strength)
{ {
struct dib3000_state* state = fe->demodulator_priv; struct dib3000_state* state = fe->demodulator_priv;

View File

@ -947,8 +947,6 @@ static const struct vb2_ops rtl2832_sdr_vb2_ops = {
.buf_queue = rtl2832_sdr_buf_queue, .buf_queue = rtl2832_sdr_buf_queue,
.start_streaming = rtl2832_sdr_start_streaming, .start_streaming = rtl2832_sdr_start_streaming,
.stop_streaming = rtl2832_sdr_stop_streaming, .stop_streaming = rtl2832_sdr_stop_streaming,
.wait_prepare = vb2_ops_wait_prepare,
.wait_finish = vb2_ops_wait_finish,
}; };
static int rtl2832_sdr_g_tuner(struct file *file, void *priv, static int rtl2832_sdr_g_tuner(struct file *file, void *priv,
@ -1487,7 +1485,7 @@ static struct platform_driver rtl2832_sdr_driver = {
.name = "rtl2832_sdr", .name = "rtl2832_sdr",
}, },
.probe = rtl2832_sdr_probe, .probe = rtl2832_sdr_probe,
.remove_new = rtl2832_sdr_remove, .remove = rtl2832_sdr_remove,
}; };
module_platform_driver(rtl2832_sdr_driver); module_platform_driver(rtl2832_sdr_driver);

View File

@ -161,7 +161,7 @@ static const struct slookup gain_rfagc_lookup[] = {
}; };
/* /*
* This table is 6 dB too low comapred to the others (probably created with * This table is 6 dB too low compared to the others (probably created with
* a different BB_MAG setting) * a different BB_MAG setting)
*/ */
static const struct slookup gain_channel_agc_nf_lookup[] = { static const struct slookup gain_channel_agc_nf_lookup[] = {

View File

@ -954,7 +954,7 @@ static int RFTrackingFiltersCorrection(struct tda_state *state,
Capprox = 255; Capprox = 255;
/* TODO Temperature compensation. There is defenitely a scale factor */ /* TODO Temperature compensation. There is definitely a scale factor */
/* missing in the datasheet, so leave it out for now. */ /* missing in the datasheet, so leave it out for now. */
state->m_Regs[EB14] = Capprox; state->m_Regs[EB14] = Capprox;

View File

@ -553,13 +553,19 @@ static void ts2020_regmap_unlock(void *__dev)
static int ts2020_probe(struct i2c_client *client) static int ts2020_probe(struct i2c_client *client)
{ {
struct ts2020_config *pdata = client->dev.platform_data; struct ts2020_config *pdata = client->dev.platform_data;
struct dvb_frontend *fe = pdata->fe; struct dvb_frontend *fe;
struct ts2020_priv *dev; struct ts2020_priv *dev;
int ret; int ret;
u8 u8tmp; u8 u8tmp;
unsigned int utmp; unsigned int utmp;
char *chip_str; char *chip_str;
if (!pdata) {
dev_err(&client->dev, "platform data is mandatory\n");
return -EINVAL;
}
fe = pdata->fe;
dev = kzalloc(sizeof(*dev), GFP_KERNEL); dev = kzalloc(sizeof(*dev), GFP_KERNEL);
if (!dev) { if (!dev) {
ret = -ENOMEM; ret = -ENOMEM;

View File

@ -531,7 +531,7 @@ static struct platform_driver zd1301_demod_driver = {
.suppress_bind_attrs = true, .suppress_bind_attrs = true,
}, },
.probe = zd1301_demod_probe, .probe = zd1301_demod_probe,
.remove_new = zd1301_demod_remove, .remove = zd1301_demod_remove,
}; };
module_platform_driver(zd1301_demod_driver); module_platform_driver(zd1301_demod_driver);

View File

@ -89,7 +89,7 @@ static int zl10036_write(struct zl10036_state *state, u8 buf[], u8 count)
int ret; int ret;
if (zl10036_debug & 0x02) { if (zl10036_debug & 0x02) {
/* every 8bit-value satisifes this! /* every 8bit-value satisfies this!
* so only check for debug log */ * so only check for debug log */
if ((buf[0] & 0x80) == 0x00) if ((buf[0] & 0x80) == 0x00)
reg = 2; reg = 2;

View File

@ -1440,7 +1440,8 @@ static int adv7180_probe(struct i2c_client *client)
return ret; return ret;
} }
if (of_property_read_bool(np, "adv,force-bt656-4")) if (of_property_read_bool(np, "adv,force-bt656-4") ||
of_property_read_bool(np, "adi,force-bt656-4"))
state->force_bt656_4 = true; state->force_bt656_4 = true;
if (state->chip_info->flags & ADV7180_FLAG_MIPI_CSI2) { if (state->chip_info->flags & ADV7180_FLAG_MIPI_CSI2) {

View File

@ -116,6 +116,9 @@ struct adv7511_state {
unsigned edid_detect_counter; unsigned edid_detect_counter;
struct workqueue_struct *work_queue; struct workqueue_struct *work_queue;
struct delayed_work edid_handler; /* work entry */ struct delayed_work edid_handler; /* work entry */
struct dentry *debugfs_dir;
struct v4l2_debugfs_if *infoframes;
}; };
static void adv7511_check_monitor_present_status(struct v4l2_subdev *sd); static void adv7511_check_monitor_present_status(struct v4l2_subdev *sd);
@ -483,27 +486,25 @@ static u8 hdmi_infoframe_checksum(u8 *ptr, size_t size)
return 256 - csum; return 256 - csum;
} }
static void log_infoframe(struct v4l2_subdev *sd, const struct adv7511_cfg_read_infoframe *cri) static int read_infoframe(struct v4l2_subdev *sd,
const struct adv7511_cfg_read_infoframe *cri,
u8 *buffer)
{ {
struct i2c_client *client = v4l2_get_subdevdata(sd);
struct device *dev = &client->dev;
union hdmi_infoframe frame;
u8 buffer[32];
u8 len; u8 len;
int i; int i;
if (!(adv7511_rd(sd, cri->present_reg) & cri->present_mask)) { if (!(adv7511_rd(sd, cri->present_reg) & cri->present_mask)) {
v4l2_info(sd, "%s infoframe not transmitted\n", cri->desc); v4l2_info(sd, "%s infoframe not transmitted\n", cri->desc);
return; return 0;
} }
memcpy(buffer, cri->header, sizeof(cri->header)); memcpy(buffer, cri->header, sizeof(cri->header));
len = buffer[2]; len = buffer[2];
if (len + 4 > sizeof(buffer)) { if (len + 4 > V4L2_DEBUGFS_IF_MAX_LEN) {
v4l2_err(sd, "%s: invalid %s infoframe length %d\n", __func__, cri->desc, len); v4l2_err(sd, "%s: invalid %s infoframe length %d\n", __func__, cri->desc, len);
return; return 0;
} }
if (cri->payload_addr >= 0x100) { if (cri->payload_addr >= 0x100) {
@ -516,21 +517,38 @@ static void log_infoframe(struct v4l2_subdev *sd, const struct adv7511_cfg_read_
buffer[3] = 0; buffer[3] = 0;
buffer[3] = hdmi_infoframe_checksum(buffer, len + 4); buffer[3] = hdmi_infoframe_checksum(buffer, len + 4);
if (hdmi_infoframe_unpack(&frame, buffer, len + 4) < 0) { return len + 4;
v4l2_err(sd, "%s: unpack of %s infoframe failed\n", __func__, cri->desc); }
static void log_infoframe(struct v4l2_subdev *sd,
const struct adv7511_cfg_read_infoframe *cri)
{
union hdmi_infoframe frame;
struct i2c_client *client = v4l2_get_subdevdata(sd);
struct device *dev = &client->dev;
u8 buffer[V4L2_DEBUGFS_IF_MAX_LEN] = {};
int len = read_infoframe(sd, cri, buffer);
if (len <= 0)
return;
if (hdmi_infoframe_unpack(&frame, buffer, len) < 0) {
v4l2_err(sd, "%s: unpack of %s infoframe failed\n",
__func__, cri->desc);
return; return;
} }
hdmi_infoframe_log(KERN_INFO, dev, &frame); hdmi_infoframe_log(KERN_INFO, dev, &frame);
} }
static void adv7511_log_infoframes(struct v4l2_subdev *sd)
{
static const struct adv7511_cfg_read_infoframe cri[] = { static const struct adv7511_cfg_read_infoframe cri[] = {
{ "AVI", 0x44, 0x10, { 0x82, 2, 13 }, 0x55 }, { "AVI", 0x44, 0x10, { 0x82, 2, 13 }, 0x55 },
{ "Audio", 0x44, 0x08, { 0x84, 1, 10 }, 0x73 }, { "Audio", 0x44, 0x08, { 0x84, 1, 10 }, 0x73 },
{ "SDP", 0x40, 0x40, { 0x83, 1, 25 }, 0x103 }, { "SDP", 0x40, 0x40, { 0x83, 1, 25 }, 0x103 },
}; };
static void adv7511_log_infoframes(struct v4l2_subdev *sd)
{
int i; int i;
for (i = 0; i < ARRAY_SIZE(cri); i++) for (i = 0; i < ARRAY_SIZE(cri); i++)
@ -1693,6 +1711,34 @@ static bool adv7511_check_edid_status(struct v4l2_subdev *sd)
return false; return false;
} }
static ssize_t
adv7511_debugfs_if_read(u32 type, void *priv,
struct file *filp, char __user *ubuf, size_t count, loff_t *ppos)
{
u8 buf[V4L2_DEBUGFS_IF_MAX_LEN] = {};
struct v4l2_subdev *sd = priv;
int index;
int len;
switch (type) {
case V4L2_DEBUGFS_IF_AVI:
index = 0;
break;
case V4L2_DEBUGFS_IF_AUDIO:
index = 1;
break;
case V4L2_DEBUGFS_IF_SPD:
index = 2;
break;
default:
return 0;
}
len = read_infoframe(sd, &cri[index], buf);
if (len > 0)
len = simple_read_from_buffer(ubuf, count, ppos, buf, len);
return len < 0 ? 0 : len;
}
static int adv7511_registered(struct v4l2_subdev *sd) static int adv7511_registered(struct v4l2_subdev *sd)
{ {
struct adv7511_state *state = get_adv7511_state(sd); struct adv7511_state *state = get_adv7511_state(sd);
@ -1700,16 +1746,27 @@ static int adv7511_registered(struct v4l2_subdev *sd)
int err; int err;
err = cec_register_adapter(state->cec_adap, &client->dev); err = cec_register_adapter(state->cec_adap, &client->dev);
if (err) if (err) {
cec_delete_adapter(state->cec_adap); cec_delete_adapter(state->cec_adap);
return err; return err;
} }
state->debugfs_dir = debugfs_create_dir(sd->name, v4l2_debugfs_root());
state->infoframes = v4l2_debugfs_if_alloc(state->debugfs_dir,
V4L2_DEBUGFS_IF_AVI | V4L2_DEBUGFS_IF_AUDIO |
V4L2_DEBUGFS_IF_SPD, sd, adv7511_debugfs_if_read);
return 0;
}
static void adv7511_unregistered(struct v4l2_subdev *sd) static void adv7511_unregistered(struct v4l2_subdev *sd)
{ {
struct adv7511_state *state = get_adv7511_state(sd); struct adv7511_state *state = get_adv7511_state(sd);
cec_unregister_adapter(state->cec_adap); cec_unregister_adapter(state->cec_adap);
v4l2_debugfs_if_free(state->infoframes);
state->infoframes = NULL;
debugfs_remove_recursive(state->debugfs_dir);
state->debugfs_dir = NULL;
} }
static const struct v4l2_subdev_internal_ops adv7511_int_ops = { static const struct v4l2_subdev_internal_ops adv7511_int_ops = {

View File

@ -42,7 +42,7 @@ module_param(debug, int, 0644);
MODULE_PARM_DESC(debug, "debug level (0-2)"); MODULE_PARM_DESC(debug, "debug level (0-2)");
MODULE_DESCRIPTION("Analog Devices ADV7604/10/11/12 video decoder driver"); MODULE_DESCRIPTION("Analog Devices ADV7604/10/11/12 video decoder driver");
MODULE_AUTHOR("Hans Verkuil <hans.verkuil@cisco.com>"); MODULE_AUTHOR("Hans Verkuil <hansverk@cisco.com>");
MODULE_AUTHOR("Mats Randgaard <mats.randgaard@cisco.com>"); MODULE_AUTHOR("Mats Randgaard <mats.randgaard@cisco.com>");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
@ -193,6 +193,9 @@ struct adv76xx_state {
struct delayed_work delayed_work_enable_hotplug; struct delayed_work delayed_work_enable_hotplug;
bool restart_stdi_once; bool restart_stdi_once;
struct dentry *debugfs_dir;
struct v4l2_debugfs_if *infoframes;
/* CEC */ /* CEC */
struct cec_adapter *cec_adap; struct cec_adapter *cec_adap;
u8 cec_addr[ADV76XX_MAX_ADDRS]; u8 cec_addr[ADV76XX_MAX_ADDRS];
@ -1405,12 +1408,13 @@ static int stdi2dv_timings(struct v4l2_subdev *sd,
if (v4l2_detect_cvt(stdi->lcf + 1, hfreq, stdi->lcvs, 0, if (v4l2_detect_cvt(stdi->lcf + 1, hfreq, stdi->lcvs, 0,
(stdi->hs_pol == '+' ? V4L2_DV_HSYNC_POS_POL : 0) | (stdi->hs_pol == '+' ? V4L2_DV_HSYNC_POS_POL : 0) |
(stdi->vs_pol == '+' ? V4L2_DV_VSYNC_POS_POL : 0), (stdi->vs_pol == '+' ? V4L2_DV_VSYNC_POS_POL : 0),
false, timings)) false, adv76xx_get_dv_timings_cap(sd, -1), timings))
return 0; return 0;
if (v4l2_detect_gtf(stdi->lcf + 1, hfreq, stdi->lcvs, if (v4l2_detect_gtf(stdi->lcf + 1, hfreq, stdi->lcvs,
(stdi->hs_pol == '+' ? V4L2_DV_HSYNC_POS_POL : 0) | (stdi->hs_pol == '+' ? V4L2_DV_HSYNC_POS_POL : 0) |
(stdi->vs_pol == '+' ? V4L2_DV_VSYNC_POS_POL : 0), (stdi->vs_pol == '+' ? V4L2_DV_VSYNC_POS_POL : 0),
false, state->aspect_ratio, timings)) false, state->aspect_ratio,
adv76xx_get_dv_timings_cap(sd, -1), timings))
return 0; return 0;
v4l2_dbg(2, debug, sd, v4l2_dbg(2, debug, sd,
@ -2458,10 +2462,9 @@ static const struct adv76xx_cfg_read_infoframe adv76xx_cri[] = {
{ "Vendor", 0x10, 0xec, 0x54 } { "Vendor", 0x10, 0xec, 0x54 }
}; };
static int adv76xx_read_infoframe(struct v4l2_subdev *sd, int index, static int adv76xx_read_infoframe_buf(struct v4l2_subdev *sd, int index,
union hdmi_infoframe *frame) u8 buf[V4L2_DEBUGFS_IF_MAX_LEN])
{ {
uint8_t buffer[32];
u8 len; u8 len;
int i; int i;
@ -2472,27 +2475,20 @@ static int adv76xx_read_infoframe(struct v4l2_subdev *sd, int index,
} }
for (i = 0; i < 3; i++) for (i = 0; i < 3; i++)
buffer[i] = infoframe_read(sd, buf[i] = infoframe_read(sd, adv76xx_cri[index].head_addr + i);
adv76xx_cri[index].head_addr + i);
len = buffer[2] + 1; len = buf[2] + 1;
if (len + 3 > sizeof(buffer)) { if (len + 3 > V4L2_DEBUGFS_IF_MAX_LEN) {
v4l2_err(sd, "%s: invalid %s infoframe length %d\n", __func__, v4l2_err(sd, "%s: invalid %s infoframe length %d\n", __func__,
adv76xx_cri[index].desc, len); adv76xx_cri[index].desc, len);
return -ENOENT; return -ENOENT;
} }
for (i = 0; i < len; i++) for (i = 0; i < len; i++)
buffer[i + 3] = infoframe_read(sd, buf[i + 3] = infoframe_read(sd,
adv76xx_cri[index].payload_addr + i); adv76xx_cri[index].payload_addr + i);
return len + 3;
if (hdmi_infoframe_unpack(frame, buffer, len + 3) < 0) {
v4l2_err(sd, "%s: unpack of %s infoframe failed\n", __func__,
adv76xx_cri[index].desc);
return -ENOENT;
}
return 0;
} }
static void adv76xx_log_infoframes(struct v4l2_subdev *sd) static void adv76xx_log_infoframes(struct v4l2_subdev *sd)
@ -2505,10 +2501,19 @@ static void adv76xx_log_infoframes(struct v4l2_subdev *sd)
} }
for (i = 0; i < ARRAY_SIZE(adv76xx_cri); i++) { for (i = 0; i < ARRAY_SIZE(adv76xx_cri); i++) {
union hdmi_infoframe frame;
struct i2c_client *client = v4l2_get_subdevdata(sd); struct i2c_client *client = v4l2_get_subdevdata(sd);
u8 buffer[V4L2_DEBUGFS_IF_MAX_LEN] = {};
union hdmi_infoframe frame;
int len;
if (!adv76xx_read_infoframe(sd, i, &frame)) len = adv76xx_read_infoframe_buf(sd, i, buffer);
if (len < 0)
continue;
if (hdmi_infoframe_unpack(&frame, buffer, len) < 0)
v4l2_err(sd, "%s: unpack of %s infoframe failed\n",
__func__, adv76xx_cri[i].desc);
else
hdmi_infoframe_log(KERN_INFO, &client->dev, &frame); hdmi_infoframe_log(KERN_INFO, &client->dev, &frame);
} }
} }
@ -2694,6 +2699,41 @@ static int adv76xx_subscribe_event(struct v4l2_subdev *sd,
} }
} }
static ssize_t
adv76xx_debugfs_if_read(u32 type, void *priv, struct file *filp,
char __user *ubuf, size_t count, loff_t *ppos)
{
u8 buf[V4L2_DEBUGFS_IF_MAX_LEN] = {};
struct v4l2_subdev *sd = priv;
int index;
int len;
if (!is_hdmi(sd))
return 0;
switch (type) {
case V4L2_DEBUGFS_IF_AVI:
index = 0;
break;
case V4L2_DEBUGFS_IF_AUDIO:
index = 1;
break;
case V4L2_DEBUGFS_IF_SPD:
index = 2;
break;
case V4L2_DEBUGFS_IF_HDMI:
index = 3;
break;
default:
return 0;
}
len = adv76xx_read_infoframe_buf(sd, index, buf);
if (len > 0)
len = simple_read_from_buffer(ubuf, count, ppos, buf, len);
return len < 0 ? 0 : len;
}
static int adv76xx_registered(struct v4l2_subdev *sd) static int adv76xx_registered(struct v4l2_subdev *sd)
{ {
struct adv76xx_state *state = to_state(sd); struct adv76xx_state *state = to_state(sd);
@ -2701,16 +2741,27 @@ static int adv76xx_registered(struct v4l2_subdev *sd)
int err; int err;
err = cec_register_adapter(state->cec_adap, &client->dev); err = cec_register_adapter(state->cec_adap, &client->dev);
if (err) if (err) {
cec_delete_adapter(state->cec_adap); cec_delete_adapter(state->cec_adap);
return err; return err;
} }
state->debugfs_dir = debugfs_create_dir(sd->name, v4l2_debugfs_root());
state->infoframes = v4l2_debugfs_if_alloc(state->debugfs_dir,
V4L2_DEBUGFS_IF_AVI | V4L2_DEBUGFS_IF_AUDIO |
V4L2_DEBUGFS_IF_SPD | V4L2_DEBUGFS_IF_HDMI, sd,
adv76xx_debugfs_if_read);
return 0;
}
static void adv76xx_unregistered(struct v4l2_subdev *sd) static void adv76xx_unregistered(struct v4l2_subdev *sd)
{ {
struct adv76xx_state *state = to_state(sd); struct adv76xx_state *state = to_state(sd);
cec_unregister_adapter(state->cec_adap); cec_unregister_adapter(state->cec_adap);
v4l2_debugfs_if_free(state->infoframes);
state->infoframes = NULL;
debugfs_remove_recursive(state->debugfs_dir);
state->debugfs_dir = NULL;
} }
/* ----------------------------------------------------------------------- */ /* ----------------------------------------------------------------------- */

View File

@ -38,7 +38,7 @@ module_param(debug, int, 0644);
MODULE_PARM_DESC(debug, "debug level (0-2)"); MODULE_PARM_DESC(debug, "debug level (0-2)");
MODULE_DESCRIPTION("Analog Devices ADV7842 video decoder driver"); MODULE_DESCRIPTION("Analog Devices ADV7842 video decoder driver");
MODULE_AUTHOR("Hans Verkuil <hans.verkuil@cisco.com>"); MODULE_AUTHOR("Hans Verkuil <hansverk@cisco.com>");
MODULE_AUTHOR("Martin Bugge <marbugge@cisco.com>"); MODULE_AUTHOR("Martin Bugge <marbugge@cisco.com>");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
@ -114,6 +114,9 @@ struct adv7842_state {
bool restart_stdi_once; bool restart_stdi_once;
bool hdmi_port_a; bool hdmi_port_a;
struct dentry *debugfs_dir;
struct v4l2_debugfs_if *infoframes;
/* i2c clients */ /* i2c clients */
struct i2c_client *i2c_sdp_io; struct i2c_client *i2c_sdp_io;
struct i2c_client *i2c_sdp; struct i2c_client *i2c_sdp;
@ -1433,12 +1436,13 @@ static int stdi2dv_timings(struct v4l2_subdev *sd,
if (v4l2_detect_cvt(stdi->lcf + 1, hfreq, stdi->lcvs, 0, if (v4l2_detect_cvt(stdi->lcf + 1, hfreq, stdi->lcvs, 0,
(stdi->hs_pol == '+' ? V4L2_DV_HSYNC_POS_POL : 0) | (stdi->hs_pol == '+' ? V4L2_DV_HSYNC_POS_POL : 0) |
(stdi->vs_pol == '+' ? V4L2_DV_VSYNC_POS_POL : 0), (stdi->vs_pol == '+' ? V4L2_DV_VSYNC_POS_POL : 0),
false, timings)) false, adv7842_get_dv_timings_cap(sd), timings))
return 0; return 0;
if (v4l2_detect_gtf(stdi->lcf + 1, hfreq, stdi->lcvs, if (v4l2_detect_gtf(stdi->lcf + 1, hfreq, stdi->lcvs,
(stdi->hs_pol == '+' ? V4L2_DV_HSYNC_POS_POL : 0) | (stdi->hs_pol == '+' ? V4L2_DV_HSYNC_POS_POL : 0) |
(stdi->vs_pol == '+' ? V4L2_DV_VSYNC_POS_POL : 0), (stdi->vs_pol == '+' ? V4L2_DV_VSYNC_POS_POL : 0),
false, state->aspect_ratio, timings)) false, state->aspect_ratio,
adv7842_get_dv_timings_cap(sd), timings))
return 0; return 0;
v4l2_dbg(2, debug, sd, v4l2_dbg(2, debug, sd,
@ -2565,58 +2569,65 @@ struct adv7842_cfg_read_infoframe {
u8 payload_addr; u8 payload_addr;
}; };
static void log_infoframe(struct v4l2_subdev *sd, const struct adv7842_cfg_read_infoframe *cri) static const struct adv7842_cfg_read_infoframe adv7842_cri[] = {
{
int i;
u8 buffer[32];
union hdmi_infoframe frame;
u8 len;
struct i2c_client *client = v4l2_get_subdevdata(sd);
struct device *dev = &client->dev;
if (!(io_read(sd, 0x60) & cri->present_mask)) {
v4l2_info(sd, "%s infoframe not received\n", cri->desc);
return;
}
for (i = 0; i < 3; i++)
buffer[i] = infoframe_read(sd, cri->head_addr + i);
len = buffer[2] + 1;
if (len + 3 > sizeof(buffer)) {
v4l2_err(sd, "%s: invalid %s infoframe length %d\n", __func__, cri->desc, len);
return;
}
for (i = 0; i < len; i++)
buffer[i + 3] = infoframe_read(sd, cri->payload_addr + i);
if (hdmi_infoframe_unpack(&frame, buffer, len + 3) < 0) {
v4l2_err(sd, "%s: unpack of %s infoframe failed\n", __func__, cri->desc);
return;
}
hdmi_infoframe_log(KERN_INFO, dev, &frame);
}
static void adv7842_log_infoframes(struct v4l2_subdev *sd)
{
int i;
static const struct adv7842_cfg_read_infoframe cri[] = {
{ "AVI", 0x01, 0xe0, 0x00 }, { "AVI", 0x01, 0xe0, 0x00 },
{ "Audio", 0x02, 0xe3, 0x1c }, { "Audio", 0x02, 0xe3, 0x1c },
{ "SDP", 0x04, 0xe6, 0x2a }, { "SDP", 0x04, 0xe6, 0x2a },
{ "Vendor", 0x10, 0xec, 0x54 } { "Vendor", 0x10, 0xec, 0x54 }
}; };
static int adv7842_read_infoframe_buf(struct v4l2_subdev *sd, int index,
u8 buf[V4L2_DEBUGFS_IF_MAX_LEN])
{
const struct adv7842_cfg_read_infoframe *cri = &adv7842_cri[index];
int len, i;
if (!(io_read(sd, 0x60) & cri->present_mask)) {
v4l2_dbg(1, debug, sd,
"%s infoframe not received\n", cri->desc);
return -ENOENT;
}
for (i = 0; i < 3; i++)
buf[i] = infoframe_read(sd, cri->head_addr + i);
len = buf[2] + 1;
if (len + 3 > V4L2_DEBUGFS_IF_MAX_LEN) {
v4l2_err(sd, "%s: invalid %s infoframe length %d\n",
__func__, cri->desc, len);
return -ENOENT;
}
for (i = 0; i < len; i++)
buf[i + 3] = infoframe_read(sd, cri->payload_addr + i);
return len + 3;
}
static void adv7842_log_infoframes(struct v4l2_subdev *sd)
{
struct i2c_client *client = v4l2_get_subdevdata(sd);
struct device *dev = &client->dev;
union hdmi_infoframe frame;
u8 buffer[V4L2_DEBUGFS_IF_MAX_LEN] = {};
int len, i;
if (!(hdmi_read(sd, 0x05) & 0x80)) { if (!(hdmi_read(sd, 0x05) & 0x80)) {
v4l2_info(sd, "receive DVI-D signal, no infoframes\n"); v4l2_info(sd, "receive DVI-D signal, no infoframes\n");
return; return;
} }
for (i = 0; i < ARRAY_SIZE(cri); i++) for (i = 0; i < ARRAY_SIZE(adv7842_cri); i++) {
log_infoframe(sd, &cri[i]); len = adv7842_read_infoframe_buf(sd, i, buffer);
if (len < 0)
continue;
if (hdmi_infoframe_unpack(&frame, buffer, len) < 0)
v4l2_err(sd, "%s: unpack of %s infoframe failed\n",
__func__, adv7842_cri[i].desc);
else
hdmi_infoframe_log(KERN_INFO, dev, &frame);
}
} }
#if 0 #if 0
@ -3263,6 +3274,41 @@ static int adv7842_subscribe_event(struct v4l2_subdev *sd,
} }
} }
static ssize_t
adv7842_debugfs_if_read(u32 type, void *priv, struct file *filp,
char __user *ubuf, size_t count, loff_t *ppos)
{
u8 buf[V4L2_DEBUGFS_IF_MAX_LEN] = {};
struct v4l2_subdev *sd = priv;
int index;
int len;
if (!is_hdmi(sd))
return 0;
switch (type) {
case V4L2_DEBUGFS_IF_AVI:
index = 0;
break;
case V4L2_DEBUGFS_IF_AUDIO:
index = 1;
break;
case V4L2_DEBUGFS_IF_SPD:
index = 2;
break;
case V4L2_DEBUGFS_IF_HDMI:
index = 3;
break;
default:
return 0;
}
len = adv7842_read_infoframe_buf(sd, index, buf);
if (len > 0)
len = simple_read_from_buffer(ubuf, count, ppos, buf, len);
return len < 0 ? 0 : len;
}
static int adv7842_registered(struct v4l2_subdev *sd) static int adv7842_registered(struct v4l2_subdev *sd)
{ {
struct adv7842_state *state = to_state(sd); struct adv7842_state *state = to_state(sd);
@ -3270,8 +3316,15 @@ static int adv7842_registered(struct v4l2_subdev *sd)
int err; int err;
err = cec_register_adapter(state->cec_adap, &client->dev); err = cec_register_adapter(state->cec_adap, &client->dev);
if (err) if (err) {
cec_delete_adapter(state->cec_adap); cec_delete_adapter(state->cec_adap);
} else {
state->debugfs_dir = debugfs_create_dir(sd->name, v4l2_debugfs_root());
state->infoframes = v4l2_debugfs_if_alloc(state->debugfs_dir,
V4L2_DEBUGFS_IF_AVI | V4L2_DEBUGFS_IF_AUDIO |
V4L2_DEBUGFS_IF_SPD | V4L2_DEBUGFS_IF_HDMI, sd,
adv7842_debugfs_if_read);
}
return err; return err;
} }
@ -3280,6 +3333,10 @@ static void adv7842_unregistered(struct v4l2_subdev *sd)
struct adv7842_state *state = to_state(sd); struct adv7842_state *state = to_state(sd);
cec_unregister_adapter(state->cec_adap); cec_unregister_adapter(state->cec_adap);
v4l2_debugfs_if_free(state->infoframes);
state->infoframes = NULL;
debugfs_remove_recursive(state->debugfs_dir);
state->debugfs_dir = NULL;
} }
/* ----------------------------------------------------------------------- */ /* ----------------------------------------------------------------------- */

View File

@ -16,7 +16,6 @@
#include <media/v4l2-async.h> #include <media/v4l2-async.h>
#include <media/v4l2-ctrls.h> #include <media/v4l2-ctrls.h>
#include <media/v4l2-device.h> #include <media/v4l2-device.h>
#include <media/v4l2-event.h>
#include <media/v4l2-fwnode.h> #include <media/v4l2-fwnode.h>
#include <media/v4l2-subdev.h> #include <media/v4l2-subdev.h>
@ -2240,8 +2239,6 @@ free_ctrls:
static const struct v4l2_subdev_core_ops alvium_core_ops = { static const struct v4l2_subdev_core_ops alvium_core_ops = {
.log_status = v4l2_ctrl_subdev_log_status, .log_status = v4l2_ctrl_subdev_log_status,
.subscribe_event = v4l2_ctrl_subdev_subscribe_event,
.unsubscribe_event = v4l2_event_subdev_unsubscribe,
}; };
static const struct v4l2_subdev_video_ops alvium_video_ops = { static const struct v4l2_subdev_video_ops alvium_video_ops = {
@ -2289,7 +2286,7 @@ static int alvium_subdev_init(struct alvium_dev *alvium)
v4l2_i2c_subdev_init(sd, client, &alvium_subdev_ops); v4l2_i2c_subdev_init(sd, client, &alvium_subdev_ops);
sd->internal_ops = &alvium_internal_ops; sd->internal_ops = &alvium_internal_ops;
sd->flags |= V4L2_SUBDEV_FL_HAS_EVENTS | V4L2_SUBDEV_FL_HAS_DEVNODE; sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
alvium->pad.flags = MEDIA_PAD_FL_SOURCE; alvium->pad.flags = MEDIA_PAD_FL_SOURCE;
sd->entity.function = MEDIA_ENT_F_CAM_SENSOR; sd->entity.function = MEDIA_ENT_F_CAM_SENSOR;

View File

@ -24,7 +24,6 @@
#include <media/i2c/ds90ub9xx.h> #include <media/i2c/ds90ub9xx.h>
#include <media/v4l2-ctrls.h> #include <media/v4l2-ctrls.h>
#include <media/v4l2-event.h>
#include <media/v4l2-fwnode.h> #include <media/v4l2-fwnode.h>
#include <media/v4l2-mediabus.h> #include <media/v4l2-mediabus.h>
#include <media/v4l2-subdev.h> #include <media/v4l2-subdev.h>
@ -717,8 +716,6 @@ static const struct v4l2_subdev_pad_ops ub953_pad_ops = {
static const struct v4l2_subdev_core_ops ub953_subdev_core_ops = { static const struct v4l2_subdev_core_ops ub953_subdev_core_ops = {
.log_status = ub953_log_status, .log_status = ub953_log_status,
.subscribe_event = v4l2_ctrl_subdev_subscribe_event,
.unsubscribe_event = v4l2_event_subdev_unsubscribe,
}; };
static const struct v4l2_subdev_ops ub953_subdev_ops = { static const struct v4l2_subdev_ops ub953_subdev_ops = {
@ -1246,7 +1243,7 @@ static int ub953_subdev_init(struct ub953_data *priv)
priv->sd.internal_ops = &ub953_internal_ops; priv->sd.internal_ops = &ub953_internal_ops;
priv->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE | priv->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE |
V4L2_SUBDEV_FL_HAS_EVENTS | V4L2_SUBDEV_FL_STREAMS; V4L2_SUBDEV_FL_STREAMS;
priv->sd.entity.function = MEDIA_ENT_F_VID_IF_BRIDGE; priv->sd.entity.function = MEDIA_ENT_F_VID_IF_BRIDGE;
priv->sd.entity.ops = &ub953_entity_ops; priv->sd.entity.ops = &ub953_entity_ops;

View File

@ -48,7 +48,6 @@
#include <media/i2c/ds90ub9xx.h> #include <media/i2c/ds90ub9xx.h>
#include <media/mipi-csi2.h> #include <media/mipi-csi2.h>
#include <media/v4l2-ctrls.h> #include <media/v4l2-ctrls.h>
#include <media/v4l2-event.h>
#include <media/v4l2-fwnode.h> #include <media/v4l2-fwnode.h>
#include <media/v4l2-subdev.h> #include <media/v4l2-subdev.h>
@ -1286,7 +1285,7 @@ static int ub960_rxport_get_strobe_pos(struct ub960_data *priv,
clk_delay += v & UB960_IR_RX_ANA_STROBE_SET_CLK_DELAY_MASK; clk_delay += v & UB960_IR_RX_ANA_STROBE_SET_CLK_DELAY_MASK;
ub960_rxport_read(priv, nport, UB960_RR_SFILTER_STS_1, &v); ret = ub960_rxport_read(priv, nport, UB960_RR_SFILTER_STS_1, &v);
if (ret) if (ret)
return ret; return ret;
@ -3085,8 +3084,6 @@ static int ub960_log_status(struct v4l2_subdev *sd)
static const struct v4l2_subdev_core_ops ub960_subdev_core_ops = { static const struct v4l2_subdev_core_ops ub960_subdev_core_ops = {
.log_status = ub960_log_status, .log_status = ub960_log_status,
.subscribe_event = v4l2_ctrl_subdev_subscribe_event,
.unsubscribe_event = v4l2_event_subdev_unsubscribe,
}; };
static const struct v4l2_subdev_internal_ops ub960_internal_ops = { static const struct v4l2_subdev_internal_ops ub960_internal_ops = {
@ -3667,7 +3664,7 @@ static int ub960_create_subdev(struct ub960_data *priv)
} }
priv->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE | priv->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE |
V4L2_SUBDEV_FL_HAS_EVENTS | V4L2_SUBDEV_FL_STREAMS; V4L2_SUBDEV_FL_STREAMS;
priv->sd.entity.function = MEDIA_ENT_F_VID_IF_BRIDGE; priv->sd.entity.function = MEDIA_ENT_F_VID_IF_BRIDGE;
priv->sd.entity.ops = &ub960_entity_ops; priv->sd.entity.ops = &ub960_entity_ops;

View File

@ -374,7 +374,8 @@ static int dw9768_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
static int dw9768_close(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) static int dw9768_close(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
{ {
pm_runtime_put(sd->dev); pm_runtime_mark_last_busy(sd->dev);
pm_runtime_put_autosuspend(sd->dev);
return 0; return 0;
} }
@ -471,10 +472,9 @@ static int dw9768_probe(struct i2c_client *client)
* to be powered on in an ACPI system. Similarly for power off in * to be powered on in an ACPI system. Similarly for power off in
* remove. * remove.
*/ */
pm_runtime_enable(dev);
full_power = (is_acpi_node(dev_fwnode(dev)) && full_power = (is_acpi_node(dev_fwnode(dev)) &&
acpi_dev_state_d0(dev)) || acpi_dev_state_d0(dev)) ||
(is_of_node(dev_fwnode(dev)) && !pm_runtime_enabled(dev)); (is_of_node(dev_fwnode(dev)) && !IS_ENABLED(CONFIG_PM));
if (full_power) { if (full_power) {
ret = dw9768_runtime_resume(dev); ret = dw9768_runtime_resume(dev);
if (ret < 0) { if (ret < 0) {
@ -484,23 +484,26 @@ static int dw9768_probe(struct i2c_client *client)
pm_runtime_set_active(dev); pm_runtime_set_active(dev);
} }
pm_runtime_enable(dev);
ret = v4l2_async_register_subdev(&dw9768->sd); ret = v4l2_async_register_subdev(&dw9768->sd);
if (ret < 0) { if (ret < 0) {
dev_err(dev, "failed to register V4L2 subdev: %d", ret); dev_err(dev, "failed to register V4L2 subdev: %d", ret);
goto err_power_off; goto err_power_off;
} }
pm_runtime_set_autosuspend_delay(dev, 1000);
pm_runtime_use_autosuspend(dev);
pm_runtime_idle(dev); pm_runtime_idle(dev);
return 0; return 0;
err_power_off: err_power_off:
pm_runtime_disable(dev);
if (full_power) { if (full_power) {
dw9768_runtime_suspend(dev); dw9768_runtime_suspend(dev);
pm_runtime_set_suspended(dev); pm_runtime_set_suspended(dev);
} }
err_clean_entity: err_clean_entity:
pm_runtime_disable(dev);
media_entity_cleanup(&dw9768->sd.entity); media_entity_cleanup(&dw9768->sd.entity);
err_free_handler: err_free_handler:
v4l2_ctrl_handler_free(&dw9768->ctrls); v4l2_ctrl_handler_free(&dw9768->ctrls);
@ -517,12 +520,12 @@ static void dw9768_remove(struct i2c_client *client)
v4l2_async_unregister_subdev(&dw9768->sd); v4l2_async_unregister_subdev(&dw9768->sd);
v4l2_ctrl_handler_free(&dw9768->ctrls); v4l2_ctrl_handler_free(&dw9768->ctrls);
media_entity_cleanup(&dw9768->sd.entity); media_entity_cleanup(&dw9768->sd.entity);
pm_runtime_disable(dev);
if ((is_acpi_node(dev_fwnode(dev)) && acpi_dev_state_d0(dev)) || if ((is_acpi_node(dev_fwnode(dev)) && acpi_dev_state_d0(dev)) ||
(is_of_node(dev_fwnode(dev)) && !pm_runtime_enabled(dev))) { (is_of_node(dev_fwnode(dev)) && !IS_ENABLED(CONFIG_PM))) {
dw9768_runtime_suspend(dev); dw9768_runtime_suspend(dev);
pm_runtime_set_suspended(dev); pm_runtime_set_suspended(dev);
} }
pm_runtime_disable(dev);
} }
static const struct of_device_id dw9768_of_table[] = { static const struct of_device_id dw9768_of_table[] = {

View File

@ -18,7 +18,6 @@
#include <media/v4l2-cci.h> #include <media/v4l2-cci.h>
#include <media/v4l2-ctrls.h> #include <media/v4l2-ctrls.h>
#include <media/v4l2-device.h> #include <media/v4l2-device.h>
#include <media/v4l2-event.h>
#include <media/v4l2-fwnode.h> #include <media/v4l2-fwnode.h>
#include <media/v4l2-subdev.h> #include <media/v4l2-subdev.h>
@ -987,8 +986,6 @@ static const struct v4l2_ctrl_ops gc0308_ctrl_ops = {
static const struct v4l2_subdev_core_ops gc0308_core_ops = { static const struct v4l2_subdev_core_ops gc0308_core_ops = {
.log_status = v4l2_ctrl_subdev_log_status, .log_status = v4l2_ctrl_subdev_log_status,
.subscribe_event = v4l2_ctrl_subdev_subscribe_event,
.unsubscribe_event = v4l2_event_subdev_unsubscribe,
#ifdef CONFIG_VIDEO_ADV_DEBUG #ifdef CONFIG_VIDEO_ADV_DEBUG
.g_register = gc0308_g_register, .g_register = gc0308_g_register,
.s_register = gc0308_s_register, .s_register = gc0308_s_register,
@ -1338,7 +1335,6 @@ static int gc0308_probe(struct i2c_client *client)
v4l2_i2c_subdev_init(&gc0308->sd, client, &gc0308_subdev_ops); v4l2_i2c_subdev_init(&gc0308->sd, client, &gc0308_subdev_ops);
gc0308->sd.internal_ops = &gc0308_internal_ops; gc0308->sd.internal_ops = &gc0308_internal_ops;
gc0308->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; gc0308->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
gc0308->sd.flags |= V4L2_SUBDEV_FL_HAS_EVENTS;
ret = gc0308_init_controls(gc0308); ret = gc0308_init_controls(gc0308);
if (ret) if (ret)

View File

@ -24,7 +24,6 @@
#include <media/v4l2-cci.h> #include <media/v4l2-cci.h>
#include <media/v4l2-ctrls.h> #include <media/v4l2-ctrls.h>
#include <media/v4l2-event.h>
#include <media/v4l2-fwnode.h> #include <media/v4l2-fwnode.h>
#include <media/v4l2-subdev.h> #include <media/v4l2-subdev.h>
@ -1059,13 +1058,7 @@ static const struct v4l2_subdev_pad_ops gc05a2_subdev_pad_ops = {
.get_selection = gc05a2_get_selection, .get_selection = gc05a2_get_selection,
}; };
static const struct v4l2_subdev_core_ops gc05a2_core_ops = {
.subscribe_event = v4l2_ctrl_subdev_subscribe_event,
.unsubscribe_event = v4l2_event_subdev_unsubscribe,
};
static const struct v4l2_subdev_ops gc05a2_subdev_ops = { static const struct v4l2_subdev_ops gc05a2_subdev_ops = {
.core = &gc05a2_core_ops,
.video = &gc05a2_video_ops, .video = &gc05a2_video_ops,
.pad = &gc05a2_subdev_pad_ops, .pad = &gc05a2_subdev_pad_ops,
}; };
@ -1271,8 +1264,7 @@ static int gc05a2_probe(struct i2c_client *client)
return dev_err_probe(dev, ret, return dev_err_probe(dev, ret,
"failed to init controls\n"); "failed to init controls\n");
gc05a2->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE | gc05a2->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
V4L2_SUBDEV_FL_HAS_EVENTS;
gc05a2->pad.flags = MEDIA_PAD_FL_SOURCE; gc05a2->pad.flags = MEDIA_PAD_FL_SOURCE;
gc05a2->sd.dev = &client->dev; gc05a2->sd.dev = &client->dev;
gc05a2->sd.entity.function = MEDIA_ENT_F_CAM_SENSOR; gc05a2->sd.entity.function = MEDIA_ENT_F_CAM_SENSOR;

View File

@ -24,7 +24,6 @@
#include <media/v4l2-cci.h> #include <media/v4l2-cci.h>
#include <media/v4l2-ctrls.h> #include <media/v4l2-ctrls.h>
#include <media/v4l2-event.h>
#include <media/v4l2-fwnode.h> #include <media/v4l2-fwnode.h>
#include <media/v4l2-subdev.h> #include <media/v4l2-subdev.h>
@ -1001,13 +1000,7 @@ static const struct v4l2_subdev_pad_ops gc08a3_subdev_pad_ops = {
.get_selection = gc08a3_get_selection, .get_selection = gc08a3_get_selection,
}; };
static const struct v4l2_subdev_core_ops gc08a3_core_ops = {
.subscribe_event = v4l2_ctrl_subdev_subscribe_event,
.unsubscribe_event = v4l2_event_subdev_unsubscribe,
};
static const struct v4l2_subdev_ops gc08a3_subdev_ops = { static const struct v4l2_subdev_ops gc08a3_subdev_ops = {
.core = &gc08a3_core_ops,
.video = &gc08a3_video_ops, .video = &gc08a3_video_ops,
.pad = &gc08a3_subdev_pad_ops, .pad = &gc08a3_subdev_pad_ops,
}; };
@ -1247,8 +1240,7 @@ static int gc08a3_probe(struct i2c_client *client)
goto err_power_off; goto err_power_off;
} }
gc08a3->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE | gc08a3->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
V4L2_SUBDEV_FL_HAS_EVENTS;
gc08a3->pad.flags = MEDIA_PAD_FL_SOURCE; gc08a3->pad.flags = MEDIA_PAD_FL_SOURCE;
gc08a3->sd.dev = &client->dev; gc08a3->sd.dev = &client->dev;
gc08a3->sd.entity.function = MEDIA_ENT_F_CAM_SENSOR; gc08a3->sd.entity.function = MEDIA_ENT_F_CAM_SENSOR;

View File

@ -21,7 +21,6 @@
#include <media/v4l2-cci.h> #include <media/v4l2-cci.h>
#include <media/v4l2-ctrls.h> #include <media/v4l2-ctrls.h>
#include <media/v4l2-device.h> #include <media/v4l2-device.h>
#include <media/v4l2-event.h>
#include <media/v4l2-fwnode.h> #include <media/v4l2-fwnode.h>
#include <media/v4l2-mediabus.h> #include <media/v4l2-mediabus.h>
@ -899,9 +898,11 @@ static int gc2145_config_mipi_mode(struct gc2145 *gc2145,
return ret; return ret;
} }
static int gc2145_start_streaming(struct gc2145 *gc2145, static int gc2145_enable_streams(struct v4l2_subdev *sd,
struct v4l2_subdev_state *state) struct v4l2_subdev_state *state, u32 pad,
u64 streams_mask)
{ {
struct gc2145 *gc2145 = to_gc2145(sd);
struct i2c_client *client = v4l2_get_subdevdata(&gc2145->sd); struct i2c_client *client = v4l2_get_subdevdata(&gc2145->sd);
const struct gc2145_format *gc2145_format; const struct gc2145_format *gc2145_format;
struct v4l2_mbus_framefmt *fmt; struct v4l2_mbus_framefmt *fmt;
@ -967,8 +968,11 @@ err_rpm_put:
return ret; return ret;
} }
static void gc2145_stop_streaming(struct gc2145 *gc2145) static int gc2145_disable_streams(struct v4l2_subdev *sd,
struct v4l2_subdev_state *state, u32 pad,
u64 streams_mask)
{ {
struct gc2145 *gc2145 = to_gc2145(sd);
struct i2c_client *client = v4l2_get_subdevdata(&gc2145->sd); struct i2c_client *client = v4l2_get_subdevdata(&gc2145->sd);
int ret = 0; int ret = 0;
@ -983,22 +987,6 @@ static void gc2145_stop_streaming(struct gc2145 *gc2145)
pm_runtime_mark_last_busy(&client->dev); pm_runtime_mark_last_busy(&client->dev);
pm_runtime_put_autosuspend(&client->dev); pm_runtime_put_autosuspend(&client->dev);
}
static int gc2145_set_stream(struct v4l2_subdev *sd, int enable)
{
struct gc2145 *gc2145 = to_gc2145(sd);
struct v4l2_subdev_state *state;
int ret = 0;
state = v4l2_subdev_lock_and_get_active_state(sd);
if (enable)
ret = gc2145_start_streaming(gc2145, state);
else
gc2145_stop_streaming(gc2145);
v4l2_subdev_unlock_state(state);
return ret; return ret;
} }
@ -1123,13 +1111,8 @@ static const u8 test_pattern_val[] = {
GC2145_TEST_UNIFORM | GC2145_TEST_BLACK, GC2145_TEST_UNIFORM | GC2145_TEST_BLACK,
}; };
static const struct v4l2_subdev_core_ops gc2145_core_ops = {
.subscribe_event = v4l2_ctrl_subdev_subscribe_event,
.unsubscribe_event = v4l2_event_subdev_unsubscribe,
};
static const struct v4l2_subdev_video_ops gc2145_video_ops = { static const struct v4l2_subdev_video_ops gc2145_video_ops = {
.s_stream = gc2145_set_stream, .s_stream = v4l2_subdev_s_stream_helper,
}; };
static const struct v4l2_subdev_pad_ops gc2145_pad_ops = { static const struct v4l2_subdev_pad_ops gc2145_pad_ops = {
@ -1138,10 +1121,11 @@ static const struct v4l2_subdev_pad_ops gc2145_pad_ops = {
.set_fmt = gc2145_set_pad_format, .set_fmt = gc2145_set_pad_format,
.get_selection = gc2145_get_selection, .get_selection = gc2145_get_selection,
.enum_frame_size = gc2145_enum_frame_size, .enum_frame_size = gc2145_enum_frame_size,
.enable_streams = gc2145_enable_streams,
.disable_streams = gc2145_disable_streams,
}; };
static const struct v4l2_subdev_ops gc2145_subdev_ops = { static const struct v4l2_subdev_ops gc2145_subdev_ops = {
.core = &gc2145_core_ops,
.video = &gc2145_video_ops, .video = &gc2145_video_ops,
.pad = &gc2145_pad_ops, .pad = &gc2145_pad_ops,
}; };
@ -1407,8 +1391,7 @@ static int gc2145_probe(struct i2c_client *client)
goto error_power_off; goto error_power_off;
/* Initialize subdev */ /* Initialize subdev */
gc2145->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE | gc2145->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
V4L2_SUBDEV_FL_HAS_EVENTS;
gc2145->sd.entity.function = MEDIA_ENT_F_CAM_SENSOR; gc2145->sd.entity.function = MEDIA_ENT_F_CAM_SENSOR;
/* Initialize source pad */ /* Initialize source pad */

View File

@ -644,7 +644,7 @@ struct hi556 {
/* Current mode */ /* Current mode */
const struct hi556_mode *cur_mode; const struct hi556_mode *cur_mode;
/* To serialize asynchronus callbacks */ /* To serialize asynchronous callbacks */
struct mutex mutex; struct mutex mutex;
/* True if the device has been identified */ /* True if the device has been identified */

View File

@ -26,7 +26,6 @@
#include <media/v4l2-cci.h> #include <media/v4l2-cci.h>
#include <media/v4l2-ctrls.h> #include <media/v4l2-ctrls.h>
#include <media/v4l2-device.h> #include <media/v4l2-device.h>
#include <media/v4l2-event.h>
#include <media/v4l2-fwnode.h> #include <media/v4l2-fwnode.h>
#include <media/v4l2-mediabus.h> #include <media/v4l2-mediabus.h>
@ -922,11 +921,6 @@ static int imx219_init_state(struct v4l2_subdev *sd,
return 0; return 0;
} }
static const struct v4l2_subdev_core_ops imx219_core_ops = {
.subscribe_event = v4l2_ctrl_subdev_subscribe_event,
.unsubscribe_event = v4l2_event_subdev_unsubscribe,
};
static const struct v4l2_subdev_video_ops imx219_video_ops = { static const struct v4l2_subdev_video_ops imx219_video_ops = {
.s_stream = imx219_set_stream, .s_stream = imx219_set_stream,
}; };
@ -940,7 +934,6 @@ static const struct v4l2_subdev_pad_ops imx219_pad_ops = {
}; };
static const struct v4l2_subdev_ops imx219_subdev_ops = { static const struct v4l2_subdev_ops imx219_subdev_ops = {
.core = &imx219_core_ops,
.video = &imx219_video_ops, .video = &imx219_video_ops,
.pad = &imx219_pad_ops, .pad = &imx219_pad_ops,
}; };
@ -1166,8 +1159,7 @@ static int imx219_probe(struct i2c_client *client)
goto error_power_off; goto error_power_off;
/* Initialize subdev */ /* Initialize subdev */
imx219->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE | imx219->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
V4L2_SUBDEV_FL_HAS_EVENTS;
imx219->sd.entity.function = MEDIA_ENT_F_CAM_SENSOR; imx219->sd.entity.function = MEDIA_ENT_F_CAM_SENSOR;
/* Initialize source pad */ /* Initialize source pad */

View File

@ -32,7 +32,6 @@
#include <media/v4l2-cci.h> #include <media/v4l2-cci.h>
#include <media/v4l2-ctrls.h> #include <media/v4l2-ctrls.h>
#include <media/v4l2-device.h> #include <media/v4l2-device.h>
#include <media/v4l2-event.h>
#include <media/v4l2-fwnode.h> #include <media/v4l2-fwnode.h>
#include <media/v4l2-mediabus.h> #include <media/v4l2-mediabus.h>
@ -1284,11 +1283,6 @@ static int imx283_get_selection(struct v4l2_subdev *sd,
} }
} }
static const struct v4l2_subdev_core_ops imx283_core_ops = {
.subscribe_event = v4l2_ctrl_subdev_subscribe_event,
.unsubscribe_event = v4l2_event_subdev_unsubscribe,
};
static const struct v4l2_subdev_video_ops imx283_video_ops = { static const struct v4l2_subdev_video_ops imx283_video_ops = {
.s_stream = v4l2_subdev_s_stream_helper, .s_stream = v4l2_subdev_s_stream_helper,
}; };
@ -1308,7 +1302,6 @@ static const struct v4l2_subdev_internal_ops imx283_internal_ops = {
}; };
static const struct v4l2_subdev_ops imx283_subdev_ops = { static const struct v4l2_subdev_ops imx283_subdev_ops = {
.core = &imx283_core_ops,
.video = &imx283_video_ops, .video = &imx283_video_ops,
.pad = &imx283_pad_ops, .pad = &imx283_pad_ops,
}; };
@ -1548,8 +1541,7 @@ static int imx283_probe(struct i2c_client *client)
goto error_pm; goto error_pm;
/* Initialize subdev */ /* Initialize subdev */
imx283->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE | imx283->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
V4L2_SUBDEV_FL_HAS_EVENTS;
imx283->sd.entity.function = MEDIA_ENT_F_CAM_SENSOR; imx283->sd.entity.function = MEDIA_ENT_F_CAM_SENSOR;
imx283->sd.internal_ops = &imx283_internal_ops; imx283->sd.internal_ops = &imx283_internal_ops;

View File

@ -24,7 +24,6 @@
#include <media/v4l2-cci.h> #include <media/v4l2-cci.h>
#include <media/v4l2-ctrls.h> #include <media/v4l2-ctrls.h>
#include <media/v4l2-device.h> #include <media/v4l2-device.h>
#include <media/v4l2-event.h>
#include <media/v4l2-fwnode.h> #include <media/v4l2-fwnode.h>
#include <media/v4l2-subdev.h> #include <media/v4l2-subdev.h>
@ -78,7 +77,6 @@
#define IMX290_ADBIT2 CCI_REG8(0x317c) #define IMX290_ADBIT2 CCI_REG8(0x317c)
#define IMX290_ADBIT2_10BIT 0x12 #define IMX290_ADBIT2_10BIT 0x12
#define IMX290_ADBIT2_12BIT 0x00 #define IMX290_ADBIT2_12BIT 0x00
#define IMX290_CHIP_ID CCI_REG16_LE(0x319a)
#define IMX290_ADBIT3 CCI_REG8(0x31ec) #define IMX290_ADBIT3 CCI_REG8(0x31ec)
#define IMX290_ADBIT3_10BIT 0x37 #define IMX290_ADBIT3_10BIT 0x37
#define IMX290_ADBIT3_12BIT 0x0e #define IMX290_ADBIT3_12BIT 0x0e
@ -1211,11 +1209,6 @@ static int imx290_entity_init_state(struct v4l2_subdev *subdev,
return 0; return 0;
} }
static const struct v4l2_subdev_core_ops imx290_core_ops = {
.subscribe_event = v4l2_ctrl_subdev_subscribe_event,
.unsubscribe_event = v4l2_event_subdev_unsubscribe,
};
static const struct v4l2_subdev_video_ops imx290_video_ops = { static const struct v4l2_subdev_video_ops imx290_video_ops = {
.s_stream = imx290_set_stream, .s_stream = imx290_set_stream,
}; };
@ -1229,7 +1222,6 @@ static const struct v4l2_subdev_pad_ops imx290_pad_ops = {
}; };
static const struct v4l2_subdev_ops imx290_subdev_ops = { static const struct v4l2_subdev_ops imx290_subdev_ops = {
.core = &imx290_core_ops,
.video = &imx290_video_ops, .video = &imx290_video_ops,
.pad = &imx290_pad_ops, .pad = &imx290_pad_ops,
}; };
@ -1250,11 +1242,20 @@ static int imx290_subdev_init(struct imx290 *imx290)
imx290->current_mode = &imx290_modes_ptr(imx290)[0]; imx290->current_mode = &imx290_modes_ptr(imx290)[0];
/*
* After linking the subdev with the imx290 instance, we are allowed to
* use the pm_runtime functions. Decrease the PM usage count. The device
* will get suspended after the autosuspend delay, turning the power
* off. However, the communication happening in imx290_ctrl_update()
* will already be prevented even before the delay.
*/
v4l2_i2c_subdev_init(&imx290->sd, client, &imx290_subdev_ops); v4l2_i2c_subdev_init(&imx290->sd, client, &imx290_subdev_ops);
imx290->sd.internal_ops = &imx290_internal_ops;
imx290->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE |
V4L2_SUBDEV_FL_HAS_EVENTS;
imx290->sd.dev = imx290->dev; imx290->sd.dev = imx290->dev;
pm_runtime_mark_last_busy(imx290->dev);
pm_runtime_put_autosuspend(imx290->dev);
imx290->sd.internal_ops = &imx290_internal_ops;
imx290->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
imx290->sd.entity.ops = &imx290_subdev_entity_ops; imx290->sd.entity.ops = &imx290_subdev_entity_ops;
imx290->sd.entity.function = MEDIA_ENT_F_CAM_SENSOR; imx290->sd.entity.function = MEDIA_ENT_F_CAM_SENSOR;
@ -1580,6 +1581,16 @@ static int imx290_probe(struct i2c_client *client)
pm_runtime_set_autosuspend_delay(dev, 1000); pm_runtime_set_autosuspend_delay(dev, 1000);
pm_runtime_use_autosuspend(dev); pm_runtime_use_autosuspend(dev);
/*
* Make sure the sensor is available, in STANDBY and not streaming
* before the V4L2 subdev is initialized.
*/
ret = imx290_stop_streaming(imx290);
if (ret) {
ret = dev_err_probe(dev, ret, "Could not initialize device\n");
goto err_pm;
}
/* Initialize the V4L2 subdev. */ /* Initialize the V4L2 subdev. */
ret = imx290_subdev_init(imx290); ret = imx290_subdev_init(imx290);
if (ret) if (ret)
@ -1599,13 +1610,6 @@ static int imx290_probe(struct i2c_client *client)
goto err_subdev; goto err_subdev;
} }
/*
* Decrease the PM usage count. The device will get suspended after the
* autosuspend delay, turning the power off.
*/
pm_runtime_mark_last_busy(dev);
pm_runtime_put_autosuspend(dev);
return 0; return 0;
err_subdev: err_subdev:

View File

@ -1113,8 +1113,7 @@ static int imx415_subdev_init(struct imx415 *sensor)
if (ret) if (ret)
return ret; return ret;
sensor->subdev.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE | sensor->subdev.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
V4L2_SUBDEV_FL_HAS_EVENTS;
sensor->pad.flags = MEDIA_PAD_FL_SOURCE; sensor->pad.flags = MEDIA_PAD_FL_SOURCE;
sensor->subdev.entity.function = MEDIA_ENT_F_CAM_SENSOR; sensor->subdev.entity.function = MEDIA_ENT_F_CAM_SENSOR;
ret = media_entity_pads_init(&sensor->subdev.entity, 1, &sensor->pad); ret = media_entity_pads_init(&sensor->subdev.entity, 1, &sensor->pad);

View File

@ -697,8 +697,10 @@ static int max96717_subdev_init(struct max96717_priv *priv)
priv->pads[MAX96717_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE; priv->pads[MAX96717_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE;
ret = media_entity_pads_init(&priv->sd.entity, 2, priv->pads); ret = media_entity_pads_init(&priv->sd.entity, 2, priv->pads);
if (ret) if (ret) {
return dev_err_probe(dev, ret, "Failed to init pads\n"); dev_err_probe(dev, ret, "Failed to init pads\n");
goto err_free_ctrl;
}
ret = v4l2_subdev_init_finalize(&priv->sd); ret = v4l2_subdev_init_finalize(&priv->sd);
if (ret) { if (ret) {

View File

@ -17,14 +17,12 @@
#include <linux/log2.h> #include <linux/log2.h>
#include <linux/mod_devicetable.h> #include <linux/mod_devicetable.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/of.h>
#include <linux/of_graph.h>
#include <linux/pm.h> #include <linux/pm.h>
#include <linux/property.h>
#include <linux/regulator/consumer.h> #include <linux/regulator/consumer.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/videodev2.h> #include <linux/videodev2.h>
#include <media/i2c/mt9p031.h>
#include <media/v4l2-async.h> #include <media/v4l2-async.h>
#include <media/v4l2-ctrls.h> #include <media/v4l2-ctrls.h>
#include <media/v4l2-device.h> #include <media/v4l2-device.h>
@ -113,18 +111,25 @@
#define MT9P031_TEST_PATTERN_RED 0xa2 #define MT9P031_TEST_PATTERN_RED 0xa2
#define MT9P031_TEST_PATTERN_BLUE 0xa3 #define MT9P031_TEST_PATTERN_BLUE 0xa3
struct mt9p031_model_info {
u32 code;
};
struct mt9p031 { struct mt9p031 {
struct v4l2_subdev subdev; struct v4l2_subdev subdev;
struct media_pad pad; struct media_pad pad;
struct v4l2_rect crop; /* Sensor window */ struct v4l2_rect crop; /* Sensor window */
struct v4l2_mbus_framefmt format; struct v4l2_mbus_framefmt format;
struct mt9p031_platform_data *pdata;
struct mutex power_lock; /* lock to protect power_count */ struct mutex power_lock; /* lock to protect power_count */
int power_count; int power_count;
struct clk *clk; struct clk *clk;
struct regulator_bulk_data regulators[3]; struct regulator_bulk_data regulators[3];
unsigned int pixclk_pol:1;
int ext_freq;
int target_freq;
u32 code; u32 code;
struct aptina_pll pll; struct aptina_pll pll;
unsigned int clk_div; unsigned int clk_div;
@ -225,7 +230,6 @@ static int mt9p031_clk_setup(struct mt9p031 *mt9p031)
}; };
struct i2c_client *client = v4l2_get_subdevdata(&mt9p031->subdev); struct i2c_client *client = v4l2_get_subdevdata(&mt9p031->subdev);
struct mt9p031_platform_data *pdata = mt9p031->pdata;
unsigned long ext_freq; unsigned long ext_freq;
int ret; int ret;
@ -233,7 +237,7 @@ static int mt9p031_clk_setup(struct mt9p031 *mt9p031)
if (IS_ERR(mt9p031->clk)) if (IS_ERR(mt9p031->clk))
return PTR_ERR(mt9p031->clk); return PTR_ERR(mt9p031->clk);
ret = clk_set_rate(mt9p031->clk, pdata->ext_freq); ret = clk_set_rate(mt9p031->clk, mt9p031->ext_freq);
if (ret < 0) if (ret < 0)
return ret; return ret;
@ -245,7 +249,7 @@ static int mt9p031_clk_setup(struct mt9p031 *mt9p031)
if (ext_freq > limits.ext_clock_max) { if (ext_freq > limits.ext_clock_max) {
unsigned int div; unsigned int div;
div = DIV_ROUND_UP(ext_freq, pdata->target_freq); div = DIV_ROUND_UP(ext_freq, mt9p031->target_freq);
div = roundup_pow_of_two(div) / 2; div = roundup_pow_of_two(div) / 2;
mt9p031->clk_div = min_t(unsigned int, div, 64); mt9p031->clk_div = min_t(unsigned int, div, 64);
@ -255,7 +259,7 @@ static int mt9p031_clk_setup(struct mt9p031 *mt9p031)
} }
mt9p031->pll.ext_clock = ext_freq; mt9p031->pll.ext_clock = ext_freq;
mt9p031->pll.pix_clock = pdata->target_freq; mt9p031->pll.pix_clock = mt9p031->target_freq;
mt9p031->use_pll = true; mt9p031->use_pll = true;
return aptina_pll_calculate(&client->dev, &limits, &mt9p031->pll); return aptina_pll_calculate(&client->dev, &limits, &mt9p031->pll);
@ -376,7 +380,7 @@ static int __mt9p031_set_power(struct mt9p031 *mt9p031, bool on)
} }
/* Configure the pixel clock polarity */ /* Configure the pixel clock polarity */
if (mt9p031->pdata && mt9p031->pdata->pixclk_pol) { if (mt9p031->pixclk_pol) {
ret = mt9p031_write(client, MT9P031_PIXEL_CLOCK_CONTROL, ret = mt9p031_write(client, MT9P031_PIXEL_CLOCK_CONTROL,
MT9P031_PIXEL_CLOCK_INVERT); MT9P031_PIXEL_CLOCK_INVERT);
if (ret < 0) if (ret < 0)
@ -1057,53 +1061,41 @@ static const struct v4l2_subdev_internal_ops mt9p031_subdev_internal_ops = {
* Driver initialization and probing * Driver initialization and probing
*/ */
static struct mt9p031_platform_data * static int mt9p031_parse_properties(struct mt9p031 *mt9p031, struct device *dev)
mt9p031_get_pdata(struct i2c_client *client)
{ {
struct mt9p031_platform_data *pdata = NULL;
struct device_node *np;
struct v4l2_fwnode_endpoint endpoint = { struct v4l2_fwnode_endpoint endpoint = {
.bus_type = V4L2_MBUS_PARALLEL .bus_type = V4L2_MBUS_PARALLEL
}; };
struct fwnode_handle *np;
int ret;
if (!IS_ENABLED(CONFIG_OF) || !client->dev.of_node) np = fwnode_graph_get_next_endpoint(dev_fwnode(dev), NULL);
return client->dev.platform_data;
np = of_graph_get_endpoint_by_regs(client->dev.of_node, 0, -1);
if (!np) if (!np)
return NULL; return dev_err_probe(dev, -EINVAL, "endpoint node not found\n");
if (v4l2_fwnode_endpoint_parse(of_fwnode_handle(np), &endpoint) < 0) ret = v4l2_fwnode_endpoint_parse(np, &endpoint);
goto done; fwnode_handle_put(np);
if (ret)
return dev_err_probe(dev, -EINVAL, "could not parse endpoint\n");
pdata = devm_kzalloc(&client->dev, sizeof(*pdata), GFP_KERNEL); fwnode_property_read_u32(np, "input-clock-frequency",
if (!pdata) &mt9p031->ext_freq);
goto done; fwnode_property_read_u32(np, "pixel-clock-frequency",
&mt9p031->target_freq);
of_property_read_u32(np, "input-clock-frequency", &pdata->ext_freq); mt9p031->pixclk_pol = !!(endpoint.bus.parallel.flags &
of_property_read_u32(np, "pixel-clock-frequency", &pdata->target_freq);
pdata->pixclk_pol = !!(endpoint.bus.parallel.flags &
V4L2_MBUS_PCLK_SAMPLE_RISING); V4L2_MBUS_PCLK_SAMPLE_RISING);
done: return 0;
of_node_put(np);
return pdata;
} }
static int mt9p031_probe(struct i2c_client *client) static int mt9p031_probe(struct i2c_client *client)
{ {
struct mt9p031_platform_data *pdata = mt9p031_get_pdata(client);
struct i2c_adapter *adapter = client->adapter; struct i2c_adapter *adapter = client->adapter;
struct mt9p031 *mt9p031; struct mt9p031 *mt9p031;
unsigned int i; unsigned int i;
int ret; int ret;
if (pdata == NULL) {
dev_err(&client->dev, "No platform data\n");
return -EINVAL;
}
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WORD_DATA)) { if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WORD_DATA)) {
dev_warn(&client->dev, dev_warn(&client->dev,
"I2C-Adapter doesn't support I2C_FUNC_SMBUS_WORD\n"); "I2C-Adapter doesn't support I2C_FUNC_SMBUS_WORD\n");
@ -1114,10 +1106,13 @@ static int mt9p031_probe(struct i2c_client *client)
if (mt9p031 == NULL) if (mt9p031 == NULL)
return -ENOMEM; return -ENOMEM;
mt9p031->pdata = pdata; ret = mt9p031_parse_properties(mt9p031, &client->dev);
if (ret)
return ret;
mt9p031->output_control = MT9P031_OUTPUT_CONTROL_DEF; mt9p031->output_control = MT9P031_OUTPUT_CONTROL_DEF;
mt9p031->mode2 = MT9P031_READ_MODE_2_ROW_BLC; mt9p031->mode2 = MT9P031_READ_MODE_2_ROW_BLC;
mt9p031->code = (uintptr_t)i2c_get_match_data(client); mt9p031->code = (uintptr_t)device_get_match_data(&client->dev);
mt9p031->regulators[0].supply = "vdd"; mt9p031->regulators[0].supply = "vdd";
mt9p031->regulators[1].supply = "vdd_io"; mt9p031->regulators[1].supply = "vdd_io";
@ -1145,8 +1140,8 @@ static int mt9p031_probe(struct i2c_client *client)
v4l2_ctrl_new_std(&mt9p031->ctrls, &mt9p031_ctrl_ops, v4l2_ctrl_new_std(&mt9p031->ctrls, &mt9p031_ctrl_ops,
V4L2_CID_VFLIP, 0, 1, 1, 0); V4L2_CID_VFLIP, 0, 1, 1, 0);
v4l2_ctrl_new_std(&mt9p031->ctrls, &mt9p031_ctrl_ops, v4l2_ctrl_new_std(&mt9p031->ctrls, &mt9p031_ctrl_ops,
V4L2_CID_PIXEL_RATE, pdata->target_freq, V4L2_CID_PIXEL_RATE, mt9p031->target_freq,
pdata->target_freq, 1, pdata->target_freq); mt9p031->target_freq, 1, mt9p031->target_freq);
v4l2_ctrl_new_std_menu_items(&mt9p031->ctrls, &mt9p031_ctrl_ops, v4l2_ctrl_new_std_menu_items(&mt9p031->ctrls, &mt9p031_ctrl_ops,
V4L2_CID_TEST_PATTERN, V4L2_CID_TEST_PATTERN,
ARRAY_SIZE(mt9p031_test_pattern_menu) - 1, 0, ARRAY_SIZE(mt9p031_test_pattern_menu) - 1, 0,
@ -1213,18 +1208,18 @@ static void mt9p031_remove(struct i2c_client *client)
mutex_destroy(&mt9p031->power_lock); mutex_destroy(&mt9p031->power_lock);
} }
static const struct i2c_device_id mt9p031_id[] = { static const struct mt9p031_model_info mt9p031_models_bayer = {
{ "mt9p006", MEDIA_BUS_FMT_SGRBG12_1X12 }, .code = MEDIA_BUS_FMT_SGRBG12_1X12
{ "mt9p031", MEDIA_BUS_FMT_SGRBG12_1X12 }, };
{ "mt9p031m", MEDIA_BUS_FMT_Y12_1X12 },
{ /* sentinel */ } static const struct mt9p031_model_info mt9p031_models_mono = {
.code = MEDIA_BUS_FMT_Y12_1X12
}; };
MODULE_DEVICE_TABLE(i2c, mt9p031_id);
static const struct of_device_id mt9p031_of_match[] = { static const struct of_device_id mt9p031_of_match[] = {
{ .compatible = "aptina,mt9p006", .data = (void *)MEDIA_BUS_FMT_SGRBG12_1X12 }, { .compatible = "aptina,mt9p006", .data = &mt9p031_models_bayer },
{ .compatible = "aptina,mt9p031", .data = (void *)MEDIA_BUS_FMT_SGRBG12_1X12 }, { .compatible = "aptina,mt9p031", .data = &mt9p031_models_bayer },
{ .compatible = "aptina,mt9p031m", .data = (void *)MEDIA_BUS_FMT_Y12_1X12 }, { .compatible = "aptina,mt9p031m", .data = &mt9p031_models_mono },
{ /* sentinel */ } { /* sentinel */ }
}; };
MODULE_DEVICE_TABLE(of, mt9p031_of_match); MODULE_DEVICE_TABLE(of, mt9p031_of_match);
@ -1236,7 +1231,6 @@ static struct i2c_driver mt9p031_i2c_driver = {
}, },
.probe = mt9p031_probe, .probe = mt9p031_probe,
.remove = mt9p031_remove, .remove = mt9p031_remove,
.id_table = mt9p031_id,
}; };
module_i2c_driver(mt9p031_i2c_driver); module_i2c_driver(mt9p031_i2c_driver);

View File

@ -13,7 +13,6 @@
#include <media/v4l2-ctrls.h> #include <media/v4l2-ctrls.h>
#include <media/v4l2-device.h> #include <media/v4l2-device.h>
#include <media/v4l2-event.h>
#include <media/v4l2-fwnode.h> #include <media/v4l2-fwnode.h>
#define OV01A10_LINK_FREQ_400MHZ 400000000ULL #define OV01A10_LINK_FREQ_400MHZ 400000000ULL
@ -804,8 +803,6 @@ static int ov01a10_get_selection(struct v4l2_subdev *sd,
static const struct v4l2_subdev_core_ops ov01a10_core_ops = { static const struct v4l2_subdev_core_ops ov01a10_core_ops = {
.log_status = v4l2_ctrl_subdev_log_status, .log_status = v4l2_ctrl_subdev_log_status,
.subscribe_event = v4l2_ctrl_subdev_subscribe_event,
.unsubscribe_event = v4l2_event_subdev_unsubscribe,
}; };
static const struct v4l2_subdev_video_ops ov01a10_video_ops = { static const struct v4l2_subdev_video_ops ov01a10_video_ops = {
@ -892,8 +889,7 @@ static int ov01a10_probe(struct i2c_client *client)
} }
ov01a10->sd.state_lock = ov01a10->ctrl_handler.lock; ov01a10->sd.state_lock = ov01a10->ctrl_handler.lock;
ov01a10->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE | ov01a10->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
V4L2_SUBDEV_FL_HAS_EVENTS;
ov01a10->sd.entity.ops = &ov01a10_subdev_entity_ops; ov01a10->sd.entity.ops = &ov01a10_subdev_entity_ops;
ov01a10->sd.entity.function = MEDIA_ENT_F_CAM_SENSOR; ov01a10->sd.entity.function = MEDIA_ENT_F_CAM_SENSOR;
ov01a10->pad.flags = MEDIA_PAD_FL_SOURCE; ov01a10->pad.flags = MEDIA_PAD_FL_SOURCE;

View File

@ -3,10 +3,13 @@
#include <linux/unaligned.h> #include <linux/unaligned.h>
#include <linux/acpi.h> #include <linux/acpi.h>
#include <linux/clk.h>
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/gpio/consumer.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/pm_runtime.h> #include <linux/pm_runtime.h>
#include <linux/regulator/consumer.h>
#include <media/v4l2-ctrls.h> #include <media/v4l2-ctrls.h>
#include <media/v4l2-device.h> #include <media/v4l2-device.h>
#include <media/v4l2-fwnode.h> #include <media/v4l2-fwnode.h>
@ -1215,7 +1218,7 @@ static const char * const ov08x40_test_pattern_menu[] = {
/* Configurations for supported link frequencies */ /* Configurations for supported link frequencies */
#define OV08X40_LINK_FREQ_400MHZ 400000000ULL #define OV08X40_LINK_FREQ_400MHZ 400000000ULL
#define OV08X40_SCLK_96MHZ 96000000ULL #define OV08X40_SCLK_96MHZ 96000000ULL
#define OV08X40_EXT_CLK 19200000 #define OV08X40_XVCLK 19200000
#define OV08X40_DATA_LANES 4 #define OV08X40_DATA_LANES 4
/* /*
@ -1279,6 +1282,12 @@ static const struct ov08x40_mode supported_modes[] = {
}, },
}; };
static const char * const ov08x40_supply_names[] = {
"dovdd", /* Digital I/O power */
"avdd", /* Analog power */
"dvdd", /* Digital core power */
};
struct ov08x40 { struct ov08x40 {
struct v4l2_subdev sd; struct v4l2_subdev sd;
struct media_pad pad; struct media_pad pad;
@ -1291,6 +1300,10 @@ struct ov08x40 {
struct v4l2_ctrl *hblank; struct v4l2_ctrl *hblank;
struct v4l2_ctrl *exposure; struct v4l2_ctrl *exposure;
struct clk *xvclk;
struct gpio_desc *reset_gpio;
struct regulator_bulk_data supplies[ARRAY_SIZE(ov08x40_supply_names)];
/* Current mode */ /* Current mode */
const struct ov08x40_mode *cur_mode; const struct ov08x40_mode *cur_mode;
@ -1303,6 +1316,61 @@ struct ov08x40 {
#define to_ov08x40(_sd) container_of(_sd, struct ov08x40, sd) #define to_ov08x40(_sd) container_of(_sd, struct ov08x40, sd)
static int ov08x40_power_on(struct device *dev)
{
struct v4l2_subdev *sd = dev_get_drvdata(dev);
struct ov08x40 *ov08x = to_ov08x40(sd);
int ret;
if (is_acpi_node(dev_fwnode(dev)))
return 0;
ret = clk_prepare_enable(ov08x->xvclk);
if (ret < 0) {
dev_err(dev, "failed to enable xvclk\n");
return ret;
}
if (ov08x->reset_gpio) {
gpiod_set_value_cansleep(ov08x->reset_gpio, 1);
usleep_range(1000, 2000);
}
ret = regulator_bulk_enable(ARRAY_SIZE(ov08x40_supply_names),
ov08x->supplies);
if (ret < 0) {
dev_err(dev, "failed to enable regulators\n");
goto disable_clk;
}
gpiod_set_value_cansleep(ov08x->reset_gpio, 0);
usleep_range(1500, 1800);
return 0;
disable_clk:
gpiod_set_value_cansleep(ov08x->reset_gpio, 1);
clk_disable_unprepare(ov08x->xvclk);
return ret;
}
static int ov08x40_power_off(struct device *dev)
{
struct v4l2_subdev *sd = dev_get_drvdata(dev);
struct ov08x40 *ov08x = to_ov08x40(sd);
if (is_acpi_node(dev_fwnode(dev)))
return 0;
gpiod_set_value_cansleep(ov08x->reset_gpio, 1);
regulator_bulk_disable(ARRAY_SIZE(ov08x40_supply_names),
ov08x->supplies);
clk_disable_unprepare(ov08x->xvclk);
return 0;
}
/* Read registers up to 4 at a time */ /* Read registers up to 4 at a time */
static int ov08x40_read_reg(struct ov08x40 *ov08x, static int ov08x40_read_reg(struct ov08x40 *ov08x,
u16 reg, u32 len, u32 *val) u16 reg, u32 len, u32 *val)
@ -1339,15 +1407,13 @@ static int ov08x40_read_reg(struct ov08x40 *ov08x,
return 0; return 0;
} }
static int ov08x40_burst_fill_regs(struct ov08x40 *ov08x, u16 first_reg, static int __ov08x40_burst_fill_regs(struct i2c_client *client, u16 first_reg,
u16 last_reg, u8 val) u16 last_reg, size_t num_regs, u8 val)
{ {
struct i2c_client *client = v4l2_get_subdevdata(&ov08x->sd);
struct i2c_msg msgs; struct i2c_msg msgs;
size_t i, num_regs; size_t i;
int ret; int ret;
num_regs = last_reg - first_reg + 1;
msgs.addr = client->addr; msgs.addr = client->addr;
msgs.flags = 0; msgs.flags = 0;
msgs.len = 2 + num_regs; msgs.len = 2 + num_regs;
@ -1373,6 +1439,31 @@ static int ov08x40_burst_fill_regs(struct ov08x40 *ov08x, u16 first_reg,
return 0; return 0;
} }
static int ov08x40_burst_fill_regs(struct ov08x40 *ov08x, u16 first_reg,
u16 last_reg, u8 val)
{
struct i2c_client *client = v4l2_get_subdevdata(&ov08x->sd);
size_t num_regs, num_write_regs;
int ret;
num_regs = last_reg - first_reg + 1;
num_write_regs = num_regs;
if (client->adapter->quirks && client->adapter->quirks->max_write_len)
num_write_regs = client->adapter->quirks->max_write_len - 2;
while (first_reg < last_reg) {
ret = __ov08x40_burst_fill_regs(client, first_reg, last_reg,
num_write_regs, val);
if (ret)
return ret;
first_reg += num_write_regs;
}
return 0;
}
/* Write registers up to 4 at a time */ /* Write registers up to 4 at a time */
static int ov08x40_write_reg(struct ov08x40 *ov08x, static int ov08x40_write_reg(struct ov08x40 *ov08x,
u16 reg, u32 len, u32 __val) u16 reg, u32 len, u32 __val)
@ -2049,7 +2140,7 @@ static void ov08x40_free_controls(struct ov08x40 *ov08x)
mutex_destroy(&ov08x->mutex); mutex_destroy(&ov08x->mutex);
} }
static int ov08x40_check_hwcfg(struct device *dev) static int ov08x40_check_hwcfg(struct ov08x40 *ov08x, struct device *dev)
{ {
struct v4l2_fwnode_endpoint bus_cfg = { struct v4l2_fwnode_endpoint bus_cfg = {
.bus_type = V4L2_MBUS_CSI2_DPHY .bus_type = V4L2_MBUS_CSI2_DPHY
@ -2058,21 +2149,46 @@ static int ov08x40_check_hwcfg(struct device *dev)
struct fwnode_handle *fwnode = dev_fwnode(dev); struct fwnode_handle *fwnode = dev_fwnode(dev);
unsigned int i, j; unsigned int i, j;
int ret; int ret;
u32 ext_clk; u32 xvclk_rate;
if (!fwnode) if (!fwnode)
return -ENXIO; return -ENXIO;
if (!is_acpi_node(fwnode)) {
ov08x->xvclk = devm_clk_get(dev, NULL);
if (IS_ERR(ov08x->xvclk)) {
dev_err(dev, "could not get xvclk clock (%pe)\n",
ov08x->xvclk);
return PTR_ERR(ov08x->xvclk);
}
xvclk_rate = clk_get_rate(ov08x->xvclk);
ov08x->reset_gpio = devm_gpiod_get_optional(dev, "reset",
GPIOD_OUT_LOW);
if (IS_ERR(ov08x->reset_gpio))
return PTR_ERR(ov08x->reset_gpio);
for (i = 0; i < ARRAY_SIZE(ov08x40_supply_names); i++)
ov08x->supplies[i].supply = ov08x40_supply_names[i];
ret = devm_regulator_bulk_get(dev,
ARRAY_SIZE(ov08x40_supply_names),
ov08x->supplies);
if (ret)
return ret;
} else {
ret = fwnode_property_read_u32(dev_fwnode(dev), "clock-frequency", ret = fwnode_property_read_u32(dev_fwnode(dev), "clock-frequency",
&ext_clk); &xvclk_rate);
if (ret) { if (ret) {
dev_err(dev, "can't get clock frequency"); dev_err(dev, "can't get clock frequency");
return ret; return ret;
} }
}
if (ext_clk != OV08X40_EXT_CLK) { if (xvclk_rate != OV08X40_XVCLK) {
dev_err(dev, "external clock %d is not supported", dev_err(dev, "external clock %d is not supported",
ext_clk); xvclk_rate);
return -EINVAL; return -EINVAL;
} }
@ -2120,32 +2236,37 @@ out_err:
} }
static int ov08x40_probe(struct i2c_client *client) static int ov08x40_probe(struct i2c_client *client)
{ { struct ov08x40 *ov08x;
struct ov08x40 *ov08x;
int ret; int ret;
bool full_power; bool full_power;
/* Check HW config */
ret = ov08x40_check_hwcfg(&client->dev);
if (ret) {
dev_err(&client->dev, "failed to check hwcfg: %d", ret);
return ret;
}
ov08x = devm_kzalloc(&client->dev, sizeof(*ov08x), GFP_KERNEL); ov08x = devm_kzalloc(&client->dev, sizeof(*ov08x), GFP_KERNEL);
if (!ov08x) if (!ov08x)
return -ENOMEM; return -ENOMEM;
/* Check HW config */
ret = ov08x40_check_hwcfg(ov08x, &client->dev);
if (ret) {
dev_err(&client->dev, "failed to check hwcfg: %d", ret);
return ret;
}
/* Initialize subdev */ /* Initialize subdev */
v4l2_i2c_subdev_init(&ov08x->sd, client, &ov08x40_subdev_ops); v4l2_i2c_subdev_init(&ov08x->sd, client, &ov08x40_subdev_ops);
full_power = acpi_dev_state_d0(&client->dev); full_power = acpi_dev_state_d0(&client->dev);
if (full_power) { if (full_power) {
ret = ov08x40_power_on(&client->dev);
if (ret) {
dev_err(&client->dev, "failed to power on\n");
return ret;
}
/* Check module identity */ /* Check module identity */
ret = ov08x40_identify_module(ov08x); ret = ov08x40_identify_module(ov08x);
if (ret) { if (ret) {
dev_err(&client->dev, "failed to find sensor: %d\n", ret); dev_err(&client->dev, "failed to find sensor: %d\n", ret);
return ret; goto probe_power_off;
} }
} }
@ -2154,7 +2275,7 @@ static int ov08x40_probe(struct i2c_client *client)
ret = ov08x40_init_controls(ov08x); ret = ov08x40_init_controls(ov08x);
if (ret) if (ret)
return ret; goto probe_power_off;
/* Initialize subdev */ /* Initialize subdev */
ov08x->sd.internal_ops = &ov08x40_internal_ops; ov08x->sd.internal_ops = &ov08x40_internal_ops;
@ -2187,6 +2308,9 @@ error_media_entity:
error_handler_free: error_handler_free:
ov08x40_free_controls(ov08x); ov08x40_free_controls(ov08x);
probe_power_off:
ov08x40_power_off(&client->dev);
return ret; return ret;
} }
@ -2201,6 +2325,8 @@ static void ov08x40_remove(struct i2c_client *client)
pm_runtime_disable(&client->dev); pm_runtime_disable(&client->dev);
pm_runtime_set_suspended(&client->dev); pm_runtime_set_suspended(&client->dev);
ov08x40_power_off(&client->dev);
} }
#ifdef CONFIG_ACPI #ifdef CONFIG_ACPI
@ -2212,10 +2338,17 @@ static const struct acpi_device_id ov08x40_acpi_ids[] = {
MODULE_DEVICE_TABLE(acpi, ov08x40_acpi_ids); MODULE_DEVICE_TABLE(acpi, ov08x40_acpi_ids);
#endif #endif
static const struct of_device_id ov08x40_of_match[] = {
{ .compatible = "ovti,ov08x40" },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, ov08x40_of_match);
static struct i2c_driver ov08x40_i2c_driver = { static struct i2c_driver ov08x40_i2c_driver = {
.driver = { .driver = {
.name = "ov08x40", .name = "ov08x40",
.acpi_match_table = ACPI_PTR(ov08x40_acpi_ids), .acpi_match_table = ACPI_PTR(ov08x40_acpi_ids),
.of_match_table = ov08x40_of_match,
}, },
.probe = ov08x40_probe, .probe = ov08x40_probe,
.remove = ov08x40_remove, .remove = ov08x40_remove,

View File

@ -530,7 +530,7 @@ struct ov2740 {
/* Current mode */ /* Current mode */
const struct ov2740_mode *cur_mode; const struct ov2740_mode *cur_mode;
/* NVM data inforamtion */ /* NVM data information */
struct nvm_data *nvm; struct nvm_data *nvm;
/* Supported modes */ /* Supported modes */
@ -1132,7 +1132,8 @@ static int ov2740_check_hwcfg(struct device *dev)
*/ */
ep = fwnode_graph_get_next_endpoint(fwnode, NULL); ep = fwnode_graph_get_next_endpoint(fwnode, NULL);
if (!ep) if (!ep)
return -EPROBE_DEFER; return dev_err_probe(dev, -EPROBE_DEFER,
"waiting for fwnode graph endpoint\n");
ret = fwnode_property_read_u32(fwnode, "clock-frequency", &mclk); ret = fwnode_property_read_u32(fwnode, "clock-frequency", &mclk);
if (ret) { if (ret) {
@ -1330,7 +1331,7 @@ static int ov2740_probe(struct i2c_client *client)
ret = ov2740_check_hwcfg(dev); ret = ov2740_check_hwcfg(dev);
if (ret) if (ret)
return dev_err_probe(dev, ret, "failed to check HW configuration\n"); return ret;
ov2740->reset_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_HIGH); ov2740->reset_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_HIGH);
if (IS_ERR(ov2740->reset_gpio)) { if (IS_ERR(ov2740->reset_gpio)) {

View File

@ -377,7 +377,7 @@ struct reg_value {
struct ov5640_timings { struct ov5640_timings {
/* Analog crop rectangle. */ /* Analog crop rectangle. */
struct v4l2_rect analog_crop; struct v4l2_rect analog_crop;
/* Visibile crop: from analog crop top-left corner. */ /* Visible crop: from analog crop top-left corner. */
struct v4l2_rect crop; struct v4l2_rect crop;
/* Total pixels per line: width + fixed hblank. */ /* Total pixels per line: width + fixed hblank. */
u32 htot; u32 htot;

View File

@ -88,7 +88,6 @@ struct ov5645 {
struct v4l2_subdev sd; struct v4l2_subdev sd;
struct media_pad pad; struct media_pad pad;
struct v4l2_fwnode_endpoint ep; struct v4l2_fwnode_endpoint ep;
struct v4l2_mbus_framefmt fmt;
struct v4l2_rect crop; struct v4l2_rect crop;
struct clk *xclk; struct clk *xclk;
@ -105,8 +104,6 @@ struct ov5645 {
u8 timing_tc_reg20; u8 timing_tc_reg20;
u8 timing_tc_reg21; u8 timing_tc_reg21;
struct mutex power_lock; /* lock to protect power state */
struct gpio_desc *enable_gpio; struct gpio_desc *enable_gpio;
struct gpio_desc *rst_gpio; struct gpio_desc *rst_gpio;
}; };
@ -781,11 +778,8 @@ static int ov5645_s_ctrl(struct v4l2_ctrl *ctrl)
struct ov5645, ctrls); struct ov5645, ctrls);
int ret; int ret;
mutex_lock(&ov5645->power_lock); if (!pm_runtime_get_if_in_use(ov5645->dev))
if (!pm_runtime_get_if_in_use(ov5645->dev)) {
mutex_unlock(&ov5645->power_lock);
return 0; return 0;
}
switch (ctrl->id) { switch (ctrl->id) {
case V4L2_CID_SATURATION: case V4L2_CID_SATURATION:
@ -816,7 +810,6 @@ static int ov5645_s_ctrl(struct v4l2_ctrl *ctrl)
pm_runtime_mark_last_busy(ov5645->dev); pm_runtime_mark_last_busy(ov5645->dev);
pm_runtime_put_autosuspend(ov5645->dev); pm_runtime_put_autosuspend(ov5645->dev);
mutex_unlock(&ov5645->power_lock);
return ret; return ret;
} }
@ -855,49 +848,6 @@ static int ov5645_enum_frame_size(struct v4l2_subdev *subdev,
return 0; return 0;
} }
static struct v4l2_mbus_framefmt *
__ov5645_get_pad_format(struct ov5645 *ov5645,
struct v4l2_subdev_state *sd_state,
unsigned int pad,
enum v4l2_subdev_format_whence which)
{
switch (which) {
case V4L2_SUBDEV_FORMAT_TRY:
return v4l2_subdev_state_get_format(sd_state, pad);
case V4L2_SUBDEV_FORMAT_ACTIVE:
return &ov5645->fmt;
default:
return NULL;
}
}
static int ov5645_get_format(struct v4l2_subdev *sd,
struct v4l2_subdev_state *sd_state,
struct v4l2_subdev_format *format)
{
struct ov5645 *ov5645 = to_ov5645(sd);
format->format = *__ov5645_get_pad_format(ov5645, sd_state,
format->pad,
format->which);
return 0;
}
static struct v4l2_rect *
__ov5645_get_pad_crop(struct ov5645 *ov5645,
struct v4l2_subdev_state *sd_state,
unsigned int pad, enum v4l2_subdev_format_whence which)
{
switch (which) {
case V4L2_SUBDEV_FORMAT_TRY:
return v4l2_subdev_state_get_crop(sd_state, pad);
case V4L2_SUBDEV_FORMAT_ACTIVE:
return &ov5645->crop;
default:
return NULL;
}
}
static int ov5645_set_format(struct v4l2_subdev *sd, static int ov5645_set_format(struct v4l2_subdev *sd,
struct v4l2_subdev_state *sd_state, struct v4l2_subdev_state *sd_state,
struct v4l2_subdev_format *format) struct v4l2_subdev_format *format)
@ -908,24 +858,22 @@ static int ov5645_set_format(struct v4l2_subdev *sd,
const struct ov5645_mode_info *new_mode; const struct ov5645_mode_info *new_mode;
int ret; int ret;
__crop = __ov5645_get_pad_crop(ov5645, sd_state, format->pad, __crop = v4l2_subdev_state_get_crop(sd_state, 0);
format->which);
new_mode = v4l2_find_nearest_size(ov5645_mode_info_data, new_mode = v4l2_find_nearest_size(ov5645_mode_info_data,
ARRAY_SIZE(ov5645_mode_info_data), ARRAY_SIZE(ov5645_mode_info_data),
width, height, width, height, format->format.width,
format->format.width, format->format.height); format->format.height);
__crop->width = new_mode->width; __crop->width = new_mode->width;
__crop->height = new_mode->height; __crop->height = new_mode->height;
if (format->which == V4L2_SUBDEV_FORMAT_ACTIVE) { if (format->which == V4L2_SUBDEV_FORMAT_ACTIVE) {
ret = v4l2_ctrl_s_ctrl_int64(ov5645->pixel_clock, ret = __v4l2_ctrl_s_ctrl_int64(ov5645->pixel_clock,
new_mode->pixel_clock); new_mode->pixel_clock);
if (ret < 0) if (ret < 0)
return ret; return ret;
ret = v4l2_ctrl_s_ctrl(ov5645->link_freq, ret = __v4l2_ctrl_s_ctrl(ov5645->link_freq,
new_mode->link_freq); new_mode->link_freq);
if (ret < 0) if (ret < 0)
return ret; return ret;
@ -933,8 +881,7 @@ static int ov5645_set_format(struct v4l2_subdev *sd,
ov5645->current_mode = new_mode; ov5645->current_mode = new_mode;
} }
__format = __ov5645_get_pad_format(ov5645, sd_state, format->pad, __format = v4l2_subdev_state_get_format(sd_state, 0);
format->which);
__format->width = __crop->width; __format->width = __crop->width;
__format->height = __crop->height; __format->height = __crop->height;
__format->code = MEDIA_BUS_FMT_UYVY8_1X16; __format->code = MEDIA_BUS_FMT_UYVY8_1X16;
@ -949,11 +896,15 @@ static int ov5645_set_format(struct v4l2_subdev *sd,
static int ov5645_init_state(struct v4l2_subdev *subdev, static int ov5645_init_state(struct v4l2_subdev *subdev,
struct v4l2_subdev_state *sd_state) struct v4l2_subdev_state *sd_state)
{ {
struct v4l2_subdev_format fmt = { 0 }; struct v4l2_subdev_format fmt = {
.which = V4L2_SUBDEV_FORMAT_TRY,
fmt.which = sd_state ? V4L2_SUBDEV_FORMAT_TRY : V4L2_SUBDEV_FORMAT_ACTIVE; .pad = 0,
fmt.format.width = 1920; .format = {
fmt.format.height = 1080; .code = MEDIA_BUS_FMT_UYVY8_1X16,
.width = ov5645_mode_info_data[1].width,
.height = ov5645_mode_info_data[1].height,
},
};
ov5645_set_format(subdev, sd_state, &fmt); ov5645_set_format(subdev, sd_state, &fmt);
@ -964,22 +915,20 @@ static int ov5645_get_selection(struct v4l2_subdev *sd,
struct v4l2_subdev_state *sd_state, struct v4l2_subdev_state *sd_state,
struct v4l2_subdev_selection *sel) struct v4l2_subdev_selection *sel)
{ {
struct ov5645 *ov5645 = to_ov5645(sd);
if (sel->target != V4L2_SEL_TGT_CROP) if (sel->target != V4L2_SEL_TGT_CROP)
return -EINVAL; return -EINVAL;
sel->r = *__ov5645_get_pad_crop(ov5645, sd_state, sel->pad, sel->r = *v4l2_subdev_state_get_crop(sd_state, 0);
sel->which);
return 0; return 0;
} }
static int ov5645_s_stream(struct v4l2_subdev *subdev, int enable) static int ov5645_enable_streams(struct v4l2_subdev *sd,
struct v4l2_subdev_state *state, u32 pad,
u64 streams_mask)
{ {
struct ov5645 *ov5645 = to_ov5645(subdev); struct ov5645 *ov5645 = to_ov5645(sd);
int ret; int ret;
if (enable) {
ret = pm_runtime_resume_and_get(ov5645->dev); ret = pm_runtime_resume_and_get(ov5645->dev);
if (ret < 0) if (ret < 0)
return ret; return ret;
@ -993,7 +942,7 @@ static int ov5645_s_stream(struct v4l2_subdev *subdev, int enable)
ov5645->current_mode->height); ov5645->current_mode->height);
goto err_rpm_put; goto err_rpm_put;
} }
ret = v4l2_ctrl_handler_setup(&ov5645->ctrls); ret = __v4l2_ctrl_handler_setup(&ov5645->ctrls);
if (ret < 0) { if (ret < 0) {
dev_err(ov5645->dev, "could not sync v4l2 controls\n"); dev_err(ov5645->dev, "could not sync v4l2 controls\n");
goto err_rpm_put; goto err_rpm_put;
@ -1007,39 +956,47 @@ static int ov5645_s_stream(struct v4l2_subdev *subdev, int enable)
OV5645_SYSTEM_CTRL0_START); OV5645_SYSTEM_CTRL0_START);
if (ret < 0) if (ret < 0)
goto err_rpm_put; goto err_rpm_put;
} else {
ret = ov5645_write_reg(ov5645, OV5645_IO_MIPI_CTRL00, 0x40);
if (ret < 0)
goto stream_off_rpm_put;
ret = ov5645_write_reg(ov5645, OV5645_SYSTEM_CTRL0,
OV5645_SYSTEM_CTRL0_STOP);
goto stream_off_rpm_put;
}
return 0; return 0;
err_rpm_put: err_rpm_put:
pm_runtime_put_sync(ov5645->dev); pm_runtime_put_sync(ov5645->dev);
return ret; return ret;
}
stream_off_rpm_put: static int ov5645_disable_streams(struct v4l2_subdev *sd,
struct v4l2_subdev_state *state, u32 pad,
u64 streams_mask)
{
struct ov5645 *ov5645 = to_ov5645(sd);
int ret;
ret = ov5645_write_reg(ov5645, OV5645_IO_MIPI_CTRL00, 0x40);
if (ret < 0)
goto rpm_put;
ret = ov5645_write_reg(ov5645, OV5645_SYSTEM_CTRL0,
OV5645_SYSTEM_CTRL0_STOP);
rpm_put:
pm_runtime_mark_last_busy(ov5645->dev); pm_runtime_mark_last_busy(ov5645->dev);
pm_runtime_put_autosuspend(ov5645->dev); pm_runtime_put_autosuspend(ov5645->dev);
return ret; return ret;
} }
static const struct v4l2_subdev_video_ops ov5645_video_ops = { static const struct v4l2_subdev_video_ops ov5645_video_ops = {
.s_stream = ov5645_s_stream, .s_stream = v4l2_subdev_s_stream_helper,
}; };
static const struct v4l2_subdev_pad_ops ov5645_subdev_pad_ops = { static const struct v4l2_subdev_pad_ops ov5645_subdev_pad_ops = {
.enum_mbus_code = ov5645_enum_mbus_code, .enum_mbus_code = ov5645_enum_mbus_code,
.enum_frame_size = ov5645_enum_frame_size, .enum_frame_size = ov5645_enum_frame_size,
.get_fmt = ov5645_get_format, .get_fmt = v4l2_subdev_get_fmt,
.set_fmt = ov5645_set_format, .set_fmt = ov5645_set_format,
.get_selection = ov5645_get_selection, .get_selection = ov5645_get_selection,
.enable_streams = ov5645_enable_streams,
.disable_streams = ov5645_disable_streams,
}; };
static const struct v4l2_subdev_ops ov5645_subdev_ops = { static const struct v4l2_subdev_ops ov5645_subdev_ops = {
@ -1069,51 +1026,44 @@ static int ov5645_probe(struct i2c_client *client)
ov5645->dev = dev; ov5645->dev = dev;
endpoint = of_graph_get_endpoint_by_regs(dev->of_node, 0, -1); endpoint = of_graph_get_endpoint_by_regs(dev->of_node, 0, -1);
if (!endpoint) { if (!endpoint)
dev_err(dev, "endpoint node not found\n"); return dev_err_probe(dev, -EINVAL,
return -EINVAL; "endpoint node not found\n");
}
ret = v4l2_fwnode_endpoint_parse(of_fwnode_handle(endpoint), ret = v4l2_fwnode_endpoint_parse(of_fwnode_handle(endpoint),
&ov5645->ep); &ov5645->ep);
of_node_put(endpoint); of_node_put(endpoint);
if (ret < 0) { if (ret < 0)
dev_err(dev, "parsing endpoint node failed\n"); return dev_err_probe(dev, ret,
return ret; "parsing endpoint node failed\n");
}
if (ov5645->ep.bus_type != V4L2_MBUS_CSI2_DPHY) { if (ov5645->ep.bus_type != V4L2_MBUS_CSI2_DPHY)
dev_err(dev, "invalid bus type, must be CSI2\n"); return dev_err_probe(dev, -EINVAL,
return -EINVAL; "invalid bus type, must be CSI2\n");
}
/* get system clock (xclk) */ /* get system clock (xclk) */
ov5645->xclk = devm_clk_get(dev, NULL); ov5645->xclk = devm_clk_get(dev, NULL);
if (IS_ERR(ov5645->xclk)) { if (IS_ERR(ov5645->xclk))
dev_err(dev, "could not get xclk"); return dev_err_probe(dev, PTR_ERR(ov5645->xclk),
return PTR_ERR(ov5645->xclk); "could not get xclk");
}
ret = of_property_read_u32(dev->of_node, "clock-frequency", &xclk_freq); ret = of_property_read_u32(dev->of_node, "clock-frequency", &xclk_freq);
if (ret) { if (ret)
dev_err(dev, "could not get xclk frequency\n"); return dev_err_probe(dev, ret,
return ret; "could not get xclk frequency\n");
}
/* external clock must be 24MHz, allow 1% tolerance */ /* external clock must be 24MHz, allow 1% tolerance */
if (xclk_freq < 23760000 || xclk_freq > 24240000) { if (xclk_freq < 23760000 || xclk_freq > 24240000)
dev_err(dev, "external clock frequency %u is not supported\n", return dev_err_probe(dev, -EINVAL,
"unsupported xclk frequency %u\n",
xclk_freq); xclk_freq);
return -EINVAL;
}
ret = clk_set_rate(ov5645->xclk, xclk_freq); ret = clk_set_rate(ov5645->xclk, xclk_freq);
if (ret) { if (ret)
dev_err(dev, "could not set xclk frequency\n"); return dev_err_probe(dev, ret,
return ret; "could not set xclk frequency\n");
}
for (i = 0; i < OV5645_NUM_SUPPLIES; i++) for (i = 0; i < OV5645_NUM_SUPPLIES; i++)
ov5645->supplies[i].supply = ov5645_supply_name[i]; ov5645->supplies[i].supply = ov5645_supply_name[i];
@ -1124,18 +1074,14 @@ static int ov5645_probe(struct i2c_client *client)
return ret; return ret;
ov5645->enable_gpio = devm_gpiod_get(dev, "enable", GPIOD_OUT_HIGH); ov5645->enable_gpio = devm_gpiod_get(dev, "enable", GPIOD_OUT_HIGH);
if (IS_ERR(ov5645->enable_gpio)) { if (IS_ERR(ov5645->enable_gpio))
dev_err(dev, "cannot get enable gpio\n"); return dev_err_probe(dev, PTR_ERR(ov5645->enable_gpio),
return PTR_ERR(ov5645->enable_gpio); "cannot get enable gpio\n");
}
ov5645->rst_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH); ov5645->rst_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH);
if (IS_ERR(ov5645->rst_gpio)) { if (IS_ERR(ov5645->rst_gpio))
dev_err(dev, "cannot get reset gpio\n"); return dev_err_probe(dev, PTR_ERR(ov5645->rst_gpio),
return PTR_ERR(ov5645->rst_gpio); "cannot get reset gpio\n");
}
mutex_init(&ov5645->power_lock);
v4l2_ctrl_handler_init(&ov5645->ctrls, 9); v4l2_ctrl_handler_init(&ov5645->ctrls, 9);
v4l2_ctrl_new_std(&ov5645->ctrls, &ov5645_ctrl_ops, v4l2_ctrl_new_std(&ov5645->ctrls, &ov5645_ctrl_ops,
@ -1170,9 +1116,8 @@ static int ov5645_probe(struct i2c_client *client)
ov5645->sd.ctrl_handler = &ov5645->ctrls; ov5645->sd.ctrl_handler = &ov5645->ctrls;
if (ov5645->ctrls.error) { if (ov5645->ctrls.error) {
dev_err(dev, "%s: control initialization error %d\n",
__func__, ov5645->ctrls.error);
ret = ov5645->ctrls.error; ret = ov5645->ctrls.error;
dev_err_probe(dev, ret, "failed to add controls\n");
goto free_ctrl; goto free_ctrl;
} }
@ -1180,12 +1125,12 @@ static int ov5645_probe(struct i2c_client *client)
ov5645->sd.internal_ops = &ov5645_internal_ops; ov5645->sd.internal_ops = &ov5645_internal_ops;
ov5645->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; ov5645->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
ov5645->pad.flags = MEDIA_PAD_FL_SOURCE; ov5645->pad.flags = MEDIA_PAD_FL_SOURCE;
ov5645->sd.dev = &client->dev; ov5645->sd.dev = dev;
ov5645->sd.entity.function = MEDIA_ENT_F_CAM_SENSOR; ov5645->sd.entity.function = MEDIA_ENT_F_CAM_SENSOR;
ret = media_entity_pads_init(&ov5645->sd.entity, 1, &ov5645->pad); ret = media_entity_pads_init(&ov5645->sd.entity, 1, &ov5645->pad);
if (ret < 0) { if (ret < 0) {
dev_err(dev, "could not register media entity\n"); dev_err_probe(dev, ret, "could not register media entity\n");
goto free_ctrl; goto free_ctrl;
} }
@ -1195,14 +1140,14 @@ static int ov5645_probe(struct i2c_client *client)
ret = ov5645_read_reg(ov5645, OV5645_CHIP_ID_HIGH, &chip_id_high); ret = ov5645_read_reg(ov5645, OV5645_CHIP_ID_HIGH, &chip_id_high);
if (ret < 0 || chip_id_high != OV5645_CHIP_ID_HIGH_BYTE) { if (ret < 0 || chip_id_high != OV5645_CHIP_ID_HIGH_BYTE) {
dev_err(dev, "could not read ID high\n");
ret = -ENODEV; ret = -ENODEV;
dev_err_probe(dev, ret, "could not read ID high\n");
goto power_down; goto power_down;
} }
ret = ov5645_read_reg(ov5645, OV5645_CHIP_ID_LOW, &chip_id_low); ret = ov5645_read_reg(ov5645, OV5645_CHIP_ID_LOW, &chip_id_low);
if (ret < 0 || chip_id_low != OV5645_CHIP_ID_LOW_BYTE) { if (ret < 0 || chip_id_low != OV5645_CHIP_ID_LOW_BYTE) {
dev_err(dev, "could not read ID low\n");
ret = -ENODEV; ret = -ENODEV;
dev_err_probe(dev, ret, "could not read ID low\n");
goto power_down; goto power_down;
} }
@ -1211,24 +1156,31 @@ static int ov5645_probe(struct i2c_client *client)
ret = ov5645_read_reg(ov5645, OV5645_AEC_PK_MANUAL, ret = ov5645_read_reg(ov5645, OV5645_AEC_PK_MANUAL,
&ov5645->aec_pk_manual); &ov5645->aec_pk_manual);
if (ret < 0) { if (ret < 0) {
dev_err(dev, "could not read AEC/AGC mode\n");
ret = -ENODEV; ret = -ENODEV;
dev_err_probe(dev, ret, "could not read AEC/AGC mode\n");
goto power_down; goto power_down;
} }
ret = ov5645_read_reg(ov5645, OV5645_TIMING_TC_REG20, ret = ov5645_read_reg(ov5645, OV5645_TIMING_TC_REG20,
&ov5645->timing_tc_reg20); &ov5645->timing_tc_reg20);
if (ret < 0) { if (ret < 0) {
dev_err(dev, "could not read vflip value\n");
ret = -ENODEV; ret = -ENODEV;
dev_err_probe(dev, ret, "could not read vflip value\n");
goto power_down; goto power_down;
} }
ret = ov5645_read_reg(ov5645, OV5645_TIMING_TC_REG21, ret = ov5645_read_reg(ov5645, OV5645_TIMING_TC_REG21,
&ov5645->timing_tc_reg21); &ov5645->timing_tc_reg21);
if (ret < 0) { if (ret < 0) {
dev_err(dev, "could not read hflip value\n");
ret = -ENODEV; ret = -ENODEV;
dev_err_probe(dev, ret, "could not read hflip value\n");
goto power_down;
}
ov5645->sd.state_lock = ov5645->ctrls.lock;
ret = v4l2_subdev_init_finalize(&ov5645->sd);
if (ret < 0) {
dev_err_probe(dev, ret, "subdev init error\n");
goto power_down; goto power_down;
} }
@ -1236,11 +1188,9 @@ static int ov5645_probe(struct i2c_client *client)
pm_runtime_get_noresume(dev); pm_runtime_get_noresume(dev);
pm_runtime_enable(dev); pm_runtime_enable(dev);
ov5645_init_state(&ov5645->sd, NULL); ret = v4l2_async_register_subdev_sensor(&ov5645->sd);
ret = v4l2_async_register_subdev(&ov5645->sd);
if (ret < 0) { if (ret < 0) {
dev_err(dev, "could not register v4l2 device\n"); dev_err_probe(dev, ret, "could not register v4l2 device\n");
goto err_pm_runtime; goto err_pm_runtime;
} }
@ -1254,13 +1204,13 @@ static int ov5645_probe(struct i2c_client *client)
err_pm_runtime: err_pm_runtime:
pm_runtime_disable(dev); pm_runtime_disable(dev);
pm_runtime_put_noidle(dev); pm_runtime_put_noidle(dev);
v4l2_subdev_cleanup(&ov5645->sd);
power_down: power_down:
ov5645_set_power_off(dev); ov5645_set_power_off(dev);
free_entity: free_entity:
media_entity_cleanup(&ov5645->sd.entity); media_entity_cleanup(&ov5645->sd.entity);
free_ctrl: free_ctrl:
v4l2_ctrl_handler_free(&ov5645->ctrls); v4l2_ctrl_handler_free(&ov5645->ctrls);
mutex_destroy(&ov5645->power_lock);
return ret; return ret;
} }
@ -1271,13 +1221,13 @@ static void ov5645_remove(struct i2c_client *client)
struct ov5645 *ov5645 = to_ov5645(sd); struct ov5645 *ov5645 = to_ov5645(sd);
v4l2_async_unregister_subdev(&ov5645->sd); v4l2_async_unregister_subdev(&ov5645->sd);
v4l2_subdev_cleanup(sd);
media_entity_cleanup(&ov5645->sd.entity); media_entity_cleanup(&ov5645->sd.entity);
v4l2_ctrl_handler_free(&ov5645->ctrls); v4l2_ctrl_handler_free(&ov5645->ctrls);
pm_runtime_disable(ov5645->dev); pm_runtime_disable(ov5645->dev);
if (!pm_runtime_status_suspended(ov5645->dev)) if (!pm_runtime_status_suspended(ov5645->dev))
ov5645_set_power_off(ov5645->dev); ov5645_set_power_off(ov5645->dev);
pm_runtime_set_suspended(ov5645->dev); pm_runtime_set_suspended(ov5645->dev);
mutex_destroy(&ov5645->power_lock);
} }
static const struct i2c_device_id ov5645_id[] = { static const struct i2c_device_id ov5645_id[] = {

View File

@ -1879,7 +1879,7 @@ struct ov5670 {
struct gpio_desc *pwdn_gpio; /* PWDNB pin. */ struct gpio_desc *pwdn_gpio; /* PWDNB pin. */
struct gpio_desc *reset_gpio; /* XSHUTDOWN pin. */ struct gpio_desc *reset_gpio; /* XSHUTDOWN pin. */
/* To serialize asynchronus callbacks */ /* To serialize asynchronous callbacks */
struct mutex mutex; struct mutex mutex;
/* True if the device has been identified */ /* True if the device has been identified */

View File

@ -510,7 +510,7 @@ struct ov5675 {
/* Current mode */ /* Current mode */
const struct ov5675_mode *cur_mode; const struct ov5675_mode *cur_mode;
/* To serialize asynchronus callbacks */ /* To serialize asynchronous callbacks */
struct mutex mutex; struct mutex mutex;
/* True if the device has been identified */ /* True if the device has been identified */
@ -732,7 +732,7 @@ static int ov5675_set_ctrl(struct v4l2_ctrl *ctrl)
case V4L2_CID_EXPOSURE: case V4L2_CID_EXPOSURE:
/* 4 least significant bits of expsoure are fractional part /* 4 least significant bits of expsoure are fractional part
* val = val << 4 * val = val << 4
* for ov5675, the unit of exposure is differnt from other * for ov5675, the unit of exposure is different from other
* OmniVision sensors, its exposure value is twice of the * OmniVision sensors, its exposure value is twice of the
* register value, the exposure should be divided by 2 before * register value, the exposure should be divided by 2 before
* set register, e.g. val << 3. * set register, e.g. val << 3.

View File

@ -18,7 +18,6 @@
#include <media/v4l2-cci.h> #include <media/v4l2-cci.h>
#include <media/v4l2-ctrls.h> #include <media/v4l2-ctrls.h>
#include <media/v4l2-device.h> #include <media/v4l2-device.h>
#include <media/v4l2-event.h>
#include <media/v4l2-fwnode.h> #include <media/v4l2-fwnode.h>
#include <media/v4l2-mediabus.h> #include <media/v4l2-mediabus.h>
#include <media/v4l2-subdev.h> #include <media/v4l2-subdev.h>
@ -3200,13 +3199,7 @@ static const struct v4l2_subdev_pad_ops ov64a40_pad_ops = {
.get_selection = ov64a40_get_selection, .get_selection = ov64a40_get_selection,
}; };
static const struct v4l2_subdev_core_ops ov64a40_core_ops = {
.subscribe_event = v4l2_ctrl_subdev_subscribe_event,
.unsubscribe_event = v4l2_event_subdev_unsubscribe,
};
static const struct v4l2_subdev_ops ov64a40_subdev_ops = { static const struct v4l2_subdev_ops ov64a40_subdev_ops = {
.core = &ov64a40_core_ops,
.video = &ov64a40_video_ops, .video = &ov64a40_video_ops,
.pad = &ov64a40_pad_ops, .pad = &ov64a40_pad_ops,
}; };
@ -3605,8 +3598,7 @@ static int ov64a40_probe(struct i2c_client *client)
/* Initialize subdev */ /* Initialize subdev */
ov64a40->sd.internal_ops = &ov64a40_internal_ops; ov64a40->sd.internal_ops = &ov64a40_internal_ops;
ov64a40->sd.flags = V4L2_SUBDEV_FL_HAS_DEVNODE ov64a40->sd.flags = V4L2_SUBDEV_FL_HAS_DEVNODE;
| V4L2_SUBDEV_FL_HAS_EVENTS;
ov64a40->sd.entity.function = MEDIA_ENT_F_CAM_SENSOR; ov64a40->sd.entity.function = MEDIA_ENT_F_CAM_SENSOR;
ov64a40->pad.flags = MEDIA_PAD_FL_SOURCE; ov64a40->pad.flags = MEDIA_PAD_FL_SOURCE;

View File

@ -269,7 +269,7 @@
#define AF_8x 0x08 /* Add frame when AGC reaches 8x gain */ #define AF_8x 0x08 /* Add frame when AGC reaches 8x gain */
#define AF_16x 0x0c /* Add frame when AGC reaches 16x gain */ #define AF_16x 0x0c /* Add frame when AGC reaches 16x gain */
/* AEC max step control */ /* AEC max step control */
#define AEC_NO_LIMIT 0x01 /* 0 : AEC incease step has limit */ #define AEC_NO_LIMIT 0x01 /* 0 : AEC increase step has limit */
/* 1 : No limit to AEC increase step */ /* 1 : No limit to AEC increase step */
/* CLKRC */ /* CLKRC */
/* Input clock divider register */ /* Input clock divider register */

View File

@ -117,7 +117,7 @@ struct ov7740 {
struct v4l2_ctrl *brightness; struct v4l2_ctrl *brightness;
struct v4l2_ctrl *contrast; struct v4l2_ctrl *contrast;
struct mutex mutex; /* To serialize asynchronus callbacks */ struct mutex mutex; /* To serialize asynchronous callbacks */
struct gpio_desc *resetb_gpio; struct gpio_desc *resetb_gpio;
struct gpio_desc *pwdn_gpio; struct gpio_desc *pwdn_gpio;

View File

@ -1435,7 +1435,7 @@ struct ov8856 {
/* Application specified mbus format */ /* Application specified mbus format */
u32 cur_mbus_index; u32 cur_mbus_index;
/* To serialize asynchronus callbacks */ /* To serialize asynchronous callbacks */
struct mutex mutex; struct mutex mutex;
/* lanes index */ /* lanes index */

View File

@ -24,7 +24,6 @@
#include <media/v4l2-common.h> #include <media/v4l2-common.h>
#include <media/v4l2-ctrls.h> #include <media/v4l2-ctrls.h>
#include <media/v4l2-device.h> #include <media/v4l2-device.h>
#include <media/v4l2-event.h>
#include <media/v4l2-fwnode.h> #include <media/v4l2-fwnode.h>
#include <media/v4l2-mediabus.h> #include <media/v4l2-mediabus.h>
#include <media/v4l2-subdev.h> #include <media/v4l2-subdev.h>
@ -1500,13 +1499,7 @@ static const struct v4l2_subdev_pad_ops ov8858_pad_ops = {
.set_fmt = ov8858_set_fmt, .set_fmt = ov8858_set_fmt,
}; };
static const struct v4l2_subdev_core_ops ov8858_core_ops = {
.subscribe_event = v4l2_ctrl_subdev_subscribe_event,
.unsubscribe_event = v4l2_event_subdev_unsubscribe,
};
static const struct v4l2_subdev_ops ov8858_subdev_ops = { static const struct v4l2_subdev_ops ov8858_subdev_ops = {
.core = &ov8858_core_ops,
.video = &ov8858_video_ops, .video = &ov8858_video_ops,
.pad = &ov8858_pad_ops, .pad = &ov8858_pad_ops,
}; };
@ -1917,7 +1910,7 @@ static int ov8858_probe(struct i2c_client *client)
return ret; return ret;
sd = &ov8858->subdev; sd = &ov8858->subdev;
sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE | V4L2_SUBDEV_FL_HAS_EVENTS; sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
ov8858->pad.flags = MEDIA_PAD_FL_SOURCE; ov8858->pad.flags = MEDIA_PAD_FL_SOURCE;
sd->entity.function = MEDIA_ENT_F_CAM_SENSOR; sd->entity.function = MEDIA_ENT_F_CAM_SENSOR;
ret = media_entity_pads_init(&sd->entity, 1, &ov8858->pad); ret = media_entity_pads_init(&sd->entity, 1, &ov8858->pad);

View File

@ -286,7 +286,7 @@ static const struct i2c_rv ov965x_init_regs[] = {
{ REG_COM5, 0x00 }, /* System clock options */ { REG_COM5, 0x00 }, /* System clock options */
{ REG_COM2, 0x01 }, /* Output drive, soft sleep mode */ { REG_COM2, 0x01 }, /* Output drive, soft sleep mode */
{ REG_COM10, 0x00 }, /* Slave mode, HREF vs HSYNC, signals negate */ { REG_COM10, 0x00 }, /* Slave mode, HREF vs HSYNC, signals negate */
{ REG_EDGE, 0xa6 }, /* Edge enhancement treshhold and factor */ { REG_EDGE, 0xa6 }, /* Edge enhancement threshold and factor */
{ REG_COM16, 0x02 }, /* Color matrix coeff double option */ { REG_COM16, 0x02 }, /* Color matrix coeff double option */
{ REG_COM17, 0x08 }, /* Single frame out, banding filter */ { REG_COM17, 0x08 }, /* Single frame out, banding filter */
{ 0x16, 0x06 }, { 0x16, 0x06 },

View File

@ -335,7 +335,7 @@ struct ov9734 {
/* Current mode */ /* Current mode */
const struct ov9734_mode *cur_mode; const struct ov9734_mode *cur_mode;
/* To serialize asynchronus callbacks */ /* To serialize asynchronous callbacks */
struct mutex mutex; struct mutex mutex;
}; };

View File

@ -14,6 +14,7 @@
#include <linux/gpio/consumer.h> #include <linux/gpio/consumer.h>
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/pm_runtime.h>
#include <linux/of_graph.h> #include <linux/of_graph.h>
#include <linux/regulator/consumer.h> #include <linux/regulator/consumer.h>
#include <media/mipi-csi2.h> #include <media/mipi-csi2.h>
@ -67,9 +68,6 @@ static const u32 mipid02_supported_fmt_codes[] = {
MEDIA_BUS_FMT_YUYV8_1X16, MEDIA_BUS_FMT_YVYU8_1X16, MEDIA_BUS_FMT_YUYV8_1X16, MEDIA_BUS_FMT_YVYU8_1X16,
MEDIA_BUS_FMT_UYVY8_1X16, MEDIA_BUS_FMT_VYUY8_1X16, MEDIA_BUS_FMT_UYVY8_1X16, MEDIA_BUS_FMT_VYUY8_1X16,
MEDIA_BUS_FMT_RGB565_1X16, MEDIA_BUS_FMT_BGR888_1X24, MEDIA_BUS_FMT_RGB565_1X16, MEDIA_BUS_FMT_BGR888_1X24,
MEDIA_BUS_FMT_RGB565_2X8_LE, MEDIA_BUS_FMT_RGB565_2X8_BE,
MEDIA_BUS_FMT_YUYV8_2X8, MEDIA_BUS_FMT_YVYU8_2X8,
MEDIA_BUS_FMT_UYVY8_2X8, MEDIA_BUS_FMT_VYUY8_2X8,
MEDIA_BUS_FMT_Y8_1X8, MEDIA_BUS_FMT_JPEG_1X8 MEDIA_BUS_FMT_Y8_1X8, MEDIA_BUS_FMT_JPEG_1X8
}; };
@ -100,6 +98,7 @@ struct mipid02_dev {
/* remote source */ /* remote source */
struct v4l2_async_notifier notifier; struct v4l2_async_notifier notifier;
struct v4l2_subdev *s_subdev; struct v4l2_subdev *s_subdev;
u16 s_subdev_pad_id;
/* registers */ /* registers */
struct { struct {
u8 clk_lane_reg1; u8 clk_lane_reg1;
@ -138,12 +137,6 @@ static int bpp_from_code(__u32 code)
case MEDIA_BUS_FMT_UYVY8_1X16: case MEDIA_BUS_FMT_UYVY8_1X16:
case MEDIA_BUS_FMT_VYUY8_1X16: case MEDIA_BUS_FMT_VYUY8_1X16:
case MEDIA_BUS_FMT_RGB565_1X16: case MEDIA_BUS_FMT_RGB565_1X16:
case MEDIA_BUS_FMT_YUYV8_2X8:
case MEDIA_BUS_FMT_YVYU8_2X8:
case MEDIA_BUS_FMT_UYVY8_2X8:
case MEDIA_BUS_FMT_VYUY8_2X8:
case MEDIA_BUS_FMT_RGB565_2X8_LE:
case MEDIA_BUS_FMT_RGB565_2X8_BE:
return 16; return 16;
case MEDIA_BUS_FMT_BGR888_1X24: case MEDIA_BUS_FMT_BGR888_1X24:
return 24; return 24;
@ -175,16 +168,10 @@ static u8 data_type_from_code(__u32 code)
case MEDIA_BUS_FMT_YVYU8_1X16: case MEDIA_BUS_FMT_YVYU8_1X16:
case MEDIA_BUS_FMT_UYVY8_1X16: case MEDIA_BUS_FMT_UYVY8_1X16:
case MEDIA_BUS_FMT_VYUY8_1X16: case MEDIA_BUS_FMT_VYUY8_1X16:
case MEDIA_BUS_FMT_YUYV8_2X8:
case MEDIA_BUS_FMT_YVYU8_2X8:
case MEDIA_BUS_FMT_UYVY8_2X8:
case MEDIA_BUS_FMT_VYUY8_2X8:
return MIPI_CSI2_DT_YUV422_8B; return MIPI_CSI2_DT_YUV422_8B;
case MEDIA_BUS_FMT_BGR888_1X24: case MEDIA_BUS_FMT_BGR888_1X24:
return MIPI_CSI2_DT_RGB888; return MIPI_CSI2_DT_RGB888;
case MEDIA_BUS_FMT_RGB565_1X16: case MEDIA_BUS_FMT_RGB565_1X16:
case MEDIA_BUS_FMT_RGB565_2X8_LE:
case MEDIA_BUS_FMT_RGB565_2X8_BE:
return MIPI_CSI2_DT_RGB565; return MIPI_CSI2_DT_RGB565;
default: default:
return 0; return 0;
@ -248,8 +235,10 @@ static void mipid02_apply_reset(struct mipid02_dev *bridge)
usleep_range(5000, 10000); usleep_range(5000, 10000);
} }
static int mipid02_set_power_on(struct mipid02_dev *bridge) static int mipid02_set_power_on(struct device *dev)
{ {
struct v4l2_subdev *sd = dev_get_drvdata(dev);
struct mipid02_dev *bridge = to_mipid02_dev(sd);
struct i2c_client *client = bridge->i2c_client; struct i2c_client *client = bridge->i2c_client;
int ret; int ret;
@ -282,10 +271,15 @@ xclk_off:
return ret; return ret;
} }
static void mipid02_set_power_off(struct mipid02_dev *bridge) static int mipid02_set_power_off(struct device *dev)
{ {
struct v4l2_subdev *sd = dev_get_drvdata(dev);
struct mipid02_dev *bridge = to_mipid02_dev(sd);
regulator_bulk_disable(MIPID02_NUM_SUPPLIES, bridge->supplies); regulator_bulk_disable(MIPID02_NUM_SUPPLIES, bridge->supplies);
clk_disable_unprepare(bridge->xclk); clk_disable_unprepare(bridge->xclk);
return 0;
} }
static int mipid02_detect(struct mipid02_dev *bridge) static int mipid02_detect(struct mipid02_dev *bridge)
@ -447,15 +441,19 @@ static int mipid02_configure_from_code(struct mipid02_dev *bridge,
return 0; return 0;
} }
static int mipid02_stream_disable(struct mipid02_dev *bridge) static int mipid02_disable_streams(struct v4l2_subdev *sd,
struct v4l2_subdev_state *state, u32 pad,
u64 streams_mask)
{ {
struct mipid02_dev *bridge = to_mipid02_dev(sd);
struct i2c_client *client = bridge->i2c_client; struct i2c_client *client = bridge->i2c_client;
int ret = -EINVAL; int ret = -EINVAL;
if (!bridge->s_subdev) if (!bridge->s_subdev)
goto error; goto error;
ret = v4l2_subdev_call(bridge->s_subdev, video, s_stream, 0); ret = v4l2_subdev_disable_streams(bridge->s_subdev,
bridge->s_subdev_pad_id, BIT(0));
if (ret) if (ret)
goto error; goto error;
@ -465,6 +463,10 @@ static int mipid02_stream_disable(struct mipid02_dev *bridge)
cci_write(bridge->regmap, MIPID02_DATA_LANE1_REG1, 0, &ret); cci_write(bridge->regmap, MIPID02_DATA_LANE1_REG1, 0, &ret);
if (ret) if (ret)
goto error; goto error;
pm_runtime_mark_last_busy(&client->dev);
pm_runtime_put_autosuspend(&client->dev);
error: error:
if (ret) if (ret)
dev_err(&client->dev, "failed to stream off %d", ret); dev_err(&client->dev, "failed to stream off %d", ret);
@ -472,33 +474,36 @@ error:
return ret; return ret;
} }
static int mipid02_stream_enable(struct mipid02_dev *bridge) static int mipid02_enable_streams(struct v4l2_subdev *sd,
struct v4l2_subdev_state *state, u32 pad,
u64 streams_mask)
{ {
struct mipid02_dev *bridge = to_mipid02_dev(sd);
struct i2c_client *client = bridge->i2c_client; struct i2c_client *client = bridge->i2c_client;
struct v4l2_subdev_state *state;
struct v4l2_mbus_framefmt *fmt; struct v4l2_mbus_framefmt *fmt;
int ret = -EINVAL; int ret = -EINVAL;
if (!bridge->s_subdev) if (!bridge->s_subdev)
goto error; return ret;
memset(&bridge->r, 0, sizeof(bridge->r)); memset(&bridge->r, 0, sizeof(bridge->r));
state = v4l2_subdev_lock_and_get_active_state(&bridge->sd);
fmt = v4l2_subdev_state_get_format(state, MIPID02_SINK_0); fmt = v4l2_subdev_state_get_format(state, MIPID02_SINK_0);
/* build registers content */ /* build registers content */
ret = mipid02_configure_from_rx(bridge, fmt); ret = mipid02_configure_from_rx(bridge, fmt);
if (ret) if (ret)
goto error; return ret;
ret = mipid02_configure_from_tx(bridge); ret = mipid02_configure_from_tx(bridge);
if (ret) if (ret)
goto error; return ret;
ret = mipid02_configure_from_code(bridge, fmt); ret = mipid02_configure_from_code(bridge, fmt);
if (ret) if (ret)
goto error; return ret;
v4l2_subdev_unlock_state(state); ret = pm_runtime_resume_and_get(&client->dev);
if (ret < 0)
return ret;
/* write mipi registers */ /* write mipi registers */
cci_write(bridge->regmap, MIPID02_CLK_LANE_REG1, cci_write(bridge->regmap, MIPID02_CLK_LANE_REG1,
@ -524,33 +529,20 @@ static int mipid02_stream_enable(struct mipid02_dev *bridge)
if (ret) if (ret)
goto error; goto error;
ret = v4l2_subdev_call(bridge->s_subdev, video, s_stream, 1); ret = v4l2_subdev_enable_streams(bridge->s_subdev,
bridge->s_subdev_pad_id, BIT(0));
if (ret) if (ret)
goto error; goto error;
return 0; return 0;
error: error:
dev_err(&client->dev, "failed to stream on %d", ret); cci_write(bridge->regmap, MIPID02_CLK_LANE_REG1, 0, &ret);
mipid02_stream_disable(bridge); cci_write(bridge->regmap, MIPID02_DATA_LANE0_REG1, 0, &ret);
cci_write(bridge->regmap, MIPID02_DATA_LANE1_REG1, 0, &ret);
return ret;
}
static int mipid02_s_stream(struct v4l2_subdev *sd, int enable)
{
struct mipid02_dev *bridge = to_mipid02_dev(sd);
struct i2c_client *client = bridge->i2c_client;
int ret = 0;
dev_dbg(&client->dev, "%s : requested %d\n", __func__, enable);
ret = enable ? mipid02_stream_enable(bridge) :
mipid02_stream_disable(bridge);
if (ret)
dev_err(&client->dev, "failed to stream %s (%d)\n",
enable ? "enable" : "disable", ret);
pm_runtime_mark_last_busy(&client->dev);
pm_runtime_put_autosuspend(&client->dev);
return ret; return ret;
} }
@ -640,13 +632,15 @@ static int mipid02_set_fmt(struct v4l2_subdev *sd,
} }
static const struct v4l2_subdev_video_ops mipid02_video_ops = { static const struct v4l2_subdev_video_ops mipid02_video_ops = {
.s_stream = mipid02_s_stream, .s_stream = v4l2_subdev_s_stream_helper,
}; };
static const struct v4l2_subdev_pad_ops mipid02_pad_ops = { static const struct v4l2_subdev_pad_ops mipid02_pad_ops = {
.enum_mbus_code = mipid02_enum_mbus_code, .enum_mbus_code = mipid02_enum_mbus_code,
.get_fmt = v4l2_subdev_get_fmt, .get_fmt = v4l2_subdev_get_fmt,
.set_fmt = mipid02_set_fmt, .set_fmt = mipid02_set_fmt,
.enable_streams = mipid02_enable_streams,
.disable_streams = mipid02_disable_streams,
}; };
static const struct v4l2_subdev_ops mipid02_subdev_ops = { static const struct v4l2_subdev_ops mipid02_subdev_ops = {
@ -692,6 +686,7 @@ static int mipid02_async_bound(struct v4l2_async_notifier *notifier,
} }
bridge->s_subdev = s_subdev; bridge->s_subdev = s_subdev;
bridge->s_subdev_pad_id = source_pad;
return 0; return 0;
} }
@ -875,7 +870,7 @@ static int mipid02_probe(struct i2c_client *client)
} }
/* enable clock, power and reset device if available */ /* enable clock, power and reset device if available */
ret = mipid02_set_power_on(bridge); ret = mipid02_set_power_on(&client->dev);
if (ret) if (ret)
goto entity_cleanup; goto entity_cleanup;
@ -897,6 +892,15 @@ static int mipid02_probe(struct i2c_client *client)
goto power_off; goto power_off;
} }
/* Enable runtime PM and turn off the device */
pm_runtime_set_active(dev);
pm_runtime_get_noresume(&client->dev);
pm_runtime_enable(dev);
pm_runtime_set_autosuspend_delay(&client->dev, 1000);
pm_runtime_use_autosuspend(&client->dev);
pm_runtime_put_autosuspend(&client->dev);
ret = v4l2_async_register_subdev(&bridge->sd); ret = v4l2_async_register_subdev(&bridge->sd);
if (ret < 0) { if (ret < 0) {
dev_err(&client->dev, "v4l2_async_register_subdev failed %d", dev_err(&client->dev, "v4l2_async_register_subdev failed %d",
@ -911,8 +915,10 @@ static int mipid02_probe(struct i2c_client *client)
unregister_notifier: unregister_notifier:
v4l2_async_nf_unregister(&bridge->notifier); v4l2_async_nf_unregister(&bridge->notifier);
v4l2_async_nf_cleanup(&bridge->notifier); v4l2_async_nf_cleanup(&bridge->notifier);
pm_runtime_disable(&client->dev);
pm_runtime_set_suspended(&client->dev);
power_off: power_off:
mipid02_set_power_off(bridge); mipid02_set_power_off(&client->dev);
entity_cleanup: entity_cleanup:
media_entity_cleanup(&bridge->sd.entity); media_entity_cleanup(&bridge->sd.entity);
@ -927,7 +933,11 @@ static void mipid02_remove(struct i2c_client *client)
v4l2_async_nf_unregister(&bridge->notifier); v4l2_async_nf_unregister(&bridge->notifier);
v4l2_async_nf_cleanup(&bridge->notifier); v4l2_async_nf_cleanup(&bridge->notifier);
v4l2_async_unregister_subdev(&bridge->sd); v4l2_async_unregister_subdev(&bridge->sd);
mipid02_set_power_off(bridge);
pm_runtime_disable(&client->dev);
if (!pm_runtime_status_suspended(&client->dev))
mipid02_set_power_off(&client->dev);
pm_runtime_set_suspended(&client->dev);
media_entity_cleanup(&bridge->sd.entity); media_entity_cleanup(&bridge->sd.entity);
} }
@ -937,10 +947,15 @@ static const struct of_device_id mipid02_dt_ids[] = {
}; };
MODULE_DEVICE_TABLE(of, mipid02_dt_ids); MODULE_DEVICE_TABLE(of, mipid02_dt_ids);
static const struct dev_pm_ops mipid02_pm_ops = {
RUNTIME_PM_OPS(mipid02_set_power_off, mipid02_set_power_on, NULL)
};
static struct i2c_driver mipid02_i2c_driver = { static struct i2c_driver mipid02_i2c_driver = {
.driver = { .driver = {
.name = "st-mipid02", .name = "st-mipid02",
.of_match_table = mipid02_dt_ids, .of_match_table = mipid02_dt_ids,
.pm = pm_ptr(&mipid02_pm_ops),
}, },
.probe = mipid02_probe, .probe = mipid02_probe,
.remove = mipid02_remove, .remove = mipid02_remove,

View File

@ -87,6 +87,10 @@ struct tc358743_state {
struct timer_list timer; struct timer_list timer;
struct work_struct work_i2c_poll; struct work_struct work_i2c_poll;
/* debugfs */
struct dentry *debugfs_dir;
struct v4l2_debugfs_if *infoframes;
/* edid */ /* edid */
u8 edid_blocks_written; u8 edid_blocks_written;
@ -430,12 +434,35 @@ static void tc358743_erase_bksv(struct v4l2_subdev *sd)
/* --------------- AVI infoframe --------------- */ /* --------------- AVI infoframe --------------- */
static ssize_t
tc358743_debugfs_if_read(u32 type, void *priv, struct file *filp,
char __user *ubuf, size_t count, loff_t *ppos)
{
u8 buf[V4L2_DEBUGFS_IF_MAX_LEN] = {};
struct v4l2_subdev *sd = priv;
int len;
if (!is_hdmi(sd))
return 0;
if (type != V4L2_DEBUGFS_IF_AVI)
return 0;
i2c_rd(sd, PK_AVI_0HEAD, buf, PK_AVI_16BYTE - PK_AVI_0HEAD + 1);
len = buf[2] + 4;
if (len > V4L2_DEBUGFS_IF_MAX_LEN)
len = -ENOENT;
if (len > 0)
len = simple_read_from_buffer(ubuf, count, ppos, buf, len);
return len < 0 ? 0 : len;
}
static void print_avi_infoframe(struct v4l2_subdev *sd) static void print_avi_infoframe(struct v4l2_subdev *sd)
{ {
struct i2c_client *client = v4l2_get_subdevdata(sd); struct i2c_client *client = v4l2_get_subdevdata(sd);
struct device *dev = &client->dev; struct device *dev = &client->dev;
union hdmi_infoframe frame; union hdmi_infoframe frame;
u8 buffer[HDMI_INFOFRAME_SIZE(AVI)]; u8 buffer[HDMI_INFOFRAME_SIZE(AVI)] = {};
if (!is_hdmi(sd)) { if (!is_hdmi(sd)) {
v4l2_info(sd, "DVI-D signal - AVI infoframe not supported\n"); v4l2_info(sd, "DVI-D signal - AVI infoframe not supported\n");
@ -2161,6 +2188,11 @@ static int tc358743_probe(struct i2c_client *client)
if (err < 0) if (err < 0)
goto err_work_queues; goto err_work_queues;
state->debugfs_dir = debugfs_create_dir(sd->name, v4l2_debugfs_root());
state->infoframes = v4l2_debugfs_if_alloc(state->debugfs_dir,
V4L2_DEBUGFS_IF_AVI, sd,
tc358743_debugfs_if_read);
v4l2_info(sd, "%s found @ 0x%x (%s)\n", client->name, v4l2_info(sd, "%s found @ 0x%x (%s)\n", client->name,
client->addr << 1, client->adapter->name); client->addr << 1, client->adapter->name);
@ -2168,8 +2200,10 @@ static int tc358743_probe(struct i2c_client *client)
err_work_queues: err_work_queues:
cec_unregister_adapter(state->cec_adap); cec_unregister_adapter(state->cec_adap);
if (!state->i2c_client->irq) if (!state->i2c_client->irq) {
del_timer(&state->timer);
flush_work(&state->work_i2c_poll); flush_work(&state->work_i2c_poll);
}
cancel_delayed_work(&state->delayed_work_enable_hotplug); cancel_delayed_work(&state->delayed_work_enable_hotplug);
mutex_destroy(&state->confctl_mutex); mutex_destroy(&state->confctl_mutex);
err_hdl: err_hdl:
@ -2188,6 +2222,8 @@ static void tc358743_remove(struct i2c_client *client)
flush_work(&state->work_i2c_poll); flush_work(&state->work_i2c_poll);
} }
cancel_delayed_work_sync(&state->delayed_work_enable_hotplug); cancel_delayed_work_sync(&state->delayed_work_enable_hotplug);
v4l2_debugfs_if_free(state->infoframes);
debugfs_remove_recursive(state->debugfs_dir);
cec_unregister_adapter(state->cec_adap); cec_unregister_adapter(state->cec_adap);
v4l2_async_unregister_subdev(sd); v4l2_async_unregister_subdev(sd);
v4l2_device_unregister_subdev(sd); v4l2_device_unregister_subdev(sd);

View File

@ -27,7 +27,6 @@
#include <media/v4l2-cci.h> #include <media/v4l2-cci.h>
#include <media/v4l2-ctrls.h> #include <media/v4l2-ctrls.h>
#include <media/v4l2-device.h> #include <media/v4l2-device.h>
#include <media/v4l2-event.h>
#include <media/v4l2-fwnode.h> #include <media/v4l2-fwnode.h>
#include <media/v4l2-subdev.h> #include <media/v4l2-subdev.h>
@ -879,8 +878,6 @@ static int thp7312_init_state(struct v4l2_subdev *sd,
static const struct v4l2_subdev_core_ops thp7312_core_ops = { static const struct v4l2_subdev_core_ops thp7312_core_ops = {
.log_status = v4l2_ctrl_subdev_log_status, .log_status = v4l2_ctrl_subdev_log_status,
.subscribe_event = v4l2_ctrl_subdev_subscribe_event,
.unsubscribe_event = v4l2_event_subdev_unsubscribe,
}; };
static const struct v4l2_subdev_video_ops thp7312_video_ops = { static const struct v4l2_subdev_video_ops thp7312_video_ops = {
@ -2127,7 +2124,7 @@ static int thp7312_probe(struct i2c_client *client)
v4l2_i2c_subdev_init(&thp7312->sd, client, &thp7312_subdev_ops); v4l2_i2c_subdev_init(&thp7312->sd, client, &thp7312_subdev_ops);
thp7312->sd.internal_ops = &thp7312_internal_ops; thp7312->sd.internal_ops = &thp7312_internal_ops;
thp7312->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE | V4L2_SUBDEV_FL_HAS_EVENTS; thp7312->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
thp7312->pad.flags = MEDIA_PAD_FL_SOURCE; thp7312->pad.flags = MEDIA_PAD_FL_SOURCE;
thp7312->sd.entity.function = MEDIA_ENT_F_CAM_SENSOR; thp7312->sd.entity.function = MEDIA_ENT_F_CAM_SENSOR;

View File

@ -7,7 +7,7 @@
* Author: Chaithrika U S <chaithrika@ti.com> * Author: Chaithrika U S <chaithrika@ti.com>
* *
* Contributors: * Contributors:
* Hans Verkuil <hans.verkuil@cisco.com> * Hans Verkuil <hansverk@cisco.com>
* Lad, Prabhakar <prabhakar.lad@ti.com> * Lad, Prabhakar <prabhakar.lad@ti.com>
* Martin Bugge <marbugge@cisco.com> * Martin Bugge <marbugge@cisco.com>
* *

View File

@ -1617,7 +1617,7 @@ static int vgxy61_detect(struct vgxy61_dev *sensor)
ret = cci_read(sensor->regmap, VGXY61_REG_NVM, &st, NULL); ret = cci_read(sensor->regmap, VGXY61_REG_NVM, &st, NULL);
if (ret < 0) if (ret < 0)
return st; return ret;
if (st != VGXY61_NVM_OK) if (st != VGXY61_NVM_OK)
dev_warn(&client->dev, "Bad nvm state got %u\n", (u8)st); dev_warn(&client->dev, "Bad nvm state got %u\n", (u8)st);

View File

@ -566,8 +566,6 @@ static const struct vb2_ops video_i2c_video_qops = {
.buf_queue = buffer_queue, .buf_queue = buffer_queue,
.start_streaming = start_streaming, .start_streaming = start_streaming,
.stop_streaming = stop_streaming, .stop_streaming = stop_streaming,
.wait_prepare = vb2_ops_wait_prepare,
.wait_finish = vb2_ops_wait_finish,
}; };
static int video_i2c_querycap(struct file *file, void *priv, static int video_i2c_querycap(struct file *file, void *priv,
@ -798,13 +796,13 @@ static int video_i2c_probe(struct i2c_client *client)
queue->min_queued_buffers = 1; queue->min_queued_buffers = 1;
queue->ops = &video_i2c_video_qops; queue->ops = &video_i2c_video_qops;
queue->mem_ops = &vb2_vmalloc_memops; queue->mem_ops = &vb2_vmalloc_memops;
queue->lock = &data->queue_lock;
ret = vb2_queue_init(queue); ret = vb2_queue_init(queue);
if (ret < 0) if (ret < 0)
goto error_unregister_device; goto error_unregister_device;
data->vdev.queue = queue; data->vdev.queue = queue;
data->vdev.queue->lock = &data->queue_lock;
snprintf(data->vdev.name, sizeof(data->vdev.name), snprintf(data->vdev.name, sizeof(data->vdev.name),
"I2C %d-%d Transport Video", "I2C %d-%d Transport Video",

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