mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-23 04:04:26 +08:00
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:
commit
9f5a6a1fe6
4
.mailmap
4
.mailmap
@ -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> <ast@fb.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>
|
||||
Alex Elder <elder@kernel.org>
|
||||
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 <padovan@profusion.mobi>
|
||||
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> <heiko.carstens@de.ibm.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.kim@samsung.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>
|
||||
James Bottomley <jejb@mulgrave.(none)>
|
||||
James Bottomley <jejb@titanic.il.steeleye.com>
|
||||
|
@ -15,7 +15,7 @@ Please notice, however, that, if:
|
||||
|
||||
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
|
||||
`LinuxTv wiki pages <https://linuxtv.org/wiki>`_:
|
||||
|
@ -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/
|
27
Documentation/admin-guide/media/raspberrypi-rp1-cfe.dot
Normal file
27
Documentation/admin-guide/media/raspberrypi-rp1-cfe.dot
Normal 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
|
||||
}
|
78
Documentation/admin-guide/media/raspberrypi-rp1-cfe.rst
Normal file
78
Documentation/admin-guide/media/raspberrypi-rp1-cfe.rst
Normal 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.
|
@ -67,7 +67,7 @@ Changes / Fixes
|
||||
Please mail to linux-media AT vger.kernel.org unified diffs against
|
||||
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
|
||||
submitting the patch using ``git send-email``. Don't forget to
|
||||
|
@ -20,12 +20,12 @@ Video4Linux (V4L) driver-specific documentation
|
||||
ivtv
|
||||
mgb4
|
||||
omap3isp
|
||||
omap4_camera
|
||||
philips
|
||||
qcom_camss
|
||||
raspberrypi-pisp-be
|
||||
rcar-fdp1
|
||||
rkisp1
|
||||
raspberrypi-rp1-cfe
|
||||
saa7134
|
||||
si470x
|
||||
si4713
|
||||
|
@ -39,6 +39,12 @@ properties:
|
||||
maxItems: 1
|
||||
|
||||
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:
|
||||
Indicates that the output is a BT.656-4 compatible stream.
|
||||
type: boolean
|
||||
|
@ -28,12 +28,6 @@ properties:
|
||||
items:
|
||||
- description: Reference to the mclk clock.
|
||||
|
||||
assigned-clocks:
|
||||
maxItems: 1
|
||||
|
||||
assigned-clock-rates:
|
||||
maxItems: 1
|
||||
|
||||
reset-gpios:
|
||||
description: Reference to the GPIO connected to the RESETB pin. Active low.
|
||||
maxItems: 1
|
||||
@ -82,8 +76,6 @@ required:
|
||||
- compatible
|
||||
- reg
|
||||
- clocks
|
||||
- assigned-clocks
|
||||
- assigned-clock-rates
|
||||
- vddio-supply
|
||||
- vdda-supply
|
||||
- vddd-supply
|
||||
@ -105,8 +97,6 @@ examples:
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&pinctrl_csi1>;
|
||||
clocks = <&clk 0>;
|
||||
assigned-clocks = <&clk 0>;
|
||||
assigned-clock-rates = <25000000>;
|
||||
vdda-supply = <®_camera_vdda>;
|
||||
vddd-supply = <®_camera_vddd>;
|
||||
vddio-supply = <®_camera_vddio>;
|
||||
|
@ -25,7 +25,10 @@ description: |
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: maxim,max96712
|
||||
items:
|
||||
- enum:
|
||||
- maxim,max96712
|
||||
- maxim,max96724
|
||||
|
||||
reg:
|
||||
description: I2C device address
|
||||
|
120
Documentation/devicetree/bindings/media/i2c/ovti,ov08x40.yaml
Normal file
120
Documentation/devicetree/bindings/media/i2c/ovti,ov08x40.yaml
Normal 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>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
...
|
@ -20,12 +20,6 @@ properties:
|
||||
items:
|
||||
- description: XVCLK Clock
|
||||
|
||||
assigned-clocks:
|
||||
maxItems: 1
|
||||
|
||||
assigned-clock-rates:
|
||||
maxItems: 1
|
||||
|
||||
dvdd-supply:
|
||||
description: Digital Domain Power Supply
|
||||
|
||||
@ -68,8 +62,6 @@ required:
|
||||
- compatible
|
||||
- reg
|
||||
- clocks
|
||||
- assigned-clocks
|
||||
- assigned-clock-rates
|
||||
- dvdd-supply
|
||||
- dovdd-supply
|
||||
- port
|
||||
@ -93,9 +85,6 @@ examples:
|
||||
avdd-supply = <&ov5648_avdd>;
|
||||
dovdd-supply = <&ov5648_dovdd>;
|
||||
clocks = <&ov5648_xvclk 0>;
|
||||
assigned-clocks = <&ov5648_xvclk 0>;
|
||||
assigned-clock-rates = <24000000>;
|
||||
|
||||
|
||||
ov5648_out: port {
|
||||
ov5648_out_mipi_csi2: endpoint {
|
||||
|
@ -20,12 +20,6 @@ properties:
|
||||
items:
|
||||
- description: EXTCLK Clock
|
||||
|
||||
assigned-clocks:
|
||||
maxItems: 1
|
||||
|
||||
assigned-clock-rates:
|
||||
maxItems: 1
|
||||
|
||||
dvdd-supply:
|
||||
description: Digital Domain Power Supply
|
||||
|
||||
@ -68,8 +62,6 @@ required:
|
||||
- compatible
|
||||
- reg
|
||||
- clocks
|
||||
- assigned-clocks
|
||||
- assigned-clock-rates
|
||||
- dvdd-supply
|
||||
- avdd-supply
|
||||
- dovdd-supply
|
||||
@ -94,8 +86,6 @@ examples:
|
||||
pinctrl-0 = <&csi_mclk_pin>;
|
||||
|
||||
clocks = <&ccu CLK_CSI_MCLK>;
|
||||
assigned-clocks = <&ccu CLK_CSI_MCLK>;
|
||||
assigned-clock-rates = <24000000>;
|
||||
|
||||
avdd-supply = <®_ov8865_avdd>;
|
||||
dovdd-supply = <®_ov8865_dovdd>;
|
||||
|
@ -27,10 +27,6 @@ properties:
|
||||
description: I2C address
|
||||
maxItems: 1
|
||||
|
||||
assigned-clocks: true
|
||||
assigned-clock-parents: true
|
||||
assigned-clock-rates: true
|
||||
|
||||
clocks:
|
||||
description: Clock frequency from 6 to 27MHz
|
||||
maxItems: 1
|
||||
@ -87,10 +83,6 @@ examples:
|
||||
reg = <0x60>;
|
||||
clocks = <&ov9282_clk>;
|
||||
|
||||
assigned-clocks = <&ov9282_clk>;
|
||||
assigned-clock-parents = <&ov9282_clk_parent>;
|
||||
assigned-clock-rates = <24000000>;
|
||||
|
||||
port {
|
||||
ov9282: endpoint {
|
||||
remote-endpoint = <&cam>;
|
||||
|
@ -24,10 +24,6 @@ properties:
|
||||
- sony,imx258
|
||||
- sony,imx258-pdaf
|
||||
|
||||
assigned-clocks: true
|
||||
assigned-clock-parents: true
|
||||
assigned-clock-rates: true
|
||||
|
||||
clocks:
|
||||
description:
|
||||
Clock frequency from 6 to 27 MHz.
|
||||
@ -125,9 +121,6 @@ examples:
|
||||
reg = <0x6c>;
|
||||
clocks = <&imx258_clk>;
|
||||
|
||||
assigned-clocks = <&imx258_clk>;
|
||||
assigned-clock-rates = <19200000>;
|
||||
|
||||
port {
|
||||
endpoint {
|
||||
remote-endpoint = <&csi1_ep>;
|
||||
|
@ -24,10 +24,6 @@ properties:
|
||||
description: I2C address
|
||||
maxItems: 1
|
||||
|
||||
assigned-clocks: true
|
||||
assigned-clock-parents: true
|
||||
assigned-clock-rates: true
|
||||
|
||||
clocks:
|
||||
description: Clock frequency from 6 to 27 MHz, 37.125MHz, 74.25MHz
|
||||
maxItems: 1
|
||||
@ -74,10 +70,6 @@ examples:
|
||||
reg = <0x1a>;
|
||||
clocks = <&imx334_clk>;
|
||||
|
||||
assigned-clocks = <&imx334_clk>;
|
||||
assigned-clock-parents = <&imx334_clk_parent>;
|
||||
assigned-clock-rates = <24000000>;
|
||||
|
||||
port {
|
||||
imx334: endpoint {
|
||||
remote-endpoint = <&cam>;
|
||||
|
@ -24,10 +24,6 @@ properties:
|
||||
description: I2C address
|
||||
maxItems: 1
|
||||
|
||||
assigned-clocks: true
|
||||
assigned-clock-parents: true
|
||||
assigned-clock-rates: true
|
||||
|
||||
clocks:
|
||||
description: Clock frequency from 6 to 27 MHz, 37.125MHz, 74.25MHz
|
||||
maxItems: 1
|
||||
@ -86,10 +82,6 @@ examples:
|
||||
reg = <0x1a>;
|
||||
clocks = <&imx335_clk>;
|
||||
|
||||
assigned-clocks = <&imx335_clk>;
|
||||
assigned-clock-parents = <&imx335_clk_parent>;
|
||||
assigned-clock-rates = <24000000>;
|
||||
|
||||
avdd-supply = <&camera_vdda_2v9>;
|
||||
ovdd-supply = <&camera_vddo_1v8>;
|
||||
dvdd-supply = <&camera_vddd_1v2>;
|
||||
|
@ -26,10 +26,6 @@ properties:
|
||||
description: I2C address
|
||||
maxItems: 1
|
||||
|
||||
assigned-clocks: true
|
||||
assigned-clock-parents: true
|
||||
assigned-clock-rates: true
|
||||
|
||||
clocks:
|
||||
description: Clock frequency 6MHz, 12MHz, 18MHz, 24MHz or 27MHz
|
||||
maxItems: 1
|
||||
@ -86,10 +82,6 @@ examples:
|
||||
reg = <0x1a>;
|
||||
clocks = <&imx412_clk>;
|
||||
|
||||
assigned-clocks = <&imx412_clk>;
|
||||
assigned-clock-parents = <&imx412_clk_parent>;
|
||||
assigned-clock-rates = <24000000>;
|
||||
|
||||
port {
|
||||
imx412: endpoint {
|
||||
remote-endpoint = <&cam>;
|
||||
|
322
Documentation/devicetree/bindings/media/qcom,msm8953-camss.yaml
Normal file
322
Documentation/devicetree/bindings/media/qcom,msm8953-camss.yaml
Normal 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 = <®_2v8>;
|
||||
|
||||
ports {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
};
|
||||
};
|
@ -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>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
@ -32,6 +32,7 @@ properties:
|
||||
- renesas,r8a77990-csi2 # R-Car E3
|
||||
- renesas,r8a779a0-csi2 # R-Car V3U
|
||||
- renesas,r8a779g0-csi2 # R-Car V4H
|
||||
- renesas,r8a779h0-csi2 # R-Car V4M
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
@ -22,6 +22,8 @@ properties:
|
||||
- enum:
|
||||
- renesas,r8a779a0-isp # V3U
|
||||
- renesas,r8a779g0-isp # V4H
|
||||
- renesas,r8a779h0-isp # V4M
|
||||
- const: renesas,rcar-gen4-isp # Generic R-Car Gen4
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
@ -116,7 +118,7 @@ examples:
|
||||
#include <dt-bindings/power/r8a779a0-sysc.h>
|
||||
|
||||
isp1: isp@fed20000 {
|
||||
compatible = "renesas,r8a779a0-isp";
|
||||
compatible = "renesas,r8a779a0-isp", "renesas,rcar-gen4-isp";
|
||||
reg = <0xfed20000 0x10000>;
|
||||
interrupts = <GIC_SPI 155 IRQ_TYPE_LEVEL_HIGH>;
|
||||
clocks = <&cpg CPG_MOD 613>;
|
||||
|
@ -13,7 +13,7 @@ description: |
|
||||
CSI_RX_IF section.
|
||||
|
||||
maintainers:
|
||||
- Jai Luthra <j-luthra@ti.com>
|
||||
- Jai Luthra <jai.luthra@linux.dev>
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
|
@ -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
|
||||
responsible for this coordination, and instruct camera sensors to stop and
|
||||
restart streaming by calling the appropriate subdev operations
|
||||
(``.s_stream()``, ``.enable_streams()`` or ``.disable_streams()``). Camera
|
||||
sensor drivers shall therefore **not** keep track of the streaming state to
|
||||
stop streaming in the PM suspend handler and restart it in the resume handler.
|
||||
Drivers should in general not implement the system PM handlers.
|
||||
(``.enable_streams()`` or ``.disable_streams()``). Camera sensor drivers shall
|
||||
therefore **not** keep track of the streaming state to stop streaming in the PM
|
||||
suspend handler and restart it in the resume handler. Drivers should in general
|
||||
not implement the system PM handlers.
|
||||
|
||||
Camera sensor drivers shall **not** implement the subdev ``.s_power()``
|
||||
operation, as it is deprecated. While this operation is implemented in some
|
||||
|
@ -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
|
||||
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
|
||||
====================
|
||||
|
||||
|
@ -49,11 +49,14 @@ Link frequency
|
||||
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).
|
||||
|
||||
``.s_stream()`` callback
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
``.enable_streams()`` and ``.disable_streams()`` callbacks
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The struct struct v4l2_subdev_video_ops->s_stream() callback is used by the
|
||||
receiver driver to control the transmitter driver's streaming state.
|
||||
The struct v4l2_subdev_pad_ops->enable_streams() and struct
|
||||
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
|
||||
@ -127,7 +130,7 @@ Stopping the transmitter
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
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,
|
||||
effectively leaving the current frame unfinished. The receiver driver
|
||||
should not make assumptions either way, but function properly in both
|
||||
|
@ -27,7 +27,7 @@ Arguments
|
||||
File descriptor returned by open().
|
||||
|
||||
``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.
|
||||
|
||||
Description
|
||||
|
@ -290,13 +290,15 @@ Control IDs
|
||||
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
|
||||
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)``
|
||||
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
|
||||
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:
|
||||
|
||||
|
@ -16,6 +16,7 @@ These formats are used for the :ref:`metadata` interface only.
|
||||
metafmt-generic
|
||||
metafmt-intel-ipu3
|
||||
metafmt-pisp-be
|
||||
metafmt-pisp-fe
|
||||
metafmt-rkisp1
|
||||
metafmt-uvc
|
||||
metafmt-vivid
|
||||
|
39
Documentation/userspace-api/media/v4l/metafmt-pisp-fe.rst
Normal file
39
Documentation/userspace-api/media/v4l/metafmt-pisp-fe.rst
Normal 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.
|
73
Documentation/userspace-api/media/v4l/pixfmt-y16i.rst
Normal file
73
Documentation/userspace-api/media/v4l/pixfmt-y16i.rst
Normal 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`
|
@ -86,6 +86,16 @@ the ``mbus_code`` field is handled differently:
|
||||
- ``index``
|
||||
- Number of the format in the enumeration, set by the application.
|
||||
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
|
||||
- ``type``
|
||||
- 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``
|
||||
Data Units of data and the offset (in bytes) between the beginning of
|
||||
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
|
||||
============
|
||||
|
@ -269,5 +269,6 @@ image.
|
||||
pixfmt-yuv-luma
|
||||
pixfmt-y8i
|
||||
pixfmt-y12i
|
||||
pixfmt-y16i
|
||||
pixfmt-uv8
|
||||
pixfmt-m420
|
||||
|
@ -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_QUANTIZATION fmtdesc-flags
|
||||
replace define V4L2_FMT_FLAG_META_LINE_BASED fmtdesc-flags
|
||||
replace define V4L2_FMTDESC_FLAG_ENUM_ALL fmtdesc-flags
|
||||
|
||||
# V4L2 timecode types
|
||||
replace define V4L2_TC_TYPE_24FPS timecode-type
|
||||
|
358
MAINTAINERS
358
MAINTAINERS
File diff suppressed because it is too large
Load Diff
@ -438,6 +438,6 @@ static void __exit cec_devnode_exit(void)
|
||||
subsys_initcall(cec_devnode_init);
|
||||
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_LICENSE("GPL");
|
||||
|
@ -99,7 +99,7 @@ config CEC_TEGRA
|
||||
|
||||
config CEC_SECO
|
||||
tristate "SECO Boards HDMI CEC driver"
|
||||
depends on X86 || COMPILE_TEST
|
||||
depends on X86 || (COMPILE_TEST && HAS_IOPORT)
|
||||
depends on PCI && DMI
|
||||
select CEC_CORE
|
||||
select CEC_NOTIFIER
|
||||
|
@ -279,7 +279,7 @@ MODULE_DEVICE_TABLE(of, cec_gpio_match);
|
||||
|
||||
static struct platform_driver cec_gpio_pdrv = {
|
||||
.probe = cec_gpio_probe,
|
||||
.remove_new = cec_gpio_remove,
|
||||
.remove = cec_gpio_remove,
|
||||
.driver = {
|
||||
.name = "cec-gpio",
|
||||
.of_match_table = cec_gpio_match,
|
||||
@ -288,6 +288,6 @@ static struct 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_DESCRIPTION("CEC GPIO driver");
|
||||
|
@ -582,7 +582,7 @@ MODULE_DEVICE_TABLE(platform, cros_ec_cec_id);
|
||||
|
||||
static struct platform_driver cros_ec_cec_driver = {
|
||||
.probe = cros_ec_cec_probe,
|
||||
.remove_new = cros_ec_cec_remove,
|
||||
.remove = cros_ec_cec_remove,
|
||||
.driver = {
|
||||
.name = DRV_NAME,
|
||||
.pm = &cros_ec_cec_pm_ops,
|
||||
|
@ -778,7 +778,7 @@ MODULE_DEVICE_TABLE(of, meson_ao_cec_g12a_of_match);
|
||||
|
||||
static struct platform_driver meson_ao_cec_g12a_driver = {
|
||||
.probe = meson_ao_cec_g12a_probe,
|
||||
.remove_new = meson_ao_cec_g12a_remove,
|
||||
.remove = meson_ao_cec_g12a_remove,
|
||||
.driver = {
|
||||
.name = "meson-ao-cec-g12a",
|
||||
.of_match_table = of_match_ptr(meson_ao_cec_g12a_of_match),
|
||||
|
@ -714,7 +714,7 @@ MODULE_DEVICE_TABLE(of, meson_ao_cec_of_match);
|
||||
|
||||
static struct platform_driver meson_ao_cec_driver = {
|
||||
.probe = meson_ao_cec_probe,
|
||||
.remove_new = meson_ao_cec_remove,
|
||||
.remove = meson_ao_cec_remove,
|
||||
.driver = {
|
||||
.name = "meson-ao-cec",
|
||||
.of_match_table = meson_ao_cec_of_match,
|
||||
|
@ -294,7 +294,7 @@ MODULE_DEVICE_TABLE(of, s5p_cec_match);
|
||||
|
||||
static struct platform_driver s5p_cec_pdrv = {
|
||||
.probe = s5p_cec_probe,
|
||||
.remove_new = s5p_cec_remove,
|
||||
.remove = s5p_cec_remove,
|
||||
.driver = {
|
||||
.name = CEC_NAME,
|
||||
.of_match_table = s5p_cec_match,
|
||||
|
@ -778,7 +778,7 @@ static struct platform_driver secocec_driver = {
|
||||
.pm = SECOCEC_PM_OPS,
|
||||
},
|
||||
.probe = secocec_probe,
|
||||
.remove_new = secocec_remove,
|
||||
.remove = secocec_remove,
|
||||
};
|
||||
|
||||
module_platform_driver(secocec_driver);
|
||||
|
@ -383,7 +383,7 @@ MODULE_DEVICE_TABLE(of, stih_cec_match);
|
||||
|
||||
static struct platform_driver stih_cec_pdrv = {
|
||||
.probe = stih_cec_probe,
|
||||
.remove_new = stih_cec_remove,
|
||||
.remove = stih_cec_remove,
|
||||
.driver = {
|
||||
.name = CEC_NAME,
|
||||
.of_match_table = stih_cec_match,
|
||||
|
@ -361,7 +361,7 @@ MODULE_DEVICE_TABLE(of, stm32_cec_of_match);
|
||||
|
||||
static struct platform_driver stm32_cec_driver = {
|
||||
.probe = stm32_cec_probe,
|
||||
.remove_new = stm32_cec_remove,
|
||||
.remove = stm32_cec_remove,
|
||||
.driver = {
|
||||
.name = CEC_NAME,
|
||||
.of_match_table = stm32_cec_of_match,
|
||||
|
@ -465,7 +465,7 @@ static struct platform_driver tegra_cec_driver = {
|
||||
.of_match_table = tegra_cec_of_match,
|
||||
},
|
||||
.probe = tegra_cec_probe,
|
||||
.remove_new = tegra_cec_remove,
|
||||
.remove = tegra_cec_remove,
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
.suspend = tegra_cec_suspend,
|
||||
|
@ -407,8 +407,6 @@ const struct vb2_ops vbi_qops = {
|
||||
.buf_cleanup = buf_cleanup,
|
||||
.start_streaming = start_streaming,
|
||||
.stop_streaming = stop_streaming,
|
||||
.wait_prepare = vb2_ops_wait_prepare,
|
||||
.wait_finish = vb2_ops_wait_finish,
|
||||
};
|
||||
|
||||
/* ------------------------------------------------------------------ */
|
||||
|
@ -681,8 +681,6 @@ const struct vb2_ops video_qops = {
|
||||
.buf_cleanup = buf_cleanup,
|
||||
.start_streaming = start_streaming,
|
||||
.stop_streaming = stop_streaming,
|
||||
.wait_prepare = vb2_ops_wait_prepare,
|
||||
.wait_finish = vb2_ops_wait_finish,
|
||||
};
|
||||
|
||||
/********************************************************************************/
|
||||
|
@ -398,8 +398,6 @@ void smsdvb_debugfs_release(struct smsdvb_client_t *client)
|
||||
|
||||
void smsdvb_debugfs_register(void)
|
||||
{
|
||||
struct dentry *d;
|
||||
|
||||
/*
|
||||
* FIXME: This was written to debug Siano USB devices. So, it creates
|
||||
* 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
|
||||
* subsystem.
|
||||
*/
|
||||
d = 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;
|
||||
smsdvb_debugfs_usb_root = debugfs_create_dir("smsdvb", usb_debug_root);
|
||||
}
|
||||
|
||||
void smsdvb_debugfs_unregister(void)
|
||||
|
@ -96,6 +96,10 @@ static const struct uvc_format_desc uvc_fmts[] = {
|
||||
.guid = UVC_GUID_FORMAT_RGBP,
|
||||
.fcc = V4L2_PIX_FMT_RGB565,
|
||||
},
|
||||
{
|
||||
.guid = UVC_GUID_FORMAT_D3DFMT_R5G6B5,
|
||||
.fcc = V4L2_PIX_FMT_RGB565,
|
||||
},
|
||||
{
|
||||
.guid = UVC_GUID_FORMAT_BGR3,
|
||||
.fcc = V4L2_PIX_FMT_BGR24,
|
||||
@ -120,6 +124,10 @@ static const struct uvc_format_desc uvc_fmts[] = {
|
||||
.guid = UVC_GUID_FORMAT_Y12I,
|
||||
.fcc = V4L2_PIX_FMT_Y12I,
|
||||
},
|
||||
{
|
||||
.guid = UVC_GUID_FORMAT_Y16I,
|
||||
.fcc = V4L2_PIX_FMT_Y16I,
|
||||
},
|
||||
{
|
||||
.guid = UVC_GUID_FORMAT_Z16,
|
||||
.fcc = V4L2_PIX_FMT_Z16,
|
||||
|
@ -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
|
||||
* allow streamoff or qbuf to be called while waiting.
|
||||
*/
|
||||
if (q->ops->wait_prepare)
|
||||
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.
|
||||
@ -2047,12 +2050,16 @@ static int __vb2_wait_for_done_vb(struct vb2_queue *q, int nonblocking)
|
||||
!list_empty(&q->done_list) || !q->streaming ||
|
||||
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
|
||||
* the locks or return an error if one occurred.
|
||||
*/
|
||||
call_void_qop(q, wait_finish, q);
|
||||
q->waiting_in_dqbuf = 0;
|
||||
if (ret) {
|
||||
dprintk(q, 1, "sleep was interrupted\n");
|
||||
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) {
|
||||
dprintk(q, 1, "need at least %u queued buffers\n",
|
||||
dprintk(q, 1, "need at least %u allocated buffers\n",
|
||||
q->min_queued_buffers);
|
||||
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))
|
||||
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->done_list);
|
||||
spin_lock_init(&q->done_lock);
|
||||
@ -3205,10 +3220,17 @@ static int vb2_thread(void *data)
|
||||
continue;
|
||||
prequeue--;
|
||||
} else {
|
||||
if (!threadio->stop) {
|
||||
if (q->ops->wait_finish)
|
||||
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);
|
||||
if (q->ops->wait_prepare)
|
||||
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);
|
||||
if (!ret)
|
||||
vb = vb2_get_buffer(q, index);
|
||||
@ -3220,12 +3242,19 @@ static int vb2_thread(void *data)
|
||||
if (vb->state != VB2_BUF_STATE_ERROR)
|
||||
if (threadio->fnc(vb, threadio->priv))
|
||||
break;
|
||||
call_void_qop(q, wait_finish, q);
|
||||
if (copy_timestamp)
|
||||
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);
|
||||
if (q->ops->wait_prepare)
|
||||
call_void_qop(q, wait_prepare, q);
|
||||
else if (q->lock)
|
||||
mutex_unlock(q->lock);
|
||||
}
|
||||
if (ret || threadio->stop)
|
||||
break;
|
||||
}
|
||||
|
@ -231,7 +231,7 @@ static int vb2_fill_vb2_v4l2_buffer(struct vb2_buffer *vb, struct v4l2_buffer *b
|
||||
break;
|
||||
}
|
||||
|
||||
/* Fill in driver-provided information for OUTPUT types */
|
||||
/* Fill in user-provided information for OUTPUT types */
|
||||
if (V4L2_TYPE_IS_OUTPUT(b->type)) {
|
||||
/*
|
||||
* Will have to go up to b->length when API starts
|
||||
|
@ -729,7 +729,7 @@ static int bcm3510_init_cold(struct bcm3510_state *st)
|
||||
int ret;
|
||||
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)
|
||||
return ret;
|
||||
if (v.APSTAT1_a2.RUN) {
|
||||
|
@ -78,7 +78,7 @@ MODULE_PARM_DESC(debug, "turn on debugging (default: 0)");
|
||||
#define SOC_8090_P1G_11R1 0x86
|
||||
#define SOC_8090_P1G_21R1 0x8e
|
||||
|
||||
/* else use thos ones to check */
|
||||
/* else use those ones to check */
|
||||
#define P1A_B 0x0
|
||||
#define P1C 0x1
|
||||
#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))
|
||||
dib0090_set_EFUSE(state);
|
||||
|
||||
/* Congigure in function of the crystal */
|
||||
/* Configure in function of the crystal */
|
||||
if (state->config->force_crystal_mode != 0)
|
||||
dib0090_write_reg(state, 0x14,
|
||||
state->config->force_crystal_mode & 3);
|
||||
|
@ -640,7 +640,7 @@ static int dib3000mb_read_ber(struct dvb_frontend* fe, u32 *ber)
|
||||
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)
|
||||
{
|
||||
struct dib3000_state* state = fe->demodulator_priv;
|
||||
|
@ -947,8 +947,6 @@ static const struct vb2_ops rtl2832_sdr_vb2_ops = {
|
||||
.buf_queue = rtl2832_sdr_buf_queue,
|
||||
.start_streaming = rtl2832_sdr_start_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,
|
||||
@ -1487,7 +1485,7 @@ static struct platform_driver rtl2832_sdr_driver = {
|
||||
.name = "rtl2832_sdr",
|
||||
},
|
||||
.probe = rtl2832_sdr_probe,
|
||||
.remove_new = rtl2832_sdr_remove,
|
||||
.remove = rtl2832_sdr_remove,
|
||||
};
|
||||
module_platform_driver(rtl2832_sdr_driver);
|
||||
|
||||
|
@ -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)
|
||||
*/
|
||||
static const struct slookup gain_channel_agc_nf_lookup[] = {
|
||||
|
@ -954,7 +954,7 @@ static int RFTrackingFiltersCorrection(struct tda_state *state,
|
||||
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. */
|
||||
state->m_Regs[EB14] = Capprox;
|
||||
|
||||
|
@ -553,13 +553,19 @@ static void ts2020_regmap_unlock(void *__dev)
|
||||
static int ts2020_probe(struct i2c_client *client)
|
||||
{
|
||||
struct ts2020_config *pdata = client->dev.platform_data;
|
||||
struct dvb_frontend *fe = pdata->fe;
|
||||
struct dvb_frontend *fe;
|
||||
struct ts2020_priv *dev;
|
||||
int ret;
|
||||
u8 u8tmp;
|
||||
unsigned int utmp;
|
||||
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);
|
||||
if (!dev) {
|
||||
ret = -ENOMEM;
|
||||
|
@ -531,7 +531,7 @@ static struct platform_driver zd1301_demod_driver = {
|
||||
.suppress_bind_attrs = true,
|
||||
},
|
||||
.probe = zd1301_demod_probe,
|
||||
.remove_new = zd1301_demod_remove,
|
||||
.remove = zd1301_demod_remove,
|
||||
};
|
||||
module_platform_driver(zd1301_demod_driver);
|
||||
|
||||
|
@ -89,7 +89,7 @@ static int zl10036_write(struct zl10036_state *state, u8 buf[], u8 count)
|
||||
int ret;
|
||||
|
||||
if (zl10036_debug & 0x02) {
|
||||
/* every 8bit-value satisifes this!
|
||||
/* every 8bit-value satisfies this!
|
||||
* so only check for debug log */
|
||||
if ((buf[0] & 0x80) == 0x00)
|
||||
reg = 2;
|
||||
|
@ -1440,7 +1440,8 @@ static int adv7180_probe(struct i2c_client *client)
|
||||
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;
|
||||
|
||||
if (state->chip_info->flags & ADV7180_FLAG_MIPI_CSI2) {
|
||||
|
@ -116,6 +116,9 @@ struct adv7511_state {
|
||||
unsigned edid_detect_counter;
|
||||
struct workqueue_struct *work_queue;
|
||||
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);
|
||||
@ -483,27 +486,25 @@ static u8 hdmi_infoframe_checksum(u8 *ptr, size_t size)
|
||||
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;
|
||||
int i;
|
||||
|
||||
if (!(adv7511_rd(sd, cri->present_reg) & cri->present_mask)) {
|
||||
v4l2_info(sd, "%s infoframe not transmitted\n", cri->desc);
|
||||
return;
|
||||
return 0;
|
||||
}
|
||||
|
||||
memcpy(buffer, cri->header, sizeof(cri->header));
|
||||
|
||||
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);
|
||||
return;
|
||||
return 0;
|
||||
}
|
||||
|
||||
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] = hdmi_infoframe_checksum(buffer, len + 4);
|
||||
|
||||
if (hdmi_infoframe_unpack(&frame, buffer, len + 4) < 0) {
|
||||
v4l2_err(sd, "%s: unpack of %s infoframe failed\n", __func__, cri->desc);
|
||||
return len + 4;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
hdmi_infoframe_log(KERN_INFO, dev, &frame);
|
||||
}
|
||||
|
||||
static void adv7511_log_infoframes(struct v4l2_subdev *sd)
|
||||
{
|
||||
static const struct adv7511_cfg_read_infoframe cri[] = {
|
||||
{ "AVI", 0x44, 0x10, { 0x82, 2, 13 }, 0x55 },
|
||||
{ "Audio", 0x44, 0x08, { 0x84, 1, 10 }, 0x73 },
|
||||
{ "SDP", 0x40, 0x40, { 0x83, 1, 25 }, 0x103 },
|
||||
};
|
||||
|
||||
static void adv7511_log_infoframes(struct v4l2_subdev *sd)
|
||||
{
|
||||
int 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;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
struct adv7511_state *state = get_adv7511_state(sd);
|
||||
@ -1700,16 +1746,27 @@ static int adv7511_registered(struct v4l2_subdev *sd)
|
||||
int err;
|
||||
|
||||
err = cec_register_adapter(state->cec_adap, &client->dev);
|
||||
if (err)
|
||||
if (err) {
|
||||
cec_delete_adapter(state->cec_adap);
|
||||
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)
|
||||
{
|
||||
struct adv7511_state *state = get_adv7511_state(sd);
|
||||
|
||||
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 = {
|
||||
|
@ -42,7 +42,7 @@ module_param(debug, int, 0644);
|
||||
MODULE_PARM_DESC(debug, "debug level (0-2)");
|
||||
|
||||
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_LICENSE("GPL");
|
||||
|
||||
@ -193,6 +193,9 @@ struct adv76xx_state {
|
||||
struct delayed_work delayed_work_enable_hotplug;
|
||||
bool restart_stdi_once;
|
||||
|
||||
struct dentry *debugfs_dir;
|
||||
struct v4l2_debugfs_if *infoframes;
|
||||
|
||||
/* CEC */
|
||||
struct cec_adapter *cec_adap;
|
||||
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,
|
||||
(stdi->hs_pol == '+' ? V4L2_DV_HSYNC_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;
|
||||
if (v4l2_detect_gtf(stdi->lcf + 1, hfreq, stdi->lcvs,
|
||||
(stdi->hs_pol == '+' ? V4L2_DV_HSYNC_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;
|
||||
|
||||
v4l2_dbg(2, debug, sd,
|
||||
@ -2458,10 +2462,9 @@ static const struct adv76xx_cfg_read_infoframe adv76xx_cri[] = {
|
||||
{ "Vendor", 0x10, 0xec, 0x54 }
|
||||
};
|
||||
|
||||
static int adv76xx_read_infoframe(struct v4l2_subdev *sd, int index,
|
||||
union hdmi_infoframe *frame)
|
||||
static int adv76xx_read_infoframe_buf(struct v4l2_subdev *sd, int index,
|
||||
u8 buf[V4L2_DEBUGFS_IF_MAX_LEN])
|
||||
{
|
||||
uint8_t buffer[32];
|
||||
u8 len;
|
||||
int i;
|
||||
|
||||
@ -2472,27 +2475,20 @@ static int adv76xx_read_infoframe(struct v4l2_subdev *sd, int index,
|
||||
}
|
||||
|
||||
for (i = 0; i < 3; i++)
|
||||
buffer[i] = infoframe_read(sd,
|
||||
adv76xx_cri[index].head_addr + i);
|
||||
buf[i] = infoframe_read(sd, 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__,
|
||||
adv76xx_cri[index].desc, len);
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
for (i = 0; i < len; i++)
|
||||
buffer[i + 3] = infoframe_read(sd,
|
||||
buf[i + 3] = infoframe_read(sd,
|
||||
adv76xx_cri[index].payload_addr + i);
|
||||
|
||||
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;
|
||||
return len + 3;
|
||||
}
|
||||
|
||||
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++) {
|
||||
union hdmi_infoframe frame;
|
||||
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);
|
||||
}
|
||||
}
|
||||
@ -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)
|
||||
{
|
||||
struct adv76xx_state *state = to_state(sd);
|
||||
@ -2701,16 +2741,27 @@ static int adv76xx_registered(struct v4l2_subdev *sd)
|
||||
int err;
|
||||
|
||||
err = cec_register_adapter(state->cec_adap, &client->dev);
|
||||
if (err)
|
||||
if (err) {
|
||||
cec_delete_adapter(state->cec_adap);
|
||||
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)
|
||||
{
|
||||
struct adv76xx_state *state = to_state(sd);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------- */
|
||||
|
@ -38,7 +38,7 @@ module_param(debug, int, 0644);
|
||||
MODULE_PARM_DESC(debug, "debug level (0-2)");
|
||||
|
||||
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_LICENSE("GPL");
|
||||
|
||||
@ -114,6 +114,9 @@ struct adv7842_state {
|
||||
bool restart_stdi_once;
|
||||
bool hdmi_port_a;
|
||||
|
||||
struct dentry *debugfs_dir;
|
||||
struct v4l2_debugfs_if *infoframes;
|
||||
|
||||
/* i2c clients */
|
||||
struct i2c_client *i2c_sdp_io;
|
||||
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,
|
||||
(stdi->hs_pol == '+' ? V4L2_DV_HSYNC_POS_POL : 0) |
|
||||
(stdi->vs_pol == '+' ? V4L2_DV_VSYNC_POS_POL : 0),
|
||||
false, timings))
|
||||
false, adv7842_get_dv_timings_cap(sd), timings))
|
||||
return 0;
|
||||
if (v4l2_detect_gtf(stdi->lcf + 1, hfreq, stdi->lcvs,
|
||||
(stdi->hs_pol == '+' ? V4L2_DV_HSYNC_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;
|
||||
|
||||
v4l2_dbg(2, debug, sd,
|
||||
@ -2565,58 +2569,65 @@ struct adv7842_cfg_read_infoframe {
|
||||
u8 payload_addr;
|
||||
};
|
||||
|
||||
static void log_infoframe(struct v4l2_subdev *sd, const struct adv7842_cfg_read_infoframe *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[] = {
|
||||
static const struct adv7842_cfg_read_infoframe adv7842_cri[] = {
|
||||
{ "AVI", 0x01, 0xe0, 0x00 },
|
||||
{ "Audio", 0x02, 0xe3, 0x1c },
|
||||
{ "SDP", 0x04, 0xe6, 0x2a },
|
||||
{ "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)) {
|
||||
v4l2_info(sd, "receive DVI-D signal, no infoframes\n");
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(cri); i++)
|
||||
log_infoframe(sd, &cri[i]);
|
||||
for (i = 0; i < ARRAY_SIZE(adv7842_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
|
||||
@ -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)
|
||||
{
|
||||
struct adv7842_state *state = to_state(sd);
|
||||
@ -3270,8 +3316,15 @@ static int adv7842_registered(struct v4l2_subdev *sd)
|
||||
int err;
|
||||
|
||||
err = cec_register_adapter(state->cec_adap, &client->dev);
|
||||
if (err)
|
||||
if (err) {
|
||||
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;
|
||||
}
|
||||
|
||||
@ -3280,6 +3333,10 @@ static void adv7842_unregistered(struct v4l2_subdev *sd)
|
||||
struct adv7842_state *state = to_state(sd);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------- */
|
||||
|
@ -16,7 +16,6 @@
|
||||
#include <media/v4l2-async.h>
|
||||
#include <media/v4l2-ctrls.h>
|
||||
#include <media/v4l2-device.h>
|
||||
#include <media/v4l2-event.h>
|
||||
#include <media/v4l2-fwnode.h>
|
||||
#include <media/v4l2-subdev.h>
|
||||
|
||||
@ -2240,8 +2239,6 @@ free_ctrls:
|
||||
|
||||
static const struct v4l2_subdev_core_ops alvium_core_ops = {
|
||||
.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 = {
|
||||
@ -2289,7 +2286,7 @@ static int alvium_subdev_init(struct alvium_dev *alvium)
|
||||
v4l2_i2c_subdev_init(sd, client, &alvium_subdev_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;
|
||||
sd->entity.function = MEDIA_ENT_F_CAM_SENSOR;
|
||||
|
||||
|
@ -24,7 +24,6 @@
|
||||
|
||||
#include <media/i2c/ds90ub9xx.h>
|
||||
#include <media/v4l2-ctrls.h>
|
||||
#include <media/v4l2-event.h>
|
||||
#include <media/v4l2-fwnode.h>
|
||||
#include <media/v4l2-mediabus.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 = {
|
||||
.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 = {
|
||||
@ -1246,7 +1243,7 @@ static int ub953_subdev_init(struct ub953_data *priv)
|
||||
priv->sd.internal_ops = &ub953_internal_ops;
|
||||
|
||||
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.ops = &ub953_entity_ops;
|
||||
|
||||
|
@ -48,7 +48,6 @@
|
||||
#include <media/i2c/ds90ub9xx.h>
|
||||
#include <media/mipi-csi2.h>
|
||||
#include <media/v4l2-ctrls.h>
|
||||
#include <media/v4l2-event.h>
|
||||
#include <media/v4l2-fwnode.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;
|
||||
|
||||
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)
|
||||
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 = {
|
||||
.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 = {
|
||||
@ -3667,7 +3664,7 @@ static int ub960_create_subdev(struct ub960_data *priv)
|
||||
}
|
||||
|
||||
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.ops = &ub960_entity_ops;
|
||||
|
||||
|
@ -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)
|
||||
{
|
||||
pm_runtime_put(sd->dev);
|
||||
pm_runtime_mark_last_busy(sd->dev);
|
||||
pm_runtime_put_autosuspend(sd->dev);
|
||||
|
||||
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
|
||||
* remove.
|
||||
*/
|
||||
pm_runtime_enable(dev);
|
||||
full_power = (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));
|
||||
if (full_power) {
|
||||
ret = dw9768_runtime_resume(dev);
|
||||
if (ret < 0) {
|
||||
@ -484,23 +484,26 @@ static int dw9768_probe(struct i2c_client *client)
|
||||
pm_runtime_set_active(dev);
|
||||
}
|
||||
|
||||
pm_runtime_enable(dev);
|
||||
ret = v4l2_async_register_subdev(&dw9768->sd);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "failed to register V4L2 subdev: %d", ret);
|
||||
goto err_power_off;
|
||||
}
|
||||
|
||||
pm_runtime_set_autosuspend_delay(dev, 1000);
|
||||
pm_runtime_use_autosuspend(dev);
|
||||
pm_runtime_idle(dev);
|
||||
|
||||
return 0;
|
||||
|
||||
err_power_off:
|
||||
pm_runtime_disable(dev);
|
||||
if (full_power) {
|
||||
dw9768_runtime_suspend(dev);
|
||||
pm_runtime_set_suspended(dev);
|
||||
}
|
||||
err_clean_entity:
|
||||
pm_runtime_disable(dev);
|
||||
media_entity_cleanup(&dw9768->sd.entity);
|
||||
err_free_handler:
|
||||
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_ctrl_handler_free(&dw9768->ctrls);
|
||||
media_entity_cleanup(&dw9768->sd.entity);
|
||||
pm_runtime_disable(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);
|
||||
pm_runtime_set_suspended(dev);
|
||||
}
|
||||
pm_runtime_disable(dev);
|
||||
}
|
||||
|
||||
static const struct of_device_id dw9768_of_table[] = {
|
||||
|
@ -18,7 +18,6 @@
|
||||
#include <media/v4l2-cci.h>
|
||||
#include <media/v4l2-ctrls.h>
|
||||
#include <media/v4l2-device.h>
|
||||
#include <media/v4l2-event.h>
|
||||
#include <media/v4l2-fwnode.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 = {
|
||||
.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
|
||||
.g_register = gc0308_g_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);
|
||||
gc0308->sd.internal_ops = &gc0308_internal_ops;
|
||||
gc0308->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
|
||||
gc0308->sd.flags |= V4L2_SUBDEV_FL_HAS_EVENTS;
|
||||
|
||||
ret = gc0308_init_controls(gc0308);
|
||||
if (ret)
|
||||
|
@ -24,7 +24,6 @@
|
||||
|
||||
#include <media/v4l2-cci.h>
|
||||
#include <media/v4l2-ctrls.h>
|
||||
#include <media/v4l2-event.h>
|
||||
#include <media/v4l2-fwnode.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,
|
||||
};
|
||||
|
||||
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 = {
|
||||
.core = &gc05a2_core_ops,
|
||||
.video = &gc05a2_video_ops,
|
||||
.pad = &gc05a2_subdev_pad_ops,
|
||||
};
|
||||
@ -1271,8 +1264,7 @@ static int gc05a2_probe(struct i2c_client *client)
|
||||
return dev_err_probe(dev, ret,
|
||||
"failed to init controls\n");
|
||||
|
||||
gc05a2->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE |
|
||||
V4L2_SUBDEV_FL_HAS_EVENTS;
|
||||
gc05a2->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
|
||||
gc05a2->pad.flags = MEDIA_PAD_FL_SOURCE;
|
||||
gc05a2->sd.dev = &client->dev;
|
||||
gc05a2->sd.entity.function = MEDIA_ENT_F_CAM_SENSOR;
|
||||
|
@ -24,7 +24,6 @@
|
||||
|
||||
#include <media/v4l2-cci.h>
|
||||
#include <media/v4l2-ctrls.h>
|
||||
#include <media/v4l2-event.h>
|
||||
#include <media/v4l2-fwnode.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,
|
||||
};
|
||||
|
||||
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 = {
|
||||
.core = &gc08a3_core_ops,
|
||||
.video = &gc08a3_video_ops,
|
||||
.pad = &gc08a3_subdev_pad_ops,
|
||||
};
|
||||
@ -1247,8 +1240,7 @@ static int gc08a3_probe(struct i2c_client *client)
|
||||
goto err_power_off;
|
||||
}
|
||||
|
||||
gc08a3->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE |
|
||||
V4L2_SUBDEV_FL_HAS_EVENTS;
|
||||
gc08a3->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
|
||||
gc08a3->pad.flags = MEDIA_PAD_FL_SOURCE;
|
||||
gc08a3->sd.dev = &client->dev;
|
||||
gc08a3->sd.entity.function = MEDIA_ENT_F_CAM_SENSOR;
|
||||
|
@ -21,7 +21,6 @@
|
||||
#include <media/v4l2-cci.h>
|
||||
#include <media/v4l2-ctrls.h>
|
||||
#include <media/v4l2-device.h>
|
||||
#include <media/v4l2-event.h>
|
||||
#include <media/v4l2-fwnode.h>
|
||||
#include <media/v4l2-mediabus.h>
|
||||
|
||||
@ -899,9 +898,11 @@ static int gc2145_config_mipi_mode(struct gc2145 *gc2145,
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int gc2145_start_streaming(struct gc2145 *gc2145,
|
||||
struct v4l2_subdev_state *state)
|
||||
static int gc2145_enable_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);
|
||||
const struct gc2145_format *gc2145_format;
|
||||
struct v4l2_mbus_framefmt *fmt;
|
||||
@ -967,8 +968,11 @@ err_rpm_put:
|
||||
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);
|
||||
int ret = 0;
|
||||
|
||||
@ -983,22 +987,6 @@ static void gc2145_stop_streaming(struct gc2145 *gc2145)
|
||||
|
||||
pm_runtime_mark_last_busy(&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;
|
||||
}
|
||||
@ -1123,13 +1111,8 @@ static const u8 test_pattern_val[] = {
|
||||
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 = {
|
||||
.s_stream = gc2145_set_stream,
|
||||
.s_stream = v4l2_subdev_s_stream_helper,
|
||||
};
|
||||
|
||||
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,
|
||||
.get_selection = gc2145_get_selection,
|
||||
.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 = {
|
||||
.core = &gc2145_core_ops,
|
||||
.video = &gc2145_video_ops,
|
||||
.pad = &gc2145_pad_ops,
|
||||
};
|
||||
@ -1407,8 +1391,7 @@ static int gc2145_probe(struct i2c_client *client)
|
||||
goto error_power_off;
|
||||
|
||||
/* Initialize subdev */
|
||||
gc2145->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE |
|
||||
V4L2_SUBDEV_FL_HAS_EVENTS;
|
||||
gc2145->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
|
||||
gc2145->sd.entity.function = MEDIA_ENT_F_CAM_SENSOR;
|
||||
|
||||
/* Initialize source pad */
|
||||
|
@ -644,7 +644,7 @@ struct hi556 {
|
||||
/* Current mode */
|
||||
const struct hi556_mode *cur_mode;
|
||||
|
||||
/* To serialize asynchronus callbacks */
|
||||
/* To serialize asynchronous callbacks */
|
||||
struct mutex mutex;
|
||||
|
||||
/* True if the device has been identified */
|
||||
|
@ -26,7 +26,6 @@
|
||||
#include <media/v4l2-cci.h>
|
||||
#include <media/v4l2-ctrls.h>
|
||||
#include <media/v4l2-device.h>
|
||||
#include <media/v4l2-event.h>
|
||||
#include <media/v4l2-fwnode.h>
|
||||
#include <media/v4l2-mediabus.h>
|
||||
|
||||
@ -922,11 +921,6 @@ static int imx219_init_state(struct v4l2_subdev *sd,
|
||||
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 = {
|
||||
.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 = {
|
||||
.core = &imx219_core_ops,
|
||||
.video = &imx219_video_ops,
|
||||
.pad = &imx219_pad_ops,
|
||||
};
|
||||
@ -1166,8 +1159,7 @@ static int imx219_probe(struct i2c_client *client)
|
||||
goto error_power_off;
|
||||
|
||||
/* Initialize subdev */
|
||||
imx219->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE |
|
||||
V4L2_SUBDEV_FL_HAS_EVENTS;
|
||||
imx219->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
|
||||
imx219->sd.entity.function = MEDIA_ENT_F_CAM_SENSOR;
|
||||
|
||||
/* Initialize source pad */
|
||||
|
@ -32,7 +32,6 @@
|
||||
#include <media/v4l2-cci.h>
|
||||
#include <media/v4l2-ctrls.h>
|
||||
#include <media/v4l2-device.h>
|
||||
#include <media/v4l2-event.h>
|
||||
#include <media/v4l2-fwnode.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 = {
|
||||
.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 = {
|
||||
.core = &imx283_core_ops,
|
||||
.video = &imx283_video_ops,
|
||||
.pad = &imx283_pad_ops,
|
||||
};
|
||||
@ -1548,8 +1541,7 @@ static int imx283_probe(struct i2c_client *client)
|
||||
goto error_pm;
|
||||
|
||||
/* Initialize subdev */
|
||||
imx283->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE |
|
||||
V4L2_SUBDEV_FL_HAS_EVENTS;
|
||||
imx283->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
|
||||
imx283->sd.entity.function = MEDIA_ENT_F_CAM_SENSOR;
|
||||
imx283->sd.internal_ops = &imx283_internal_ops;
|
||||
|
||||
|
@ -24,7 +24,6 @@
|
||||
#include <media/v4l2-cci.h>
|
||||
#include <media/v4l2-ctrls.h>
|
||||
#include <media/v4l2-device.h>
|
||||
#include <media/v4l2-event.h>
|
||||
#include <media/v4l2-fwnode.h>
|
||||
#include <media/v4l2-subdev.h>
|
||||
|
||||
@ -78,7 +77,6 @@
|
||||
#define IMX290_ADBIT2 CCI_REG8(0x317c)
|
||||
#define IMX290_ADBIT2_10BIT 0x12
|
||||
#define IMX290_ADBIT2_12BIT 0x00
|
||||
#define IMX290_CHIP_ID CCI_REG16_LE(0x319a)
|
||||
#define IMX290_ADBIT3 CCI_REG8(0x31ec)
|
||||
#define IMX290_ADBIT3_10BIT 0x37
|
||||
#define IMX290_ADBIT3_12BIT 0x0e
|
||||
@ -1211,11 +1209,6 @@ static int imx290_entity_init_state(struct v4l2_subdev *subdev,
|
||||
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 = {
|
||||
.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 = {
|
||||
.core = &imx290_core_ops,
|
||||
.video = &imx290_video_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];
|
||||
|
||||
/*
|
||||
* 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);
|
||||
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;
|
||||
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.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_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. */
|
||||
ret = imx290_subdev_init(imx290);
|
||||
if (ret)
|
||||
@ -1599,13 +1610,6 @@ static int imx290_probe(struct i2c_client *client)
|
||||
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;
|
||||
|
||||
err_subdev:
|
||||
|
@ -1113,8 +1113,7 @@ static int imx415_subdev_init(struct imx415 *sensor)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
sensor->subdev.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE |
|
||||
V4L2_SUBDEV_FL_HAS_EVENTS;
|
||||
sensor->subdev.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
|
||||
sensor->pad.flags = MEDIA_PAD_FL_SOURCE;
|
||||
sensor->subdev.entity.function = MEDIA_ENT_F_CAM_SENSOR;
|
||||
ret = media_entity_pads_init(&sensor->subdev.entity, 1, &sensor->pad);
|
||||
|
@ -697,8 +697,10 @@ static int max96717_subdev_init(struct max96717_priv *priv)
|
||||
priv->pads[MAX96717_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE;
|
||||
|
||||
ret = media_entity_pads_init(&priv->sd.entity, 2, priv->pads);
|
||||
if (ret)
|
||||
return dev_err_probe(dev, ret, "Failed to init pads\n");
|
||||
if (ret) {
|
||||
dev_err_probe(dev, ret, "Failed to init pads\n");
|
||||
goto err_free_ctrl;
|
||||
}
|
||||
|
||||
ret = v4l2_subdev_init_finalize(&priv->sd);
|
||||
if (ret) {
|
||||
|
@ -17,14 +17,12 @@
|
||||
#include <linux/log2.h>
|
||||
#include <linux/mod_devicetable.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_graph.h>
|
||||
#include <linux/pm.h>
|
||||
#include <linux/property.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/videodev2.h>
|
||||
|
||||
#include <media/i2c/mt9p031.h>
|
||||
#include <media/v4l2-async.h>
|
||||
#include <media/v4l2-ctrls.h>
|
||||
#include <media/v4l2-device.h>
|
||||
@ -113,18 +111,25 @@
|
||||
#define MT9P031_TEST_PATTERN_RED 0xa2
|
||||
#define MT9P031_TEST_PATTERN_BLUE 0xa3
|
||||
|
||||
struct mt9p031_model_info {
|
||||
u32 code;
|
||||
};
|
||||
|
||||
struct mt9p031 {
|
||||
struct v4l2_subdev subdev;
|
||||
struct media_pad pad;
|
||||
struct v4l2_rect crop; /* Sensor window */
|
||||
struct v4l2_mbus_framefmt format;
|
||||
struct mt9p031_platform_data *pdata;
|
||||
struct mutex power_lock; /* lock to protect power_count */
|
||||
int power_count;
|
||||
|
||||
struct clk *clk;
|
||||
struct regulator_bulk_data regulators[3];
|
||||
|
||||
unsigned int pixclk_pol:1;
|
||||
int ext_freq;
|
||||
int target_freq;
|
||||
|
||||
u32 code;
|
||||
struct aptina_pll pll;
|
||||
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 mt9p031_platform_data *pdata = mt9p031->pdata;
|
||||
unsigned long ext_freq;
|
||||
int ret;
|
||||
|
||||
@ -233,7 +237,7 @@ static int mt9p031_clk_setup(struct mt9p031 *mt9p031)
|
||||
if (IS_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)
|
||||
return ret;
|
||||
|
||||
@ -245,7 +249,7 @@ static int mt9p031_clk_setup(struct mt9p031 *mt9p031)
|
||||
if (ext_freq > limits.ext_clock_max) {
|
||||
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;
|
||||
|
||||
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.pix_clock = pdata->target_freq;
|
||||
mt9p031->pll.pix_clock = mt9p031->target_freq;
|
||||
mt9p031->use_pll = true;
|
||||
|
||||
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 */
|
||||
if (mt9p031->pdata && mt9p031->pdata->pixclk_pol) {
|
||||
if (mt9p031->pixclk_pol) {
|
||||
ret = mt9p031_write(client, MT9P031_PIXEL_CLOCK_CONTROL,
|
||||
MT9P031_PIXEL_CLOCK_INVERT);
|
||||
if (ret < 0)
|
||||
@ -1057,53 +1061,41 @@ static const struct v4l2_subdev_internal_ops mt9p031_subdev_internal_ops = {
|
||||
* Driver initialization and probing
|
||||
*/
|
||||
|
||||
static struct mt9p031_platform_data *
|
||||
mt9p031_get_pdata(struct i2c_client *client)
|
||||
static int mt9p031_parse_properties(struct mt9p031 *mt9p031, struct device *dev)
|
||||
{
|
||||
struct mt9p031_platform_data *pdata = NULL;
|
||||
struct device_node *np;
|
||||
struct v4l2_fwnode_endpoint endpoint = {
|
||||
.bus_type = V4L2_MBUS_PARALLEL
|
||||
};
|
||||
struct fwnode_handle *np;
|
||||
int ret;
|
||||
|
||||
if (!IS_ENABLED(CONFIG_OF) || !client->dev.of_node)
|
||||
return client->dev.platform_data;
|
||||
|
||||
np = of_graph_get_endpoint_by_regs(client->dev.of_node, 0, -1);
|
||||
np = fwnode_graph_get_next_endpoint(dev_fwnode(dev), NULL);
|
||||
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)
|
||||
goto done;
|
||||
ret = v4l2_fwnode_endpoint_parse(np, &endpoint);
|
||||
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);
|
||||
if (!pdata)
|
||||
goto done;
|
||||
fwnode_property_read_u32(np, "input-clock-frequency",
|
||||
&mt9p031->ext_freq);
|
||||
fwnode_property_read_u32(np, "pixel-clock-frequency",
|
||||
&mt9p031->target_freq);
|
||||
|
||||
of_property_read_u32(np, "input-clock-frequency", &pdata->ext_freq);
|
||||
of_property_read_u32(np, "pixel-clock-frequency", &pdata->target_freq);
|
||||
|
||||
pdata->pixclk_pol = !!(endpoint.bus.parallel.flags &
|
||||
mt9p031->pixclk_pol = !!(endpoint.bus.parallel.flags &
|
||||
V4L2_MBUS_PCLK_SAMPLE_RISING);
|
||||
|
||||
done:
|
||||
of_node_put(np);
|
||||
return pdata;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mt9p031_probe(struct i2c_client *client)
|
||||
{
|
||||
struct mt9p031_platform_data *pdata = mt9p031_get_pdata(client);
|
||||
struct i2c_adapter *adapter = client->adapter;
|
||||
struct mt9p031 *mt9p031;
|
||||
unsigned int i;
|
||||
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)) {
|
||||
dev_warn(&client->dev,
|
||||
"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)
|
||||
return -ENOMEM;
|
||||
|
||||
mt9p031->pdata = pdata;
|
||||
ret = mt9p031_parse_properties(mt9p031, &client->dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
mt9p031->output_control = MT9P031_OUTPUT_CONTROL_DEF;
|
||||
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[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_CID_VFLIP, 0, 1, 1, 0);
|
||||
v4l2_ctrl_new_std(&mt9p031->ctrls, &mt9p031_ctrl_ops,
|
||||
V4L2_CID_PIXEL_RATE, pdata->target_freq,
|
||||
pdata->target_freq, 1, pdata->target_freq);
|
||||
V4L2_CID_PIXEL_RATE, mt9p031->target_freq,
|
||||
mt9p031->target_freq, 1, mt9p031->target_freq);
|
||||
v4l2_ctrl_new_std_menu_items(&mt9p031->ctrls, &mt9p031_ctrl_ops,
|
||||
V4L2_CID_TEST_PATTERN,
|
||||
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);
|
||||
}
|
||||
|
||||
static const struct i2c_device_id mt9p031_id[] = {
|
||||
{ "mt9p006", 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_bayer = {
|
||||
.code = MEDIA_BUS_FMT_SGRBG12_1X12
|
||||
};
|
||||
|
||||
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[] = {
|
||||
{ .compatible = "aptina,mt9p006", .data = (void *)MEDIA_BUS_FMT_SGRBG12_1X12 },
|
||||
{ .compatible = "aptina,mt9p031", .data = (void *)MEDIA_BUS_FMT_SGRBG12_1X12 },
|
||||
{ .compatible = "aptina,mt9p031m", .data = (void *)MEDIA_BUS_FMT_Y12_1X12 },
|
||||
{ .compatible = "aptina,mt9p006", .data = &mt9p031_models_bayer },
|
||||
{ .compatible = "aptina,mt9p031", .data = &mt9p031_models_bayer },
|
||||
{ .compatible = "aptina,mt9p031m", .data = &mt9p031_models_mono },
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, mt9p031_of_match);
|
||||
@ -1236,7 +1231,6 @@ static struct i2c_driver mt9p031_i2c_driver = {
|
||||
},
|
||||
.probe = mt9p031_probe,
|
||||
.remove = mt9p031_remove,
|
||||
.id_table = mt9p031_id,
|
||||
};
|
||||
|
||||
module_i2c_driver(mt9p031_i2c_driver);
|
||||
|
@ -13,7 +13,6 @@
|
||||
|
||||
#include <media/v4l2-ctrls.h>
|
||||
#include <media/v4l2-device.h>
|
||||
#include <media/v4l2-event.h>
|
||||
#include <media/v4l2-fwnode.h>
|
||||
|
||||
#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 = {
|
||||
.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 = {
|
||||
@ -892,8 +889,7 @@ static int ov01a10_probe(struct i2c_client *client)
|
||||
}
|
||||
|
||||
ov01a10->sd.state_lock = ov01a10->ctrl_handler.lock;
|
||||
ov01a10->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE |
|
||||
V4L2_SUBDEV_FL_HAS_EVENTS;
|
||||
ov01a10->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
|
||||
ov01a10->sd.entity.ops = &ov01a10_subdev_entity_ops;
|
||||
ov01a10->sd.entity.function = MEDIA_ENT_F_CAM_SENSOR;
|
||||
ov01a10->pad.flags = MEDIA_PAD_FL_SOURCE;
|
||||
|
@ -3,10 +3,13 @@
|
||||
|
||||
#include <linux/unaligned.h>
|
||||
#include <linux/acpi.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
#include <media/v4l2-ctrls.h>
|
||||
#include <media/v4l2-device.h>
|
||||
#include <media/v4l2-fwnode.h>
|
||||
@ -1215,7 +1218,7 @@ static const char * const ov08x40_test_pattern_menu[] = {
|
||||
/* Configurations for supported link frequencies */
|
||||
#define OV08X40_LINK_FREQ_400MHZ 400000000ULL
|
||||
#define OV08X40_SCLK_96MHZ 96000000ULL
|
||||
#define OV08X40_EXT_CLK 19200000
|
||||
#define OV08X40_XVCLK 19200000
|
||||
#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 v4l2_subdev sd;
|
||||
struct media_pad pad;
|
||||
@ -1291,6 +1300,10 @@ struct ov08x40 {
|
||||
struct v4l2_ctrl *hblank;
|
||||
struct v4l2_ctrl *exposure;
|
||||
|
||||
struct clk *xvclk;
|
||||
struct gpio_desc *reset_gpio;
|
||||
struct regulator_bulk_data supplies[ARRAY_SIZE(ov08x40_supply_names)];
|
||||
|
||||
/* Current mode */
|
||||
const struct ov08x40_mode *cur_mode;
|
||||
|
||||
@ -1303,6 +1316,61 @@ struct ov08x40 {
|
||||
|
||||
#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 */
|
||||
static int ov08x40_read_reg(struct ov08x40 *ov08x,
|
||||
u16 reg, u32 len, u32 *val)
|
||||
@ -1339,15 +1407,13 @@ static int ov08x40_read_reg(struct ov08x40 *ov08x,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ov08x40_burst_fill_regs(struct ov08x40 *ov08x, u16 first_reg,
|
||||
u16 last_reg, u8 val)
|
||||
static int __ov08x40_burst_fill_regs(struct i2c_client *client, u16 first_reg,
|
||||
u16 last_reg, size_t num_regs, u8 val)
|
||||
{
|
||||
struct i2c_client *client = v4l2_get_subdevdata(&ov08x->sd);
|
||||
struct i2c_msg msgs;
|
||||
size_t i, num_regs;
|
||||
size_t i;
|
||||
int ret;
|
||||
|
||||
num_regs = last_reg - first_reg + 1;
|
||||
msgs.addr = client->addr;
|
||||
msgs.flags = 0;
|
||||
msgs.len = 2 + num_regs;
|
||||
@ -1373,6 +1439,31 @@ static int ov08x40_burst_fill_regs(struct ov08x40 *ov08x, u16 first_reg,
|
||||
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 */
|
||||
static int ov08x40_write_reg(struct ov08x40 *ov08x,
|
||||
u16 reg, u32 len, u32 __val)
|
||||
@ -2049,7 +2140,7 @@ static void ov08x40_free_controls(struct ov08x40 *ov08x)
|
||||
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 = {
|
||||
.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);
|
||||
unsigned int i, j;
|
||||
int ret;
|
||||
u32 ext_clk;
|
||||
u32 xvclk_rate;
|
||||
|
||||
if (!fwnode)
|
||||
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",
|
||||
&ext_clk);
|
||||
&xvclk_rate);
|
||||
if (ret) {
|
||||
dev_err(dev, "can't get clock frequency");
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
if (ext_clk != OV08X40_EXT_CLK) {
|
||||
if (xvclk_rate != OV08X40_XVCLK) {
|
||||
dev_err(dev, "external clock %d is not supported",
|
||||
ext_clk);
|
||||
xvclk_rate);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@ -2120,32 +2236,37 @@ out_err:
|
||||
}
|
||||
|
||||
static int ov08x40_probe(struct i2c_client *client)
|
||||
{
|
||||
struct ov08x40 *ov08x;
|
||||
{ struct ov08x40 *ov08x;
|
||||
int ret;
|
||||
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);
|
||||
if (!ov08x)
|
||||
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 */
|
||||
v4l2_i2c_subdev_init(&ov08x->sd, client, &ov08x40_subdev_ops);
|
||||
|
||||
full_power = acpi_dev_state_d0(&client->dev);
|
||||
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 */
|
||||
ret = ov08x40_identify_module(ov08x);
|
||||
if (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);
|
||||
if (ret)
|
||||
return ret;
|
||||
goto probe_power_off;
|
||||
|
||||
/* Initialize subdev */
|
||||
ov08x->sd.internal_ops = &ov08x40_internal_ops;
|
||||
@ -2187,6 +2308,9 @@ error_media_entity:
|
||||
error_handler_free:
|
||||
ov08x40_free_controls(ov08x);
|
||||
|
||||
probe_power_off:
|
||||
ov08x40_power_off(&client->dev);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -2201,6 +2325,8 @@ static void ov08x40_remove(struct i2c_client *client)
|
||||
|
||||
pm_runtime_disable(&client->dev);
|
||||
pm_runtime_set_suspended(&client->dev);
|
||||
|
||||
ov08x40_power_off(&client->dev);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_ACPI
|
||||
@ -2212,10 +2338,17 @@ static const struct acpi_device_id ov08x40_acpi_ids[] = {
|
||||
MODULE_DEVICE_TABLE(acpi, ov08x40_acpi_ids);
|
||||
#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 = {
|
||||
.driver = {
|
||||
.name = "ov08x40",
|
||||
.acpi_match_table = ACPI_PTR(ov08x40_acpi_ids),
|
||||
.of_match_table = ov08x40_of_match,
|
||||
},
|
||||
.probe = ov08x40_probe,
|
||||
.remove = ov08x40_remove,
|
||||
|
@ -530,7 +530,7 @@ struct ov2740 {
|
||||
/* Current mode */
|
||||
const struct ov2740_mode *cur_mode;
|
||||
|
||||
/* NVM data inforamtion */
|
||||
/* NVM data information */
|
||||
struct nvm_data *nvm;
|
||||
|
||||
/* Supported modes */
|
||||
@ -1132,7 +1132,8 @@ static int ov2740_check_hwcfg(struct device *dev)
|
||||
*/
|
||||
ep = fwnode_graph_get_next_endpoint(fwnode, NULL);
|
||||
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);
|
||||
if (ret) {
|
||||
@ -1330,7 +1331,7 @@ static int ov2740_probe(struct i2c_client *client)
|
||||
|
||||
ret = ov2740_check_hwcfg(dev);
|
||||
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);
|
||||
if (IS_ERR(ov2740->reset_gpio)) {
|
||||
|
@ -377,7 +377,7 @@ struct reg_value {
|
||||
struct ov5640_timings {
|
||||
/* Analog crop rectangle. */
|
||||
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;
|
||||
/* Total pixels per line: width + fixed hblank. */
|
||||
u32 htot;
|
||||
|
@ -88,7 +88,6 @@ struct ov5645 {
|
||||
struct v4l2_subdev sd;
|
||||
struct media_pad pad;
|
||||
struct v4l2_fwnode_endpoint ep;
|
||||
struct v4l2_mbus_framefmt fmt;
|
||||
struct v4l2_rect crop;
|
||||
struct clk *xclk;
|
||||
|
||||
@ -105,8 +104,6 @@ struct ov5645 {
|
||||
u8 timing_tc_reg20;
|
||||
u8 timing_tc_reg21;
|
||||
|
||||
struct mutex power_lock; /* lock to protect power state */
|
||||
|
||||
struct gpio_desc *enable_gpio;
|
||||
struct gpio_desc *rst_gpio;
|
||||
};
|
||||
@ -781,11 +778,8 @@ static int ov5645_s_ctrl(struct v4l2_ctrl *ctrl)
|
||||
struct ov5645, ctrls);
|
||||
int ret;
|
||||
|
||||
mutex_lock(&ov5645->power_lock);
|
||||
if (!pm_runtime_get_if_in_use(ov5645->dev)) {
|
||||
mutex_unlock(&ov5645->power_lock);
|
||||
if (!pm_runtime_get_if_in_use(ov5645->dev))
|
||||
return 0;
|
||||
}
|
||||
|
||||
switch (ctrl->id) {
|
||||
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_put_autosuspend(ov5645->dev);
|
||||
mutex_unlock(&ov5645->power_lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@ -855,49 +848,6 @@ static int ov5645_enum_frame_size(struct v4l2_subdev *subdev,
|
||||
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,
|
||||
struct v4l2_subdev_state *sd_state,
|
||||
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;
|
||||
int ret;
|
||||
|
||||
__crop = __ov5645_get_pad_crop(ov5645, sd_state, format->pad,
|
||||
format->which);
|
||||
|
||||
__crop = v4l2_subdev_state_get_crop(sd_state, 0);
|
||||
new_mode = v4l2_find_nearest_size(ov5645_mode_info_data,
|
||||
ARRAY_SIZE(ov5645_mode_info_data),
|
||||
width, height,
|
||||
format->format.width, format->format.height);
|
||||
width, height, format->format.width,
|
||||
format->format.height);
|
||||
|
||||
__crop->width = new_mode->width;
|
||||
__crop->height = new_mode->height;
|
||||
|
||||
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);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = v4l2_ctrl_s_ctrl(ov5645->link_freq,
|
||||
ret = __v4l2_ctrl_s_ctrl(ov5645->link_freq,
|
||||
new_mode->link_freq);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
@ -933,8 +881,7 @@ static int ov5645_set_format(struct v4l2_subdev *sd,
|
||||
ov5645->current_mode = new_mode;
|
||||
}
|
||||
|
||||
__format = __ov5645_get_pad_format(ov5645, sd_state, format->pad,
|
||||
format->which);
|
||||
__format = v4l2_subdev_state_get_format(sd_state, 0);
|
||||
__format->width = __crop->width;
|
||||
__format->height = __crop->height;
|
||||
__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,
|
||||
struct v4l2_subdev_state *sd_state)
|
||||
{
|
||||
struct v4l2_subdev_format fmt = { 0 };
|
||||
|
||||
fmt.which = sd_state ? V4L2_SUBDEV_FORMAT_TRY : V4L2_SUBDEV_FORMAT_ACTIVE;
|
||||
fmt.format.width = 1920;
|
||||
fmt.format.height = 1080;
|
||||
struct v4l2_subdev_format fmt = {
|
||||
.which = V4L2_SUBDEV_FORMAT_TRY,
|
||||
.pad = 0,
|
||||
.format = {
|
||||
.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);
|
||||
|
||||
@ -964,22 +915,20 @@ static int ov5645_get_selection(struct v4l2_subdev *sd,
|
||||
struct v4l2_subdev_state *sd_state,
|
||||
struct v4l2_subdev_selection *sel)
|
||||
{
|
||||
struct ov5645 *ov5645 = to_ov5645(sd);
|
||||
|
||||
if (sel->target != V4L2_SEL_TGT_CROP)
|
||||
return -EINVAL;
|
||||
|
||||
sel->r = *__ov5645_get_pad_crop(ov5645, sd_state, sel->pad,
|
||||
sel->which);
|
||||
sel->r = *v4l2_subdev_state_get_crop(sd_state, 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;
|
||||
|
||||
if (enable) {
|
||||
ret = pm_runtime_resume_and_get(ov5645->dev);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
@ -993,7 +942,7 @@ static int ov5645_s_stream(struct v4l2_subdev *subdev, int enable)
|
||||
ov5645->current_mode->height);
|
||||
goto err_rpm_put;
|
||||
}
|
||||
ret = v4l2_ctrl_handler_setup(&ov5645->ctrls);
|
||||
ret = __v4l2_ctrl_handler_setup(&ov5645->ctrls);
|
||||
if (ret < 0) {
|
||||
dev_err(ov5645->dev, "could not sync v4l2 controls\n");
|
||||
goto err_rpm_put;
|
||||
@ -1007,39 +956,47 @@ static int ov5645_s_stream(struct v4l2_subdev *subdev, int enable)
|
||||
OV5645_SYSTEM_CTRL0_START);
|
||||
if (ret < 0)
|
||||
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;
|
||||
|
||||
err_rpm_put:
|
||||
pm_runtime_put_sync(ov5645->dev);
|
||||
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_put_autosuspend(ov5645->dev);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
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 = {
|
||||
.enum_mbus_code = ov5645_enum_mbus_code,
|
||||
.enum_frame_size = ov5645_enum_frame_size,
|
||||
.get_fmt = ov5645_get_format,
|
||||
.get_fmt = v4l2_subdev_get_fmt,
|
||||
.set_fmt = ov5645_set_format,
|
||||
.get_selection = ov5645_get_selection,
|
||||
.enable_streams = ov5645_enable_streams,
|
||||
.disable_streams = ov5645_disable_streams,
|
||||
};
|
||||
|
||||
static const struct v4l2_subdev_ops ov5645_subdev_ops = {
|
||||
@ -1069,51 +1026,44 @@ static int ov5645_probe(struct i2c_client *client)
|
||||
ov5645->dev = dev;
|
||||
|
||||
endpoint = of_graph_get_endpoint_by_regs(dev->of_node, 0, -1);
|
||||
if (!endpoint) {
|
||||
dev_err(dev, "endpoint node not found\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
if (!endpoint)
|
||||
return dev_err_probe(dev, -EINVAL,
|
||||
"endpoint node not found\n");
|
||||
|
||||
ret = v4l2_fwnode_endpoint_parse(of_fwnode_handle(endpoint),
|
||||
&ov5645->ep);
|
||||
|
||||
of_node_put(endpoint);
|
||||
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "parsing endpoint node failed\n");
|
||||
return ret;
|
||||
}
|
||||
if (ret < 0)
|
||||
return dev_err_probe(dev, ret,
|
||||
"parsing endpoint node failed\n");
|
||||
|
||||
if (ov5645->ep.bus_type != V4L2_MBUS_CSI2_DPHY) {
|
||||
dev_err(dev, "invalid bus type, must be CSI2\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
if (ov5645->ep.bus_type != V4L2_MBUS_CSI2_DPHY)
|
||||
return dev_err_probe(dev, -EINVAL,
|
||||
"invalid bus type, must be CSI2\n");
|
||||
|
||||
/* get system clock (xclk) */
|
||||
ov5645->xclk = devm_clk_get(dev, NULL);
|
||||
if (IS_ERR(ov5645->xclk)) {
|
||||
dev_err(dev, "could not get xclk");
|
||||
return PTR_ERR(ov5645->xclk);
|
||||
}
|
||||
if (IS_ERR(ov5645->xclk))
|
||||
return dev_err_probe(dev, PTR_ERR(ov5645->xclk),
|
||||
"could not get xclk");
|
||||
|
||||
ret = of_property_read_u32(dev->of_node, "clock-frequency", &xclk_freq);
|
||||
if (ret) {
|
||||
dev_err(dev, "could not get xclk frequency\n");
|
||||
return ret;
|
||||
}
|
||||
if (ret)
|
||||
return dev_err_probe(dev, ret,
|
||||
"could not get xclk frequency\n");
|
||||
|
||||
/* external clock must be 24MHz, allow 1% tolerance */
|
||||
if (xclk_freq < 23760000 || xclk_freq > 24240000) {
|
||||
dev_err(dev, "external clock frequency %u is not supported\n",
|
||||
if (xclk_freq < 23760000 || xclk_freq > 24240000)
|
||||
return dev_err_probe(dev, -EINVAL,
|
||||
"unsupported xclk frequency %u\n",
|
||||
xclk_freq);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = clk_set_rate(ov5645->xclk, xclk_freq);
|
||||
if (ret) {
|
||||
dev_err(dev, "could not set xclk frequency\n");
|
||||
return ret;
|
||||
}
|
||||
if (ret)
|
||||
return dev_err_probe(dev, ret,
|
||||
"could not set xclk frequency\n");
|
||||
|
||||
for (i = 0; i < OV5645_NUM_SUPPLIES; i++)
|
||||
ov5645->supplies[i].supply = ov5645_supply_name[i];
|
||||
@ -1124,18 +1074,14 @@ static int ov5645_probe(struct i2c_client *client)
|
||||
return ret;
|
||||
|
||||
ov5645->enable_gpio = devm_gpiod_get(dev, "enable", GPIOD_OUT_HIGH);
|
||||
if (IS_ERR(ov5645->enable_gpio)) {
|
||||
dev_err(dev, "cannot get enable gpio\n");
|
||||
return PTR_ERR(ov5645->enable_gpio);
|
||||
}
|
||||
if (IS_ERR(ov5645->enable_gpio))
|
||||
return dev_err_probe(dev, PTR_ERR(ov5645->enable_gpio),
|
||||
"cannot get enable gpio\n");
|
||||
|
||||
ov5645->rst_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH);
|
||||
if (IS_ERR(ov5645->rst_gpio)) {
|
||||
dev_err(dev, "cannot get reset gpio\n");
|
||||
return PTR_ERR(ov5645->rst_gpio);
|
||||
}
|
||||
|
||||
mutex_init(&ov5645->power_lock);
|
||||
if (IS_ERR(ov5645->rst_gpio))
|
||||
return dev_err_probe(dev, PTR_ERR(ov5645->rst_gpio),
|
||||
"cannot get reset gpio\n");
|
||||
|
||||
v4l2_ctrl_handler_init(&ov5645->ctrls, 9);
|
||||
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;
|
||||
|
||||
if (ov5645->ctrls.error) {
|
||||
dev_err(dev, "%s: control initialization error %d\n",
|
||||
__func__, ov5645->ctrls.error);
|
||||
ret = ov5645->ctrls.error;
|
||||
dev_err_probe(dev, ret, "failed to add controls\n");
|
||||
goto free_ctrl;
|
||||
}
|
||||
|
||||
@ -1180,12 +1125,12 @@ static int ov5645_probe(struct i2c_client *client)
|
||||
ov5645->sd.internal_ops = &ov5645_internal_ops;
|
||||
ov5645->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
|
||||
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;
|
||||
|
||||
ret = media_entity_pads_init(&ov5645->sd.entity, 1, &ov5645->pad);
|
||||
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;
|
||||
}
|
||||
|
||||
@ -1195,14 +1140,14 @@ static int ov5645_probe(struct i2c_client *client)
|
||||
|
||||
ret = ov5645_read_reg(ov5645, OV5645_CHIP_ID_HIGH, &chip_id_high);
|
||||
if (ret < 0 || chip_id_high != OV5645_CHIP_ID_HIGH_BYTE) {
|
||||
dev_err(dev, "could not read ID high\n");
|
||||
ret = -ENODEV;
|
||||
dev_err_probe(dev, ret, "could not read ID high\n");
|
||||
goto power_down;
|
||||
}
|
||||
ret = ov5645_read_reg(ov5645, OV5645_CHIP_ID_LOW, &chip_id_low);
|
||||
if (ret < 0 || chip_id_low != OV5645_CHIP_ID_LOW_BYTE) {
|
||||
dev_err(dev, "could not read ID low\n");
|
||||
ret = -ENODEV;
|
||||
dev_err_probe(dev, ret, "could not read ID low\n");
|
||||
goto power_down;
|
||||
}
|
||||
|
||||
@ -1211,24 +1156,31 @@ static int ov5645_probe(struct i2c_client *client)
|
||||
ret = ov5645_read_reg(ov5645, OV5645_AEC_PK_MANUAL,
|
||||
&ov5645->aec_pk_manual);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "could not read AEC/AGC mode\n");
|
||||
ret = -ENODEV;
|
||||
dev_err_probe(dev, ret, "could not read AEC/AGC mode\n");
|
||||
goto power_down;
|
||||
}
|
||||
|
||||
ret = ov5645_read_reg(ov5645, OV5645_TIMING_TC_REG20,
|
||||
&ov5645->timing_tc_reg20);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "could not read vflip value\n");
|
||||
ret = -ENODEV;
|
||||
dev_err_probe(dev, ret, "could not read vflip value\n");
|
||||
goto power_down;
|
||||
}
|
||||
|
||||
ret = ov5645_read_reg(ov5645, OV5645_TIMING_TC_REG21,
|
||||
&ov5645->timing_tc_reg21);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "could not read hflip value\n");
|
||||
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;
|
||||
}
|
||||
|
||||
@ -1236,11 +1188,9 @@ static int ov5645_probe(struct i2c_client *client)
|
||||
pm_runtime_get_noresume(dev);
|
||||
pm_runtime_enable(dev);
|
||||
|
||||
ov5645_init_state(&ov5645->sd, NULL);
|
||||
|
||||
ret = v4l2_async_register_subdev(&ov5645->sd);
|
||||
ret = v4l2_async_register_subdev_sensor(&ov5645->sd);
|
||||
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;
|
||||
}
|
||||
|
||||
@ -1254,13 +1204,13 @@ static int ov5645_probe(struct i2c_client *client)
|
||||
err_pm_runtime:
|
||||
pm_runtime_disable(dev);
|
||||
pm_runtime_put_noidle(dev);
|
||||
v4l2_subdev_cleanup(&ov5645->sd);
|
||||
power_down:
|
||||
ov5645_set_power_off(dev);
|
||||
free_entity:
|
||||
media_entity_cleanup(&ov5645->sd.entity);
|
||||
free_ctrl:
|
||||
v4l2_ctrl_handler_free(&ov5645->ctrls);
|
||||
mutex_destroy(&ov5645->power_lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@ -1271,13 +1221,13 @@ static void ov5645_remove(struct i2c_client *client)
|
||||
struct ov5645 *ov5645 = to_ov5645(sd);
|
||||
|
||||
v4l2_async_unregister_subdev(&ov5645->sd);
|
||||
v4l2_subdev_cleanup(sd);
|
||||
media_entity_cleanup(&ov5645->sd.entity);
|
||||
v4l2_ctrl_handler_free(&ov5645->ctrls);
|
||||
pm_runtime_disable(ov5645->dev);
|
||||
if (!pm_runtime_status_suspended(ov5645->dev))
|
||||
ov5645_set_power_off(ov5645->dev);
|
||||
pm_runtime_set_suspended(ov5645->dev);
|
||||
mutex_destroy(&ov5645->power_lock);
|
||||
}
|
||||
|
||||
static const struct i2c_device_id ov5645_id[] = {
|
||||
|
@ -1879,7 +1879,7 @@ struct ov5670 {
|
||||
struct gpio_desc *pwdn_gpio; /* PWDNB pin. */
|
||||
struct gpio_desc *reset_gpio; /* XSHUTDOWN pin. */
|
||||
|
||||
/* To serialize asynchronus callbacks */
|
||||
/* To serialize asynchronous callbacks */
|
||||
struct mutex mutex;
|
||||
|
||||
/* True if the device has been identified */
|
||||
|
@ -510,7 +510,7 @@ struct ov5675 {
|
||||
/* Current mode */
|
||||
const struct ov5675_mode *cur_mode;
|
||||
|
||||
/* To serialize asynchronus callbacks */
|
||||
/* To serialize asynchronous callbacks */
|
||||
struct mutex mutex;
|
||||
|
||||
/* True if the device has been identified */
|
||||
@ -732,7 +732,7 @@ static int ov5675_set_ctrl(struct v4l2_ctrl *ctrl)
|
||||
case V4L2_CID_EXPOSURE:
|
||||
/* 4 least significant bits of expsoure are fractional part
|
||||
* 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
|
||||
* register value, the exposure should be divided by 2 before
|
||||
* set register, e.g. val << 3.
|
||||
|
@ -18,7 +18,6 @@
|
||||
#include <media/v4l2-cci.h>
|
||||
#include <media/v4l2-ctrls.h>
|
||||
#include <media/v4l2-device.h>
|
||||
#include <media/v4l2-event.h>
|
||||
#include <media/v4l2-fwnode.h>
|
||||
#include <media/v4l2-mediabus.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,
|
||||
};
|
||||
|
||||
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 = {
|
||||
.core = &ov64a40_core_ops,
|
||||
.video = &ov64a40_video_ops,
|
||||
.pad = &ov64a40_pad_ops,
|
||||
};
|
||||
@ -3605,8 +3598,7 @@ static int ov64a40_probe(struct i2c_client *client)
|
||||
|
||||
/* Initialize subdev */
|
||||
ov64a40->sd.internal_ops = &ov64a40_internal_ops;
|
||||
ov64a40->sd.flags = V4L2_SUBDEV_FL_HAS_DEVNODE
|
||||
| V4L2_SUBDEV_FL_HAS_EVENTS;
|
||||
ov64a40->sd.flags = V4L2_SUBDEV_FL_HAS_DEVNODE;
|
||||
ov64a40->sd.entity.function = MEDIA_ENT_F_CAM_SENSOR;
|
||||
|
||||
ov64a40->pad.flags = MEDIA_PAD_FL_SOURCE;
|
||||
|
@ -269,7 +269,7 @@
|
||||
#define AF_8x 0x08 /* Add frame when AGC reaches 8x gain */
|
||||
#define AF_16x 0x0c /* Add frame when AGC reaches 16x gain */
|
||||
/* 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 */
|
||||
/* CLKRC */
|
||||
/* Input clock divider register */
|
||||
|
@ -117,7 +117,7 @@ struct ov7740 {
|
||||
struct v4l2_ctrl *brightness;
|
||||
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 *pwdn_gpio;
|
||||
|
@ -1435,7 +1435,7 @@ struct ov8856 {
|
||||
/* Application specified mbus format */
|
||||
u32 cur_mbus_index;
|
||||
|
||||
/* To serialize asynchronus callbacks */
|
||||
/* To serialize asynchronous callbacks */
|
||||
struct mutex mutex;
|
||||
|
||||
/* lanes index */
|
||||
|
@ -24,7 +24,6 @@
|
||||
#include <media/v4l2-common.h>
|
||||
#include <media/v4l2-ctrls.h>
|
||||
#include <media/v4l2-device.h>
|
||||
#include <media/v4l2-event.h>
|
||||
#include <media/v4l2-fwnode.h>
|
||||
#include <media/v4l2-mediabus.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,
|
||||
};
|
||||
|
||||
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 = {
|
||||
.core = &ov8858_core_ops,
|
||||
.video = &ov8858_video_ops,
|
||||
.pad = &ov8858_pad_ops,
|
||||
};
|
||||
@ -1917,7 +1910,7 @@ static int ov8858_probe(struct i2c_client *client)
|
||||
return ret;
|
||||
|
||||
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;
|
||||
sd->entity.function = MEDIA_ENT_F_CAM_SENSOR;
|
||||
ret = media_entity_pads_init(&sd->entity, 1, &ov8858->pad);
|
||||
|
@ -286,7 +286,7 @@ static const struct i2c_rv ov965x_init_regs[] = {
|
||||
{ REG_COM5, 0x00 }, /* System clock options */
|
||||
{ REG_COM2, 0x01 }, /* Output drive, soft sleep mode */
|
||||
{ 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_COM17, 0x08 }, /* Single frame out, banding filter */
|
||||
{ 0x16, 0x06 },
|
||||
|
@ -335,7 +335,7 @@ struct ov9734 {
|
||||
/* Current mode */
|
||||
const struct ov9734_mode *cur_mode;
|
||||
|
||||
/* To serialize asynchronus callbacks */
|
||||
/* To serialize asynchronous callbacks */
|
||||
struct mutex mutex;
|
||||
};
|
||||
|
||||
|
@ -14,6 +14,7 @@
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <linux/of_graph.h>
|
||||
#include <linux/regulator/consumer.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_UYVY8_1X16, MEDIA_BUS_FMT_VYUY8_1X16,
|
||||
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
|
||||
};
|
||||
|
||||
@ -100,6 +98,7 @@ struct mipid02_dev {
|
||||
/* remote source */
|
||||
struct v4l2_async_notifier notifier;
|
||||
struct v4l2_subdev *s_subdev;
|
||||
u16 s_subdev_pad_id;
|
||||
/* registers */
|
||||
struct {
|
||||
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_VYUY8_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;
|
||||
case MEDIA_BUS_FMT_BGR888_1X24:
|
||||
return 24;
|
||||
@ -175,16 +168,10 @@ static u8 data_type_from_code(__u32 code)
|
||||
case MEDIA_BUS_FMT_YVYU8_1X16:
|
||||
case MEDIA_BUS_FMT_UYVY8_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;
|
||||
case MEDIA_BUS_FMT_BGR888_1X24:
|
||||
return MIPI_CSI2_DT_RGB888;
|
||||
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;
|
||||
default:
|
||||
return 0;
|
||||
@ -248,8 +235,10 @@ static void mipid02_apply_reset(struct mipid02_dev *bridge)
|
||||
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;
|
||||
int ret;
|
||||
|
||||
@ -282,10 +271,15 @@ xclk_off:
|
||||
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);
|
||||
clk_disable_unprepare(bridge->xclk);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mipid02_detect(struct mipid02_dev *bridge)
|
||||
@ -447,15 +441,19 @@ static int mipid02_configure_from_code(struct mipid02_dev *bridge,
|
||||
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;
|
||||
int ret = -EINVAL;
|
||||
|
||||
if (!bridge->s_subdev)
|
||||
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)
|
||||
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);
|
||||
if (ret)
|
||||
goto error;
|
||||
|
||||
pm_runtime_mark_last_busy(&client->dev);
|
||||
pm_runtime_put_autosuspend(&client->dev);
|
||||
|
||||
error:
|
||||
if (ret)
|
||||
dev_err(&client->dev, "failed to stream off %d", ret);
|
||||
@ -472,33 +474,36 @@ error:
|
||||
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 v4l2_subdev_state *state;
|
||||
struct v4l2_mbus_framefmt *fmt;
|
||||
int ret = -EINVAL;
|
||||
|
||||
if (!bridge->s_subdev)
|
||||
goto error;
|
||||
return ret;
|
||||
|
||||
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);
|
||||
|
||||
/* build registers content */
|
||||
ret = mipid02_configure_from_rx(bridge, fmt);
|
||||
if (ret)
|
||||
goto error;
|
||||
return ret;
|
||||
ret = mipid02_configure_from_tx(bridge);
|
||||
if (ret)
|
||||
goto error;
|
||||
return ret;
|
||||
ret = mipid02_configure_from_code(bridge, fmt);
|
||||
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 */
|
||||
cci_write(bridge->regmap, MIPID02_CLK_LANE_REG1,
|
||||
@ -524,33 +529,20 @@ static int mipid02_stream_enable(struct mipid02_dev *bridge)
|
||||
if (ret)
|
||||
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)
|
||||
goto error;
|
||||
|
||||
return 0;
|
||||
|
||||
error:
|
||||
dev_err(&client->dev, "failed to stream on %d", ret);
|
||||
mipid02_stream_disable(bridge);
|
||||
|
||||
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);
|
||||
cci_write(bridge->regmap, MIPID02_CLK_LANE_REG1, 0, &ret);
|
||||
cci_write(bridge->regmap, MIPID02_DATA_LANE0_REG1, 0, &ret);
|
||||
cci_write(bridge->regmap, MIPID02_DATA_LANE1_REG1, 0, &ret);
|
||||
|
||||
pm_runtime_mark_last_busy(&client->dev);
|
||||
pm_runtime_put_autosuspend(&client->dev);
|
||||
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 = {
|
||||
.s_stream = mipid02_s_stream,
|
||||
.s_stream = v4l2_subdev_s_stream_helper,
|
||||
};
|
||||
|
||||
static const struct v4l2_subdev_pad_ops mipid02_pad_ops = {
|
||||
.enum_mbus_code = mipid02_enum_mbus_code,
|
||||
.get_fmt = v4l2_subdev_get_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 = {
|
||||
@ -692,6 +686,7 @@ static int mipid02_async_bound(struct v4l2_async_notifier *notifier,
|
||||
}
|
||||
|
||||
bridge->s_subdev = s_subdev;
|
||||
bridge->s_subdev_pad_id = source_pad;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -875,7 +870,7 @@ static int mipid02_probe(struct i2c_client *client)
|
||||
}
|
||||
|
||||
/* enable clock, power and reset device if available */
|
||||
ret = mipid02_set_power_on(bridge);
|
||||
ret = mipid02_set_power_on(&client->dev);
|
||||
if (ret)
|
||||
goto entity_cleanup;
|
||||
|
||||
@ -897,6 +892,15 @@ static int mipid02_probe(struct i2c_client *client)
|
||||
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);
|
||||
if (ret < 0) {
|
||||
dev_err(&client->dev, "v4l2_async_register_subdev failed %d",
|
||||
@ -911,8 +915,10 @@ static int mipid02_probe(struct i2c_client *client)
|
||||
unregister_notifier:
|
||||
v4l2_async_nf_unregister(&bridge->notifier);
|
||||
v4l2_async_nf_cleanup(&bridge->notifier);
|
||||
pm_runtime_disable(&client->dev);
|
||||
pm_runtime_set_suspended(&client->dev);
|
||||
power_off:
|
||||
mipid02_set_power_off(bridge);
|
||||
mipid02_set_power_off(&client->dev);
|
||||
entity_cleanup:
|
||||
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_cleanup(&bridge->notifier);
|
||||
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);
|
||||
}
|
||||
|
||||
@ -937,10 +947,15 @@ static const struct of_device_id 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 = {
|
||||
.driver = {
|
||||
.name = "st-mipid02",
|
||||
.of_match_table = mipid02_dt_ids,
|
||||
.pm = pm_ptr(&mipid02_pm_ops),
|
||||
},
|
||||
.probe = mipid02_probe,
|
||||
.remove = mipid02_remove,
|
||||
|
@ -87,6 +87,10 @@ struct tc358743_state {
|
||||
struct timer_list timer;
|
||||
struct work_struct work_i2c_poll;
|
||||
|
||||
/* debugfs */
|
||||
struct dentry *debugfs_dir;
|
||||
struct v4l2_debugfs_if *infoframes;
|
||||
|
||||
/* edid */
|
||||
u8 edid_blocks_written;
|
||||
|
||||
@ -430,12 +434,35 @@ static void tc358743_erase_bksv(struct v4l2_subdev *sd)
|
||||
|
||||
/* --------------- 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)
|
||||
{
|
||||
struct i2c_client *client = v4l2_get_subdevdata(sd);
|
||||
struct device *dev = &client->dev;
|
||||
union hdmi_infoframe frame;
|
||||
u8 buffer[HDMI_INFOFRAME_SIZE(AVI)];
|
||||
u8 buffer[HDMI_INFOFRAME_SIZE(AVI)] = {};
|
||||
|
||||
if (!is_hdmi(sd)) {
|
||||
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)
|
||||
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,
|
||||
client->addr << 1, client->adapter->name);
|
||||
|
||||
@ -2168,8 +2200,10 @@ static int tc358743_probe(struct i2c_client *client)
|
||||
|
||||
err_work_queues:
|
||||
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);
|
||||
}
|
||||
cancel_delayed_work(&state->delayed_work_enable_hotplug);
|
||||
mutex_destroy(&state->confctl_mutex);
|
||||
err_hdl:
|
||||
@ -2188,6 +2222,8 @@ static void tc358743_remove(struct i2c_client *client)
|
||||
flush_work(&state->work_i2c_poll);
|
||||
}
|
||||
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);
|
||||
v4l2_async_unregister_subdev(sd);
|
||||
v4l2_device_unregister_subdev(sd);
|
||||
|
@ -27,7 +27,6 @@
|
||||
#include <media/v4l2-cci.h>
|
||||
#include <media/v4l2-ctrls.h>
|
||||
#include <media/v4l2-device.h>
|
||||
#include <media/v4l2-event.h>
|
||||
#include <media/v4l2-fwnode.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 = {
|
||||
.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 = {
|
||||
@ -2127,7 +2124,7 @@ static int thp7312_probe(struct i2c_client *client)
|
||||
|
||||
v4l2_i2c_subdev_init(&thp7312->sd, client, &thp7312_subdev_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->sd.entity.function = MEDIA_ENT_F_CAM_SENSOR;
|
||||
|
||||
|
@ -7,7 +7,7 @@
|
||||
* Author: Chaithrika U S <chaithrika@ti.com>
|
||||
*
|
||||
* Contributors:
|
||||
* Hans Verkuil <hans.verkuil@cisco.com>
|
||||
* Hans Verkuil <hansverk@cisco.com>
|
||||
* Lad, Prabhakar <prabhakar.lad@ti.com>
|
||||
* Martin Bugge <marbugge@cisco.com>
|
||||
*
|
||||
|
@ -1617,7 +1617,7 @@ static int vgxy61_detect(struct vgxy61_dev *sensor)
|
||||
|
||||
ret = cci_read(sensor->regmap, VGXY61_REG_NVM, &st, NULL);
|
||||
if (ret < 0)
|
||||
return st;
|
||||
return ret;
|
||||
if (st != VGXY61_NVM_OK)
|
||||
dev_warn(&client->dev, "Bad nvm state got %u\n", (u8)st);
|
||||
|
||||
|
@ -566,8 +566,6 @@ static const struct vb2_ops video_i2c_video_qops = {
|
||||
.buf_queue = buffer_queue,
|
||||
.start_streaming = start_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,
|
||||
@ -798,13 +796,13 @@ static int video_i2c_probe(struct i2c_client *client)
|
||||
queue->min_queued_buffers = 1;
|
||||
queue->ops = &video_i2c_video_qops;
|
||||
queue->mem_ops = &vb2_vmalloc_memops;
|
||||
queue->lock = &data->queue_lock;
|
||||
|
||||
ret = vb2_queue_init(queue);
|
||||
if (ret < 0)
|
||||
goto error_unregister_device;
|
||||
|
||||
data->vdev.queue = queue;
|
||||
data->vdev.queue->lock = &data->queue_lock;
|
||||
|
||||
snprintf(data->vdev.name, sizeof(data->vdev.name),
|
||||
"I2C %d-%d Transport Video",
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user