media updates for v5.16-rc1

-----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCAAdFiEE+QmuaPwR3wnBdVwACF8+vY7k4RUFAmF/qI0ACgkQCF8+vY7k
 4RWt1A//QSrYq6cxSzdEB+Jr6sZ4ToD2Lhp+Iq4vBMjeWljmIXLmsez7JHqTw2us
 sYocQS4tHUht6Y3T+ZV7dM2KWzKZfv18qKz1h2u36QuEfGN8y3PYGcBF4MQMmVpw
 gznqZb8bWS2onIDKSwn5BW7VRmc/HwRk0k9lXwJ7RuN7UX6zkAWhMUlEA7MiztfF
 DeTQ7KTWqc6v3xzYZ8BHBSOm+GPxvG7oiZv839cFfkNWsgz2ETJYBUvBQdgoWvbC
 uE5P+0/U+VoksRCuKzItltJQKaUsrXPDKODtA/UvWFr8NfTN7SAa8EsWbzC/cgBo
 8caHuhz++aYCfKZ6+rpwZ9oRY0BTnVXI52K0qC+NtsybU4pIDueZqwcYfo6bZr46
 XQXoFELOV6wkC7dHZ0+pFC3Lrqm5qXM3tmtITHOk8Xp1aPAzvTMMj4+mL3CawnXZ
 YH+ViKfadGdQ7gQb6ybbxwl1bvhGdSd1Pg8twYwO8yo3UHl2KI1iPKg7s9sDJupg
 npUUFNacyuv1+cSgEy4xqtiO+j6eoRBjYoj/Nv2D8tF8mJ3IZsf2JS+aIVqEAvg0
 d7M1IEFdvsPxgwnFMoOInr3mOZf2om6gTXVY71y01S1EbSfOqv/UG9mVZS1VMhJK
 Z3oigVDsujYJbGRWRomQTNhNxlsgpvGf3dTYSViLAH05CgtEIY0=
 =eLup
 -----END PGP SIGNATURE-----

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

Pull media updates from Mauro Carvalho Chehab:

 - New driver for SK Hynix Hi-846 8M pixel camera

 - New driver for the ov13b10 camera

 - New driver for Renesas R-Car ISP

 - mtk-vcodec gained support for version 2 of decoder firmware ABI

 - The legacy sir_ir driver got removed

 - videobuf2: the vb2_mem_ops kAPI had some improvements

 - lots of cleanups, fixes and new features at device drivers

* tag 'media/v5.16-1' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media: (328 commits)
  media: venus: core: Add sdm660 DT compatible and resource struct
  media: dt-bindings: media: venus: Add sdm660 dt schema
  media: venus: vdec: decoded picture buffer handling during reconfig sequence
  media: venus: Handle fatal errors during encoding and decoding
  media: venus: helpers: Add helper to mark fatal vb2 error
  media: venus: hfi: Check for sys error on session hfi functions
  media: venus: Make sys_error flag an atomic bitops
  media: venus: venc: Use pmruntime autosuspend
  media: allegro: write vui parameters for HEVC
  media: allegro: nal-hevc: implement generator for vui
  media: allegro: write correct colorspace into SPS
  media: allegro: extract nal value lookup functions to header
  media: allegro: correctly scale the bit rate in SPS
  media: allegro: remove external QP table
  media: allegro: fix row and column in response message
  media: allegro: add control to disable encoder buffer
  media: allegro: add encoder buffer support
  media: allegro: add pm_runtime support
  media: allegro: lookup VCU settings
  media: allegro: fix module removal if initialization failed
  ...
This commit is contained in:
Linus Torvalds 2021-11-01 18:45:08 -07:00
commit 73d21a3579
341 changed files with 14168 additions and 4815 deletions

View File

@ -100,6 +100,7 @@ Douglas Gilbert <dougg@torque.net>
Ed L. Cashin <ecashin@coraid.com> Ed L. Cashin <ecashin@coraid.com>
Erik Kaneda <erik.kaneda@intel.com> <erik.schmauss@intel.com> Erik Kaneda <erik.kaneda@intel.com> <erik.schmauss@intel.com>
Evgeniy Polyakov <johnpol@2ka.mipt.ru> Evgeniy Polyakov <johnpol@2ka.mipt.ru>
Ezequiel Garcia <ezequiel@vanguardiasur.com.ar> <ezequiel@collabora.com>
Felipe W Damasio <felipewd@terra.com.br> Felipe W Damasio <felipewd@terra.com.br>
Felix Kuhling <fxkuehl@gmx.de> Felix Kuhling <fxkuehl@gmx.de>
Felix Moeller <felix@derklecks.de> Felix Moeller <felix@derklecks.de>

View File

@ -58,15 +58,20 @@ Camera sensor devices
============ ========================================================== ============ ==========================================================
Driver Name Driver Name
============ ========================================================== ============ ==========================================================
ccs MIPI CCS compliant camera sensors (also SMIA++ and SMIA)
et8ek8 ET8EK8 camera sensor et8ek8 ET8EK8 camera sensor
hi556 Hynix Hi-556 sensor hi556 Hynix Hi-556 sensor
hi846 Hynix Hi-846 sensor
imx208 Sony IMX208 sensor
imx214 Sony IMX214 sensor imx214 Sony IMX214 sensor
imx219 Sony IMX219 sensor imx219 Sony IMX219 sensor
imx258 Sony IMX258 sensor imx258 Sony IMX258 sensor
imx274 Sony IMX274 sensor imx274 Sony IMX274 sensor
imx290 Sony IMX290 sensor imx290 Sony IMX290 sensor
imx319 Sony IMX319 sensor imx319 Sony IMX319 sensor
imx334 Sony IMX334 sensor
imx355 Sony IMX355 sensor imx355 Sony IMX355 sensor
imx412 Sony IMX412 sensor
m5mols Fujitsu M-5MOLS 8MP sensor m5mols Fujitsu M-5MOLS 8MP sensor
mt9m001 mt9m001 mt9m001 mt9m001
mt9m032 MT9M032 camera sensor mt9m032 MT9M032 camera sensor
@ -79,6 +84,7 @@ mt9v032 Micron MT9V032 sensor
mt9v111 Aptina MT9V111 sensor mt9v111 Aptina MT9V111 sensor
noon010pc30 Siliconfile NOON010PC30 sensor noon010pc30 Siliconfile NOON010PC30 sensor
ov13858 OmniVision OV13858 sensor ov13858 OmniVision OV13858 sensor
ov13b10 OmniVision OV13B10 sensor
ov2640 OmniVision OV2640 sensor ov2640 OmniVision OV2640 sensor
ov2659 OmniVision OV2659 sensor ov2659 OmniVision OV2659 sensor
ov2680 OmniVision OV2680 sensor ov2680 OmniVision OV2680 sensor
@ -104,7 +110,6 @@ s5k4ecgx Samsung S5K4ECGX sensor
s5k5baf Samsung S5K5BAF sensor s5k5baf Samsung S5K5BAF sensor
s5k6a3 Samsung S5K6A3 sensor s5k6a3 Samsung S5K6A3 sensor
s5k6aa Samsung S5K6AAFX sensor s5k6aa Samsung S5K6AAFX sensor
smiapp SMIA++/SMIA sensor
sr030pc30 Siliconfile SR030PC30 sensor sr030pc30 Siliconfile SR030PC30 sensor
vs6624 ST VS6624 sensor vs6624 ST VS6624 sensor
============ ========================================================== ============ ==========================================================
@ -138,6 +143,7 @@ Driver Name
ad5820 AD5820 lens voice coil ad5820 AD5820 lens voice coil
ak7375 AK7375 lens voice coil ak7375 AK7375 lens voice coil
dw9714 DW9714 lens voice coil dw9714 DW9714 lens voice coil
dw9768 DW9768 lens voice coil
dw9807-vcm DW9807 lens voice coil dw9807-vcm DW9807 lens voice coil
============ ========================================================== ============ ==========================================================

View File

@ -155,6 +155,66 @@ the resolutions supported by the sensor.
[fmt:SBGGR10_1X10/800x600@1/30 field:none colorspace:srgb] [fmt:SBGGR10_1X10/800x600@1/30 field:none colorspace:srgb]
-> "imx7-mipi-csis.0":0 [ENABLED] -> "imx7-mipi-csis.0":0 [ENABLED]
i.MX6ULL-EVK with OV5640
------------------------
On this platform a parallel OV5640 sensor is connected to the CSI port.
The following example configures a video capture pipeline with an output
of 640x480 and UYVY8_2X8 format:
.. code-block:: none
# Setup links
media-ctl -l "'ov5640 1-003c':0 -> 'csi':0[1]"
media-ctl -l "'csi':1 -> 'csi capture':0[1]"
# Configure pads for pipeline
media-ctl -v -V "'ov5640 1-003c':0 [fmt:UYVY8_2X8/640x480 field:none]"
After this streaming can start:
.. code-block:: none
gst-launch-1.0 -v v4l2src device=/dev/video1 ! video/x-raw,format=UYVY,width=640,height=480 ! v4l2convert ! fbdevsink
.. code-block:: none
# media-ctl -p
Media controller API version 5.14.0
Media device information
------------------------
driver imx7-csi
model imx-media
serial
bus info
hw revision 0x0
driver version 5.14.0
Device topology
- entity 1: csi (2 pads, 2 links)
type V4L2 subdev subtype Unknown flags 0
device node name /dev/v4l-subdev0
pad0: Sink
[fmt:UYVY8_2X8/640x480 field:none colorspace:srgb xfer:srgb ycbcr:601 quantization:full-range]
<- "ov5640 1-003c":0 [ENABLED,IMMUTABLE]
pad1: Source
[fmt:UYVY8_2X8/640x480 field:none colorspace:srgb xfer:srgb ycbcr:601 quantization:full-range]
-> "csi capture":0 [ENABLED,IMMUTABLE]
- entity 4: csi capture (1 pad, 1 link)
type Node subtype V4L flags 0
device node name /dev/video1
pad0: Sink
<- "csi":1 [ENABLED,IMMUTABLE]
- entity 10: ov5640 1-003c (1 pad, 1 link)
type V4L2 subdev subtype Sensor flags 0
device node name /dev/v4l-subdev1
pad0: Source
[fmt:UYVY8_2X8/640x480@1/30 field:none colorspace:srgb xfer:srgb ycbcr:601 quantization:full-range]
-> "csi":0 [ENABLED,IMMUTABLE]
References References
---------- ----------

View File

@ -51,10 +51,11 @@ to userspace as a V4L2 sub-device node and has two pads:
.. tabularcolumns:: |p{0.8cm}|p{4.0cm}|p{4.0cm}| .. tabularcolumns:: |p{0.8cm}|p{4.0cm}|p{4.0cm}|
.. flat-table:: .. flat-table::
:header-rows: 1
* - pad * - Pad
- direction - Direction
- purpose - Purpose
* - 0 * - 0
- sink - sink
@ -148,10 +149,11 @@ Each pipe has two sink pads and three source pads for the following purpose:
.. tabularcolumns:: |p{0.8cm}|p{4.0cm}|p{4.0cm}| .. tabularcolumns:: |p{0.8cm}|p{4.0cm}|p{4.0cm}|
.. flat-table:: .. flat-table::
:header-rows: 1
* - pad * - Pad
- direction - Direction
- purpose - Purpose
* - 0 * - 0
- sink - sink

View File

@ -159,7 +159,7 @@ whatever). Otherwise the device numbers can get confusing. The ivtv
Read-only Read-only
The raw YUV video output from the current video input. The YUV format The raw YUV video output from the current video input. The YUV format
is non-standard (V4L2_PIX_FMT_HM12). is a 16x16 linear tiled NV12 format (V4L2_PIX_FMT_NV12_16L16)
Note that the YUV and PCM streams are not synchronized, so they are of Note that the YUV and PCM streams are not synchronized, so they are of
limited use. limited use.

View File

@ -61,9 +61,10 @@ vimc-debayer:
* 1 Pad source * 1 Pad source
vimc-scaler: vimc-scaler:
Scale up the image by a factor of 3. E.g.: a 640x480 image becomes a Re-size the image to meet the source pad resolution. E.g.: if the sync
1920x1440 image. (this value can be configured, see at pad is configured to 360x480 and the source to 1280x720, the image will
`Module options`_). be stretched to fit the source resolution. Works for any resolution
within the vimc limitations (even shrinking the image if necessary).
Exposes: Exposes:
* 1 Pad sink * 1 Pad sink
@ -75,16 +76,3 @@ vimc-capture:
* 1 Pad sink * 1 Pad sink
* 1 Pad source * 1 Pad source
Module options
--------------
Vimc has a module parameter to configure the driver.
* ``sca_mult=<unsigned int>``
Image size multiplier factor to be used to multiply both width and
height, so the image size will be ``sca_mult^2`` bigger than the
original one. Currently, only supports scaling up (the default value
is 3).

View File

@ -4,23 +4,24 @@
$id: http://devicetree.org/schemas/media/i2c/adv7604.yaml# $id: http://devicetree.org/schemas/media/i2c/adv7604.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml# $schema: http://devicetree.org/meta-schemas/core.yaml#
title: Analog Devices ADV7604/11/12 video decoder with HDMI receiver title: Analog Devices ADV7604/10/11/12 video decoder with HDMI receiver
maintainers: maintainers:
- Hans Verkuil <hverkuil-cisco@xs4all.nl> - Hans Verkuil <hverkuil-cisco@xs4all.nl>
description: description:
The ADV7604 and ADV7611/12 are multiformat video decoders with an integrated The ADV7604 and ADV7610/11/12 are multiformat video decoders with
HDMI receiver. The ADV7604 has four multiplexed HDMI inputs and one analog an integrated HDMI receiver. The ADV7604 has four multiplexed HDMI inputs
input, and the ADV7611 has one HDMI input and no analog input. The 7612 is and one analog input, and the ADV7610/11 have one HDMI input and no analog
similar to the 7611 but has 2 HDMI inputs. input. The ADV7612 is similar to the ADV7610/11 but has 2 HDMI inputs.
These device tree bindings support the ADV7611/12 only at the moment. These device tree bindings support the ADV7610/11/12 only at the moment.
properties: properties:
compatible: compatible:
items: items:
- enum: - enum:
- adi,adv7610
- adi,adv7611 - adi,adv7611
- adi,adv7612 - adi,adv7612

View File

@ -0,0 +1,108 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/media/i2c/aptina,mt9p031.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Aptina 1/2.5-Inch 5Mp CMOS Digital Image Sensor
maintainers:
- Laurent Pinchart <laurent.pinchart@ideasonboard.com>
description: |
The Aptina MT9P031 is a 1/2.5-inch CMOS active pixel digital image sensor
with an active array size of 2592H x 1944V. It is programmable through a
simple two-wire serial interface.
properties:
compatible:
enum:
- aptina,mt9p031
- aptina,mt9p031m
reg:
description: I2C device address
maxItems: 1
clocks:
maxItems: 1
vdd-supply:
description: Digital supply voltage, 1.8 V
vdd_io-supply:
description: I/O supply voltage, 1.8 or 2.8 V
vaa-supply:
description: Analog supply voltage, 2.8 V
reset-gpios:
maxItems: 1
description: Chip reset GPIO
port:
$ref: /schemas/graph.yaml#/$defs/port-base
additionalProperties: false
properties:
endpoint:
$ref: /schemas/media/video-interfaces.yaml#
unevaluatedProperties: false
properties:
input-clock-frequency:
$ref: /schemas/types.yaml#/definitions/uint32
minimum: 6000000
maximum: 96000000
description: Input clock frequency
pixel-clock-frequency:
$ref: /schemas/types.yaml#/definitions/uint32
maximum: 96000000
description: Target pixel clock frequency
pclk-sample:
default: 0
required:
- input-clock-frequency
- pixel-clock-frequency
required:
- compatible
- reg
- clocks
- vdd-supply
- vdd_io-supply
- vaa-supply
- port
additionalProperties: false
examples:
- |
i2c0 {
#address-cells = <1>;
#size-cells = <0>;
mt9p031@5d {
compatible = "aptina,mt9p031";
reg = <0x5d>;
reset-gpios = <&gpio_sensor 0 0>;
clocks = <&sensor_clk>;
vdd-supply = <&reg_vdd>;
vdd_io-supply = <&reg_vdd_io>;
vaa-supply = <&reg_vaa>;
port {
mt9p031_1: endpoint {
input-clock-frequency = <6000000>;
pixel-clock-frequency = <96000000>;
};
};
};
};
...

View File

@ -0,0 +1,120 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/media/i2c/hynix,hi846.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: SK Hynix Hi-846 1/4" 8M Pixel MIPI CSI-2 sensor
maintainers:
- Martin Kepplinger <martin.kepplinger@puri.sm>
description: |-
The Hi-846 is a raw image sensor with an MIPI CSI-2 image data
interface and CCI (I2C compatible) control bus. The output format
is raw Bayer.
properties:
compatible:
const: hynix,hi846
reg:
maxItems: 1
clocks:
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
shutdown-gpios:
description: Reference to the GPIO connected to the XSHUTDOWN pin. Active low.
maxItems: 1
vddio-supply:
description: Definition of the regulator used for the VDDIO power supply.
vdda-supply:
description: Definition of the regulator used for the VDDA power supply.
vddd-supply:
description: Definition of the regulator used for the VDDD power supply.
port:
$ref: /schemas/graph.yaml#/properties/port
properties:
endpoint:
$ref: /schemas/media/video-interfaces.yaml#
unevaluatedProperties: false
properties:
data-lanes:
oneOf:
- items:
- const: 1
- const: 2
- const: 3
- const: 4
- items:
- const: 1
- const: 2
required:
- data-lanes
required:
- compatible
- reg
- clocks
- assigned-clocks
- assigned-clock-rates
- vddio-supply
- vdda-supply
- vddd-supply
- port
additionalProperties: false
examples:
- |
#include <dt-bindings/gpio/gpio.h>
i2c {
#address-cells = <1>;
#size-cells = <0>;
hi846: camera@20 {
compatible = "hynix,hi846";
reg = <0x20>;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_csi1>;
clocks = <&clk 0>;
assigned-clocks = <&clk 0>;
assigned-clock-rates = <25000000>;
vdda-supply = <&reg_camera_vdda>;
vddd-supply = <&reg_camera_vddd>;
vddio-supply = <&reg_camera_vddio>;
reset-gpios = <&gpio1 25 GPIO_ACTIVE_LOW>;
shutdown-gpios = <&gpio5 4 GPIO_ACTIVE_LOW>;
port {
camera_out: endpoint {
remote-endpoint = <&csi1_ep1>;
link-frequencies = /bits/ 64
<80000000 200000000>;
data-lanes = <1 2>;
};
};
};
};
...

View File

@ -1,40 +0,0 @@
* Aptina 1/2.5-Inch 5Mp CMOS Digital Image Sensor
The Aptina MT9P031 is a 1/2.5-inch CMOS active pixel digital image sensor with
an active array size of 2592H x 1944V. It is programmable through a simple
two-wire serial interface.
Required Properties:
- compatible: value should be either one among the following
(a) "aptina,mt9p031" for mt9p031 sensor
(b) "aptina,mt9p031m" for mt9p031m sensor
- input-clock-frequency: Input clock frequency.
- pixel-clock-frequency: Pixel clock frequency.
Optional Properties:
- reset-gpios: Chip reset GPIO
For further reading on port node refer to
Documentation/devicetree/bindings/media/video-interfaces.txt.
Example:
i2c0@1c22000 {
...
...
mt9p031@5d {
compatible = "aptina,mt9p031";
reg = <0x5d>;
reset-gpios = <&gpio3 30 0>;
port {
mt9p031_1: endpoint {
input-clock-frequency = <6000000>;
pixel-clock-frequency = <96000000>;
};
};
};
...
};

View File

@ -10,6 +10,8 @@ Required properties:
"mediatek,mt8183-vcodec-enc" for MT8183 encoder. "mediatek,mt8183-vcodec-enc" for MT8183 encoder.
"mediatek,mt8173-vcodec-dec" for MT8173 decoder. "mediatek,mt8173-vcodec-dec" for MT8173 decoder.
"mediatek,mt8192-vcodec-enc" for MT8192 encoder. "mediatek,mt8192-vcodec-enc" for MT8192 encoder.
"mediatek,mt8183-vcodec-dec" for MT8183 decoder.
"mediatek,mt8195-vcodec-enc" for MT8195 encoder.
- reg : Physical base address of the video codec registers and length of - reg : Physical base address of the video codec registers and length of
memory mapped region. memory mapped region.
- interrupts : interrupt number to the cpu. - interrupts : interrupt number to the cpu.

View File

@ -0,0 +1,162 @@
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
%YAML 1.2
---
$id: "http://devicetree.org/schemas/media/qcom,sc7280-venus.yaml#"
$schema: "http://devicetree.org/meta-schemas/core.yaml#"
title: Qualcomm Venus video encode and decode accelerators
maintainers:
- Stanimir Varbanov <stanimir.varbanov@linaro.org>
description: |
The Venus Iris2 IP is a video encode and decode accelerator present
on Qualcomm platforms
properties:
compatible:
const: qcom,sc7280-venus
reg:
maxItems: 1
interrupts:
maxItems: 1
power-domains:
minItems: 2
maxItems: 3
power-domain-names:
minItems: 2
maxItems: 3
items:
- const: venus
- const: vcodec0
- const: cx
clocks:
maxItems: 5
clock-names:
items:
- const: core
- const: bus
- const: iface
- const: vcodec_core
- const: vcodec_bus
iommus:
maxItems: 2
memory-region:
maxItems: 1
interconnects:
maxItems: 2
interconnect-names:
items:
- const: cpu-cfg
- const: video-mem
video-decoder:
type: object
properties:
compatible:
const: venus-decoder
required:
- compatible
additionalProperties: false
video-encoder:
type: object
properties:
compatible:
const: venus-encoder
required:
- compatible
additionalProperties: false
video-firmware:
type: object
description: |
Firmware subnode is needed when the platform does not
have TrustZone.
properties:
iommus:
maxItems: 1
required:
- iommus
required:
- compatible
- reg
- interrupts
- power-domains
- power-domain-names
- clocks
- clock-names
- iommus
- memory-region
- video-decoder
- video-encoder
additionalProperties: false
examples:
- |
#include <dt-bindings/interrupt-controller/arm-gic.h>
#include <dt-bindings/clock/qcom,videocc-sc7280.h>
#include <dt-bindings/interconnect/qcom,sc7280.h>
#include <dt-bindings/power/qcom-rpmpd.h>
venus: video-codec@aa00000 {
compatible = "qcom,sc7280-venus";
reg = <0x0aa00000 0xd0600>;
interrupts = <GIC_SPI 174 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&videocc VIDEO_CC_MVSC_CORE_CLK>,
<&videocc VIDEO_CC_MVSC_CTL_AXI_CLK>,
<&videocc VIDEO_CC_VENUS_AHB_CLK>,
<&videocc VIDEO_CC_MVS0_CORE_CLK>,
<&videocc VIDEO_CC_MVS0_AXI_CLK>;
clock-names = "core", "bus", "iface",
"vcodec_core", "vcodec_bus";
power-domains = <&videocc MVSC_GDSC>,
<&videocc MVS0_GDSC>,
<&rpmhpd SC7280_CX>;
power-domain-names = "venus", "vcodec0", "cx";
interconnects = <&gem_noc MASTER_APPSS_PROC 0 &cnoc2 SLAVE_VENUS_CFG 0>,
<&mmss_noc MASTER_VIDEO_P0 0 &mc_virt SLAVE_EBI1 0>;
interconnect-names = "cpu-cfg", "video-mem";
iommus = <&apps_smmu 0x2180 0x20>,
<&apps_smmu 0x2184 0x20>;
memory-region = <&video_mem>;
video-decoder {
compatible = "venus-decoder";
};
video-encoder {
compatible = "venus-encoder";
};
video-firmware {
iommus = <&apps_smmu 0x21a2 0x0>;
};
};

View File

@ -0,0 +1,186 @@
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
%YAML 1.2
---
$id: "http://devicetree.org/schemas/media/qcom,sdm660-venus.yaml#"
$schema: "http://devicetree.org/meta-schemas/core.yaml#"
title: Qualcomm Venus video encode and decode accelerators
maintainers:
- Stanimir Varbanov <stanimir.varbanov@linaro.org>
- AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
description: |
The Venus IP is a video encode and decode accelerator present
on Qualcomm platforms
properties:
compatible:
const: qcom,sdm660-venus
reg:
maxItems: 1
clocks:
maxItems: 4
clock-names:
items:
- const: core
- const: iface
- const: bus
- const: bus_throttle
interconnects:
maxItems: 2
interconnect-names:
items:
- const: cpu-cfg
- const: video-mem
interrupts:
maxItems: 1
iommus:
maxItems: 20
memory-region:
maxItems: 1
power-domains:
maxItems: 1
video-decoder:
type: object
properties:
compatible:
const: venus-decoder
clocks:
maxItems: 1
clock-names:
items:
- const: vcodec0_core
power-domains:
maxItems: 1
required:
- compatible
- clocks
- clock-names
- power-domains
additionalProperties: false
video-encoder:
type: object
properties:
compatible:
const: venus-encoder
clocks:
maxItems: 1
clock-names:
items:
- const: vcodec0_core
power-domains:
maxItems: 1
required:
- compatible
- clocks
- clock-names
- power-domains
additionalProperties: false
video-firmware:
type: object
description: |
Firmware subnode is needed when the platform does not
have TrustZone.
properties:
iommus:
maxItems: 1
required:
- iommus
required:
- compatible
- reg
- clocks
- clock-names
- interrupts
- iommus
- memory-region
- power-domains
- video-decoder
- video-encoder
additionalProperties: false
examples:
- |
#include <dt-bindings/clock/qcom,mmcc-sdm660.h>
#include <dt-bindings/interrupt-controller/arm-gic.h>
video-codec@cc00000 {
compatible = "qcom,sdm660-venus";
reg = <0x0cc00000 0xff000>;
clocks = <&mmcc VIDEO_CORE_CLK>,
<&mmcc VIDEO_AHB_CLK>,
<&mmcc VIDEO_AXI_CLK>,
<&mmcc THROTTLE_VIDEO_AXI_CLK>;
clock-names = "core", "iface", "bus", "bus_throttle";
interconnects = <&gnoc 0 &mnoc 13>,
<&mnoc 4 &bimc 5>;
interconnect-names = "cpu-cfg", "video-mem";
interrupts = <GIC_SPI 287 IRQ_TYPE_LEVEL_HIGH>;
iommus = <&mmss_smmu 0x400>,
<&mmss_smmu 0x401>,
<&mmss_smmu 0x40a>,
<&mmss_smmu 0x407>,
<&mmss_smmu 0x40e>,
<&mmss_smmu 0x40f>,
<&mmss_smmu 0x408>,
<&mmss_smmu 0x409>,
<&mmss_smmu 0x40b>,
<&mmss_smmu 0x40c>,
<&mmss_smmu 0x40d>,
<&mmss_smmu 0x410>,
<&mmss_smmu 0x421>,
<&mmss_smmu 0x428>,
<&mmss_smmu 0x429>,
<&mmss_smmu 0x42b>,
<&mmss_smmu 0x42c>,
<&mmss_smmu 0x42d>,
<&mmss_smmu 0x411>,
<&mmss_smmu 0x431>;
memory-region = <&venus_region>;
power-domains = <&mmcc VENUS_GDSC>;
video-decoder {
compatible = "venus-decoder";
clocks = <&mmcc VIDEO_SUBCORE0_CLK>;
clock-names = "vcodec0_core";
power-domains = <&mmcc VENUS_CORE0_GDSC>;
};
video-encoder {
compatible = "venus-encoder";
clocks = <&mmcc VIDEO_SUBCORE0_CLK>;
clock-names = "vcodec0_core";
power-domains = <&mmcc VENUS_CORE0_GDSC>;
};
};

View File

@ -30,6 +30,7 @@ properties:
- renesas,r8a77970-csi2 # R-Car V3M - renesas,r8a77970-csi2 # R-Car V3M
- renesas,r8a77980-csi2 # R-Car V3H - renesas,r8a77980-csi2 # R-Car V3H
- renesas,r8a77990-csi2 # R-Car E3 - renesas,r8a77990-csi2 # R-Car E3
- renesas,r8a779a0-csi2 # R-Car V3U
reg: reg:
maxItems: 1 maxItems: 1

View File

@ -1,31 +0,0 @@
Renesas R-Car Image Renderer (Distortion Correction Engine)
-----------------------------------------------------------
The image renderer, or the distortion correction engine, is a drawing processor
with a simple instruction system capable of referencing video capture data or
data in an external memory as 2D texture data and performing texture mapping
and drawing with respect to any shape that is split into triangular objects.
Required properties:
- compatible: "renesas,<soctype>-imr-lx4", "renesas,imr-lx4" as a fallback for
the image renderer light extended 4 (IMR-LX4) found in the R-Car gen3 SoCs,
where the examples with <soctype> are:
- "renesas,r8a7795-imr-lx4" for R-Car H3,
- "renesas,r8a7796-imr-lx4" for R-Car M3-W.
- reg: offset and length of the register block;
- interrupts: single interrupt specifier;
- clocks: single clock phandle/specifier pair;
- power-domains: power domain phandle/specifier pair;
- resets: reset phandle/specifier pair.
Example:
imr-lx4@fe860000 {
compatible = "renesas,r8a7795-imr-lx4", "renesas,imr-lx4";
reg = <0 0xfe860000 0 0x2000>;
interrupts = <GIC_SPI 192 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&cpg CPG_MOD 823>;
power-domains = <&sysc R8A7795_PD_A3VC>;
resets = <&cpg 823>;
};

View File

@ -0,0 +1,67 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/media/renesas,imr.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Renesas R-Car Image Renderer (Distortion Correction Engine)
maintainers:
- Sergei Shtylyov <sergei.shtylyov@gmail.com>
description: |
The image renderer, or the distortion correction engine, is a drawing
processor with a simple instruction system capable of referencing video
capture data or data in an external memory as 2D texture data and performing
texture mapping and drawing with respect to any shape that is split into
triangular objects.
The image renderer light extended 4 (IMR-LX4) is found in R-Car Gen3 SoCs.
properties:
compatible:
items:
- enum:
- renesas,r8a7795-imr-lx4 # R-Car H3
- renesas,r8a7796-imr-lx4 # R-Car M3-W
- const: renesas,imr-lx4 # R-Car Gen3
reg:
maxItems: 1
interrupts:
maxItems: 1
clocks:
maxItems: 1
power-domains:
maxItems: 1
resets:
maxItems: 1
required:
- compatible
- reg
- interrupts
- clocks
- power-domains
- resets
additionalProperties: false
examples:
- |
#include <dt-bindings/clock/r8a7795-cpg-mssr.h>
#include <dt-bindings/interrupt-controller/arm-gic.h>
#include <dt-bindings/power/r8a7795-sysc.h>
imr-lx4@fe860000 {
compatible = "renesas,r8a7795-imr-lx4", "renesas,imr-lx4";
reg = <0xfe860000 0x2000>;
interrupts = <GIC_SPI 192 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&cpg CPG_MOD 823>;
power-domains = <&sysc R8A7795_PD_A3VC>;
resets = <&cpg 823>;
};

View File

@ -15,13 +15,22 @@ description: |
properties: properties:
compatible: compatible:
const: rockchip,rk3399-cif-isp enum:
- rockchip,px30-cif-isp
- rockchip,rk3399-cif-isp
reg: reg:
maxItems: 1 maxItems: 1
interrupts: interrupts:
maxItems: 1 minItems: 1
maxItems: 3
interrupt-names:
items:
- const: isp
- const: mi
- const: mipi
clocks: clocks:
minItems: 3 minItems: 3
@ -41,7 +50,7 @@ properties:
- const: aclk - const: aclk
- const: hclk - const: hclk
# only for isp1 # only for isp1
- const: pclk_isp - const: pclk
iommus: iommus:
maxItems: 1 maxItems: 1
@ -90,19 +99,29 @@ required:
- power-domains - power-domains
- ports - ports
if: allOf:
properties: - if:
compatible: properties:
contains: compatible:
const: rockchip,rk3399-cif-isp contains:
then: const: rockchip,rk3399-cif-isp
properties: then:
clocks: properties:
minItems: 3 clocks:
maxItems: 4 minItems: 3
clock-names: maxItems: 4
minItems: 3 clock-names:
maxItems: 4 minItems: 3
maxItems: 4
- if:
properties:
compatible:
contains:
const: rockchip,px30-cif-isp
then:
required:
- interrupt-names
additionalProperties: false additionalProperties: false
@ -183,3 +202,66 @@ examples:
}; };
}; };
}; };
- |
#include <dt-bindings/interrupt-controller/arm-gic.h>
#include <dt-bindings/power/px30-power.h>
parent1: parent {
#address-cells = <2>;
#size-cells = <2>;
isp: isp@ff4a0000 {
compatible = "rockchip,px30-cif-isp";
reg = <0x0 0xff4a0000 0x0 0x8000>;
interrupts = <GIC_SPI 70 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 73 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 74 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "isp", "mi", "mipi";
clocks = <&cru SCLK_ISP0>,
<&cru ACLK_ISP0_WRAPPER>,
<&cru HCLK_ISP0_WRAPPER>,
<&cru PCLK_ISP1_WRAPPER>;
clock-names = "isp", "aclk", "hclk", "pclk";
iommus = <&isp_mmu>;
phys = <&csi_dphy>;
phy-names = "dphy";
power-domains = <&power PX30_PD_VI>;
ports {
#address-cells = <1>;
#size-cells = <0>;
port@0 {
reg = <0>;
#address-cells = <1>;
#size-cells = <0>;
mipi_in_ucam1: endpoint@0 {
reg = <0>;
remote-endpoint = <&ucam1_out>;
data-lanes = <1 2>;
};
};
};
};
i2c2: i2c {
#address-cells = <1>;
#size-cells = <0>;
ov5695: camera@36 {
compatible = "ovti,ov5647";
reg = <0x36>;
clocks = <&cru SCLK_CIF_OUT>;
port {
ucam1_out: endpoint {
remote-endpoint = <&mipi_in_ucam1>;
data-lanes = <1 2>;
};
};
};
};
};

View File

@ -509,6 +509,8 @@ patternProperties:
description: Hycon Technology Corp. description: Hycon Technology Corp.
"^hydis,.*": "^hydis,.*":
description: Hydis Technologies description: Hydis Technologies
"^hynix,.*":
description: SK Hynix Inc.
"^hyundai,.*": "^hyundai,.*":
description: Hyundai Technology description: Hyundai Technology
"^i2se,.*": "^i2se,.*":

View File

@ -0,0 +1,43 @@
.. SPDX-License-Identifier: GPL-2.0
The Rockchip Image Signal Processor Driver (rkisp1)
===================================================
Versions and their differences
------------------------------
The rkisp1 block underwent some changes between SoC implementations.
The vendor designates them as:
- V10: used at least in rk3288 and rk3399
- V11: declared in the original vendor code, but not used
- V12: used at least in rk3326 and px30
- V13: used at least in rk1808
- V20: used in rk3568 and beyond
Right now the kernel supports rkisp1 implementations based
on V10 and V12 variants. V11 does not seem to be actually used
and V13 will need some more additions but isn't researched yet,
especially as it seems to be limited to the rk1808 which hasn't
reached much market spread.
V20 on the other hand will probably be used in future SoCs and
has seen really big changes in the vendor kernel, so will need
quite a bit of research.
Changes from V10 to V12
-----------------------
- V12 supports a new CSI-host implementation but can still
also use the same implementation from V10
- The module for lens shading correction got changed
from 12bit to 13bit width
- The AWB and AEC modules got replaced to support finer
grained data collection
Changes from V12 to V13
-----------------------
The list for V13 is incomplete and needs further investigation.
- V13 does not support the old CSI-host implementation anymore

View File

@ -71,7 +71,7 @@ media maintainers do the review.
The media maintainers that work on specific areas of the subsystem are: The media maintainers that work on specific areas of the subsystem are:
- Digital TV and remote controllers: - Remote Controllers (infrared):
Sean Young <sean@mess.org> Sean Young <sean@mess.org>
- HDMI CEC: - HDMI CEC:

View File

@ -191,21 +191,21 @@ registered this way are stored in a global list of subdevices, ready to be
picked up by bridge drivers. picked up by bridge drivers.
Bridge drivers in turn have to register a notifier object. This is Bridge drivers in turn have to register a notifier object. This is
performed using the :c:func:`v4l2_async_notifier_register` call. To performed using the :c:func:`v4l2_async_nf_register` call. To
unregister the notifier the driver has to call unregister the notifier the driver has to call
:c:func:`v4l2_async_notifier_unregister`. The former of the two functions :c:func:`v4l2_async_nf_unregister`. The former of the two functions
takes two arguments: a pointer to struct :c:type:`v4l2_device` and a takes two arguments: a pointer to struct :c:type:`v4l2_device` and a
pointer to struct :c:type:`v4l2_async_notifier`. pointer to struct :c:type:`v4l2_async_notifier`.
Before registering the notifier, bridge drivers must do two things: first, the Before registering the notifier, bridge drivers must do two things: first, the
notifier must be initialized using the :c:func:`v4l2_async_notifier_init`. notifier must be initialized using the :c:func:`v4l2_async_nf_init`.
Second, bridge drivers can then begin to form a list of subdevice descriptors Second, bridge drivers can then begin to form a list of subdevice descriptors
that the bridge device needs for its operation. Several functions are available that the bridge device needs for its operation. Several functions are available
to add subdevice descriptors to a notifier, depending on the type of device and to add subdevice descriptors to a notifier, depending on the type of device and
the needs of the driver. the needs of the driver.
:c:func:`v4l2_async_notifier_add_fwnode_remote_subdev` and :c:func:`v4l2_async_nf_add_fwnode_remote` and
:c:func:`v4l2_async_notifier_add_i2c_subdev` are for bridge and ISP drivers for :c:func:`v4l2_async_nf_add_i2c` are for bridge and ISP drivers for
registering their async sub-devices with the notifier. registering their async sub-devices with the notifier.
:c:func:`v4l2_async_register_subdev_sensor` is a helper function for :c:func:`v4l2_async_register_subdev_sensor` is a helper function for
@ -230,8 +230,8 @@ These functions allocate an async sub-device descriptor which is of type struct
... ...
my_asd = v4l2_async_notifier_add_fwnode_remote_subdev(&notifier, ep, my_asd = v4l2_async_nf_add_fwnode_remote(&notifier, ep,
struct my_async_subdev); struct my_async_subdev);
fwnode_handle_put(ep); fwnode_handle_put(ep);
if (IS_ERR(asd)) if (IS_ERR(asd))

View File

@ -7,9 +7,7 @@ Non-compressed file format
-------------------------- --------------------------
The cx23416 can produce (and the cx23415 can also read) raw YUV output. The The cx23416 can produce (and the cx23415 can also read) raw YUV output. The
format of a YUV frame is specific to this chip and is called HM12. 'HM' stands format of a YUV frame is 16x16 linear tiled NV12 (V4L2_PIX_FMT_NV12_16L16).
for 'Hauppauge Macroblock', which is a misnomer as 'Conexant Macroblock' would
be more accurate.
The format is YUV 4:2:0 which uses 1 Y byte per pixel and 1 U and V byte per The format is YUV 4:2:0 which uses 1 Y byte per pixel and 1 U and V byte per
four pixels. four pixels.
@ -34,8 +32,8 @@ second line of 8 UV pairs of the top-left block, etc. After transmitting
this block the first line of the block on the right to the first block is this block the first line of the block on the right to the first block is
transmitted, etc. transmitted, etc.
The code below is given as an example on how to convert HM12 to separate The code below is given as an example on how to convert V4L2_PIX_FMT_NV12_16L16
Y, U and V planes. This code assumes frames of 720x576 (PAL) pixels. to separate Y, U and V planes. This code assumes frames of 720x576 (PAL) pixels.
The width of a frame is always 720 pixels, regardless of the actual specified The width of a frame is always 720 pixels, regardless of the actual specified
width. width.

View File

@ -676,8 +676,6 @@ Buffer Flags
\normalsize \normalsize
.. _memory-flags:
enum v4l2_memory enum v4l2_memory
================ ================
@ -701,6 +699,44 @@ enum v4l2_memory
- 4 - 4
- The buffer is used for :ref:`DMA shared buffer <dmabuf>` I/O. - The buffer is used for :ref:`DMA shared buffer <dmabuf>` I/O.
.. _memory-flags:
Memory Consistency Flags
------------------------
.. raw:: latex
\small
.. tabularcolumns:: |p{7.0cm}|p{2.1cm}|p{8.4cm}|
.. cssclass:: longtable
.. flat-table::
:header-rows: 0
:stub-columns: 0
:widths: 3 1 4
* .. _`V4L2-MEMORY-FLAG-NON-COHERENT`:
- ``V4L2_MEMORY_FLAG_NON_COHERENT``
- 0x00000001
- A buffer is allocated either in coherent (it will be automatically
coherent between the CPU and the bus) or non-coherent memory. The
latter can provide performance gains, for instance the CPU cache
sync/flush operations can be avoided if the buffer is accessed by the
corresponding device only and the CPU does not read/write to/from that
buffer. However, this requires extra care from the driver -- it must
guarantee memory consistency by issuing a cache flush/sync when
consistency is needed. If this flag is set V4L2 will attempt to
allocate the buffer in non-coherent memory. The flag takes effect
only if the buffer is used for :ref:`memory mapping <mmap>` I/O and the
queue reports the :ref:`V4L2_BUF_CAP_SUPPORTS_MMAP_CACHE_HINTS
<V4L2-BUF-CAP-SUPPORTS-MMAP-CACHE-HINTS>` capability.
.. raw:: latex
\normalsize
Timecodes Timecodes
========= =========

View File

@ -3088,6 +3088,63 @@ enum v4l2_mpeg_video_hevc_size_of_length_field -
\normalsize \normalsize
``V4L2_CID_MPEG_VIDEO_HEVC_SCALING_MATRIX (struct)``
Specifies the HEVC scaling matrix parameters used for the scaling process
for transform coefficients.
These matrix and parameters are defined according to :ref:`hevc`.
They are described in section 7.4.5 "Scaling list data semantics" of
the specification.
.. c:type:: v4l2_ctrl_hevc_scaling_matrix
.. raw:: latex
\scriptsize
.. tabularcolumns:: |p{5.4cm}|p{6.8cm}|p{5.1cm}|
.. cssclass:: longtable
.. flat-table:: struct v4l2_ctrl_hevc_scaling_matrix
:header-rows: 0
:stub-columns: 0
:widths: 1 1 2
* - __u8
- ``scaling_list_4x4[6][16]``
- Scaling list is used for the scaling process for transform
coefficients. The values on each scaling list are expected
in raster scan order.
* - __u8
- ``scaling_list_8x8[6][64]``
- Scaling list is used for the scaling process for transform
coefficients. The values on each scaling list are expected
in raster scan order.
* - __u8
- ``scaling_list_16x16[6][64]``
- Scaling list is used for the scaling process for transform
coefficients. The values on each scaling list are expected
in raster scan order.
* - __u8
- ``scaling_list_32x32[2][64]``
- Scaling list is used for the scaling process for transform
coefficients. The values on each scaling list are expected
in raster scan order.
* - __u8
- ``scaling_list_dc_coef_16x16[6]``
- Scaling list is used for the scaling process for transform
coefficients. The values on each scaling list are expected
in raster scan order.
* - __u8
- ``scaling_list_dc_coef_32x32[2]``
- Scaling list is used for the scaling process for transform
coefficients. The values on each scaling list are expected
in raster scan order.
.. raw:: latex
\normalsize
.. c:type:: v4l2_hevc_dpb_entry .. c:type:: v4l2_hevc_dpb_entry
.. raw:: latex .. raw:: latex

View File

@ -72,3 +72,23 @@ Image Source Control IDs
* - __u32 * - __u32
- ``height`` - ``height``
- Height of the area. - Height of the area.
``V4L2_CID_NOTIFY_GAINS (integer array)``
The sensor is notified what gains will be applied to the different
colour channels by subsequent processing (such as by an ISP). The
sensor is merely informed of these values in case it performs
processing that requires them, but it does not apply them itself to
the output pixels.
Currently it is defined only for Bayer sensors, and is an array
control taking 4 gain values, being the gains for each of the
Bayer channels. The gains are always in the order B, Gb, Gr and R,
irrespective of the exact Bayer order of the sensor itself.
The use of an array allows this control to be extended to sensors
with, for example, non-Bayer CFAs (colour filter arrays).
The units for the gain values are linear, with the default value
representing a gain of exactly 1.0. For example, if this default value
is reported as being (say) 128, then a value of 192 would represent
a gain of exactly 1.5.

View File

@ -48,14 +48,6 @@ please make a proposal on the linux-media mailing list.
- ``V4L2_PIX_FMT_HI240`` - ``V4L2_PIX_FMT_HI240``
- 'HI24' - 'HI24'
- 8 bit RGB format used by the BTTV driver. - 8 bit RGB format used by the BTTV driver.
* .. _V4L2-PIX-FMT-HM12:
- ``V4L2_PIX_FMT_HM12``
- 'HM12'
- YUV 4:2:0 format used by the IVTV driver.
The format is documented in the kernel sources in the file
``Documentation/userspace-api/media/drivers/cx2341x-uapi.rst``
* .. _V4L2-PIX-FMT-CPIA1: * .. _V4L2-PIX-FMT-CPIA1:
- ``V4L2_PIX_FMT_CPIA1`` - ``V4L2_PIX_FMT_CPIA1``
@ -246,20 +238,13 @@ please make a proposal on the linux-media mailing list.
It is an opaque intermediate format and the MDP hardware must be It is an opaque intermediate format and the MDP hardware must be
used to convert ``V4L2_PIX_FMT_MT21C`` to ``V4L2_PIX_FMT_NV12M``, used to convert ``V4L2_PIX_FMT_MT21C`` to ``V4L2_PIX_FMT_NV12M``,
``V4L2_PIX_FMT_YUV420M`` or ``V4L2_PIX_FMT_YVU420``. ``V4L2_PIX_FMT_YUV420M`` or ``V4L2_PIX_FMT_YVU420``.
* .. _V4L2-PIX-FMT-SUNXI-TILED-NV12: * .. _V4L2-PIX-FMT-MM21:
- ``V4L2_PIX_FMT_SUNXI_TILED_NV12`` - ``V4L2_PIX_FMT_MM21``
- 'ST12' - 'MM21'
- Two-planar NV12-based format used by the video engine found on Allwinner - Non-compressed, tiled two-planar format used by Mediatek MT8183.
(codenamed sunxi) platforms, with 32x32 tiles for the luminance plane This is an opaque intermediate format and the MDP3 hardware can be
and 32x64 tiles for the chrominance plane. The data in each tile is used to convert it to other formats.
stored in linear order, within the tile bounds. Each tile follows the
previous one linearly in memory (from left to right, top to bottom).
The associated buffer dimensions are aligned to match an integer number
of tiles, resulting in 32-aligned resolutions for the luminance plane
and 16-aligned resolutions for the chrominance plane (with 2x2
subsampling).
.. raw:: latex .. raw:: latex

View File

@ -99,7 +99,7 @@ All components are stored with the same number of bits per component.
- 4:2:0 - 4:2:0
- Cb, Cr - Cb, Cr
- No - No
- 64x32 macroblocks - 64x32 tiles
Horizontal Z order Horizontal Z order
* - V4L2_PIX_FMT_NV12MT_16X16 * - V4L2_PIX_FMT_NV12MT_16X16
@ -108,7 +108,7 @@ All components are stored with the same number of bits per component.
- 4:2:2 - 4:2:2
- Cb, Cr - Cb, Cr
- No - No
- 16x16 macroblocks - 16x16 tiles
* - V4L2_PIX_FMT_NV16 * - V4L2_PIX_FMT_NV16
- 'NV16' - 'NV16'
- 8 - 8
@ -254,27 +254,47 @@ of the luma plane.
.. _V4L2-PIX-FMT-NV12MT: .. _V4L2-PIX-FMT-NV12MT:
.. _V4L2-PIX-FMT-NV12MT-16X16: .. _V4L2-PIX-FMT-NV12MT-16X16:
.. _V4L2-PIX-FMT-NV12-4L4:
.. _V4L2-PIX-FMT-NV12-16L16:
.. _V4L2-PIX-FMT-NV12-32L32:
NV12MT and MV12MT_16X16 Tiled NV12
----------------------- ----------
Semi-planar YUV 4:2:0 formats, using macroblock tiling. The chroma plane is Semi-planar YUV 4:2:0 formats, using macroblock tiling. The chroma plane is
subsampled by 2 in each direction. Chroma lines contain half the number of subsampled by 2 in each direction. Chroma lines contain half the number of
pixels and the same number of bytes as luma lines, and the chroma plane pixels and the same number of bytes as luma lines, and the chroma plane
contains half the number of lines of the luma plane. contains half the number of lines of the luma plane. Each tile follows the
previous one linearly in memory (from left to right, top to bottom).
``V4L2_PIX_FMT_NV12MT_16X16`` stores pixel in 2D 16x16 macroblocks, and stores ``V4L2_PIX_FMT_NV12MT_16X16`` is similar to ``V4L2_PIX_FMT_NV12M`` but stores
macroblocks linearly in memory. The line stride and image height must be pixels in 2D 16x16 tiles, and stores tiles linearly in memory.
The line stride and image height must be aligned to a multiple of 16.
The layouts of the luma and chroma planes are identical.
``V4L2_PIX_FMT_NV12MT`` is similar to ``V4L2_PIX_FMT_NV12M`` but stores
pixels in 2D 64x32 tiles, and stores 2x2 groups of tiles in
Z-order in memory, alternating Z and mirrored Z shapes horizontally.
The line stride must be a multiple of 128 pixels to ensure an
integer number of Z shapes. The image height must be a multiple of 32 pixels.
If the vertical resolution is an odd number of tiles, the last row of
tiles is stored in linear order. The layouts of the luma and chroma
planes are identical.
``V4L2_PIX_FMT_NV12_4L4`` stores pixel in 4x4 tiles, and stores
tiles linearly in memory. The line stride and image height must be
aligned to a multiple of 4. The layouts of the luma and chroma planes are
identical.
``V4L2_PIX_FMT_NV12_16L16`` stores pixel in 16x16 tiles, and stores
tiles linearly in memory. The line stride and image height must be
aligned to a multiple of 16. The layouts of the luma and chroma planes are aligned to a multiple of 16. The layouts of the luma and chroma planes are
identical. identical.
``V4L2_PIX_FMT_NV12MT`` stores pixels in 2D 64x32 macroblocks, and stores 2x2 ``V4L2_PIX_FMT_NV12_32L32`` stores pixel in 32x32 tiles, and stores
groups of macroblocks in Z-order in memory, alternating Z and mirrored Z shapes tiles linearly in memory. The line stride and image height must be
horizontally. The line stride must be a multiple of 128 pixels to ensure an aligned to a multiple of 32. The layouts of the luma and chroma planes are
integer number of Z shapes. The image height must be a multiple of 32 pixels. identical.
If the vertical resolution is an odd number of macroblocks, the last row of
macroblocks is stored in linear order. The layouts of the luma and chroma
planes are identical.
.. _nv12mt: .. _nv12mt:
@ -290,7 +310,7 @@ planes are identical.
:alt: nv12mt_example.svg :alt: nv12mt_example.svg
:align: center :align: center
Example V4L2_PIX_FMT_NV12MT memory layout of macroblocks Example V4L2_PIX_FMT_NV12MT memory layout of tiles
.. _V4L2-PIX-FMT-NV16: .. _V4L2-PIX-FMT-NV16:

View File

@ -113,7 +113,12 @@ than the number requested.
``V4L2_MEMORY_MMAP`` and ``format.type`` to the buffer type. ``V4L2_MEMORY_MMAP`` and ``format.type`` to the buffer type.
* - __u32 * - __u32
- ``reserved``\ [7] - ``flags``
- Specifies additional buffer management attributes.
See :ref:`memory-flags`.
* - __u32
- ``reserved``\ [6]
- A place holder for future extensions. Drivers and applications - A place holder for future extensions. Drivers and applications
must set the array to zero. must set the array to zero.

View File

@ -95,3 +95,6 @@ EBUSY
EACCES EACCES
Attempt to set a read-only control or to get a write-only control. Attempt to set a read-only control or to get a write-only control.
Or if there is an attempt to set an inactive control and the driver is
not capable of caching the new value until the control is active again.

View File

@ -470,3 +470,6 @@ EACCES
Or the ``which`` field was set to ``V4L2_CTRL_WHICH_REQUEST_VAL`` but the Or the ``which`` field was set to ``V4L2_CTRL_WHICH_REQUEST_VAL`` but the
device does not support requests. device does not support requests.
Or if there is an attempt to set an inactive control and the driver is
not capable of caching the new value until the control is active again.

View File

@ -495,6 +495,12 @@ See also the examples in :ref:`control`.
- n/a - n/a
- A struct :c:type:`v4l2_ctrl_hevc_slice_params`, containing HEVC - A struct :c:type:`v4l2_ctrl_hevc_slice_params`, containing HEVC
slice parameters for stateless video decoders. slice parameters for stateless video decoders.
* - ``V4L2_CTRL_TYPE_HEVC_SCALING_MATRIX``
- n/a
- n/a
- n/a
- A struct :c:type:`v4l2_ctrl_hevc_scaling_matrix`, containing HEVC
scaling matrix for stateless video decoders.
* - ``V4L2_CTRL_TYPE_VP8_FRAME`` * - ``V4L2_CTRL_TYPE_VP8_FRAME``
- n/a - n/a
- n/a - n/a

View File

@ -104,10 +104,13 @@ aborting or finishing any DMA in progress, an implicit
``V4L2_MEMORY_MMAP`` and ``type`` set to the buffer type. This will ``V4L2_MEMORY_MMAP`` and ``type`` set to the buffer type. This will
free any previously allocated buffers, so this is typically something free any previously allocated buffers, so this is typically something
that will be done at the start of the application. that will be done at the start of the application.
* - __u32 * - __u8
- ``reserved``\ [1] - ``flags``
- A place holder for future extensions. Drivers and applications - Specifies additional buffer management attributes.
must set the array to zero. See :ref:`memory-flags`.
* - __u8
- ``reserved``\ [3]
- Reserved for future extensions.
.. _v4l2-buf-capabilities: .. _v4l2-buf-capabilities:
.. _V4L2-BUF-CAP-SUPPORTS-MMAP: .. _V4L2-BUF-CAP-SUPPORTS-MMAP:
@ -158,8 +161,9 @@ aborting or finishing any DMA in progress, an implicit
- This capability is set by the driver to indicate that the queue supports - This capability is set by the driver to indicate that the queue supports
cache and memory management hints. However, it's only valid when the cache and memory management hints. However, it's only valid when the
queue is used for :ref:`memory mapping <mmap>` streaming I/O. See queue is used for :ref:`memory mapping <mmap>` streaming I/O. See
:ref:`V4L2_BUF_FLAG_NO_CACHE_INVALIDATE <V4L2-BUF-FLAG-NO-CACHE-INVALIDATE>` and :ref:`V4L2_BUF_FLAG_NO_CACHE_INVALIDATE <V4L2-BUF-FLAG-NO-CACHE-INVALIDATE>`,
:ref:`V4L2_BUF_FLAG_NO_CACHE_CLEAN <V4L2-BUF-FLAG-NO-CACHE-CLEAN>`. :ref:`V4L2_BUF_FLAG_NO_CACHE_CLEAN <V4L2-BUF-FLAG-NO-CACHE-CLEAN>` and
:ref:`V4L2_MEMORY_FLAG_NON_COHERENT <V4L2-MEMORY-FLAG-NON-COHERENT>`.
.. raw:: latex .. raw:: latex

View File

@ -187,6 +187,8 @@ replace define V4L2_CAP_IO_MC device-capabilities
# V4L2 pix flags # V4L2 pix flags
replace define V4L2_PIX_FMT_PRIV_MAGIC :c:type:`v4l2_pix_format` replace define V4L2_PIX_FMT_PRIV_MAGIC :c:type:`v4l2_pix_format`
replace define V4L2_PIX_FMT_FLAG_PREMUL_ALPHA format-flags replace define V4L2_PIX_FMT_FLAG_PREMUL_ALPHA format-flags
replace define V4L2_PIX_FMT_HM12 :c:type:`v4l2_pix_format`
replace define V4L2_PIX_FMT_SUNXI_TILED_NV12 :c:type:`v4l2_pix_format`
# V4L2 format flags # V4L2 format flags
replace define V4L2_FMT_FLAG_COMPRESSED fmtdesc-flags replace define V4L2_FMT_FLAG_COMPRESSED fmtdesc-flags

View File

@ -4436,7 +4436,7 @@ N: cros_ec
N: cros-ec N: cros-ec
CHRONTEL CH7322 CEC DRIVER CHRONTEL CH7322 CEC DRIVER
M: Jeff Chase <jnchase@google.com> M: Joe Tessler <jrt@google.com>
L: linux-media@vger.kernel.org L: linux-media@vger.kernel.org
S: Maintained S: Maintained
T: git git://linuxtv.org/media_tree.git T: git git://linuxtv.org/media_tree.git
@ -8220,7 +8220,7 @@ T: git git://linuxtv.org/anttip/media_tree.git
F: drivers/media/usb/hackrf/ F: drivers/media/usb/hackrf/
HANTRO VPU CODEC DRIVER HANTRO VPU CODEC DRIVER
M: Ezequiel Garcia <ezequiel@collabora.com> M: Ezequiel Garcia <ezequiel@vanguardiasur.com.ar>
M: Philipp Zabel <p.zabel@pengutronix.de> M: Philipp Zabel <p.zabel@pengutronix.de>
L: linux-media@vger.kernel.org L: linux-media@vger.kernel.org
L: linux-rockchip@lists.infradead.org L: linux-rockchip@lists.infradead.org
@ -8688,6 +8688,12 @@ S: Maintained
T: git git://linuxtv.org/media_tree.git T: git git://linuxtv.org/media_tree.git
F: drivers/media/i2c/hi556.c F: drivers/media/i2c/hi556.c
HYNIX HI846 SENSOR DRIVER
M: Martin Kepplinger <martin.kepplinger@puri.sm>
L: linux-media@vger.kernel.org
S: Maintained
F: drivers/media/i2c/hi846.c
Hyper-V/Azure CORE AND DRIVERS Hyper-V/Azure CORE AND DRIVERS
M: "K. Y. Srinivasan" <kys@microsoft.com> M: "K. Y. Srinivasan" <kys@microsoft.com>
M: Haiyang Zhang <haiyangz@microsoft.com> M: Haiyang Zhang <haiyangz@microsoft.com>
@ -10062,6 +10068,7 @@ F: include/linux/jbd2.h
JPU V4L2 MEM2MEM DRIVER FOR RENESAS JPU V4L2 MEM2MEM DRIVER FOR RENESAS
M: Mikhail Ulyanov <mikhail.ulyanov@cogentembedded.com> M: Mikhail Ulyanov <mikhail.ulyanov@cogentembedded.com>
L: linux-media@vger.kernel.org L: linux-media@vger.kernel.org
L: linux-renesas-soc@vger.kernel.org
S: Maintained S: Maintained
F: drivers/media/platform/rcar_jpu.c F: drivers/media/platform/rcar_jpu.c
@ -11700,6 +11707,7 @@ T: git git://linuxtv.org/media_tree.git
F: Documentation/devicetree/bindings/media/renesas,csi2.yaml F: Documentation/devicetree/bindings/media/renesas,csi2.yaml
F: Documentation/devicetree/bindings/media/renesas,isp.yaml F: Documentation/devicetree/bindings/media/renesas,isp.yaml
F: Documentation/devicetree/bindings/media/renesas,vin.yaml F: Documentation/devicetree/bindings/media/renesas,vin.yaml
F: drivers/media/platform/rcar-isp.c
F: drivers/media/platform/rcar-vin/ F: drivers/media/platform/rcar-vin/
MEDIA DRIVERS FOR RENESAS - VSP1 MEDIA DRIVERS FOR RENESAS - VSP1
@ -12781,6 +12789,7 @@ M: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
L: linux-media@vger.kernel.org L: linux-media@vger.kernel.org
S: Maintained S: Maintained
T: git git://linuxtv.org/media_tree.git T: git git://linuxtv.org/media_tree.git
F: Documentation/devicetree/bindings/media/i2c/aptina,mt9p031.yaml
F: drivers/media/i2c/mt9p031.c F: drivers/media/i2c/mt9p031.c
F: include/media/i2c/mt9p031.h F: include/media/i2c/mt9p031.h
@ -13833,6 +13842,13 @@ S: Maintained
T: git git://linuxtv.org/media_tree.git T: git git://linuxtv.org/media_tree.git
F: drivers/media/i2c/ov13858.c F: drivers/media/i2c/ov13858.c
OMNIVISION OV13B10 SENSOR DRIVER
M: Arec Kao <arec.kao@intel.com>
L: linux-media@vger.kernel.org
S: Maintained
T: git git://linuxtv.org/media_tree.git
F: drivers/media/i2c/ov13b10.c
OMNIVISION OV2680 SENSOR DRIVER OMNIVISION OV2680 SENSOR DRIVER
M: Rui Miguel Silva <rmfrfs@gmail.com> M: Rui Miguel Silva <rmfrfs@gmail.com>
L: linux-media@vger.kernel.org L: linux-media@vger.kernel.org
@ -16145,7 +16161,7 @@ F: include/uapi/linux/rkisp1-config.h
ROCKCHIP RASTER 2D GRAPHIC ACCELERATION UNIT DRIVER ROCKCHIP RASTER 2D GRAPHIC ACCELERATION UNIT DRIVER
M: Jacob Chen <jacob-chen@iotwrt.com> M: Jacob Chen <jacob-chen@iotwrt.com>
M: Ezequiel Garcia <ezequiel@collabora.com> M: Ezequiel Garcia <ezequiel@vanguardiasur.com.ar>
L: linux-media@vger.kernel.org L: linux-media@vger.kernel.org
L: linux-rockchip@lists.infradead.org L: linux-rockchip@lists.infradead.org
S: Maintained S: Maintained
@ -16153,7 +16169,7 @@ F: Documentation/devicetree/bindings/media/rockchip-rga.yaml
F: drivers/media/platform/rockchip/rga/ F: drivers/media/platform/rockchip/rga/
ROCKCHIP VIDEO DECODER DRIVER ROCKCHIP VIDEO DECODER DRIVER
M: Ezequiel Garcia <ezequiel@collabora.com> M: Ezequiel Garcia <ezequiel@vanguardiasur.com.ar>
L: linux-media@vger.kernel.org L: linux-media@vger.kernel.org
L: linux-rockchip@lists.infradead.org L: linux-rockchip@lists.infradead.org
S: Maintained S: Maintained

View File

@ -259,10 +259,24 @@ static int mbus_code_to_bus_cfg(struct ipu_csi_bus_config *cfg, u32 mbus_code,
cfg->data_width = IPU_CSI_DATA_WIDTH_8; cfg->data_width = IPU_CSI_DATA_WIDTH_8;
break; break;
case MEDIA_BUS_FMT_UYVY8_1X16: case MEDIA_BUS_FMT_UYVY8_1X16:
case MEDIA_BUS_FMT_YUYV8_1X16: if (mbus_type == V4L2_MBUS_BT656) {
cfg->data_fmt = CSI_SENS_CONF_DATA_FMT_BAYER; cfg->data_fmt = CSI_SENS_CONF_DATA_FMT_YUV422_UYVY;
cfg->data_width = IPU_CSI_DATA_WIDTH_8;
} else {
cfg->data_fmt = CSI_SENS_CONF_DATA_FMT_BAYER;
cfg->data_width = IPU_CSI_DATA_WIDTH_16;
}
cfg->mipi_dt = MIPI_DT_YUV422;
break;
case MEDIA_BUS_FMT_YUYV8_1X16:
if (mbus_type == V4L2_MBUS_BT656) {
cfg->data_fmt = CSI_SENS_CONF_DATA_FMT_YUV422_YUYV;
cfg->data_width = IPU_CSI_DATA_WIDTH_8;
} else {
cfg->data_fmt = CSI_SENS_CONF_DATA_FMT_BAYER;
cfg->data_width = IPU_CSI_DATA_WIDTH_16;
}
cfg->mipi_dt = MIPI_DT_YUV422; cfg->mipi_dt = MIPI_DT_YUV422;
cfg->data_width = IPU_CSI_DATA_WIDTH_16;
break; break;
case MEDIA_BUS_FMT_SBGGR8_1X8: case MEDIA_BUS_FMT_SBGGR8_1X8:
case MEDIA_BUS_FMT_SGBRG8_1X8: case MEDIA_BUS_FMT_SGBRG8_1X8:
@ -332,7 +346,7 @@ static int fill_csi_bus_cfg(struct ipu_csi_bus_config *csicfg,
const struct v4l2_mbus_config *mbus_cfg, const struct v4l2_mbus_config *mbus_cfg,
const struct v4l2_mbus_framefmt *mbus_fmt) const struct v4l2_mbus_framefmt *mbus_fmt)
{ {
int ret; int ret, is_bt1120;
memset(csicfg, 0, sizeof(*csicfg)); memset(csicfg, 0, sizeof(*csicfg));
@ -353,11 +367,18 @@ static int fill_csi_bus_cfg(struct ipu_csi_bus_config *csicfg,
break; break;
case V4L2_MBUS_BT656: case V4L2_MBUS_BT656:
csicfg->ext_vsync = 0; csicfg->ext_vsync = 0;
/* UYVY10_1X20 etc. should be supported as well */
is_bt1120 = mbus_fmt->code == MEDIA_BUS_FMT_UYVY8_1X16 ||
mbus_fmt->code == MEDIA_BUS_FMT_YUYV8_1X16;
if (V4L2_FIELD_HAS_BOTH(mbus_fmt->field) || if (V4L2_FIELD_HAS_BOTH(mbus_fmt->field) ||
mbus_fmt->field == V4L2_FIELD_ALTERNATE) mbus_fmt->field == V4L2_FIELD_ALTERNATE)
csicfg->clk_mode = IPU_CSI_CLK_MODE_CCIR656_INTERLACED; csicfg->clk_mode = is_bt1120 ?
IPU_CSI_CLK_MODE_CCIR1120_INTERLACED_SDR :
IPU_CSI_CLK_MODE_CCIR656_INTERLACED;
else else
csicfg->clk_mode = IPU_CSI_CLK_MODE_CCIR656_PROGRESSIVE; csicfg->clk_mode = is_bt1120 ?
IPU_CSI_CLK_MODE_CCIR1120_PROGRESSIVE_SDR :
IPU_CSI_CLK_MODE_CCIR656_PROGRESSIVE;
break; break;
case V4L2_MBUS_CSI2_DPHY: case V4L2_MBUS_CSI2_DPHY:
/* /*

View File

@ -8,6 +8,8 @@ config CEC_NOTIFIER
config CEC_PIN config CEC_PIN
bool bool
menu "CEC support"
config MEDIA_CEC_RC config MEDIA_CEC_RC
bool "HDMI CEC RC integration" bool "HDMI CEC RC integration"
depends on CEC_CORE && RC_CORE depends on CEC_CORE && RC_CORE
@ -37,3 +39,5 @@ source "drivers/media/cec/i2c/Kconfig"
source "drivers/media/cec/platform/Kconfig" source "drivers/media/cec/platform/Kconfig"
source "drivers/media/cec/usb/Kconfig" source "drivers/media/cec/usb/Kconfig"
endif endif
endmenu

View File

@ -957,7 +957,7 @@ static enum hrtimer_restart cec_pin_timer(struct hrtimer *timer)
* so we can kick off the pending transmit. * so we can kick off the pending transmit.
*/ */
delta = ktime_us_delta(ts, pin->ts); delta = ktime_us_delta(ts, pin->ts);
if (delta / CEC_TIM_DATA_BIT_TOTAL > if (delta / CEC_TIM_DATA_BIT_TOTAL >=
pin->tx_signal_free_time) { pin->tx_signal_free_time) {
pin->tx_nacked = false; pin->tx_nacked = false;
if (tx_custom_start(pin)) if (tx_custom_start(pin))
@ -968,7 +968,7 @@ static enum hrtimer_restart cec_pin_timer(struct hrtimer *timer)
cec_pin_low(pin); cec_pin_low(pin);
break; break;
} }
if (delta / CEC_TIM_DATA_BIT_TOTAL > if (delta / CEC_TIM_DATA_BIT_TOTAL >=
pin->tx_signal_free_time - 1) pin->tx_signal_free_time - 1)
pin->state = CEC_ST_TX_WAIT; pin->state = CEC_ST_TX_WAIT;
break; break;

View File

@ -633,7 +633,6 @@ static int meson_ao_cec_g12a_probe(struct platform_device *pdev)
{ {
struct meson_ao_cec_g12a_device *ao_cec; struct meson_ao_cec_g12a_device *ao_cec;
struct device *hdmi_dev; struct device *hdmi_dev;
struct resource *res;
void __iomem *base; void __iomem *base;
int ret, irq; int ret, irq;
@ -664,8 +663,7 @@ static int meson_ao_cec_g12a_probe(struct platform_device *pdev)
ao_cec->adap->owner = THIS_MODULE; ao_cec->adap->owner = THIS_MODULE;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0); base = devm_platform_ioremap_resource(pdev, 0);
base = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(base)) { if (IS_ERR(base)) {
ret = PTR_ERR(base); ret = PTR_ERR(base);
goto out_probe_adapter; goto out_probe_adapter;

View File

@ -602,7 +602,6 @@ static int meson_ao_cec_probe(struct platform_device *pdev)
{ {
struct meson_ao_cec_device *ao_cec; struct meson_ao_cec_device *ao_cec;
struct device *hdmi_dev; struct device *hdmi_dev;
struct resource *res;
int ret, irq; int ret, irq;
hdmi_dev = cec_notifier_parse_hdmi_phandle(&pdev->dev); hdmi_dev = cec_notifier_parse_hdmi_phandle(&pdev->dev);
@ -626,8 +625,7 @@ static int meson_ao_cec_probe(struct platform_device *pdev)
ao_cec->adap->owner = THIS_MODULE; ao_cec->adap->owner = THIS_MODULE;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ao_cec->base = devm_platform_ioremap_resource(pdev, 0);
ao_cec->base = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(ao_cec->base)) { if (IS_ERR(ao_cec->base)) {
ret = PTR_ERR(ao_cec->base); ret = PTR_ERR(ao_cec->base);
goto out_probe_adapter; goto out_probe_adapter;

View File

@ -178,7 +178,6 @@ static int s5p_cec_probe(struct platform_device *pdev)
{ {
struct device *dev = &pdev->dev; struct device *dev = &pdev->dev;
struct device *hdmi_dev; struct device *hdmi_dev;
struct resource *res;
struct s5p_cec_dev *cec; struct s5p_cec_dev *cec;
bool needs_hpd = of_property_read_bool(pdev->dev.of_node, "needs-hpd"); bool needs_hpd = of_property_read_bool(pdev->dev.of_node, "needs-hpd");
int ret; int ret;
@ -212,8 +211,7 @@ static int s5p_cec_probe(struct platform_device *pdev)
if (IS_ERR(cec->pmu)) if (IS_ERR(cec->pmu))
return -EPROBE_DEFER; return -EPROBE_DEFER;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0); cec->reg = devm_platform_ioremap_resource(pdev, 0);
cec->reg = devm_ioremap_resource(dev, res);
if (IS_ERR(cec->reg)) if (IS_ERR(cec->reg))
return PTR_ERR(cec->reg); return PTR_ERR(cec->reg);

View File

@ -299,7 +299,6 @@ static const struct cec_adap_ops sti_cec_adap_ops = {
static int stih_cec_probe(struct platform_device *pdev) static int stih_cec_probe(struct platform_device *pdev)
{ {
struct device *dev = &pdev->dev; struct device *dev = &pdev->dev;
struct resource *res;
struct stih_cec *cec; struct stih_cec *cec;
struct device *hdmi_dev; struct device *hdmi_dev;
int ret; int ret;
@ -315,8 +314,7 @@ static int stih_cec_probe(struct platform_device *pdev)
cec->dev = dev; cec->dev = dev;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0); cec->regs = devm_platform_ioremap_resource(pdev, 0);
cec->regs = devm_ioremap_resource(dev, res);
if (IS_ERR(cec->regs)) if (IS_ERR(cec->regs))
return PTR_ERR(cec->regs); return PTR_ERR(cec->regs);

View File

@ -255,7 +255,6 @@ static const struct regmap_config stm32_cec_regmap_cfg = {
static int stm32_cec_probe(struct platform_device *pdev) static int stm32_cec_probe(struct platform_device *pdev)
{ {
u32 caps = CEC_CAP_DEFAULTS | CEC_CAP_PHYS_ADDR | CEC_MODE_MONITOR_ALL; u32 caps = CEC_CAP_DEFAULTS | CEC_CAP_PHYS_ADDR | CEC_MODE_MONITOR_ALL;
struct resource *res;
struct stm32_cec *cec; struct stm32_cec *cec;
void __iomem *mmio; void __iomem *mmio;
int ret; int ret;
@ -266,8 +265,7 @@ static int stm32_cec_probe(struct platform_device *pdev)
cec->dev = &pdev->dev; cec->dev = &pdev->dev;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0); mmio = devm_platform_ioremap_resource(pdev, 0);
mmio = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(mmio)) if (IS_ERR(mmio))
return PTR_ERR(mmio); return PTR_ERR(mmio);

View File

@ -414,10 +414,10 @@ struct smscore_registry_entry_t {
static struct list_head g_smscore_notifyees; static struct list_head g_smscore_notifyees;
static struct list_head g_smscore_devices; static struct list_head g_smscore_devices;
static struct mutex g_smscore_deviceslock; static DEFINE_MUTEX(g_smscore_deviceslock);
static struct list_head g_smscore_registry; static struct list_head g_smscore_registry;
static struct mutex g_smscore_registrylock; static DEFINE_MUTEX(g_smscore_registrylock);
static int default_mode = DEVICE_MODE_NONE; static int default_mode = DEVICE_MODE_NONE;
@ -2119,10 +2119,7 @@ static int __init smscore_module_init(void)
{ {
INIT_LIST_HEAD(&g_smscore_notifyees); INIT_LIST_HEAD(&g_smscore_notifyees);
INIT_LIST_HEAD(&g_smscore_devices); INIT_LIST_HEAD(&g_smscore_devices);
mutex_init(&g_smscore_deviceslock);
INIT_LIST_HEAD(&g_smscore_registry); INIT_LIST_HEAD(&g_smscore_registry);
mutex_init(&g_smscore_registrylock);
return 0; return 0;
} }

View File

@ -68,13 +68,13 @@ module_param(debug, int, 0644);
err; \ err; \
}) })
#define call_ptr_memop(vb, op, args...) \ #define call_ptr_memop(op, vb, args...) \
({ \ ({ \
struct vb2_queue *_q = (vb)->vb2_queue; \ struct vb2_queue *_q = (vb)->vb2_queue; \
void *ptr; \ void *ptr; \
\ \
log_memop(vb, op); \ log_memop(vb, op); \
ptr = _q->mem_ops->op ? _q->mem_ops->op(args) : NULL; \ ptr = _q->mem_ops->op ? _q->mem_ops->op(vb, args) : NULL; \
if (!IS_ERR_OR_NULL(ptr)) \ if (!IS_ERR_OR_NULL(ptr)) \
(vb)->cnt_mem_ ## op++; \ (vb)->cnt_mem_ ## op++; \
ptr; \ ptr; \
@ -144,9 +144,9 @@ module_param(debug, int, 0644);
((vb)->vb2_queue->mem_ops->op ? \ ((vb)->vb2_queue->mem_ops->op ? \
(vb)->vb2_queue->mem_ops->op(args) : 0) (vb)->vb2_queue->mem_ops->op(args) : 0)
#define call_ptr_memop(vb, op, args...) \ #define call_ptr_memop(op, vb, args...) \
((vb)->vb2_queue->mem_ops->op ? \ ((vb)->vb2_queue->mem_ops->op ? \
(vb)->vb2_queue->mem_ops->op(args) : NULL) (vb)->vb2_queue->mem_ops->op(vb, args) : NULL)
#define call_void_memop(vb, op, args...) \ #define call_void_memop(vb, op, args...) \
do { \ do { \
@ -230,9 +230,10 @@ static int __vb2_buf_mem_alloc(struct vb2_buffer *vb)
if (size < vb->planes[plane].length) if (size < vb->planes[plane].length)
goto free; goto free;
mem_priv = call_ptr_memop(vb, alloc, mem_priv = call_ptr_memop(alloc,
q->alloc_devs[plane] ? : q->dev, vb,
q->dma_attrs, size, q->dma_dir, q->gfp_flags); q->alloc_devs[plane] ? : q->dev,
size);
if (IS_ERR_OR_NULL(mem_priv)) { if (IS_ERR_OR_NULL(mem_priv)) {
if (mem_priv) if (mem_priv)
ret = PTR_ERR(mem_priv); ret = PTR_ERR(mem_priv);
@ -326,12 +327,9 @@ static void __vb2_buf_mem_prepare(struct vb2_buffer *vb)
if (vb->synced) if (vb->synced)
return; return;
if (vb->need_cache_sync_on_prepare) {
for (plane = 0; plane < vb->num_planes; ++plane)
call_void_memop(vb, prepare,
vb->planes[plane].mem_priv);
}
vb->synced = 1; vb->synced = 1;
for (plane = 0; plane < vb->num_planes; ++plane)
call_void_memop(vb, prepare, vb->planes[plane].mem_priv);
} }
/* /*
@ -345,12 +343,9 @@ static void __vb2_buf_mem_finish(struct vb2_buffer *vb)
if (!vb->synced) if (!vb->synced)
return; return;
if (vb->need_cache_sync_on_finish) {
for (plane = 0; plane < vb->num_planes; ++plane)
call_void_memop(vb, finish,
vb->planes[plane].mem_priv);
}
vb->synced = 0; vb->synced = 0;
for (plane = 0; plane < vb->num_planes; ++plane)
call_void_memop(vb, finish, vb->planes[plane].mem_priv);
} }
/* /*
@ -381,6 +376,27 @@ static void __setup_offsets(struct vb2_buffer *vb)
} }
} }
static void init_buffer_cache_hints(struct vb2_queue *q, struct vb2_buffer *vb)
{
/*
* DMA exporter should take care of cache syncs, so we can avoid
* explicit ->prepare()/->finish() syncs. For other ->memory types
* we always need ->prepare() or/and ->finish() cache sync.
*/
if (q->memory == VB2_MEMORY_DMABUF) {
vb->skip_cache_sync_on_finish = 1;
vb->skip_cache_sync_on_prepare = 1;
return;
}
/*
* ->finish() cache sync can be avoided when queue direction is
* TO_DEVICE.
*/
if (q->dma_dir == DMA_TO_DEVICE)
vb->skip_cache_sync_on_finish = 1;
}
/* /*
* __vb2_queue_alloc() - allocate videobuf buffer structures and (for MMAP type) * __vb2_queue_alloc() - allocate videobuf buffer structures and (for MMAP type)
* video buffer memory for all buffers/planes on the queue and initializes the * video buffer memory for all buffers/planes on the queue and initializes the
@ -414,17 +430,7 @@ static int __vb2_queue_alloc(struct vb2_queue *q, enum vb2_memory memory,
vb->index = q->num_buffers + buffer; vb->index = q->num_buffers + buffer;
vb->type = q->type; vb->type = q->type;
vb->memory = memory; vb->memory = memory;
/* init_buffer_cache_hints(q, vb);
* We need to set these flags here so that the videobuf2 core
* will call ->prepare()/->finish() cache sync/flush on vb2
* buffers when appropriate. However, we can avoid explicit
* ->prepare() and ->finish() cache sync for DMABUF buffers,
* because DMA exporter takes care of it.
*/
if (q->memory != VB2_MEMORY_DMABUF) {
vb->need_cache_sync_on_prepare = 1;
vb->need_cache_sync_on_finish = 1;
}
for (plane = 0; plane < num_planes; ++plane) { for (plane = 0; plane < num_planes; ++plane) {
vb->planes[plane].length = plane_sizes[plane]; vb->planes[plane].length = plane_sizes[plane];
vb->planes[plane].min_length = plane_sizes[plane]; vb->planes[plane].min_length = plane_sizes[plane];
@ -732,11 +738,30 @@ int vb2_verify_memory_type(struct vb2_queue *q,
} }
EXPORT_SYMBOL(vb2_verify_memory_type); EXPORT_SYMBOL(vb2_verify_memory_type);
static void set_queue_coherency(struct vb2_queue *q, bool non_coherent_mem)
{
q->non_coherent_mem = 0;
if (!vb2_queue_allows_cache_hints(q))
return;
q->non_coherent_mem = non_coherent_mem;
}
static bool verify_coherency_flags(struct vb2_queue *q, bool non_coherent_mem)
{
if (non_coherent_mem != q->non_coherent_mem) {
dprintk(q, 1, "memory coherency model mismatch\n");
return false;
}
return true;
}
int vb2_core_reqbufs(struct vb2_queue *q, enum vb2_memory memory, int vb2_core_reqbufs(struct vb2_queue *q, enum vb2_memory memory,
unsigned int *count) unsigned int flags, unsigned int *count)
{ {
unsigned int num_buffers, allocated_buffers, num_planes = 0; unsigned int num_buffers, allocated_buffers, num_planes = 0;
unsigned plane_sizes[VB2_MAX_PLANES] = { }; unsigned plane_sizes[VB2_MAX_PLANES] = { };
bool non_coherent_mem = flags & V4L2_MEMORY_FLAG_NON_COHERENT;
unsigned int i; unsigned int i;
int ret; int ret;
@ -751,7 +776,8 @@ int vb2_core_reqbufs(struct vb2_queue *q, enum vb2_memory memory,
} }
if (*count == 0 || q->num_buffers != 0 || if (*count == 0 || q->num_buffers != 0 ||
(q->memory != VB2_MEMORY_UNKNOWN && q->memory != memory)) { (q->memory != VB2_MEMORY_UNKNOWN && q->memory != memory) ||
!verify_coherency_flags(q, non_coherent_mem)) {
/* /*
* We already have buffers allocated, so first check if they * We already have buffers allocated, so first check if they
* are not in use and can be freed. * are not in use and can be freed.
@ -788,6 +814,7 @@ int vb2_core_reqbufs(struct vb2_queue *q, enum vb2_memory memory,
num_buffers = min_t(unsigned int, num_buffers, VB2_MAX_FRAME); num_buffers = min_t(unsigned int, num_buffers, VB2_MAX_FRAME);
memset(q->alloc_devs, 0, sizeof(q->alloc_devs)); memset(q->alloc_devs, 0, sizeof(q->alloc_devs));
q->memory = memory; q->memory = memory;
set_queue_coherency(q, non_coherent_mem);
/* /*
* Ask the driver how many buffers and planes per buffer it requires. * Ask the driver how many buffers and planes per buffer it requires.
@ -872,12 +899,13 @@ int vb2_core_reqbufs(struct vb2_queue *q, enum vb2_memory memory,
EXPORT_SYMBOL_GPL(vb2_core_reqbufs); EXPORT_SYMBOL_GPL(vb2_core_reqbufs);
int vb2_core_create_bufs(struct vb2_queue *q, enum vb2_memory memory, int vb2_core_create_bufs(struct vb2_queue *q, enum vb2_memory memory,
unsigned int *count, unsigned int flags, unsigned int *count,
unsigned int requested_planes, unsigned int requested_planes,
const unsigned int requested_sizes[]) const unsigned int requested_sizes[])
{ {
unsigned int num_planes = 0, num_buffers, allocated_buffers; unsigned int num_planes = 0, num_buffers, allocated_buffers;
unsigned plane_sizes[VB2_MAX_PLANES] = { }; unsigned plane_sizes[VB2_MAX_PLANES] = { };
bool non_coherent_mem = flags & V4L2_MEMORY_FLAG_NON_COHERENT;
int ret; int ret;
if (q->num_buffers == VB2_MAX_FRAME) { if (q->num_buffers == VB2_MAX_FRAME) {
@ -893,11 +921,14 @@ int vb2_core_create_bufs(struct vb2_queue *q, enum vb2_memory memory,
memset(q->alloc_devs, 0, sizeof(q->alloc_devs)); memset(q->alloc_devs, 0, sizeof(q->alloc_devs));
q->memory = memory; q->memory = memory;
q->waiting_for_buffers = !q->is_output; q->waiting_for_buffers = !q->is_output;
set_queue_coherency(q, non_coherent_mem);
} else { } else {
if (q->memory != memory) { if (q->memory != memory) {
dprintk(q, 1, "memory model mismatch\n"); dprintk(q, 1, "memory model mismatch\n");
return -EINVAL; return -EINVAL;
} }
if (!verify_coherency_flags(q, non_coherent_mem))
return -EINVAL;
} }
num_buffers = min(*count, VB2_MAX_FRAME - q->num_buffers); num_buffers = min(*count, VB2_MAX_FRAME - q->num_buffers);
@ -975,7 +1006,7 @@ void *vb2_plane_vaddr(struct vb2_buffer *vb, unsigned int plane_no)
if (plane_no >= vb->num_planes || !vb->planes[plane_no].mem_priv) if (plane_no >= vb->num_planes || !vb->planes[plane_no].mem_priv)
return NULL; return NULL;
return call_ptr_memop(vb, vaddr, vb->planes[plane_no].mem_priv); return call_ptr_memop(vaddr, vb, vb->planes[plane_no].mem_priv);
} }
EXPORT_SYMBOL_GPL(vb2_plane_vaddr); EXPORT_SYMBOL_GPL(vb2_plane_vaddr);
@ -985,7 +1016,7 @@ void *vb2_plane_cookie(struct vb2_buffer *vb, unsigned int plane_no)
if (plane_no >= vb->num_planes || !vb->planes[plane_no].mem_priv) if (plane_no >= vb->num_planes || !vb->planes[plane_no].mem_priv)
return NULL; return NULL;
return call_ptr_memop(vb, cookie, vb->planes[plane_no].mem_priv); return call_ptr_memop(cookie, vb, vb->planes[plane_no].mem_priv);
} }
EXPORT_SYMBOL_GPL(vb2_plane_cookie); EXPORT_SYMBOL_GPL(vb2_plane_cookie);
@ -1125,10 +1156,11 @@ static int __prepare_userptr(struct vb2_buffer *vb)
vb->planes[plane].data_offset = 0; vb->planes[plane].data_offset = 0;
/* Acquire each plane's memory */ /* Acquire each plane's memory */
mem_priv = call_ptr_memop(vb, get_userptr, mem_priv = call_ptr_memop(get_userptr,
q->alloc_devs[plane] ? : q->dev, vb,
planes[plane].m.userptr, q->alloc_devs[plane] ? : q->dev,
planes[plane].length, q->dma_dir); planes[plane].m.userptr,
planes[plane].length);
if (IS_ERR(mem_priv)) { if (IS_ERR(mem_priv)) {
dprintk(q, 1, "failed acquiring userspace memory for plane %d\n", dprintk(q, 1, "failed acquiring userspace memory for plane %d\n",
plane); plane);
@ -1249,9 +1281,11 @@ static int __prepare_dmabuf(struct vb2_buffer *vb)
vb->planes[plane].data_offset = 0; vb->planes[plane].data_offset = 0;
/* Acquire each plane's memory */ /* Acquire each plane's memory */
mem_priv = call_ptr_memop(vb, attach_dmabuf, mem_priv = call_ptr_memop(attach_dmabuf,
q->alloc_devs[plane] ? : q->dev, vb,
dbuf, planes[plane].length, q->dma_dir); q->alloc_devs[plane] ? : q->dev,
dbuf,
planes[plane].length);
if (IS_ERR(mem_priv)) { if (IS_ERR(mem_priv)) {
dprintk(q, 1, "failed to attach dmabuf\n"); dprintk(q, 1, "failed to attach dmabuf\n");
ret = PTR_ERR(mem_priv); ret = PTR_ERR(mem_priv);
@ -1421,9 +1455,19 @@ int vb2_core_qbuf(struct vb2_queue *q, unsigned int index, void *pb,
static void vb2_req_queue(struct media_request_object *obj) static void vb2_req_queue(struct media_request_object *obj)
{ {
struct vb2_buffer *vb = container_of(obj, struct vb2_buffer, req_obj); struct vb2_buffer *vb = container_of(obj, struct vb2_buffer, req_obj);
int err;
mutex_lock(vb->vb2_queue->lock); mutex_lock(vb->vb2_queue->lock);
vb2_core_qbuf(vb->vb2_queue, vb->index, NULL, NULL); /*
* There is no method to propagate an error from vb2_core_qbuf(),
* so if this returns a non-0 value, then WARN.
*
* The only exception is -EIO which is returned if q->error is
* set. We just ignore that, and expect this will be caught the
* next time vb2_req_prepare() is called.
*/
err = vb2_core_qbuf(vb->vb2_queue, vb->index, NULL, NULL);
WARN_ON_ONCE(err && err != -EIO);
mutex_unlock(vb->vb2_queue->lock); mutex_unlock(vb->vb2_queue->lock);
} }
@ -2187,8 +2231,10 @@ int vb2_core_expbuf(struct vb2_queue *q, int *fd, unsigned int type,
vb_plane = &vb->planes[plane]; vb_plane = &vb->planes[plane];
dbuf = call_ptr_memop(vb, get_dmabuf, vb_plane->mem_priv, dbuf = call_ptr_memop(get_dmabuf,
flags & O_ACCMODE); vb,
vb_plane->mem_priv,
flags & O_ACCMODE);
if (IS_ERR_OR_NULL(dbuf)) { if (IS_ERR_OR_NULL(dbuf)) {
dprintk(q, 1, "failed to export buffer %d, plane %d\n", dprintk(q, 1, "failed to export buffer %d, plane %d\n",
index, plane); index, plane);
@ -2342,6 +2388,17 @@ int vb2_core_queue_init(struct vb2_queue *q)
if (WARN_ON(q->requires_requests && !q->supports_requests)) if (WARN_ON(q->requires_requests && !q->supports_requests))
return -EINVAL; return -EINVAL;
/*
* This combination is not allowed since a non-zero value of
* q->min_buffers_needed can cause vb2_core_qbuf() to fail if
* it has to call start_streaming(), and the Request API expects
* that queueing a request (and thus queueing a buffer contained
* in that request) will always succeed. There is no method of
* propagating an error back to userspace.
*/
if (WARN_ON(q->supports_requests && q->min_buffers_needed))
return -EINVAL;
INIT_LIST_HEAD(&q->queued_list); INIT_LIST_HEAD(&q->queued_list);
INIT_LIST_HEAD(&q->done_list); INIT_LIST_HEAD(&q->done_list);
spin_lock_init(&q->done_lock); spin_lock_init(&q->done_lock);
@ -2576,7 +2633,7 @@ static int __vb2_init_fileio(struct vb2_queue *q, int read)
fileio->memory = VB2_MEMORY_MMAP; fileio->memory = VB2_MEMORY_MMAP;
fileio->type = q->type; fileio->type = q->type;
q->fileio = fileio; q->fileio = fileio;
ret = vb2_core_reqbufs(q, fileio->memory, &fileio->count); ret = vb2_core_reqbufs(q, fileio->memory, 0, &fileio->count);
if (ret) if (ret)
goto err_kfree; goto err_kfree;
@ -2633,7 +2690,7 @@ static int __vb2_init_fileio(struct vb2_queue *q, int read)
err_reqbufs: err_reqbufs:
fileio->count = 0; fileio->count = 0;
vb2_core_reqbufs(q, fileio->memory, &fileio->count); vb2_core_reqbufs(q, fileio->memory, 0, &fileio->count);
err_kfree: err_kfree:
q->fileio = NULL; q->fileio = NULL;
@ -2653,7 +2710,7 @@ static int __vb2_cleanup_fileio(struct vb2_queue *q)
vb2_core_streamoff(q, q->type); vb2_core_streamoff(q, q->type);
q->fileio = NULL; q->fileio = NULL;
fileio->count = 0; fileio->count = 0;
vb2_core_reqbufs(q, fileio->memory, &fileio->count); vb2_core_reqbufs(q, fileio->memory, 0, &fileio->count);
kfree(fileio); kfree(fileio);
dprintk(q, 3, "file io emulator closed\n"); dprintk(q, 3, "file io emulator closed\n");
} }

View File

@ -17,6 +17,7 @@
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/dma-mapping.h> #include <linux/dma-mapping.h>
#include <linux/highmem.h>
#include <media/videobuf2-v4l2.h> #include <media/videobuf2-v4l2.h>
#include <media/videobuf2-dma-contig.h> #include <media/videobuf2-dma-contig.h>
@ -40,6 +41,9 @@ struct vb2_dc_buf {
/* DMABUF related */ /* DMABUF related */
struct dma_buf_attachment *db_attach; struct dma_buf_attachment *db_attach;
struct vb2_buffer *vb;
bool non_coherent_mem;
}; };
/*********************************************/ /*********************************************/
@ -66,24 +70,46 @@ static unsigned long vb2_dc_get_contiguous_size(struct sg_table *sgt)
/* callbacks for all buffers */ /* callbacks for all buffers */
/*********************************************/ /*********************************************/
static void *vb2_dc_cookie(void *buf_priv) static void *vb2_dc_cookie(struct vb2_buffer *vb, void *buf_priv)
{ {
struct vb2_dc_buf *buf = buf_priv; struct vb2_dc_buf *buf = buf_priv;
return &buf->dma_addr; return &buf->dma_addr;
} }
static void *vb2_dc_vaddr(void *buf_priv) /*
* This function may fail if:
*
* - dma_buf_vmap() fails
* E.g. due to lack of virtual mapping address space, or due to
* dmabuf->ops misconfiguration.
*
* - dma_vmap_noncontiguous() fails
* For instance, when requested buffer size is larger than totalram_pages().
* Relevant for buffers that use non-coherent memory.
*
* - Queue DMA attrs have DMA_ATTR_NO_KERNEL_MAPPING set
* Relevant for buffers that use coherent memory.
*/
static void *vb2_dc_vaddr(struct vb2_buffer *vb, void *buf_priv)
{ {
struct vb2_dc_buf *buf = buf_priv; struct vb2_dc_buf *buf = buf_priv;
struct dma_buf_map map;
int ret;
if (!buf->vaddr && buf->db_attach) { if (buf->vaddr)
ret = dma_buf_vmap(buf->db_attach->dmabuf, &map); return buf->vaddr;
buf->vaddr = ret ? NULL : map.vaddr;
if (buf->db_attach) {
struct dma_buf_map map;
if (!dma_buf_vmap(buf->db_attach->dmabuf, &map))
buf->vaddr = map.vaddr;
return buf->vaddr;
} }
if (buf->non_coherent_mem)
buf->vaddr = dma_vmap_noncontiguous(buf->dev, buf->size,
buf->dma_sgt);
return buf->vaddr; return buf->vaddr;
} }
@ -99,10 +125,19 @@ static void vb2_dc_prepare(void *buf_priv)
struct vb2_dc_buf *buf = buf_priv; struct vb2_dc_buf *buf = buf_priv;
struct sg_table *sgt = buf->dma_sgt; struct sg_table *sgt = buf->dma_sgt;
if (!sgt) /* This takes care of DMABUF and user-enforced cache sync hint */
if (buf->vb->skip_cache_sync_on_prepare)
return; return;
if (!buf->non_coherent_mem)
return;
/* For both USERPTR and non-coherent MMAP */
dma_sync_sgtable_for_device(buf->dev, sgt, buf->dma_dir); dma_sync_sgtable_for_device(buf->dev, sgt, buf->dma_dir);
/* Non-coherent MMAP only */
if (buf->vaddr)
flush_kernel_vmap_range(buf->vaddr, buf->size);
} }
static void vb2_dc_finish(void *buf_priv) static void vb2_dc_finish(void *buf_priv)
@ -110,10 +145,19 @@ static void vb2_dc_finish(void *buf_priv)
struct vb2_dc_buf *buf = buf_priv; struct vb2_dc_buf *buf = buf_priv;
struct sg_table *sgt = buf->dma_sgt; struct sg_table *sgt = buf->dma_sgt;
if (!sgt) /* This takes care of DMABUF and user-enforced cache sync hint */
if (buf->vb->skip_cache_sync_on_finish)
return; return;
if (!buf->non_coherent_mem)
return;
/* For both USERPTR and non-coherent MMAP */
dma_sync_sgtable_for_cpu(buf->dev, sgt, buf->dma_dir); dma_sync_sgtable_for_cpu(buf->dev, sgt, buf->dma_dir);
/* Non-coherent MMAP only */
if (buf->vaddr)
invalidate_kernel_vmap_range(buf->vaddr, buf->size);
} }
/*********************************************/ /*********************************************/
@ -127,21 +171,69 @@ static void vb2_dc_put(void *buf_priv)
if (!refcount_dec_and_test(&buf->refcount)) if (!refcount_dec_and_test(&buf->refcount))
return; return;
if (buf->sgt_base) { if (buf->non_coherent_mem) {
sg_free_table(buf->sgt_base); if (buf->vaddr)
kfree(buf->sgt_base); dma_vunmap_noncontiguous(buf->dev, buf->vaddr);
dma_free_noncontiguous(buf->dev, buf->size,
buf->dma_sgt, buf->dma_dir);
} else {
if (buf->sgt_base) {
sg_free_table(buf->sgt_base);
kfree(buf->sgt_base);
}
dma_free_attrs(buf->dev, buf->size, buf->cookie,
buf->dma_addr, buf->attrs);
} }
dma_free_attrs(buf->dev, buf->size, buf->cookie, buf->dma_addr,
buf->attrs);
put_device(buf->dev); put_device(buf->dev);
kfree(buf); kfree(buf);
} }
static void *vb2_dc_alloc(struct device *dev, unsigned long attrs, static int vb2_dc_alloc_coherent(struct vb2_dc_buf *buf)
unsigned long size, enum dma_data_direction dma_dir, {
gfp_t gfp_flags) struct vb2_queue *q = buf->vb->vb2_queue;
buf->cookie = dma_alloc_attrs(buf->dev,
buf->size,
&buf->dma_addr,
GFP_KERNEL | q->gfp_flags,
buf->attrs);
if (!buf->cookie)
return -ENOMEM;
if (q->dma_attrs & DMA_ATTR_NO_KERNEL_MAPPING)
return 0;
buf->vaddr = buf->cookie;
return 0;
}
static int vb2_dc_alloc_non_coherent(struct vb2_dc_buf *buf)
{
struct vb2_queue *q = buf->vb->vb2_queue;
buf->dma_sgt = dma_alloc_noncontiguous(buf->dev,
buf->size,
buf->dma_dir,
GFP_KERNEL | q->gfp_flags,
buf->attrs);
if (!buf->dma_sgt)
return -ENOMEM;
buf->dma_addr = sg_dma_address(buf->dma_sgt->sgl);
/*
* For non-coherent buffers the kernel mapping is created on demand
* in vb2_dc_vaddr().
*/
return 0;
}
static void *vb2_dc_alloc(struct vb2_buffer *vb,
struct device *dev,
unsigned long size)
{ {
struct vb2_dc_buf *buf; struct vb2_dc_buf *buf;
int ret;
if (WARN_ON(!dev)) if (WARN_ON(!dev))
return ERR_PTR(-EINVAL); return ERR_PTR(-EINVAL);
@ -150,23 +242,26 @@ static void *vb2_dc_alloc(struct device *dev, unsigned long attrs,
if (!buf) if (!buf)
return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM);
buf->attrs = attrs; buf->attrs = vb->vb2_queue->dma_attrs;
buf->cookie = dma_alloc_attrs(dev, size, &buf->dma_addr, buf->dma_dir = vb->vb2_queue->dma_dir;
GFP_KERNEL | gfp_flags, buf->attrs); buf->vb = vb;
if (!buf->cookie) { buf->non_coherent_mem = vb->vb2_queue->non_coherent_mem;
dev_err(dev, "dma_alloc_coherent of size %ld failed\n", size);
buf->size = size;
/* Prevent the device from being released while the buffer is used */
buf->dev = get_device(dev);
if (buf->non_coherent_mem)
ret = vb2_dc_alloc_non_coherent(buf);
else
ret = vb2_dc_alloc_coherent(buf);
if (ret) {
dev_err(dev, "dma alloc of size %ld failed\n", size);
kfree(buf); kfree(buf);
return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM);
} }
if ((buf->attrs & DMA_ATTR_NO_KERNEL_MAPPING) == 0)
buf->vaddr = buf->cookie;
/* Prevent the device from being released while the buffer is used */
buf->dev = get_device(dev);
buf->size = size;
buf->dma_dir = dma_dir;
buf->handler.refcount = &buf->refcount; buf->handler.refcount = &buf->refcount;
buf->handler.put = vb2_dc_put; buf->handler.put = vb2_dc_put;
buf->handler.arg = buf; buf->handler.arg = buf;
@ -186,9 +281,12 @@ static int vb2_dc_mmap(void *buf_priv, struct vm_area_struct *vma)
return -EINVAL; return -EINVAL;
} }
ret = dma_mmap_attrs(buf->dev, vma, buf->cookie, if (buf->non_coherent_mem)
buf->dma_addr, buf->size, buf->attrs); ret = dma_mmap_noncontiguous(buf->dev, vma, buf->size,
buf->dma_sgt);
else
ret = dma_mmap_attrs(buf->dev, vma, buf->cookie, buf->dma_addr,
buf->size, buf->attrs);
if (ret) { if (ret) {
pr_err("Remapping memory failed, error: %d\n", ret); pr_err("Remapping memory failed, error: %d\n", ret);
return ret; return ret;
@ -350,9 +448,15 @@ vb2_dc_dmabuf_ops_end_cpu_access(struct dma_buf *dbuf,
static int vb2_dc_dmabuf_ops_vmap(struct dma_buf *dbuf, struct dma_buf_map *map) static int vb2_dc_dmabuf_ops_vmap(struct dma_buf *dbuf, struct dma_buf_map *map)
{ {
struct vb2_dc_buf *buf = dbuf->priv; struct vb2_dc_buf *buf;
void *vaddr;
dma_buf_map_set_vaddr(map, buf->vaddr); buf = dbuf->priv;
vaddr = vb2_dc_vaddr(buf->vb, buf);
if (!vaddr)
return -EINVAL;
dma_buf_map_set_vaddr(map, vaddr);
return 0; return 0;
} }
@ -380,6 +484,9 @@ static struct sg_table *vb2_dc_get_base_sgt(struct vb2_dc_buf *buf)
int ret; int ret;
struct sg_table *sgt; struct sg_table *sgt;
if (buf->non_coherent_mem)
return buf->dma_sgt;
sgt = kmalloc(sizeof(*sgt), GFP_KERNEL); sgt = kmalloc(sizeof(*sgt), GFP_KERNEL);
if (!sgt) { if (!sgt) {
dev_err(buf->dev, "failed to alloc sg table\n"); dev_err(buf->dev, "failed to alloc sg table\n");
@ -397,7 +504,9 @@ static struct sg_table *vb2_dc_get_base_sgt(struct vb2_dc_buf *buf)
return sgt; return sgt;
} }
static struct dma_buf *vb2_dc_get_dmabuf(void *buf_priv, unsigned long flags) static struct dma_buf *vb2_dc_get_dmabuf(struct vb2_buffer *vb,
void *buf_priv,
unsigned long flags)
{ {
struct vb2_dc_buf *buf = buf_priv; struct vb2_dc_buf *buf = buf_priv;
struct dma_buf *dbuf; struct dma_buf *dbuf;
@ -459,8 +568,8 @@ static void vb2_dc_put_userptr(void *buf_priv)
kfree(buf); kfree(buf);
} }
static void *vb2_dc_get_userptr(struct device *dev, unsigned long vaddr, static void *vb2_dc_get_userptr(struct vb2_buffer *vb, struct device *dev,
unsigned long size, enum dma_data_direction dma_dir) unsigned long vaddr, unsigned long size)
{ {
struct vb2_dc_buf *buf; struct vb2_dc_buf *buf;
struct frame_vector *vec; struct frame_vector *vec;
@ -490,7 +599,8 @@ static void *vb2_dc_get_userptr(struct device *dev, unsigned long vaddr,
return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM);
buf->dev = dev; buf->dev = dev;
buf->dma_dir = dma_dir; buf->dma_dir = vb->vb2_queue->dma_dir;
buf->vb = vb;
offset = lower_32_bits(offset_in_page(vaddr)); offset = lower_32_bits(offset_in_page(vaddr));
vec = vb2_create_framevec(vaddr, size); vec = vb2_create_framevec(vaddr, size);
@ -555,6 +665,8 @@ static void *vb2_dc_get_userptr(struct device *dev, unsigned long vaddr,
buf->dma_addr = sg_dma_address(sgt->sgl); buf->dma_addr = sg_dma_address(sgt->sgl);
buf->dma_sgt = sgt; buf->dma_sgt = sgt;
buf->non_coherent_mem = 1;
out: out:
buf->size = size; buf->size = size;
@ -660,8 +772,8 @@ static void vb2_dc_detach_dmabuf(void *mem_priv)
kfree(buf); kfree(buf);
} }
static void *vb2_dc_attach_dmabuf(struct device *dev, struct dma_buf *dbuf, static void *vb2_dc_attach_dmabuf(struct vb2_buffer *vb, struct device *dev,
unsigned long size, enum dma_data_direction dma_dir) struct dma_buf *dbuf, unsigned long size)
{ {
struct vb2_dc_buf *buf; struct vb2_dc_buf *buf;
struct dma_buf_attachment *dba; struct dma_buf_attachment *dba;
@ -677,6 +789,8 @@ static void *vb2_dc_attach_dmabuf(struct device *dev, struct dma_buf *dbuf,
return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM);
buf->dev = dev; buf->dev = dev;
buf->vb = vb;
/* create attachment for the dmabuf with the user device */ /* create attachment for the dmabuf with the user device */
dba = dma_buf_attach(dbuf, buf->dev); dba = dma_buf_attach(dbuf, buf->dev);
if (IS_ERR(dba)) { if (IS_ERR(dba)) {
@ -685,7 +799,7 @@ static void *vb2_dc_attach_dmabuf(struct device *dev, struct dma_buf *dbuf,
return dba; return dba;
} }
buf->dma_dir = dma_dir; buf->dma_dir = vb->vb2_queue->dma_dir;
buf->size = size; buf->size = size;
buf->db_attach = dba; buf->db_attach = dba;

View File

@ -51,6 +51,8 @@ struct vb2_dma_sg_buf {
struct vb2_vmarea_handler handler; struct vb2_vmarea_handler handler;
struct dma_buf_attachment *db_attach; struct dma_buf_attachment *db_attach;
struct vb2_buffer *vb;
}; };
static void vb2_dma_sg_put(void *buf_priv); static void vb2_dma_sg_put(void *buf_priv);
@ -96,9 +98,8 @@ static int vb2_dma_sg_alloc_compacted(struct vb2_dma_sg_buf *buf,
return 0; return 0;
} }
static void *vb2_dma_sg_alloc(struct device *dev, unsigned long dma_attrs, static void *vb2_dma_sg_alloc(struct vb2_buffer *vb, struct device *dev,
unsigned long size, enum dma_data_direction dma_dir, unsigned long size)
gfp_t gfp_flags)
{ {
struct vb2_dma_sg_buf *buf; struct vb2_dma_sg_buf *buf;
struct sg_table *sgt; struct sg_table *sgt;
@ -113,7 +114,7 @@ static void *vb2_dma_sg_alloc(struct device *dev, unsigned long dma_attrs,
return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM);
buf->vaddr = NULL; buf->vaddr = NULL;
buf->dma_dir = dma_dir; buf->dma_dir = vb->vb2_queue->dma_dir;
buf->offset = 0; buf->offset = 0;
buf->size = size; buf->size = size;
/* size is already page aligned */ /* size is already page aligned */
@ -130,7 +131,7 @@ static void *vb2_dma_sg_alloc(struct device *dev, unsigned long dma_attrs,
if (!buf->pages) if (!buf->pages)
goto fail_pages_array_alloc; goto fail_pages_array_alloc;
ret = vb2_dma_sg_alloc_compacted(buf, gfp_flags); ret = vb2_dma_sg_alloc_compacted(buf, vb->vb2_queue->gfp_flags);
if (ret) if (ret)
goto fail_pages_alloc; goto fail_pages_alloc;
@ -154,6 +155,7 @@ static void *vb2_dma_sg_alloc(struct device *dev, unsigned long dma_attrs,
buf->handler.refcount = &buf->refcount; buf->handler.refcount = &buf->refcount;
buf->handler.put = vb2_dma_sg_put; buf->handler.put = vb2_dma_sg_put;
buf->handler.arg = buf; buf->handler.arg = buf;
buf->vb = vb;
refcount_set(&buf->refcount, 1); refcount_set(&buf->refcount, 1);
@ -202,6 +204,9 @@ static void vb2_dma_sg_prepare(void *buf_priv)
struct vb2_dma_sg_buf *buf = buf_priv; struct vb2_dma_sg_buf *buf = buf_priv;
struct sg_table *sgt = buf->dma_sgt; struct sg_table *sgt = buf->dma_sgt;
if (buf->vb->skip_cache_sync_on_prepare)
return;
dma_sync_sgtable_for_device(buf->dev, sgt, buf->dma_dir); dma_sync_sgtable_for_device(buf->dev, sgt, buf->dma_dir);
} }
@ -210,12 +215,14 @@ static void vb2_dma_sg_finish(void *buf_priv)
struct vb2_dma_sg_buf *buf = buf_priv; struct vb2_dma_sg_buf *buf = buf_priv;
struct sg_table *sgt = buf->dma_sgt; struct sg_table *sgt = buf->dma_sgt;
if (buf->vb->skip_cache_sync_on_finish)
return;
dma_sync_sgtable_for_cpu(buf->dev, sgt, buf->dma_dir); dma_sync_sgtable_for_cpu(buf->dev, sgt, buf->dma_dir);
} }
static void *vb2_dma_sg_get_userptr(struct device *dev, unsigned long vaddr, static void *vb2_dma_sg_get_userptr(struct vb2_buffer *vb, struct device *dev,
unsigned long size, unsigned long vaddr, unsigned long size)
enum dma_data_direction dma_dir)
{ {
struct vb2_dma_sg_buf *buf; struct vb2_dma_sg_buf *buf;
struct sg_table *sgt; struct sg_table *sgt;
@ -230,7 +237,7 @@ static void *vb2_dma_sg_get_userptr(struct device *dev, unsigned long vaddr,
buf->vaddr = NULL; buf->vaddr = NULL;
buf->dev = dev; buf->dev = dev;
buf->dma_dir = dma_dir; buf->dma_dir = vb->vb2_queue->dma_dir;
buf->offset = vaddr & ~PAGE_MASK; buf->offset = vaddr & ~PAGE_MASK;
buf->size = size; buf->size = size;
buf->dma_sgt = &buf->sg_table; buf->dma_sgt = &buf->sg_table;
@ -292,7 +299,7 @@ static void vb2_dma_sg_put_userptr(void *buf_priv)
kfree(buf); kfree(buf);
} }
static void *vb2_dma_sg_vaddr(void *buf_priv) static void *vb2_dma_sg_vaddr(struct vb2_buffer *vb, void *buf_priv)
{ {
struct vb2_dma_sg_buf *buf = buf_priv; struct vb2_dma_sg_buf *buf = buf_priv;
struct dma_buf_map map; struct dma_buf_map map;
@ -511,7 +518,9 @@ static const struct dma_buf_ops vb2_dma_sg_dmabuf_ops = {
.release = vb2_dma_sg_dmabuf_ops_release, .release = vb2_dma_sg_dmabuf_ops_release,
}; };
static struct dma_buf *vb2_dma_sg_get_dmabuf(void *buf_priv, unsigned long flags) static struct dma_buf *vb2_dma_sg_get_dmabuf(struct vb2_buffer *vb,
void *buf_priv,
unsigned long flags)
{ {
struct vb2_dma_sg_buf *buf = buf_priv; struct vb2_dma_sg_buf *buf = buf_priv;
struct dma_buf *dbuf; struct dma_buf *dbuf;
@ -605,8 +614,8 @@ static void vb2_dma_sg_detach_dmabuf(void *mem_priv)
kfree(buf); kfree(buf);
} }
static void *vb2_dma_sg_attach_dmabuf(struct device *dev, struct dma_buf *dbuf, static void *vb2_dma_sg_attach_dmabuf(struct vb2_buffer *vb, struct device *dev,
unsigned long size, enum dma_data_direction dma_dir) struct dma_buf *dbuf, unsigned long size)
{ {
struct vb2_dma_sg_buf *buf; struct vb2_dma_sg_buf *buf;
struct dma_buf_attachment *dba; struct dma_buf_attachment *dba;
@ -630,14 +639,14 @@ static void *vb2_dma_sg_attach_dmabuf(struct device *dev, struct dma_buf *dbuf,
return dba; return dba;
} }
buf->dma_dir = dma_dir; buf->dma_dir = vb->vb2_queue->dma_dir;
buf->size = size; buf->size = size;
buf->db_attach = dba; buf->db_attach = dba;
return buf; return buf;
} }
static void *vb2_dma_sg_cookie(void *buf_priv) static void *vb2_dma_sg_cookie(struct vb2_buffer *vb, void *buf_priv)
{ {
struct vb2_dma_sg_buf *buf = buf_priv; struct vb2_dma_sg_buf *buf = buf_priv;

View File

@ -345,24 +345,6 @@ static void set_buffer_cache_hints(struct vb2_queue *q,
struct vb2_buffer *vb, struct vb2_buffer *vb,
struct v4l2_buffer *b) struct v4l2_buffer *b)
{ {
/*
* DMA exporter should take care of cache syncs, so we can avoid
* explicit ->prepare()/->finish() syncs. For other ->memory types
* we always need ->prepare() or/and ->finish() cache sync.
*/
if (q->memory == VB2_MEMORY_DMABUF) {
vb->need_cache_sync_on_finish = 0;
vb->need_cache_sync_on_prepare = 0;
return;
}
/*
* Cache sync/invalidation flags are set by default in order to
* preserve existing behaviour for old apps/drivers.
*/
vb->need_cache_sync_on_prepare = 1;
vb->need_cache_sync_on_finish = 1;
if (!vb2_queue_allows_cache_hints(q)) { if (!vb2_queue_allows_cache_hints(q)) {
/* /*
* Clear buffer cache flags if queue does not support user * Clear buffer cache flags if queue does not support user
@ -374,18 +356,11 @@ static void set_buffer_cache_hints(struct vb2_queue *q,
return; return;
} }
/*
* ->finish() cache sync can be avoided when queue direction is
* TO_DEVICE.
*/
if (q->dma_dir == DMA_TO_DEVICE)
vb->need_cache_sync_on_finish = 0;
if (b->flags & V4L2_BUF_FLAG_NO_CACHE_INVALIDATE) if (b->flags & V4L2_BUF_FLAG_NO_CACHE_INVALIDATE)
vb->need_cache_sync_on_finish = 0; vb->skip_cache_sync_on_finish = 1;
if (b->flags & V4L2_BUF_FLAG_NO_CACHE_CLEAN) if (b->flags & V4L2_BUF_FLAG_NO_CACHE_CLEAN)
vb->need_cache_sync_on_prepare = 0; vb->skip_cache_sync_on_prepare = 1;
} }
static int vb2_queue_or_prepare_buf(struct vb2_queue *q, struct media_device *mdev, static int vb2_queue_or_prepare_buf(struct vb2_queue *q, struct media_device *mdev,
@ -717,12 +692,32 @@ static void fill_buf_caps(struct vb2_queue *q, u32 *caps)
#endif #endif
} }
static void validate_memory_flags(struct vb2_queue *q,
int memory,
u32 *flags)
{
if (!q->allow_cache_hints || memory != V4L2_MEMORY_MMAP) {
/*
* This needs to clear V4L2_MEMORY_FLAG_NON_COHERENT only,
* but in order to avoid bugs we zero out all bits.
*/
*flags = 0;
} else {
/* Clear all unknown flags. */
*flags &= V4L2_MEMORY_FLAG_NON_COHERENT;
}
}
int vb2_reqbufs(struct vb2_queue *q, struct v4l2_requestbuffers *req) int vb2_reqbufs(struct vb2_queue *q, struct v4l2_requestbuffers *req)
{ {
int ret = vb2_verify_memory_type(q, req->memory, req->type); int ret = vb2_verify_memory_type(q, req->memory, req->type);
u32 flags = req->flags;
fill_buf_caps(q, &req->capabilities); fill_buf_caps(q, &req->capabilities);
return ret ? ret : vb2_core_reqbufs(q, req->memory, &req->count); validate_memory_flags(q, req->memory, &flags);
req->flags = flags;
return ret ? ret : vb2_core_reqbufs(q, req->memory,
req->flags, &req->count);
} }
EXPORT_SYMBOL_GPL(vb2_reqbufs); EXPORT_SYMBOL_GPL(vb2_reqbufs);
@ -754,6 +749,7 @@ int vb2_create_bufs(struct vb2_queue *q, struct v4l2_create_buffers *create)
unsigned i; unsigned i;
fill_buf_caps(q, &create->capabilities); fill_buf_caps(q, &create->capabilities);
validate_memory_flags(q, create->memory, &create->flags);
create->index = q->num_buffers; create->index = q->num_buffers;
if (create->count == 0) if (create->count == 0)
return ret != -EBUSY ? ret : 0; return ret != -EBUSY ? ret : 0;
@ -797,6 +793,7 @@ int vb2_create_bufs(struct vb2_queue *q, struct v4l2_create_buffers *create)
if (requested_sizes[i] == 0) if (requested_sizes[i] == 0)
return -EINVAL; return -EINVAL;
return ret ? ret : vb2_core_create_bufs(q, create->memory, return ret ? ret : vb2_core_create_bufs(q, create->memory,
create->flags,
&create->count, &create->count,
requested_planes, requested_planes,
requested_sizes); requested_sizes);
@ -993,13 +990,16 @@ int vb2_ioctl_reqbufs(struct file *file, void *priv,
{ {
struct video_device *vdev = video_devdata(file); struct video_device *vdev = video_devdata(file);
int res = vb2_verify_memory_type(vdev->queue, p->memory, p->type); int res = vb2_verify_memory_type(vdev->queue, p->memory, p->type);
u32 flags = p->flags;
fill_buf_caps(vdev->queue, &p->capabilities); fill_buf_caps(vdev->queue, &p->capabilities);
validate_memory_flags(vdev->queue, p->memory, &flags);
p->flags = flags;
if (res) if (res)
return res; return res;
if (vb2_queue_is_busy(vdev, file)) if (vb2_queue_is_busy(vdev, file))
return -EBUSY; return -EBUSY;
res = vb2_core_reqbufs(vdev->queue, p->memory, &p->count); res = vb2_core_reqbufs(vdev->queue, p->memory, p->flags, &p->count);
/* If count == 0, then the owner has released all buffers and he /* If count == 0, then the owner has released all buffers and he
is no longer owner of the queue. Otherwise we have a new owner. */ is no longer owner of the queue. Otherwise we have a new owner. */
if (res == 0) if (res == 0)
@ -1017,6 +1017,7 @@ int vb2_ioctl_create_bufs(struct file *file, void *priv,
p->index = vdev->queue->num_buffers; p->index = vdev->queue->num_buffers;
fill_buf_caps(vdev->queue, &p->capabilities); fill_buf_caps(vdev->queue, &p->capabilities);
validate_memory_flags(vdev->queue, p->memory, &p->flags);
/* /*
* If count == 0, then just check if memory and type are valid. * If count == 0, then just check if memory and type are valid.
* Any -EBUSY result from vb2_verify_memory_type can be mapped to 0. * Any -EBUSY result from vb2_verify_memory_type can be mapped to 0.

View File

@ -34,13 +34,12 @@ struct vb2_vmalloc_buf {
static void vb2_vmalloc_put(void *buf_priv); static void vb2_vmalloc_put(void *buf_priv);
static void *vb2_vmalloc_alloc(struct device *dev, unsigned long attrs, static void *vb2_vmalloc_alloc(struct vb2_buffer *vb, struct device *dev,
unsigned long size, enum dma_data_direction dma_dir, unsigned long size)
gfp_t gfp_flags)
{ {
struct vb2_vmalloc_buf *buf; struct vb2_vmalloc_buf *buf;
buf = kzalloc(sizeof(*buf), GFP_KERNEL | gfp_flags); buf = kzalloc(sizeof(*buf), GFP_KERNEL | vb->vb2_queue->gfp_flags);
if (!buf) if (!buf)
return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM);
@ -52,7 +51,7 @@ static void *vb2_vmalloc_alloc(struct device *dev, unsigned long attrs,
return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM);
} }
buf->dma_dir = dma_dir; buf->dma_dir = vb->vb2_queue->dma_dir;
buf->handler.refcount = &buf->refcount; buf->handler.refcount = &buf->refcount;
buf->handler.put = vb2_vmalloc_put; buf->handler.put = vb2_vmalloc_put;
buf->handler.arg = buf; buf->handler.arg = buf;
@ -71,9 +70,8 @@ static void vb2_vmalloc_put(void *buf_priv)
} }
} }
static void *vb2_vmalloc_get_userptr(struct device *dev, unsigned long vaddr, static void *vb2_vmalloc_get_userptr(struct vb2_buffer *vb, struct device *dev,
unsigned long size, unsigned long vaddr, unsigned long size)
enum dma_data_direction dma_dir)
{ {
struct vb2_vmalloc_buf *buf; struct vb2_vmalloc_buf *buf;
struct frame_vector *vec; struct frame_vector *vec;
@ -84,7 +82,7 @@ static void *vb2_vmalloc_get_userptr(struct device *dev, unsigned long vaddr,
if (!buf) if (!buf)
return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM);
buf->dma_dir = dma_dir; buf->dma_dir = vb->vb2_queue->dma_dir;
offset = vaddr & ~PAGE_MASK; offset = vaddr & ~PAGE_MASK;
buf->size = size; buf->size = size;
vec = vb2_create_framevec(vaddr, size); vec = vb2_create_framevec(vaddr, size);
@ -147,7 +145,7 @@ static void vb2_vmalloc_put_userptr(void *buf_priv)
kfree(buf); kfree(buf);
} }
static void *vb2_vmalloc_vaddr(void *buf_priv) static void *vb2_vmalloc_vaddr(struct vb2_buffer *vb, void *buf_priv)
{ {
struct vb2_vmalloc_buf *buf = buf_priv; struct vb2_vmalloc_buf *buf = buf_priv;
@ -339,7 +337,9 @@ static const struct dma_buf_ops vb2_vmalloc_dmabuf_ops = {
.release = vb2_vmalloc_dmabuf_ops_release, .release = vb2_vmalloc_dmabuf_ops_release,
}; };
static struct dma_buf *vb2_vmalloc_get_dmabuf(void *buf_priv, unsigned long flags) static struct dma_buf *vb2_vmalloc_get_dmabuf(struct vb2_buffer *vb,
void *buf_priv,
unsigned long flags)
{ {
struct vb2_vmalloc_buf *buf = buf_priv; struct vb2_vmalloc_buf *buf = buf_priv;
struct dma_buf *dbuf; struct dma_buf *dbuf;
@ -403,8 +403,10 @@ static void vb2_vmalloc_detach_dmabuf(void *mem_priv)
kfree(buf); kfree(buf);
} }
static void *vb2_vmalloc_attach_dmabuf(struct device *dev, struct dma_buf *dbuf, static void *vb2_vmalloc_attach_dmabuf(struct vb2_buffer *vb,
unsigned long size, enum dma_data_direction dma_dir) struct device *dev,
struct dma_buf *dbuf,
unsigned long size)
{ {
struct vb2_vmalloc_buf *buf; struct vb2_vmalloc_buf *buf;
@ -416,7 +418,7 @@ static void *vb2_vmalloc_attach_dmabuf(struct device *dev, struct dma_buf *dbuf,
return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM);
buf->dbuf = dbuf; buf->dbuf = dbuf;
buf->dma_dir = dma_dir; buf->dma_dir = vb->vb2_queue->dma_dir;
buf->size = size; buf->size = size;
return buf; return buf;

View File

@ -342,7 +342,7 @@ int dvb_vb2_reqbufs(struct dvb_vb2_ctx *ctx, struct dmx_requestbuffers *req)
ctx->buf_siz = req->size; ctx->buf_siz = req->size;
ctx->buf_cnt = req->count; ctx->buf_cnt = req->count;
ret = vb2_core_reqbufs(&ctx->vb_q, VB2_MEMORY_MMAP, &req->count); ret = vb2_core_reqbufs(&ctx->vb_q, VB2_MEMORY_MMAP, 0, &req->count);
if (ret) { if (ret) {
ctx->state = DVB_VB2_STATE_NONE; ctx->state = DVB_VB2_STATE_NONE;
dprintk(1, "[%s] count=%d size=%d errno=%d\n", ctx->name, dprintk(1, "[%s] count=%d size=%d errno=%d\n", ctx->name,

View File

@ -3,15 +3,6 @@
* cxd2099.c: Driver for the Sony CXD2099AR Common Interface Controller * cxd2099.c: Driver for the Sony CXD2099AR Common Interface Controller
* *
* Copyright (C) 2010-2013 Digital Devices GmbH * Copyright (C) 2010-2013 Digital Devices GmbH
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 only, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/ */
#include <linux/slab.h> #include <linux/slab.h>

View File

@ -3,15 +3,6 @@
* cxd2099.h: Driver for the Sony CXD2099AR Common Interface Controller * cxd2099.h: Driver for the Sony CXD2099AR Common Interface Controller
* *
* Copyright (C) 2010-2011 Digital Devices GmbH * Copyright (C) 2010-2011 Digital Devices GmbH
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 only, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/ */
#ifndef _CXD2099_H_ #ifndef _CXD2099_H_

View File

@ -13,7 +13,7 @@
#include <media/dvb_frontend.h> #include <media/dvb_frontend.h>
#include <media/dvb_math.h> #include <media/dvb_math.h>
#include "cxd2820r.h" #include "cxd2820r.h"
#include <linux/gpio.h> #include <linux/gpio/driver.h> /* For gpio_chip */
#include <linux/math64.h> #include <linux/math64.h>
#include <linux/regmap.h> #include <linux/regmap.h>

View File

@ -444,11 +444,11 @@ static int mb86a20s_get_interleaving(struct mb86a20s_state *state,
unsigned layer) unsigned layer)
{ {
int rc; int rc;
int interleaving[] = { static const int interleaving[] = {
0, 1, 2, 4, 8 0, 1, 2, 4, 8
}; };
static unsigned char reg[] = { static const unsigned char reg[] = {
[0] = 0x88, /* Layer A */ [0] = 0x88, /* Layer A */
[1] = 0x8c, /* Layer B */ [1] = 0x8c, /* Layer B */
[2] = 0x90, /* Layer C */ [2] = 0x90, /* Layer C */

View File

@ -204,11 +204,18 @@ struct mn88443x_priv {
struct regmap *regmap_t; struct regmap *regmap_t;
}; };
static void mn88443x_cmn_power_on(struct mn88443x_priv *chip) static int mn88443x_cmn_power_on(struct mn88443x_priv *chip)
{ {
struct device *dev = &chip->client_s->dev;
struct regmap *r_t = chip->regmap_t; struct regmap *r_t = chip->regmap_t;
int ret;
clk_prepare_enable(chip->mclk); ret = clk_prepare_enable(chip->mclk);
if (ret) {
dev_err(dev, "Failed to prepare and enable mclk: %d\n",
ret);
return ret;
}
gpiod_set_value_cansleep(chip->reset_gpio, 1); gpiod_set_value_cansleep(chip->reset_gpio, 1);
usleep_range(100, 1000); usleep_range(100, 1000);
@ -222,6 +229,8 @@ static void mn88443x_cmn_power_on(struct mn88443x_priv *chip)
} else { } else {
regmap_write(r_t, HIZSET3, 0x8f); regmap_write(r_t, HIZSET3, 0x8f);
} }
return 0;
} }
static void mn88443x_cmn_power_off(struct mn88443x_priv *chip) static void mn88443x_cmn_power_off(struct mn88443x_priv *chip)
@ -738,7 +747,10 @@ static int mn88443x_probe(struct i2c_client *client,
chip->fe.demodulator_priv = chip; chip->fe.demodulator_priv = chip;
i2c_set_clientdata(client, chip); i2c_set_clientdata(client, chip);
mn88443x_cmn_power_on(chip); ret = mn88443x_cmn_power_on(chip);
if (ret)
goto err_i2c_t;
mn88443x_s_sleep(chip); mn88443x_s_sleep(chip);
mn88443x_t_sleep(chip); mn88443x_t_sleep(chip);

View File

@ -9,15 +9,6 @@
* based on code: * based on code:
* Copyright (c) 2011-2013 MaxLinear, Inc. All rights reserved * Copyright (c) 2011-2013 MaxLinear, Inc. All rights reserved
* which was released under GPL V2 * which was released under GPL V2
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/ */
#include <linux/kernel.h> #include <linux/kernel.h>

View File

@ -9,15 +9,6 @@
* based on code: * based on code:
* Copyright (c) 2011-2013 MaxLinear, Inc. All rights reserved * Copyright (c) 2011-2013 MaxLinear, Inc. All rights reserved
* which was released under GPL V2 * which was released under GPL V2
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/ */
#ifndef _MXL5XX_H_ #ifndef _MXL5XX_H_

View File

@ -7,10 +7,6 @@
* based on code: * based on code:
* Copyright (c) 2011-2013 MaxLinear, Inc. All rights reserved * Copyright (c) 2011-2013 MaxLinear, Inc. All rights reserved
* which was released under GPL V2 * which was released under GPL V2
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2, as published by the Free Software Foundation.
*/ */
enum MXL_BOOL_E { enum MXL_BOOL_E {

View File

@ -2,16 +2,6 @@
/* /*
* Copyright (c) 2011-2013 MaxLinear, Inc. All rights reserved * Copyright (c) 2011-2013 MaxLinear, Inc. All rights reserved
* *
* License type: GPLv2
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License as published by the Free Software
* Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* This program may alternatively be licensed under a proprietary license from * This program may alternatively be licensed under a proprietary license from
* MaxLinear, Inc. * MaxLinear, Inc.
* *

View File

@ -7,15 +7,6 @@
* based on code: * based on code:
* Copyright (c) 2016 MaxLinear, Inc. All rights reserved * Copyright (c) 2016 MaxLinear, Inc. All rights reserved
* which was released under GPL V2 * which was released under GPL V2
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/ */
#include <linux/mutex.h> #include <linux/mutex.h>

View File

@ -7,15 +7,6 @@
* based on code: * based on code:
* Copyright (c) 2016 MaxLinear, Inc. All rights reserved * Copyright (c) 2016 MaxLinear, Inc. All rights reserved
* which was released under GPL V2 * which was released under GPL V2
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/ */
#ifndef _MXL692_H_ #ifndef _MXL692_H_

View File

@ -7,15 +7,6 @@
* based on code: * based on code:
* Copyright (c) 2016 MaxLinear, Inc. All rights reserved * Copyright (c) 2016 MaxLinear, Inc. All rights reserved
* which was released under GPL V2 * which was released under GPL V2
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/ */
/***************************************************************************** /*****************************************************************************

View File

@ -376,8 +376,11 @@ static int rtl2832_sdr_alloc_urbs(struct rtl2832_sdr_dev *dev)
dev_dbg(&pdev->dev, "alloc urb=%d\n", i); dev_dbg(&pdev->dev, "alloc urb=%d\n", i);
dev->urb_list[i] = usb_alloc_urb(0, GFP_KERNEL); dev->urb_list[i] = usb_alloc_urb(0, GFP_KERNEL);
if (!dev->urb_list[i]) { if (!dev->urb_list[i]) {
for (j = 0; j < i; j++) for (j = 0; j < i; j++) {
usb_free_urb(dev->urb_list[j]); usb_free_urb(dev->urb_list[j]);
dev->urb_list[j] = NULL;
}
dev->urbs_initialized = 0;
return -ENOMEM; return -ENOMEM;
} }
usb_fill_bulk_urb(dev->urb_list[i], usb_fill_bulk_urb(dev->urb_list[i],

View File

@ -5,15 +5,6 @@
* Copyright (C) 2014-2015 Ralph Metzler <rjkm@metzlerbros.de> * Copyright (C) 2014-2015 Ralph Metzler <rjkm@metzlerbros.de>
* Marcus Metzler <mocm@metzlerbros.de> * Marcus Metzler <mocm@metzlerbros.de>
* developed for Digital Devices GmbH * developed for Digital Devices GmbH
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 only, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/ */
#include <linux/kernel.h> #include <linux/kernel.h>

View File

@ -5,15 +5,6 @@
* Copyright (C) 2014-2015 Ralph Metzler <rjkm@metzlerbros.de> * Copyright (C) 2014-2015 Ralph Metzler <rjkm@metzlerbros.de>
* Marcus Metzler <mocm@metzlerbros.de> * Marcus Metzler <mocm@metzlerbros.de>
* developed for Digital Devices GmbH * developed for Digital Devices GmbH
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 only, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/ */
#ifndef _STV0910_H_ #ifndef _STV0910_H_

View File

@ -3,15 +3,6 @@
* Driver for the ST STV6111 tuner * Driver for the ST STV6111 tuner
* *
* Copyright (C) 2014 Digital Devices GmbH * Copyright (C) 2014 Digital Devices GmbH
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 only, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/ */
#include <linux/kernel.h> #include <linux/kernel.h>

View File

@ -3,15 +3,6 @@
* Driver for the ST STV6111 tuner * Driver for the ST STV6111 tuner
* *
* Copyright (C) 2014 Digital Devices GmbH * Copyright (C) 2014 Digital Devices GmbH
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 only, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/ */
#ifndef _STV6111_H_ #ifndef _STV6111_H_

View File

@ -1165,7 +1165,11 @@ int avc_ca_pmt(struct firedtv *fdtv, char *msg, int length)
read_pos += program_info_length; read_pos += program_info_length;
write_pos += program_info_length; write_pos += program_info_length;
} }
while (read_pos < length) { while (read_pos + 4 < length) {
if (write_pos + 4 >= sizeof(c->operand) - 4) {
ret = -EINVAL;
goto out;
}
c->operand[write_pos++] = msg[read_pos++]; c->operand[write_pos++] = msg[read_pos++];
c->operand[write_pos++] = msg[read_pos++]; c->operand[write_pos++] = msg[read_pos++];
c->operand[write_pos++] = msg[read_pos++]; c->operand[write_pos++] = msg[read_pos++];
@ -1177,13 +1181,17 @@ int avc_ca_pmt(struct firedtv *fdtv, char *msg, int length)
c->operand[write_pos++] = es_info_length >> 8; c->operand[write_pos++] = es_info_length >> 8;
c->operand[write_pos++] = es_info_length & 0xff; c->operand[write_pos++] = es_info_length & 0xff;
if (es_info_length > 0) { if (es_info_length > 0) {
if (read_pos >= length) {
ret = -EINVAL;
goto out;
}
pmt_cmd_id = msg[read_pos++]; pmt_cmd_id = msg[read_pos++];
if (pmt_cmd_id != 1 && pmt_cmd_id != 4) if (pmt_cmd_id != 1 && pmt_cmd_id != 4)
dev_err(fdtv->device, "invalid pmt_cmd_id %d at stream level\n", dev_err(fdtv->device, "invalid pmt_cmd_id %d at stream level\n",
pmt_cmd_id); pmt_cmd_id);
if (es_info_length > sizeof(c->operand) - 4 - if (es_info_length > sizeof(c->operand) - 4 - write_pos ||
write_pos) { es_info_length > length - read_pos) {
ret = -EINVAL; ret = -EINVAL;
goto out; goto out;
} }

View File

@ -134,6 +134,8 @@ static int fdtv_ca_pmt(struct firedtv *fdtv, void *arg)
} else { } else {
data_length = msg->msg[3]; data_length = msg->msg[3];
} }
if (data_length > sizeof(msg->msg) - data_pos)
return -EINVAL;
return avc_ca_pmt(fdtv, &msg->msg[data_pos], data_length); return avc_ca_pmt(fdtv, &msg->msg[data_pos], data_length);
} }

View File

@ -450,6 +450,7 @@ config VIDEO_TW9906
config VIDEO_TW9910 config VIDEO_TW9910
tristate "Techwell TW9910 video decoder" tristate "Techwell TW9910 video decoder"
depends on VIDEO_V4L2 && I2C depends on VIDEO_V4L2 && I2C
select V4L2_ASYNC
help help
Support for Techwell TW9910 NTSC/PAL/SECAM video decoder. Support for Techwell TW9910 NTSC/PAL/SECAM video decoder.
@ -597,6 +598,7 @@ config VIDEO_AK881X
config VIDEO_THS8200 config VIDEO_THS8200
tristate "Texas Instruments THS8200 video encoder" tristate "Texas Instruments THS8200 video encoder"
depends on VIDEO_V4L2 && I2C depends on VIDEO_V4L2 && I2C
select V4L2_ASYNC
help help
Support for the Texas Instruments THS8200 video encoder. Support for the Texas Instruments THS8200 video encoder.
@ -610,6 +612,7 @@ menu "Video improvement chips"
config VIDEO_UPD64031A config VIDEO_UPD64031A
tristate "NEC Electronics uPD64031A Ghost Reduction" tristate "NEC Electronics uPD64031A Ghost Reduction"
depends on VIDEO_V4L2 && I2C depends on VIDEO_V4L2 && I2C
select V4L2_ASYNC
help help
Support for the NEC Electronics uPD64031A Ghost Reduction Support for the NEC Electronics uPD64031A Ghost Reduction
video chip. It is most often found in NTSC TV cards made for video chip. It is most often found in NTSC TV cards made for
@ -742,6 +745,19 @@ config VIDEO_HI556
To compile this driver as a module, choose M here: the To compile this driver as a module, choose M here: the
module will be called hi556. module will be called hi556.
config VIDEO_HI846
tristate "Hynix Hi-846 sensor support"
depends on I2C && VIDEO_V4L2
select MEDIA_CONTROLLER
select VIDEO_V4L2_SUBDEV_API
select V4L2_FWNODE
help
This is a Video4Linux2 sensor driver for the Hynix
Hi-846 camera.
To compile this driver as a module, choose M here: the
module will be called hi846.
config VIDEO_IMX208 config VIDEO_IMX208
tristate "Sony IMX208 sensor support" tristate "Sony IMX208 sensor support"
depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API
@ -1186,6 +1202,16 @@ config VIDEO_OV13858
This is a Video4Linux2 sensor driver for the OmniVision This is a Video4Linux2 sensor driver for the OmniVision
OV13858 camera. OV13858 camera.
config VIDEO_OV13B10
tristate "OmniVision OV13B10 sensor support"
depends on I2C && VIDEO_V4L2
select MEDIA_CONTROLLER
select VIDEO_V4L2_SUBDEV_API
select V4L2_FWNODE
help
This is a Video4Linux2 sensor driver for the OmniVision
OV13B10 camera.
config VIDEO_VS6624 config VIDEO_VS6624
tristate "ST VS6624 sensor support" tristate "ST VS6624 sensor support"
depends on VIDEO_V4L2 && I2C depends on VIDEO_V4L2 && I2C
@ -1229,6 +1255,7 @@ config VIDEO_MT9P031
select MEDIA_CONTROLLER select MEDIA_CONTROLLER
select VIDEO_V4L2_SUBDEV_API select VIDEO_V4L2_SUBDEV_API
select VIDEO_APTINA_PLL select VIDEO_APTINA_PLL
select V4L2_FWNODE
help help
This is a Video4Linux2 sensor driver for the Aptina This is a Video4Linux2 sensor driver for the Aptina
(Micron) mt9p031 5 Mpixel camera. (Micron) mt9p031 5 Mpixel camera.

View File

@ -89,6 +89,7 @@ obj-$(CONFIG_VIDEO_OV9640) += ov9640.o
obj-$(CONFIG_VIDEO_OV9650) += ov9650.o obj-$(CONFIG_VIDEO_OV9650) += ov9650.o
obj-$(CONFIG_VIDEO_OV9734) += ov9734.o obj-$(CONFIG_VIDEO_OV9734) += ov9734.o
obj-$(CONFIG_VIDEO_OV13858) += ov13858.o obj-$(CONFIG_VIDEO_OV13858) += ov13858.o
obj-$(CONFIG_VIDEO_OV13B10) += ov13b10.o
obj-$(CONFIG_VIDEO_MT9M001) += mt9m001.o obj-$(CONFIG_VIDEO_MT9M001) += mt9m001.o
obj-$(CONFIG_VIDEO_MT9M032) += mt9m032.o obj-$(CONFIG_VIDEO_MT9M032) += mt9m032.o
obj-$(CONFIG_VIDEO_MT9M111) += mt9m111.o obj-$(CONFIG_VIDEO_MT9M111) += mt9m111.o
@ -117,6 +118,7 @@ obj-$(CONFIG_VIDEO_ML86V7667) += ml86v7667.o
obj-$(CONFIG_VIDEO_OV2659) += ov2659.o obj-$(CONFIG_VIDEO_OV2659) += ov2659.o
obj-$(CONFIG_VIDEO_TC358743) += tc358743.o obj-$(CONFIG_VIDEO_TC358743) += tc358743.o
obj-$(CONFIG_VIDEO_HI556) += hi556.o obj-$(CONFIG_VIDEO_HI556) += hi556.o
obj-$(CONFIG_VIDEO_HI846) += hi846.o
obj-$(CONFIG_VIDEO_IMX208) += imx208.o obj-$(CONFIG_VIDEO_IMX208) += imx208.o
obj-$(CONFIG_VIDEO_IMX214) += imx214.o obj-$(CONFIG_VIDEO_IMX214) += imx214.o
obj-$(CONFIG_VIDEO_IMX219) += imx219.o obj-$(CONFIG_VIDEO_IMX219) += imx219.o

View File

@ -41,7 +41,7 @@ static int debug;
module_param(debug, int, 0644); module_param(debug, int, 0644);
MODULE_PARM_DESC(debug, "debug level (0-2)"); MODULE_PARM_DESC(debug, "debug level (0-2)");
MODULE_DESCRIPTION("Analog Devices ADV7604 video decoder driver"); MODULE_DESCRIPTION("Analog Devices ADV7604/10/11/12 video decoder driver");
MODULE_AUTHOR("Hans Verkuil <hans.verkuil@cisco.com>"); MODULE_AUTHOR("Hans Verkuil <hans.verkuil@cisco.com>");
MODULE_AUTHOR("Mats Randgaard <mats.randgaard@cisco.com>"); MODULE_AUTHOR("Mats Randgaard <mats.randgaard@cisco.com>");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
@ -77,7 +77,7 @@ MODULE_LICENSE("GPL");
enum adv76xx_type { enum adv76xx_type {
ADV7604, ADV7604,
ADV7611, ADV7611, // including ADV7610
ADV7612, ADV7612,
}; };
@ -3176,6 +3176,7 @@ static const struct adv76xx_chip_info adv76xx_chip_info[] = {
static const struct i2c_device_id adv76xx_i2c_id[] = { static const struct i2c_device_id adv76xx_i2c_id[] = {
{ "adv7604", (kernel_ulong_t)&adv76xx_chip_info[ADV7604] }, { "adv7604", (kernel_ulong_t)&adv76xx_chip_info[ADV7604] },
{ "adv7610", (kernel_ulong_t)&adv76xx_chip_info[ADV7611] },
{ "adv7611", (kernel_ulong_t)&adv76xx_chip_info[ADV7611] }, { "adv7611", (kernel_ulong_t)&adv76xx_chip_info[ADV7611] },
{ "adv7612", (kernel_ulong_t)&adv76xx_chip_info[ADV7612] }, { "adv7612", (kernel_ulong_t)&adv76xx_chip_info[ADV7612] },
{ } { }
@ -3183,6 +3184,7 @@ static const struct i2c_device_id adv76xx_i2c_id[] = {
MODULE_DEVICE_TABLE(i2c, adv76xx_i2c_id); MODULE_DEVICE_TABLE(i2c, adv76xx_i2c_id);
static const struct of_device_id adv76xx_of_id[] __maybe_unused = { static const struct of_device_id adv76xx_of_id[] __maybe_unused = {
{ .compatible = "adi,adv7610", .data = &adv76xx_chip_info[ADV7611] },
{ .compatible = "adi,adv7611", .data = &adv76xx_chip_info[ADV7611] }, { .compatible = "adi,adv7611", .data = &adv76xx_chip_info[ADV7611] },
{ .compatible = "adi,adv7612", .data = &adv76xx_chip_info[ADV7612] }, { .compatible = "adi,adv7612", .data = &adv76xx_chip_info[ADV7612] },
{ } { }
@ -3500,8 +3502,8 @@ static int adv76xx_probe(struct i2c_client *client,
return -ENODEV; return -ENODEV;
} }
if (val != 0x68) { if (val != 0x68) {
v4l2_err(sd, "not an adv7604 on address 0x%x\n", v4l2_err(sd, "not an ADV7604 on address 0x%x\n",
client->addr << 1); client->addr << 1);
return -ENODEV; return -ENODEV;
} }
break; break;
@ -3525,8 +3527,9 @@ static int adv76xx_probe(struct i2c_client *client,
val |= val2; val |= val2;
if ((state->info->type == ADV7611 && val != 0x2051) || if ((state->info->type == ADV7611 && val != 0x2051) ||
(state->info->type == ADV7612 && val != 0x2041)) { (state->info->type == ADV7612 && val != 0x2041)) {
v4l2_err(sd, "not an adv761x on address 0x%x\n", v4l2_err(sd, "not an %s on address 0x%x\n",
client->addr << 1); state->info->type == ADV7611 ? "ADV7610/11" : "ADV7612",
client->addr << 1);
return -ENODEV; return -ENODEV;
} }
break; break;

View File

@ -7,6 +7,7 @@
#include <linux/pm_runtime.h> #include <linux/pm_runtime.h>
#include <media/v4l2-ctrls.h> #include <media/v4l2-ctrls.h>
#include <media/v4l2-device.h> #include <media/v4l2-device.h>
#include <media/v4l2-event.h>
#define DW9714_NAME "dw9714" #define DW9714_NAME "dw9714"
#define DW9714_MAX_FOCUS_POS 1023 #define DW9714_MAX_FOCUS_POS 1023
@ -100,7 +101,15 @@ static const struct v4l2_subdev_internal_ops dw9714_int_ops = {
.close = dw9714_close, .close = dw9714_close,
}; };
static const struct v4l2_subdev_ops dw9714_ops = { }; static const struct v4l2_subdev_core_ops dw9714_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_ops dw9714_ops = {
.core = &dw9714_core_ops,
};
static void dw9714_subdev_cleanup(struct dw9714_device *dw9714_dev) static void dw9714_subdev_cleanup(struct dw9714_device *dw9714_dev)
{ {
@ -137,7 +146,8 @@ static int dw9714_probe(struct i2c_client *client)
return -ENOMEM; return -ENOMEM;
v4l2_i2c_subdev_init(&dw9714_dev->sd, client, &dw9714_ops); v4l2_i2c_subdev_init(&dw9714_dev->sd, client, &dw9714_ops);
dw9714_dev->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; dw9714_dev->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE |
V4L2_SUBDEV_FL_HAS_EVENTS;
dw9714_dev->sd.internal_ops = &dw9714_int_ops; dw9714_dev->sd.internal_ops = &dw9714_int_ops;
rval = dw9714_init_controls(dw9714_dev); rval = dw9714_init_controls(dw9714_dev);

2190
drivers/media/i2c/hi846.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -1260,18 +1260,18 @@ static int imx258_probe(struct i2c_client *client)
return -ENOMEM; return -ENOMEM;
imx258->clk = devm_clk_get_optional(&client->dev, NULL); imx258->clk = devm_clk_get_optional(&client->dev, NULL);
if (IS_ERR(imx258->clk))
return dev_err_probe(&client->dev, PTR_ERR(imx258->clk),
"error getting clock\n");
if (!imx258->clk) { if (!imx258->clk) {
dev_dbg(&client->dev, dev_dbg(&client->dev,
"no clock provided, using clock-frequency property\n"); "no clock provided, using clock-frequency property\n");
device_property_read_u32(&client->dev, "clock-frequency", &val); device_property_read_u32(&client->dev, "clock-frequency", &val);
if (val != IMX258_INPUT_CLOCK_FREQ) } else {
return -EINVAL; val = clk_get_rate(imx258->clk);
} else if (IS_ERR(imx258->clk)) {
return dev_err_probe(&client->dev, PTR_ERR(imx258->clk),
"error getting clock\n");
} }
if (clk_get_rate(imx258->clk) != IMX258_INPUT_CLOCK_FREQ) { if (val != IMX258_INPUT_CLOCK_FREQ) {
dev_err(&client->dev, "input clock frequency not supported\n"); dev_err(&client->dev, "input clock frequency not supported\n");
return -EINVAL; return -EINVAL;
} }

View File

@ -791,6 +791,7 @@ static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id)
rc_proto = RC_PROTO_BIT_RC5 | RC_PROTO_BIT_RC6_MCE | rc_proto = RC_PROTO_BIT_RC5 | RC_PROTO_BIT_RC6_MCE |
RC_PROTO_BIT_RC6_6A_32; RC_PROTO_BIT_RC6_6A_32;
ir_codes = RC_MAP_HAUPPAUGE; ir_codes = RC_MAP_HAUPPAUGE;
ir->polling_interval = 125;
probe_tx = true; probe_tx = true;
break; break;
} }

View File

@ -606,19 +606,18 @@ static int max9286_v4l2_notifier_register(struct max9286_priv *priv)
if (!priv->nsources) if (!priv->nsources)
return 0; return 0;
v4l2_async_notifier_init(&priv->notifier); v4l2_async_nf_init(&priv->notifier);
for_each_source(priv, source) { for_each_source(priv, source) {
unsigned int i = to_index(priv, source); unsigned int i = to_index(priv, source);
struct max9286_asd *mas; struct max9286_asd *mas;
mas = v4l2_async_notifier_add_fwnode_subdev(&priv->notifier, mas = v4l2_async_nf_add_fwnode(&priv->notifier, source->fwnode,
source->fwnode, struct max9286_asd);
struct max9286_asd);
if (IS_ERR(mas)) { if (IS_ERR(mas)) {
dev_err(dev, "Failed to add subdev for source %u: %ld", dev_err(dev, "Failed to add subdev for source %u: %ld",
i, PTR_ERR(mas)); i, PTR_ERR(mas));
v4l2_async_notifier_cleanup(&priv->notifier); v4l2_async_nf_cleanup(&priv->notifier);
return PTR_ERR(mas); return PTR_ERR(mas);
} }
@ -627,10 +626,10 @@ static int max9286_v4l2_notifier_register(struct max9286_priv *priv)
priv->notifier.ops = &max9286_notify_ops; priv->notifier.ops = &max9286_notify_ops;
ret = v4l2_async_subdev_notifier_register(&priv->sd, &priv->notifier); ret = v4l2_async_subdev_nf_register(&priv->sd, &priv->notifier);
if (ret) { if (ret) {
dev_err(dev, "Failed to register subdev_notifier"); dev_err(dev, "Failed to register subdev_notifier");
v4l2_async_notifier_cleanup(&priv->notifier); v4l2_async_nf_cleanup(&priv->notifier);
return ret; return ret;
} }
@ -642,8 +641,8 @@ static void max9286_v4l2_notifier_unregister(struct max9286_priv *priv)
if (!priv->nsources) if (!priv->nsources)
return; return;
v4l2_async_notifier_unregister(&priv->notifier); v4l2_async_nf_unregister(&priv->notifier);
v4l2_async_notifier_cleanup(&priv->notifier); v4l2_async_nf_cleanup(&priv->notifier);
} }
static int max9286_s_stream(struct v4l2_subdev *sd, int enable) static int max9286_s_stream(struct v4l2_subdev *sd, int enable)

View File

@ -27,6 +27,7 @@
#include <media/v4l2-async.h> #include <media/v4l2-async.h>
#include <media/v4l2-ctrls.h> #include <media/v4l2-ctrls.h>
#include <media/v4l2-device.h> #include <media/v4l2-device.h>
#include <media/v4l2-fwnode.h>
#include <media/v4l2-subdev.h> #include <media/v4l2-subdev.h>
#include "aptina-pll.h" #include "aptina-pll.h"
@ -75,38 +76,38 @@
#define MT9P031_PLL_CONFIG_1 0x11 #define MT9P031_PLL_CONFIG_1 0x11
#define MT9P031_PLL_CONFIG_2 0x12 #define MT9P031_PLL_CONFIG_2 0x12
#define MT9P031_PIXEL_CLOCK_CONTROL 0x0a #define MT9P031_PIXEL_CLOCK_CONTROL 0x0a
#define MT9P031_PIXEL_CLOCK_INVERT (1 << 15) #define MT9P031_PIXEL_CLOCK_INVERT BIT(15)
#define MT9P031_PIXEL_CLOCK_SHIFT(n) ((n) << 8) #define MT9P031_PIXEL_CLOCK_SHIFT(n) ((n) << 8)
#define MT9P031_PIXEL_CLOCK_DIVIDE(n) ((n) << 0) #define MT9P031_PIXEL_CLOCK_DIVIDE(n) ((n) << 0)
#define MT9P031_FRAME_RESTART 0x0b #define MT9P031_RESTART 0x0b
#define MT9P031_FRAME_PAUSE_RESTART BIT(1)
#define MT9P031_FRAME_RESTART BIT(0)
#define MT9P031_SHUTTER_DELAY 0x0c #define MT9P031_SHUTTER_DELAY 0x0c
#define MT9P031_RST 0x0d #define MT9P031_RST 0x0d
#define MT9P031_RST_ENABLE 1 #define MT9P031_RST_ENABLE BIT(0)
#define MT9P031_RST_DISABLE 0
#define MT9P031_READ_MODE_1 0x1e #define MT9P031_READ_MODE_1 0x1e
#define MT9P031_READ_MODE_2 0x20 #define MT9P031_READ_MODE_2 0x20
#define MT9P031_READ_MODE_2_ROW_MIR (1 << 15) #define MT9P031_READ_MODE_2_ROW_MIR BIT(15)
#define MT9P031_READ_MODE_2_COL_MIR (1 << 14) #define MT9P031_READ_MODE_2_COL_MIR BIT(14)
#define MT9P031_READ_MODE_2_ROW_BLC (1 << 6) #define MT9P031_READ_MODE_2_ROW_BLC BIT(6)
#define MT9P031_ROW_ADDRESS_MODE 0x22 #define MT9P031_ROW_ADDRESS_MODE 0x22
#define MT9P031_COLUMN_ADDRESS_MODE 0x23 #define MT9P031_COLUMN_ADDRESS_MODE 0x23
#define MT9P031_GLOBAL_GAIN 0x35 #define MT9P031_GLOBAL_GAIN 0x35
#define MT9P031_GLOBAL_GAIN_MIN 8 #define MT9P031_GLOBAL_GAIN_MIN 8
#define MT9P031_GLOBAL_GAIN_MAX 1024 #define MT9P031_GLOBAL_GAIN_MAX 1024
#define MT9P031_GLOBAL_GAIN_DEF 8 #define MT9P031_GLOBAL_GAIN_DEF 8
#define MT9P031_GLOBAL_GAIN_MULT (1 << 6) #define MT9P031_GLOBAL_GAIN_MULT BIT(6)
#define MT9P031_ROW_BLACK_TARGET 0x49 #define MT9P031_ROW_BLACK_TARGET 0x49
#define MT9P031_ROW_BLACK_DEF_OFFSET 0x4b #define MT9P031_ROW_BLACK_DEF_OFFSET 0x4b
#define MT9P031_GREEN1_OFFSET 0x60 #define MT9P031_GREEN1_OFFSET 0x60
#define MT9P031_GREEN2_OFFSET 0x61 #define MT9P031_GREEN2_OFFSET 0x61
#define MT9P031_BLACK_LEVEL_CALIBRATION 0x62 #define MT9P031_BLACK_LEVEL_CALIBRATION 0x62
#define MT9P031_BLC_MANUAL_BLC (1 << 0) #define MT9P031_BLC_MANUAL_BLC BIT(0)
#define MT9P031_RED_OFFSET 0x63 #define MT9P031_RED_OFFSET 0x63
#define MT9P031_BLUE_OFFSET 0x64 #define MT9P031_BLUE_OFFSET 0x64
#define MT9P031_TEST_PATTERN 0xa0 #define MT9P031_TEST_PATTERN 0xa0
#define MT9P031_TEST_PATTERN_SHIFT 3 #define MT9P031_TEST_PATTERN_SHIFT 3
#define MT9P031_TEST_PATTERN_ENABLE (1 << 0) #define MT9P031_TEST_PATTERN_ENABLE BIT(0)
#define MT9P031_TEST_PATTERN_DISABLE (0 << 0)
#define MT9P031_TEST_PATTERN_GREEN 0xa1 #define MT9P031_TEST_PATTERN_GREEN 0xa1
#define MT9P031_TEST_PATTERN_RED 0xa2 #define MT9P031_TEST_PATTERN_RED 0xa2
#define MT9P031_TEST_PATTERN_BLUE 0xa3 #define MT9P031_TEST_PATTERN_BLUE 0xa3
@ -196,7 +197,7 @@ static int mt9p031_reset(struct mt9p031 *mt9p031)
ret = mt9p031_write(client, MT9P031_RST, MT9P031_RST_ENABLE); ret = mt9p031_write(client, MT9P031_RST, MT9P031_RST_ENABLE);
if (ret < 0) if (ret < 0)
return ret; return ret;
ret = mt9p031_write(client, MT9P031_RST, MT9P031_RST_DISABLE); ret = mt9p031_write(client, MT9P031_RST, 0);
if (ret < 0) if (ret < 0)
return ret; return ret;
@ -229,6 +230,7 @@ static int mt9p031_clk_setup(struct mt9p031 *mt9p031)
struct i2c_client *client = v4l2_get_subdevdata(&mt9p031->subdev); struct i2c_client *client = v4l2_get_subdevdata(&mt9p031->subdev);
struct mt9p031_platform_data *pdata = mt9p031->pdata; struct mt9p031_platform_data *pdata = mt9p031->pdata;
unsigned long ext_freq;
int ret; int ret;
mt9p031->clk = devm_clk_get(&client->dev, NULL); mt9p031->clk = devm_clk_get(&client->dev, NULL);
@ -239,13 +241,15 @@ static int mt9p031_clk_setup(struct mt9p031 *mt9p031)
if (ret < 0) if (ret < 0)
return ret; return ret;
ext_freq = clk_get_rate(mt9p031->clk);
/* If the external clock frequency is out of bounds for the PLL use the /* If the external clock frequency is out of bounds for the PLL use the
* pixel clock divider only and disable the PLL. * pixel clock divider only and disable the PLL.
*/ */
if (pdata->ext_freq > limits.ext_clock_max) { if (ext_freq > limits.ext_clock_max) {
unsigned int div; unsigned int div;
div = DIV_ROUND_UP(pdata->ext_freq, pdata->target_freq); div = DIV_ROUND_UP(ext_freq, pdata->target_freq);
div = roundup_pow_of_two(div) / 2; div = roundup_pow_of_two(div) / 2;
mt9p031->clk_div = min_t(unsigned int, div, 64); mt9p031->clk_div = min_t(unsigned int, div, 64);
@ -254,7 +258,7 @@ static int mt9p031_clk_setup(struct mt9p031 *mt9p031)
return 0; return 0;
} }
mt9p031->pll.ext_clock = pdata->ext_freq; mt9p031->pll.ext_clock = ext_freq;
mt9p031->pll.pix_clock = pdata->target_freq; mt9p031->pll.pix_clock = pdata->target_freq;
mt9p031->use_pll = true; mt9p031->use_pll = true;
@ -369,6 +373,14 @@ static int __mt9p031_set_power(struct mt9p031 *mt9p031, bool on)
return ret; return ret;
} }
/* Configure the pixel clock polarity */
if (mt9p031->pdata && mt9p031->pdata->pixclk_pol) {
ret = mt9p031_write(client, MT9P031_PIXEL_CLOCK_CONTROL,
MT9P031_PIXEL_CLOCK_INVERT);
if (ret < 0)
return ret;
}
return v4l2_ctrl_handler_setup(&mt9p031->ctrls); return v4l2_ctrl_handler_setup(&mt9p031->ctrls);
} }
@ -444,9 +456,23 @@ static int mt9p031_set_params(struct mt9p031 *mt9p031)
static int mt9p031_s_stream(struct v4l2_subdev *subdev, int enable) static int mt9p031_s_stream(struct v4l2_subdev *subdev, int enable)
{ {
struct mt9p031 *mt9p031 = to_mt9p031(subdev); struct mt9p031 *mt9p031 = to_mt9p031(subdev);
struct i2c_client *client = v4l2_get_subdevdata(subdev);
int val;
int ret; int ret;
if (!enable) { if (!enable) {
/* enable pause restart */
val = MT9P031_FRAME_PAUSE_RESTART;
ret = mt9p031_write(client, MT9P031_RESTART, val);
if (ret < 0)
return ret;
/* enable restart + keep pause restart set */
val |= MT9P031_FRAME_RESTART;
ret = mt9p031_write(client, MT9P031_RESTART, val);
if (ret < 0)
return ret;
/* Stop sensor readout */ /* Stop sensor readout */
ret = mt9p031_set_output_control(mt9p031, ret = mt9p031_set_output_control(mt9p031,
MT9P031_OUTPUT_CONTROL_CEN, 0); MT9P031_OUTPUT_CONTROL_CEN, 0);
@ -466,6 +492,16 @@ static int mt9p031_s_stream(struct v4l2_subdev *subdev, int enable)
if (ret < 0) if (ret < 0)
return ret; return ret;
/*
* - clear pause restart
* - don't clear restart as clearing restart manually can cause
* undefined behavior
*/
val = MT9P031_FRAME_RESTART;
ret = mt9p031_write(client, MT9P031_RESTART, val);
if (ret < 0)
return ret;
return mt9p031_pll_enable(mt9p031); return mt9p031_pll_enable(mt9p031);
} }
@ -756,8 +792,7 @@ static int mt9p031_s_ctrl(struct v4l2_ctrl *ctrl)
if (ret < 0) if (ret < 0)
return ret; return ret;
return mt9p031_write(client, MT9P031_TEST_PATTERN, return mt9p031_write(client, MT9P031_TEST_PATTERN, 0);
MT9P031_TEST_PATTERN_DISABLE);
} }
ret = mt9p031_write(client, MT9P031_TEST_PATTERN_GREEN, 0x05a0); ret = mt9p031_write(client, MT9P031_TEST_PATTERN_GREEN, 0x05a0);
@ -1011,8 +1046,11 @@ static const struct v4l2_subdev_internal_ops mt9p031_subdev_internal_ops = {
static struct mt9p031_platform_data * static struct mt9p031_platform_data *
mt9p031_get_pdata(struct i2c_client *client) mt9p031_get_pdata(struct i2c_client *client)
{ {
struct mt9p031_platform_data *pdata; struct mt9p031_platform_data *pdata = NULL;
struct device_node *np; struct device_node *np;
struct v4l2_fwnode_endpoint endpoint = {
.bus_type = V4L2_MBUS_PARALLEL
};
if (!IS_ENABLED(CONFIG_OF) || !client->dev.of_node) if (!IS_ENABLED(CONFIG_OF) || !client->dev.of_node)
return client->dev.platform_data; return client->dev.platform_data;
@ -1021,6 +1059,9 @@ mt9p031_get_pdata(struct i2c_client *client)
if (!np) if (!np)
return NULL; return NULL;
if (v4l2_fwnode_endpoint_parse(of_fwnode_handle(np), &endpoint) < 0)
goto done;
pdata = devm_kzalloc(&client->dev, sizeof(*pdata), GFP_KERNEL); pdata = devm_kzalloc(&client->dev, sizeof(*pdata), GFP_KERNEL);
if (!pdata) if (!pdata)
goto done; goto done;
@ -1028,6 +1069,9 @@ mt9p031_get_pdata(struct i2c_client *client)
of_property_read_u32(np, "input-clock-frequency", &pdata->ext_freq); of_property_read_u32(np, "input-clock-frequency", &pdata->ext_freq);
of_property_read_u32(np, "pixel-clock-frequency", &pdata->target_freq); of_property_read_u32(np, "pixel-clock-frequency", &pdata->target_freq);
pdata->pixclk_pol = !!(endpoint.bus.parallel.flags &
V4L2_MBUS_PCLK_SAMPLE_RISING);
done: done:
of_node_put(np); of_node_put(np);
return pdata; return pdata;

View File

@ -7,6 +7,7 @@
#include <linux/pm_runtime.h> #include <linux/pm_runtime.h>
#include <media/v4l2-ctrls.h> #include <media/v4l2-ctrls.h>
#include <media/v4l2-device.h> #include <media/v4l2-device.h>
#include <media/v4l2-event.h>
#include <media/v4l2-fwnode.h> #include <media/v4l2-fwnode.h>
#define OV13858_REG_VALUE_08BIT 1 #define OV13858_REG_VALUE_08BIT 1
@ -1553,6 +1554,12 @@ static int ov13858_identify_module(struct ov13858 *ov13858)
return 0; return 0;
} }
static const struct v4l2_subdev_core_ops ov13858_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 ov13858_video_ops = { static const struct v4l2_subdev_video_ops ov13858_video_ops = {
.s_stream = ov13858_set_stream, .s_stream = ov13858_set_stream,
}; };
@ -1569,6 +1576,7 @@ static const struct v4l2_subdev_sensor_ops ov13858_sensor_ops = {
}; };
static const struct v4l2_subdev_ops ov13858_subdev_ops = { static const struct v4l2_subdev_ops ov13858_subdev_ops = {
.core = &ov13858_core_ops,
.video = &ov13858_video_ops, .video = &ov13858_video_ops,
.pad = &ov13858_pad_ops, .pad = &ov13858_pad_ops,
.sensor = &ov13858_sensor_ops, .sensor = &ov13858_sensor_ops,
@ -1724,7 +1732,8 @@ static int ov13858_probe(struct i2c_client *client,
/* Initialize subdev */ /* Initialize subdev */
ov13858->sd.internal_ops = &ov13858_internal_ops; ov13858->sd.internal_ops = &ov13858_internal_ops;
ov13858->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; ov13858->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE |
V4L2_SUBDEV_FL_HAS_EVENTS;
ov13858->sd.entity.ops = &ov13858_subdev_entity_ops; ov13858->sd.entity.ops = &ov13858_subdev_entity_ops;
ov13858->sd.entity.function = MEDIA_ENT_F_CAM_SENSOR; ov13858->sd.entity.function = MEDIA_ENT_F_CAM_SENSOR;

1491
drivers/media/i2c/ov13b10.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -7,6 +7,7 @@
#include <linux/pm_runtime.h> #include <linux/pm_runtime.h>
#include <media/v4l2-ctrls.h> #include <media/v4l2-ctrls.h>
#include <media/v4l2-device.h> #include <media/v4l2-device.h>
#include <media/v4l2-event.h>
#include <media/v4l2-fwnode.h> #include <media/v4l2-fwnode.h>
#define OV5670_REG_CHIP_ID 0x300a #define OV5670_REG_CHIP_ID 0x300a
@ -2420,6 +2421,12 @@ static int ov5670_identify_module(struct ov5670 *ov5670)
return 0; return 0;
} }
static const struct v4l2_subdev_core_ops ov5670_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 ov5670_video_ops = { static const struct v4l2_subdev_video_ops ov5670_video_ops = {
.s_stream = ov5670_set_stream, .s_stream = ov5670_set_stream,
}; };
@ -2436,6 +2443,7 @@ static const struct v4l2_subdev_sensor_ops ov5670_sensor_ops = {
}; };
static const struct v4l2_subdev_ops ov5670_subdev_ops = { static const struct v4l2_subdev_ops ov5670_subdev_ops = {
.core = &ov5670_core_ops,
.video = &ov5670_video_ops, .video = &ov5670_video_ops,
.pad = &ov5670_pad_ops, .pad = &ov5670_pad_ops,
.sensor = &ov5670_sensor_ops, .sensor = &ov5670_sensor_ops,
@ -2489,7 +2497,8 @@ static int ov5670_probe(struct i2c_client *client)
} }
ov5670->sd.internal_ops = &ov5670_internal_ops; ov5670->sd.internal_ops = &ov5670_internal_ops;
ov5670->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; ov5670->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE |
V4L2_SUBDEV_FL_HAS_EVENTS;
ov5670->sd.entity.ops = &ov5670_subdev_entity_ops; ov5670->sd.entity.ops = &ov5670_subdev_entity_ops;
ov5670->sd.entity.function = MEDIA_ENT_F_CAM_SENSOR; ov5670->sd.entity.function = MEDIA_ENT_F_CAM_SENSOR;

View File

@ -107,6 +107,11 @@ static const char * const ov8856_supply_names[] = {
"dvdd", /* Digital core power */ "dvdd", /* Digital core power */
}; };
enum {
OV8856_MEDIA_BUS_FMT_SBGGR10_1X10,
OV8856_MEDIA_BUS_FMT_SGRBG10_1X10,
};
struct ov8856_reg { struct ov8856_reg {
u16 address; u16 address;
u8 val; u8 val;
@ -145,6 +150,9 @@ struct ov8856_mode {
/* Number of data lanes */ /* Number of data lanes */
u8 data_lanes; u8 data_lanes;
/* Default MEDIA_BUS_FMT for this mode */
u32 default_mbus_index;
}; };
struct ov8856_mipi_data_rates { struct ov8856_mipi_data_rates {
@ -1055,7 +1063,7 @@ static const struct ov8856_reg lane_4_mode_3264x2448[] = {
{0x3810, 0x00}, {0x3810, 0x00},
{0x3811, 0x04}, {0x3811, 0x04},
{0x3812, 0x00}, {0x3812, 0x00},
{0x3813, 0x01}, {0x3813, 0x02},
{0x3814, 0x01}, {0x3814, 0x01},
{0x3815, 0x01}, {0x3815, 0x01},
{0x3816, 0x00}, {0x3816, 0x00},
@ -1259,7 +1267,7 @@ static const struct ov8856_reg lane_4_mode_1632x1224[] = {
{0x3810, 0x00}, {0x3810, 0x00},
{0x3811, 0x02}, {0x3811, 0x02},
{0x3812, 0x00}, {0x3812, 0x00},
{0x3813, 0x01}, {0x3813, 0x02},
{0x3814, 0x03}, {0x3814, 0x03},
{0x3815, 0x01}, {0x3815, 0x01},
{0x3816, 0x00}, {0x3816, 0x00},
@ -1372,6 +1380,19 @@ static const struct ov8856_reg lane_4_mode_1632x1224[] = {
{0x5e10, 0xfc} {0x5e10, 0xfc}
}; };
static const struct ov8856_reg mipi_data_mbus_sbggr10_1x10[] = {
{0x3813, 0x02},
};
static const struct ov8856_reg mipi_data_mbus_sgrbg10_1x10[] = {
{0x3813, 0x01},
};
static const u32 ov8856_mbus_codes[] = {
MEDIA_BUS_FMT_SBGGR10_1X10,
MEDIA_BUS_FMT_SGRBG10_1X10
};
static const char * const ov8856_test_pattern_menu[] = { static const char * const ov8856_test_pattern_menu[] = {
"Disabled", "Disabled",
"Standard Color Bar", "Standard Color Bar",
@ -1380,6 +1401,17 @@ static const char * const ov8856_test_pattern_menu[] = {
"Bottom-Top Darker Color Bar" "Bottom-Top Darker Color Bar"
}; };
static const struct ov8856_reg_list bayer_offset_configs[] = {
[OV8856_MEDIA_BUS_FMT_SBGGR10_1X10] = {
.num_of_regs = ARRAY_SIZE(mipi_data_mbus_sbggr10_1x10),
.regs = mipi_data_mbus_sbggr10_1x10,
},
[OV8856_MEDIA_BUS_FMT_SGRBG10_1X10] = {
.num_of_regs = ARRAY_SIZE(mipi_data_mbus_sgrbg10_1x10),
.regs = mipi_data_mbus_sgrbg10_1x10,
}
};
struct ov8856 { struct ov8856 {
struct v4l2_subdev sd; struct v4l2_subdev sd;
struct media_pad pad; struct media_pad pad;
@ -1399,6 +1431,9 @@ struct ov8856 {
/* Current mode */ /* Current mode */
const struct ov8856_mode *cur_mode; const struct ov8856_mode *cur_mode;
/* Application specified mbus format */
u32 cur_mbus_index;
/* To serialize asynchronus callbacks */ /* To serialize asynchronus callbacks */
struct mutex mutex; struct mutex mutex;
@ -1450,6 +1485,7 @@ static const struct ov8856_lane_cfg lane_cfg_2 = {
}, },
.link_freq_index = 0, .link_freq_index = 0,
.data_lanes = 2, .data_lanes = 2,
.default_mbus_index = OV8856_MEDIA_BUS_FMT_SGRBG10_1X10,
}, },
{ {
.width = 1640, .width = 1640,
@ -1464,6 +1500,7 @@ static const struct ov8856_lane_cfg lane_cfg_2 = {
}, },
.link_freq_index = 1, .link_freq_index = 1,
.data_lanes = 2, .data_lanes = 2,
.default_mbus_index = OV8856_MEDIA_BUS_FMT_SGRBG10_1X10,
}} }}
}; };
@ -1499,6 +1536,7 @@ static const struct ov8856_lane_cfg lane_cfg_4 = {
}, },
.link_freq_index = 0, .link_freq_index = 0,
.data_lanes = 4, .data_lanes = 4,
.default_mbus_index = OV8856_MEDIA_BUS_FMT_SGRBG10_1X10,
}, },
{ {
.width = 1640, .width = 1640,
@ -1513,6 +1551,7 @@ static const struct ov8856_lane_cfg lane_cfg_4 = {
}, },
.link_freq_index = 1, .link_freq_index = 1,
.data_lanes = 4, .data_lanes = 4,
.default_mbus_index = OV8856_MEDIA_BUS_FMT_SGRBG10_1X10,
}, },
{ {
.width = 3264, .width = 3264,
@ -1527,6 +1566,7 @@ static const struct ov8856_lane_cfg lane_cfg_4 = {
}, },
.link_freq_index = 0, .link_freq_index = 0,
.data_lanes = 4, .data_lanes = 4,
.default_mbus_index = OV8856_MEDIA_BUS_FMT_SBGGR10_1X10,
}, },
{ {
.width = 1632, .width = 1632,
@ -1541,6 +1581,7 @@ static const struct ov8856_lane_cfg lane_cfg_4 = {
}, },
.link_freq_index = 1, .link_freq_index = 1,
.data_lanes = 4, .data_lanes = 4,
.default_mbus_index = OV8856_MEDIA_BUS_FMT_SBGGR10_1X10,
}} }}
}; };
@ -1904,12 +1945,21 @@ static int ov8856_init_controls(struct ov8856 *ov8856)
return 0; return 0;
} }
static void ov8856_update_pad_format(const struct ov8856_mode *mode, static void ov8856_update_pad_format(struct ov8856 *ov8856,
const struct ov8856_mode *mode,
struct v4l2_mbus_framefmt *fmt) struct v4l2_mbus_framefmt *fmt)
{ {
int index;
fmt->width = mode->width; fmt->width = mode->width;
fmt->height = mode->height; fmt->height = mode->height;
fmt->code = MEDIA_BUS_FMT_SGRBG10_1X10; for (index = 0; index < ARRAY_SIZE(ov8856_mbus_codes); ++index)
if (ov8856_mbus_codes[index] == fmt->code)
break;
if (index == ARRAY_SIZE(ov8856_mbus_codes))
index = mode->default_mbus_index;
fmt->code = ov8856_mbus_codes[index];
ov8856->cur_mbus_index = index;
fmt->field = V4L2_FIELD_NONE; fmt->field = V4L2_FIELD_NONE;
} }
@ -1935,6 +1985,13 @@ static int ov8856_start_streaming(struct ov8856 *ov8856)
return ret; return ret;
} }
reg_list = &bayer_offset_configs[ov8856->cur_mbus_index];
ret = ov8856_write_reg_list(ov8856, reg_list);
if (ret) {
dev_err(&client->dev, "failed to set mbus format");
return ret;
}
ret = __v4l2_ctrl_handler_setup(ov8856->sd.ctrl_handler); ret = __v4l2_ctrl_handler_setup(ov8856->sd.ctrl_handler);
if (ret) if (ret)
return ret; return ret;
@ -2096,7 +2153,7 @@ static int ov8856_set_format(struct v4l2_subdev *sd,
fmt->format.height); fmt->format.height);
mutex_lock(&ov8856->mutex); mutex_lock(&ov8856->mutex);
ov8856_update_pad_format(mode, &fmt->format); ov8856_update_pad_format(ov8856, mode, &fmt->format);
if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) { if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
*v4l2_subdev_get_try_format(sd, sd_state, fmt->pad) = fmt->format; *v4l2_subdev_get_try_format(sd, sd_state, fmt->pad) = fmt->format;
} else { } else {
@ -2140,7 +2197,7 @@ static int ov8856_get_format(struct v4l2_subdev *sd,
sd_state, sd_state,
fmt->pad); fmt->pad);
else else
ov8856_update_pad_format(ov8856->cur_mode, &fmt->format); ov8856_update_pad_format(ov8856, ov8856->cur_mode, &fmt->format);
mutex_unlock(&ov8856->mutex); mutex_unlock(&ov8856->mutex);
@ -2151,11 +2208,10 @@ static int ov8856_enum_mbus_code(struct v4l2_subdev *sd,
struct v4l2_subdev_state *sd_state, struct v4l2_subdev_state *sd_state,
struct v4l2_subdev_mbus_code_enum *code) struct v4l2_subdev_mbus_code_enum *code)
{ {
/* Only one bayer order GRBG is supported */ if (code->index >= ARRAY_SIZE(ov8856_mbus_codes))
if (code->index > 0)
return -EINVAL; return -EINVAL;
code->code = MEDIA_BUS_FMT_SGRBG10_1X10; code->code = ov8856_mbus_codes[code->index];
return 0; return 0;
} }
@ -2165,11 +2221,15 @@ static int ov8856_enum_frame_size(struct v4l2_subdev *sd,
struct v4l2_subdev_frame_size_enum *fse) struct v4l2_subdev_frame_size_enum *fse)
{ {
struct ov8856 *ov8856 = to_ov8856(sd); struct ov8856 *ov8856 = to_ov8856(sd);
int index;
if (fse->index >= ov8856->modes_size) if (fse->index >= ov8856->modes_size)
return -EINVAL; return -EINVAL;
if (fse->code != MEDIA_BUS_FMT_SGRBG10_1X10) for (index = 0; index < ARRAY_SIZE(ov8856_mbus_codes); ++index)
if (fse->code == ov8856_mbus_codes[index])
break;
if (index == ARRAY_SIZE(ov8856_mbus_codes))
return -EINVAL; return -EINVAL;
fse->min_width = ov8856->priv_lane->supported_modes[fse->index].width; fse->min_width = ov8856->priv_lane->supported_modes[fse->index].width;
@ -2185,7 +2245,7 @@ static int ov8856_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
struct ov8856 *ov8856 = to_ov8856(sd); struct ov8856 *ov8856 = to_ov8856(sd);
mutex_lock(&ov8856->mutex); mutex_lock(&ov8856->mutex);
ov8856_update_pad_format(&ov8856->priv_lane->supported_modes[0], ov8856_update_pad_format(ov8856, &ov8856->priv_lane->supported_modes[0],
v4l2_subdev_get_try_format(sd, fh->state, 0)); v4l2_subdev_get_try_format(sd, fh->state, 0));
mutex_unlock(&ov8856->mutex); mutex_unlock(&ov8856->mutex);
@ -2426,6 +2486,7 @@ static int ov8856_probe(struct i2c_client *client)
mutex_init(&ov8856->mutex); mutex_init(&ov8856->mutex);
ov8856->cur_mode = &ov8856->priv_lane->supported_modes[0]; ov8856->cur_mode = &ov8856->priv_lane->supported_modes[0];
ov8856->cur_mbus_index = ov8856->cur_mode->default_mbus_index;
ret = ov8856_init_controls(ov8856); ret = ov8856_init_controls(ov8856);
if (ret) { if (ret) {
dev_err(&client->dev, "failed to init controls: %d", ret); dev_err(&client->dev, "failed to init controls: %d", ret);

View File

@ -876,11 +876,10 @@ static int mipid02_parse_rx_ep(struct mipid02_dev *bridge)
bridge->rx = ep; bridge->rx = ep;
/* register async notifier so we get noticed when sensor is connected */ /* register async notifier so we get noticed when sensor is connected */
v4l2_async_notifier_init(&bridge->notifier); v4l2_async_nf_init(&bridge->notifier);
asd = v4l2_async_notifier_add_fwnode_remote_subdev( asd = v4l2_async_nf_add_fwnode_remote(&bridge->notifier,
&bridge->notifier, of_fwnode_handle(ep_node),
of_fwnode_handle(ep_node), struct v4l2_async_subdev);
struct v4l2_async_subdev);
of_node_put(ep_node); of_node_put(ep_node);
if (IS_ERR(asd)) { if (IS_ERR(asd)) {
@ -890,10 +889,9 @@ static int mipid02_parse_rx_ep(struct mipid02_dev *bridge)
} }
bridge->notifier.ops = &mipid02_notifier_ops; bridge->notifier.ops = &mipid02_notifier_ops;
ret = v4l2_async_subdev_notifier_register(&bridge->sd, ret = v4l2_async_subdev_nf_register(&bridge->sd, &bridge->notifier);
&bridge->notifier);
if (ret) if (ret)
v4l2_async_notifier_cleanup(&bridge->notifier); v4l2_async_nf_cleanup(&bridge->notifier);
return ret; return ret;
@ -1031,8 +1029,8 @@ static int mipid02_probe(struct i2c_client *client)
return 0; return 0;
unregister_notifier: unregister_notifier:
v4l2_async_notifier_unregister(&bridge->notifier); v4l2_async_nf_unregister(&bridge->notifier);
v4l2_async_notifier_cleanup(&bridge->notifier); v4l2_async_nf_cleanup(&bridge->notifier);
power_off: power_off:
mipid02_set_power_off(bridge); mipid02_set_power_off(bridge);
entity_cleanup: entity_cleanup:
@ -1048,8 +1046,8 @@ static int mipid02_remove(struct i2c_client *client)
struct v4l2_subdev *sd = i2c_get_clientdata(client); struct v4l2_subdev *sd = i2c_get_clientdata(client);
struct mipid02_dev *bridge = to_mipid02_dev(sd); struct mipid02_dev *bridge = to_mipid02_dev(sd);
v4l2_async_notifier_unregister(&bridge->notifier); v4l2_async_nf_unregister(&bridge->notifier);
v4l2_async_notifier_cleanup(&bridge->notifier); v4l2_async_nf_cleanup(&bridge->notifier);
v4l2_async_unregister_subdev(&bridge->sd); v4l2_async_unregister_subdev(&bridge->sd);
mipid02_set_power_off(bridge); mipid02_set_power_off(bridge);
media_entity_cleanup(&bridge->sd.entity); media_entity_cleanup(&bridge->sd.entity);

View File

@ -1092,67 +1092,82 @@ tda1997x_detect_std(struct tda1997x_state *state,
struct v4l2_dv_timings *timings) struct v4l2_dv_timings *timings)
{ {
struct v4l2_subdev *sd = &state->sd; struct v4l2_subdev *sd = &state->sd;
u32 vper;
u16 hper;
u16 hsper;
int i;
/* /*
* Read the FMT registers * Read the FMT registers
* REG_V_PER: Period of a frame (or two fields) in MCLK(27MHz) cycles * REG_V_PER: Period of a frame (or field) in MCLK (27MHz) cycles
* REG_H_PER: Period of a line in MCLK(27MHz) cycles * REG_H_PER: Period of a line in MCLK (27MHz) cycles
* REG_HS_WIDTH: Period of horiz sync pulse in MCLK(27MHz) cycles * REG_HS_WIDTH: Period of horiz sync pulse in MCLK (27MHz) cycles
*/ */
vper = io_read24(sd, REG_V_PER) & MASK_VPER; u32 vper, vsync_pos;
hper = io_read16(sd, REG_H_PER) & MASK_HPER; u16 hper, hsync_pos, hsper, interlaced;
hsper = io_read16(sd, REG_HS_WIDTH) & MASK_HSWIDTH; u16 htot, hact, hfront, hsync, hback;
v4l2_dbg(1, debug, sd, "Signal Timings: %u/%u/%u\n", vper, hper, hsper); u16 vtot, vact, vfront1, vfront2, vsync, vback1, vback2;
if (!state->input_detect[0] && !state->input_detect[1]) if (!state->input_detect[0] && !state->input_detect[1])
return -ENOLINK; return -ENOLINK;
for (i = 0; v4l2_dv_timings_presets[i].bt.width; i++) { vper = io_read24(sd, REG_V_PER);
const struct v4l2_bt_timings *bt; hper = io_read16(sd, REG_H_PER);
u32 lines, width, _hper, _hsper; hsper = io_read16(sd, REG_HS_WIDTH);
u32 vmin, vmax, hmin, hmax, hsmin, hsmax; vsync_pos = vper & MASK_VPER_SYNC_POS;
bool vmatch, hmatch, hsmatch; hsync_pos = hper & MASK_HPER_SYNC_POS;
interlaced = hsper & MASK_HSWIDTH_INTERLACED;
vper &= MASK_VPER;
hper &= MASK_HPER;
hsper &= MASK_HSWIDTH;
v4l2_dbg(1, debug, sd, "Signal Timings: %u/%u/%u\n", vper, hper, hsper);
bt = &v4l2_dv_timings_presets[i].bt; htot = io_read16(sd, REG_FMT_H_TOT);
width = V4L2_DV_BT_FRAME_WIDTH(bt); hact = io_read16(sd, REG_FMT_H_ACT);
lines = V4L2_DV_BT_FRAME_HEIGHT(bt); hfront = io_read16(sd, REG_FMT_H_FRONT);
_hper = (u32)bt->pixelclock / width; hsync = io_read16(sd, REG_FMT_H_SYNC);
if (bt->interlaced) hback = io_read16(sd, REG_FMT_H_BACK);
lines /= 2;
/* vper +/- 0.7% */
vmin = ((27000000 / 1000) * 993) / _hper * lines;
vmax = ((27000000 / 1000) * 1007) / _hper * lines;
/* hper +/- 1.0% */
hmin = ((27000000 / 100) * 99) / _hper;
hmax = ((27000000 / 100) * 101) / _hper;
/* hsper +/- 2 (take care to avoid 32bit overflow) */
_hsper = 27000 * bt->hsync / ((u32)bt->pixelclock/1000);
hsmin = _hsper - 2;
hsmax = _hsper + 2;
/* vmatch matches the framerate */ vtot = io_read16(sd, REG_FMT_V_TOT);
vmatch = ((vper <= vmax) && (vper >= vmin)) ? 1 : 0; vact = io_read16(sd, REG_FMT_V_ACT);
/* hmatch matches the width */ vfront1 = io_read(sd, REG_FMT_V_FRONT_F1);
hmatch = ((hper <= hmax) && (hper >= hmin)) ? 1 : 0; vfront2 = io_read(sd, REG_FMT_V_FRONT_F2);
/* hsmatch matches the hswidth */ vsync = io_read(sd, REG_FMT_V_SYNC);
hsmatch = ((hsper <= hsmax) && (hsper >= hsmin)) ? 1 : 0; vback1 = io_read(sd, REG_FMT_V_BACK_F1);
if (hmatch && vmatch && hsmatch) { vback2 = io_read(sd, REG_FMT_V_BACK_F2);
v4l2_print_dv_timings(sd->name, "Detected format: ",
&v4l2_dv_timings_presets[i], v4l2_dbg(1, debug, sd, "Geometry: H %u %u %u %u %u Sync%c V %u %u %u %u %u %u %u Sync%c\n",
false); htot, hact, hfront, hsync, hback, hsync_pos ? '+' : '-',
if (timings) vtot, vact, vfront1, vfront2, vsync, vback1, vback2, vsync_pos ? '+' : '-');
*timings = v4l2_dv_timings_presets[i];
return 0; if (!timings)
} return 0;
timings->type = V4L2_DV_BT_656_1120;
timings->bt.width = hact;
timings->bt.hfrontporch = hfront;
timings->bt.hsync = hsync;
timings->bt.hbackporch = hback;
timings->bt.height = vact;
timings->bt.vfrontporch = vfront1;
timings->bt.vsync = vsync;
timings->bt.vbackporch = vback1;
timings->bt.interlaced = interlaced ? V4L2_DV_INTERLACED : V4L2_DV_PROGRESSIVE;
timings->bt.polarities = vsync_pos ? V4L2_DV_VSYNC_POS_POL : 0;
timings->bt.polarities |= hsync_pos ? V4L2_DV_HSYNC_POS_POL : 0;
timings->bt.pixelclock = (u64)htot * vtot * 27000000;
if (interlaced) {
timings->bt.il_vfrontporch = vfront2;
timings->bt.il_vsync = timings->bt.vsync;
timings->bt.il_vbackporch = vback2;
do_div(timings->bt.pixelclock, vper * 2 /* full frame */);
} else {
timings->bt.il_vfrontporch = 0;
timings->bt.il_vsync = 0;
timings->bt.il_vbackporch = 0;
do_div(timings->bt.pixelclock, vper);
} }
v4l2_find_dv_timings_cap(timings, &tda1997x_dv_timings_cap,
v4l_err(state->client, "no resolution match for timings: %d/%d/%d\n", (u32)timings->bt.pixelclock / 500, NULL, NULL);
vper, hper, hsper); v4l2_print_dv_timings(sd->name, "Detected format: ", timings, false);
return -ERANGE; return 0;
} }
/* some sort of errata workaround for chip revision 0 (N1) */ /* some sort of errata workaround for chip revision 0 (N1) */
@ -1248,13 +1263,13 @@ tda1997x_parse_infoframe(struct tda1997x_state *state, u16 addr)
{ {
struct v4l2_subdev *sd = &state->sd; struct v4l2_subdev *sd = &state->sd;
union hdmi_infoframe frame; union hdmi_infoframe frame;
u8 buffer[40]; u8 buffer[40] = { 0 };
u8 reg; u8 reg;
int len, err; int len, err;
/* read data */ /* read data */
len = io_readn(sd, addr, sizeof(buffer), buffer); len = io_readn(sd, addr, sizeof(buffer), buffer);
err = hdmi_infoframe_unpack(&frame, buffer, sizeof(buffer)); err = hdmi_infoframe_unpack(&frame, buffer, len);
if (err) { if (err) {
v4l_err(state->client, v4l_err(state->client,
"failed parsing %d byte infoframe: 0x%04x/0x%02x\n", "failed parsing %d byte infoframe: 0x%04x/0x%02x\n",
@ -1928,13 +1943,13 @@ static int tda1997x_log_infoframe(struct v4l2_subdev *sd, int addr)
{ {
struct tda1997x_state *state = to_state(sd); struct tda1997x_state *state = to_state(sd);
union hdmi_infoframe frame; union hdmi_infoframe frame;
u8 buffer[40]; u8 buffer[40] = { 0 };
int len, err; int len, err;
/* read data */ /* read data */
len = io_readn(sd, addr, sizeof(buffer), buffer); len = io_readn(sd, addr, sizeof(buffer), buffer);
v4l2_dbg(1, debug, sd, "infoframe: addr=%d len=%d\n", addr, len); v4l2_dbg(1, debug, sd, "infoframe: addr=%d len=%d\n", addr, len);
err = hdmi_infoframe_unpack(&frame, buffer, sizeof(buffer)); err = hdmi_infoframe_unpack(&frame, buffer, len);
if (err) { if (err) {
v4l_err(state->client, v4l_err(state->client,
"failed parsing %d byte infoframe: 0x%04x/0x%02x\n", "failed parsing %d byte infoframe: 0x%04x/0x%02x\n",
@ -2450,7 +2465,8 @@ static const struct media_entity_operations tda1997x_media_ops = {
static int tda1997x_pcm_startup(struct snd_pcm_substream *substream, static int tda1997x_pcm_startup(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai) struct snd_soc_dai *dai)
{ {
struct tda1997x_state *state = snd_soc_dai_get_drvdata(dai); struct v4l2_subdev *sd = snd_soc_dai_get_drvdata(dai);
struct tda1997x_state *state = to_state(sd);
struct snd_soc_component *component = dai->component; struct snd_soc_component *component = dai->component;
struct snd_pcm_runtime *rtd = substream->runtime; struct snd_pcm_runtime *rtd = substream->runtime;
int rate, err; int rate, err;
@ -2759,7 +2775,6 @@ static int tda1997x_probe(struct i2c_client *client,
dev_err(&client->dev, "register audio codec failed\n"); dev_err(&client->dev, "register audio codec failed\n");
goto err_free_media; goto err_free_media;
} }
dev_set_drvdata(&state->client->dev, state);
v4l_info(state->client, "registered audio codec\n"); v4l_info(state->client, "registered audio codec\n");
} }

View File

@ -117,9 +117,12 @@
#define REG_CURPAGE_00H 0xFF #define REG_CURPAGE_00H 0xFF
#define MASK_VPER 0x3fffff #define MASK_VPER 0x3fffff
#define MASK_VPER_SYNC_POS 0x800000
#define MASK_VHREF 0x3fff #define MASK_VHREF 0x3fff
#define MASK_HPER 0x0fff #define MASK_HPER 0x0fff
#define MASK_HPER_SYNC_POS 0x8000
#define MASK_HSWIDTH 0x03ff #define MASK_HSWIDTH 0x03ff
#define MASK_HSWIDTH_INTERLACED 0x8000
/* HPD Detection */ /* HPD Detection */
#define DETECT_UTIL BIT(7) /* utility of HDMI level */ #define DETECT_UTIL BIT(7) /* utility of HDMI level */

View File

@ -441,14 +441,15 @@ static void buffer_queue(struct vb2_buffer *vb)
static int video_i2c_thread_vid_cap(void *priv) static int video_i2c_thread_vid_cap(void *priv)
{ {
struct video_i2c_data *data = priv; struct video_i2c_data *data = priv;
unsigned int delay = mult_frac(HZ, data->frame_interval.numerator, u32 delay = mult_frac(1000000UL, data->frame_interval.numerator,
data->frame_interval.denominator); data->frame_interval.denominator);
s64 end_us = ktime_to_us(ktime_get());
set_freezable(); set_freezable();
do { do {
unsigned long start_jiffies = jiffies;
struct video_i2c_buffer *vid_cap_buf = NULL; struct video_i2c_buffer *vid_cap_buf = NULL;
s64 current_us;
int schedule_delay; int schedule_delay;
try_to_freeze(); try_to_freeze();
@ -475,12 +476,14 @@ static int video_i2c_thread_vid_cap(void *priv)
VB2_BUF_STATE_ERROR : VB2_BUF_STATE_DONE); VB2_BUF_STATE_ERROR : VB2_BUF_STATE_DONE);
} }
schedule_delay = delay - (jiffies - start_jiffies); end_us += delay;
current_us = ktime_to_us(ktime_get());
if (time_after(jiffies, start_jiffies + delay)) if (current_us < end_us) {
schedule_delay = delay; schedule_delay = end_us - current_us;
usleep_range(schedule_delay * 3 / 4, schedule_delay);
schedule_timeout_interruptible(schedule_delay); } else {
end_us = current_us;
}
} while (!kthread_should_stop()); } while (!kthread_should_stop());
return 0; return 0;

View File

@ -16,13 +16,5 @@ config MEDIA_CONTROLLER_REQUEST_API
bool bool
depends on MEDIA_CONTROLLER depends on MEDIA_CONTROLLER
help help
DO NOT ENABLE THIS OPTION UNLESS YOU KNOW WHAT YOU'RE DOING.
This option enables the Request API for the Media controller and V4L2 This option enables the Request API for the Media controller and V4L2
interfaces. It is currently needed by a few stateless codec drivers. interfaces. It is currently needed by a few stateless codec drivers.
There is currently no intention to provide API or ABI stability for
this new API as of yet.
comment "Please notice that the enabled Media controller Request API is EXPERIMENTAL"
depends on MEDIA_CONTROLLER_REQUEST_API

View File

@ -332,8 +332,8 @@ static int cobalt_setup_pci(struct cobalt *cobalt, struct pci_dev *pci_dev,
} }
} }
if (pci_set_dma_mask(pci_dev, DMA_BIT_MASK(64))) { if (dma_set_mask(&pci_dev->dev, DMA_BIT_MASK(64))) {
ret = pci_set_dma_mask(pci_dev, DMA_BIT_MASK(32)); ret = dma_set_mask(&pci_dev->dev, DMA_BIT_MASK(32));
if (ret) { if (ret) {
cobalt_err("no suitable DMA available\n"); cobalt_err("no suitable DMA available\n");
goto err_disable; goto err_disable;

View File

@ -804,7 +804,7 @@ static int cx18_setup_pci(struct cx18 *cx, struct pci_dev *pci_dev,
CX18_ERR("Can't enable device %d!\n", cx->instance); CX18_ERR("Can't enable device %d!\n", cx->instance);
return -EIO; return -EIO;
} }
if (pci_set_dma_mask(pci_dev, DMA_BIT_MASK(32))) { if (dma_set_mask(&pci_dev->dev, DMA_BIT_MASK(32))) {
CX18_ERR("No suitable DMA available, card %d\n", cx->instance); CX18_ERR("No suitable DMA available, card %d\n", cx->instance);
return -EIO; return -EIO;
} }

View File

@ -276,7 +276,7 @@ static int cx18_s_fmt_vid_cap(struct file *file, void *fh,
s->pixelformat = fmt->fmt.pix.pixelformat; s->pixelformat = fmt->fmt.pix.pixelformat;
/* HM12 YUV size is (Y=(h*720) + UV=(h*(720/2))) /* HM12 YUV size is (Y=(h*720) + UV=(h*(720/2)))
UYUV YUV size is (Y=(h*720) + UV=(h*(720))) */ UYUV YUV size is (Y=(h*720) + UV=(h*(720))) */
if (s->pixelformat == V4L2_PIX_FMT_HM12) { if (s->pixelformat == V4L2_PIX_FMT_NV12_16L16) {
s->vb_bytes_per_frame = h * 720 * 3 / 2; s->vb_bytes_per_frame = h * 720 * 3 / 2;
s->vb_bytes_per_line = 720; /* First plane */ s->vb_bytes_per_line = 720; /* First plane */
} else { } else {
@ -470,7 +470,7 @@ static int cx18_enum_fmt_vid_cap(struct file *file, void *fh,
.index = 0, .index = 0,
.type = V4L2_BUF_TYPE_VIDEO_CAPTURE, .type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
.description = "HM12 (YUV 4:1:1)", .description = "HM12 (YUV 4:1:1)",
.pixelformat = V4L2_PIX_FMT_HM12, .pixelformat = V4L2_PIX_FMT_NV12_16L16,
}, },
{ {
.index = 1, .index = 1,

View File

@ -325,8 +325,8 @@ void _cx18_mdl_sync_for_device(struct cx18_stream *s, struct cx18_mdl *mdl)
struct cx18_buffer *buf; struct cx18_buffer *buf;
list_for_each_entry(buf, &mdl->buf_list, list) list_for_each_entry(buf, &mdl->buf_list, list)
pci_dma_sync_single_for_device(pci_dev, buf->dma_handle, dma_sync_single_for_device(&pci_dev->dev, buf->dma_handle,
buf_size, dma); buf_size, dma);
} }
int cx18_stream_alloc(struct cx18_stream *s) int cx18_stream_alloc(struct cx18_stream *s)
@ -385,8 +385,9 @@ int cx18_stream_alloc(struct cx18_stream *s)
cx18_enqueue(s, mdl, &s->q_idle); cx18_enqueue(s, mdl, &s->q_idle);
INIT_LIST_HEAD(&buf->list); INIT_LIST_HEAD(&buf->list);
buf->dma_handle = pci_map_single(s->cx->pci_dev, buf->dma_handle = dma_map_single(&s->cx->pci_dev->dev,
buf->buf, s->buf_size, s->dma); buf->buf, s->buf_size,
s->dma);
cx18_buf_sync_for_cpu(s, buf); cx18_buf_sync_for_cpu(s, buf);
list_add_tail(&buf->list, &s->buf_pool); list_add_tail(&buf->list, &s->buf_pool);
} }
@ -419,8 +420,8 @@ void cx18_stream_free(struct cx18_stream *s)
buf = list_first_entry(&s->buf_pool, struct cx18_buffer, list); buf = list_first_entry(&s->buf_pool, struct cx18_buffer, list);
list_del_init(&buf->list); list_del_init(&buf->list);
pci_unmap_single(s->cx->pci_dev, buf->dma_handle, dma_unmap_single(&s->cx->pci_dev->dev, buf->dma_handle,
s->buf_size, s->dma); s->buf_size, s->dma);
kfree(buf->buf); kfree(buf->buf);
kfree(buf); kfree(buf);
} }

View File

@ -49,44 +49,44 @@ static struct {
{ /* CX18_ENC_STREAM_TYPE_MPG */ { /* CX18_ENC_STREAM_TYPE_MPG */
"encoder MPEG", "encoder MPEG",
VFL_TYPE_VIDEO, 0, VFL_TYPE_VIDEO, 0,
PCI_DMA_FROMDEVICE, DMA_FROM_DEVICE,
V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE | V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE |
V4L2_CAP_AUDIO | V4L2_CAP_TUNER V4L2_CAP_AUDIO | V4L2_CAP_TUNER
}, },
{ /* CX18_ENC_STREAM_TYPE_TS */ { /* CX18_ENC_STREAM_TYPE_TS */
"TS", "TS",
VFL_TYPE_VIDEO, -1, VFL_TYPE_VIDEO, -1,
PCI_DMA_FROMDEVICE, DMA_FROM_DEVICE,
}, },
{ /* CX18_ENC_STREAM_TYPE_YUV */ { /* CX18_ENC_STREAM_TYPE_YUV */
"encoder YUV", "encoder YUV",
VFL_TYPE_VIDEO, CX18_V4L2_ENC_YUV_OFFSET, VFL_TYPE_VIDEO, CX18_V4L2_ENC_YUV_OFFSET,
PCI_DMA_FROMDEVICE, DMA_FROM_DEVICE,
V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE | V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE |
V4L2_CAP_STREAMING | V4L2_CAP_AUDIO | V4L2_CAP_TUNER V4L2_CAP_STREAMING | V4L2_CAP_AUDIO | V4L2_CAP_TUNER
}, },
{ /* CX18_ENC_STREAM_TYPE_VBI */ { /* CX18_ENC_STREAM_TYPE_VBI */
"encoder VBI", "encoder VBI",
VFL_TYPE_VBI, 0, VFL_TYPE_VBI, 0,
PCI_DMA_FROMDEVICE, DMA_FROM_DEVICE,
V4L2_CAP_VBI_CAPTURE | V4L2_CAP_SLICED_VBI_CAPTURE | V4L2_CAP_VBI_CAPTURE | V4L2_CAP_SLICED_VBI_CAPTURE |
V4L2_CAP_READWRITE | V4L2_CAP_TUNER V4L2_CAP_READWRITE | V4L2_CAP_TUNER
}, },
{ /* CX18_ENC_STREAM_TYPE_PCM */ { /* CX18_ENC_STREAM_TYPE_PCM */
"encoder PCM audio", "encoder PCM audio",
VFL_TYPE_VIDEO, CX18_V4L2_ENC_PCM_OFFSET, VFL_TYPE_VIDEO, CX18_V4L2_ENC_PCM_OFFSET,
PCI_DMA_FROMDEVICE, DMA_FROM_DEVICE,
V4L2_CAP_TUNER | V4L2_CAP_AUDIO | V4L2_CAP_READWRITE, V4L2_CAP_TUNER | V4L2_CAP_AUDIO | V4L2_CAP_READWRITE,
}, },
{ /* CX18_ENC_STREAM_TYPE_IDX */ { /* CX18_ENC_STREAM_TYPE_IDX */
"encoder IDX", "encoder IDX",
VFL_TYPE_VIDEO, -1, VFL_TYPE_VIDEO, -1,
PCI_DMA_FROMDEVICE, DMA_FROM_DEVICE,
}, },
{ /* CX18_ENC_STREAM_TYPE_RAD */ { /* CX18_ENC_STREAM_TYPE_RAD */
"encoder radio", "encoder radio",
VFL_TYPE_RADIO, 0, VFL_TYPE_RADIO, 0,
PCI_DMA_NONE, DMA_NONE,
V4L2_CAP_RADIO | V4L2_CAP_TUNER V4L2_CAP_RADIO | V4L2_CAP_TUNER
}, },
}; };
@ -133,7 +133,7 @@ static int cx18_prepare_buffer(struct videobuf_queue *q,
/* HM12 YUV size is (Y=(h*720) + UV=(h*(720/2))) /* HM12 YUV size is (Y=(h*720) + UV=(h*(720/2)))
UYUV YUV size is (Y=(h*720) + UV=(h*(720))) */ UYUV YUV size is (Y=(h*720) + UV=(h*(720))) */
if (s->pixelformat == V4L2_PIX_FMT_HM12) if (s->pixelformat == V4L2_PIX_FMT_NV12_16L16)
s->vb_bytes_per_frame = height * 720 * 3 / 2; s->vb_bytes_per_frame = height * 720 * 3 / 2;
else else
s->vb_bytes_per_frame = height * 720 * 2; s->vb_bytes_per_frame = height * 720 * 2;
@ -155,7 +155,7 @@ static int cx18_prepare_buffer(struct videobuf_queue *q,
/* HM12 YUV size is (Y=(h*720) + UV=(h*(720/2))) /* HM12 YUV size is (Y=(h*720) + UV=(h*(720/2)))
UYUV YUV size is (Y=(h*720) + UV=(h*(720))) */ UYUV YUV size is (Y=(h*720) + UV=(h*(720))) */
if (s->pixelformat == V4L2_PIX_FMT_HM12) if (s->pixelformat == V4L2_PIX_FMT_NV12_16L16)
s->vb_bytes_per_frame = height * 720 * 3 / 2; s->vb_bytes_per_frame = height * 720 * 3 / 2;
else else
s->vb_bytes_per_frame = height * 720 * 2; s->vb_bytes_per_frame = height * 720 * 2;
@ -287,7 +287,7 @@ static void cx18_stream_init(struct cx18 *cx, int type)
s, &cx->serialize_lock); s, &cx->serialize_lock);
/* Assume the previous pixel default */ /* Assume the previous pixel default */
s->pixelformat = V4L2_PIX_FMT_HM12; s->pixelformat = V4L2_PIX_FMT_NV12_16L16;
s->vb_bytes_per_frame = cx->cxhdl.height * 720 * 3 / 2; s->vb_bytes_per_frame = cx->cxhdl.height * 720 * 3 / 2;
s->vb_bytes_per_line = 720; s->vb_bytes_per_line = 720;
} }
@ -324,7 +324,7 @@ static int cx18_prep_dev(struct cx18 *cx, int type)
/* User explicitly selected 0 buffers for these streams, so don't /* User explicitly selected 0 buffers for these streams, so don't
create them. */ create them. */
if (cx18_stream_info[type].dma != PCI_DMA_NONE && if (cx18_stream_info[type].dma != DMA_NONE &&
cx->stream_buffers[type] == 0) { cx->stream_buffers[type] == 0) {
CX18_INFO("Disabled %s device\n", cx18_stream_info[type].name); CX18_INFO("Disabled %s device\n", cx18_stream_info[type].name);
return 0; return 0;
@ -733,7 +733,7 @@ static void cx18_stream_configure_mdls(struct cx18_stream *s)
* Set the MDL size to the exact size needed for one frame. * Set the MDL size to the exact size needed for one frame.
* Use enough buffers per MDL to cover the MDL size * Use enough buffers per MDL to cover the MDL size
*/ */
if (s->pixelformat == V4L2_PIX_FMT_HM12) if (s->pixelformat == V4L2_PIX_FMT_NV12_16L16)
s->mdl_size = 720 * s->cx->cxhdl.height * 3 / 2; s->mdl_size = 720 * s->cx->cxhdl.height * 3 / 2;
else else
s->mdl_size = 720 * s->cx->cxhdl.height * 2; s->mdl_size = 720 * s->cx->cxhdl.height * 2;

View File

@ -550,7 +550,7 @@ struct cx23885_audio_dev *cx23885_audio_register(struct cx23885_dev *dev)
SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1,
THIS_MODULE, sizeof(struct cx23885_audio_dev), &card); THIS_MODULE, sizeof(struct cx23885_audio_dev), &card);
if (err < 0) if (err < 0)
goto error; goto error_msg;
chip = (struct cx23885_audio_dev *) card->private_data; chip = (struct cx23885_audio_dev *) card->private_data;
chip->dev = dev; chip->dev = dev;
@ -576,6 +576,7 @@ struct cx23885_audio_dev *cx23885_audio_register(struct cx23885_dev *dev)
error: error:
snd_card_free(card); snd_card_free(card);
error_msg:
pr_err("%s(): Failed to register analog audio adapter\n", pr_err("%s(): Failed to register analog audio adapter\n",
__func__); __func__);

View File

@ -180,8 +180,8 @@ static int ddb_probe(struct pci_dev *pdev,
pci_set_master(pdev); pci_set_master(pdev);
if (pci_set_dma_mask(pdev, DMA_BIT_MASK(64))) if (dma_set_mask(&pdev->dev, DMA_BIT_MASK(64)))
if (pci_set_dma_mask(pdev, DMA_BIT_MASK(32))) if (dma_set_mask(&pdev->dev, DMA_BIT_MASK(32)))
return -ENODEV; return -ENODEV;
dev = vzalloc(sizeof(*dev)); dev = vzalloc(sizeof(*dev));

View File

@ -29,6 +29,7 @@ static const struct cio2_sensor_config cio2_supported_sensors[] = {
static const struct cio2_property_names prop_names = { static const struct cio2_property_names prop_names = {
.clock_frequency = "clock-frequency", .clock_frequency = "clock-frequency",
.rotation = "rotation", .rotation = "rotation",
.orientation = "orientation",
.bus_type = "bus-type", .bus_type = "bus-type",
.data_lanes = "data-lanes", .data_lanes = "data-lanes",
.remote_endpoint = "remote-endpoint", .remote_endpoint = "remote-endpoint",
@ -72,11 +73,51 @@ out_free_buff:
return ret; return ret;
} }
static u32 cio2_bridge_parse_rotation(struct cio2_sensor *sensor)
{
switch (sensor->ssdb.degree) {
case CIO2_SENSOR_ROTATION_NORMAL:
return 0;
case CIO2_SENSOR_ROTATION_INVERTED:
return 180;
default:
dev_warn(&sensor->adev->dev,
"Unknown rotation %d. Assume 0 degree rotation\n",
sensor->ssdb.degree);
return 0;
}
}
static enum v4l2_fwnode_orientation cio2_bridge_parse_orientation(struct cio2_sensor *sensor)
{
switch (sensor->pld->panel) {
case ACPI_PLD_PANEL_FRONT:
return V4L2_FWNODE_ORIENTATION_FRONT;
case ACPI_PLD_PANEL_BACK:
return V4L2_FWNODE_ORIENTATION_BACK;
case ACPI_PLD_PANEL_TOP:
case ACPI_PLD_PANEL_LEFT:
case ACPI_PLD_PANEL_RIGHT:
case ACPI_PLD_PANEL_UNKNOWN:
return V4L2_FWNODE_ORIENTATION_EXTERNAL;
default:
dev_warn(&sensor->adev->dev, "Unknown _PLD panel value %d\n",
sensor->pld->panel);
return V4L2_FWNODE_ORIENTATION_EXTERNAL;
}
}
static void cio2_bridge_create_fwnode_properties( static void cio2_bridge_create_fwnode_properties(
struct cio2_sensor *sensor, struct cio2_sensor *sensor,
struct cio2_bridge *bridge, struct cio2_bridge *bridge,
const struct cio2_sensor_config *cfg) const struct cio2_sensor_config *cfg)
{ {
u32 rotation;
enum v4l2_fwnode_orientation orientation;
rotation = cio2_bridge_parse_rotation(sensor);
orientation = cio2_bridge_parse_orientation(sensor);
sensor->prop_names = prop_names; sensor->prop_names = prop_names;
sensor->local_ref[0] = SOFTWARE_NODE_REFERENCE(&sensor->swnodes[SWNODE_CIO2_ENDPOINT]); sensor->local_ref[0] = SOFTWARE_NODE_REFERENCE(&sensor->swnodes[SWNODE_CIO2_ENDPOINT]);
@ -85,9 +126,12 @@ static void cio2_bridge_create_fwnode_properties(
sensor->dev_properties[0] = PROPERTY_ENTRY_U32( sensor->dev_properties[0] = PROPERTY_ENTRY_U32(
sensor->prop_names.clock_frequency, sensor->prop_names.clock_frequency,
sensor->ssdb.mclkspeed); sensor->ssdb.mclkspeed);
sensor->dev_properties[1] = PROPERTY_ENTRY_U8( sensor->dev_properties[1] = PROPERTY_ENTRY_U32(
sensor->prop_names.rotation, sensor->prop_names.rotation,
sensor->ssdb.degree); rotation);
sensor->dev_properties[2] = PROPERTY_ENTRY_U32(
sensor->prop_names.orientation,
orientation);
sensor->ep_properties[0] = PROPERTY_ENTRY_U32( sensor->ep_properties[0] = PROPERTY_ENTRY_U32(
sensor->prop_names.bus_type, sensor->prop_names.bus_type,
@ -159,6 +203,7 @@ static void cio2_bridge_unregister_sensors(struct cio2_bridge *bridge)
for (i = 0; i < bridge->n_sensors; i++) { for (i = 0; i < bridge->n_sensors; i++) {
sensor = &bridge->sensors[i]; sensor = &bridge->sensors[i];
software_node_unregister_nodes(sensor->swnodes); software_node_unregister_nodes(sensor->swnodes);
ACPI_FREE(sensor->pld);
acpi_dev_put(sensor->adev); acpi_dev_put(sensor->adev);
} }
} }
@ -170,6 +215,7 @@ static int cio2_bridge_connect_sensor(const struct cio2_sensor_config *cfg,
struct fwnode_handle *fwnode; struct fwnode_handle *fwnode;
struct cio2_sensor *sensor; struct cio2_sensor *sensor;
struct acpi_device *adev; struct acpi_device *adev;
acpi_status status;
int ret; int ret;
for_each_acpi_dev_match(adev, cfg->hid, NULL, -1) { for_each_acpi_dev_match(adev, cfg->hid, NULL, -1) {
@ -191,11 +237,15 @@ static int cio2_bridge_connect_sensor(const struct cio2_sensor_config *cfg,
if (ret) if (ret)
goto err_put_adev; goto err_put_adev;
status = acpi_get_physical_device_location(adev->handle, &sensor->pld);
if (ACPI_FAILURE(status))
goto err_put_adev;
if (sensor->ssdb.lanes > CIO2_MAX_LANES) { if (sensor->ssdb.lanes > CIO2_MAX_LANES) {
dev_err(&adev->dev, dev_err(&adev->dev,
"Number of lanes in SSDB is invalid\n"); "Number of lanes in SSDB is invalid\n");
ret = -EINVAL; ret = -EINVAL;
goto err_put_adev; goto err_free_pld;
} }
cio2_bridge_create_fwnode_properties(sensor, bridge, cfg); cio2_bridge_create_fwnode_properties(sensor, bridge, cfg);
@ -203,7 +253,7 @@ static int cio2_bridge_connect_sensor(const struct cio2_sensor_config *cfg,
ret = software_node_register_nodes(sensor->swnodes); ret = software_node_register_nodes(sensor->swnodes);
if (ret) if (ret)
goto err_put_adev; goto err_free_pld;
fwnode = software_node_fwnode(&sensor->swnodes[ fwnode = software_node_fwnode(&sensor->swnodes[
SWNODE_SENSOR_HID]); SWNODE_SENSOR_HID]);
@ -225,6 +275,8 @@ static int cio2_bridge_connect_sensor(const struct cio2_sensor_config *cfg,
err_free_swnodes: err_free_swnodes:
software_node_unregister_nodes(sensor->swnodes); software_node_unregister_nodes(sensor->swnodes);
err_free_pld:
ACPI_FREE(sensor->pld);
err_put_adev: err_put_adev:
acpi_dev_put(adev); acpi_dev_put(adev);
return ret; return ret;

View File

@ -12,6 +12,10 @@
#define CIO2_MAX_LANES 4 #define CIO2_MAX_LANES 4
#define MAX_NUM_LINK_FREQS 3 #define MAX_NUM_LINK_FREQS 3
/* Values are educated guesses as we don't have a spec */
#define CIO2_SENSOR_ROTATION_NORMAL 0
#define CIO2_SENSOR_ROTATION_INVERTED 1
#define CIO2_SENSOR_CONFIG(_HID, _NR, ...) \ #define CIO2_SENSOR_CONFIG(_HID, _NR, ...) \
(const struct cio2_sensor_config) { \ (const struct cio2_sensor_config) { \
.hid = _HID, \ .hid = _HID, \
@ -80,6 +84,7 @@ struct cio2_sensor_ssdb {
struct cio2_property_names { struct cio2_property_names {
char clock_frequency[16]; char clock_frequency[16];
char rotation[9]; char rotation[9];
char orientation[12];
char bus_type[9]; char bus_type[9];
char data_lanes[11]; char data_lanes[11];
char remote_endpoint[16]; char remote_endpoint[16];
@ -106,9 +111,11 @@ struct cio2_sensor {
struct cio2_node_names node_names; struct cio2_node_names node_names;
struct cio2_sensor_ssdb ssdb; struct cio2_sensor_ssdb ssdb;
struct acpi_pld_info *pld;
struct cio2_property_names prop_names; struct cio2_property_names prop_names;
struct property_entry ep_properties[5]; struct property_entry ep_properties[5];
struct property_entry dev_properties[3]; struct property_entry dev_properties[4];
struct property_entry cio2_properties[3]; struct property_entry cio2_properties[3];
struct software_node_ref_args local_ref[1]; struct software_node_ref_args local_ref[1];
struct software_node_ref_args remote_ref[1]; struct software_node_ref_args remote_ref[1];

View File

@ -11,6 +11,7 @@
* et al. * et al.
*/ */
#include <linux/bitops.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/iopoll.h> #include <linux/iopoll.h>
@ -102,26 +103,29 @@ static inline u32 cio2_bytesperline(const unsigned int width)
static void cio2_fbpt_exit_dummy(struct cio2_device *cio2) static void cio2_fbpt_exit_dummy(struct cio2_device *cio2)
{ {
struct device *dev = &cio2->pci_dev->dev;
if (cio2->dummy_lop) { if (cio2->dummy_lop) {
dma_free_coherent(&cio2->pci_dev->dev, PAGE_SIZE, dma_free_coherent(dev, PAGE_SIZE, cio2->dummy_lop,
cio2->dummy_lop, cio2->dummy_lop_bus_addr); cio2->dummy_lop_bus_addr);
cio2->dummy_lop = NULL; cio2->dummy_lop = NULL;
} }
if (cio2->dummy_page) { if (cio2->dummy_page) {
dma_free_coherent(&cio2->pci_dev->dev, PAGE_SIZE, dma_free_coherent(dev, PAGE_SIZE, cio2->dummy_page,
cio2->dummy_page, cio2->dummy_page_bus_addr); cio2->dummy_page_bus_addr);
cio2->dummy_page = NULL; cio2->dummy_page = NULL;
} }
} }
static int cio2_fbpt_init_dummy(struct cio2_device *cio2) static int cio2_fbpt_init_dummy(struct cio2_device *cio2)
{ {
struct device *dev = &cio2->pci_dev->dev;
unsigned int i; unsigned int i;
cio2->dummy_page = dma_alloc_coherent(&cio2->pci_dev->dev, PAGE_SIZE, cio2->dummy_page = dma_alloc_coherent(dev, PAGE_SIZE,
&cio2->dummy_page_bus_addr, &cio2->dummy_page_bus_addr,
GFP_KERNEL); GFP_KERNEL);
cio2->dummy_lop = dma_alloc_coherent(&cio2->pci_dev->dev, PAGE_SIZE, cio2->dummy_lop = dma_alloc_coherent(dev, PAGE_SIZE,
&cio2->dummy_lop_bus_addr, &cio2->dummy_lop_bus_addr,
GFP_KERNEL); GFP_KERNEL);
if (!cio2->dummy_page || !cio2->dummy_lop) { if (!cio2->dummy_page || !cio2->dummy_lop) {
@ -497,6 +501,7 @@ static int cio2_hw_init(struct cio2_device *cio2, struct cio2_queue *q)
static void cio2_hw_exit(struct cio2_device *cio2, struct cio2_queue *q) static void cio2_hw_exit(struct cio2_device *cio2, struct cio2_queue *q)
{ {
struct device *dev = &cio2->pci_dev->dev;
void __iomem *const base = cio2->base; void __iomem *const base = cio2->base;
unsigned int i; unsigned int i;
u32 value; u32 value;
@ -514,8 +519,7 @@ static void cio2_hw_exit(struct cio2_device *cio2, struct cio2_queue *q)
value, value & CIO2_CDMAC0_DMA_HALTED, value, value & CIO2_CDMAC0_DMA_HALTED,
4000, 2000000); 4000, 2000000);
if (ret) if (ret)
dev_err(&cio2->pci_dev->dev, dev_err(dev, "DMA %i can not be halted\n", CIO2_DMA_CHAN);
"DMA %i can not be halted\n", CIO2_DMA_CHAN);
for (i = 0; i < CIO2_NUM_PORTS; i++) { for (i = 0; i < CIO2_NUM_PORTS; i++) {
writel(readl(base + CIO2_REG_PXM_FRF_CFG(i)) | writel(readl(base + CIO2_REG_PXM_FRF_CFG(i)) |
@ -539,8 +543,7 @@ static void cio2_buffer_done(struct cio2_device *cio2, unsigned int dma_chan)
entry = &q->fbpt[q->bufs_first * CIO2_MAX_LOPS]; entry = &q->fbpt[q->bufs_first * CIO2_MAX_LOPS];
if (entry->first_entry.ctrl & CIO2_FBPT_CTRL_VALID) { if (entry->first_entry.ctrl & CIO2_FBPT_CTRL_VALID) {
dev_warn(&cio2->pci_dev->dev, dev_warn(dev, "no ready buffers found on DMA channel %u\n",
"no ready buffers found on DMA channel %u\n",
dma_chan); dma_chan);
return; return;
} }
@ -557,8 +560,7 @@ static void cio2_buffer_done(struct cio2_device *cio2, unsigned int dma_chan)
q->bufs[q->bufs_first] = NULL; q->bufs[q->bufs_first] = NULL;
atomic_dec(&q->bufs_queued); atomic_dec(&q->bufs_queued);
dev_dbg(&cio2->pci_dev->dev, dev_dbg(dev, "buffer %i done\n", b->vbb.vb2_buf.index);
"buffer %i done\n", b->vbb.vb2_buf.index);
b->vbb.vb2_buf.timestamp = ns; b->vbb.vb2_buf.timestamp = ns;
b->vbb.field = V4L2_FIELD_NONE; b->vbb.field = V4L2_FIELD_NONE;
@ -612,6 +614,20 @@ static const char *const cio2_irq_errs[] = {
"non-matching Long Packet stalled", "non-matching Long Packet stalled",
}; };
static void cio2_irq_log_irq_errs(struct device *dev, u8 port, u32 status)
{
unsigned long csi2_status = status;
unsigned int i;
for_each_set_bit(i, &csi2_status, ARRAY_SIZE(cio2_irq_errs))
dev_err(dev, "CSI-2 receiver port %i: %s\n",
port, cio2_irq_errs[i]);
if (fls_long(csi2_status) >= ARRAY_SIZE(cio2_irq_errs))
dev_warn(dev, "unknown CSI2 error 0x%lx on port %i\n",
csi2_status, port);
}
static const char *const cio2_port_errs[] = { static const char *const cio2_port_errs[] = {
"ECC recoverable", "ECC recoverable",
"DPHY not recoverable", "DPHY not recoverable",
@ -622,10 +638,19 @@ static const char *const cio2_port_errs[] = {
"PKT2LONG", "PKT2LONG",
}; };
static void cio2_irq_log_port_errs(struct device *dev, u8 port, u32 status)
{
unsigned long port_status = status;
unsigned int i;
for_each_set_bit(i, &port_status, ARRAY_SIZE(cio2_port_errs))
dev_err(dev, "port %i error %s\n", port, cio2_port_errs[i]);
}
static void cio2_irq_handle_once(struct cio2_device *cio2, u32 int_status) static void cio2_irq_handle_once(struct cio2_device *cio2, u32 int_status)
{ {
void __iomem *const base = cio2->base;
struct device *dev = &cio2->pci_dev->dev; struct device *dev = &cio2->pci_dev->dev;
void __iomem *const base = cio2->base;
if (int_status & CIO2_INT_IOOE) { if (int_status & CIO2_INT_IOOE) {
/* /*
@ -687,59 +712,32 @@ static void cio2_irq_handle_once(struct cio2_device *cio2, u32 int_status)
if (int_status & (CIO2_INT_IOIE | CIO2_INT_IOIRQ)) { if (int_status & (CIO2_INT_IOIE | CIO2_INT_IOIRQ)) {
/* CSI2 receiver (error) interrupt */ /* CSI2 receiver (error) interrupt */
u32 ie_status, ie_clear;
unsigned int port; unsigned int port;
u32 ie_status;
ie_clear = readl(base + CIO2_REG_INT_STS_EXT_IE); ie_status = readl(base + CIO2_REG_INT_STS_EXT_IE);
ie_status = ie_clear;
for (port = 0; port < CIO2_NUM_PORTS; port++) { for (port = 0; port < CIO2_NUM_PORTS; port++) {
u32 port_status = (ie_status >> (port * 8)) & 0xff; u32 port_status = (ie_status >> (port * 8)) & 0xff;
u32 err_mask = BIT_MASK(ARRAY_SIZE(cio2_port_errs)) - 1;
void __iomem *const csi_rx_base =
base + CIO2_REG_PIPE_BASE(port);
unsigned int i;
while (port_status & err_mask) { cio2_irq_log_port_errs(dev, port, port_status);
i = ffs(port_status) - 1;
dev_err(dev, "port %i error %s\n",
port, cio2_port_errs[i]);
ie_status &= ~BIT(port * 8 + i);
port_status &= ~BIT(i);
}
if (ie_status & CIO2_INT_EXT_IE_IRQ(port)) { if (ie_status & CIO2_INT_EXT_IE_IRQ(port)) {
u32 csi2_status, csi2_clear; void __iomem *csi_rx_base =
base + CIO2_REG_PIPE_BASE(port);
u32 csi2_status;
csi2_status = readl(csi_rx_base + csi2_status = readl(csi_rx_base +
CIO2_REG_IRQCTRL_STATUS); CIO2_REG_IRQCTRL_STATUS);
csi2_clear = csi2_status;
err_mask =
BIT_MASK(ARRAY_SIZE(cio2_irq_errs)) - 1;
while (csi2_status & err_mask) { cio2_irq_log_irq_errs(dev, port, csi2_status);
i = ffs(csi2_status) - 1;
dev_err(dev,
"CSI-2 receiver port %i: %s\n",
port, cio2_irq_errs[i]);
csi2_status &= ~BIT(i);
}
writel(csi2_clear, writel(csi2_status,
csi_rx_base + CIO2_REG_IRQCTRL_CLEAR); csi_rx_base + CIO2_REG_IRQCTRL_CLEAR);
if (csi2_status)
dev_warn(dev,
"unknown CSI2 error 0x%x on port %i\n",
csi2_status, port);
ie_status &= ~CIO2_INT_EXT_IE_IRQ(port);
} }
} }
writel(ie_clear, base + CIO2_REG_INT_STS_EXT_IE); writel(ie_status, base + CIO2_REG_INT_STS_EXT_IE);
if (ie_status)
dev_warn(dev, "unknown interrupt 0x%x on IE\n",
ie_status);
int_status &= ~(CIO2_INT_IOIE | CIO2_INT_IOIRQ); int_status &= ~(CIO2_INT_IOIE | CIO2_INT_IOIRQ);
} }
@ -795,16 +793,21 @@ static int cio2_vb2_queue_setup(struct vb2_queue *vq,
struct device *alloc_devs[]) struct device *alloc_devs[])
{ {
struct cio2_device *cio2 = vb2_get_drv_priv(vq); struct cio2_device *cio2 = vb2_get_drv_priv(vq);
struct device *dev = &cio2->pci_dev->dev;
struct cio2_queue *q = vb2q_to_cio2_queue(vq); struct cio2_queue *q = vb2q_to_cio2_queue(vq);
unsigned int i; unsigned int i;
*num_planes = q->format.num_planes; if (*num_planes && *num_planes < q->format.num_planes)
return -EINVAL;
for (i = 0; i < *num_planes; ++i) { for (i = 0; i < q->format.num_planes; ++i) {
if (*num_planes && sizes[i] < q->format.plane_fmt[i].sizeimage)
return -EINVAL;
sizes[i] = q->format.plane_fmt[i].sizeimage; sizes[i] = q->format.plane_fmt[i].sizeimage;
alloc_devs[i] = &cio2->pci_dev->dev; alloc_devs[i] = dev;
} }
*num_planes = q->format.num_planes;
*num_buffers = clamp_val(*num_buffers, 1, CIO2_MAX_BUFFERS); *num_buffers = clamp_val(*num_buffers, 1, CIO2_MAX_BUFFERS);
/* Initialize buffer queue */ /* Initialize buffer queue */
@ -824,8 +827,7 @@ static int cio2_vb2_buf_init(struct vb2_buffer *vb)
{ {
struct cio2_device *cio2 = vb2_get_drv_priv(vb->vb2_queue); struct cio2_device *cio2 = vb2_get_drv_priv(vb->vb2_queue);
struct device *dev = &cio2->pci_dev->dev; struct device *dev = &cio2->pci_dev->dev;
struct cio2_buffer *b = struct cio2_buffer *b = to_cio2_buffer(vb);
container_of(vb, struct cio2_buffer, vbb.vb2_buf);
unsigned int pages = PFN_UP(vb->planes[0].length); unsigned int pages = PFN_UP(vb->planes[0].length);
unsigned int lops = DIV_ROUND_UP(pages + 1, CIO2_LOP_ENTRIES); unsigned int lops = DIV_ROUND_UP(pages + 1, CIO2_LOP_ENTRIES);
struct sg_table *sg; struct sg_table *sg;
@ -879,17 +881,17 @@ fail:
static void cio2_vb2_buf_queue(struct vb2_buffer *vb) static void cio2_vb2_buf_queue(struct vb2_buffer *vb)
{ {
struct cio2_device *cio2 = vb2_get_drv_priv(vb->vb2_queue); struct cio2_device *cio2 = vb2_get_drv_priv(vb->vb2_queue);
struct device *dev = &cio2->pci_dev->dev;
struct cio2_queue *q = struct cio2_queue *q =
container_of(vb->vb2_queue, struct cio2_queue, vbq); container_of(vb->vb2_queue, struct cio2_queue, vbq);
struct cio2_buffer *b = struct cio2_buffer *b = to_cio2_buffer(vb);
container_of(vb, struct cio2_buffer, vbb.vb2_buf);
struct cio2_fbpt_entry *entry; struct cio2_fbpt_entry *entry;
unsigned long flags; unsigned long flags;
unsigned int i, j, next = q->bufs_next; unsigned int i, j, next = q->bufs_next;
int bufs_queued = atomic_inc_return(&q->bufs_queued); int bufs_queued = atomic_inc_return(&q->bufs_queued);
u32 fbpt_rp; u32 fbpt_rp;
dev_dbg(&cio2->pci_dev->dev, "queue buffer %d\n", vb->index); dev_dbg(dev, "queue buffer %d\n", vb->index);
/* /*
* This code queues the buffer to the CIO2 DMA engine, which starts * This code queues the buffer to the CIO2 DMA engine, which starts
@ -940,12 +942,12 @@ static void cio2_vb2_buf_queue(struct vb2_buffer *vb)
return; return;
} }
dev_dbg(&cio2->pci_dev->dev, "entry %i was full!\n", next); dev_dbg(dev, "entry %i was full!\n", next);
next = (next + 1) % CIO2_MAX_BUFFERS; next = (next + 1) % CIO2_MAX_BUFFERS;
} }
local_irq_restore(flags); local_irq_restore(flags);
dev_err(&cio2->pci_dev->dev, "error: all cio2 entries were full!\n"); dev_err(dev, "error: all cio2 entries were full!\n");
atomic_dec(&q->bufs_queued); atomic_dec(&q->bufs_queued);
vb2_buffer_done(vb, VB2_BUF_STATE_ERROR); vb2_buffer_done(vb, VB2_BUF_STATE_ERROR);
} }
@ -954,14 +956,14 @@ static void cio2_vb2_buf_queue(struct vb2_buffer *vb)
static void cio2_vb2_buf_cleanup(struct vb2_buffer *vb) static void cio2_vb2_buf_cleanup(struct vb2_buffer *vb)
{ {
struct cio2_device *cio2 = vb2_get_drv_priv(vb->vb2_queue); struct cio2_device *cio2 = vb2_get_drv_priv(vb->vb2_queue);
struct cio2_buffer *b = struct device *dev = &cio2->pci_dev->dev;
container_of(vb, struct cio2_buffer, vbb.vb2_buf); struct cio2_buffer *b = to_cio2_buffer(vb);
unsigned int i; unsigned int i;
/* Free LOP table */ /* Free LOP table */
for (i = 0; i < CIO2_MAX_LOPS; i++) { for (i = 0; i < CIO2_MAX_LOPS; i++) {
if (b->lop[i]) if (b->lop[i])
dma_free_coherent(&cio2->pci_dev->dev, PAGE_SIZE, dma_free_coherent(dev, PAGE_SIZE,
b->lop[i], b->lop_bus_addr[i]); b->lop[i], b->lop_bus_addr[i]);
} }
} }
@ -970,14 +972,15 @@ static int cio2_vb2_start_streaming(struct vb2_queue *vq, unsigned int count)
{ {
struct cio2_queue *q = vb2q_to_cio2_queue(vq); struct cio2_queue *q = vb2q_to_cio2_queue(vq);
struct cio2_device *cio2 = vb2_get_drv_priv(vq); struct cio2_device *cio2 = vb2_get_drv_priv(vq);
struct device *dev = &cio2->pci_dev->dev;
int r; int r;
cio2->cur_queue = q; cio2->cur_queue = q;
atomic_set(&q->frame_sequence, 0); atomic_set(&q->frame_sequence, 0);
r = pm_runtime_resume_and_get(&cio2->pci_dev->dev); r = pm_runtime_resume_and_get(dev);
if (r < 0) { if (r < 0) {
dev_info(&cio2->pci_dev->dev, "failed to set power %d\n", r); dev_info(dev, "failed to set power %d\n", r);
return r; return r;
} }
@ -1003,9 +1006,9 @@ fail_csi2_subdev:
fail_hw: fail_hw:
media_pipeline_stop(&q->vdev.entity); media_pipeline_stop(&q->vdev.entity);
fail_pipeline: fail_pipeline:
dev_dbg(&cio2->pci_dev->dev, "failed to start streaming (%d)\n", r); dev_dbg(dev, "failed to start streaming (%d)\n", r);
cio2_vb2_return_all_buffers(q, VB2_BUF_STATE_QUEUED); cio2_vb2_return_all_buffers(q, VB2_BUF_STATE_QUEUED);
pm_runtime_put(&cio2->pci_dev->dev); pm_runtime_put(dev);
return r; return r;
} }
@ -1014,16 +1017,16 @@ static void cio2_vb2_stop_streaming(struct vb2_queue *vq)
{ {
struct cio2_queue *q = vb2q_to_cio2_queue(vq); struct cio2_queue *q = vb2q_to_cio2_queue(vq);
struct cio2_device *cio2 = vb2_get_drv_priv(vq); struct cio2_device *cio2 = vb2_get_drv_priv(vq);
struct device *dev = &cio2->pci_dev->dev;
if (v4l2_subdev_call(q->sensor, video, s_stream, 0)) if (v4l2_subdev_call(q->sensor, video, s_stream, 0))
dev_err(&cio2->pci_dev->dev, dev_err(dev, "failed to stop sensor streaming\n");
"failed to stop sensor streaming\n");
cio2_hw_exit(cio2, q); cio2_hw_exit(cio2, q);
synchronize_irq(cio2->pci_dev->irq); synchronize_irq(cio2->pci_dev->irq);
cio2_vb2_return_all_buffers(q, VB2_BUF_STATE_ERROR); cio2_vb2_return_all_buffers(q, VB2_BUF_STATE_ERROR);
media_pipeline_stop(&q->vdev.entity); media_pipeline_stop(&q->vdev.entity);
pm_runtime_put(&cio2->pci_dev->dev); pm_runtime_put(dev);
cio2->streaming = false; cio2->streaming = false;
} }
@ -1311,16 +1314,16 @@ static int cio2_subdev_link_validate_get_format(struct media_pad *pad,
static int cio2_video_link_validate(struct media_link *link) static int cio2_video_link_validate(struct media_link *link)
{ {
struct video_device *vd = container_of(link->sink->entity, struct media_entity *entity = link->sink->entity;
struct video_device, entity); struct video_device *vd = media_entity_to_video_device(entity);
struct cio2_queue *q = container_of(vd, struct cio2_queue, vdev); struct cio2_queue *q = container_of(vd, struct cio2_queue, vdev);
struct cio2_device *cio2 = video_get_drvdata(vd); struct cio2_device *cio2 = video_get_drvdata(vd);
struct device *dev = &cio2->pci_dev->dev;
struct v4l2_subdev_format source_fmt; struct v4l2_subdev_format source_fmt;
int ret; int ret;
if (!media_entity_remote_pad(link->sink->entity->pads)) { if (!media_entity_remote_pad(entity->pads)) {
dev_info(&cio2->pci_dev->dev, dev_info(dev, "video node %s pad not connected\n", vd->name);
"video node %s pad not connected\n", vd->name);
return -ENOTCONN; return -ENOTCONN;
} }
@ -1330,8 +1333,7 @@ static int cio2_video_link_validate(struct media_link *link)
if (source_fmt.format.width != q->format.width || if (source_fmt.format.width != q->format.width ||
source_fmt.format.height != q->format.height) { source_fmt.format.height != q->format.height) {
dev_err(&cio2->pci_dev->dev, dev_err(dev, "Wrong width or height %ux%u (%ux%u expected)\n",
"Wrong width or height %ux%u (%ux%u expected)\n",
q->format.width, q->format.height, q->format.width, q->format.height,
source_fmt.format.width, source_fmt.format.height); source_fmt.format.width, source_fmt.format.height);
return -EINVAL; return -EINVAL;
@ -1371,15 +1373,15 @@ struct sensor_async_subdev {
struct csi2_bus_info csi2; struct csi2_bus_info csi2;
}; };
#define to_sensor_asd(asd) container_of(asd, struct sensor_async_subdev, asd)
/* The .bound() notifier callback when a match is found */ /* The .bound() notifier callback when a match is found */
static int cio2_notifier_bound(struct v4l2_async_notifier *notifier, static int cio2_notifier_bound(struct v4l2_async_notifier *notifier,
struct v4l2_subdev *sd, struct v4l2_subdev *sd,
struct v4l2_async_subdev *asd) struct v4l2_async_subdev *asd)
{ {
struct cio2_device *cio2 = container_of(notifier, struct cio2_device *cio2 = to_cio2_device(notifier);
struct cio2_device, notifier); struct sensor_async_subdev *s_asd = to_sensor_asd(asd);
struct sensor_async_subdev *s_asd = container_of(asd,
struct sensor_async_subdev, asd);
struct cio2_queue *q; struct cio2_queue *q;
if (cio2->queue[s_asd->csi2.port].sensor) if (cio2->queue[s_asd->csi2.port].sensor)
@ -1399,10 +1401,8 @@ static void cio2_notifier_unbind(struct v4l2_async_notifier *notifier,
struct v4l2_subdev *sd, struct v4l2_subdev *sd,
struct v4l2_async_subdev *asd) struct v4l2_async_subdev *asd)
{ {
struct cio2_device *cio2 = container_of(notifier, struct cio2_device *cio2 = to_cio2_device(notifier);
struct cio2_device, notifier); struct sensor_async_subdev *s_asd = to_sensor_asd(asd);
struct sensor_async_subdev *s_asd = container_of(asd,
struct sensor_async_subdev, asd);
cio2->queue[s_asd->csi2.port].sensor = NULL; cio2->queue[s_asd->csi2.port].sensor = NULL;
} }
@ -1410,8 +1410,8 @@ static void cio2_notifier_unbind(struct v4l2_async_notifier *notifier,
/* .complete() is called after all subdevices have been located */ /* .complete() is called after all subdevices have been located */
static int cio2_notifier_complete(struct v4l2_async_notifier *notifier) static int cio2_notifier_complete(struct v4l2_async_notifier *notifier)
{ {
struct cio2_device *cio2 = container_of(notifier, struct cio2_device, struct cio2_device *cio2 = to_cio2_device(notifier);
notifier); struct device *dev = &cio2->pci_dev->dev;
struct sensor_async_subdev *s_asd; struct sensor_async_subdev *s_asd;
struct v4l2_async_subdev *asd; struct v4l2_async_subdev *asd;
struct cio2_queue *q; struct cio2_queue *q;
@ -1419,7 +1419,7 @@ static int cio2_notifier_complete(struct v4l2_async_notifier *notifier)
int ret; int ret;
list_for_each_entry(asd, &cio2->notifier.asd_list, asd_list) { list_for_each_entry(asd, &cio2->notifier.asd_list, asd_list) {
s_asd = container_of(asd, struct sensor_async_subdev, asd); s_asd = to_sensor_asd(asd);
q = &cio2->queue[s_asd->csi2.port]; q = &cio2->queue[s_asd->csi2.port];
for (pad = 0; pad < q->sensor->entity.num_pads; pad++) for (pad = 0; pad < q->sensor->entity.num_pads; pad++)
@ -1428,8 +1428,7 @@ static int cio2_notifier_complete(struct v4l2_async_notifier *notifier)
break; break;
if (pad == q->sensor->entity.num_pads) { if (pad == q->sensor->entity.num_pads) {
dev_err(&cio2->pci_dev->dev, dev_err(dev, "failed to find src pad for %s\n",
"failed to find src pad for %s\n",
q->sensor->name); q->sensor->name);
return -ENXIO; return -ENXIO;
} }
@ -1439,8 +1438,7 @@ static int cio2_notifier_complete(struct v4l2_async_notifier *notifier)
&q->subdev.entity, CIO2_PAD_SINK, &q->subdev.entity, CIO2_PAD_SINK,
0); 0);
if (ret) { if (ret) {
dev_err(&cio2->pci_dev->dev, dev_err(dev, "failed to create link for %s\n",
"failed to create link for %s\n",
q->sensor->name); q->sensor->name);
return ret; return ret;
} }
@ -1457,6 +1455,7 @@ static const struct v4l2_async_notifier_operations cio2_async_ops = {
static int cio2_parse_firmware(struct cio2_device *cio2) static int cio2_parse_firmware(struct cio2_device *cio2)
{ {
struct device *dev = &cio2->pci_dev->dev;
unsigned int i; unsigned int i;
int ret; int ret;
@ -1467,10 +1466,8 @@ static int cio2_parse_firmware(struct cio2_device *cio2)
struct sensor_async_subdev *s_asd; struct sensor_async_subdev *s_asd;
struct fwnode_handle *ep; struct fwnode_handle *ep;
ep = fwnode_graph_get_endpoint_by_id( ep = fwnode_graph_get_endpoint_by_id(dev_fwnode(dev), i, 0,
dev_fwnode(&cio2->pci_dev->dev), i, 0, FWNODE_GRAPH_ENDPOINT_NEXT);
FWNODE_GRAPH_ENDPOINT_NEXT);
if (!ep) if (!ep)
continue; continue;
@ -1478,8 +1475,9 @@ static int cio2_parse_firmware(struct cio2_device *cio2)
if (ret) if (ret)
goto err_parse; goto err_parse;
s_asd = v4l2_async_notifier_add_fwnode_remote_subdev( s_asd = v4l2_async_nf_add_fwnode_remote(&cio2->notifier, ep,
&cio2->notifier, ep, struct sensor_async_subdev); struct
sensor_async_subdev);
if (IS_ERR(s_asd)) { if (IS_ERR(s_asd)) {
ret = PTR_ERR(s_asd); ret = PTR_ERR(s_asd);
goto err_parse; goto err_parse;
@ -1502,10 +1500,9 @@ err_parse:
* suspend. * suspend.
*/ */
cio2->notifier.ops = &cio2_async_ops; cio2->notifier.ops = &cio2_async_ops;
ret = v4l2_async_notifier_register(&cio2->v4l2_dev, &cio2->notifier); ret = v4l2_async_nf_register(&cio2->v4l2_dev, &cio2->notifier);
if (ret) if (ret)
dev_err(&cio2->pci_dev->dev, dev_err(dev, "failed to register async notifier : %d\n", ret);
"failed to register async notifier : %d\n", ret);
return ret; return ret;
} }
@ -1524,7 +1521,7 @@ static int cio2_queue_init(struct cio2_device *cio2, struct cio2_queue *q)
static const u32 default_width = 1936; static const u32 default_width = 1936;
static const u32 default_height = 1096; static const u32 default_height = 1096;
const struct ipu3_cio2_fmt dflt_fmt = formats[0]; const struct ipu3_cio2_fmt dflt_fmt = formats[0];
struct device *dev = &cio2->pci_dev->dev;
struct video_device *vdev = &q->vdev; struct video_device *vdev = &q->vdev;
struct vb2_queue *vbq = &q->vbq; struct vb2_queue *vbq = &q->vbq;
struct v4l2_subdev *subdev = &q->subdev; struct v4l2_subdev *subdev = &q->subdev;
@ -1566,8 +1563,7 @@ static int cio2_queue_init(struct cio2_device *cio2, struct cio2_queue *q)
subdev->internal_ops = &cio2_subdev_internal_ops; subdev->internal_ops = &cio2_subdev_internal_ops;
r = media_entity_pads_init(&subdev->entity, CIO2_PADS, q->subdev_pads); r = media_entity_pads_init(&subdev->entity, CIO2_PADS, q->subdev_pads);
if (r) { if (r) {
dev_err(&cio2->pci_dev->dev, dev_err(dev, "failed initialize subdev media entity (%d)\n", r);
"failed initialize subdev media entity (%d)\n", r);
goto fail_subdev_media_entity; goto fail_subdev_media_entity;
} }
@ -1575,8 +1571,8 @@ static int cio2_queue_init(struct cio2_device *cio2, struct cio2_queue *q)
vdev->entity.ops = &cio2_video_entity_ops; vdev->entity.ops = &cio2_video_entity_ops;
r = media_entity_pads_init(&vdev->entity, 1, &q->vdev_pad); r = media_entity_pads_init(&vdev->entity, 1, &q->vdev_pad);
if (r) { if (r) {
dev_err(&cio2->pci_dev->dev, dev_err(dev, "failed initialize videodev media entity (%d)\n",
"failed initialize videodev media entity (%d)\n", r); r);
goto fail_vdev_media_entity; goto fail_vdev_media_entity;
} }
@ -1590,8 +1586,7 @@ static int cio2_queue_init(struct cio2_device *cio2, struct cio2_queue *q)
v4l2_set_subdevdata(subdev, cio2); v4l2_set_subdevdata(subdev, cio2);
r = v4l2_device_register_subdev(&cio2->v4l2_dev, subdev); r = v4l2_device_register_subdev(&cio2->v4l2_dev, subdev);
if (r) { if (r) {
dev_err(&cio2->pci_dev->dev, dev_err(dev, "failed initialize subdev (%d)\n", r);
"failed initialize subdev (%d)\n", r);
goto fail_subdev; goto fail_subdev;
} }
@ -1607,8 +1602,7 @@ static int cio2_queue_init(struct cio2_device *cio2, struct cio2_queue *q)
vbq->lock = &q->lock; vbq->lock = &q->lock;
r = vb2_queue_init(vbq); r = vb2_queue_init(vbq);
if (r) { if (r) {
dev_err(&cio2->pci_dev->dev, dev_err(dev, "failed to initialize videobuf2 queue (%d)\n", r);
"failed to initialize videobuf2 queue (%d)\n", r);
goto fail_subdev; goto fail_subdev;
} }
@ -1625,8 +1619,7 @@ static int cio2_queue_init(struct cio2_device *cio2, struct cio2_queue *q)
video_set_drvdata(vdev, cio2); video_set_drvdata(vdev, cio2);
r = video_register_device(vdev, VFL_TYPE_VIDEO, -1); r = video_register_device(vdev, VFL_TYPE_VIDEO, -1);
if (r) { if (r) {
dev_err(&cio2->pci_dev->dev, dev_err(dev, "failed to register video device (%d)\n", r);
"failed to register video device (%d)\n", r);
goto fail_vdev; goto fail_vdev;
} }
@ -1648,7 +1641,7 @@ fail_subdev:
fail_vdev_media_entity: fail_vdev_media_entity:
media_entity_cleanup(&subdev->entity); media_entity_cleanup(&subdev->entity);
fail_subdev_media_entity: fail_subdev_media_entity:
cio2_fbpt_exit(q, &cio2->pci_dev->dev); cio2_fbpt_exit(q, dev);
fail_fbpt: fail_fbpt:
mutex_destroy(&q->subdev_lock); mutex_destroy(&q->subdev_lock);
mutex_destroy(&q->lock); mutex_destroy(&q->lock);
@ -1715,11 +1708,12 @@ static int cio2_check_fwnode_graph(struct fwnode_handle *fwnode)
static int cio2_pci_probe(struct pci_dev *pci_dev, static int cio2_pci_probe(struct pci_dev *pci_dev,
const struct pci_device_id *id) const struct pci_device_id *id)
{ {
struct fwnode_handle *fwnode = dev_fwnode(&pci_dev->dev); struct device *dev = &pci_dev->dev;
struct fwnode_handle *fwnode = dev_fwnode(dev);
struct cio2_device *cio2; struct cio2_device *cio2;
int r; int r;
cio2 = devm_kzalloc(&pci_dev->dev, sizeof(*cio2), GFP_KERNEL); cio2 = devm_kzalloc(dev, sizeof(*cio2), GFP_KERNEL);
if (!cio2) if (!cio2)
return -ENOMEM; return -ENOMEM;
cio2->pci_dev = pci_dev; cio2->pci_dev = pci_dev;
@ -1732,7 +1726,7 @@ static int cio2_pci_probe(struct pci_dev *pci_dev,
r = cio2_check_fwnode_graph(fwnode); r = cio2_check_fwnode_graph(fwnode);
if (r) { if (r) {
if (fwnode && !IS_ERR_OR_NULL(fwnode->secondary)) { if (fwnode && !IS_ERR_OR_NULL(fwnode->secondary)) {
dev_err(&pci_dev->dev, "fwnode graph has no endpoints connected\n"); dev_err(dev, "fwnode graph has no endpoints connected\n");
return -EINVAL; return -EINVAL;
} }
@ -1743,16 +1737,16 @@ static int cio2_pci_probe(struct pci_dev *pci_dev,
r = pcim_enable_device(pci_dev); r = pcim_enable_device(pci_dev);
if (r) { if (r) {
dev_err(&pci_dev->dev, "failed to enable device (%d)\n", r); dev_err(dev, "failed to enable device (%d)\n", r);
return r; return r;
} }
dev_info(&pci_dev->dev, "device 0x%x (rev: 0x%x)\n", dev_info(dev, "device 0x%x (rev: 0x%x)\n",
pci_dev->device, pci_dev->revision); pci_dev->device, pci_dev->revision);
r = pcim_iomap_regions(pci_dev, 1 << CIO2_PCI_BAR, pci_name(pci_dev)); r = pcim_iomap_regions(pci_dev, 1 << CIO2_PCI_BAR, pci_name(pci_dev));
if (r) { if (r) {
dev_err(&pci_dev->dev, "failed to remap I/O memory (%d)\n", r); dev_err(dev, "failed to remap I/O memory (%d)\n", r);
return -ENODEV; return -ENODEV;
} }
@ -1762,15 +1756,15 @@ static int cio2_pci_probe(struct pci_dev *pci_dev,
pci_set_master(pci_dev); pci_set_master(pci_dev);
r = pci_set_dma_mask(pci_dev, CIO2_DMA_MASK); r = dma_set_mask(&pci_dev->dev, CIO2_DMA_MASK);
if (r) { if (r) {
dev_err(&pci_dev->dev, "failed to set DMA mask (%d)\n", r); dev_err(dev, "failed to set DMA mask (%d)\n", r);
return -ENODEV; return -ENODEV;
} }
r = pci_enable_msi(pci_dev); r = pci_enable_msi(pci_dev);
if (r) { if (r) {
dev_err(&pci_dev->dev, "failed to enable MSI (%d)\n", r); dev_err(dev, "failed to enable MSI (%d)\n", r);
return r; return r;
} }
@ -1780,7 +1774,7 @@ static int cio2_pci_probe(struct pci_dev *pci_dev,
mutex_init(&cio2->lock); mutex_init(&cio2->lock);
cio2->media_dev.dev = &cio2->pci_dev->dev; cio2->media_dev.dev = dev;
strscpy(cio2->media_dev.model, CIO2_DEVICE_NAME, strscpy(cio2->media_dev.model, CIO2_DEVICE_NAME,
sizeof(cio2->media_dev.model)); sizeof(cio2->media_dev.model));
snprintf(cio2->media_dev.bus_info, sizeof(cio2->media_dev.bus_info), snprintf(cio2->media_dev.bus_info, sizeof(cio2->media_dev.bus_info),
@ -1793,10 +1787,9 @@ static int cio2_pci_probe(struct pci_dev *pci_dev,
goto fail_mutex_destroy; goto fail_mutex_destroy;
cio2->v4l2_dev.mdev = &cio2->media_dev; cio2->v4l2_dev.mdev = &cio2->media_dev;
r = v4l2_device_register(&pci_dev->dev, &cio2->v4l2_dev); r = v4l2_device_register(dev, &cio2->v4l2_dev);
if (r) { if (r) {
dev_err(&pci_dev->dev, dev_err(dev, "failed to register V4L2 device (%d)\n", r);
"failed to register V4L2 device (%d)\n", r);
goto fail_media_device_unregister; goto fail_media_device_unregister;
} }
@ -1804,28 +1797,28 @@ static int cio2_pci_probe(struct pci_dev *pci_dev,
if (r) if (r)
goto fail_v4l2_device_unregister; goto fail_v4l2_device_unregister;
v4l2_async_notifier_init(&cio2->notifier); v4l2_async_nf_init(&cio2->notifier);
/* Register notifier for subdevices we care */ /* Register notifier for subdevices we care */
r = cio2_parse_firmware(cio2); r = cio2_parse_firmware(cio2);
if (r) if (r)
goto fail_clean_notifier; goto fail_clean_notifier;
r = devm_request_irq(&pci_dev->dev, pci_dev->irq, cio2_irq, r = devm_request_irq(dev, pci_dev->irq, cio2_irq, IRQF_SHARED,
IRQF_SHARED, CIO2_NAME, cio2); CIO2_NAME, cio2);
if (r) { if (r) {
dev_err(&pci_dev->dev, "failed to request IRQ (%d)\n", r); dev_err(dev, "failed to request IRQ (%d)\n", r);
goto fail_clean_notifier; goto fail_clean_notifier;
} }
pm_runtime_put_noidle(&pci_dev->dev); pm_runtime_put_noidle(dev);
pm_runtime_allow(&pci_dev->dev); pm_runtime_allow(dev);
return 0; return 0;
fail_clean_notifier: fail_clean_notifier:
v4l2_async_notifier_unregister(&cio2->notifier); v4l2_async_nf_unregister(&cio2->notifier);
v4l2_async_notifier_cleanup(&cio2->notifier); v4l2_async_nf_cleanup(&cio2->notifier);
cio2_queues_exit(cio2); cio2_queues_exit(cio2);
fail_v4l2_device_unregister: fail_v4l2_device_unregister:
v4l2_device_unregister(&cio2->v4l2_dev); v4l2_device_unregister(&cio2->v4l2_dev);
@ -1844,8 +1837,8 @@ static void cio2_pci_remove(struct pci_dev *pci_dev)
struct cio2_device *cio2 = pci_get_drvdata(pci_dev); struct cio2_device *cio2 = pci_get_drvdata(pci_dev);
media_device_unregister(&cio2->media_dev); media_device_unregister(&cio2->media_dev);
v4l2_async_notifier_unregister(&cio2->notifier); v4l2_async_nf_unregister(&cio2->notifier);
v4l2_async_notifier_cleanup(&cio2->notifier); v4l2_async_nf_cleanup(&cio2->notifier);
cio2_queues_exit(cio2); cio2_queues_exit(cio2);
cio2_fbpt_exit_dummy(cio2); cio2_fbpt_exit_dummy(cio2);
v4l2_device_unregister(&cio2->v4l2_dev); v4l2_device_unregister(&cio2->v4l2_dev);
@ -2005,10 +1998,9 @@ static int __maybe_unused cio2_resume(struct device *dev)
if (!cio2->streaming) if (!cio2->streaming)
return 0; return 0;
/* Start stream */ /* Start stream */
r = pm_runtime_force_resume(&cio2->pci_dev->dev); r = pm_runtime_force_resume(dev);
if (r < 0) { if (r < 0) {
dev_err(&cio2->pci_dev->dev, dev_err(dev, "failed to set power %d\n", r);
"failed to set power %d\n", r);
return r; return r;
} }

View File

@ -338,6 +338,8 @@ struct cio2_buffer {
unsigned int offset; unsigned int offset;
}; };
#define to_cio2_buffer(vb) container_of(vb, struct cio2_buffer, vbb.vb2_buf)
struct csi2_bus_info { struct csi2_bus_info {
u32 port; u32 port;
u32 lanes; u32 lanes;
@ -399,6 +401,8 @@ struct cio2_device {
dma_addr_t dummy_lop_bus_addr; dma_addr_t dummy_lop_bus_addr;
}; };
#define to_cio2_device(n) container_of(n, struct cio2_device, notifier)
/**************** Virtual channel ****************/ /**************** Virtual channel ****************/
/* /*
* This should come from sensor driver. No * This should come from sensor driver. No

View File

@ -837,7 +837,7 @@ static int ivtv_setup_pci(struct ivtv *itv, struct pci_dev *pdev,
IVTV_ERR("Can't enable device!\n"); IVTV_ERR("Can't enable device!\n");
return -EIO; return -EIO;
} }
if (pci_set_dma_mask(pdev, DMA_BIT_MASK(32))) { if (dma_set_mask(&pdev->dev, DMA_BIT_MASK(32))) {
IVTV_ERR("No suitable DMA available.\n"); IVTV_ERR("No suitable DMA available.\n");
return -EIO; return -EIO;
} }

View File

@ -339,7 +339,7 @@ static int ivtv_g_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *f
pixfmt->colorspace = V4L2_COLORSPACE_SMPTE170M; pixfmt->colorspace = V4L2_COLORSPACE_SMPTE170M;
pixfmt->field = V4L2_FIELD_INTERLACED; pixfmt->field = V4L2_FIELD_INTERLACED;
if (id->type == IVTV_ENC_STREAM_TYPE_YUV) { if (id->type == IVTV_ENC_STREAM_TYPE_YUV) {
pixfmt->pixelformat = V4L2_PIX_FMT_HM12; pixfmt->pixelformat = V4L2_PIX_FMT_NV12_16L16;
/* YUV size is (Y=(h*720) + UV=(h*(720/2))) */ /* YUV size is (Y=(h*720) + UV=(h*(720/2))) */
pixfmt->sizeimage = pixfmt->height * 720 * 3 / 2; pixfmt->sizeimage = pixfmt->height * 720 * 3 / 2;
pixfmt->bytesperline = 720; pixfmt->bytesperline = 720;
@ -417,7 +417,7 @@ static int ivtv_g_fmt_vid_out(struct file *file, void *fh, struct v4l2_format *f
pixfmt->field = V4L2_FIELD_ANY; pixfmt->field = V4L2_FIELD_ANY;
break; break;
} }
pixfmt->pixelformat = V4L2_PIX_FMT_HM12; pixfmt->pixelformat = V4L2_PIX_FMT_NV12_16L16;
pixfmt->bytesperline = 720; pixfmt->bytesperline = 720;
pixfmt->width = itv->yuv_info.v4l2_src_w; pixfmt->width = itv->yuv_info.v4l2_src_w;
pixfmt->height = itv->yuv_info.v4l2_src_h; pixfmt->height = itv->yuv_info.v4l2_src_h;
@ -917,7 +917,7 @@ static int ivtv_enum_fmt_vid_cap(struct file *file, void *fh, struct v4l2_fmtdes
static const struct v4l2_fmtdesc hm12 = { static const struct v4l2_fmtdesc hm12 = {
.type = V4L2_BUF_TYPE_VIDEO_CAPTURE, .type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
.description = "HM12 (YUV 4:2:0)", .description = "HM12 (YUV 4:2:0)",
.pixelformat = V4L2_PIX_FMT_HM12, .pixelformat = V4L2_PIX_FMT_NV12_16L16,
}; };
static const struct v4l2_fmtdesc mpeg = { static const struct v4l2_fmtdesc mpeg = {
.type = V4L2_BUF_TYPE_VIDEO_CAPTURE, .type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
@ -944,7 +944,7 @@ static int ivtv_enum_fmt_vid_out(struct file *file, void *fh, struct v4l2_fmtdes
static const struct v4l2_fmtdesc hm12 = { static const struct v4l2_fmtdesc hm12 = {
.type = V4L2_BUF_TYPE_VIDEO_OUTPUT, .type = V4L2_BUF_TYPE_VIDEO_OUTPUT,
.description = "HM12 (YUV 4:2:0)", .description = "HM12 (YUV 4:2:0)",
.pixelformat = V4L2_PIX_FMT_HM12, .pixelformat = V4L2_PIX_FMT_NV12_16L16,
}; };
static const struct v4l2_fmtdesc mpeg = { static const struct v4l2_fmtdesc mpeg = {
.type = V4L2_BUF_TYPE_VIDEO_OUTPUT, .type = V4L2_BUF_TYPE_VIDEO_OUTPUT,

View File

@ -188,7 +188,7 @@ int ivtv_stream_alloc(struct ivtv_stream *s)
return 0; return 0;
IVTV_DEBUG_INFO("Allocate %s%s stream: %d x %d buffers (%dkB total)\n", IVTV_DEBUG_INFO("Allocate %s%s stream: %d x %d buffers (%dkB total)\n",
s->dma != PCI_DMA_NONE ? "DMA " : "", s->dma != DMA_NONE ? "DMA " : "",
s->name, s->buffers, s->buf_size, s->buffers * s->buf_size / 1024); s->name, s->buffers, s->buf_size, s->buffers * s->buf_size / 1024);
s->sg_pending = kzalloc(SGsize, GFP_KERNEL|__GFP_NOWARN); s->sg_pending = kzalloc(SGsize, GFP_KERNEL|__GFP_NOWARN);
@ -218,8 +218,9 @@ int ivtv_stream_alloc(struct ivtv_stream *s)
return -ENOMEM; return -ENOMEM;
} }
if (ivtv_might_use_dma(s)) { if (ivtv_might_use_dma(s)) {
s->sg_handle = pci_map_single(itv->pdev, s->sg_dma, s->sg_handle = dma_map_single(&itv->pdev->dev, s->sg_dma,
sizeof(struct ivtv_sg_element), PCI_DMA_TODEVICE); sizeof(struct ivtv_sg_element),
DMA_TO_DEVICE);
ivtv_stream_sync_for_cpu(s); ivtv_stream_sync_for_cpu(s);
} }
@ -237,7 +238,7 @@ int ivtv_stream_alloc(struct ivtv_stream *s)
} }
INIT_LIST_HEAD(&buf->list); INIT_LIST_HEAD(&buf->list);
if (ivtv_might_use_dma(s)) { if (ivtv_might_use_dma(s)) {
buf->dma_handle = pci_map_single(s->itv->pdev, buf->dma_handle = dma_map_single(&s->itv->pdev->dev,
buf->buf, s->buf_size + 256, s->dma); buf->buf, s->buf_size + 256, s->dma);
ivtv_buf_sync_for_cpu(s, buf); ivtv_buf_sync_for_cpu(s, buf);
} }
@ -260,8 +261,8 @@ void ivtv_stream_free(struct ivtv_stream *s)
/* empty q_free */ /* empty q_free */
while ((buf = ivtv_dequeue(s, &s->q_free))) { while ((buf = ivtv_dequeue(s, &s->q_free))) {
if (ivtv_might_use_dma(s)) if (ivtv_might_use_dma(s))
pci_unmap_single(s->itv->pdev, buf->dma_handle, dma_unmap_single(&s->itv->pdev->dev, buf->dma_handle,
s->buf_size + 256, s->dma); s->buf_size + 256, s->dma);
kfree(buf->buf); kfree(buf->buf);
kfree(buf); kfree(buf);
} }
@ -269,8 +270,9 @@ void ivtv_stream_free(struct ivtv_stream *s)
/* Free SG Array/Lists */ /* Free SG Array/Lists */
if (s->sg_dma != NULL) { if (s->sg_dma != NULL) {
if (s->sg_handle != IVTV_DMA_UNMAPPED) { if (s->sg_handle != IVTV_DMA_UNMAPPED) {
pci_unmap_single(s->itv->pdev, s->sg_handle, dma_unmap_single(&s->itv->pdev->dev, s->sg_handle,
sizeof(struct ivtv_sg_element), PCI_DMA_TODEVICE); sizeof(struct ivtv_sg_element),
DMA_TO_DEVICE);
s->sg_handle = IVTV_DMA_UNMAPPED; s->sg_handle = IVTV_DMA_UNMAPPED;
} }
kfree(s->sg_pending); kfree(s->sg_pending);

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