media updates for v5.15-rc1

-----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCAAdFiEE+QmuaPwR3wnBdVwACF8+vY7k4RUFAmEvK4gACgkQCF8+vY7k
 4RUn3Q//YocYb+1s6K+nX2LFFGv5wKgMuqcjJbnuex43/z1dQ+B3T5/RiMmndOvw
 xZwcCQJFI0c42kfDapdCunfICgYDzqncnUZ5V7pO3efeeuN3j6t3EAMxQKD0gR5A
 RmFHe/aJpkRANoEWiA4vFKDNWy1cmi6zQDQ8njK1LUb4euwqxrH5mMJSSpObZU/p
 4/mV5no2CjhvE3k/JPGqh6zJ8WZtptbcf8E6e9fwTsS91nIfbO1/FqudeOleS3fU
 4BYv7zjx/fQsNHpkJZoNNTlZcZGzA1QcWHne4cem+5yudJO2AgRHKC0LnEyhfn19
 Q8xw23yB9TP2/mq0QAjc4r6XfJJd18UGp/rI9LP2K6+YjAqX067+TVIfQXswpcui
 oLDWwGXKtOT7tA5Mrk9XeocpQ6yMUJlCg/JUfpTwJDSaJdEFgAfxVSCsJLLoBT3/
 I8AkfcvBeybwUXgZDaYpDdeE2CBWXvYzdXGzWkiQlZ/jIC35cjRcfWjoUvXIAw8K
 QRDT71VAR67HwufmjkayyDCB0szx+u3xskPdoIAsbtoZCfzgzF+14Z+dAPGQ5YF1
 /+UdiNF5lTRMlTR6Xlz5Zckfix0NV002FeHorSoHD/E9jlLwvd3s+sv/1XSzFBQN
 9Be5hsEJZpE7uuygLzZ09yj4g0wHlWPTkcOuOTyrH+y0IFU5PI4=
 =PQpb
 -----END PGP SIGNATURE-----

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

Pull media updates from Mauro Carvalho Chehab:

 - new sensor drivers: imx335, imx412, ov9282

 - new IR transmitter driver: meson-ir-tx

 - handro driver gained support for H.264 for Rockchip VDPU2

 - imx gained support for i.MX8MQ

 - ti-vpe has gained support for other SoC variants

 - lots of cleanups, fixes, board additions and doc improvements

* tag 'media/v5.15-1' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media: (195 commits)
  media: venus: venc: add support for V4L2_CID_MPEG_VIDEO_H264_8X8_TRANSFORM control
  media: venus: venc: Add support for intra-refresh period
  media: v4l2-ctrls: Add intra-refresh period control
  media: docs: ext-ctrls-codec: Document cyclic intra-refresh zero control value
  media: venus: helper: do not set constrained parameters for UBWC
  media: venus: venc: Fix potential null pointer dereference on pointer fmt
  media: venus: hfi: fix return value check in sys_get_prop_image_version()
  media: tegra-cec: Handle errors of clk_prepare_enable()
  media: cec-pin: rename timer overrun variables
  media: TDA1997x: report -ENOLINK after disconnecting HDMI source
  media: TDA1997x: fix tda1997x_query_dv_timings() return value
  media: Fix cosmetic error in TDA1997x driver
  media: v4l2-dv-timings.c: fix wrong condition in two for-loops
  media: imx: add a driver for i.MX8MQ mipi csi rx phy and controller
  media: dt-bindings: media: document the nxp,imx8mq-mipi-csi2 receiver phy and controller
  media: imx: imx7_mipi_csis: convert some switch cases to the default
  media: imx: imx7-media-csi: Fix buffer return upon stream start failure
  media: imx: imx7-media-csi: Don't set PIXEL_BIT in CSICR1
  media: imx: imx7-media-csi: Set TWO_8BIT_SENSOR for >= 10-bit formats
  media: dt-bindings: media: nxp,imx7-csi: Add i.MX8MM support
  ...
This commit is contained in:
Linus Torvalds 2021-09-01 10:34:52 -07:00
commit 835d31d319
150 changed files with 7972 additions and 1338 deletions

View File

@ -0,0 +1,60 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: "http://devicetree.org/schemas/media/amlogic,meson-ir-tx.yaml#"
$schema: "http://devicetree.org/meta-schemas/core.yaml#"
title: Amlogic Meson IR transmitter
maintainers:
- Viktor Prutyanov <viktor.prutyanov@phystech.edu>
description: |
Some Amlogic SoCs such as A311D and T950D4 have IR transmitter
(also called blaster) controller onboard. It is capable of
sending IR signals with arbitrary carrier frequency and duty cycle.
properties:
compatible:
oneOf:
- const: amlogic,meson-ir-tx
- items:
- const: amlogic,meson-g12a-ir-tx
- const: amlogic,meson-ir-tx
reg:
maxItems: 1
interrupts:
maxItems: 1
clocks:
maxItems: 2
clock-names:
items:
- const: sysclk
- const: xtal
required:
- compatible
- reg
- interrupts
- clocks
- clock-names
additionalProperties: false
examples:
- |
#include <dt-bindings/interrupt-controller/irq.h>
#include <dt-bindings/clock/g12a-clkc.h>
ir@ff80014c {
compatible = "amlogic,meson-g12a-ir-tx", "amlogic,meson-ir-tx";
reg = <0xff80014c 0x10>;
interrupts = <0 198 IRQ_TYPE_EDGE_RISING>;
clocks = <&clkc CLKID_CLK81>, <&xtal>;
clock-names = "sysclk", "xtal";
};

View File

@ -35,6 +35,14 @@ properties:
powerdown-gpios:
maxItems: 1
reset-gpios:
maxItems: 1
adv,force-bt656-4:
description:
Indicates that the output is a BT.656-4 compatible stream.
type: boolean
port:
$ref: /schemas/graph.yaml#/$defs/port-base
unevaluatedProperties: false

View File

@ -0,0 +1,91 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
# Copyright (C) 2021 Intel Corporation
%YAML 1.2
---
$id: http://devicetree.org/schemas/media/i2c/ovti,ov9282.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: OmniVision OV9282 Sensor
maintainers:
- Paul J. Murphy <paul.j.murphy@intel.com>
- Daniele Alessandrelli <daniele.alessandrelli@intel.com>
description:
OV9282 sensor is an OmniVision black & white CMOS active pixel digital image
sensor with an active array size of 1296H x 816V. It is programmable through
I2C interface. The I2C client address is fixed to 0x60/0x70 as per sensor data
sheet. Image data is sent through MIPI CSI-2.
properties:
compatible:
const: ovti,ov9282
reg:
description: I2C address
maxItems: 1
assigned-clocks: true
assigned-clock-parents: true
assigned-clock-rates: true
clocks:
description: Clock frequency from 6 to 27MHz
maxItems: 1
reset-gpios:
description: Reference to the GPIO connected to the XCLR pin, if any.
maxItems: 1
port:
additionalProperties: false
$ref: /schemas/graph.yaml#/properties/port
properties:
endpoint:
$ref: /schemas/media/video-interfaces.yaml#
unevaluatedProperties: false
properties:
data-lanes: true
link-frequencies: true
required:
- data-lanes
- link-frequencies
required:
- endpoint
required:
- compatible
- reg
- clocks
- port
additionalProperties: false
examples:
- |
i2c0 {
#address-cells = <1>;
#size-cells = <0>;
camera@60 {
compatible = "ovti,ov9282";
reg = <0x60>;
clocks = <&ov9282_clk>;
assigned-clocks = <&ov9282_clk>;
assigned-clock-parents = <&ov9282_clk_parent>;
assigned-clock-rates = <24000000>;
port {
ov9282: endpoint {
remote-endpoint = <&cam>;
data-lanes = <1 2>;
link-frequencies = /bits/ 64 <800000000>;
};
};
};
};
...

View File

@ -0,0 +1,91 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
# Copyright (C) 2021 Intel Corporation
%YAML 1.2
---
$id: http://devicetree.org/schemas/media/i2c/sony,imx335.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Sony IMX335 Sensor
maintainers:
- Paul J. Murphy <paul.j.murphy@intel.com>
- Daniele Alessandrelli <daniele.alessandrelli@intel.com>
description:
IMX335 sensor is a Sony CMOS active pixel digital image sensor with an active
array size of 2592H x 1944V. It is programmable through I2C interface. The
I2C client address is fixed to 0x1a as per sensor data sheet. Image data is
sent through MIPI CSI-2.
properties:
compatible:
const: sony,imx335
reg:
description: I2C address
maxItems: 1
assigned-clocks: true
assigned-clock-parents: true
assigned-clock-rates: true
clocks:
description: Clock frequency from 6 to 27 MHz, 37.125MHz, 74.25MHz
maxItems: 1
reset-gpios:
description: Reference to the GPIO connected to the XCLR pin, if any.
maxItems: 1
port:
additionalProperties: false
$ref: /schemas/graph.yaml#/properties/port
properties:
endpoint:
$ref: /schemas/media/video-interfaces.yaml#
unevaluatedProperties: false
properties:
data-lanes: true
link-frequencies: true
required:
- data-lanes
- link-frequencies
required:
- endpoint
required:
- compatible
- reg
- clocks
- port
additionalProperties: false
examples:
- |
i2c0 {
#address-cells = <1>;
#size-cells = <0>;
camera@1a {
compatible = "sony,imx335";
reg = <0x1a>;
clocks = <&imx335_clk>;
assigned-clocks = <&imx335_clk>;
assigned-clock-parents = <&imx335_clk_parent>;
assigned-clock-rates = <24000000>;
port {
imx335: endpoint {
remote-endpoint = <&cam>;
data-lanes = <1 2 3 4>;
link-frequencies = /bits/ 64 <594000000>;
};
};
};
};
...

View File

@ -0,0 +1,91 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
# Copyright (C) 2021 Intel Corporation
%YAML 1.2
---
$id: http://devicetree.org/schemas/media/i2c/sony,imx412.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Sony IMX412 Sensor
maintainers:
- Paul J. Murphy <paul.j.murphy@intel.com>
- Daniele Alessandrelli <daniele.alessandrelli@intel.com>
description:
IMX412 sensor is a Sony CMOS active pixel digital image sensor with an active
array size of 4072H x 3176V. It is programmable through I2C interface. The
I2C client address is fixed to 0x1a as per sensor data sheet. Image data is
sent through MIPI CSI-2.
properties:
compatible:
const: sony,imx412
reg:
description: I2C address
maxItems: 1
assigned-clocks: true
assigned-clock-parents: true
assigned-clock-rates: true
clocks:
description: Clock frequency 6MHz, 12MHz, 18MHz, 24MHz or 27MHz
maxItems: 1
reset-gpios:
description: Reference to the GPIO connected to the XCLR pin, if any.
maxItems: 1
port:
additionalProperties: false
$ref: /schemas/graph.yaml#/properties/port
properties:
endpoint:
$ref: /schemas/media/video-interfaces.yaml#
unevaluatedProperties: false
properties:
data-lanes: true
link-frequencies: true
required:
- data-lanes
- link-frequencies
required:
- endpoint
required:
- compatible
- reg
- clocks
- port
additionalProperties: false
examples:
- |
i2c0 {
#address-cells = <1>;
#size-cells = <0>;
camera@1a {
compatible = "sony,imx412";
reg = <0x1a>;
clocks = <&imx412_clk>;
assigned-clocks = <&imx412_clk>;
assigned-clock-parents = <&imx412_clk_parent>;
assigned-clock-rates = <24000000>;
port {
imx412: endpoint {
remote-endpoint = <&cam>;
data-lanes = <1 2 3 4>;
link-frequencies = /bits/ 64 <600000000>;
};
};
};
};
...

View File

@ -4,7 +4,7 @@
$id: http://devicetree.org/schemas/media/nxp,imx7-csi.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: i.MX7 CMOS Sensor Interface
title: i.MX7 and i.MX8 CSI bridge (CMOS Sensor Interface)
maintainers:
- Rui Miguel Silva <rmfrfs@gmail.com>
@ -15,9 +15,13 @@ description: |
properties:
compatible:
enum:
- fsl,imx7-csi
- fsl,imx6ul-csi
oneOf:
- enum:
- fsl,imx7-csi
- fsl,imx6ul-csi
- items:
- const: fsl,imx8mm-csi
- const: fsl,imx7-csi
reg:
maxItems: 1

View File

@ -0,0 +1,174 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/media/nxp,imx8mq-mipi-csi2.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: NXP i.MX8MQ MIPI CSI-2 receiver
maintainers:
- Martin Kepplinger <martin.kepplinger@puri.sm>
description: |-
This binding covers the CSI-2 RX PHY and host controller included in the
NXP i.MX8MQ SoC. It handles the sensor/image input and process for all the
input imaging devices.
properties:
compatible:
enum:
- fsl,imx8mq-mipi-csi2
reg:
maxItems: 1
clocks:
items:
- description: core is the RX Controller Core Clock input. This clock
must be exactly equal to or faster than the receive
byteclock from the RX DPHY.
- description: esc is the Rx Escape Clock. This must be the same escape
clock that the RX DPHY receives.
- description: ui is the pixel clock (phy_ref up to 333Mhz).
See the reference manual for details.
clock-names:
items:
- const: core
- const: esc
- const: ui
power-domains:
maxItems: 1
resets:
items:
- description: CORE_RESET reset register bit definition
- description: PHY_REF_RESET reset register bit definition
- description: ESC_RESET reset register bit definition
fsl,mipi-phy-gpr:
description: |
The phandle to the imx8mq syscon iomux-gpr with the register
for setting RX_ENABLE for the mipi receiver.
The format should be as follows:
<gpr req_gpr>
gpr is the phandle to general purpose register node.
req_gpr is the gpr register offset of RX_ENABLE for the mipi phy.
$ref: /schemas/types.yaml#/definitions/phandle-array
items:
items:
- description: The 'gpr' is the phandle to general purpose register node.
- description: The 'req_gpr' is the gpr register offset containing
CSI2_1_RX_ENABLE or CSI2_2_RX_ENABLE respectively.
maximum: 0xff
interconnects:
maxItems: 1
interconnect-names:
const: dram
ports:
$ref: /schemas/graph.yaml#/properties/ports
properties:
port@0:
$ref: /schemas/graph.yaml#/$defs/port-base
unevaluatedProperties: false
description:
Input port node, single endpoint describing the CSI-2 transmitter.
properties:
endpoint:
$ref: video-interfaces.yaml#
unevaluatedProperties: false
properties:
data-lanes:
items:
minItems: 1
maxItems: 4
items:
- const: 1
- const: 2
- const: 3
- const: 4
required:
- data-lanes
port@1:
$ref: /schemas/graph.yaml#/properties/port
description:
Output port node
required:
- port@0
- port@1
required:
- compatible
- reg
- clocks
- clock-names
- power-domains
- resets
- fsl,mipi-phy-gpr
- ports
additionalProperties: false
examples:
- |
#include <dt-bindings/clock/imx8mq-clock.h>
#include <dt-bindings/interconnect/imx8mq.h>
#include <dt-bindings/reset/imx8mq-reset.h>
csi@30a70000 {
compatible = "fsl,imx8mq-mipi-csi2";
reg = <0x30a70000 0x1000>;
clocks = <&clk IMX8MQ_CLK_CSI1_CORE>,
<&clk IMX8MQ_CLK_CSI1_ESC>,
<&clk IMX8MQ_CLK_CSI1_PHY_REF>;
clock-names = "core", "esc", "ui";
assigned-clocks = <&clk IMX8MQ_CLK_CSI1_CORE>,
<&clk IMX8MQ_CLK_CSI1_PHY_REF>,
<&clk IMX8MQ_CLK_CSI1_ESC>;
assigned-clock-rates = <266000000>, <200000000>, <66000000>;
assigned-clock-parents = <&clk IMX8MQ_SYS1_PLL_266M>,
<&clk IMX8MQ_SYS2_PLL_1000M>,
<&clk IMX8MQ_SYS1_PLL_800M>;
power-domains = <&pgc_mipi_csi1>;
resets = <&src IMX8MQ_RESET_MIPI_CSI1_CORE_RESET>,
<&src IMX8MQ_RESET_MIPI_CSI1_PHY_REF_RESET>,
<&src IMX8MQ_RESET_MIPI_CSI1_ESC_RESET>;
fsl,mipi-phy-gpr = <&iomuxc_gpr 0x88>;
interconnects = <&noc IMX8MQ_ICM_CSI1 &noc IMX8MQ_ICS_DRAM>;
interconnect-names = "dram";
ports {
#address-cells = <1>;
#size-cells = <0>;
port@0 {
reg = <0>;
imx8mm_mipi_csi_in: endpoint {
remote-endpoint = <&imx477_out>;
data-lanes = <1 2 3 4>;
};
};
port@1 {
reg = <1>;
imx8mm_mipi_csi_out: endpoint {
remote-endpoint = <&csi_in>;
};
};
};
};
...

View File

@ -22,6 +22,7 @@ properties:
- rockchip,rk3288-vpu
- rockchip,rk3328-vpu
- rockchip,rk3399-vpu
- rockchip,px30-vpu
- items:
- const: rockchip,rk3188-vpu
- const: rockchip,rk3066-vpu

View File

@ -3,10 +3,10 @@
Writing camera sensor drivers
=============================
CSI-2
-----
CSI-2 and parallel (BT.601 and BT.656) busses
---------------------------------------------
Please see what is written on :ref:`MIPI_CSI_2`.
Please see :ref:`transmitter-receiver`.
Handling clocks
---------------
@ -26,15 +26,16 @@ user.
ACPI
~~~~
Read the "clock-frequency" _DSD property to denote the frequency. The driver can
rely on this frequency being used.
Read the ``clock-frequency`` _DSD property to denote the frequency. The driver
can rely on this frequency being used.
Devicetree
~~~~~~~~~~
The currently preferred way to achieve this is using "assigned-clock-rates"
property. See Documentation/devicetree/bindings/clock/clock-bindings.txt for
more information. The driver then gets the frequency using clk_get_rate().
The currently preferred way to achieve this is using ``assigned-clocks``,
``assigned-clock-parents`` and ``assigned-clock-rates`` properties. See
``Documentation/devicetree/bindings/clock/clock-bindings.txt`` for more
information. The driver then gets the frequency using ``clk_get_rate()``.
This approach has the drawback that there's no guarantee that the frequency
hasn't been modified directly or indirectly by another driver, or supported by
@ -55,7 +56,7 @@ processing pipeline as one or more sub-devices with different cropping and
scaling configurations. The output size of the device is the result of a series
of cropping and scaling operations from the device's pixel array's size.
An example of such a driver is the smiapp driver (see drivers/media/i2c/smiapp).
An example of such a driver is the CCS driver (see ``drivers/media/i2c/ccs``).
Register list based drivers
~~~~~~~~~~~~~~~~~~~~~~~~~~~
@ -67,7 +68,7 @@ level are independent. How a driver picks such configuration is based on the
format set on a source pad at the end of the device's internal pipeline.
Most sensor drivers are implemented this way, see e.g.
drivers/media/i2c/imx319.c for an example.
``drivers/media/i2c/imx319.c`` for an example.
Frame interval configuration
----------------------------
@ -94,9 +95,10 @@ large variety of devices beyond camera sensors. Devices that have no analogue
crop, use the full source image size, i.e. pixel array size.
Horizontal and vertical blanking are specified by ``V4L2_CID_HBLANK`` and
``V4L2_CID_VBLANK``, respectively. The unit of these controls are lines. The
pixel rate is specified by ``V4L2_CID_PIXEL_RATE`` in the same sub-device. The
unit of that control is Hz.
``V4L2_CID_VBLANK``, respectively. The unit of the ``V4L2_CID_HBLANK`` control
is pixels and the unit of the ``V4L2_CID_VBLANK`` is lines. The pixel rate in
the sensor's **pixel array** is specified by ``V4L2_CID_PIXEL_RATE`` in the same
sub-device. The unit of that control is pixels per second.
Register list based drivers need to implement read-only sub-device nodes for the
purpose. Devices that are not register list based need these to configure the
@ -125,14 +127,14 @@ general, the device must be powered on at least when its registers are being
accessed and when it is streaming.
Existing camera sensor drivers may rely on the old
:c:type:`v4l2_subdev_core_ops`->s_power() callback for bridge or ISP drivers to
struct v4l2_subdev_core_ops->s_power() callback for bridge or ISP drivers to
manage their power state. This is however **deprecated**. If you feel you need
to begin calling an s_power from an ISP or a bridge driver, instead please add
runtime PM support to the sensor driver you are using. Likewise, new drivers
should not use s_power.
Please see examples in e.g. ``drivers/media/i2c/ov8856.c`` and
``drivers/media/i2c/smiapp/smiapp-core.c``. The two drivers work in both ACPI
``drivers/media/i2c/ccs/ccs-core.c``. The two drivers work in both ACPI
and DT based systems.
Control framework
@ -149,16 +151,3 @@ used to obtain device's power state after the power state transition:
The function returns a non-zero value if it succeeded getting the power count or
runtime PM was disabled, in either of which cases the driver may proceed to
access the device.
Controls
--------
For camera sensors that are connected to a bus where transmitter and receiver
require common configuration set by drivers, such as CSI-2 or parallel (BT.601
or BT.656) bus, the ``V4L2_CID_LINK_FREQ`` control is mandatory on transmitter
drivers. Receiver drivers can use the ``V4L2_CID_LINK_FREQ`` to query the
frequency used on the bus.
The transmitter drivers should also implement ``V4L2_CID_PIXEL_RATE`` control in
order to tell the maximum pixel rate to the receiver. This is required on raw
camera sensors.

View File

@ -130,9 +130,12 @@ To enable/disable the hardware::
int (*adap_enable)(struct cec_adapter *adap, bool enable);
This callback enables or disables the CEC hardware. Enabling the CEC hardware
means powering it up in a state where no logical addresses are claimed. This
op assumes that the physical address (adap->phys_addr) is valid when enable is
true and will not change while the CEC adapter remains enabled. The initial
means powering it up in a state where no logical addresses are claimed. The
physical address will always be valid if CEC_CAP_NEEDS_HPD is set. If that
capability is not set, then the physical address can change while the CEC
hardware is enabled. CEC drivers should not set CEC_CAP_NEEDS_HPD unless
the hardware design requires that as this will make it impossible to wake
up displays that pull the HPD low when in standby mode. The initial
state of the CEC adapter after calling cec_allocate_adapter() is disabled.
Note that adap_enable must return 0 if enable is false.

View File

@ -1,94 +0,0 @@
.. SPDX-License-Identifier: GPL-2.0
.. _MIPI_CSI_2:
MIPI CSI-2
==========
CSI-2 is a data bus intended for transferring images from cameras to
the host SoC. It is defined by the `MIPI alliance`_.
.. _`MIPI alliance`: http://www.mipi.org/
Media bus formats
-----------------
See :ref:`v4l2-mbus-pixelcode` for details on which media bus formats should
be used for CSI-2 interfaces.
Transmitter drivers
-------------------
CSI-2 transmitter, such as a sensor or a TV tuner, drivers need to
provide the CSI-2 receiver with information on the CSI-2 bus
configuration. These include the V4L2_CID_LINK_FREQ and
V4L2_CID_PIXEL_RATE controls and
(:c:type:`v4l2_subdev_video_ops`->s_stream() callback). These
interface elements must be present on the sub-device represents the
CSI-2 transmitter.
The V4L2_CID_LINK_FREQ control is used to tell the receiver driver the
frequency (and not the symbol rate) of the link. The V4L2_CID_PIXEL_RATE
control may be used by the receiver to obtain the pixel rate the transmitter
uses. The :c:type:`v4l2_subdev_video_ops`->s_stream() callback provides an
ability to start and stop the stream.
The value of the V4L2_CID_PIXEL_RATE is calculated as follows::
pixel_rate = link_freq * 2 * nr_of_lanes * 16 / k / bits_per_sample
where
.. list-table:: variables in pixel rate calculation
:header-rows: 1
* - variable or constant
- description
* - link_freq
- The value of the V4L2_CID_LINK_FREQ integer64 menu item.
* - nr_of_lanes
- Number of data lanes used on the CSI-2 link. This can
be obtained from the OF endpoint configuration.
* - 2
- Two bits are transferred per clock cycle per lane.
* - bits_per_sample
- Number of bits per sample.
* - k
- 16 for D-PHY and 7 for C-PHY
The transmitter drivers must, if possible, configure the CSI-2
transmitter to *LP-11 mode* whenever the transmitter is powered on but
not active, and maintain *LP-11 mode* until stream on. Only at stream
on should the transmitter activate the clock on the clock lane and
transition to *HS mode*.
Some transmitters do this automatically but some have to be explicitly
programmed to do so, and some are unable to do so altogether due to
hardware constraints.
Stopping the transmitter
^^^^^^^^^^^^^^^^^^^^^^^^
A transmitter stops sending the stream of images as a result of
calling the ``.s_stream()`` callback. Some transmitters may stop the
stream at a frame boundary whereas others stop immediately,
effectively leaving the current frame unfinished. The receiver driver
should not make assumptions either way, but function properly in both
cases.
Receiver drivers
----------------
Before the receiver driver may enable the CSI-2 transmitter by using
the :c:type:`v4l2_subdev_video_ops`->s_stream(), it must have powered
the transmitter up by using the
:c:type:`v4l2_subdev_core_ops`->s_power() callback. This may take
place either indirectly by using :c:func:`v4l2_pipeline_pm_get` or
directly.
Formats
-------
The media bus pixel codes document parallel formats. Should the pixel data be
transported over a serial bus, the media bus pixel code that describes a
parallel format that transfers a sample on a single clock cycle is used.

View File

@ -37,7 +37,7 @@ Documentation/userspace-api/media/index.rst
rc-core
mc-core
cec-core
csi2
tx-rx
camera-sensor
drivers/index

View File

@ -0,0 +1,133 @@
.. SPDX-License-Identifier: GPL-2.0
.. _transmitter-receiver:
Pixel data transmitter and receiver drivers
===========================================
V4L2 supports various devices that transmit and receive pixel data. Examples of
these devices include a camera sensor, a TV tuner and a parallel or a CSI-2
receiver in an SoC.
Bus types
---------
The following busses are the most common. This section discusses these two only.
MIPI CSI-2
^^^^^^^^^^
CSI-2 is a data bus intended for transferring images from cameras to
the host SoC. It is defined by the `MIPI alliance`_.
.. _`MIPI alliance`: https://www.mipi.org/
Parallel
^^^^^^^^
`BT.601`_ and `BT.656`_ are the most common parallel busses.
.. _`BT.601`: https://en.wikipedia.org/wiki/Rec._601
.. _`BT.656`: https://en.wikipedia.org/wiki/ITU-R_BT.656
Transmitter drivers
-------------------
Transmitter drivers generally need to provide the receiver drivers with the
configuration of the transmitter. What is required depends on the type of the
bus. These are common for both busses.
Media bus pixel code
^^^^^^^^^^^^^^^^^^^^
See :ref:`v4l2-mbus-pixelcode`.
Link frequency
^^^^^^^^^^^^^^
The :ref:`V4L2_CID_LINK_FREQ <v4l2-cid-link-freq>` control is used to tell the
receiver the frequency of the bus (i.e. it is not the same as the symbol rate).
``.s_stream()`` callback
^^^^^^^^^^^^^^^^^^^^^^^^
The struct struct v4l2_subdev_video_ops->s_stream() callback is used by the
receiver driver to control the transmitter driver's streaming state.
CSI-2 transmitter drivers
-------------------------
Pixel rate
^^^^^^^^^^
The pixel rate on the bus is calculated as follows::
pixel_rate = link_freq * 2 * nr_of_lanes * 16 / k / bits_per_sample
where
.. list-table:: variables in pixel rate calculation
:header-rows: 1
* - variable or constant
- description
* - link_freq
- The value of the ``V4L2_CID_LINK_FREQ`` integer64 menu item.
* - nr_of_lanes
- Number of data lanes used on the CSI-2 link. This can
be obtained from the OF endpoint configuration.
* - 2
- Data is transferred on both rising and falling edge of the signal.
* - bits_per_sample
- Number of bits per sample.
* - k
- 16 for D-PHY and 7 for C-PHY
.. note::
The pixel rate calculated this way is **not** the same thing as the
pixel rate on the camera sensor's pixel array which is indicated by the
:ref:`V4L2_CID_PIXEL_RATE <v4l2-cid-pixel-rate>` control.
LP-11 and LP-111 modes
^^^^^^^^^^^^^^^^^^^^^^
As part of transitioning to high speed mode, a CSI-2 transmitter typically
briefly sets the bus to LP-11 or LP-111 state, depending on the PHY. This period
may be as short as 100 µs, during which the receiver observes this state and
proceeds its own part of high speed mode transition.
Most receivers are capable of autonomously handling this once the software has
configured them to do so, but there are receivers which require software
involvement in observing LP-11 or LP-111 state. 100 µs is a brief period to hit
in software, especially when there is no interrupt telling something is
happening.
One way to address this is to configure the transmitter side explicitly to LP-11
or LP-111 mode, which requires support from the transmitter hardware. This is
not universally available. Many devices return to this state once streaming is
stopped while the state after power-on is LP-00 or LP-000.
The ``.pre_streamon()`` callback may be used to prepare a transmitter for
transitioning to streaming state, but not yet start streaming. Similarly, the
``.post_streamoff()`` callback is used to undo what was done by the
``.pre_streamon()`` callback. The caller of ``.pre_streamon()`` is thus required
to call ``.post_streamoff()`` for each successful call of ``.pre_streamon()``.
In the context of CSI-2, the ``.pre_streamon()`` callback is used to transition
the transmitter to the LP-11 or LP-111 mode. This also requires powering on the
device, so this should be only done when it is needed.
Receiver drivers that do not need explicit LP-11 or LP-111 mode setup are waived
from calling the two callbacks.
Stopping the transmitter
^^^^^^^^^^^^^^^^^^^^^^^^
A transmitter stops sending the stream of images as a result of
calling the ``.s_stream()`` callback. Some transmitters may stop the
stream at a frame boundary whereas others stop immediately,
effectively leaving the current frame unfinished. The receiver driver
should not make assumptions either way, but function properly in both
cases.

View File

@ -140,7 +140,7 @@ ignore define CEC_OP_REC_SEQ_TUESDAY
ignore define CEC_OP_REC_SEQ_WEDNESDAY
ignore define CEC_OP_REC_SEQ_THURSDAY
ignore define CEC_OP_REC_SEQ_FRIDAY
ignore define CEC_OP_REC_SEQ_SATERDAY
ignore define CEC_OP_REC_SEQ_SATURDAY
ignore define CEC_OP_REC_SEQ_ONCE_ONLY
ignore define CEC_MSG_CLEAR_DIGITAL_TIMER

View File

@ -1174,7 +1174,24 @@ enum v4l2_mpeg_video_h264_entropy_mode -
Cyclic intra macroblock refresh. This is the number of continuous
macroblocks refreshed every frame. Each frame a successive set of
macroblocks is refreshed until the cycle completes and starts from
the top of the frame. Applicable to H264, H263 and MPEG4 encoder.
the top of the frame. Setting this control to zero means that
macroblocks will not be refreshed. Note that this control will not
take effect when ``V4L2_CID_MPEG_VIDEO_INTRA_REFRESH_PERIOD`` control
is set to non zero value.
Applicable to H264, H263 and MPEG4 encoder.
``V4L2_CID_MPEG_VIDEO_INTRA_REFRESH_PERIOD (integer)``
Intra macroblock refresh period. This sets the period to refresh
the whole frame. In other words, this defines the number of frames
for which the whole frame will be intra-refreshed. An example:
setting period to 1 means that the whole frame will be refreshed,
setting period to 2 means that the half of macroblocks will be
intra-refreshed on frameX and the other half of macroblocks
will be refreshed in frameX + 1 and so on. Setting the period to
zero means no period is specified.
Note that if the client sets this control to non zero value the
``V4L2_CID_MPEG_VIDEO_CYCLIC_INTRA_REFRESH_MB`` control shall be
ignored. Applicable to H264 and HEVC encoders.
``V4L2_CID_MPEG_VIDEO_FRAME_RC_ENABLE (boolean)``
Frame level rate control enable. If this control is disabled then
@ -3000,6 +3017,9 @@ enum v4l2_mpeg_video_hevc_size_of_length_field -
* - __u8
- ``pic_struct``
-
* - __u32
- ``slice_segment_addr``
-
* - __u8
- ``ref_idx_l0[V4L2_HEVC_DPB_ENTRIES_NUM_MAX]``
- The list of L0 reference elements as indices in the DPB.

View File

@ -20,25 +20,26 @@ Image Process Control IDs
``V4L2_CID_IMAGE_PROC_CLASS (class)``
The IMAGE_PROC class descriptor.
.. _v4l2-cid-link-freq:
``V4L2_CID_LINK_FREQ (integer menu)``
Data bus frequency. Together with the media bus pixel code, bus type
(clock cycles per sample), the data bus frequency defines the pixel
rate (``V4L2_CID_PIXEL_RATE``) in the pixel array (or possibly
elsewhere, if the device is not an image sensor). The frame rate can
be calculated from the pixel clock, image width and height and
horizontal and vertical blanking. While the pixel rate control may
be defined elsewhere than in the subdev containing the pixel array,
the frame rate cannot be obtained from that information. This is
because only on the pixel array it can be assumed that the vertical
and horizontal blanking information is exact: no other blanking is
allowed in the pixel array. The selection of frame rate is performed
by selecting the desired horizontal and vertical blanking. The unit
of this control is Hz.
The frequency of the data bus (e.g. parallel or CSI-2).
.. _v4l2-cid-pixel-rate:
``V4L2_CID_PIXEL_RATE (64-bit integer)``
Pixel rate in the source pads of the subdev. This control is
Pixel sampling rate in the device's pixel array. This control is
read-only and its unit is pixels / second.
Some devices use horizontal and vertical balanking to configure the frame
rate. The frame rate can be calculated from the pixel rate, analogue crop
rectangle as well as horizontal and vertical blanking. The pixel rate
control may be present in a different sub-device than the blanking controls
and the analogue crop rectangle configuration.
The configuration of the frame rate is performed by selecting the desired
horizontal and vertical blanking. The unit of this control is Hz.
``V4L2_CID_TEST_PATTERN (menu)``
Some capture/display/sensor devices have the capability to generate
test pattern images. These hardware specific test patterns can be

View File

@ -13833,6 +13833,15 @@ T: git git://linuxtv.org/media_tree.git
F: Documentation/devicetree/bindings/media/i2c/ov8856.yaml
F: drivers/media/i2c/ov8856.c
OMNIVISION OV9282 SENSOR DRIVER
M: Paul J. Murphy <paul.j.murphy@intel.com>
M: Daniele Alessandrelli <daniele.alessandrelli@intel.com>
L: linux-media@vger.kernel.org
S: Maintained
T: git git://linuxtv.org/media_tree.git
F: Documentation/devicetree/bindings/media/i2c/ovti,ov9282.yaml
F: drivers/media/i2c/ov9282.c
OMNIVISION OV9640 SENSOR DRIVER
M: Petr Cvek <petrcvekcz@gmail.com>
L: linux-media@vger.kernel.org
@ -17366,6 +17375,15 @@ T: git git://linuxtv.org/media_tree.git
F: Documentation/devicetree/bindings/media/i2c/sony,imx334.yaml
F: drivers/media/i2c/imx334.c
SONY IMX335 SENSOR DRIVER
M: Paul J. Murphy <paul.j.murphy@intel.com>
M: Daniele Alessandrelli <daniele.alessandrelli@intel.com>
L: linux-media@vger.kernel.org
S: Maintained
T: git git://linuxtv.org/media_tree.git
F: Documentation/devicetree/bindings/media/i2c/sony,imx335.yaml
F: drivers/media/i2c/imx335.c
SONY IMX355 SENSOR DRIVER
M: Tianshu Qiu <tian.shu.qiu@intel.com>
L: linux-media@vger.kernel.org
@ -17373,6 +17391,15 @@ S: Maintained
T: git git://linuxtv.org/media_tree.git
F: drivers/media/i2c/imx355.c
SONY IMX412 SENSOR DRIVER
M: Paul J. Murphy <paul.j.murphy@intel.com>
M: Daniele Alessandrelli <daniele.alessandrelli@intel.com>
L: linux-media@vger.kernel.org
S: Maintained
T: git git://linuxtv.org/media_tree.git
F: Documentation/devicetree/bindings/media/i2c/sony,imx412.yaml
F: drivers/media/i2c/imx412.c
SONY MEMORYSTICK SUBSYSTEM
M: Maxim Levitsky <maximlevitsky@gmail.com>
M: Alex Dubov <oakad@yahoo.com>

View File

@ -209,8 +209,8 @@ struct cec_pin {
u32 work_pin_events_dropped_cnt;
ktime_t timer_ts;
u32 timer_cnt;
u32 timer_100ms_overruns;
u32 timer_300ms_overruns;
u32 timer_100us_overruns;
u32 timer_300us_overruns;
u32 timer_max_overrun;
u32 timer_sum_overrun;

View File

@ -854,9 +854,9 @@ static enum hrtimer_restart cec_pin_timer(struct hrtimer *timer)
if (delta > 100 && pin->state != CEC_ST_IDLE) {
/* Keep track of timer overruns */
pin->timer_sum_overrun += delta;
pin->timer_100ms_overruns++;
pin->timer_100us_overruns++;
if (delta > 300)
pin->timer_300ms_overruns++;
pin->timer_300us_overruns++;
if (delta > pin->timer_max_overrun)
pin->timer_max_overrun = delta;
}
@ -1207,15 +1207,15 @@ static void cec_pin_adap_status(struct cec_adapter *adap,
seq_printf(file, "cec pin events dropped: %u\n",
pin->work_pin_events_dropped_cnt);
seq_printf(file, "irq failed: %d\n", pin->enable_irq_failed);
if (pin->timer_100ms_overruns) {
seq_printf(file, "timer overruns > 100ms: %u of %u\n",
pin->timer_100ms_overruns, pin->timer_cnt);
seq_printf(file, "timer overruns > 300ms: %u of %u\n",
pin->timer_300ms_overruns, pin->timer_cnt);
if (pin->timer_100us_overruns) {
seq_printf(file, "timer overruns > 100us: %u of %u\n",
pin->timer_100us_overruns, pin->timer_cnt);
seq_printf(file, "timer overruns > 300us: %u of %u\n",
pin->timer_300us_overruns, pin->timer_cnt);
seq_printf(file, "max timer overrun: %u usecs\n",
pin->timer_max_overrun);
seq_printf(file, "avg timer overrun: %u usecs\n",
pin->timer_sum_overrun / pin->timer_100ms_overruns);
pin->timer_sum_overrun / pin->timer_100us_overruns);
}
if (pin->rx_start_bit_low_too_short_cnt)
seq_printf(file,
@ -1245,8 +1245,8 @@ static void cec_pin_adap_status(struct cec_adapter *adap,
seq_printf(file, "tx detected low drive: %u\n", pin->tx_low_drive_cnt);
pin->work_pin_events_dropped_cnt = 0;
pin->timer_cnt = 0;
pin->timer_100ms_overruns = 0;
pin->timer_300ms_overruns = 0;
pin->timer_100us_overruns = 0;
pin->timer_300us_overruns = 0;
pin->timer_max_overrun = 0;
pin->timer_sum_overrun = 0;
pin->rx_start_bit_low_too_short_cnt = 0;

View File

@ -305,14 +305,16 @@ static int stm32_cec_probe(struct platform_device *pdev)
cec->clk_hdmi_cec = devm_clk_get(&pdev->dev, "hdmi-cec");
if (IS_ERR(cec->clk_hdmi_cec) &&
PTR_ERR(cec->clk_hdmi_cec) == -EPROBE_DEFER)
return -EPROBE_DEFER;
PTR_ERR(cec->clk_hdmi_cec) == -EPROBE_DEFER) {
ret = -EPROBE_DEFER;
goto err_unprepare_cec_clk;
}
if (!IS_ERR(cec->clk_hdmi_cec)) {
ret = clk_prepare(cec->clk_hdmi_cec);
if (ret) {
dev_err(&pdev->dev, "Can't prepare hdmi-cec clock\n");
return ret;
goto err_unprepare_cec_clk;
}
}
@ -324,19 +326,27 @@ static int stm32_cec_probe(struct platform_device *pdev)
CEC_NAME, caps, CEC_MAX_LOG_ADDRS);
ret = PTR_ERR_OR_ZERO(cec->adap);
if (ret)
return ret;
goto err_unprepare_hdmi_cec_clk;
ret = cec_register_adapter(cec->adap, &pdev->dev);
if (ret) {
cec_delete_adapter(cec->adap);
return ret;
}
if (ret)
goto err_delete_adapter;
cec_hw_init(cec);
platform_set_drvdata(pdev, cec);
return 0;
err_delete_adapter:
cec_delete_adapter(cec->adap);
err_unprepare_hdmi_cec_clk:
clk_unprepare(cec->clk_hdmi_cec);
err_unprepare_cec_clk:
clk_unprepare(cec->clk_cec);
return ret;
}
static int stm32_cec_remove(struct platform_device *pdev)

View File

@ -366,7 +366,11 @@ static int tegra_cec_probe(struct platform_device *pdev)
return -ENOENT;
}
clk_prepare_enable(cec->clk);
ret = clk_prepare_enable(cec->clk);
if (ret) {
dev_err(&pdev->dev, "Unable to prepare clock for CEC\n");
return ret;
}
/* set context info. */
cec->dev = &pdev->dev;
@ -446,9 +450,7 @@ static int tegra_cec_resume(struct platform_device *pdev)
dev_notice(&pdev->dev, "Resuming\n");
clk_prepare_enable(cec->clk);
return 0;
return clk_prepare_enable(cec->clk);
}
#endif

View File

@ -1172,7 +1172,6 @@ struct dvb_frontend *cx24117_attach(const struct cx24117_config *config,
"%s: Error attaching frontend %d\n",
KBUILD_MODNAME, demod);
goto error1;
break;
case 1:
/* new priv instance */
priv->i2c = i2c;

View File

@ -2107,32 +2107,55 @@ static void dib8000_load_ana_fe_coefs(struct dib8000_state *state, const s16 *an
dib8000_write_word(state, 117 + mode, ana_fe[mode]);
}
static const u16 lut_prbs_2k[14] = {
0, 0x423, 0x009, 0x5C7, 0x7A6, 0x3D8, 0x527, 0x7FF, 0x79B, 0x3D6, 0x3A2, 0x53B, 0x2F4, 0x213
static const u16 lut_prbs_2k[13] = {
0x423, 0x009, 0x5C7,
0x7A6, 0x3D8, 0x527,
0x7FF, 0x79B, 0x3D6,
0x3A2, 0x53B, 0x2F4,
0x213
};
static const u16 lut_prbs_4k[14] = {
0, 0x208, 0x0C3, 0x7B9, 0x423, 0x5C7, 0x3D8, 0x7FF, 0x3D6, 0x53B, 0x213, 0x029, 0x0D0, 0x48E
static const u16 lut_prbs_4k[13] = {
0x208, 0x0C3, 0x7B9,
0x423, 0x5C7, 0x3D8,
0x7FF, 0x3D6, 0x53B,
0x213, 0x029, 0x0D0,
0x48E
};
static const u16 lut_prbs_8k[14] = {
0, 0x740, 0x069, 0x7DD, 0x208, 0x7B9, 0x5C7, 0x7FF, 0x53B, 0x029, 0x48E, 0x4C4, 0x367, 0x684
static const u16 lut_prbs_8k[13] = {
0x740, 0x069, 0x7DD,
0x208, 0x7B9, 0x5C7,
0x7FF, 0x53B, 0x029,
0x48E, 0x4C4, 0x367,
0x684
};
static u16 dib8000_get_init_prbs(struct dib8000_state *state, u16 subchannel)
{
int sub_channel_prbs_group = 0;
int prbs_group;
sub_channel_prbs_group = (subchannel / 3) + 1;
dprintk("sub_channel_prbs_group = %d , subchannel =%d prbs = 0x%04x\n", sub_channel_prbs_group, subchannel, lut_prbs_8k[sub_channel_prbs_group]);
sub_channel_prbs_group = subchannel / 3;
if (sub_channel_prbs_group >= ARRAY_SIZE(lut_prbs_2k))
return 0;
switch (state->fe[0]->dtv_property_cache.transmission_mode) {
case TRANSMISSION_MODE_2K:
return lut_prbs_2k[sub_channel_prbs_group];
prbs_group = lut_prbs_2k[sub_channel_prbs_group];
break;
case TRANSMISSION_MODE_4K:
return lut_prbs_4k[sub_channel_prbs_group];
prbs_group = lut_prbs_4k[sub_channel_prbs_group];
break;
default:
case TRANSMISSION_MODE_8K:
return lut_prbs_8k[sub_channel_prbs_group];
prbs_group = lut_prbs_8k[sub_channel_prbs_group];
}
dprintk("sub_channel_prbs_group = %d , subchannel =%d prbs = 0x%04x\n",
sub_channel_prbs_group, subchannel, prbs_group);
return prbs_group;
}
static void dib8000_set_13seg_channel(struct dib8000_state *state)
@ -2409,10 +2432,8 @@ static void dib8000_set_isdbt_common_channel(struct dib8000_state *state, u8 seq
/* TSB or ISDBT ? apply it now */
if (c->isdbt_sb_mode) {
dib8000_set_sb_channel(state);
if (c->isdbt_sb_subchannel < 14)
init_prbs = dib8000_get_init_prbs(state, c->isdbt_sb_subchannel);
else
init_prbs = 0;
init_prbs = dib8000_get_init_prbs(state,
c->isdbt_sb_subchannel);
} else {
dib8000_set_13seg_channel(state);
init_prbs = 0xfff;
@ -3004,6 +3025,7 @@ static int dib8000_tune(struct dvb_frontend *fe)
unsigned long *timeout = &state->timeout;
unsigned long now = jiffies;
u16 init_prbs;
#ifdef DIB8000_AGC_FREEZE
u16 agc1, agc2;
#endif
@ -3302,8 +3324,10 @@ static int dib8000_tune(struct dvb_frontend *fe)
break;
case CT_DEMOD_STEP_11: /* 41 : init prbs autosearch */
if (state->subchannel <= 41) {
dib8000_set_subchannel_prbs(state, dib8000_get_init_prbs(state, state->subchannel));
init_prbs = dib8000_get_init_prbs(state, state->subchannel);
if (init_prbs) {
dib8000_set_subchannel_prbs(state, init_prbs);
*tune_state = CT_DEMOD_STEP_9;
} else {
*tune_state = CT_DEMOD_STOP;

View File

@ -842,6 +842,20 @@ config VIDEO_IMX334
To compile this driver as a module, choose M here: the
module will be called imx334.
config VIDEO_IMX335
tristate "Sony IMX335 sensor support"
depends on OF_GPIO
depends on I2C && VIDEO_V4L2
select VIDEO_V4L2_SUBDEV_API
select MEDIA_CONTROLLER
select V4L2_FWNODE
help
This is a Video4Linux2 sensor driver for the Sony
IMX335 camera.
To compile this driver as a module, choose M here: the
module will be called imx335.
config VIDEO_IMX355
tristate "Sony IMX355 sensor support"
depends on I2C && VIDEO_V4L2
@ -854,6 +868,20 @@ config VIDEO_IMX355
To compile this driver as a module, choose M here: the
module will be called imx355.
config VIDEO_IMX412
tristate "Sony IMX412 sensor support"
depends on OF_GPIO
depends on I2C && VIDEO_V4L2
select VIDEO_V4L2_SUBDEV_API
select MEDIA_CONTROLLER
select V4L2_FWNODE
help
This is a Video4Linux2 sensor driver for the Sony
IMX412 camera.
To compile this driver as a module, choose M here: the
module will be called imx412.
config VIDEO_OV02A10
tristate "OmniVision OV02A10 sensor support"
depends on VIDEO_V4L2 && I2C
@ -1103,6 +1131,20 @@ config VIDEO_OV8865
To compile this driver as a module, choose M here: the
module will be called ov8865.
config VIDEO_OV9282
tristate "OmniVision OV9282 sensor support"
depends on OF_GPIO
depends on I2C && VIDEO_V4L2
select VIDEO_V4L2_SUBDEV_API
select MEDIA_CONTROLLER
select V4L2_FWNODE
help
This is a Video4Linux2 sensor driver for the OmniVision
OV9282 camera sensor.
To compile this driver as a module, choose M here: the
module will be called ov9282.
config VIDEO_OV9640
tristate "OmniVision OV9640 sensor support"
depends on I2C && VIDEO_V4L2

View File

@ -84,6 +84,7 @@ obj-$(CONFIG_VIDEO_OV772X) += ov772x.o
obj-$(CONFIG_VIDEO_OV7740) += ov7740.o
obj-$(CONFIG_VIDEO_OV8856) += ov8856.o
obj-$(CONFIG_VIDEO_OV8865) += ov8865.o
obj-$(CONFIG_VIDEO_OV9282) += ov9282.o
obj-$(CONFIG_VIDEO_OV9640) += ov9640.o
obj-$(CONFIG_VIDEO_OV9650) += ov9650.o
obj-$(CONFIG_VIDEO_OV9734) += ov9734.o
@ -124,11 +125,12 @@ obj-$(CONFIG_VIDEO_IMX274) += imx274.o
obj-$(CONFIG_VIDEO_IMX290) += imx290.o
obj-$(CONFIG_VIDEO_IMX319) += imx319.o
obj-$(CONFIG_VIDEO_IMX334) += imx334.o
obj-$(CONFIG_VIDEO_IMX335) += imx335.o
obj-$(CONFIG_VIDEO_IMX355) += imx355.o
obj-$(CONFIG_VIDEO_IMX412) += imx412.o
obj-$(CONFIG_VIDEO_MAX9286) += max9286.o
obj-$(CONFIG_VIDEO_MAX9271_LIB) += max9271.o
obj-$(CONFIG_VIDEO_RDACM20) += rdacm20.o
obj-$(CONFIG_VIDEO_RDACM21) += rdacm21.o
obj-$(CONFIG_VIDEO_ST_MIPID02) += st-mipid02.o
obj-$(CONFIG_SDR_MAX2175) += max2175.o

View File

@ -94,6 +94,7 @@
#define ADV7180_REG_SHAP_FILTER_CTL_1 0x0017
#define ADV7180_REG_CTRL_2 0x001d
#define ADV7180_REG_VSYNC_FIELD_CTL_1 0x0031
#define ADV7180_VSYNC_FIELD_CTL_1_NEWAV 0x12
#define ADV7180_REG_MANUAL_WIN_CTL_1 0x003d
#define ADV7180_REG_MANUAL_WIN_CTL_2 0x003e
#define ADV7180_REG_MANUAL_WIN_CTL_3 0x003f
@ -205,6 +206,7 @@ struct adv7180_state {
struct mutex mutex; /* mutual excl. when accessing chip */
int irq;
struct gpio_desc *pwdn_gpio;
struct gpio_desc *rst_gpio;
v4l2_std_id curr_norm;
bool powered;
bool streaming;
@ -216,6 +218,7 @@ struct adv7180_state {
struct i2c_client *vpp_client;
const struct adv7180_chip_info *chip_info;
enum v4l2_field field;
bool force_bt656_4;
};
#define to_adv7180_sd(_ctrl) (&container_of(_ctrl->handler, \
struct adv7180_state, \
@ -484,6 +487,19 @@ static void adv7180_set_power_pin(struct adv7180_state *state, bool on)
}
}
static void adv7180_set_reset_pin(struct adv7180_state *state, bool on)
{
if (!state->rst_gpio)
return;
if (on) {
gpiod_set_value_cansleep(state->rst_gpio, 1);
} else {
gpiod_set_value_cansleep(state->rst_gpio, 0);
usleep_range(5000, 10000);
}
}
static int adv7180_set_power(struct adv7180_state *state, bool on)
{
u8 val;
@ -963,10 +979,26 @@ static int adv7182_init(struct adv7180_state *state)
adv7180_write(state, ADV7180_REG_EXTENDED_OUTPUT_CONTROL, 0x57);
adv7180_write(state, ADV7180_REG_CTRL_2, 0xc0);
} else {
if (state->chip_info->flags & ADV7180_FLAG_V2)
adv7180_write(state,
ADV7180_REG_EXTENDED_OUTPUT_CONTROL,
0x17);
if (state->chip_info->flags & ADV7180_FLAG_V2) {
if (state->force_bt656_4) {
/* ITU-R BT.656-4 compatible */
adv7180_write(state,
ADV7180_REG_EXTENDED_OUTPUT_CONTROL,
ADV7180_EXTENDED_OUTPUT_CONTROL_NTSCDIS);
/* Manually set NEWAVMODE */
adv7180_write(state,
ADV7180_REG_VSYNC_FIELD_CTL_1,
ADV7180_VSYNC_FIELD_CTL_1_NEWAV);
/* Manually set V bit end position in NTSC mode */
adv7180_write(state,
ADV7180_REG_NTSC_V_BIT_END,
ADV7180_NTSC_V_BIT_END_MANUAL_NVEND);
} else {
adv7180_write(state,
ADV7180_REG_EXTENDED_OUTPUT_CONTROL,
0x17);
}
}
else
adv7180_write(state,
ADV7180_REG_EXTENDED_OUTPUT_CONTROL,
@ -1263,6 +1295,7 @@ static int init_device(struct adv7180_state *state)
mutex_lock(&state->mutex);
adv7180_set_power_pin(state, true);
adv7180_set_reset_pin(state, false);
adv7180_write(state, ADV7180_REG_PWR_MAN, ADV7180_PWR_MAN_RES);
usleep_range(5000, 10000);
@ -1314,6 +1347,7 @@ out_unlock:
static int adv7180_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct device_node *np = client->dev.of_node;
struct adv7180_state *state;
struct v4l2_subdev *sd;
int ret;
@ -1338,6 +1372,17 @@ static int adv7180_probe(struct i2c_client *client,
return ret;
}
state->rst_gpio = devm_gpiod_get_optional(&client->dev, "reset",
GPIOD_OUT_HIGH);
if (IS_ERR(state->rst_gpio)) {
ret = PTR_ERR(state->rst_gpio);
v4l_err(client, "request for reset pin failed: %d\n", ret);
return ret;
}
if (of_property_read_bool(np, "adv,force-bt656-4"))
state->force_bt656_4 = true;
if (state->chip_info->flags & ADV7180_FLAG_MIPI_CSI2) {
state->csi_client = i2c_new_dummy_device(client->adapter,
ADV7180_DEFAULT_CSI_I2C_ADDR);
@ -1392,11 +1437,19 @@ static int adv7180_probe(struct i2c_client *client,
if (ret)
goto err_free_irq;
v4l_info(client, "chip found @ 0x%02x (%s)\n",
client->addr, client->adapter->name);
mutex_lock(&state->mutex);
ret = adv7180_read(state, ADV7180_REG_IDENT);
mutex_unlock(&state->mutex);
if (ret < 0)
goto err_v4l2_async_unregister;
v4l_info(client, "chip id 0x%x found @ 0x%02x (%s)\n",
ret, client->addr, client->adapter->name);
return 0;
err_v4l2_async_unregister:
v4l2_async_unregister_subdev(sd);
err_free_irq:
if (state->irq > 0)
free_irq(client->irq, state);
@ -1428,6 +1481,7 @@ static int adv7180_remove(struct i2c_client *client)
i2c_unregister_device(state->vpp_client);
i2c_unregister_device(state->csi_client);
adv7180_set_reset_pin(state, true);
adv7180_set_power_pin(state, false);
mutex_destroy(&state->mutex);

View File

@ -1943,6 +1943,51 @@ static int ccs_set_stream(struct v4l2_subdev *subdev, int enable)
return rval;
}
static int ccs_pre_streamon(struct v4l2_subdev *subdev, u32 flags)
{
struct ccs_sensor *sensor = to_ccs_sensor(subdev);
struct i2c_client *client = v4l2_get_subdevdata(&sensor->src->sd);
int rval;
if (flags & V4L2_SUBDEV_PRE_STREAMON_FL_MANUAL_LP) {
switch (sensor->hwcfg.csi_signalling_mode) {
case CCS_CSI_SIGNALING_MODE_CSI_2_DPHY:
if (!(CCS_LIM(sensor, PHY_CTRL_CAPABILITY_2) &
CCS_PHY_CTRL_CAPABILITY_2_MANUAL_LP_DPHY))
return -EACCES;
break;
case CCS_CSI_SIGNALING_MODE_CSI_2_CPHY:
if (!(CCS_LIM(sensor, PHY_CTRL_CAPABILITY_2) &
CCS_PHY_CTRL_CAPABILITY_2_MANUAL_LP_CPHY))
return -EACCES;
break;
default:
return -EACCES;
}
}
rval = ccs_pm_get_init(sensor);
if (rval)
return rval;
if (flags & V4L2_SUBDEV_PRE_STREAMON_FL_MANUAL_LP) {
rval = ccs_write(sensor, MANUAL_LP_CTRL,
CCS_MANUAL_LP_CTRL_ENABLE);
if (rval)
pm_runtime_put(&client->dev);
}
return rval;
}
static int ccs_post_streamoff(struct v4l2_subdev *subdev)
{
struct ccs_sensor *sensor = to_ccs_sensor(subdev);
struct i2c_client *client = v4l2_get_subdevdata(&sensor->src->sd);
return pm_runtime_put(&client->dev);
}
static int ccs_enum_mbus_code(struct v4l2_subdev *subdev,
struct v4l2_subdev_state *sd_state,
struct v4l2_subdev_mbus_code_enum *code)
@ -2673,8 +2718,7 @@ static int ccs_get_skip_top_lines(struct v4l2_subdev *subdev, u32 *lines)
*/
static ssize_t
ccs_sysfs_nvm_read(struct device *dev, struct device_attribute *attr,
char *buf)
nvm_show(struct device *dev, struct device_attribute *attr, char *buf)
{
struct v4l2_subdev *subdev = i2c_get_clientdata(to_i2c_client(dev));
struct i2c_client *client = v4l2_get_subdevdata(subdev);
@ -2704,11 +2748,10 @@ ccs_sysfs_nvm_read(struct device *dev, struct device_attribute *attr,
*/
return rval;
}
static DEVICE_ATTR(nvm, S_IRUGO, ccs_sysfs_nvm_read, NULL);
static DEVICE_ATTR_RO(nvm);
static ssize_t
ccs_sysfs_ident_read(struct device *dev, struct device_attribute *attr,
char *buf)
ident_show(struct device *dev, struct device_attribute *attr, char *buf)
{
struct v4l2_subdev *subdev = i2c_get_clientdata(to_i2c_client(dev));
struct ccs_sensor *sensor = to_ccs_sensor(subdev);
@ -2723,8 +2766,7 @@ ccs_sysfs_ident_read(struct device *dev, struct device_attribute *attr,
minfo->smia_manufacturer_id, minfo->model_id,
minfo->revision_number) + 1;
}
static DEVICE_ATTR(ident, S_IRUGO, ccs_sysfs_ident_read, NULL);
static DEVICE_ATTR_RO(ident);
/* -----------------------------------------------------------------------------
* V4L2 subdev core operations
@ -3058,6 +3100,8 @@ static int ccs_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
static const struct v4l2_subdev_video_ops ccs_video_ops = {
.s_stream = ccs_set_stream,
.pre_streamon = ccs_pre_streamon,
.post_streamoff = ccs_post_streamoff,
};
static const struct v4l2_subdev_pad_ops ccs_pad_ops = {

View File

@ -1237,8 +1237,7 @@ out_poweroff:
* sysfs attributes
*/
static ssize_t
et8ek8_priv_mem_read(struct device *dev, struct device_attribute *attr,
char *buf)
priv_mem_show(struct device *dev, struct device_attribute *attr, char *buf)
{
struct v4l2_subdev *subdev = dev_get_drvdata(dev);
struct et8ek8_sensor *sensor = to_et8ek8_sensor(subdev);
@ -1251,7 +1250,7 @@ et8ek8_priv_mem_read(struct device *dev, struct device_attribute *attr,
return ET8EK8_PRIV_MEM_SIZE;
}
static DEVICE_ATTR(priv_mem, 0444, et8ek8_priv_mem_read, NULL);
static DEVICE_ATTR_RO(priv_mem);
/* --------------------------------------------------------------------------
* V4L2 subdev core operations

View File

@ -23,7 +23,7 @@
#define IMX258_CHIP_ID 0x0258
/* V_TIMING internal */
#define IMX258_VTS_30FPS 0x0c98
#define IMX258_VTS_30FPS 0x0c50
#define IMX258_VTS_30FPS_2K 0x0638
#define IMX258_VTS_30FPS_VGA 0x034c
#define IMX258_VTS_MAX 0xffff
@ -47,7 +47,7 @@
/* Analog gain control */
#define IMX258_REG_ANALOG_GAIN 0x0204
#define IMX258_ANA_GAIN_MIN 0
#define IMX258_ANA_GAIN_MAX 0x1fff
#define IMX258_ANA_GAIN_MAX 480
#define IMX258_ANA_GAIN_STEP 1
#define IMX258_ANA_GAIN_DEFAULT 0x0

1129
drivers/media/i2c/imx335.c Normal file

File diff suppressed because it is too large Load Diff

1272
drivers/media/i2c/imx412.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -51,7 +51,7 @@
#define OV2740_REG_MWB_R_GAIN 0x500a
#define OV2740_REG_MWB_G_GAIN 0x500c
#define OV2740_REG_MWB_B_GAIN 0x500e
#define OV2740_DGTL_GAIN_MIN 0
#define OV2740_DGTL_GAIN_MIN 1024
#define OV2740_DGTL_GAIN_MAX 4095
#define OV2740_DGTL_GAIN_STEP 1
#define OV2740_DGTL_GAIN_DEFAULT 1024
@ -61,6 +61,12 @@
#define OV2740_TEST_PATTERN_ENABLE BIT(7)
#define OV2740_TEST_PATTERN_BAR_SHIFT 2
/* Group Access */
#define OV2740_REG_GROUP_ACCESS 0x3208
#define OV2740_GROUP_HOLD_START 0x0
#define OV2740_GROUP_HOLD_END 0x10
#define OV2740_GROUP_HOLD_LAUNCH 0xa0
/* ISP CTRL00 */
#define OV2740_REG_ISP_CTRL00 0x5000
/* ISP CTRL01 */
@ -438,6 +444,11 @@ static int ov2740_update_digital_gain(struct ov2740 *ov2740, u32 d_gain)
{
int ret = 0;
ret = ov2740_write_reg(ov2740, OV2740_REG_GROUP_ACCESS, 1,
OV2740_GROUP_HOLD_START);
if (ret)
return ret;
ret = ov2740_write_reg(ov2740, OV2740_REG_MWB_R_GAIN, 2, d_gain);
if (ret)
return ret;
@ -446,7 +457,18 @@ static int ov2740_update_digital_gain(struct ov2740 *ov2740, u32 d_gain)
if (ret)
return ret;
return ov2740_write_reg(ov2740, OV2740_REG_MWB_B_GAIN, 2, d_gain);
ret = ov2740_write_reg(ov2740, OV2740_REG_MWB_B_GAIN, 2, d_gain);
if (ret)
return ret;
ret = ov2740_write_reg(ov2740, OV2740_REG_GROUP_ACCESS, 1,
OV2740_GROUP_HOLD_END);
if (ret)
return ret;
ret = ov2740_write_reg(ov2740, OV2740_REG_GROUP_ACCESS, 1,
OV2740_GROUP_HOLD_LAUNCH);
return ret;
}
static int ov2740_test_pattern(struct ov2740 *ov2740, u32 pattern)

View File

@ -135,7 +135,9 @@ struct ov5640_pixfmt {
static const struct ov5640_pixfmt ov5640_formats[] = {
{ MEDIA_BUS_FMT_JPEG_1X8, V4L2_COLORSPACE_JPEG, },
{ MEDIA_BUS_FMT_UYVY8_2X8, V4L2_COLORSPACE_SRGB, },
{ MEDIA_BUS_FMT_UYVY8_1X16, V4L2_COLORSPACE_SRGB, },
{ MEDIA_BUS_FMT_YUYV8_2X8, V4L2_COLORSPACE_SRGB, },
{ MEDIA_BUS_FMT_YUYV8_1X16, V4L2_COLORSPACE_SRGB, },
{ MEDIA_BUS_FMT_RGB565_2X8_LE, V4L2_COLORSPACE_SRGB, },
{ MEDIA_BUS_FMT_RGB565_2X8_BE, V4L2_COLORSPACE_SRGB, },
{ MEDIA_BUS_FMT_SBGGR8_1X8, V4L2_COLORSPACE_SRGB, },
@ -2338,11 +2340,13 @@ static int ov5640_set_framefmt(struct ov5640_dev *sensor,
u8 fmt, mux;
switch (format->code) {
case MEDIA_BUS_FMT_UYVY8_1X16:
case MEDIA_BUS_FMT_UYVY8_2X8:
/* YUV422, UYVY */
fmt = 0x3f;
mux = OV5640_FMT_MUX_YUV422;
break;
case MEDIA_BUS_FMT_YUYV8_1X16:
case MEDIA_BUS_FMT_YUYV8_2X8:
/* YUV422, YUYV */
fmt = 0x30;

View File

@ -2304,25 +2304,26 @@ static int ov8856_get_hwcfg(struct ov8856 *ov8856, struct device *dev)
clk_set_rate(ov8856->xvclk, xvclk_rate);
xvclk_rate = clk_get_rate(ov8856->xvclk);
ov8856->reset_gpio = devm_gpiod_get_optional(dev, "reset",
GPIOD_OUT_LOW);
if (IS_ERR(ov8856->reset_gpio))
return PTR_ERR(ov8856->reset_gpio);
for (i = 0; i < ARRAY_SIZE(ov8856_supply_names); i++)
ov8856->supplies[i].supply = ov8856_supply_names[i];
ret = devm_regulator_bulk_get(dev,
ARRAY_SIZE(ov8856_supply_names),
ov8856->supplies);
if (ret)
return ret;
}
if (xvclk_rate != OV8856_XVCLK_19_2)
dev_warn(dev, "external clock rate %u is unsupported",
xvclk_rate);
ov8856->reset_gpio = devm_gpiod_get_optional(dev, "reset",
GPIOD_OUT_LOW);
if (IS_ERR(ov8856->reset_gpio))
return PTR_ERR(ov8856->reset_gpio);
for (i = 0; i < ARRAY_SIZE(ov8856_supply_names); i++)
ov8856->supplies[i].supply = ov8856_supply_names[i];
ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(ov8856_supply_names),
ov8856->supplies);
if (ret)
return ret;
ep = fwnode_graph_get_next_endpoint(fwnode, NULL);
if (!ep)
return -ENXIO;

1137
drivers/media/i2c/ov9282.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -60,6 +60,12 @@
#define OV9734_TEST_PATTERN_ENABLE BIT(7)
#define OV9734_TEST_PATTERN_BAR_SHIFT 2
/* Group Access */
#define OV9734_REG_GROUP_ACCESS 0x3208
#define OV9734_GROUP_HOLD_START 0x0
#define OV9734_GROUP_HOLD_END 0x10
#define OV9734_GROUP_HOLD_LAUNCH 0xa0
enum {
OV9734_LINK_FREQ_180MHZ_INDEX,
};
@ -433,6 +439,11 @@ static int ov9734_update_digital_gain(struct ov9734 *ov9734, u32 d_gain)
{
int ret;
ret = ov9734_write_reg(ov9734, OV9734_REG_GROUP_ACCESS, 1,
OV9734_GROUP_HOLD_START);
if (ret)
return ret;
ret = ov9734_write_reg(ov9734, OV9734_REG_MWB_R_GAIN, 2, d_gain);
if (ret)
return ret;
@ -441,7 +452,18 @@ static int ov9734_update_digital_gain(struct ov9734 *ov9734, u32 d_gain)
if (ret)
return ret;
return ov9734_write_reg(ov9734, OV9734_REG_MWB_B_GAIN, 2, d_gain);
ret = ov9734_write_reg(ov9734, OV9734_REG_MWB_B_GAIN, 2, d_gain);
if (ret)
return ret;
ret = ov9734_write_reg(ov9734, OV9734_REG_GROUP_ACCESS, 1,
OV9734_GROUP_HOLD_END);
if (ret)
return ret;
ret = ov9734_write_reg(ov9734, OV9734_REG_GROUP_ACCESS, 1,
OV9734_GROUP_HOLD_LAUNCH);
return ret;
}
static int ov9734_test_pattern(struct ov9734 *ov9734, u32 pattern)

View File

@ -563,7 +563,7 @@ static void tda1997x_delayed_work_enable_hpd(struct work_struct *work)
delayed_work_enable_hpd);
struct v4l2_subdev *sd = &state->sd;
v4l2_dbg(2, debug, sd, "%s:\n", __func__);
v4l2_dbg(2, debug, sd, "%s\n", __func__);
/* Set HPD high */
tda1997x_manual_hpd(sd, HPD_HIGH_OTHER);
@ -1107,7 +1107,8 @@ tda1997x_detect_std(struct tda1997x_state *state,
hper = io_read16(sd, REG_H_PER) & MASK_HPER;
hsper = io_read16(sd, REG_HS_WIDTH) & MASK_HSWIDTH;
v4l2_dbg(1, debug, sd, "Signal Timings: %u/%u/%u\n", vper, hper, hsper);
if (!vper || !hper || !hsper)
if (!state->input_detect[0] && !state->input_detect[1])
return -ENOLINK;
for (i = 0; v4l2_dv_timings_presets[i].bt.width; i++) {
@ -1695,14 +1696,15 @@ static int tda1997x_query_dv_timings(struct v4l2_subdev *sd,
struct v4l2_dv_timings *timings)
{
struct tda1997x_state *state = to_state(sd);
int ret;
v4l_dbg(1, debug, state->client, "%s\n", __func__);
memset(timings, 0, sizeof(struct v4l2_dv_timings));
mutex_lock(&state->lock);
tda1997x_detect_std(state, timings);
ret = tda1997x_detect_std(state, timings);
mutex_unlock(&state->lock);
return 0;
return ret;
}
static const struct v4l2_subdev_video_ops tda1997x_video_ops = {
@ -2233,6 +2235,7 @@ static int tda1997x_core_init(struct v4l2_subdev *sd)
/* get initial HDMI status */
state->hdmi_status = io_read(sd, REG_HDMI_FLAGS);
io_write(sd, REG_EDID_ENABLE, EDID_ENABLE_A_EN | EDID_ENABLE_B_EN);
return 0;
}

View File

@ -964,7 +964,7 @@ static int tvp5150_enable(struct v4l2_subdev *sd)
/*
* Enable the YCbCr and clock outputs. In discrete sync mode
* (non-BT.656) additionally enable the the sync outputs.
* (non-BT.656) additionally enable the sync outputs.
*/
switch (decoder->mbus_type) {
case V4L2_MBUS_PARALLEL:

View File

@ -556,7 +556,7 @@ static const struct media_file_operations media_device_fops = {
* sysfs
*/
static ssize_t show_model(struct device *cd,
static ssize_t model_show(struct device *cd,
struct device_attribute *attr, char *buf)
{
struct media_devnode *devnode = to_media_devnode(cd);
@ -565,7 +565,7 @@ static ssize_t show_model(struct device *cd,
return sprintf(buf, "%.*s\n", (int)sizeof(mdev->model), mdev->model);
}
static DEVICE_ATTR(model, S_IRUGO, show_model, NULL);
static DEVICE_ATTR_RO(model);
/* -----------------------------------------------------------------------------
* Registration/unregistration

View File

@ -78,27 +78,53 @@
#define IVTV_PCI_ID_SONY 0x104d
/* hardware flags, no gaps allowed */
#define IVTV_HW_CX25840 (1 << 0)
#define IVTV_HW_SAA7115 (1 << 1)
#define IVTV_HW_SAA7127 (1 << 2)
#define IVTV_HW_MSP34XX (1 << 3)
#define IVTV_HW_TUNER (1 << 4)
#define IVTV_HW_WM8775 (1 << 5)
#define IVTV_HW_CS53L32A (1 << 6)
#define IVTV_HW_TVEEPROM (1 << 7)
#define IVTV_HW_SAA7114 (1 << 8)
#define IVTV_HW_UPD64031A (1 << 9)
#define IVTV_HW_UPD6408X (1 << 10)
#define IVTV_HW_SAA717X (1 << 11)
#define IVTV_HW_WM8739 (1 << 12)
#define IVTV_HW_VP27SMPX (1 << 13)
#define IVTV_HW_M52790 (1 << 14)
#define IVTV_HW_GPIO (1 << 15)
#define IVTV_HW_I2C_IR_RX_AVER (1 << 16)
#define IVTV_HW_I2C_IR_RX_HAUP_EXT (1 << 17) /* External before internal */
#define IVTV_HW_I2C_IR_RX_HAUP_INT (1 << 18)
#define IVTV_HW_Z8F0811_IR_HAUP (1 << 19)
#define IVTV_HW_I2C_IR_RX_ADAPTEC (1 << 20)
enum ivtv_hw_bits {
IVTV_HW_BIT_CX25840,
IVTV_HW_BIT_SAA7115,
IVTV_HW_BIT_SAA7127,
IVTV_HW_BIT_MSP34XX,
IVTV_HW_BIT_TUNER,
IVTV_HW_BIT_WM8775,
IVTV_HW_BIT_CS53L32A,
IVTV_HW_BIT_TVEEPROM,
IVTV_HW_BIT_SAA7114,
IVTV_HW_BIT_UPD64031A,
IVTV_HW_BIT_UPD6408X,
IVTV_HW_BIT_SAA717X,
IVTV_HW_BIT_WM8739,
IVTV_HW_BIT_VP27SMPX,
IVTV_HW_BIT_M52790,
IVTV_HW_BIT_GPIO,
IVTV_HW_BIT_I2C_IR_RX_AVER,
IVTV_HW_BIT_I2C_IR_RX_HAUP_EXT, /* External before internal */
IVTV_HW_BIT_I2C_IR_RX_HAUP_INT,
IVTV_HW_BIT_Z8F0811_IR_HAUP,
IVTV_HW_BIT_I2C_IR_RX_ADAPTEC,
IVTV_HW_MAX_BITS /* Should be the last one */
};
#define IVTV_HW_CX25840 BIT(IVTV_HW_BIT_CX25840)
#define IVTV_HW_SAA7115 BIT(IVTV_HW_BIT_SAA7115)
#define IVTV_HW_SAA7127 BIT(IVTV_HW_BIT_SAA7127)
#define IVTV_HW_MSP34XX BIT(IVTV_HW_BIT_MSP34XX)
#define IVTV_HW_TUNER BIT(IVTV_HW_BIT_TUNER)
#define IVTV_HW_WM8775 BIT(IVTV_HW_BIT_WM8775)
#define IVTV_HW_CS53L32A BIT(IVTV_HW_BIT_CS53L32A)
#define IVTV_HW_TVEEPROM BIT(IVTV_HW_BIT_TVEEPROM)
#define IVTV_HW_SAA7114 BIT(IVTV_HW_BIT_SAA7114)
#define IVTV_HW_UPD64031A BIT(IVTV_HW_BIT_UPD64031A)
#define IVTV_HW_UPD6408X BIT(IVTV_HW_BIT_UPD6408X)
#define IVTV_HW_SAA717X BIT(IVTV_HW_BIT_SAA717X)
#define IVTV_HW_WM8739 BIT(IVTV_HW_BIT_WM8739)
#define IVTV_HW_VP27SMPX BIT(IVTV_HW_BIT_VP27SMPX)
#define IVTV_HW_M52790 BIT(IVTV_HW_BIT_M52790)
#define IVTV_HW_GPIO BIT(IVTV_HW_BIT_GPIO)
#define IVTV_HW_I2C_IR_RX_AVER BIT(IVTV_HW_BIT_I2C_IR_RX_AVER)
#define IVTV_HW_I2C_IR_RX_HAUP_EXT BIT(IVTV_HW_BIT_I2C_IR_RX_HAUP_EXT)
#define IVTV_HW_I2C_IR_RX_HAUP_INT BIT(IVTV_HW_BIT_I2C_IR_RX_HAUP_INT)
#define IVTV_HW_Z8F0811_IR_HAUP BIT(IVTV_HW_BIT_Z8F0811_IR_HAUP)
#define IVTV_HW_I2C_IR_RX_ADAPTEC BIT(IVTV_HW_BIT_I2C_IR_RX_ADAPTEC)
#define IVTV_HW_SAA711X (IVTV_HW_SAA7115 | IVTV_HW_SAA7114)

View File

@ -85,7 +85,7 @@
#define IVTV_ADAPTEC_IR_ADDR 0x6b
/* This array should match the IVTV_HW_ defines */
static const u8 hw_addrs[] = {
static const u8 hw_addrs[IVTV_HW_MAX_BITS] = {
IVTV_CX25840_I2C_ADDR,
IVTV_SAA7115_I2C_ADDR,
IVTV_SAA7127_I2C_ADDR,
@ -110,7 +110,7 @@ static const u8 hw_addrs[] = {
};
/* This array should match the IVTV_HW_ defines */
static const char * const hw_devicenames[] = {
static const char * const hw_devicenames[IVTV_HW_MAX_BITS] = {
"cx25840",
"saa7115",
"saa7127_auto", /* saa7127 or saa7129 */
@ -240,10 +240,16 @@ void ivtv_i2c_new_ir_legacy(struct ivtv *itv)
int ivtv_i2c_register(struct ivtv *itv, unsigned idx)
{
struct v4l2_subdev *sd;
struct i2c_adapter *adap = &itv->i2c_adap;
const char *type = hw_devicenames[idx];
u32 hw = 1 << idx;
struct v4l2_subdev *sd;
const char *type;
u32 hw;
if (idx >= IVTV_HW_MAX_BITS)
return -ENODEV;
type = hw_devicenames[idx];
hw = 1 << idx;
if (hw == IVTV_HW_TUNER) {
/* special tuner handling */

View File

@ -1215,15 +1215,13 @@ static int alsa_device_exit(struct saa7134_dev *dev)
static int saa7134_alsa_init(void)
{
struct saa7134_dev *dev = NULL;
struct list_head *list;
saa7134_dmasound_init = alsa_device_init;
saa7134_dmasound_exit = alsa_device_exit;
pr_info("saa7134 ALSA driver for DMA sound loaded\n");
list_for_each(list,&saa7134_devlist) {
dev = list_entry(list, struct saa7134_dev, devlist);
list_for_each_entry(dev, &saa7134_devlist, devlist) {
if (dev->pci->device == PCI_DEVICE_ID_PHILIPS_SAA7130)
pr_info("%s/alsa: %s doesn't support digital audio\n",
dev->name, saa7134_boards[dev->board].name);

View File

@ -223,7 +223,8 @@ int saa7134_pgtable_alloc(struct pci_dev *pci, struct saa7134_pgtable *pt)
__le32 *cpu;
dma_addr_t dma_addr = 0;
cpu = pci_alloc_consistent(pci, SAA7134_PGTABLE_SIZE, &dma_addr);
cpu = dma_alloc_coherent(&pci->dev, SAA7134_PGTABLE_SIZE, &dma_addr,
GFP_KERNEL);
if (NULL == cpu)
return -ENOMEM;
pt->size = SAA7134_PGTABLE_SIZE;
@ -254,7 +255,7 @@ void saa7134_pgtable_free(struct pci_dev *pci, struct saa7134_pgtable *pt)
{
if (NULL == pt->cpu)
return;
pci_free_consistent(pci, pt->size, pt->cpu, pt->dma);
dma_free_coherent(&pci->dev, pt->size, pt->cpu, pt->dma);
pt->cpu = NULL;
}
@ -1092,7 +1093,7 @@ static int saa7134_initdev(struct pci_dev *pci_dev,
dev->pci_lat,
(unsigned long long)pci_resource_start(pci_dev, 0));
pci_set_master(pci_dev);
err = pci_set_dma_mask(pci_dev, DMA_BIT_MASK(32));
err = dma_set_mask(&pci_dev->dev, DMA_BIT_MASK(32));
if (err) {
pr_warn("%s: Oops: no 32bit PCI DMA ???\n", dev->name);
goto err_v4l2_unregister;

View File

@ -549,9 +549,6 @@ int saa7164_cmd_send(struct saa7164_dev *dev, u8 id, enum tmComResCmd command,
/* See of other commands are on the bus */
if (saa7164_cmd_dequeue(dev) != SAA_OK)
printk(KERN_ERR "dequeue(3) failed\n");
continue;
} /* (loop) */
/* Release the sequence number allocation */

View File

@ -663,7 +663,7 @@
#define TW5864_SYNC 0x8008
/* Define controls in register TW5864_SYNC */
/*
* 0 vlc stream to syncrous port
* 0 vlc stream to synchronous port
* 1 vlc stream to ddr buffers
*/
#define TW5864_SYNC_CFG BIT(7)

View File

@ -255,6 +255,23 @@ static void isc_sama5d2_config_rlp(struct isc_device *isc)
struct regmap *regmap = isc->regmap;
u32 rlp_mode = isc->config.rlp_cfg_mode;
/*
* In sama5d2, the YUV planar modes and the YUYV modes are treated
* in the same way in RLP register.
* Normally, YYCC mode should be Luma(n) - Color B(n) - Color R (n)
* and YCYC should be Luma(n + 1) - Color B (n) - Luma (n) - Color R (n)
* but in sama5d2, the YCYC mode does not exist, and YYCC must be
* selected for both planar and interleaved modes, as in fact
* both modes are supported.
*
* Thus, if the YCYC mode is selected, replace it with the
* sama5d2-compliant mode which is YYCC .
*/
if ((rlp_mode & ISC_RLP_CFG_MODE_YCYC) == ISC_RLP_CFG_MODE_YCYC) {
rlp_mode &= ~ISC_RLP_CFG_MODE_MASK;
rlp_mode |= ISC_RLP_CFG_MODE_YYCC;
}
regmap_update_bits(regmap, ISC_RLP_CFG + isc->offsets.rlp,
ISC_RLP_CFG_MODE_MASK, rlp_mode);
}

View File

@ -2053,17 +2053,25 @@ static int __coda_start_decoding(struct coda_ctx *ctx)
u32 src_fourcc, dst_fourcc;
int ret;
if (!ctx->initialized) {
ret = __coda_decoder_seq_init(ctx);
if (ret < 0)
return ret;
}
q_data_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT);
q_data_dst = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE);
src_fourcc = q_data_src->fourcc;
dst_fourcc = q_data_dst->fourcc;
if (!ctx->initialized) {
ret = __coda_decoder_seq_init(ctx);
if (ret < 0)
return ret;
} else {
ctx->frame_mem_ctrl &= ~(CODA_FRAME_CHROMA_INTERLEAVE | (0x3 << 9) |
CODA9_FRAME_TILED2LINEAR);
if (dst_fourcc == V4L2_PIX_FMT_NV12 || dst_fourcc == V4L2_PIX_FMT_YUYV)
ctx->frame_mem_ctrl |= CODA_FRAME_CHROMA_INTERLEAVE;
if (ctx->tiled_map_type == GDI_TILED_FRAME_MB_RASTER_MAP)
ctx->frame_mem_ctrl |= (0x3 << 9) |
((ctx->use_vdoa) ? 0 : CODA9_FRAME_TILED2LINEAR);
}
coda_write(dev, ctx->parabuf.paddr, CODA_REG_BIT_PARA_BUF_ADDR);
ret = coda_alloc_framebuffers(ctx, q_data_dst, src_fourcc);

View File

@ -189,7 +189,7 @@ int vpfe_register_ccdc_device(const struct ccdc_hw_device *dev)
if (!ccdc_cfg) {
/*
* TODO. Will this ever happen? if so, we need to fix it.
* Proabably we need to add the request to a linked list and
* Probably we need to add the request to a linked list and
* walk through it during vpfe probe
*/
printk(KERN_ERR "vpfe capture not initialized\n");

View File

@ -1238,8 +1238,8 @@ static const struct media_device_ops fimc_md_ops = {
.link_notify = fimc_md_link_notify,
};
static ssize_t fimc_md_sysfs_show(struct device *dev,
struct device_attribute *attr, char *buf)
static ssize_t subdev_conf_mode_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct fimc_md *fmd = dev_get_drvdata(dev);
@ -1249,9 +1249,9 @@ static ssize_t fimc_md_sysfs_show(struct device *dev,
return strscpy(buf, "V4L2 video node only API (vid-dev)\n", PAGE_SIZE);
}
static ssize_t fimc_md_sysfs_store(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
static ssize_t subdev_conf_mode_store(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
struct fimc_md *fmd = dev_get_drvdata(dev);
bool subdev_api;
@ -1278,8 +1278,7 @@ static ssize_t fimc_md_sysfs_store(struct device *dev,
* sub-dev - for media controller API, subdevs must be configured in user
* space before starting streaming.
*/
static DEVICE_ATTR(subdev_conf_mode, S_IWUSR | S_IRUGO,
fimc_md_sysfs_show, fimc_md_sysfs_store);
static DEVICE_ATTR_RW(subdev_conf_mode);
static int cam_clk_prepare(struct clk_hw *hw)
{

View File

@ -692,7 +692,7 @@ static void mcam_dma_sg_done(struct mcam_camera *cam, int frame)
* Scatter/gather mode requires stopping the controller between
* frames so we can put in a new DMA descriptor array. If no new
* buffer exists at frame completion, the controller is left stopped;
* this function is charged with gettig things going again.
* this function is charged with getting things going again.
*/
static void mcam_sg_restart(struct mcam_camera *cam)
{

View File

@ -2037,8 +2037,10 @@ static int isp_subdev_notifier_complete(struct v4l2_async_notifier *async)
mutex_lock(&isp->media_dev.graph_mutex);
ret = media_entity_enum_init(&isp->crashed, &isp->media_dev);
if (ret)
if (ret) {
mutex_unlock(&isp->media_dev.graph_mutex);
return ret;
}
list_for_each_entry(sd, &v4l2_dev->subdevs, list) {
if (sd->notifier != &isp->notifier)

View File

@ -234,6 +234,7 @@ struct venc_controls {
u32 h264_loop_filter_mode;
s32 h264_loop_filter_alpha;
s32 h264_loop_filter_beta;
u32 h264_8x8_transform;
u32 hevc_i_qp;
u32 hevc_p_qp;
@ -256,6 +257,7 @@ struct venc_controls {
u32 header_mode;
bool aud_enable;
u32 intra_refresh_period;
struct {
u32 h264;

View File

@ -1137,6 +1137,9 @@ int venus_helper_set_format_constraints(struct venus_inst *inst)
if (!IS_V6(inst->core))
return 0;
if (inst->opb_fmt == HFI_COLOR_FORMAT_NV12_UBWC)
return 0;
pconstraint.buffer_type = HFI_BUFFER_OUTPUT2;
pconstraint.num_planes = 2;
pconstraint.plane_format[0].stride_multiples = 128;

View File

@ -1239,6 +1239,14 @@ pkt_session_set_property_4xx(struct hfi_session_set_property_pkt *pkt,
break;
}
case HFI_PROPERTY_PARAM_VENC_H264_TRANSFORM_8X8: {
struct hfi_h264_8x8_transform *in = pdata, *tm = prop_data;
tm->enable_type = in->enable_type;
pkt->shdr.hdr.size += sizeof(u32) + sizeof(*tm);
break;
}
case HFI_PROPERTY_CONFIG_VENC_MAX_BITRATE:
case HFI_PROPERTY_CONFIG_VDEC_POST_LOOP_DEBLOCKER:
case HFI_PROPERTY_PARAM_BUFFER_ALLOC_MODE:

View File

@ -507,6 +507,7 @@
#define HFI_PROPERTY_PARAM_VENC_MAX_NUM_B_FRAMES 0x2005020
#define HFI_PROPERTY_PARAM_VENC_H264_VUI_BITSTREAM_RESTRC 0x2005021
#define HFI_PROPERTY_PARAM_VENC_PRESERVE_TEXT_QUALITY 0x2005023
#define HFI_PROPERTY_PARAM_VENC_H264_TRANSFORM_8X8 0x2005025
#define HFI_PROPERTY_PARAM_VENC_HIER_P_MAX_NUM_ENH_LAYER 0x2005026
#define HFI_PROPERTY_PARAM_VENC_DISABLE_RC_TIMESTAMP 0x2005027
#define HFI_PROPERTY_PARAM_VENC_INITIAL_QP 0x2005028
@ -562,6 +563,10 @@ struct hfi_bitrate {
u32 layer_id;
};
struct hfi_h264_8x8_transform {
u32 enable_type;
};
#define HFI_CAPABILITY_FRAME_WIDTH 0x01
#define HFI_CAPABILITY_FRAME_HEIGHT 0x02
#define HFI_CAPABILITY_MBS_PER_FRAME 0x03

View File

@ -261,7 +261,7 @@ sys_get_prop_image_version(struct device *dev,
smem_tbl_ptr = qcom_smem_get(QCOM_SMEM_HOST_ANY,
SMEM_IMG_VER_TBL, &smem_blk_sz);
if (smem_tbl_ptr && smem_blk_sz >= SMEM_IMG_OFFSET_VENUS + VER_STR_SZ)
if (!IS_ERR(smem_tbl_ptr) && smem_blk_sz >= SMEM_IMG_OFFSET_VENUS + VER_STR_SZ)
memcpy(smem_tbl_ptr + SMEM_IMG_OFFSET_VENUS,
img_ver, VER_STR_SZ);
}

View File

@ -183,6 +183,8 @@ venc_try_fmt_common(struct venus_inst *inst, struct v4l2_format *f)
else
return NULL;
fmt = find_format(inst, pixmp->pixelformat, f->type);
if (!fmt)
return NULL;
}
pixmp->width = clamp(pixmp->width, frame_width_min(inst),
@ -547,6 +549,7 @@ static int venc_set_properties(struct venus_inst *inst)
struct hfi_quantization_range quant_range;
struct hfi_enable en;
struct hfi_ltr_mode ltr_mode;
struct hfi_intra_refresh intra_refresh = {};
u32 ptype, rate_control, bitrate;
u32 profile, level;
int ret;
@ -567,6 +570,7 @@ static int venc_set_properties(struct venus_inst *inst)
struct hfi_h264_vui_timing_info info;
struct hfi_h264_entropy_control entropy;
struct hfi_h264_db_control deblock;
struct hfi_h264_8x8_transform h264_transform;
ptype = HFI_PROPERTY_PARAM_VENC_H264_VUI_TIMING_INFO;
info.enable = 1;
@ -597,6 +601,17 @@ static int venc_set_properties(struct venus_inst *inst)
ret = hfi_session_set_property(inst, ptype, &deblock);
if (ret)
return ret;
ptype = HFI_PROPERTY_PARAM_VENC_H264_TRANSFORM_8X8;
h264_transform.enable_type = 0;
if (ctr->profile.h264 == HFI_H264_PROFILE_HIGH ||
ctr->profile.h264 == HFI_H264_PROFILE_CONSTRAINED_HIGH)
h264_transform.enable_type = ctr->h264_8x8_transform;
ret = hfi_session_set_property(inst, ptype, &h264_transform);
if (ret)
return ret;
}
if (inst->fmt_cap->pixfmt == V4L2_PIX_FMT_H264 ||
@ -802,6 +817,31 @@ static int venc_set_properties(struct venus_inst *inst)
en.enable = 1;
ret = hfi_session_set_property(inst, ptype, &en);
}
if ((inst->fmt_cap->pixfmt == V4L2_PIX_FMT_H264 ||
inst->fmt_cap->pixfmt == V4L2_PIX_FMT_HEVC) &&
(rate_control == HFI_RATE_CONTROL_CBR_VFR ||
rate_control == HFI_RATE_CONTROL_CBR_CFR)) {
intra_refresh.mode = HFI_INTRA_REFRESH_NONE;
intra_refresh.cir_mbs = 0;
if (ctr->intra_refresh_period) {
u32 mbs;
mbs = ALIGN(inst->width, 16) * ALIGN(inst->height, 16);
mbs /= 16 * 16;
if (mbs % ctr->intra_refresh_period)
mbs++;
mbs /= ctr->intra_refresh_period;
intra_refresh.mode = HFI_INTRA_REFRESH_RANDOM;
intra_refresh.cir_mbs = mbs;
}
ptype = HFI_PROPERTY_PARAM_VENC_INTRA_REFRESH;
ret = hfi_session_set_property(inst, ptype, &intra_refresh);
if (ret)
return ret;
}

View File

@ -17,7 +17,6 @@
#define SLICE_BYTE_SIZE_MAX 1024
#define SLICE_BYTE_SIZE_MIN 1024
#define SLICE_MB_SIZE_MAX 300
#define INTRA_REFRESH_MBS_MAX 300
#define AT_SLICE_BOUNDARY \
V4L2_MPEG_VIDEO_H264_LOOP_FILTER_MODE_DISABLED_AT_SLICE_BOUNDARY
#define MAX_LTR_FRAME_COUNT 4
@ -227,8 +226,6 @@ static int venc_op_s_ctrl(struct v4l2_ctrl *ctrl)
}
mutex_unlock(&inst->lock);
break;
case V4L2_CID_MPEG_VIDEO_CYCLIC_INTRA_REFRESH_MB:
break;
case V4L2_CID_MPEG_VIDEO_GOP_SIZE:
ret = venc_calc_bpframes(ctrl->val, ctr->num_b_frames, &bframes,
&ctr->num_p_frames);
@ -319,6 +316,28 @@ static int venc_op_s_ctrl(struct v4l2_ctrl *ctrl)
case V4L2_CID_COLORIMETRY_HDR10_MASTERING_DISPLAY:
ctr->mastering = *ctrl->p_new.p_hdr10_mastering;
break;
case V4L2_CID_MPEG_VIDEO_INTRA_REFRESH_PERIOD:
ctr->intra_refresh_period = ctrl->val;
break;
case V4L2_CID_MPEG_VIDEO_H264_8X8_TRANSFORM:
if (ctr->profile.h264 != HFI_H264_PROFILE_HIGH &&
ctr->profile.h264 != HFI_H264_PROFILE_CONSTRAINED_HIGH)
return -EINVAL;
/*
* In video firmware, 8x8 transform is supported only for
* high profile(HP) and constrained high profile(CHP).
* If client wants to disable 8x8 transform for HP/CHP,
* it is better to set profile as main profile(MP).
* Because there is no difference between HP and MP
* if we disable 8x8 transform for HP.
*/
if (ctrl->val == 0)
return -EINVAL;
ctr->h264_8x8_transform = ctrl->val;
break;
default:
return -EINVAL;
}
@ -334,7 +353,7 @@ int venc_ctrl_init(struct venus_inst *inst)
{
int ret;
ret = v4l2_ctrl_handler_init(&inst->ctrl_handler, 57);
ret = v4l2_ctrl_handler_init(&inst->ctrl_handler, 58);
if (ret)
return ret;
@ -437,6 +456,9 @@ int venc_ctrl_init(struct venus_inst *inst)
v4l2_ctrl_new_std(&inst->ctrl_handler, &venc_ctrl_ops,
V4L2_CID_MPEG_VIDEO_H264_I_FRAME_MIN_QP, 1, 51, 1, 1);
v4l2_ctrl_new_std(&inst->ctrl_handler, &venc_ctrl_ops,
V4L2_CID_MPEG_VIDEO_H264_8X8_TRANSFORM, 0, 1, 1, 0);
v4l2_ctrl_new_std(&inst->ctrl_handler, &venc_ctrl_ops,
V4L2_CID_MPEG_VIDEO_H264_P_FRAME_MIN_QP, 1, 51, 1, 1);
@ -502,10 +524,6 @@ int venc_ctrl_init(struct venus_inst *inst)
v4l2_ctrl_new_std(&inst->ctrl_handler, &venc_ctrl_ops,
V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_BETA, -6, 6, 1, 0);
v4l2_ctrl_new_std(&inst->ctrl_handler, &venc_ctrl_ops,
V4L2_CID_MPEG_VIDEO_CYCLIC_INTRA_REFRESH_MB,
0, INTRA_REFRESH_MBS_MAX, 1, 0);
v4l2_ctrl_new_std(&inst->ctrl_handler, &venc_ctrl_ops,
V4L2_CID_MPEG_VIDEO_GOP_SIZE, 0, (1 << 16) - 1, 1, 30);
@ -564,6 +582,10 @@ int venc_ctrl_init(struct venus_inst *inst)
V4L2_CID_COLORIMETRY_HDR10_MASTERING_DISPLAY,
v4l2_ctrl_ptr_create(NULL));
v4l2_ctrl_new_std(&inst->ctrl_handler, &venc_ctrl_ops,
V4L2_CID_MPEG_VIDEO_INTRA_REFRESH_PERIOD, 0,
((4096 * 2304) >> 8), 1, 0);
ret = inst->ctrl_handler.error;
if (ret)
goto err;

View File

@ -253,8 +253,8 @@ static int rvin_try_format(struct rvin_dev *vin, u32 which,
int ret;
sd_state = v4l2_subdev_alloc_state(sd);
if (sd_state == NULL)
return -ENOMEM;
if (IS_ERR(sd_state))
return PTR_ERR(sd_state);
if (!rvin_format_from_pixel(vin, pix->pixelformat))
pix->pixelformat = RVIN_DEFAULT_FORMAT;

View File

@ -863,12 +863,12 @@ static int rga_probe(struct platform_device *pdev)
if (IS_ERR(rga->m2m_dev)) {
v4l2_err(&rga->v4l2_dev, "Failed to init mem2mem device\n");
ret = PTR_ERR(rga->m2m_dev);
goto unreg_video_dev;
goto rel_vdev;
}
ret = pm_runtime_resume_and_get(rga->dev);
if (ret < 0)
goto unreg_video_dev;
goto rel_vdev;
rga->version.major = (rga_read(rga, RGA_VERSION_INFO) >> 24) & 0xFF;
rga->version.minor = (rga_read(rga, RGA_VERSION_INFO) >> 20) & 0x0F;
@ -882,11 +882,23 @@ static int rga_probe(struct platform_device *pdev)
rga->cmdbuf_virt = dma_alloc_attrs(rga->dev, RGA_CMDBUF_SIZE,
&rga->cmdbuf_phy, GFP_KERNEL,
DMA_ATTR_WRITE_COMBINE);
if (!rga->cmdbuf_virt) {
ret = -ENOMEM;
goto rel_vdev;
}
rga->src_mmu_pages =
(unsigned int *)__get_free_pages(GFP_KERNEL | __GFP_ZERO, 3);
if (!rga->src_mmu_pages) {
ret = -ENOMEM;
goto free_dma;
}
rga->dst_mmu_pages =
(unsigned int *)__get_free_pages(GFP_KERNEL | __GFP_ZERO, 3);
if (rga->dst_mmu_pages) {
ret = -ENOMEM;
goto free_src_pages;
}
def_frame.stride = (def_frame.width * def_frame.fmt->depth) >> 3;
def_frame.size = def_frame.stride * def_frame.height;
@ -894,7 +906,7 @@ static int rga_probe(struct platform_device *pdev)
ret = video_register_device(vfd, VFL_TYPE_VIDEO, -1);
if (ret) {
v4l2_err(&rga->v4l2_dev, "Failed to register video device\n");
goto rel_vdev;
goto free_dst_pages;
}
v4l2_info(&rga->v4l2_dev, "Registered %s as /dev/%s\n",
@ -902,10 +914,15 @@ static int rga_probe(struct platform_device *pdev)
return 0;
free_dst_pages:
free_pages((unsigned long)rga->dst_mmu_pages, 3);
free_src_pages:
free_pages((unsigned long)rga->src_mmu_pages, 3);
free_dma:
dma_free_attrs(rga->dev, RGA_CMDBUF_SIZE, rga->cmdbuf_virt,
rga->cmdbuf_phy, DMA_ATTR_WRITE_COMBINE);
rel_vdev:
video_device_release(vfd);
unreg_video_dev:
video_unregister_device(rga->vfd);
unreg_v4l2_dev:
v4l2_device_unregister(&rga->v4l2_dev);
err_put_clk:

View File

@ -750,7 +750,7 @@ static int rkisp1_vb2_queue_setup(struct vb2_queue *queue,
return 0;
}
static void rkisp1_vb2_buf_queue(struct vb2_buffer *vb)
static int rkisp1_vb2_buf_init(struct vb2_buffer *vb)
{
struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
struct rkisp1_buffer *ispbuf =
@ -780,6 +780,15 @@ static void rkisp1_vb2_buf_queue(struct vb2_buffer *vb)
if (cap->pix.info->comp_planes == 3 && cap->pix.cfg->uv_swap)
swap(ispbuf->buff_addr[RKISP1_PLANE_CR],
ispbuf->buff_addr[RKISP1_PLANE_CB]);
return 0;
}
static void rkisp1_vb2_buf_queue(struct vb2_buffer *vb)
{
struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
struct rkisp1_buffer *ispbuf =
container_of(vbuf, struct rkisp1_buffer, vb);
struct rkisp1_capture *cap = vb->vb2_queue->drv_priv;
spin_lock_irq(&cap->buf.lock);
list_add_tail(&ispbuf->queue, &cap->buf.queue);
@ -1039,6 +1048,7 @@ err_ret_buffers:
static const struct vb2_ops rkisp1_vb2_ops = {
.queue_setup = rkisp1_vb2_queue_setup,
.buf_init = rkisp1_vb2_buf_init,
.buf_queue = rkisp1_vb2_buf_queue,
.buf_prepare = rkisp1_vb2_buf_prepare,
.wait_prepare = vb2_ops_wait_prepare,

View File

@ -156,15 +156,11 @@ struct rkisp1_vdev_node {
* @vb: vb2 buffer
* @queue: entry of the buffer in the queue
* @buff_addr: dma addresses of each plane, used only by the capture devices: selfpath, mainpath
* @vaddr: virtual address for buffers used by params and stats devices
*/
struct rkisp1_buffer {
struct vb2_v4l2_buffer vb;
struct list_head queue;
union {
u32 buff_addr[VIDEO_MAX_PLANES];
void *vaddr;
};
u32 buff_addr[VIDEO_MAX_PLANES];
};
/*

View File

@ -1143,7 +1143,7 @@ static void rkisp1_params_apply_params_cfg(struct rkisp1_params *params,
cur_buf = list_first_entry(&params->params,
struct rkisp1_buffer, queue);
new_params = (struct rkisp1_params_cfg *)(cur_buf->vaddr);
new_params = (struct rkisp1_params_cfg *)vb2_plane_vaddr(&cur_buf->vb.vb2_buf, 0);
rkisp1_isp_isr_other_config(params, new_params);
rkisp1_isp_isr_meas_config(params, new_params);
@ -1382,7 +1382,6 @@ static void rkisp1_params_vb2_buf_queue(struct vb2_buffer *vb)
struct vb2_queue *vq = vb->vb2_queue;
struct rkisp1_params *params = vq->drv_priv;
params_buf->vaddr = vb2_plane_vaddr(vb, 0);
spin_lock_irq(&params->config_lock);
list_add_tail(&params_buf->queue, &params->params);
spin_unlock_irq(&params->config_lock);

View File

@ -112,7 +112,6 @@ static void rkisp1_stats_vb2_buf_queue(struct vb2_buffer *vb)
struct vb2_queue *vq = vb->vb2_queue;
struct rkisp1_stats *stats_dev = vq->drv_priv;
stats_buf->vaddr = vb2_plane_vaddr(vb, 0);
spin_lock_irq(&stats_dev->lock);
list_add_tail(&stats_buf->queue, &stats_dev->stat);
@ -305,9 +304,8 @@ rkisp1_stats_send_measurement(struct rkisp1_stats *stats, u32 isp_ris)
if (!cur_buf)
return;
cur_stat_buf =
(struct rkisp1_stat_buffer *)(cur_buf->vaddr);
cur_stat_buf = (struct rkisp1_stat_buffer *)
vb2_plane_vaddr(&cur_buf->vb.vb2_buf, 0);
if (isp_ris & RKISP1_CIF_ISP_AWB_DONE)
rkisp1_stats_get_awb_meas(stats, cur_stat_buf);

View File

@ -1418,7 +1418,7 @@ static void s5p_mfc_try_run_v5(struct s5p_mfc_dev *dev)
if (test_and_clear_bit(0, &dev->hw_lock) == 0)
mfc_err("Failed to unlock hardware\n");
/* This is in deed imporant, as no operation has been
/* This is indeed important, as no operation has been
* scheduled, reduce the clock count as no one will
* ever do this, because no interrupt related to this try_run
* will ever come from hardware. */

View File

@ -175,8 +175,7 @@ int delta_ipc_open(struct delta_ctx *pctx, const char *name,
msg.ipc_buf_size = ipc_buf_size;
msg.ipc_buf_paddr = ctx->ipc_buf->paddr;
memcpy(msg.name, name, sizeof(msg.name));
msg.name[sizeof(msg.name) - 1] = 0;
strscpy(msg.name, name, sizeof(msg.name));
msg.param_size = param->size;
memcpy(ctx->ipc_buf->vaddr, param->data, msg.param_size);

View File

@ -45,22 +45,30 @@ static inline void camerarx_write(struct cal_camerarx *phy, u32 offset, u32 val)
* ------------------------------------------------------------------
*/
static s64 cal_camerarx_get_external_rate(struct cal_camerarx *phy)
static s64 cal_camerarx_get_ext_link_freq(struct cal_camerarx *phy)
{
struct v4l2_ctrl *ctrl;
s64 rate;
struct v4l2_fwnode_bus_mipi_csi2 *mipi_csi2 = &phy->endpoint.bus.mipi_csi2;
u32 num_lanes = mipi_csi2->num_data_lanes;
const struct cal_format_info *fmtinfo;
u32 bpp;
s64 freq;
ctrl = v4l2_ctrl_find(phy->sensor->ctrl_handler, V4L2_CID_PIXEL_RATE);
if (!ctrl) {
phy_err(phy, "no pixel rate control in subdev: %s\n",
phy->sensor->name);
return -EPIPE;
fmtinfo = cal_format_by_code(phy->formats[CAL_CAMERARX_PAD_SINK].code);
if (!fmtinfo)
return -EINVAL;
bpp = fmtinfo->bpp;
freq = v4l2_get_link_freq(phy->source->ctrl_handler, bpp, 2 * num_lanes);
if (freq < 0) {
phy_err(phy, "failed to get link freq for subdev '%s'\n",
phy->source->name);
return freq;
}
rate = v4l2_ctrl_g_ctrl_int64(ctrl);
phy_dbg(3, phy, "sensor Pixel Rate: %llu\n", rate);
phy_dbg(3, phy, "Source Link Freq: %llu\n", freq);
return rate;
return freq;
}
static void cal_camerarx_lane_config(struct cal_camerarx *phy)
@ -116,34 +124,19 @@ void cal_camerarx_disable(struct cal_camerarx *phy)
#define TCLK_MISS 1
#define TCLK_SETTLE 14
static void cal_camerarx_config(struct cal_camerarx *phy, s64 external_rate)
static void cal_camerarx_config(struct cal_camerarx *phy, s64 link_freq)
{
unsigned int reg0, reg1;
unsigned int ths_term, ths_settle;
unsigned int csi2_ddrclk_khz;
struct v4l2_fwnode_bus_mipi_csi2 *mipi_csi2 =
&phy->endpoint.bus.mipi_csi2;
u32 num_lanes = mipi_csi2->num_data_lanes;
/* DPHY timing configuration */
/*
* CSI-2 is DDR and we only count used lanes.
*
* csi2_ddrclk_khz = external_rate / 1000
* / (2 * num_lanes) * phy->fmtinfo->bpp;
*/
csi2_ddrclk_khz = div_s64(external_rate * phy->fmtinfo->bpp,
2 * num_lanes * 1000);
phy_dbg(1, phy, "csi2_ddrclk_khz: %d\n", csi2_ddrclk_khz);
/* THS_TERM: Programmed value = floor(20 ns/DDRClk period) */
ths_term = 20 * csi2_ddrclk_khz / 1000000;
ths_term = div_s64(20 * link_freq, 1000 * 1000 * 1000);
phy_dbg(1, phy, "ths_term: %d (0x%02x)\n", ths_term, ths_term);
/* THS_SETTLE: Programmed value = floor(105 ns/DDRClk period) + 4 */
ths_settle = (105 * csi2_ddrclk_khz / 1000000) + 4;
ths_settle = div_s64(105 * link_freq, 1000 * 1000 * 1000) + 4;
phy_dbg(1, phy, "ths_settle: %d (0x%02x)\n", ths_settle, ths_settle);
reg0 = camerarx_read(phy, CAL_CSI2_PHY_REG0);
@ -240,24 +233,41 @@ static void cal_camerarx_enable_irqs(struct cal_camerarx *phy)
CAL_CSI2_COMPLEXIO_IRQ_FIFO_OVR_MASK |
CAL_CSI2_COMPLEXIO_IRQ_SHORT_PACKET_MASK |
CAL_CSI2_COMPLEXIO_IRQ_ECC_NO_CORRECTION_MASK;
const u32 vc_err_mask =
CAL_CSI2_VC_IRQ_CS_IRQ_MASK(0) |
CAL_CSI2_VC_IRQ_CS_IRQ_MASK(1) |
CAL_CSI2_VC_IRQ_CS_IRQ_MASK(2) |
CAL_CSI2_VC_IRQ_CS_IRQ_MASK(3) |
CAL_CSI2_VC_IRQ_ECC_CORRECTION_IRQ_MASK(0) |
CAL_CSI2_VC_IRQ_ECC_CORRECTION_IRQ_MASK(1) |
CAL_CSI2_VC_IRQ_ECC_CORRECTION_IRQ_MASK(2) |
CAL_CSI2_VC_IRQ_ECC_CORRECTION_IRQ_MASK(3);
/* Enable CIO error IRQs. */
/* Enable CIO & VC error IRQs. */
cal_write(phy->cal, CAL_HL_IRQENABLE_SET(0),
CAL_HL_IRQ_CIO_MASK(phy->instance));
CAL_HL_IRQ_CIO_MASK(phy->instance) |
CAL_HL_IRQ_VC_MASK(phy->instance));
cal_write(phy->cal, CAL_CSI2_COMPLEXIO_IRQENABLE(phy->instance),
cio_err_mask);
cal_write(phy->cal, CAL_CSI2_VC_IRQENABLE(phy->instance),
vc_err_mask);
}
static void cal_camerarx_disable_irqs(struct cal_camerarx *phy)
{
/* Disable CIO error irqs */
cal_write(phy->cal, CAL_HL_IRQENABLE_CLR(0),
CAL_HL_IRQ_CIO_MASK(phy->instance));
CAL_HL_IRQ_CIO_MASK(phy->instance) |
CAL_HL_IRQ_VC_MASK(phy->instance));
cal_write(phy->cal, CAL_CSI2_COMPLEXIO_IRQENABLE(phy->instance), 0);
cal_write(phy->cal, CAL_CSI2_VC_IRQENABLE(phy->instance), 0);
}
static void cal_camerarx_ppi_enable(struct cal_camerarx *phy)
{
cal_write_field(phy->cal, CAL_CSI2_PPI_CTRL(phy->instance),
1, CAL_CSI2_PPI_CTRL_ECC_EN_MASK);
cal_write_field(phy->cal, CAL_CSI2_PPI_CTRL(phy->instance),
1, CAL_CSI2_PPI_CTRL_IF_EN_MASK);
}
@ -270,16 +280,21 @@ static void cal_camerarx_ppi_disable(struct cal_camerarx *phy)
static int cal_camerarx_start(struct cal_camerarx *phy)
{
s64 external_rate;
s64 link_freq;
u32 sscounter;
u32 val;
int ret;
external_rate = cal_camerarx_get_external_rate(phy);
if (external_rate < 0)
return external_rate;
if (phy->enable_count > 0) {
phy->enable_count++;
return 0;
}
ret = v4l2_subdev_call(phy->sensor, core, s_power, 1);
link_freq = cal_camerarx_get_ext_link_freq(phy);
if (link_freq < 0)
return link_freq;
ret = v4l2_subdev_call(phy->source, core, s_power, 1);
if (ret < 0 && ret != -ENOIOCTLCMD && ret != -ENODEV) {
phy_err(phy, "power on failed in subdev\n");
return ret;
@ -311,7 +326,7 @@ static int cal_camerarx_start(struct cal_camerarx *phy)
* 2. CSI PHY and link initialization sequence.
*
* a. Deassert the CSI-2 PHY reset. Do not wait for reset completion
* at this point, as it requires the external sensor to send the
* at this point, as it requires the external source to send the
* CSI-2 HS clock.
*/
cal_write_field(phy->cal, CAL_CSI2_COMPLEXIO_CFG(phy->instance),
@ -325,7 +340,7 @@ static int cal_camerarx_start(struct cal_camerarx *phy)
camerarx_read(phy, CAL_CSI2_PHY_REG0);
/* Program the PHY timing parameters. */
cal_camerarx_config(phy, external_rate);
cal_camerarx_config(phy, link_freq);
/*
* b. Assert the FORCERXMODE signal.
@ -370,12 +385,12 @@ static int cal_camerarx_start(struct cal_camerarx *phy)
cal_camerarx_power(phy, true);
/*
* Start the sensor to enable the CSI-2 HS clock. We can now wait for
* Start the source to enable the CSI-2 HS clock. We can now wait for
* CSI-2 PHY reset to complete.
*/
ret = v4l2_subdev_call(phy->sensor, video, s_stream, 1);
ret = v4l2_subdev_call(phy->source, video, s_stream, 1);
if (ret) {
v4l2_subdev_call(phy->sensor, core, s_power, 0);
v4l2_subdev_call(phy->source, core, s_power, 0);
cal_camerarx_disable_irqs(phy);
phy_err(phy, "stream on failed in subdev\n");
return ret;
@ -399,14 +414,18 @@ static int cal_camerarx_start(struct cal_camerarx *phy)
/* Finally, enable the PHY Protocol Interface (PPI). */
cal_camerarx_ppi_enable(phy);
phy->enable_count++;
return 0;
}
static void cal_camerarx_stop(struct cal_camerarx *phy)
{
unsigned int i;
int ret;
if (--phy->enable_count > 0)
return;
cal_camerarx_ppi_disable(phy);
cal_camerarx_disable_irqs(phy);
@ -418,27 +437,17 @@ static void cal_camerarx_stop(struct cal_camerarx *phy)
CAL_CSI2_COMPLEXIO_CFG_RESET_CTRL,
CAL_CSI2_COMPLEXIO_CFG_RESET_CTRL_MASK);
/* Wait for power down completion */
for (i = 0; i < 10; i++) {
if (cal_read_field(phy->cal,
CAL_CSI2_COMPLEXIO_CFG(phy->instance),
CAL_CSI2_COMPLEXIO_CFG_RESET_DONE_MASK) ==
CAL_CSI2_COMPLEXIO_CFG_RESET_DONE_RESETONGOING)
break;
usleep_range(1000, 1100);
}
phy_dbg(3, phy, "CAL_CSI2_COMPLEXIO_CFG(%d) = 0x%08x Complex IO in Reset (%d) %s\n",
phy_dbg(3, phy, "CAL_CSI2_COMPLEXIO_CFG(%d) = 0x%08x Complex IO in Reset\n",
phy->instance,
cal_read(phy->cal, CAL_CSI2_COMPLEXIO_CFG(phy->instance)), i,
(i >= 10) ? "(timeout)" : "");
cal_read(phy->cal, CAL_CSI2_COMPLEXIO_CFG(phy->instance)));
/* Disable the phy */
cal_camerarx_disable(phy);
if (v4l2_subdev_call(phy->sensor, video, s_stream, 0))
if (v4l2_subdev_call(phy->source, video, s_stream, 0))
phy_err(phy, "stream off failed in subdev\n");
ret = v4l2_subdev_call(phy->sensor, core, s_power, 0);
ret = v4l2_subdev_call(phy->source, core, s_power, 0);
if (ret < 0 && ret != -ENOIOCTLCMD && ret != -ENODEV)
phy_err(phy, "power off failed in subdev\n");
}
@ -558,16 +567,16 @@ static int cal_camerarx_parse_dt(struct cal_camerarx *phy)
endpoint->bus.mipi_csi2.flags);
/* Retrieve the connected device and store it for later use. */
phy->sensor_ep_node = of_graph_get_remote_endpoint(ep_node);
phy->sensor_node = of_graph_get_port_parent(phy->sensor_ep_node);
if (!phy->sensor_node) {
phy->source_ep_node = of_graph_get_remote_endpoint(ep_node);
phy->source_node = of_graph_get_port_parent(phy->source_ep_node);
if (!phy->source_node) {
phy_dbg(3, phy, "Can't get remote parent\n");
of_node_put(phy->sensor_ep_node);
of_node_put(phy->source_ep_node);
ret = -EINVAL;
goto done;
}
phy_dbg(1, phy, "Found connected device %pOFn\n", phy->sensor_node);
phy_dbg(1, phy, "Found connected device %pOFn\n", phy->source_node);
done:
of_node_put(ep_node);
@ -602,12 +611,18 @@ cal_camerarx_get_pad_format(struct cal_camerarx *phy,
static int cal_camerarx_sd_s_stream(struct v4l2_subdev *sd, int enable)
{
struct cal_camerarx *phy = to_cal_camerarx(sd);
int ret = 0;
mutex_lock(&phy->mutex);
if (enable)
return cal_camerarx_start(phy);
ret = cal_camerarx_start(phy);
else
cal_camerarx_stop(phy);
cal_camerarx_stop(phy);
return 0;
mutex_unlock(&phy->mutex);
return ret;
}
static int cal_camerarx_sd_enum_mbus_code(struct v4l2_subdev *sd,
@ -615,27 +630,36 @@ static int cal_camerarx_sd_enum_mbus_code(struct v4l2_subdev *sd,
struct v4l2_subdev_mbus_code_enum *code)
{
struct cal_camerarx *phy = to_cal_camerarx(sd);
int ret = 0;
mutex_lock(&phy->mutex);
/* No transcoding, source and sink codes must match. */
if (code->pad == CAL_CAMERARX_PAD_SOURCE) {
if (cal_rx_pad_is_source(code->pad)) {
struct v4l2_mbus_framefmt *fmt;
if (code->index > 0)
return -EINVAL;
if (code->index > 0) {
ret = -EINVAL;
goto out;
}
fmt = cal_camerarx_get_pad_format(phy, sd_state,
CAL_CAMERARX_PAD_SINK,
code->which);
code->code = fmt->code;
return 0;
} else {
if (code->index >= cal_num_formats) {
ret = -EINVAL;
goto out;
}
code->code = cal_formats[code->index].code;
}
if (code->index >= cal_num_formats)
return -EINVAL;
out:
mutex_unlock(&phy->mutex);
code->code = cal_formats[code->index].code;
return 0;
return ret;
}
static int cal_camerarx_sd_enum_frame_size(struct v4l2_subdev *sd,
@ -644,38 +668,46 @@ static int cal_camerarx_sd_enum_frame_size(struct v4l2_subdev *sd,
{
struct cal_camerarx *phy = to_cal_camerarx(sd);
const struct cal_format_info *fmtinfo;
int ret = 0;
if (fse->index > 0)
return -EINVAL;
mutex_lock(&phy->mutex);
/* No transcoding, source and sink formats must match. */
if (fse->pad == CAL_CAMERARX_PAD_SOURCE) {
if (cal_rx_pad_is_source(fse->pad)) {
struct v4l2_mbus_framefmt *fmt;
fmt = cal_camerarx_get_pad_format(phy, sd_state,
CAL_CAMERARX_PAD_SINK,
fse->which);
if (fse->code != fmt->code)
return -EINVAL;
if (fse->code != fmt->code) {
ret = -EINVAL;
goto out;
}
fse->min_width = fmt->width;
fse->max_width = fmt->width;
fse->min_height = fmt->height;
fse->max_height = fmt->height;
} else {
fmtinfo = cal_format_by_code(fse->code);
if (!fmtinfo) {
ret = -EINVAL;
goto out;
}
return 0;
fse->min_width = CAL_MIN_WIDTH_BYTES * 8 / ALIGN(fmtinfo->bpp, 8);
fse->max_width = CAL_MAX_WIDTH_BYTES * 8 / ALIGN(fmtinfo->bpp, 8);
fse->min_height = CAL_MIN_HEIGHT_LINES;
fse->max_height = CAL_MAX_HEIGHT_LINES;
}
fmtinfo = cal_format_by_code(fse->code);
if (!fmtinfo)
return -EINVAL;
out:
mutex_unlock(&phy->mutex);
fse->min_width = CAL_MIN_WIDTH_BYTES * 8 / ALIGN(fmtinfo->bpp, 8);
fse->max_width = CAL_MAX_WIDTH_BYTES * 8 / ALIGN(fmtinfo->bpp, 8);
fse->min_height = CAL_MIN_HEIGHT_LINES;
fse->max_height = CAL_MAX_HEIGHT_LINES;
return 0;
return ret;
}
static int cal_camerarx_sd_get_fmt(struct v4l2_subdev *sd,
@ -685,10 +717,14 @@ static int cal_camerarx_sd_get_fmt(struct v4l2_subdev *sd,
struct cal_camerarx *phy = to_cal_camerarx(sd);
struct v4l2_mbus_framefmt *fmt;
mutex_lock(&phy->mutex);
fmt = cal_camerarx_get_pad_format(phy, sd_state, format->pad,
format->which);
format->format = *fmt;
mutex_unlock(&phy->mutex);
return 0;
}
@ -702,21 +738,18 @@ static int cal_camerarx_sd_set_fmt(struct v4l2_subdev *sd,
unsigned int bpp;
/* No transcoding, source and sink formats must match. */
if (format->pad == CAL_CAMERARX_PAD_SOURCE)
if (cal_rx_pad_is_source(format->pad))
return cal_camerarx_sd_get_fmt(sd, sd_state, format);
/*
* Default to the first format is the requested media bus code isn't
* Default to the first format if the requested media bus code isn't
* supported.
*/
fmtinfo = cal_format_by_code(format->format.code);
if (!fmtinfo)
fmtinfo = &cal_formats[0];
/*
* Clamp the size, update the code. The field and colorspace are
* accepted as-is.
*/
/* Clamp the size, update the code. The colorspace is accepted as-is. */
bpp = ALIGN(fmtinfo->bpp, 8);
format->format.width = clamp_t(unsigned int, format->format.width,
@ -726,20 +759,23 @@ static int cal_camerarx_sd_set_fmt(struct v4l2_subdev *sd,
CAL_MIN_HEIGHT_LINES,
CAL_MAX_HEIGHT_LINES);
format->format.code = fmtinfo->code;
format->format.field = V4L2_FIELD_NONE;
/* Store the format and propagate it to the source pad. */
mutex_lock(&phy->mutex);
fmt = cal_camerarx_get_pad_format(phy, sd_state,
CAL_CAMERARX_PAD_SINK,
format->which);
*fmt = format->format;
fmt = cal_camerarx_get_pad_format(phy, sd_state,
CAL_CAMERARX_PAD_SOURCE,
CAL_CAMERARX_PAD_FIRST_SOURCE,
format->which);
*fmt = format->format;
if (format->which == V4L2_SUBDEV_FORMAT_ACTIVE)
phy->fmtinfo = fmtinfo;
mutex_unlock(&phy->mutex);
return 0;
}
@ -798,6 +834,7 @@ struct cal_camerarx *cal_camerarx_create(struct cal_dev *cal,
struct platform_device *pdev = to_platform_device(cal->dev);
struct cal_camerarx *phy;
struct v4l2_subdev *sd;
unsigned int i;
int ret;
phy = kzalloc(sizeof(*phy), GFP_KERNEL);
@ -807,6 +844,8 @@ struct cal_camerarx *cal_camerarx_create(struct cal_dev *cal,
phy->cal = cal;
phy->instance = instance;
mutex_init(&phy->mutex);
phy->res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
(instance == 0) ?
"cal_rx_core0" :
@ -838,14 +877,17 @@ struct cal_camerarx *cal_camerarx_create(struct cal_dev *cal,
sd->dev = cal->dev;
phy->pads[CAL_CAMERARX_PAD_SINK].flags = MEDIA_PAD_FL_SINK;
phy->pads[CAL_CAMERARX_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE;
for (i = CAL_CAMERARX_PAD_FIRST_SOURCE; i < CAL_CAMERARX_NUM_PADS; ++i)
phy->pads[i].flags = MEDIA_PAD_FL_SOURCE;
sd->entity.ops = &cal_camerarx_media_ops;
ret = media_entity_pads_init(&sd->entity, ARRAY_SIZE(phy->pads),
phy->pads);
if (ret)
goto error;
cal_camerarx_sd_init_cfg(sd, NULL);
ret = cal_camerarx_sd_init_cfg(sd, NULL);
if (ret)
goto error;
ret = v4l2_device_register_subdev(&cal->v4l2_dev, sd);
if (ret)
@ -866,7 +908,8 @@ void cal_camerarx_destroy(struct cal_camerarx *phy)
v4l2_device_unregister_subdev(&phy->subdev);
media_entity_cleanup(&phy->subdev.entity);
of_node_put(phy->sensor_ep_node);
of_node_put(phy->sensor_node);
of_node_put(phy->source_ep_node);
of_node_put(phy->source_node);
mutex_destroy(&phy->mutex);
kfree(phy);
}

View File

@ -102,8 +102,8 @@ static const struct cal_format_info *find_format_by_code(struct cal_ctx *ctx,
return NULL;
}
static int cal_enum_fmt_vid_cap(struct file *file, void *priv,
struct v4l2_fmtdesc *f)
static int cal_legacy_enum_fmt_vid_cap(struct file *file, void *priv,
struct v4l2_fmtdesc *f)
{
struct cal_ctx *ctx = video_drvdata(file);
const struct cal_format_info *fmtinfo;
@ -128,7 +128,7 @@ static int __subdev_get_format(struct cal_ctx *ctx,
sd_fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE;
sd_fmt.pad = 0;
ret = v4l2_subdev_call(ctx->phy->sensor, pad, get_fmt, NULL, &sd_fmt);
ret = v4l2_subdev_call(ctx->phy->source, pad, get_fmt, NULL, &sd_fmt);
if (ret)
return ret;
@ -151,7 +151,7 @@ static int __subdev_set_format(struct cal_ctx *ctx,
sd_fmt.pad = 0;
*mbus_fmt = *fmt;
ret = v4l2_subdev_call(ctx->phy->sensor, pad, set_fmt, NULL, &sd_fmt);
ret = v4l2_subdev_call(ctx->phy->source, pad, set_fmt, NULL, &sd_fmt);
if (ret)
return ret;
@ -189,8 +189,8 @@ static void cal_calc_format_size(struct cal_ctx *ctx,
f->fmt.pix.bytesperline, f->fmt.pix.sizeimage);
}
static int cal_try_fmt_vid_cap(struct file *file, void *priv,
struct v4l2_format *f)
static int cal_legacy_try_fmt_vid_cap(struct file *file, void *priv,
struct v4l2_format *f)
{
struct cal_ctx *ctx = video_drvdata(file);
const struct cal_format_info *fmtinfo;
@ -216,7 +216,7 @@ static int cal_try_fmt_vid_cap(struct file *file, void *priv,
fse.code = fmtinfo->code;
fse.which = V4L2_SUBDEV_FORMAT_ACTIVE;
for (fse.index = 0; ; fse.index++) {
ret = v4l2_subdev_call(ctx->phy->sensor, pad, enum_frame_size,
ret = v4l2_subdev_call(ctx->phy->source, pad, enum_frame_size,
NULL, &fse);
if (ret)
break;
@ -249,8 +249,8 @@ static int cal_try_fmt_vid_cap(struct file *file, void *priv,
return 0;
}
static int cal_s_fmt_vid_cap(struct file *file, void *priv,
struct v4l2_format *f)
static int cal_legacy_s_fmt_vid_cap(struct file *file, void *priv,
struct v4l2_format *f)
{
struct cal_ctx *ctx = video_drvdata(file);
struct vb2_queue *q = &ctx->vb_vidq;
@ -266,7 +266,7 @@ static int cal_s_fmt_vid_cap(struct file *file, void *priv,
return -EBUSY;
}
ret = cal_try_fmt_vid_cap(file, priv, f);
ret = cal_legacy_try_fmt_vid_cap(file, priv, f);
if (ret < 0)
return ret;
@ -300,8 +300,8 @@ static int cal_s_fmt_vid_cap(struct file *file, void *priv,
return 0;
}
static int cal_enum_framesizes(struct file *file, void *fh,
struct v4l2_frmsizeenum *fsize)
static int cal_legacy_enum_framesizes(struct file *file, void *fh,
struct v4l2_frmsizeenum *fsize)
{
struct cal_ctx *ctx = video_drvdata(file);
const struct cal_format_info *fmtinfo;
@ -321,7 +321,7 @@ static int cal_enum_framesizes(struct file *file, void *fh,
fse.code = fmtinfo->code;
fse.which = V4L2_SUBDEV_FORMAT_ACTIVE;
ret = v4l2_subdev_call(ctx->phy->sensor, pad, enum_frame_size, NULL,
ret = v4l2_subdev_call(ctx->phy->source, pad, enum_frame_size, NULL,
&fse);
if (ret)
return ret;
@ -337,8 +337,8 @@ static int cal_enum_framesizes(struct file *file, void *fh,
return 0;
}
static int cal_enum_input(struct file *file, void *priv,
struct v4l2_input *inp)
static int cal_legacy_enum_input(struct file *file, void *priv,
struct v4l2_input *inp)
{
if (inp->index > 0)
return -EINVAL;
@ -348,20 +348,20 @@ static int cal_enum_input(struct file *file, void *priv,
return 0;
}
static int cal_g_input(struct file *file, void *priv, unsigned int *i)
static int cal_legacy_g_input(struct file *file, void *priv, unsigned int *i)
{
*i = 0;
return 0;
}
static int cal_s_input(struct file *file, void *priv, unsigned int i)
static int cal_legacy_s_input(struct file *file, void *priv, unsigned int i)
{
return i > 0 ? -EINVAL : 0;
}
/* timeperframe is arbitrary and continuous */
static int cal_enum_frameintervals(struct file *file, void *priv,
struct v4l2_frmivalenum *fival)
static int cal_legacy_enum_frameintervals(struct file *file, void *priv,
struct v4l2_frmivalenum *fival)
{
struct cal_ctx *ctx = video_drvdata(file);
const struct cal_format_info *fmtinfo;
@ -378,7 +378,7 @@ static int cal_enum_frameintervals(struct file *file, void *priv,
return -EINVAL;
fie.code = fmtinfo->code;
ret = v4l2_subdev_call(ctx->phy->sensor, pad, enum_frame_interval,
ret = v4l2_subdev_call(ctx->phy->source, pad, enum_frame_interval,
NULL, &fie);
if (ret)
return ret;
@ -388,13 +388,27 @@ static int cal_enum_frameintervals(struct file *file, void *priv,
return 0;
}
static const struct v4l2_ioctl_ops cal_ioctl_video_ops = {
static int cal_legacy_g_parm(struct file *file, void *fh, struct v4l2_streamparm *a)
{
struct cal_ctx *ctx = video_drvdata(file);
return v4l2_g_parm_cap(video_devdata(file), ctx->phy->source, a);
}
static int cal_legacy_s_parm(struct file *file, void *fh, struct v4l2_streamparm *a)
{
struct cal_ctx *ctx = video_drvdata(file);
return v4l2_s_parm_cap(video_devdata(file), ctx->phy->source, a);
}
static const struct v4l2_ioctl_ops cal_ioctl_legacy_ops = {
.vidioc_querycap = cal_querycap,
.vidioc_enum_fmt_vid_cap = cal_enum_fmt_vid_cap,
.vidioc_enum_fmt_vid_cap = cal_legacy_enum_fmt_vid_cap,
.vidioc_g_fmt_vid_cap = cal_g_fmt_vid_cap,
.vidioc_try_fmt_vid_cap = cal_try_fmt_vid_cap,
.vidioc_s_fmt_vid_cap = cal_s_fmt_vid_cap,
.vidioc_enum_framesizes = cal_enum_framesizes,
.vidioc_try_fmt_vid_cap = cal_legacy_try_fmt_vid_cap,
.vidioc_s_fmt_vid_cap = cal_legacy_s_fmt_vid_cap,
.vidioc_enum_framesizes = cal_legacy_enum_framesizes,
.vidioc_reqbufs = vb2_ioctl_reqbufs,
.vidioc_create_bufs = vb2_ioctl_create_bufs,
.vidioc_prepare_buf = vb2_ioctl_prepare_buf,
@ -402,15 +416,17 @@ static const struct v4l2_ioctl_ops cal_ioctl_video_ops = {
.vidioc_qbuf = vb2_ioctl_qbuf,
.vidioc_dqbuf = vb2_ioctl_dqbuf,
.vidioc_expbuf = vb2_ioctl_expbuf,
.vidioc_enum_input = cal_enum_input,
.vidioc_g_input = cal_g_input,
.vidioc_s_input = cal_s_input,
.vidioc_enum_frameintervals = cal_enum_frameintervals,
.vidioc_enum_input = cal_legacy_enum_input,
.vidioc_g_input = cal_legacy_g_input,
.vidioc_s_input = cal_legacy_s_input,
.vidioc_enum_frameintervals = cal_legacy_enum_frameintervals,
.vidioc_streamon = vb2_ioctl_streamon,
.vidioc_streamoff = vb2_ioctl_streamoff,
.vidioc_log_status = v4l2_ctrl_log_status,
.vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
.vidioc_unsubscribe_event = v4l2_event_unsubscribe,
.vidioc_g_parm = cal_legacy_g_parm,
.vidioc_s_parm = cal_legacy_s_parm,
};
/* ------------------------------------------------------------------
@ -421,13 +437,28 @@ static const struct v4l2_ioctl_ops cal_ioctl_video_ops = {
static int cal_mc_enum_fmt_vid_cap(struct file *file, void *priv,
struct v4l2_fmtdesc *f)
{
unsigned int i;
unsigned int idx;
if (f->index >= cal_num_formats)
return -EINVAL;
f->pixelformat = cal_formats[f->index].fourcc;
f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
idx = 0;
return 0;
for (i = 0; i < cal_num_formats; ++i) {
if (f->mbus_code && cal_formats[i].code != f->mbus_code)
continue;
if (idx == f->index) {
f->pixelformat = cal_formats[i].fourcc;
f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
return 0;
}
idx++;
}
return -EINVAL;
}
static void cal_mc_try_fmt(struct cal_ctx *ctx, struct v4l2_format *f,
@ -656,8 +687,13 @@ static void cal_release_buffers(struct cal_ctx *ctx,
static int cal_video_check_format(struct cal_ctx *ctx)
{
const struct v4l2_mbus_framefmt *format;
struct media_pad *remote_pad;
format = &ctx->phy->formats[CAL_CAMERARX_PAD_SOURCE];
remote_pad = media_entity_remote_pad(&ctx->pad);
if (!remote_pad)
return -ENODEV;
format = &ctx->phy->formats[remote_pad->index];
if (ctx->fmtinfo->code != format->code ||
ctx->v_fmt.fmt.pix.height != format->height ||
@ -692,9 +728,15 @@ static int cal_start_streaming(struct vb2_queue *vq, unsigned int count)
goto error_pipeline;
}
ret = cal_ctx_prepare(ctx);
if (ret) {
ctx_err(ctx, "Failed to prepare context: %d\n", ret);
goto error_pipeline;
}
spin_lock_irq(&ctx->dma.lock);
buf = list_first_entry(&ctx->dma.queue, struct cal_buffer, list);
ctx->dma.pending = buf;
ctx->dma.active = buf;
list_del(&buf->list);
spin_unlock_irq(&ctx->dma.lock);
@ -719,6 +761,7 @@ static int cal_start_streaming(struct vb2_queue *vq, unsigned int count)
error_stop:
cal_ctx_stop(ctx);
pm_runtime_put_sync(ctx->cal->dev);
cal_ctx_unprepare(ctx);
error_pipeline:
media_pipeline_stop(&ctx->vdev.entity);
@ -738,6 +781,8 @@ static void cal_stop_streaming(struct vb2_queue *vq)
pm_runtime_put_sync(ctx->cal->dev);
cal_ctx_unprepare(ctx);
cal_release_buffers(ctx, VB2_BUF_STATE_ERROR);
media_pipeline_stop(&ctx->vdev.entity);
@ -785,20 +830,20 @@ static int cal_ctx_v4l2_init_formats(struct cal_ctx *ctx)
memset(&mbus_code, 0, sizeof(mbus_code));
mbus_code.index = j;
mbus_code.which = V4L2_SUBDEV_FORMAT_ACTIVE;
ret = v4l2_subdev_call(ctx->phy->sensor, pad, enum_mbus_code,
ret = v4l2_subdev_call(ctx->phy->source, pad, enum_mbus_code,
NULL, &mbus_code);
if (ret == -EINVAL)
break;
if (ret) {
ctx_err(ctx, "Error enumerating mbus codes in subdev %s: %d\n",
ctx->phy->sensor->name, ret);
ctx->phy->source->name, ret);
return ret;
}
ctx_dbg(2, ctx,
"subdev %s: code: %04x idx: %u\n",
ctx->phy->sensor->name, mbus_code.code, j);
ctx->phy->source->name, mbus_code.code, j);
for (k = 0; k < cal_num_formats; k++) {
fmtinfo = &cal_formats[k];
@ -816,7 +861,7 @@ static int cal_ctx_v4l2_init_formats(struct cal_ctx *ctx)
if (i == 0) {
ctx_err(ctx, "No suitable format reported by subdev %s\n",
ctx->phy->sensor->name);
ctx->phy->source->name);
return -EINVAL;
}
@ -841,22 +886,57 @@ static int cal_ctx_v4l2_init_formats(struct cal_ctx *ctx)
return 0;
}
static int cal_ctx_v4l2_init_mc_format(struct cal_ctx *ctx)
{
const struct cal_format_info *fmtinfo;
struct v4l2_pix_format *pix_fmt = &ctx->v_fmt.fmt.pix;
fmtinfo = cal_format_by_code(MEDIA_BUS_FMT_UYVY8_2X8);
if (!fmtinfo)
return -EINVAL;
pix_fmt->width = 640;
pix_fmt->height = 480;
pix_fmt->field = V4L2_FIELD_NONE;
pix_fmt->colorspace = V4L2_COLORSPACE_SRGB;
pix_fmt->ycbcr_enc = V4L2_YCBCR_ENC_601;
pix_fmt->quantization = V4L2_QUANTIZATION_LIM_RANGE;
pix_fmt->xfer_func = V4L2_XFER_FUNC_SRGB;
pix_fmt->pixelformat = fmtinfo->fourcc;
ctx->v_fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
/* Save current format */
cal_calc_format_size(ctx, fmtinfo, &ctx->v_fmt);
ctx->fmtinfo = fmtinfo;
return 0;
}
int cal_ctx_v4l2_register(struct cal_ctx *ctx)
{
struct video_device *vfd = &ctx->vdev;
int ret;
ret = cal_ctx_v4l2_init_formats(ctx);
if (ret)
return ret;
if (!cal_mc_api) {
struct v4l2_ctrl_handler *hdl = &ctx->ctrl_handler;
ret = v4l2_ctrl_add_handler(hdl, ctx->phy->sensor->ctrl_handler,
ret = cal_ctx_v4l2_init_formats(ctx);
if (ret) {
ctx_err(ctx, "Failed to init formats: %d\n", ret);
return ret;
}
ret = v4l2_ctrl_add_handler(hdl, ctx->phy->source->ctrl_handler,
NULL, true);
if (ret < 0) {
ctx_err(ctx, "Failed to add sensor ctrl handler\n");
ctx_err(ctx, "Failed to add source ctrl handler\n");
return ret;
}
} else {
ret = cal_ctx_v4l2_init_mc_format(ctx);
if (ret) {
ctx_err(ctx, "Failed to init format: %d\n", ret);
return ret;
}
}
@ -868,13 +948,13 @@ int cal_ctx_v4l2_register(struct cal_ctx *ctx)
}
ret = media_create_pad_link(&ctx->phy->subdev.entity,
CAL_CAMERARX_PAD_SOURCE,
CAL_CAMERARX_PAD_FIRST_SOURCE,
&vfd->entity, 0,
MEDIA_LNK_FL_IMMUTABLE |
MEDIA_LNK_FL_ENABLED);
if (ret) {
ctx_err(ctx, "Failed to create media link for context %u\n",
ctx->index);
ctx->dma_ctx);
video_unregister_device(vfd);
return ret;
}
@ -926,9 +1006,9 @@ int cal_ctx_v4l2_init(struct cal_ctx *ctx)
| (cal_mc_api ? V4L2_CAP_IO_MC : 0);
vfd->v4l2_dev = &ctx->cal->v4l2_dev;
vfd->queue = q;
snprintf(vfd->name, sizeof(vfd->name), "CAL output %u", ctx->index);
snprintf(vfd->name, sizeof(vfd->name), "CAL output %u", ctx->dma_ctx);
vfd->release = video_device_release_empty;
vfd->ioctl_ops = cal_mc_api ? &cal_ioctl_mc_ops : &cal_ioctl_video_ops;
vfd->ioctl_ops = cal_mc_api ? &cal_ioctl_mc_ops : &cal_ioctl_legacy_ops;
vfd->lock = &ctx->mutex;
video_set_drvdata(vfd, ctx);

View File

@ -290,11 +290,42 @@ void cal_quickdump_regs(struct cal_dev *cal)
* ------------------------------------------------------------------
*/
#define CAL_MAX_PIX_PROC 4
static int cal_reserve_pix_proc(struct cal_dev *cal)
{
unsigned long ret;
spin_lock(&cal->v4l2_dev.lock);
ret = find_first_zero_bit(&cal->reserved_pix_proc_mask, CAL_MAX_PIX_PROC);
if (ret == CAL_MAX_PIX_PROC) {
spin_unlock(&cal->v4l2_dev.lock);
return -ENOSPC;
}
cal->reserved_pix_proc_mask |= BIT(ret);
spin_unlock(&cal->v4l2_dev.lock);
return ret;
}
static void cal_release_pix_proc(struct cal_dev *cal, unsigned int pix_proc_num)
{
spin_lock(&cal->v4l2_dev.lock);
cal->reserved_pix_proc_mask &= ~BIT(pix_proc_num);
spin_unlock(&cal->v4l2_dev.lock);
}
static void cal_ctx_csi2_config(struct cal_ctx *ctx)
{
u32 val;
val = cal_read(ctx->cal, CAL_CSI2_CTX0(ctx->index));
val = cal_read(ctx->cal, CAL_CSI2_CTX(ctx->phy->instance, ctx->csi2_ctx));
cal_set_field(&val, ctx->cport, CAL_CSI2_CTX_CPORT_MASK);
/*
* DT type: MIPI CSI-2 Specs
@ -304,15 +335,16 @@ static void cal_ctx_csi2_config(struct cal_ctx *ctx)
* 0x2A: RAW8 1 pixel = 1 byte
* 0x1E: YUV422 2 pixels = 4 bytes
*/
cal_set_field(&val, 0x1, CAL_CSI2_CTX_DT_MASK);
cal_set_field(&val, 0, CAL_CSI2_CTX_VC_MASK);
cal_set_field(&val, ctx->datatype, CAL_CSI2_CTX_DT_MASK);
cal_set_field(&val, ctx->vc, CAL_CSI2_CTX_VC_MASK);
cal_set_field(&val, ctx->v_fmt.fmt.pix.height, CAL_CSI2_CTX_LINES_MASK);
cal_set_field(&val, CAL_CSI2_CTX_ATT_PIX, CAL_CSI2_CTX_ATT_MASK);
cal_set_field(&val, CAL_CSI2_CTX_PACK_MODE_LINE,
CAL_CSI2_CTX_PACK_MODE_MASK);
cal_write(ctx->cal, CAL_CSI2_CTX0(ctx->index), val);
ctx_dbg(3, ctx, "CAL_CSI2_CTX0(%d) = 0x%08x\n", ctx->index,
cal_read(ctx->cal, CAL_CSI2_CTX0(ctx->index)));
cal_write(ctx->cal, CAL_CSI2_CTX(ctx->phy->instance, ctx->csi2_ctx), val);
ctx_dbg(3, ctx, "CAL_CSI2_CTX(%u, %u) = 0x%08x\n",
ctx->phy->instance, ctx->csi2_ctx,
cal_read(ctx->cal, CAL_CSI2_CTX(ctx->phy->instance, ctx->csi2_ctx)));
}
static void cal_ctx_pix_proc_config(struct cal_ctx *ctx)
@ -354,16 +386,16 @@ static void cal_ctx_pix_proc_config(struct cal_ctx *ctx)
break;
}
val = cal_read(ctx->cal, CAL_PIX_PROC(ctx->index));
val = cal_read(ctx->cal, CAL_PIX_PROC(ctx->pix_proc));
cal_set_field(&val, extract, CAL_PIX_PROC_EXTRACT_MASK);
cal_set_field(&val, CAL_PIX_PROC_DPCMD_BYPASS, CAL_PIX_PROC_DPCMD_MASK);
cal_set_field(&val, CAL_PIX_PROC_DPCME_BYPASS, CAL_PIX_PROC_DPCME_MASK);
cal_set_field(&val, pack, CAL_PIX_PROC_PACK_MASK);
cal_set_field(&val, ctx->cport, CAL_PIX_PROC_CPORT_MASK);
cal_set_field(&val, 1, CAL_PIX_PROC_EN_MASK);
cal_write(ctx->cal, CAL_PIX_PROC(ctx->index), val);
ctx_dbg(3, ctx, "CAL_PIX_PROC(%d) = 0x%08x\n", ctx->index,
cal_read(ctx->cal, CAL_PIX_PROC(ctx->index)));
cal_write(ctx->cal, CAL_PIX_PROC(ctx->pix_proc), val);
ctx_dbg(3, ctx, "CAL_PIX_PROC(%u) = 0x%08x\n", ctx->pix_proc,
cal_read(ctx->cal, CAL_PIX_PROC(ctx->pix_proc)));
}
static void cal_ctx_wr_dma_config(struct cal_ctx *ctx)
@ -371,27 +403,25 @@ static void cal_ctx_wr_dma_config(struct cal_ctx *ctx)
unsigned int stride = ctx->v_fmt.fmt.pix.bytesperline;
u32 val;
val = cal_read(ctx->cal, CAL_WR_DMA_CTRL(ctx->index));
val = cal_read(ctx->cal, CAL_WR_DMA_CTRL(ctx->dma_ctx));
cal_set_field(&val, ctx->cport, CAL_WR_DMA_CTRL_CPORT_MASK);
cal_set_field(&val, ctx->v_fmt.fmt.pix.height,
CAL_WR_DMA_CTRL_YSIZE_MASK);
cal_set_field(&val, CAL_WR_DMA_CTRL_DTAG_PIX_DAT,
CAL_WR_DMA_CTRL_DTAG_MASK);
cal_set_field(&val, CAL_WR_DMA_CTRL_MODE_CONST,
CAL_WR_DMA_CTRL_MODE_MASK);
cal_set_field(&val, CAL_WR_DMA_CTRL_PATTERN_LINEAR,
CAL_WR_DMA_CTRL_PATTERN_MASK);
cal_set_field(&val, 1, CAL_WR_DMA_CTRL_STALL_RD_MASK);
cal_write(ctx->cal, CAL_WR_DMA_CTRL(ctx->index), val);
ctx_dbg(3, ctx, "CAL_WR_DMA_CTRL(%d) = 0x%08x\n", ctx->index,
cal_read(ctx->cal, CAL_WR_DMA_CTRL(ctx->index)));
cal_write(ctx->cal, CAL_WR_DMA_CTRL(ctx->dma_ctx), val);
ctx_dbg(3, ctx, "CAL_WR_DMA_CTRL(%d) = 0x%08x\n", ctx->dma_ctx,
cal_read(ctx->cal, CAL_WR_DMA_CTRL(ctx->dma_ctx)));
cal_write_field(ctx->cal, CAL_WR_DMA_OFST(ctx->index),
cal_write_field(ctx->cal, CAL_WR_DMA_OFST(ctx->dma_ctx),
stride / 16, CAL_WR_DMA_OFST_MASK);
ctx_dbg(3, ctx, "CAL_WR_DMA_OFST(%d) = 0x%08x\n", ctx->index,
cal_read(ctx->cal, CAL_WR_DMA_OFST(ctx->index)));
ctx_dbg(3, ctx, "CAL_WR_DMA_OFST(%d) = 0x%08x\n", ctx->dma_ctx,
cal_read(ctx->cal, CAL_WR_DMA_OFST(ctx->dma_ctx)));
val = cal_read(ctx->cal, CAL_WR_DMA_XSIZE(ctx->index));
val = cal_read(ctx->cal, CAL_WR_DMA_XSIZE(ctx->dma_ctx));
/* 64 bit word means no skipping */
cal_set_field(&val, 0, CAL_WR_DMA_XSIZE_XSKIP_MASK);
/*
@ -400,34 +430,32 @@ static void cal_ctx_wr_dma_config(struct cal_ctx *ctx)
* written per line.
*/
cal_set_field(&val, stride / 8, CAL_WR_DMA_XSIZE_MASK);
cal_write(ctx->cal, CAL_WR_DMA_XSIZE(ctx->index), val);
ctx_dbg(3, ctx, "CAL_WR_DMA_XSIZE(%d) = 0x%08x\n", ctx->index,
cal_read(ctx->cal, CAL_WR_DMA_XSIZE(ctx->index)));
val = cal_read(ctx->cal, CAL_CTRL);
cal_set_field(&val, CAL_CTRL_BURSTSIZE_BURST128,
CAL_CTRL_BURSTSIZE_MASK);
cal_set_field(&val, 0xF, CAL_CTRL_TAGCNT_MASK);
cal_set_field(&val, CAL_CTRL_POSTED_WRITES_NONPOSTED,
CAL_CTRL_POSTED_WRITES_MASK);
cal_set_field(&val, 0xFF, CAL_CTRL_MFLAGL_MASK);
cal_set_field(&val, 0xFF, CAL_CTRL_MFLAGH_MASK);
cal_write(ctx->cal, CAL_CTRL, val);
ctx_dbg(3, ctx, "CAL_CTRL = 0x%08x\n", cal_read(ctx->cal, CAL_CTRL));
cal_write(ctx->cal, CAL_WR_DMA_XSIZE(ctx->dma_ctx), val);
ctx_dbg(3, ctx, "CAL_WR_DMA_XSIZE(%d) = 0x%08x\n", ctx->dma_ctx,
cal_read(ctx->cal, CAL_WR_DMA_XSIZE(ctx->dma_ctx)));
}
void cal_ctx_set_dma_addr(struct cal_ctx *ctx, dma_addr_t addr)
{
cal_write(ctx->cal, CAL_WR_DMA_ADDR(ctx->index), addr);
cal_write(ctx->cal, CAL_WR_DMA_ADDR(ctx->dma_ctx), addr);
}
static void cal_ctx_wr_dma_enable(struct cal_ctx *ctx)
{
u32 val = cal_read(ctx->cal, CAL_WR_DMA_CTRL(ctx->dma_ctx));
cal_set_field(&val, CAL_WR_DMA_CTRL_MODE_CONST,
CAL_WR_DMA_CTRL_MODE_MASK);
cal_write(ctx->cal, CAL_WR_DMA_CTRL(ctx->dma_ctx), val);
}
static void cal_ctx_wr_dma_disable(struct cal_ctx *ctx)
{
u32 val = cal_read(ctx->cal, CAL_WR_DMA_CTRL(ctx->index));
u32 val = cal_read(ctx->cal, CAL_WR_DMA_CTRL(ctx->dma_ctx));
cal_set_field(&val, CAL_WR_DMA_CTRL_MODE_DIS,
CAL_WR_DMA_CTRL_MODE_MASK);
cal_write(ctx->cal, CAL_WR_DMA_CTRL(ctx->index), val);
cal_write(ctx->cal, CAL_WR_DMA_CTRL(ctx->dma_ctx), val);
}
static bool cal_ctx_wr_dma_stopped(struct cal_ctx *ctx)
@ -441,6 +469,31 @@ static bool cal_ctx_wr_dma_stopped(struct cal_ctx *ctx)
return stopped;
}
int cal_ctx_prepare(struct cal_ctx *ctx)
{
int ret;
ctx->use_pix_proc = !ctx->fmtinfo->meta;
if (ctx->use_pix_proc) {
ret = cal_reserve_pix_proc(ctx->cal);
if (ret < 0) {
ctx_err(ctx, "Failed to reserve pix proc: %d\n", ret);
return ret;
}
ctx->pix_proc = ret;
}
return 0;
}
void cal_ctx_unprepare(struct cal_ctx *ctx)
{
if (ctx->use_pix_proc)
cal_release_pix_proc(ctx->cal, ctx->pix_proc);
}
void cal_ctx_start(struct cal_ctx *ctx)
{
ctx->sequence = 0;
@ -448,14 +501,17 @@ void cal_ctx_start(struct cal_ctx *ctx)
/* Configure the CSI-2, pixel processing and write DMA contexts. */
cal_ctx_csi2_config(ctx);
cal_ctx_pix_proc_config(ctx);
if (ctx->use_pix_proc)
cal_ctx_pix_proc_config(ctx);
cal_ctx_wr_dma_config(ctx);
/* Enable IRQ_WDMA_END and IRQ_WDMA_START. */
cal_write(ctx->cal, CAL_HL_IRQENABLE_SET(1),
CAL_HL_IRQ_MASK(ctx->index));
CAL_HL_IRQ_WDMA_END_MASK(ctx->dma_ctx));
cal_write(ctx->cal, CAL_HL_IRQENABLE_SET(2),
CAL_HL_IRQ_MASK(ctx->index));
CAL_HL_IRQ_WDMA_START_MASK(ctx->dma_ctx));
cal_ctx_wr_dma_enable(ctx);
}
void cal_ctx_stop(struct cal_ctx *ctx)
@ -479,11 +535,18 @@ void cal_ctx_stop(struct cal_ctx *ctx)
/* Disable IRQ_WDMA_END and IRQ_WDMA_START. */
cal_write(ctx->cal, CAL_HL_IRQENABLE_CLR(1),
CAL_HL_IRQ_MASK(ctx->index));
CAL_HL_IRQ_WDMA_END_MASK(ctx->dma_ctx));
cal_write(ctx->cal, CAL_HL_IRQENABLE_CLR(2),
CAL_HL_IRQ_MASK(ctx->index));
CAL_HL_IRQ_WDMA_START_MASK(ctx->dma_ctx));
ctx->dma.state = CAL_DMA_STOPPED;
/* Disable CSI2 context */
cal_write(ctx->cal, CAL_CSI2_CTX(ctx->phy->instance, ctx->csi2_ctx), 0);
/* Disable pix proc */
if (ctx->use_pix_proc)
cal_write(ctx->cal, CAL_PIX_PROC(ctx->pix_proc), 0);
}
/* ------------------------------------------------------------------
@ -577,6 +640,16 @@ static irqreturn_t cal_irq(int irq_cal, void *data)
cal_write(cal, CAL_CSI2_COMPLEXIO_IRQSTATUS(i),
cio_stat);
}
if (status & CAL_HL_IRQ_VC_MASK(i)) {
u32 vc_stat = cal_read(cal, CAL_CSI2_VC_IRQSTATUS(i));
dev_err_ratelimited(cal->dev,
"CIO%u VC error: %#08x\n",
i, vc_stat);
cal_write(cal, CAL_CSI2_VC_IRQSTATUS(i), vc_stat);
}
}
}
@ -588,8 +661,8 @@ static irqreturn_t cal_irq(int irq_cal, void *data)
/* Clear Interrupt status */
cal_write(cal, CAL_HL_IRQSTATUS(1), status);
for (i = 0; i < ARRAY_SIZE(cal->ctx); ++i) {
if (status & CAL_HL_IRQ_MASK(i))
for (i = 0; i < cal->num_contexts; ++i) {
if (status & CAL_HL_IRQ_WDMA_END_MASK(i))
cal_irq_wdma_end(cal->ctx[i]);
}
}
@ -602,8 +675,8 @@ static irqreturn_t cal_irq(int irq_cal, void *data)
/* Clear Interrupt status */
cal_write(cal, CAL_HL_IRQSTATUS(2), status);
for (i = 0; i < ARRAY_SIZE(cal->ctx); ++i) {
if (status & CAL_HL_IRQ_MASK(i))
for (i = 0; i < cal->num_contexts; ++i) {
if (status & CAL_HL_IRQ_WDMA_START_MASK(i))
cal_irq_wdma_start(cal->ctx[i]);
}
}
@ -635,20 +708,20 @@ static int cal_async_notifier_bound(struct v4l2_async_notifier *notifier,
int pad;
int ret;
if (phy->sensor) {
if (phy->source) {
phy_info(phy, "Rejecting subdev %s (Already set!!)",
subdev->name);
return 0;
}
phy->sensor = subdev;
phy_dbg(1, phy, "Using sensor %s for capture\n", subdev->name);
phy->source = subdev;
phy_dbg(1, phy, "Using source %s for capture\n", subdev->name);
pad = media_entity_get_fwnode_pad(&subdev->entity,
of_fwnode_handle(phy->sensor_ep_node),
of_fwnode_handle(phy->source_ep_node),
MEDIA_PAD_FL_SOURCE);
if (pad < 0) {
phy_err(phy, "Sensor %s has no connected source pad\n",
phy_err(phy, "Source %s has no connected source pad\n",
subdev->name);
return pad;
}
@ -658,7 +731,7 @@ static int cal_async_notifier_bound(struct v4l2_async_notifier *notifier,
MEDIA_LNK_FL_IMMUTABLE |
MEDIA_LNK_FL_ENABLED);
if (ret) {
phy_err(phy, "Failed to create media link for sensor %s\n",
phy_err(phy, "Failed to create media link for source %s\n",
subdev->name);
return ret;
}
@ -670,15 +743,30 @@ static int cal_async_notifier_complete(struct v4l2_async_notifier *notifier)
{
struct cal_dev *cal = container_of(notifier, struct cal_dev, notifier);
unsigned int i;
int ret = 0;
int ret;
for (i = 0; i < ARRAY_SIZE(cal->ctx); ++i) {
if (cal->ctx[i])
cal_ctx_v4l2_register(cal->ctx[i]);
for (i = 0; i < cal->num_contexts; ++i) {
ret = cal_ctx_v4l2_register(cal->ctx[i]);
if (ret)
goto err_ctx_unreg;
}
if (cal_mc_api)
ret = v4l2_device_register_subdev_nodes(&cal->v4l2_dev);
if (!cal_mc_api)
return 0;
ret = v4l2_device_register_subdev_nodes(&cal->v4l2_dev);
if (ret)
goto err_ctx_unreg;
return 0;
err_ctx_unreg:
for (; i > 0; --i) {
if (!cal->ctx[i - 1])
continue;
cal_ctx_v4l2_unregister(cal->ctx[i - 1]);
}
return ret;
}
@ -701,10 +789,10 @@ static int cal_async_notifier_register(struct cal_dev *cal)
struct cal_v4l2_async_subdev *casd;
struct fwnode_handle *fwnode;
if (!phy->sensor_node)
if (!phy->source_node)
continue;
fwnode = of_fwnode_handle(phy->sensor_node);
fwnode = of_fwnode_handle(phy->source_node);
casd = v4l2_async_notifier_add_fwnode_subdev(&cal->notifier,
fwnode,
struct cal_v4l2_async_subdev);
@ -777,10 +865,8 @@ static void cal_media_unregister(struct cal_dev *cal)
unsigned int i;
/* Unregister all the V4L2 video devices. */
for (i = 0; i < ARRAY_SIZE(cal->ctx); i++) {
if (cal->ctx[i])
cal_ctx_v4l2_unregister(cal->ctx[i]);
}
for (i = 0; i < cal->num_contexts; i++)
cal_ctx_v4l2_unregister(cal->ctx[i]);
cal_async_notifier_unregister(cal);
media_device_unregister(&cal->mdev);
@ -825,13 +911,6 @@ static int cal_media_init(struct cal_dev *cal)
*/
static void cal_media_cleanup(struct cal_dev *cal)
{
unsigned int i;
for (i = 0; i < ARRAY_SIZE(cal->ctx); i++) {
if (cal->ctx[i])
cal_ctx_v4l2_cleanup(cal->ctx[i]);
}
v4l2_device_unregister(&cal->v4l2_dev);
media_device_cleanup(&cal->mdev);
@ -848,14 +927,17 @@ static struct cal_ctx *cal_ctx_create(struct cal_dev *cal, int inst)
struct cal_ctx *ctx;
int ret;
ctx = devm_kzalloc(cal->dev, sizeof(*ctx), GFP_KERNEL);
ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
if (!ctx)
return NULL;
ctx->cal = cal;
ctx->phy = cal->phy[inst];
ctx->index = inst;
ctx->dma_ctx = inst;
ctx->csi2_ctx = inst;
ctx->cport = inst;
ctx->vc = 0;
ctx->datatype = CAL_CSI2_CTX_DT_ANY;
ret = cal_ctx_v4l2_init(ctx);
if (ret)
@ -864,6 +946,13 @@ static struct cal_ctx *cal_ctx_create(struct cal_dev *cal, int inst)
return ctx;
}
static void cal_ctx_destroy(struct cal_ctx *ctx)
{
cal_ctx_v4l2_cleanup(ctx);
kfree(ctx);
}
static const struct of_device_id cal_of_match[] = {
{
.compatible = "ti,dra72-cal",
@ -976,7 +1065,6 @@ static int cal_init_camerarx_regmap(struct cal_dev *cal)
static int cal_probe(struct platform_device *pdev)
{
struct cal_dev *cal;
struct cal_ctx *ctx;
bool connected = false;
unsigned int i;
int ret;
@ -1045,7 +1133,7 @@ static int cal_probe(struct platform_device *pdev)
goto error_camerarx;
}
if (cal->phy[i]->sensor_node)
if (cal->phy[i]->source_node)
connected = true;
}
@ -1057,15 +1145,17 @@ static int cal_probe(struct platform_device *pdev)
/* Create contexts. */
for (i = 0; i < cal->data->num_csi2_phy; ++i) {
if (!cal->phy[i]->sensor_node)
if (!cal->phy[i]->source_node)
continue;
cal->ctx[i] = cal_ctx_create(cal, i);
if (!cal->ctx[i]) {
cal_err(cal, "Failed to create context %u\n", i);
cal->ctx[cal->num_contexts] = cal_ctx_create(cal, i);
if (!cal->ctx[cal->num_contexts]) {
cal_err(cal, "Failed to create context %u\n", cal->num_contexts);
ret = -ENODEV;
goto error_context;
}
cal->num_contexts++;
}
/* Register the media device. */
@ -1076,11 +1166,8 @@ static int cal_probe(struct platform_device *pdev)
return 0;
error_context:
for (i = 0; i < ARRAY_SIZE(cal->ctx); i++) {
ctx = cal->ctx[i];
if (ctx)
cal_ctx_v4l2_cleanup(ctx);
}
for (i = 0; i < cal->num_contexts; i++)
cal_ctx_destroy(cal->ctx[i]);
error_camerarx:
for (i = 0; i < cal->data->num_csi2_phy; i++)
@ -1106,16 +1193,17 @@ static int cal_remove(struct platform_device *pdev)
cal_media_unregister(cal);
for (i = 0; i < ARRAY_SIZE(cal->phy); i++) {
if (cal->phy[i])
cal_camerarx_disable(cal->phy[i]);
}
for (i = 0; i < cal->data->num_csi2_phy; i++)
cal_camerarx_disable(cal->phy[i]);
cal_media_cleanup(cal);
for (i = 0; i < cal->num_contexts; i++)
cal_ctx_destroy(cal->ctx[i]);
for (i = 0; i < cal->data->num_csi2_phy; i++)
cal_camerarx_destroy(cal->phy[i]);
cal_media_cleanup(cal);
if (ret >= 0)
pm_runtime_put_sync(&pdev->dev);
pm_runtime_disable(&pdev->dev);
@ -1127,6 +1215,7 @@ static int cal_runtime_resume(struct device *dev)
{
struct cal_dev *cal = dev_get_drvdata(dev);
unsigned int i;
u32 val;
if (cal->data->flags & DRA72_CAL_PRE_ES2_LDO_DISABLE) {
/*
@ -1143,6 +1232,17 @@ static int cal_runtime_resume(struct device *dev)
*/
cal_write(cal, CAL_HL_IRQENABLE_SET(0), CAL_HL_IRQ_OCPO_ERR_MASK);
val = cal_read(cal, CAL_CTRL);
cal_set_field(&val, CAL_CTRL_BURSTSIZE_BURST128,
CAL_CTRL_BURSTSIZE_MASK);
cal_set_field(&val, 0xf, CAL_CTRL_TAGCNT_MASK);
cal_set_field(&val, CAL_CTRL_POSTED_WRITES_NONPOSTED,
CAL_CTRL_POSTED_WRITES_MASK);
cal_set_field(&val, 0xff, CAL_CTRL_MFLAGL_MASK);
cal_set_field(&val, 0xff, CAL_CTRL_MFLAGH_MASK);
cal_write(cal, CAL_CTRL, val);
cal_dbg(3, cal, "CAL_CTRL = 0x%08x\n", cal_read(cal, CAL_CTRL));
return 0;
}

View File

@ -29,7 +29,7 @@
#include <media/videobuf2-v4l2.h>
#define CAL_MODULE_NAME "cal"
#define CAL_NUM_CONTEXT 2
#define CAL_MAX_NUM_CONTEXT 8
#define CAL_NUM_CSI2_PORTS 2
/*
@ -44,7 +44,22 @@
#define CAL_MAX_HEIGHT_LINES 16383
#define CAL_CAMERARX_PAD_SINK 0
#define CAL_CAMERARX_PAD_SOURCE 1
#define CAL_CAMERARX_PAD_FIRST_SOURCE 1
#define CAL_CAMERARX_NUM_SOURCE_PADS 1
#define CAL_CAMERARX_NUM_PADS (1 + CAL_CAMERARX_NUM_SOURCE_PADS)
static inline bool cal_rx_pad_is_sink(u32 pad)
{
/* Camera RX has 1 sink pad, and N source pads */
return pad == 0;
}
static inline bool cal_rx_pad_is_source(u32 pad)
{
/* Camera RX has 1 sink pad, and N source pads */
return pad >= CAL_CAMERARX_PAD_FIRST_SOURCE &&
pad <= CAL_CAMERARX_NUM_SOURCE_PADS;
}
struct device;
struct device_node;
@ -73,6 +88,7 @@ struct cal_format_info {
u32 code;
/* Bits per pixel */
u8 bpp;
bool meta;
};
/* buffer for one video frame */
@ -149,22 +165,29 @@ struct cal_data {
struct cal_camerarx {
void __iomem *base;
struct resource *res;
struct device *dev;
struct regmap_field *fields[F_MAX_FIELDS];
struct cal_dev *cal;
unsigned int instance;
struct v4l2_fwnode_endpoint endpoint;
struct device_node *sensor_ep_node;
struct device_node *sensor_node;
struct v4l2_subdev *sensor;
struct device_node *source_ep_node;
struct device_node *source_node;
struct v4l2_subdev *source;
struct media_pipeline pipe;
struct v4l2_subdev subdev;
struct media_pad pads[2];
struct v4l2_mbus_framefmt formats[2];
const struct cal_format_info *fmtinfo;
struct media_pad pads[CAL_CAMERARX_NUM_PADS];
struct v4l2_mbus_framefmt formats[CAL_CAMERARX_NUM_PADS];
/*
* Lock for camerarx ops. Protects:
* - formats
* - enable_count
*/
struct mutex mutex;
unsigned int enable_count;
};
struct cal_dev {
@ -184,11 +207,14 @@ struct cal_dev {
/* Camera Core Module handle */
struct cal_camerarx *phy[CAL_NUM_CSI2_PORTS];
struct cal_ctx *ctx[CAL_NUM_CONTEXT];
u32 num_contexts;
struct cal_ctx *ctx[CAL_MAX_NUM_CONTEXT];
struct media_device mdev;
struct v4l2_device v4l2_dev;
struct v4l2_async_notifier notifier;
unsigned long reserved_pix_proc_mask;
};
/*
@ -212,14 +238,20 @@ struct cal_ctx {
/* Used to store current pixel format */
struct v4l2_format v_fmt;
/* Current subdev enumerated format */
/* Current subdev enumerated format (legacy) */
const struct cal_format_info **active_fmt;
unsigned int num_active_fmt;
unsigned int sequence;
struct vb2_queue vb_vidq;
unsigned int index;
unsigned int cport;
u8 dma_ctx;
u8 cport;
u8 csi2_ctx;
u8 pix_proc;
u8 vc;
u8 datatype;
bool use_pix_proc;
};
extern unsigned int cal_debug;
@ -237,11 +269,11 @@ extern bool cal_mc_api;
dev_err((cal)->dev, fmt, ##arg)
#define ctx_dbg(level, ctx, fmt, arg...) \
cal_dbg(level, (ctx)->cal, "ctx%u: " fmt, (ctx)->index, ##arg)
cal_dbg(level, (ctx)->cal, "ctx%u: " fmt, (ctx)->dma_ctx, ##arg)
#define ctx_info(ctx, fmt, arg...) \
cal_info((ctx)->cal, "ctx%u: " fmt, (ctx)->index, ##arg)
cal_info((ctx)->cal, "ctx%u: " fmt, (ctx)->dma_ctx, ##arg)
#define ctx_err(ctx, fmt, arg...) \
cal_err((ctx)->cal, "ctx%u: " fmt, (ctx)->index, ##arg)
cal_err((ctx)->cal, "ctx%u: " fmt, (ctx)->dma_ctx, ##arg)
#define phy_dbg(level, phy, fmt, arg...) \
cal_dbg(level, (phy)->cal, "phy%u: " fmt, (phy)->instance, ##arg)
@ -297,6 +329,8 @@ struct cal_camerarx *cal_camerarx_create(struct cal_dev *cal,
unsigned int instance);
void cal_camerarx_destroy(struct cal_camerarx *phy);
int cal_ctx_prepare(struct cal_ctx *ctx);
void cal_ctx_unprepare(struct cal_ctx *ctx);
void cal_ctx_set_dma_addr(struct cal_ctx *ctx, dma_addr_t addr);
void cal_ctx_start(struct cal_ctx *ctx);
void cal_ctx_stop(struct cal_ctx *ctx);

View File

@ -72,22 +72,8 @@
#define CAL_CSI2_TIMING(m) (0x314U + (m) * 0x80U)
#define CAL_CSI2_VC_IRQENABLE(m) (0x318U + (m) * 0x80U)
#define CAL_CSI2_VC_IRQSTATUS(m) (0x328U + (m) * 0x80U)
#define CAL_CSI2_CTX0(m) (0x330U + (m) * 0x80U)
#define CAL_CSI2_CTX1(m) (0x334U + (m) * 0x80U)
#define CAL_CSI2_CTX2(m) (0x338U + (m) * 0x80U)
#define CAL_CSI2_CTX3(m) (0x33cU + (m) * 0x80U)
#define CAL_CSI2_CTX4(m) (0x340U + (m) * 0x80U)
#define CAL_CSI2_CTX5(m) (0x344U + (m) * 0x80U)
#define CAL_CSI2_CTX6(m) (0x348U + (m) * 0x80U)
#define CAL_CSI2_CTX7(m) (0x34cU + (m) * 0x80U)
#define CAL_CSI2_STATUS0(m) (0x350U + (m) * 0x80U)
#define CAL_CSI2_STATUS1(m) (0x354U + (m) * 0x80U)
#define CAL_CSI2_STATUS2(m) (0x358U + (m) * 0x80U)
#define CAL_CSI2_STATUS3(m) (0x35cU + (m) * 0x80U)
#define CAL_CSI2_STATUS4(m) (0x360U + (m) * 0x80U)
#define CAL_CSI2_STATUS5(m) (0x364U + (m) * 0x80U)
#define CAL_CSI2_STATUS6(m) (0x368U + (m) * 0x80U)
#define CAL_CSI2_STATUS7(m) (0x36cU + (m) * 0x80U)
#define CAL_CSI2_CTX(phy, csi2_ctx) (0x330U + (phy) * 0x80U + (csi2_ctx) * 4)
#define CAL_CSI2_STATUS(phy, csi2_ctx) (0x350U + (phy) * 0x80U + (csi2_ctx) * 4)
/* CAL CSI2 PHY register offsets */
#define CAL_CSI2_PHY_REG0 0x000
@ -139,7 +125,8 @@
#define CAL_HL_IRQ_EOI_LINE_NUMBER_READ0 0
#define CAL_HL_IRQ_EOI_LINE_NUMBER_EOI0 0
#define CAL_HL_IRQ_MASK(m) BIT(m)
#define CAL_HL_IRQ_WDMA_END_MASK(m) BIT(m)
#define CAL_HL_IRQ_WDMA_START_MASK(m) BIT(m)
#define CAL_HL_IRQ_OCPO_ERR_MASK BIT(6)
@ -419,32 +406,16 @@
#define CAL_CSI2_TIMING_STOP_STATE_X16_IO1_MASK BIT(14)
#define CAL_CSI2_TIMING_FORCE_RX_MODE_IO1_MASK BIT(15)
#define CAL_CSI2_VC_IRQ_FS_IRQ_0_MASK BIT(0)
#define CAL_CSI2_VC_IRQ_FE_IRQ_0_MASK BIT(1)
#define CAL_CSI2_VC_IRQ_LS_IRQ_0_MASK BIT(2)
#define CAL_CSI2_VC_IRQ_LE_IRQ_0_MASK BIT(3)
#define CAL_CSI2_VC_IRQ_CS_IRQ_0_MASK BIT(4)
#define CAL_CSI2_VC_IRQ_ECC_CORRECTION0_IRQ_0_MASK BIT(5)
#define CAL_CSI2_VC_IRQ_FS_IRQ_1_MASK BIT(8)
#define CAL_CSI2_VC_IRQ_FE_IRQ_1_MASK BIT(9)
#define CAL_CSI2_VC_IRQ_LS_IRQ_1_MASK BIT(10)
#define CAL_CSI2_VC_IRQ_LE_IRQ_1_MASK BIT(11)
#define CAL_CSI2_VC_IRQ_CS_IRQ_1_MASK BIT(12)
#define CAL_CSI2_VC_IRQ_ECC_CORRECTION0_IRQ_1_MASK BIT(13)
#define CAL_CSI2_VC_IRQ_FS_IRQ_2_MASK BIT(16)
#define CAL_CSI2_VC_IRQ_FE_IRQ_2_MASK BIT(17)
#define CAL_CSI2_VC_IRQ_LS_IRQ_2_MASK BIT(18)
#define CAL_CSI2_VC_IRQ_LE_IRQ_2_MASK BIT(19)
#define CAL_CSI2_VC_IRQ_CS_IRQ_2_MASK BIT(20)
#define CAL_CSI2_VC_IRQ_ECC_CORRECTION0_IRQ_2_MASK BIT(21)
#define CAL_CSI2_VC_IRQ_FS_IRQ_3_MASK BIT(24)
#define CAL_CSI2_VC_IRQ_FE_IRQ_3_MASK BIT(25)
#define CAL_CSI2_VC_IRQ_LS_IRQ_3_MASK BIT(26)
#define CAL_CSI2_VC_IRQ_LE_IRQ_3_MASK BIT(27)
#define CAL_CSI2_VC_IRQ_CS_IRQ_3_MASK BIT(28)
#define CAL_CSI2_VC_IRQ_ECC_CORRECTION0_IRQ_3_MASK BIT(29)
#define CAL_CSI2_VC_IRQ_FS_IRQ_MASK(n) BIT(0 + ((n) * 8))
#define CAL_CSI2_VC_IRQ_FE_IRQ_MASK(n) BIT(1 + ((n) * 8))
#define CAL_CSI2_VC_IRQ_LS_IRQ_MASK(n) BIT(2 + ((n) * 8))
#define CAL_CSI2_VC_IRQ_LE_IRQ_MASK(n) BIT(3 + ((n) * 8))
#define CAL_CSI2_VC_IRQ_CS_IRQ_MASK(n) BIT(4 + ((n) * 8))
#define CAL_CSI2_VC_IRQ_ECC_CORRECTION_IRQ_MASK(n) BIT(5 + ((n) * 8))
#define CAL_CSI2_CTX_DT_MASK GENMASK(5, 0)
#define CAL_CSI2_CTX_DT_DISABLED 0
#define CAL_CSI2_CTX_DT_ANY 1
#define CAL_CSI2_CTX_VC_MASK GENMASK(7, 6)
#define CAL_CSI2_CTX_CPORT_MASK GENMASK(12, 8)
#define CAL_CSI2_CTX_ATT_MASK BIT(13)

View File

@ -676,9 +676,9 @@ int vsp1_entity_init(struct vsp1_device *vsp1, struct vsp1_entity *entity,
* rectangles.
*/
entity->config = v4l2_subdev_alloc_state(&entity->subdev);
if (entity->config == NULL) {
if (IS_ERR(entity->config)) {
media_entity_cleanup(&entity->subdev.entity);
return -ENOMEM;
return PTR_ERR(entity->config);
}
return 0;

View File

@ -246,6 +246,16 @@ config IR_MESON
To compile this driver as a module, choose M here: the
module will be called meson-ir.
config IR_MESON_TX
tristate "Amlogic Meson IR TX"
depends on ARCH_MESON || COMPILE_TEST
help
Say Y if you want to use the IR transmitter available on
Amlogic Meson SoCs.
To compile this driver as a module, choose M here: the
module will be called meson-ir-tx.
config IR_MTK
tristate "Mediatek IR remote receiver"
depends on ARCH_MEDIATEK || COMPILE_TEST

View File

@ -28,6 +28,7 @@ obj-$(CONFIG_IR_ITE_CIR) += ite-cir.o
obj-$(CONFIG_IR_MCEUSB) += mceusb.o
obj-$(CONFIG_IR_FINTEK) += fintek-cir.o
obj-$(CONFIG_IR_MESON) += meson-ir.o
obj-$(CONFIG_IR_MESON_TX) += meson-ir-tx.o
obj-$(CONFIG_IR_NUVOTON) += nuvoton-cir.o
obj-$(CONFIG_IR_ENE) += ene_ir.o
obj-$(CONFIG_IR_REDRAT3) += redrat3.o

View File

@ -1052,7 +1052,7 @@ static int ene_probe(struct pnp_dev *pnp_dev, const struct pnp_device_id *id)
rdev->device_name = "ENE eHome Infrared Remote Receiver";
if (dev->hw_learning_and_tx_capable) {
rdev->s_learning_mode = ene_set_learning_mode;
rdev->s_wideband_receiver = ene_set_learning_mode;
init_completion(&dev->tx_complete);
rdev->tx_ir = ene_transmit;
rdev->s_tx_mask = ene_set_tx_mask;

View File

@ -412,7 +412,7 @@ static long lirc_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
val |= LIRC_CAN_SET_REC_CARRIER |
LIRC_CAN_SET_REC_CARRIER_RANGE;
if (dev->s_learning_mode)
if (dev->s_wideband_receiver)
val |= LIRC_CAN_USE_WIDEBAND_RECEIVER;
if (dev->s_carrier_report)
@ -519,10 +519,10 @@ static long lirc_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
break;
case LIRC_SET_WIDEBAND_RECEIVER:
if (!dev->s_learning_mode)
if (!dev->s_wideband_receiver)
ret = -ENOTTY;
else
ret = dev->s_learning_mode(dev, !!val);
ret = dev->s_wideband_receiver(dev, !!val);
break;
case LIRC_SET_MEASURE_CARRIER_MODE:

View File

@ -1630,7 +1630,7 @@ static struct rc_dev *mceusb_init_rc_dev(struct mceusb_dev *ir)
rc->tx_ir = mceusb_tx_ir;
}
if (ir->flags.rx2 > 0) {
rc->s_learning_mode = mceusb_set_rx_wideband;
rc->s_wideband_receiver = mceusb_set_rx_wideband;
rc->s_carrier_report = mceusb_set_rx_carrier_report;
}
rc->driver_name = DRIVER_NAME;

View File

@ -0,0 +1,407 @@
// SPDX-License-Identifier: GPL-2.0-only
/**
* meson-ir-tx.c - Amlogic Meson IR TX driver
*
* Copyright (c) 2021, SberDevices. All Rights Reserved.
*
* Author: Viktor Prutyanov <viktor.prutyanov@phystech.edu>
*/
#include <linux/device.h>
#include <linux/module.h>
#include <linux/sched.h>
#include <linux/platform_device.h>
#include <linux/of.h>
#include <linux/interrupt.h>
#include <linux/spinlock.h>
#include <linux/of_irq.h>
#include <linux/clk.h>
#include <linux/slab.h>
#include <media/rc-core.h>
#define DEVICE_NAME "Meson IR TX"
#define DRIVER_NAME "meson-ir-tx"
#define MIRTX_DEFAULT_CARRIER 38000
#define MIRTX_DEFAULT_DUTY_CYCLE 50
#define MIRTX_FIFO_THD 32
#define IRB_MOD_1US_CLK_RATE 1000000
#define IRB_FIFO_LEN 128
#define IRB_ADDR0 0x0
#define IRB_ADDR1 0x4
#define IRB_ADDR2 0x8
#define IRB_ADDR3 0xc
#define IRB_MAX_DELAY (1 << 10)
#define IRB_DELAY_MASK (IRB_MAX_DELAY - 1)
/* IRCTRL_IR_BLASTER_ADDR0 */
#define IRB_MOD_CLK(x) ((x) << 12)
#define IRB_MOD_SYS_CLK 0
#define IRB_MOD_XTAL3_CLK 1
#define IRB_MOD_1US_CLK 2
#define IRB_MOD_10US_CLK 3
#define IRB_INIT_HIGH BIT(2)
#define IRB_ENABLE BIT(0)
/* IRCTRL_IR_BLASTER_ADDR2 */
#define IRB_MOD_COUNT(lo, hi) ((((lo) - 1) << 16) | ((hi) - 1))
/* IRCTRL_IR_BLASTER_ADDR2 */
#define IRB_WRITE_FIFO BIT(16)
#define IRB_MOD_ENABLE BIT(12)
#define IRB_TB_1US (0x0 << 10)
#define IRB_TB_10US (0x1 << 10)
#define IRB_TB_100US (0x2 << 10)
#define IRB_TB_MOD_CLK (0x3 << 10)
/* IRCTRL_IR_BLASTER_ADDR3 */
#define IRB_FIFO_THD_PENDING BIT(16)
#define IRB_FIFO_IRQ_ENABLE BIT(8)
struct meson_irtx {
struct device *dev;
void __iomem *reg_base;
u32 *buf;
unsigned int buf_len;
unsigned int buf_head;
unsigned int carrier;
unsigned int duty_cycle;
/* Locks buf */
spinlock_t lock;
struct completion completion;
unsigned long clk_rate;
};
static void meson_irtx_set_mod(struct meson_irtx *ir)
{
unsigned int cnt = DIV_ROUND_CLOSEST(ir->clk_rate, ir->carrier);
unsigned int pulse_cnt = DIV_ROUND_CLOSEST(cnt * ir->duty_cycle, 100);
unsigned int space_cnt = cnt - pulse_cnt;
dev_dbg(ir->dev, "F_mod = %uHz, T_mod = %luns, duty_cycle = %u%%\n",
ir->carrier, NSEC_PER_SEC / ir->clk_rate * cnt,
100 * pulse_cnt / cnt);
writel(IRB_MOD_COUNT(pulse_cnt, space_cnt),
ir->reg_base + IRB_ADDR1);
}
static void meson_irtx_setup(struct meson_irtx *ir, unsigned int clk_nr)
{
/*
* Disable the TX, set modulator clock tick and set initialize
* output to be high. Set up carrier frequency and duty cycle. Then
* unset initialize output. Enable FIFO interrupt, set FIFO interrupt
* threshold. Finally, enable the transmitter back.
*/
writel(~IRB_ENABLE & (IRB_MOD_CLK(clk_nr) | IRB_INIT_HIGH),
ir->reg_base + IRB_ADDR0);
meson_irtx_set_mod(ir);
writel(readl(ir->reg_base + IRB_ADDR0) & ~IRB_INIT_HIGH,
ir->reg_base + IRB_ADDR0);
writel(IRB_FIFO_IRQ_ENABLE | MIRTX_FIFO_THD,
ir->reg_base + IRB_ADDR3);
writel(readl(ir->reg_base + IRB_ADDR0) | IRB_ENABLE,
ir->reg_base + IRB_ADDR0);
}
static u32 meson_irtx_prepare_pulse(struct meson_irtx *ir, unsigned int time)
{
unsigned int delay;
unsigned int tb = IRB_TB_MOD_CLK;
unsigned int tb_us = DIV_ROUND_CLOSEST(USEC_PER_SEC, ir->carrier);
delay = (DIV_ROUND_CLOSEST(time, tb_us) - 1) & IRB_DELAY_MASK;
return ((IRB_WRITE_FIFO | IRB_MOD_ENABLE) | tb | delay);
}
static u32 meson_irtx_prepare_space(struct meson_irtx *ir, unsigned int time)
{
unsigned int delay;
unsigned int tb = IRB_TB_100US;
unsigned int tb_us = 100;
if (time <= IRB_MAX_DELAY) {
tb = IRB_TB_1US;
tb_us = 1;
} else if (time <= 10 * IRB_MAX_DELAY) {
tb = IRB_TB_10US;
tb_us = 10;
} else if (time <= 100 * IRB_MAX_DELAY) {
tb = IRB_TB_100US;
tb_us = 100;
}
delay = (DIV_ROUND_CLOSEST(time, tb_us) - 1) & IRB_DELAY_MASK;
return ((IRB_WRITE_FIFO & ~IRB_MOD_ENABLE) | tb | delay);
}
static void meson_irtx_send_buffer(struct meson_irtx *ir)
{
unsigned int nr = 0;
unsigned int max_fifo_level = IRB_FIFO_LEN - MIRTX_FIFO_THD;
while (ir->buf_head < ir->buf_len && nr < max_fifo_level) {
writel(ir->buf[ir->buf_head], ir->reg_base + IRB_ADDR2);
ir->buf_head++;
nr++;
}
}
static bool meson_irtx_check_buf(struct meson_irtx *ir,
unsigned int *buf, unsigned int len)
{
unsigned int i;
for (i = 0; i < len; i++) {
unsigned int max_tb_us;
/*
* Max space timebase is 100 us.
* Pulse timebase equals to carrier period.
*/
if (i % 2 == 0)
max_tb_us = USEC_PER_SEC / ir->carrier;
else
max_tb_us = 100;
if (buf[i] >= max_tb_us * IRB_MAX_DELAY)
return false;
}
return true;
}
static void meson_irtx_fill_buf(struct meson_irtx *ir, u32 *dst_buf,
unsigned int *src_buf, unsigned int len)
{
unsigned int i;
for (i = 0; i < len; i++) {
if (i % 2 == 0)
dst_buf[i] = meson_irtx_prepare_pulse(ir, src_buf[i]);
else
dst_buf[i] = meson_irtx_prepare_space(ir, src_buf[i]);
}
}
static irqreturn_t meson_irtx_irqhandler(int irq, void *data)
{
unsigned long flags;
struct meson_irtx *ir = data;
writel(readl(ir->reg_base + IRB_ADDR3) & ~IRB_FIFO_THD_PENDING,
ir->reg_base + IRB_ADDR3);
if (completion_done(&ir->completion))
return IRQ_HANDLED;
spin_lock_irqsave(&ir->lock, flags);
if (ir->buf_head < ir->buf_len)
meson_irtx_send_buffer(ir);
else
complete(&ir->completion);
spin_unlock_irqrestore(&ir->lock, flags);
return IRQ_HANDLED;
}
static int meson_irtx_set_carrier(struct rc_dev *rc, u32 carrier)
{
struct meson_irtx *ir = rc->priv;
if (carrier == 0)
return -EINVAL;
ir->carrier = carrier;
meson_irtx_set_mod(ir);
return 0;
}
static int meson_irtx_set_duty_cycle(struct rc_dev *rc, u32 duty_cycle)
{
struct meson_irtx *ir = rc->priv;
ir->duty_cycle = duty_cycle;
meson_irtx_set_mod(ir);
return 0;
}
static void meson_irtx_update_buf(struct meson_irtx *ir, u32 *buf,
unsigned int len, unsigned int head)
{
ir->buf = buf;
ir->buf_len = len;
ir->buf_head = head;
}
static int meson_irtx_transmit(struct rc_dev *rc, unsigned int *buf,
unsigned int len)
{
unsigned long flags;
struct meson_irtx *ir = rc->priv;
u32 *tx_buf;
int ret = len;
if (!meson_irtx_check_buf(ir, buf, len))
return -EINVAL;
tx_buf = kmalloc_array(len, sizeof(u32), GFP_KERNEL);
if (!tx_buf)
return -ENOMEM;
meson_irtx_fill_buf(ir, tx_buf, buf, len);
dev_dbg(ir->dev, "TX buffer filled, length = %u\n", len);
spin_lock_irqsave(&ir->lock, flags);
meson_irtx_update_buf(ir, tx_buf, len, 0);
reinit_completion(&ir->completion);
meson_irtx_send_buffer(ir);
spin_unlock_irqrestore(&ir->lock, flags);
if (!wait_for_completion_timeout(&ir->completion,
usecs_to_jiffies(IR_MAX_DURATION)))
ret = -ETIMEDOUT;
spin_lock_irqsave(&ir->lock, flags);
kfree(ir->buf);
meson_irtx_update_buf(ir, NULL, 0, 0);
spin_unlock_irqrestore(&ir->lock, flags);
return ret;
}
static int meson_irtx_mod_clock_probe(struct meson_irtx *ir,
unsigned int *clk_nr)
{
struct device_node *np = ir->dev->of_node;
struct clk *clock;
if (!np)
return -ENODEV;
clock = devm_clk_get(ir->dev, "xtal");
if (IS_ERR(clock) || clk_prepare_enable(clock))
return -ENODEV;
*clk_nr = IRB_MOD_XTAL3_CLK;
ir->clk_rate = clk_get_rate(clock) / 3;
if (ir->clk_rate < IRB_MOD_1US_CLK_RATE) {
*clk_nr = IRB_MOD_1US_CLK;
ir->clk_rate = IRB_MOD_1US_CLK_RATE;
}
dev_info(ir->dev, "F_clk = %luHz\n", ir->clk_rate);
return 0;
}
static int __init meson_irtx_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct meson_irtx *ir;
struct rc_dev *rc;
int irq;
unsigned int clk_nr;
int ret;
ir = devm_kzalloc(dev, sizeof(*ir), GFP_KERNEL);
if (!ir)
return -ENOMEM;
ir->reg_base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(ir->reg_base))
return PTR_ERR(ir->reg_base);
irq = platform_get_irq(pdev, 0);
if (irq < 0) {
dev_err(dev, "no irq resource found\n");
return -ENODEV;
}
ir->dev = dev;
ir->carrier = MIRTX_DEFAULT_CARRIER;
ir->duty_cycle = MIRTX_DEFAULT_DUTY_CYCLE;
init_completion(&ir->completion);
spin_lock_init(&ir->lock);
ret = meson_irtx_mod_clock_probe(ir, &clk_nr);
if (ret) {
dev_err(dev, "modulator clock setup failed\n");
return ret;
}
meson_irtx_setup(ir, clk_nr);
ret = devm_request_irq(dev, irq,
meson_irtx_irqhandler,
IRQF_TRIGGER_RISING,
DRIVER_NAME, ir);
if (ret) {
dev_err(dev, "irq request failed\n");
return ret;
}
rc = rc_allocate_device(RC_DRIVER_IR_RAW_TX);
if (!rc)
return -ENOMEM;
rc->driver_name = DRIVER_NAME;
rc->device_name = DEVICE_NAME;
rc->priv = ir;
rc->tx_ir = meson_irtx_transmit;
rc->s_tx_carrier = meson_irtx_set_carrier;
rc->s_tx_duty_cycle = meson_irtx_set_duty_cycle;
ret = rc_register_device(rc);
if (ret < 0) {
dev_err(dev, "rc_dev registration failed\n");
rc_free_device(rc);
return ret;
}
platform_set_drvdata(pdev, rc);
return 0;
}
static int meson_irtx_remove(struct platform_device *pdev)
{
struct rc_dev *rc = platform_get_drvdata(pdev);
rc_unregister_device(rc);
return 0;
}
static const struct of_device_id meson_irtx_dt_match[] = {
{
.compatible = "amlogic,meson-g12a-ir-tx",
},
{},
};
MODULE_DEVICE_TABLE(of, meson_irtx_dt_match);
static struct platform_driver meson_irtx_pd = {
.remove = meson_irtx_remove,
.driver = {
.name = DRIVER_NAME,
.owner = THIS_MODULE,
.of_match_table = meson_irtx_dt_match,
},
};
module_platform_driver_probe(meson_irtx_pd, meson_irtx_probe);
MODULE_DESCRIPTION("Meson IR TX driver");
MODULE_AUTHOR("Viktor Prutyanov <viktor.prutyanov@phystech.edu>");
MODULE_LICENSE("GPL");

View File

@ -15,12 +15,9 @@
#include <linux/slab.h>
#include <media/rc-core.h>
#define DRIVER_NAME "rc-loopback"
#define dprintk(x...) if (debug) printk(KERN_INFO DRIVER_NAME ": " x)
#define RXMASK_REGULAR 0x1
#define RXMASK_LEARNING 0x2
static bool debug;
#define DRIVER_NAME "rc-loopback"
#define RXMASK_NARROWBAND 0x1
#define RXMASK_WIDEBAND 0x2
struct loopback_dev {
struct rc_dev *dev;
@ -28,7 +25,7 @@ struct loopback_dev {
u32 txcarrier;
u32 txduty;
bool idle;
bool learning;
bool wideband;
bool carrierreport;
u32 rxcarriermin;
u32 rxcarriermax;
@ -40,12 +37,12 @@ static int loop_set_tx_mask(struct rc_dev *dev, u32 mask)
{
struct loopback_dev *lodev = dev->priv;
if ((mask & (RXMASK_REGULAR | RXMASK_LEARNING)) != mask) {
dprintk("invalid tx mask: %u\n", mask);
return -EINVAL;
if ((mask & (RXMASK_NARROWBAND | RXMASK_WIDEBAND)) != mask) {
dev_dbg(&dev->dev, "invalid tx mask: %u\n", mask);
return 2;
}
dprintk("setting tx mask: %u\n", mask);
dev_dbg(&dev->dev, "setting tx mask: %u\n", mask);
lodev->txmask = mask;
return 0;
}
@ -54,7 +51,7 @@ static int loop_set_tx_carrier(struct rc_dev *dev, u32 carrier)
{
struct loopback_dev *lodev = dev->priv;
dprintk("setting tx carrier: %u\n", carrier);
dev_dbg(&dev->dev, "setting tx carrier: %u\n", carrier);
lodev->txcarrier = carrier;
return 0;
}
@ -64,11 +61,11 @@ static int loop_set_tx_duty_cycle(struct rc_dev *dev, u32 duty_cycle)
struct loopback_dev *lodev = dev->priv;
if (duty_cycle < 1 || duty_cycle > 99) {
dprintk("invalid duty cycle: %u\n", duty_cycle);
dev_dbg(&dev->dev, "invalid duty cycle: %u\n", duty_cycle);
return -EINVAL;
}
dprintk("setting duty cycle: %u\n", duty_cycle);
dev_dbg(&dev->dev, "setting duty cycle: %u\n", duty_cycle);
lodev->txduty = duty_cycle;
return 0;
}
@ -78,11 +75,11 @@ static int loop_set_rx_carrier_range(struct rc_dev *dev, u32 min, u32 max)
struct loopback_dev *lodev = dev->priv;
if (min < 1 || min > max) {
dprintk("invalid rx carrier range %u to %u\n", min, max);
dev_dbg(&dev->dev, "invalid rx carrier range %u to %u\n", min, max);
return -EINVAL;
}
dprintk("setting rx carrier range %u to %u\n", min, max);
dev_dbg(&dev->dev, "setting rx carrier range %u to %u\n", min, max);
lodev->rxcarriermin = min;
lodev->rxcarriermax = max;
return 0;
@ -97,25 +94,33 @@ static int loop_tx_ir(struct rc_dev *dev, unsigned *txbuf, unsigned count)
if (lodev->txcarrier < lodev->rxcarriermin ||
lodev->txcarrier > lodev->rxcarriermax) {
dprintk("ignoring tx, carrier out of range\n");
dev_dbg(&dev->dev, "ignoring tx, carrier out of range\n");
goto out;
}
if (lodev->learning)
rxmask = RXMASK_LEARNING;
if (lodev->wideband)
rxmask = RXMASK_WIDEBAND;
else
rxmask = RXMASK_REGULAR;
rxmask = RXMASK_NARROWBAND;
if (!(rxmask & lodev->txmask)) {
dprintk("ignoring tx, rx mask mismatch\n");
dev_dbg(&dev->dev, "ignoring tx, rx mask mismatch\n");
goto out;
}
for (i = 0; i < count; i++) {
rawir.pulse = i % 2 ? false : true;
rawir.duration = txbuf[i];
if (rawir.duration)
ir_raw_event_store_with_filter(dev, &rawir);
ir_raw_event_store_with_filter(dev, &rawir);
}
if (lodev->carrierreport) {
rawir.pulse = false;
rawir.carrier_report = true;
rawir.carrier = lodev->txcarrier;
ir_raw_event_store(dev, &rawir);
}
/* Fake a silence long enough to cause us to go idle */
@ -134,18 +139,18 @@ static void loop_set_idle(struct rc_dev *dev, bool enable)
struct loopback_dev *lodev = dev->priv;
if (lodev->idle != enable) {
dprintk("%sing idle mode\n", enable ? "enter" : "exit");
dev_dbg(&dev->dev, "%sing idle mode\n", enable ? "enter" : "exit");
lodev->idle = enable;
}
}
static int loop_set_learning_mode(struct rc_dev *dev, int enable)
static int loop_set_wideband_receiver(struct rc_dev *dev, int enable)
{
struct loopback_dev *lodev = dev->priv;
if (lodev->learning != enable) {
dprintk("%sing learning mode\n", enable ? "enter" : "exit");
lodev->learning = !!enable;
if (lodev->wideband != enable) {
dev_dbg(&dev->dev, "using %sband receiver\n", enable ? "wide" : "narrow");
lodev->wideband = !!enable;
}
return 0;
@ -156,7 +161,7 @@ static int loop_set_carrier_report(struct rc_dev *dev, int enable)
struct loopback_dev *lodev = dev->priv;
if (lodev->carrierreport != enable) {
dprintk("%sabling carrier reports\n", enable ? "en" : "dis");
dev_dbg(&dev->dev, "%sabling carrier reports\n", enable ? "en" : "dis");
lodev->carrierreport = !!enable;
}
@ -204,10 +209,8 @@ static int __init loop_init(void)
int ret;
rc = rc_allocate_device(RC_DRIVER_IR_RAW);
if (!rc) {
printk(KERN_ERR DRIVER_NAME ": rc_dev allocation failed\n");
if (!rc)
return -ENOMEM;
}
rc->device_name = "rc-core loopback device";
rc->input_phys = "rc-core/virtual";
@ -219,9 +222,9 @@ static int __init loop_init(void)
rc->allowed_protocols = RC_PROTO_BIT_ALL_IR_DECODER;
rc->allowed_wakeup_protocols = RC_PROTO_BIT_ALL_IR_ENCODER;
rc->encode_wakeup = true;
rc->timeout = MS_TO_US(100); /* 100 ms */
rc->timeout = IR_DEFAULT_TIMEOUT;
rc->min_timeout = 1;
rc->max_timeout = UINT_MAX;
rc->max_timeout = IR_MAX_TIMEOUT;
rc->rx_resolution = 1;
rc->tx_resolution = 1;
rc->s_tx_mask = loop_set_tx_mask;
@ -230,22 +233,22 @@ static int __init loop_init(void)
rc->s_rx_carrier_range = loop_set_rx_carrier_range;
rc->tx_ir = loop_tx_ir;
rc->s_idle = loop_set_idle;
rc->s_learning_mode = loop_set_learning_mode;
rc->s_wideband_receiver = loop_set_wideband_receiver;
rc->s_carrier_report = loop_set_carrier_report;
rc->s_wakeup_filter = loop_set_wakeup_filter;
loopdev.txmask = RXMASK_REGULAR;
loopdev.txmask = RXMASK_NARROWBAND;
loopdev.txcarrier = 36000;
loopdev.txduty = 50;
loopdev.rxcarriermin = 1;
loopdev.rxcarriermax = ~0;
loopdev.idle = true;
loopdev.learning = false;
loopdev.wideband = false;
loopdev.carrierreport = false;
ret = rc_register_device(rc);
if (ret < 0) {
printk(KERN_ERR DRIVER_NAME ": rc_dev registration failed\n");
dev_err(&rc->dev, "rc_dev registration failed\n");
rc_free_device(rc);
return ret;
}
@ -262,9 +265,6 @@ static void __exit loop_exit(void)
module_init(loop_init);
module_exit(loop_exit);
module_param(debug, bool, S_IRUGO | S_IWUSR);
MODULE_PARM_DESC(debug, "Enable debug messages");
MODULE_DESCRIPTION("Loopback device for rc-core debugging");
MODULE_AUTHOR("David Härdeman <david@hardeman.nu>");
MODULE_LICENSE("GPL");

View File

@ -1940,7 +1940,7 @@ int rc_register_device(struct rc_dev *dev)
kfree(path);
/*
* once the the input device is registered in rc_setup_rx_device,
* once the input device is registered in rc_setup_rx_device,
* userspace can open the input device and rc_open() will be called
* as a result. This results in driver code being allowed to submit
* keycodes with rc_keydown, so lirc must be registered first.

View File

@ -6,7 +6,7 @@
* based heavily on the work of Stephen Cox, with additional
* help from RedRat Ltd.
*
* This driver began life based an an old version of the first-generation
* This driver began life based on an old version of the first-generation
* lirc_mceusb driver from the lirc 0.7.2 distribution. It was then
* significantly rewritten by Stephen Cox with the aid of RedRat Ltd's
* Chris Dodge.

View File

@ -265,8 +265,6 @@ static void streamzap_callback(struct urb *urb)
ir_raw_event_handle(sz->rdev);
usb_submit_urb(urb, GFP_ATOMIC);
return;
}
static struct rc_dev *streamzap_init_rc_dev(struct streamzap_ir *sz)

View File

@ -524,13 +524,13 @@ cxd2880_spi_probe(struct spi_device *spi)
if (IS_ERR(dvb_spi->vcc_supply)) {
if (PTR_ERR(dvb_spi->vcc_supply) == -EPROBE_DEFER) {
ret = -EPROBE_DEFER;
goto fail_adapter;
goto fail_regulator;
}
dvb_spi->vcc_supply = NULL;
} else {
ret = regulator_enable(dvb_spi->vcc_supply);
if (ret)
goto fail_adapter;
goto fail_regulator;
}
dvb_spi->spi = spi;
@ -618,6 +618,9 @@ fail_frontend:
fail_attach:
dvb_unregister_adapter(&dvb_spi->adapter);
fail_adapter:
if (!dvb_spi->vcc_supply)
regulator_disable(dvb_spi->vcc_supply);
fail_regulator:
kfree(dvb_spi);
return ret;
}

View File

@ -282,5 +282,5 @@ struct cec_adapter *vivid_cec_alloc_adap(struct vivid_dev *dev,
snprintf(name, sizeof(name), "vivid-%03d-vid-%s%d",
dev->inst, is_source ? "out" : "cap", idx);
return cec_allocate_adapter(&vivid_cec_adap_ops, dev,
name, caps, 1);
name, caps, CEC_MAX_LOG_ADDRS);
}

View File

@ -34,6 +34,8 @@ config DVB_USB_AF9035
tristate "Afatech AF9035 DVB-T USB2.0 support"
depends on DVB_USB_V2
select DVB_AF9033
select DVB_SI2168 if MEDIA_SUBDRV_AUTOSELECT
select MEDIA_TUNER_SI2157 if MEDIA_SUBDRV_AUTOSELECT
select MEDIA_TUNER_TUA9001 if MEDIA_SUBDRV_AUTOSELECT
select MEDIA_TUNER_FC0011 if MEDIA_SUBDRV_AUTOSELECT
select MEDIA_TUNER_MXL5007T if MEDIA_SUBDRV_AUTOSELECT

View File

@ -210,6 +210,7 @@ static int af9035_add_i2c_dev(struct dvb_usb_device *d, const char *type,
/* register I2C device */
client = i2c_new_client_device(adapter, &board_info);
if (!i2c_client_has_driver(client)) {
dev_err(&intf->dev, "failed to bind i2c device to %s driver\n", type);
ret = -ENODEV;
goto err;
}

View File

@ -541,7 +541,9 @@ static int dvbsky_mygica_t230c_attach(struct dvb_usb_adapter *adap)
si2168_config.i2c_adapter = &i2c_adapter;
si2168_config.fe = &adap->fe[0];
si2168_config.ts_mode = SI2168_TS_PARALLEL;
if (le16_to_cpu(d->udev->descriptor.idProduct) == USB_PID_MYGICA_T230C2)
if (le16_to_cpu(d->udev->descriptor.idProduct) == USB_PID_MYGICA_T230C2 ||
le16_to_cpu(d->udev->descriptor.idProduct) == USB_PID_MYGICA_T230C2_LITE ||
le16_to_cpu(d->udev->descriptor.idProduct) == USB_PID_MYGICA_T230A)
si2168_config.ts_mode |= SI2168_TS_CLK_MANUAL;
si2168_config.ts_clock_inv = 1;
@ -577,15 +579,24 @@ static int dvbsky_mygica_t230c_attach(struct dvb_usb_adapter *adap)
static int dvbsky_identify_state(struct dvb_usb_device *d, const char **name)
{
dvbsky_gpio_ctrl(d, 0x04, 1);
msleep(20);
dvbsky_gpio_ctrl(d, 0x83, 0);
dvbsky_gpio_ctrl(d, 0xc0, 1);
msleep(100);
dvbsky_gpio_ctrl(d, 0x83, 1);
dvbsky_gpio_ctrl(d, 0xc0, 0);
msleep(50);
if (le16_to_cpu(d->udev->descriptor.idProduct) == USB_PID_MYGICA_T230A) {
dvbsky_gpio_ctrl(d, 0x87, 0);
msleep(20);
dvbsky_gpio_ctrl(d, 0x86, 1);
dvbsky_gpio_ctrl(d, 0x80, 0);
msleep(100);
dvbsky_gpio_ctrl(d, 0x80, 1);
msleep(50);
} else {
dvbsky_gpio_ctrl(d, 0x04, 1);
msleep(20);
dvbsky_gpio_ctrl(d, 0x83, 0);
dvbsky_gpio_ctrl(d, 0xc0, 1);
msleep(100);
dvbsky_gpio_ctrl(d, 0x83, 1);
dvbsky_gpio_ctrl(d, 0xc0, 0);
msleep(50);
}
return WARM;
}
@ -789,6 +800,12 @@ static const struct usb_device_id dvbsky_id_table[] = {
{ DVB_USB_DEVICE(USB_VID_CONEXANT, USB_PID_MYGICA_T230C2,
&mygica_t230c_props, "MyGica Mini DVB-(T/T2/C) USB Stick T230C v2",
RC_MAP_TOTAL_MEDIA_IN_HAND_02) },
{ DVB_USB_DEVICE(USB_VID_CONEXANT, USB_PID_MYGICA_T230C2_LITE,
&mygica_t230c_props, "MyGica Mini DVB-(T/T2/C) USB Stick T230C v2 Lite",
NULL) },
{ DVB_USB_DEVICE(USB_VID_CONEXANT, USB_PID_MYGICA_T230A,
&mygica_t230c_props, "MyGica Mini DVB-(T/T2/C) USB Stick T230A",
NULL) },
{ }
};
MODULE_DEVICE_TABLE(usb, dvbsky_id_table);

View File

@ -17,7 +17,8 @@ int dvb_usb_i2c_init(struct dvb_usb_device *d)
if (d->props.i2c_algo == NULL) {
err("no i2c algorithm specified");
return -EINVAL;
ret = -EINVAL;
goto err;
}
strscpy(d->i2c_adap.name, d->desc->name, sizeof(d->i2c_adap.name));
@ -27,11 +28,15 @@ int dvb_usb_i2c_init(struct dvb_usb_device *d)
i2c_set_adapdata(&d->i2c_adap, d);
if ((ret = i2c_add_adapter(&d->i2c_adap)) < 0)
ret = i2c_add_adapter(&d->i2c_adap);
if (ret < 0) {
err("could not add i2c adapter");
goto err;
}
d->state |= DVB_USB_STATE_I2C;
err:
return ret;
}

View File

@ -194,8 +194,8 @@ static int dvb_usb_init(struct dvb_usb_device *d, short *adapter_nums)
err_adapter_init:
dvb_usb_adapter_exit(d);
err_i2c_init:
dvb_usb_i2c_exit(d);
err_i2c_init:
if (d->priv && d->props.priv_destroy)
d->props.priv_destroy(d);
err_priv_init:

View File

@ -130,7 +130,7 @@ ret:
static int nova_t_read_mac_address (struct dvb_usb_device *d, u8 mac[6])
{
int i;
int i, ret;
u8 b;
mac[0] = 0x00;
@ -139,7 +139,9 @@ static int nova_t_read_mac_address (struct dvb_usb_device *d, u8 mac[6])
/* this is a complete guess, but works for my box */
for (i = 136; i < 139; i++) {
dibusb_read_eeprom_byte(d,i, &b);
ret = dibusb_read_eeprom_byte(d, i, &b);
if (ret)
return ret;
mac[5 - (i - 136)] = b;
}

View File

@ -291,16 +291,22 @@ static int vp702x_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
static int vp702x_read_mac_addr(struct dvb_usb_device *d,u8 mac[6])
{
u8 i, *buf;
int ret;
struct vp702x_device_state *st = d->priv;
mutex_lock(&st->buf_mutex);
buf = st->buf;
for (i = 6; i < 12; i++)
vp702x_usb_in_op(d, READ_EEPROM_REQ, i, 1, &buf[i - 6], 1);
for (i = 6; i < 12; i++) {
ret = vp702x_usb_in_op(d, READ_EEPROM_REQ, i, 1,
&buf[i - 6], 1);
if (ret < 0)
goto err;
}
memcpy(mac, buf, 6);
err:
mutex_unlock(&st->buf_mutex);
return 0;
return ret;
}
static int vp702x_frontend_attach(struct dvb_usb_adapter *adap)

View File

@ -842,7 +842,6 @@ error:
kfree(ir);
ref_put:
em28xx_shutdown_buttons(dev);
kref_put(&dev->ref, em28xx_free_device);
return err;
}

View File

@ -691,49 +691,23 @@ struct go7007 *go7007_alloc(const struct go7007_board_info *board,
struct device *dev)
{
struct go7007 *go;
int i;
go = kzalloc(sizeof(struct go7007), GFP_KERNEL);
if (go == NULL)
return NULL;
go->dev = dev;
go->board_info = board;
go->board_id = 0;
go->tuner_type = -1;
go->channel_number = 0;
go->name[0] = 0;
mutex_init(&go->hw_lock);
init_waitqueue_head(&go->frame_waitq);
spin_lock_init(&go->spinlock);
go->status = STATUS_INIT;
memset(&go->i2c_adapter, 0, sizeof(go->i2c_adapter));
go->i2c_adapter_online = 0;
go->interrupt_available = 0;
init_waitqueue_head(&go->interrupt_waitq);
go->input = 0;
go7007_update_board(go);
go->encoder_h_halve = 0;
go->encoder_v_halve = 0;
go->encoder_subsample = 0;
go->format = V4L2_PIX_FMT_MJPEG;
go->bitrate = 1500000;
go->fps_scale = 1;
go->pali = 0;
go->aspect_ratio = GO7007_RATIO_1_1;
go->gop_size = 0;
go->ipb = 0;
go->closed_gop = 0;
go->repeat_seqhead = 0;
go->seq_header_enable = 0;
go->gop_header_enable = 0;
go->dvd_mode = 0;
go->interlace_coding = 0;
for (i = 0; i < 4; ++i)
go->modet[i].enable = 0;
for (i = 0; i < 1624; ++i)
go->modet_map[i] = 0;
go->audio_deliver = NULL;
go->audio_enabled = 0;
return go;
}

View File

@ -1134,7 +1134,7 @@ static int go7007_usb_probe(struct usb_interface *intf,
ep = usb->usbdev->ep_in[4];
if (!ep)
return -ENODEV;
goto allocfail;
/* Allocate the URB and buffer for receiving incoming interrupts */
usb->intr_urb = usb_alloc_urb(0, GFP_KERNEL);

View File

@ -4,7 +4,6 @@ menuconfig USB_GSPCA
depends on VIDEO_V4L2
depends on INPUT || INPUT=n
select VIDEOBUF2_VMALLOC
default m
help
Say Y here if you want to enable selecting webcams based
on the GSPCA framework.

View File

@ -1796,7 +1796,7 @@ static const u8 ov7660_60HZ[][4] = {
{}
};
static const u8 ov7660_NoFliker[][4] = {
static const u8 ov7660_NoFlicker[][4] = {
{0x00, 0x13, 0x87, 0xaa},
{}
};
@ -3319,8 +3319,8 @@ static void sethvflip(struct gspca_dev *gspca_dev, bool hflip, bool vflip)
static void setlightfreq(struct gspca_dev *gspca_dev, s32 val)
{
struct sd *sd = (struct sd *) gspca_dev;
static const u8 (*ov7660_freq_tb[3])[4] =
{ov7660_NoFliker, ov7660_50HZ, ov7660_60HZ};
static const u8 (*ov7660_freq_tb[3])[4] = {
ov7660_NoFlicker, ov7660_50HZ, ov7660_60HZ};
if (sd->sensor != SENSOR_OV7660)
return;

View File

@ -323,7 +323,7 @@ static const struct usb_action adcm2700_60HZ[] = {
{0xaa, 0x28, 0x0002}, /* 00,28,02,aa */
{}
};
static const struct usb_action adcm2700_NoFliker[] = {
static const struct usb_action adcm2700_NoFlicker[] = {
{0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,01,cc */
{0xaa, 0xfe, 0x0002}, /* 00,fe,02,aa */
{0xa0, 0x0a, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,0a,cc */
@ -525,7 +525,7 @@ static const struct usb_action cs2102_60HZ[] = {
{0xa0, 0xff, ZC3XX_R020_HSYNC_3},
{}
};
static const struct usb_action cs2102_NoFlikerScale[] = {
static const struct usb_action cs2102_NoFlickerScale[] = {
{0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
{0xaa, 0x23, 0x0001},
{0xaa, 0x24, 0x005f},
@ -547,7 +547,7 @@ static const struct usb_action cs2102_NoFlikerScale[] = {
{0xa0, 0xff, ZC3XX_R020_HSYNC_3},
{}
};
static const struct usb_action cs2102_NoFliker[] = {
static const struct usb_action cs2102_NoFlicker[] = {
{0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
{0xaa, 0x23, 0x0000},
{0xaa, 0x24, 0x00af},
@ -1385,7 +1385,7 @@ static const struct usb_action gc0305_60HZ[] = {
{}
};
static const struct usb_action gc0305_NoFliker[] = {
static const struct usb_action gc0305_NoFlicker[] = {
{0xa0, 0x0c, ZC3XX_R100_OPERATIONMODE}, /* 01,00,0c,cc */
{0xaa, 0x82, 0x0000}, /* 00,82,00,aa */
{0xaa, 0x83, 0x0000}, /* 00,83,00,aa */
@ -1710,7 +1710,7 @@ static const struct usb_action hdcs2020_60HZ[] = {
{0xa0, 0x2c, ZC3XX_R01F_HSYNC_2}, /* 00,1f,2c,cc */
{}
};
static const struct usb_action hdcs2020_NoFliker[] = {
static const struct usb_action hdcs2020_NoFlicker[] = {
{0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
{0xaa, 0x13, 0x0010}, /* 00,13,10,aa */
{0xaa, 0x14, 0x0001}, /* 00,14,01,aa */
@ -1925,7 +1925,7 @@ static const struct usb_action hv7131b_60HZScale[] = { /* 320x240 */
{0xa0, 0x40, ZC3XX_R020_HSYNC_3}, /* 00,20,40,cc */
{}
};
static const struct usb_action hv7131b_NoFliker[] = { /* 640x480*/
static const struct usb_action hv7131b_NoFlicker[] = { /* 640x480*/
{0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
{0xaa, 0x25, 0x0003}, /* 00,25,03,aa */
{0xaa, 0x26, 0x0000}, /* 00,26,00,aa */
@ -1950,7 +1950,7 @@ static const struct usb_action hv7131b_NoFliker[] = { /* 640x480*/
{0xa0, 0x03, ZC3XX_R020_HSYNC_3}, /* 00,20,03,cc */
{}
};
static const struct usb_action hv7131b_NoFlikerScale[] = { /* 320x240 */
static const struct usb_action hv7131b_NoFlickerScale[] = { /* 320x240 */
{0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
{0xaa, 0x25, 0x0003}, /* 00,25,03,aa */
{0xaa, 0x26, 0x0000}, /* 00,26,00,aa */
@ -2141,7 +2141,7 @@ static const struct usb_action hv7131r_60HZScale[] = {
{0xa0, 0x08, ZC3XX_R020_HSYNC_3},
{}
};
static const struct usb_action hv7131r_NoFliker[] = {
static const struct usb_action hv7131r_NoFlicker[] = {
{0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
{0xa0, 0x2f, ZC3XX_R190_EXPOSURELIMITHIGH},
{0xa0, 0xf8, ZC3XX_R191_EXPOSURELIMITMID},
@ -2159,7 +2159,7 @@ static const struct usb_action hv7131r_NoFliker[] = {
{0xa0, 0x08, ZC3XX_R020_HSYNC_3},
{}
};
static const struct usb_action hv7131r_NoFlikerScale[] = {
static const struct usb_action hv7131r_NoFlickerScale[] = {
{0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
{0xa0, 0x2f, ZC3XX_R190_EXPOSURELIMITHIGH},
{0xa0, 0xf8, ZC3XX_R191_EXPOSURELIMITMID},
@ -2662,7 +2662,7 @@ static const struct usb_action icm105a_60HZ[] = {
{0xa0, 0xc0, ZC3XX_R1A8_DIGITALGAIN}, /* 01,a8,c0,cc */
{}
};
static const struct usb_action icm105a_NoFlikerScale[] = {
static const struct usb_action icm105a_NoFlickerScale[] = {
{0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
{0xaa, 0x0d, 0x0003}, /* 00,0d,03,aa */
{0xaa, 0x0c, 0x0004}, /* 00,0c,04,aa */
@ -2693,7 +2693,7 @@ static const struct usb_action icm105a_NoFlikerScale[] = {
{0xa0, 0xff, ZC3XX_R020_HSYNC_3}, /* 00,20,ff,cc */
{}
};
static const struct usb_action icm105a_NoFliker[] = {
static const struct usb_action icm105a_NoFlicker[] = {
{0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
{0xaa, 0x0d, 0x0003}, /* 00,0d,03,aa */
{0xaa, 0x0c, 0x0004}, /* 00,0c,04,aa */
@ -3009,7 +3009,7 @@ static const struct usb_action mc501cb_60HZScale[] = {
{}
};
static const struct usb_action mc501cb_NoFliker[] = {
static const struct usb_action mc501cb_NoFlicker[] = {
{0xaa, 0x03, 0x0003}, /* 00,03,03,aa */
{0xaa, 0x10, 0x00fc}, /* 00,10,fc,aa */
{0xaa, 0x36, 0x0018}, /* 00,36,18,aa */
@ -3021,7 +3021,7 @@ static const struct usb_action mc501cb_NoFliker[] = {
{}
};
static const struct usb_action mc501cb_NoFlikerScale[] = {
static const struct usb_action mc501cb_NoFlickerScale[] = {
{0xaa, 0x03, 0x0003}, /* 00,03,03,aa */
{0xaa, 0x10, 0x00fc}, /* 00,10,fc,aa */
{0xaa, 0x36, 0x0030}, /* 00,36,30,aa */
@ -3211,7 +3211,7 @@ static const struct usb_action ov7620_60HZ[] = {
{0xa1, 0x01, 0x0037}, */
{}
};
static const struct usb_action ov7620_NoFliker[] = {
static const struct usb_action ov7620_NoFlicker[] = {
{0xdd, 0x00, 0x0100}, /* 00,01,00,dd */
{0xaa, 0x2b, 0x0000}, /* 00,2b,00,aa */
/* disable 1/120s & 1/100s exposures for banding filter */
@ -3827,7 +3827,7 @@ static const struct usb_action pas106b_60HZ[] = {
{0xa0, 0x04, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,04,cc */
{}
};
static const struct usb_action pas106b_NoFliker[] = {
static const struct usb_action pas106b_NoFlicker[] = {
{0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */
{0xa0, 0x06, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,06,cc */
{0xa0, 0x50, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,50,cc */
@ -4051,7 +4051,7 @@ static const struct usb_action pas202b_60HZScale[] = {
{0xa0, 0x0e, ZC3XX_R088_EXPTIMELOW}, /* 00,88,0e,cc */
{}
};
static const struct usb_action pas202b_NoFliker[] = {
static const struct usb_action pas202b_NoFlicker[] = {
{0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
{0xa0, 0x20, ZC3XX_R087_EXPTIMEMID}, /* 00,87,20,cc */
{0xa0, 0x21, ZC3XX_R088_EXPTIMELOW}, /* 00,88,21,cc */
@ -4080,7 +4080,7 @@ static const struct usb_action pas202b_NoFliker[] = {
{0xa0, 0x0e, ZC3XX_R088_EXPTIMELOW}, /* 00,88,0e,cc */
{}
};
static const struct usb_action pas202b_NoFlikerScale[] = {
static const struct usb_action pas202b_NoFlickerScale[] = {
{0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
{0xa0, 0x20, ZC3XX_R087_EXPTIMEMID}, /* 00,87,20,cc */
{0xa0, 0x21, ZC3XX_R088_EXPTIMELOW}, /* 00,88,21,cc */
@ -4309,7 +4309,7 @@ static const struct usb_action mt9v111_1_AE60HZScale[] = {
{0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
{}
};
static const struct usb_action mt9v111_1_AENoFliker[] = {
static const struct usb_action mt9v111_1_AENoFlicker[] = {
{0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE},
{0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
{0xbb, 0x00, 0x0509},
@ -4332,7 +4332,7 @@ static const struct usb_action mt9v111_1_AENoFliker[] = {
{0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
{}
};
static const struct usb_action mt9v111_1_AENoFlikerScale[] = {
static const struct usb_action mt9v111_1_AENoFlickerScale[] = {
{0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE},
{0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
{0xbb, 0x00, 0x0534},
@ -4554,7 +4554,7 @@ static const struct usb_action mt9v111_3_AE60HZScale[] = {
{0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
{}
};
static const struct usb_action mt9v111_3_AENoFliker[] = {
static const struct usb_action mt9v111_3_AENoFlicker[] = {
{0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE},
{0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
{0xaa, 0x05, 0x0034},
@ -4577,7 +4577,7 @@ static const struct usb_action mt9v111_3_AENoFliker[] = {
{0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
{}
};
static const struct usb_action mt9v111_3_AENoFlikerScale[] = {
static const struct usb_action mt9v111_3_AENoFlickerScale[] = {
{0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE},
{0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
{0xaa, 0x05, 0x0034},
@ -4787,7 +4787,7 @@ static const struct usb_action pb0330_60HZScale[] = {
{0xa0, 0xd0, ZC3XX_R020_HSYNC_3},
{}
};
static const struct usb_action pb0330_NoFliker[] = {
static const struct usb_action pb0330_NoFlicker[] = {
{0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
{0xbb, 0x00, 0x0509},
{0xbb, 0x02, 0x0940},
@ -4809,7 +4809,7 @@ static const struct usb_action pb0330_NoFliker[] = {
{0xa0, 0xe0, ZC3XX_R020_HSYNC_3},
{}
};
static const struct usb_action pb0330_NoFlikerScale[] = {
static const struct usb_action pb0330_NoFlickerScale[] = {
{0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
{0xbb, 0x00, 0x0535},
{0xbb, 0x01, 0x0980},
@ -5031,7 +5031,7 @@ static const struct usb_action po2030_60HZ[] = {
{}
};
static const struct usb_action po2030_NoFliker[] = {
static const struct usb_action po2030_NoFlicker[] = {
{0xa0, 0x02, ZC3XX_R180_AUTOCORRECTENABLE}, /* 01,80,02,cc */
{0xaa, 0x8d, 0x000d}, /* 00,8d,0d,aa */
{0xaa, 0x1a, 0x0000}, /* 00,1a,00,aa */
@ -5215,7 +5215,7 @@ static const struct usb_action tas5130c_60HZScale[] = {
{0xa0, 0x50, ZC3XX_R11D_GLOBALGAIN},
{}
};
static const struct usb_action tas5130c_NoFliker[] = {
static const struct usb_action tas5130c_NoFlicker[] = {
{0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
{0xaa, 0xa3, 0x0001}, /* 00,a3,01,aa */
{0xaa, 0xa4, 0x0040}, /* 00,a4,40,aa */
@ -5241,7 +5241,7 @@ static const struct usb_action tas5130c_NoFliker[] = {
{}
};
static const struct usb_action tas5130c_NoFlikerScale[] = {
static const struct usb_action tas5130c_NoFlickerScale[] = {
{0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
{0xaa, 0xa3, 0x0001}, /* 00,a3,01,aa */
{0xaa, 0xa4, 0x0090}, /* 00,a4,90,aa */
@ -5482,7 +5482,7 @@ static const struct usb_action gc0303_60HZScale[] = {
{}
};
static const struct usb_action gc0303_NoFliker[] = {
static const struct usb_action gc0303_NoFlicker[] = {
{0xa0, 0x0c, ZC3XX_R100_OPERATIONMODE}, /* 01,00,0c,cc, */
{0xaa, 0x82, 0x0000}, /* 00,82,00,aa */
{0xaa, 0x83, 0x0000}, /* 00,83,00,aa */
@ -5504,7 +5504,7 @@ static const struct usb_action gc0303_NoFliker[] = {
{}
};
static const struct usb_action gc0303_NoFlikerScale[] = {
static const struct usb_action gc0303_NoFlickerScale[] = {
{0xa0, 0x0c, ZC3XX_R100_OPERATIONMODE}, /* 01,00,0c,cc, */
{0xaa, 0x82, 0x0000}, /* 00,82,00,aa */
{0xaa, 0x83, 0x0000}, /* 00,83,00,aa */
@ -5806,7 +5806,7 @@ static void setquality(struct gspca_dev *gspca_dev)
* Valid frequencies are:
* 50Hz, for European and Asian lighting (default)
* 60Hz, for American lighting
* 0 = No Fliker (for outdoore usage)
* 0 = No Flicker (for outdoor usage)
*/
static void setlightfreq(struct gspca_dev *gspca_dev, s32 val)
{
@ -5814,80 +5814,80 @@ static void setlightfreq(struct gspca_dev *gspca_dev, s32 val)
int i, mode;
const struct usb_action *zc3_freq;
static const struct usb_action *freq_tb[SENSOR_MAX][6] = {
[SENSOR_ADCM2700] =
{adcm2700_NoFliker, adcm2700_NoFliker,
[SENSOR_ADCM2700] = {
adcm2700_NoFlicker, adcm2700_NoFlicker,
adcm2700_50HZ, adcm2700_50HZ,
adcm2700_60HZ, adcm2700_60HZ},
[SENSOR_CS2102] =
{cs2102_NoFliker, cs2102_NoFlikerScale,
[SENSOR_CS2102] = {
cs2102_NoFlicker, cs2102_NoFlickerScale,
cs2102_50HZ, cs2102_50HZScale,
cs2102_60HZ, cs2102_60HZScale},
[SENSOR_CS2102K] =
{cs2102_NoFliker, cs2102_NoFlikerScale,
[SENSOR_CS2102K] = {
cs2102_NoFlicker, cs2102_NoFlickerScale,
NULL, NULL, /* currently disabled */
NULL, NULL},
[SENSOR_GC0303] =
{gc0303_NoFliker, gc0303_NoFlikerScale,
[SENSOR_GC0303] = {
gc0303_NoFlicker, gc0303_NoFlickerScale,
gc0303_50HZ, gc0303_50HZScale,
gc0303_60HZ, gc0303_60HZScale},
[SENSOR_GC0305] =
{gc0305_NoFliker, gc0305_NoFliker,
[SENSOR_GC0305] = {
gc0305_NoFlicker, gc0305_NoFlicker,
gc0305_50HZ, gc0305_50HZ,
gc0305_60HZ, gc0305_60HZ},
[SENSOR_HDCS2020] =
{hdcs2020_NoFliker, hdcs2020_NoFliker,
[SENSOR_HDCS2020] = {
hdcs2020_NoFlicker, hdcs2020_NoFlicker,
hdcs2020_50HZ, hdcs2020_50HZ,
hdcs2020_60HZ, hdcs2020_60HZ},
[SENSOR_HV7131B] =
{hv7131b_NoFliker, hv7131b_NoFlikerScale,
[SENSOR_HV7131B] = {
hv7131b_NoFlicker, hv7131b_NoFlickerScale,
hv7131b_50HZ, hv7131b_50HZScale,
hv7131b_60HZ, hv7131b_60HZScale},
[SENSOR_HV7131R] =
{hv7131r_NoFliker, hv7131r_NoFlikerScale,
[SENSOR_HV7131R] = {
hv7131r_NoFlicker, hv7131r_NoFlickerScale,
hv7131r_50HZ, hv7131r_50HZScale,
hv7131r_60HZ, hv7131r_60HZScale},
[SENSOR_ICM105A] =
{icm105a_NoFliker, icm105a_NoFlikerScale,
[SENSOR_ICM105A] = {
icm105a_NoFlicker, icm105a_NoFlickerScale,
icm105a_50HZ, icm105a_50HZScale,
icm105a_60HZ, icm105a_60HZScale},
[SENSOR_MC501CB] =
{mc501cb_NoFliker, mc501cb_NoFlikerScale,
[SENSOR_MC501CB] = {
mc501cb_NoFlicker, mc501cb_NoFlickerScale,
mc501cb_50HZ, mc501cb_50HZScale,
mc501cb_60HZ, mc501cb_60HZScale},
[SENSOR_MT9V111_1] =
{mt9v111_1_AENoFliker, mt9v111_1_AENoFlikerScale,
[SENSOR_MT9V111_1] = {
mt9v111_1_AENoFlicker, mt9v111_1_AENoFlickerScale,
mt9v111_1_AE50HZ, mt9v111_1_AE50HZScale,
mt9v111_1_AE60HZ, mt9v111_1_AE60HZScale},
[SENSOR_MT9V111_3] =
{mt9v111_3_AENoFliker, mt9v111_3_AENoFlikerScale,
[SENSOR_MT9V111_3] = {
mt9v111_3_AENoFlicker, mt9v111_3_AENoFlickerScale,
mt9v111_3_AE50HZ, mt9v111_3_AE50HZScale,
mt9v111_3_AE60HZ, mt9v111_3_AE60HZScale},
[SENSOR_OV7620] =
{ov7620_NoFliker, ov7620_NoFliker,
[SENSOR_OV7620] = {
ov7620_NoFlicker, ov7620_NoFlicker,
ov7620_50HZ, ov7620_50HZ,
ov7620_60HZ, ov7620_60HZ},
[SENSOR_OV7630C] =
{NULL, NULL,
[SENSOR_OV7630C] = {
NULL, NULL,
NULL, NULL,
NULL, NULL},
[SENSOR_PAS106] =
{pas106b_NoFliker, pas106b_NoFliker,
[SENSOR_PAS106] = {
pas106b_NoFlicker, pas106b_NoFlicker,
pas106b_50HZ, pas106b_50HZ,
pas106b_60HZ, pas106b_60HZ},
[SENSOR_PAS202B] =
{pas202b_NoFliker, pas202b_NoFlikerScale,
[SENSOR_PAS202B] = {
pas202b_NoFlicker, pas202b_NoFlickerScale,
pas202b_50HZ, pas202b_50HZScale,
pas202b_60HZ, pas202b_60HZScale},
[SENSOR_PB0330] =
{pb0330_NoFliker, pb0330_NoFlikerScale,
[SENSOR_PB0330] = {
pb0330_NoFlicker, pb0330_NoFlickerScale,
pb0330_50HZ, pb0330_50HZScale,
pb0330_60HZ, pb0330_60HZScale},
[SENSOR_PO2030] =
{po2030_NoFliker, po2030_NoFliker,
[SENSOR_PO2030] = {
po2030_NoFlicker, po2030_NoFlicker,
po2030_50HZ, po2030_50HZ,
po2030_60HZ, po2030_60HZ},
[SENSOR_TAS5130C] =
{tas5130c_NoFliker, tas5130c_NoFlikerScale,
[SENSOR_TAS5130C] = {
tas5130c_NoFlicker, tas5130c_NoFlickerScale,
tas5130c_50HZ, tas5130c_50HZScale,
tas5130c_60HZ, tas5130c_60HZScale},
};

View File

@ -1346,7 +1346,7 @@ static int stk_camera_probe(struct usb_interface *interface,
if (!dev->isoc_ep) {
pr_err("Could not find isoc-in endpoint\n");
err = -ENODEV;
goto error;
goto error_put;
}
dev->vsettings.palette = V4L2_PIX_FMT_RGB565;
dev->vsettings.mode = MODE_VGA;
@ -1359,10 +1359,12 @@ static int stk_camera_probe(struct usb_interface *interface,
err = stk_register_video_device(dev);
if (err)
goto error;
goto error_put;
return 0;
error_put:
usb_put_intf(interface);
error:
v4l2_ctrl_handler_free(hdl);
v4l2_device_unregister(&dev->v4l2_dev);

View File

@ -899,8 +899,8 @@ static int uvc_ioctl_g_input(struct file *file, void *fh, unsigned int *input)
{
struct uvc_fh *handle = fh;
struct uvc_video_chain *chain = handle->chain;
u8 *buf;
int ret;
u8 i;
if (chain->selector == NULL ||
(chain->dev->quirks & UVC_QUIRK_IGNORE_SELECTOR_UNIT)) {
@ -908,22 +908,27 @@ static int uvc_ioctl_g_input(struct file *file, void *fh, unsigned int *input)
return 0;
}
buf = kmalloc(1, GFP_KERNEL);
if (!buf)
return -ENOMEM;
ret = uvc_query_ctrl(chain->dev, UVC_GET_CUR, chain->selector->id,
chain->dev->intfnum, UVC_SU_INPUT_SELECT_CONTROL,
&i, 1);
if (ret < 0)
return ret;
buf, 1);
if (!ret)
*input = *buf - 1;
*input = i - 1;
return 0;
kfree(buf);
return ret;
}
static int uvc_ioctl_s_input(struct file *file, void *fh, unsigned int input)
{
struct uvc_fh *handle = fh;
struct uvc_video_chain *chain = handle->chain;
u8 *buf;
int ret;
u32 i;
ret = uvc_acquire_privileges(handle);
if (ret < 0)
@ -939,10 +944,17 @@ static int uvc_ioctl_s_input(struct file *file, void *fh, unsigned int input)
if (input >= chain->selector->bNrInPins)
return -EINVAL;
i = input + 1;
return uvc_query_ctrl(chain->dev, UVC_SET_CUR, chain->selector->id,
chain->dev->intfnum, UVC_SU_INPUT_SELECT_CONTROL,
&i, 1);
buf = kmalloc(1, GFP_KERNEL);
if (!buf)
return -ENOMEM;
*buf = input + 1;
ret = uvc_query_ctrl(chain->dev, UVC_SET_CUR, chain->selector->id,
chain->dev->intfnum, UVC_SU_INPUT_SELECT_CONTROL,
buf, 1);
kfree(buf);
return ret;
}
static int uvc_ioctl_queryctrl(struct file *file, void *fh,

View File

@ -833,6 +833,7 @@ const char *v4l2_ctrl_get_name(u32 id)
case V4L2_CID_MPEG_VIDEO_DECODER_SLICE_INTERFACE: return "Decoder Slice Interface";
case V4L2_CID_MPEG_VIDEO_DECODER_MPEG4_DEBLOCK_FILTER: return "MPEG4 Loop Filter Enable";
case V4L2_CID_MPEG_VIDEO_CYCLIC_INTRA_REFRESH_MB: return "Number of Intra Refresh MBs";
case V4L2_CID_MPEG_VIDEO_INTRA_REFRESH_PERIOD: return "Intra Refresh Period";
case V4L2_CID_MPEG_VIDEO_FRAME_RC_ENABLE: return "Frame Level Rate Control Enable";
case V4L2_CID_MPEG_VIDEO_MB_RC_ENABLE: return "H264 MB Level Rate Control";
case V4L2_CID_MPEG_VIDEO_HEADER_MODE: return "Sequence Header Mode";
@ -1258,6 +1259,7 @@ void v4l2_ctrl_fill(u32 id, const char **name, enum v4l2_ctrl_type *type,
case V4L2_CID_MPEG_VIDEO_MV_H_SEARCH_RANGE:
case V4L2_CID_MPEG_VIDEO_MV_V_SEARCH_RANGE:
case V4L2_CID_MPEG_VIDEO_DEC_DISPLAY_DELAY:
case V4L2_CID_MPEG_VIDEO_INTRA_REFRESH_PERIOD:
*type = V4L2_CTRL_TYPE_INTEGER;
break;
case V4L2_CID_MPEG_VIDEO_LTR_COUNT:

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