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:
commit
73d21a3579
1
.mailmap
1
.mailmap
@ -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>
|
||||||
|
@ -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
|
||||||
============ ==========================================================
|
============ ==========================================================
|
||||||
|
|
||||||
|
@ -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
|
||||||
----------
|
----------
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
@ -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.
|
||||||
|
@ -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).
|
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
108
Documentation/devicetree/bindings/media/i2c/aptina,mt9p031.yaml
Normal file
108
Documentation/devicetree/bindings/media/i2c/aptina,mt9p031.yaml
Normal 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 = <®_vdd>;
|
||||||
|
vdd_io-supply = <®_vdd_io>;
|
||||||
|
vaa-supply = <®_vaa>;
|
||||||
|
|
||||||
|
port {
|
||||||
|
mt9p031_1: endpoint {
|
||||||
|
input-clock-frequency = <6000000>;
|
||||||
|
pixel-clock-frequency = <96000000>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
...
|
120
Documentation/devicetree/bindings/media/i2c/hynix,hi846.yaml
Normal file
120
Documentation/devicetree/bindings/media/i2c/hynix,hi846.yaml
Normal 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 = <®_camera_vdda>;
|
||||||
|
vddd-supply = <®_camera_vddd>;
|
||||||
|
vddio-supply = <®_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>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
...
|
@ -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>;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
...
|
|
||||||
};
|
|
@ -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.
|
||||||
|
162
Documentation/devicetree/bindings/media/qcom,sc7280-venus.yaml
Normal file
162
Documentation/devicetree/bindings/media/qcom,sc7280-venus.yaml
Normal 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>;
|
||||||
|
};
|
||||||
|
};
|
186
Documentation/devicetree/bindings/media/qcom,sdm660-venus.yaml
Normal file
186
Documentation/devicetree/bindings/media/qcom,sdm660-venus.yaml
Normal 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>;
|
||||||
|
};
|
||||||
|
};
|
@ -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
|
||||||
|
@ -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>;
|
|
||||||
};
|
|
67
Documentation/devicetree/bindings/media/renesas,imr.yaml
Normal file
67
Documentation/devicetree/bindings/media/renesas,imr.yaml
Normal 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>;
|
||||||
|
};
|
@ -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>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
@ -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,.*":
|
||||||
|
43
Documentation/driver-api/media/drivers/rkisp1.rst
Normal file
43
Documentation/driver-api/media/drivers/rkisp1.rst
Normal 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
|
@ -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:
|
||||||
|
@ -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(¬ifier, ep,
|
my_asd = v4l2_async_nf_add_fwnode_remote(¬ifier, 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))
|
||||||
|
@ -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.
|
||||||
|
@ -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
|
||||||
=========
|
=========
|
||||||
|
@ -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
|
||||||
|
@ -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.
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
@ -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:
|
||||||
|
@ -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.
|
||||||
|
|
||||||
|
@ -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.
|
||||||
|
@ -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.
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
24
MAINTAINERS
24
MAINTAINERS
@ -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
|
||||||
|
@ -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:
|
||||||
/*
|
/*
|
||||||
|
@ -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
|
||||||
|
@ -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;
|
||||||
|
@ -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;
|
||||||
|
@ -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;
|
||||||
|
@ -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);
|
||||||
|
|
||||||
|
@ -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);
|
||||||
|
|
||||||
|
@ -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);
|
||||||
|
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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");
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
@ -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.
|
||||||
|
@ -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;
|
||||||
|
@ -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,
|
||||||
|
@ -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>
|
||||||
|
@ -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_
|
||||||
|
@ -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>
|
||||||
|
|
||||||
|
@ -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 */
|
||||||
|
@ -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);
|
||||||
|
|
||||||
|
@ -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>
|
||||||
|
@ -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_
|
||||||
|
@ -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 {
|
||||||
|
@ -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.
|
||||||
*
|
*
|
||||||
|
@ -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>
|
||||||
|
@ -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_
|
||||||
|
@ -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.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*****************************************************************************
|
/*****************************************************************************
|
||||||
|
@ -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],
|
||||||
|
@ -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>
|
||||||
|
@ -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_
|
||||||
|
@ -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>
|
||||||
|
@ -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_
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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.
|
||||||
|
@ -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
|
||||||
|
@ -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;
|
||||||
|
@ -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
2190
drivers/media/i2c/hi846.c
Normal file
File diff suppressed because it is too large
Load Diff
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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)
|
||||||
|
@ -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;
|
||||||
|
@ -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
1491
drivers/media/i2c/ov13b10.c
Normal file
File diff suppressed because it is too large
Load Diff
@ -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;
|
||||||
|
|
||||||
|
@ -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);
|
||||||
|
@ -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);
|
||||||
|
@ -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");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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 */
|
||||||
|
@ -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;
|
||||||
|
@ -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
|
|
||||||
|
@ -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;
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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,
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
@ -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__);
|
||||||
|
|
||||||
|
@ -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));
|
||||||
|
@ -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;
|
||||||
|
@ -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];
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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,
|
||||||
|
@ -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
Loading…
Reference in New Issue
Block a user