diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2025-10-02 13:13:26 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2025-10-02 13:13:26 -0700 |
commit | f79e772258df311c2cb21594ca0996318e720d28 (patch) | |
tree | 0d9335cddd34f5ce101600183175d45e97ca791c | |
parent | 58809f614e0e3f4e12b489bddf680bfeb31c0a20 (diff) | |
parent | afb100a5ea7a13d7e6937dcd3b36b19dc6cc9328 (diff) |
Merge tag 'media/v6.18-1' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media
Pull media updates from Mauro Carvalho Chehab:
- Added a new V4L2 clock helper
- New camera sensor drivers
- iris: Enable H.264/H.265 encoder support and fixes in iris driver
common code
- camss: add support for new SoC flavors
- venus: add new SoC support
- tc358743: support more infoframe types
- Various fixes, driver improvements and cleanups
* tag 'media/v6.18-1' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media: (439 commits)
media: venus: pm_helpers: add fallback for the opp-table
media: qcom: camss: vfe: Fix BPL alignment for QCM2290
media: tuner: xc5000: Fix use-after-free in xc5000_release
media: i2c: tc358743: Fix use-after-free bugs caused by orphan timer in probe
media: b2c2: Fix use-after-free causing by irq_check_work in flexcop_pci_remove
media: vsp1: Export missing vsp1_isp_free_buffer symbol
media: renesas: vsp1: Convert to SYSTEM_SLEEP/RUNTIME_PM_OPS()
media: renesas: ceu: Convert to RUNTIME_PM_OPS()
media: renesas: fdp1: Convert to RUNTIME_PM_OPS()
media: renesas: rcar-vin: Convert to DEFINE_SIMPLE_DEV_PM_OPS()
media: renesas: rcar_drif: Convert to DEFINE_SIMPLE_DEV_PM_OPS()
media: uvcvideo: Mark invalid entities with id UVC_INVALID_ENTITY_ID
media: uvcvideo: Support UVC_CROSXU_CONTROL_IQ_PROFILE
media: uvcvideo: Run uvc_ctrl_init_ctrl for all controls
media: uvcvideo: Shorten the transfer size non compliance message
media: uvcvideo: Do not re-reference dev->udev
media: uvcvideo: Use intf instead of udev for printks
media: uvcvideo: Move video_device under video_queue
media: uvcvideo: Drop stream->mutex
media: uvcvideo: Move MSXU_CONTROL_METADATA definition to header
...
576 files changed, 16905 insertions, 9289 deletions
@@ -216,7 +216,8 @@ Dengcheng Zhu <dzhu@wavecomp.com> <dengcheng.zhu@gmail.com> Dengcheng Zhu <dzhu@wavecomp.com> <dengcheng.zhu@imgtec.com> Dengcheng Zhu <dzhu@wavecomp.com> <dengcheng.zhu@mips.com> <dev.kurt@vandijck-laurijssen.be> <kurt.van.dijck@eia.be> -Dikshita Agarwal <quic_dikshita@quicinc.com> <dikshita@codeaurora.org> +Dikshita Agarwal <dikshita.agarwal@oss.qualcomm.com> <dikshita@codeaurora.org> +Dikshita Agarwal <dikshita.agarwal@oss.qualcomm.com> <quic_dikshita@quicinc.com> Dmitry Baryshkov <lumag@kernel.org> <dbaryshkov@gmail.com> Dmitry Baryshkov <lumag@kernel.org> <[dbaryshkov@gmail.com]> Dmitry Baryshkov <lumag@kernel.org> <dmitry_baryshkov@mentor.com> @@ -819,7 +820,8 @@ Valentin Schneider <vschneid@redhat.com> <valentin.schneider@arm.com> Veera Sundaram Sankaran <quic_veeras@quicinc.com> <veeras@codeaurora.org> Veerabhadrarao Badiganti <quic_vbadigan@quicinc.com> <vbadigan@codeaurora.org> Venkateswara Naralasetty <quic_vnaralas@quicinc.com> <vnaralas@codeaurora.org> -Vikash Garodia <quic_vgarodia@quicinc.com> <vgarodia@codeaurora.org> +Vikash Garodia <vikash.garodia@oss.qualcomm.com> <vgarodia@codeaurora.org> +Vikash Garodia <vikash.garodia@oss.qualcomm.com> <quic_vgarodia@quicinc.com> Vinod Koul <vkoul@kernel.org> <vinod.koul@intel.com> Vinod Koul <vkoul@kernel.org> <vinod.koul@linux.intel.com> Vinod Koul <vkoul@kernel.org> <vkoul@infradead.org> diff --git a/Documentation/ABI/testing/debugfs-cec-error-inj b/Documentation/ABI/testing/debugfs-cec-error-inj index 8debcb08a3b5..c512f71bba8e 100644 --- a/Documentation/ABI/testing/debugfs-cec-error-inj +++ b/Documentation/ABI/testing/debugfs-cec-error-inj @@ -1,6 +1,6 @@ What: /sys/kernel/debug/cec/*/error-inj Date: March 2018 -Contact: Hans Verkuil <hverkuil-cisco@xs4all.nl> +Contact: Hans Verkuil <hverkuil@kernel.org> Description: The CEC Framework allows for CEC error injection commands through diff --git a/Documentation/admin-guide/bug-hunting.rst b/Documentation/admin-guide/bug-hunting.rst index 30858757c9f2..7da0504388ec 100644 --- a/Documentation/admin-guide/bug-hunting.rst +++ b/Documentation/admin-guide/bug-hunting.rst @@ -252,7 +252,7 @@ For example, if you find a bug at the gspca's sonixj.c file, you can get its maintainers with:: $ ./scripts/get_maintainer.pl --bug -f drivers/media/usb/gspca/sonixj.c - Hans Verkuil <hverkuil@xs4all.nl> (odd fixer:GSPCA USB WEBCAM DRIVER,commit_signer:1/1=100%) + Hans Verkuil <hverkuil@kernel.org> (odd fixer:GSPCA USB WEBCAM DRIVER,commit_signer:1/1=100%) Mauro Carvalho Chehab <mchehab@kernel.org> (maintainer:MEDIA INPUT INFRASTRUCTURE (V4L/DVB),commit_signer:1/1=100%) Tejun Heo <tj@kernel.org> (commit_signer:1/1=100%) Bhaktipriya Shridhar <bhaktipriya96@gmail.com> (commit_signer:1/1=100%,authored:1/1=100%,added_lines:4/4=100%,removed_lines:9/9=100%) diff --git a/Documentation/admin-guide/media/i2c-cardlist.rst b/Documentation/admin-guide/media/i2c-cardlist.rst index 1825a0bb47bd..fff962558cd5 100644 --- a/Documentation/admin-guide/media/i2c-cardlist.rst +++ b/Documentation/admin-guide/media/i2c-cardlist.rst @@ -91,7 +91,6 @@ ov5647 OmniVision OV5647 sensor ov5670 OmniVision OV5670 sensor ov5675 OmniVision OV5675 sensor ov5695 OmniVision OV5695 sensor -ov6650 OmniVision OV6650 sensor ov7251 OmniVision OV7251 sensor ov7640 OmniVision OV7640 sensor ov7670 OmniVision OV7670 sensor diff --git a/Documentation/admin-guide/media/ivtv.rst b/Documentation/admin-guide/media/ivtv.rst index 101f16d0263e..8b65ac3f5321 100644 --- a/Documentation/admin-guide/media/ivtv.rst +++ b/Documentation/admin-guide/media/ivtv.rst @@ -3,7 +3,7 @@ The ivtv driver =============== -Author: Hans Verkuil <hverkuil@xs4all.nl> +Author: Hans Verkuil <hverkuil@kernel.org> This is a v4l2 device driver for the Conexant cx23415/6 MPEG encoder/decoder. The cx23415 can do both encoding and decoding, the cx23416 can only do MPEG diff --git a/Documentation/devicetree/bindings/i2c/qcom,i2c-cci.yaml b/Documentation/devicetree/bindings/i2c/qcom,i2c-cci.yaml index 7456783d1f8e..9bc99d736343 100644 --- a/Documentation/devicetree/bindings/i2c/qcom,i2c-cci.yaml +++ b/Documentation/devicetree/bindings/i2c/qcom,i2c-cci.yaml @@ -312,7 +312,8 @@ examples: clocks = <&clock_camcc CAM_CC_MCLK0_CLK>; clock-names = "xvclk"; - clock-frequency = <19200000>; + assigned-clocks = <&clock_camcc CAM_CC_MCLK0_CLK>; + assigned-clock-rates = <19200000>; dovdd-supply = <&vreg_lvs1a_1p8>; avdd-supply = <&cam0_avdd_2v8>; @@ -344,7 +345,8 @@ examples: clocks = <&clock_camcc CAM_CC_MCLK3_CLK>; clock-names = "xclk"; - clock-frequency = <24000000>; + assigned-clocks = <&clock_camcc CAM_CC_MCLK3_CLK>; + assigned-clock-rates = <24000000>; vdddo-supply = <&vreg_lvs1a_1p8>; vdda-supply = <&cam3_avdd_2v8>; diff --git a/Documentation/devicetree/bindings/media/cec/cec-common.yaml b/Documentation/devicetree/bindings/media/cec/cec-common.yaml index af6ee5f1c73f..6d5017d9bf55 100644 --- a/Documentation/devicetree/bindings/media/cec/cec-common.yaml +++ b/Documentation/devicetree/bindings/media/cec/cec-common.yaml @@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml# title: HDMI CEC Adapters Common Properties maintainers: - - Hans Verkuil <hverkuil@xs4all.nl> + - Hans Verkuil <hverkuil@kernel.org> properties: $nodename: diff --git a/Documentation/devicetree/bindings/media/cec/cec-gpio.yaml b/Documentation/devicetree/bindings/media/cec/cec-gpio.yaml index 64d7ec057672..582c6c9cae48 100644 --- a/Documentation/devicetree/bindings/media/cec/cec-gpio.yaml +++ b/Documentation/devicetree/bindings/media/cec/cec-gpio.yaml @@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml# title: HDMI CEC GPIO maintainers: - - Hans Verkuil <hverkuil-cisco@xs4all.nl> + - Hans Verkuil <hverkuil@kernel.org> description: | The HDMI CEC GPIO module supports CEC implementations where the CEC line is diff --git a/Documentation/devicetree/bindings/media/cec/nvidia,tegra114-cec.yaml b/Documentation/devicetree/bindings/media/cec/nvidia,tegra114-cec.yaml index 4b46aa755ccd..6ef545b1d622 100644 --- a/Documentation/devicetree/bindings/media/cec/nvidia,tegra114-cec.yaml +++ b/Documentation/devicetree/bindings/media/cec/nvidia,tegra114-cec.yaml @@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml# title: NVIDIA Tegra HDMI CEC maintainers: - - Hans Verkuil <hverkuil-cisco@xs4all.nl> + - Hans Verkuil <hverkuil@kernel.org> allOf: - $ref: cec-common.yaml# diff --git a/Documentation/devicetree/bindings/media/i2c/adi,adv7604.yaml b/Documentation/devicetree/bindings/media/i2c/adi,adv7604.yaml index 6c403003cdda..2dc2829d42a0 100644 --- a/Documentation/devicetree/bindings/media/i2c/adi,adv7604.yaml +++ b/Documentation/devicetree/bindings/media/i2c/adi,adv7604.yaml @@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml# title: Analog Devices ADV7604/10/11/12 video decoder with HDMI receiver maintainers: - - Hans Verkuil <hverkuil-cisco@xs4all.nl> + - Hans Verkuil <hverkuil@kernel.org> description: The ADV7604 and ADV7610/11/12 are multiformat video decoders with diff --git a/Documentation/devicetree/bindings/media/i2c/mipi-ccs.yaml b/Documentation/devicetree/bindings/media/i2c/mipi-ccs.yaml index bc664a016396..217b08c8cbbd 100644 --- a/Documentation/devicetree/bindings/media/i2c/mipi-ccs.yaml +++ b/Documentation/devicetree/bindings/media/i2c/mipi-ccs.yaml @@ -55,6 +55,7 @@ properties: clock-frequency: description: Frequency of the external clock to the sensor in Hz. + deprecated: true reset-gpios: description: Reset GPIO. Also commonly called XSHUTDOWN in hardware @@ -93,7 +94,6 @@ properties: required: - compatible - reg - - clock-frequency - clocks additionalProperties: false @@ -114,8 +114,11 @@ examples: reg = <0x10>; reset-gpios = <&gpio3 20 GPIO_ACTIVE_LOW>; vana-supply = <&vaux3>; + clocks = <&omap3_isp 0>; - clock-frequency = <9600000>; + assigned-clocks = <&omap3_isp 0>; + assigned-clock-rates = <9600000>; + port { ccs_ep: endpoint { data-lanes = <1 2>; diff --git a/Documentation/devicetree/bindings/media/i2c/ovti,og0ve1b.yaml b/Documentation/devicetree/bindings/media/i2c/ovti,og0ve1b.yaml new file mode 100644 index 000000000000..bd2f1ae23e65 --- /dev/null +++ b/Documentation/devicetree/bindings/media/i2c/ovti,og0ve1b.yaml @@ -0,0 +1,97 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/media/i2c/ovti,og0ve1b.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: OmniVision OG0VE1B Image Sensor + +description: + OmniVision OG0VE1B image sensor is a low power consuming monochrome + image sensor. The sensor is controlled over a serial camera control + bus protocol (SCCB), the widest supported image size is 640x480 at + 120 frames per second rate, data output format is 8/10-bit RAW + transferred over one-lane MIPI D-PHY at up to 800 Mbps. + +maintainers: + - Vladimir Zapolskiy <vladimir.zapolskiy@linaro.org> + +allOf: + - $ref: /schemas/media/video-interface-devices.yaml# + +properties: + compatible: + const: ovti,og0ve1b + + reg: + maxItems: 1 + + clocks: + description: XVCLK supply clock, 6MHz to 27MHz frequency. + maxItems: 1 + + reset-gpios: + description: Active low GPIO connected to XSHUTDOWN pad of the sensor. + maxItems: 1 + + strobe-gpios: + description: Input GPIO connected to strobe pad of the sensor. + maxItems: 1 + + avdd-supply: + description: Analog voltage supply, 2.6 to 3.0 volts. + + dovdd-supply: + description: Digital I/O voltage supply, 1.7 to 3.0 volts. + + dvdd-supply: + description: Digital core voltage supply. + + port: + $ref: /schemas/graph.yaml#/$defs/port-base + additionalProperties: false + + properties: + endpoint: + $ref: /schemas/media/video-interfaces.yaml# + unevaluatedProperties: false + + required: + - link-frequencies + +required: + - compatible + - reg + - port + +unevaluatedProperties: false + +examples: + - | + #include <dt-bindings/gpio/gpio.h> + + i2c { + #address-cells = <1>; + #size-cells = <0>; + + camera@3e { + compatible = "ovti,og0ve1b"; + reg = <0x3e>; + clocks = <&camera_clk 0>; + assigned-clocks = <&camera_clk 0>; + assigned-clock-rates = <24000000>; + reset-gpios = <&gpio1 10 GPIO_ACTIVE_LOW>; + avdd-supply = <&vreg_2p8>; + dovdd-supply = <&vreg_1p8>; + dvdd-supply = <&vreg_1p2>; + + port { + endpoint { + link-frequencies = /bits/ 64 <500000000>; + remote-endpoint = <&mipi_csi2_ep>; + }; + }; + }; + }; + +... diff --git a/Documentation/devicetree/bindings/media/i2c/ovti,ov02a10.yaml b/Documentation/devicetree/bindings/media/i2c/ovti,ov02a10.yaml index 67c1c291327b..0e1d9c390180 100644 --- a/Documentation/devicetree/bindings/media/i2c/ovti,ov02a10.yaml +++ b/Documentation/devicetree/bindings/media/i2c/ovti,ov02a10.yaml @@ -39,6 +39,7 @@ properties: clock-frequency: description: Frequency of the eclk clock in Hz. + deprecated: true dovdd-supply: description: @@ -100,7 +101,6 @@ required: - reg - clocks - clock-names - - clock-frequency - dovdd-supply - avdd-supply - dvdd-supply @@ -127,7 +127,6 @@ examples: clocks = <&ov02a10_clk>; clock-names = "eclk"; - clock-frequency = <24000000>; rotation = <180>; diff --git a/Documentation/devicetree/bindings/media/i2c/ovti,ov2735.yaml b/Documentation/devicetree/bindings/media/i2c/ovti,ov2735.yaml new file mode 100644 index 000000000000..bb34f21519c8 --- /dev/null +++ b/Documentation/devicetree/bindings/media/i2c/ovti,ov2735.yaml @@ -0,0 +1,108 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/media/i2c/ovti,ov2735.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: OmniVision OV2735 Image Sensor + +maintainers: + - Himanshu Bhavani <himanshu.bhavani@siliconsignals.io> + +description: + The OmniVision OV2735 is a 2MP (1920x1080) color CMOS image sensor controlled + through an I2C-compatible SCCB bus. it outputs RAW10 format and uses a 1/2.7" + optical format. + +properties: + compatible: + const: ovti,ov2735 + + reg: + maxItems: 1 + + clocks: + items: + - description: XVCLK clock + + avdd-supply: + description: Analog Domain Power Supply + + dovdd-supply: + description: I/O Domain Power Supply + + dvdd-supply: + description: Digital Domain Power Supply + + reset-gpios: + maxItems: 1 + description: Reset Pin GPIO Control (active low) + + enable-gpios: + maxItems: 1 + description: + Active-low enable pin. Labeled as 'PWDN' in the datasheet, but acts as + an enable signal. During power rail ramp-up, the device remains powered + down. Once power rails are stable, pulling this pin low powers on the + device. + + port: + description: MIPI CSI-2 transmitter port + $ref: /schemas/graph.yaml#/$defs/port-base + additionalProperties: false + + properties: + endpoint: + $ref: /schemas/media/video-interfaces.yaml# + unevaluatedProperties: false + + properties: + data-lanes: + items: + - const: 1 + - const: 2 + + required: + - data-lanes + - link-frequencies + +required: + - compatible + - reg + - clocks + - avdd-supply + - dovdd-supply + - dvdd-supply + - port + +additionalProperties: false + +examples: + - | + #include <dt-bindings/gpio/gpio.h> + + i2c { + #address-cells = <1>; + #size-cells = <0>; + + camera-sensor@3c { + compatible = "ovti,ov2735"; + reg = <0x3c>; + clocks = <&ov2735_clk>; + + avdd-supply = <&ov2735_avdd>; + dovdd-supply = <&ov2735_dovdd>; + dvdd-supply = <&ov2735_dvdd>; + + reset-gpios = <&gpio1 6 GPIO_ACTIVE_LOW>; + enable-gpios = <&gpio2 11 GPIO_ACTIVE_LOW>; + + port { + cam_out: endpoint { + remote-endpoint = <&mipi_in_cam>; + data-lanes = <1 2>; + link-frequencies = /bits/ 64 <420000000>; + }; + }; + }; + }; diff --git a/Documentation/devicetree/bindings/media/i2c/ovti,ov5645.yaml b/Documentation/devicetree/bindings/media/i2c/ovti,ov5645.yaml index bc9b27afe3ea..a583714b1ac7 100644 --- a/Documentation/devicetree/bindings/media/i2c/ovti,ov5645.yaml +++ b/Documentation/devicetree/bindings/media/i2c/ovti,ov5645.yaml @@ -21,6 +21,7 @@ properties: clock-frequency: description: Frequency of the xclk clock in Hz. + deprecated: true vdda-supply: description: Analog voltage supply, 2.8 volts @@ -83,8 +84,11 @@ examples: camera@3c { compatible = "ovti,ov5645"; reg = <0x3c>; + clocks = <&clks 1>; - clock-frequency = <24000000>; + assigned-clocks = <&clks 1>; + assigned-clock-rates = <24000000>; + vdddo-supply = <&ov5645_vdddo_1v8>; vdda-supply = <&ov5645_vdda_2v8>; vddd-supply = <&ov5645_vddd_1v5>; diff --git a/Documentation/devicetree/bindings/media/i2c/ovti,ov6211.yaml b/Documentation/devicetree/bindings/media/i2c/ovti,ov6211.yaml new file mode 100644 index 000000000000..5a857fa2f371 --- /dev/null +++ b/Documentation/devicetree/bindings/media/i2c/ovti,ov6211.yaml @@ -0,0 +1,96 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/media/i2c/ovti,ov6211.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: OmniVision OV6211 Image Sensor + +description: + OmniVision OV6211 image sensor is a high performance monochrome image + sensor. The sensor is controlled over a serial camera control bus + protocol (SCCB), the widest supported output image frame size is 400x400 + at 120 frames per second rate, data output format is 8/10-bit RAW + transferred over one-lane MIPI D-PHY interface. + +maintainers: + - Vladimir Zapolskiy <vladimir.zapolskiy@linaro.org> + +allOf: + - $ref: /schemas/media/video-interface-devices.yaml# + +properties: + compatible: + const: ovti,ov6211 + + reg: + maxItems: 1 + + clocks: + description: XVCLK supply clock, 6MHz to 27MHz frequency. + maxItems: 1 + + reset-gpios: + description: Active low GPIO connected to XSHUTDOWN pad of the sensor. + maxItems: 1 + + strobe-gpios: + description: Input GPIO connected to strobe pad of the sensor. + maxItems: 1 + + avdd-supply: + description: Analogue voltage supply, 2.6 to 3.0 volts. + + dovdd-supply: + description: Digital I/O voltage supply, 1.8 volts. + + dvdd-supply: + description: Digital core voltage supply. + + port: + $ref: /schemas/graph.yaml#/$defs/port-base + additionalProperties: false + + properties: + endpoint: + $ref: /schemas/media/video-interfaces.yaml# + unevaluatedProperties: false + + required: + - link-frequencies + +required: + - compatible + - reg + - port + +unevaluatedProperties: false + +examples: + - | + #include <dt-bindings/gpio/gpio.h> + + i2c { + #address-cells = <1>; + #size-cells = <0>; + + camera@60 { + compatible = "ovti,ov6211"; + reg = <0x60>; + clocks = <&camera_clk 0>; + assigned-clocks = <&camera_clk 0>; + assigned-clock-rates = <24000000>; + reset-gpios = <&gpio1 10 GPIO_ACTIVE_LOW>; + avdd-supply = <&vreg_2p8>; + dovdd-supply = <&vreg_1p8>; + dvdd-supply = <&vreg_1p2>; + + port { + endpoint { + link-frequencies = /bits/ 64 <480000000>; + remote-endpoint = <&mipi_csi2_ep>; + }; + }; + }; + }; +... diff --git a/Documentation/devicetree/bindings/media/i2c/ovti,ov7251.yaml b/Documentation/devicetree/bindings/media/i2c/ovti,ov7251.yaml index 2e5187acbbb8..922996da59b2 100644 --- a/Documentation/devicetree/bindings/media/i2c/ovti,ov7251.yaml +++ b/Documentation/devicetree/bindings/media/i2c/ovti,ov7251.yaml @@ -29,6 +29,7 @@ properties: clock-frequency: description: Frequency of the xclk clock in Hz. + deprecated: true vdda-supply: description: Analog voltage supply, 2.8 volts @@ -89,8 +90,11 @@ examples: camera@3c { compatible = "ovti,ov7251"; reg = <0x3c>; + clocks = <&clks 1>; - clock-frequency = <24000000>; + assigned-clocks = <&clks 1>; + assigned-clock-rates = <24000000>; + vdddo-supply = <&ov7251_vdddo_1v8>; vdda-supply = <&ov7251_vdda_2v8>; vddd-supply = <&ov7251_vddd_1v5>; diff --git a/Documentation/devicetree/bindings/media/i2c/ovti,ov8856.yaml b/Documentation/devicetree/bindings/media/i2c/ovti,ov8856.yaml index 3f6f72c35485..fa71f24823f2 100644 --- a/Documentation/devicetree/bindings/media/i2c/ovti,ov8856.yaml +++ b/Documentation/devicetree/bindings/media/i2c/ovti,ov8856.yaml @@ -37,6 +37,7 @@ properties: clock-frequency: description: Frequency of the xvclk clock in Hertz. + deprecated: true dovdd-supply: description: @@ -87,7 +88,6 @@ required: - reg - clocks - clock-names - - clock-frequency - dovdd-supply - avdd-supply - dvdd-supply @@ -114,7 +114,6 @@ examples: clocks = <&cam_osc>; clock-names = "xvclk"; - clock-frequency = <19200000>; avdd-supply = <&mt6358_vcama2_reg>; dvdd-supply = <&mt6358_vcamd_reg>; diff --git a/Documentation/devicetree/bindings/media/i2c/samsung,s5k5baf.yaml b/Documentation/devicetree/bindings/media/i2c/samsung,s5k5baf.yaml index c8f2955e0825..ebd95a8d9b2f 100644 --- a/Documentation/devicetree/bindings/media/i2c/samsung,s5k5baf.yaml +++ b/Documentation/devicetree/bindings/media/i2c/samsung,s5k5baf.yaml @@ -26,6 +26,7 @@ properties: clock-frequency: default: 24000000 description: mclk clock frequency + deprecated: true rstn-gpios: maxItems: 1 @@ -82,9 +83,12 @@ examples: sensor@2d { compatible = "samsung,s5k5baf"; reg = <0x2d>; + clocks = <&camera 0>; + assigned-clocks = <&camera 0>; + assigned-clock-rates = <24000000>; + clock-names = "mclk"; - clock-frequency = <24000000>; rstn-gpios = <&gpl2 1 GPIO_ACTIVE_LOW>; stbyn-gpios = <&gpl2 0 GPIO_ACTIVE_LOW>; vdda-supply = <&cam_io_en_reg>; diff --git a/Documentation/devicetree/bindings/media/i2c/samsung,s5k6a3.yaml b/Documentation/devicetree/bindings/media/i2c/samsung,s5k6a3.yaml index 7e83a94124b5..e563e35920c4 100644 --- a/Documentation/devicetree/bindings/media/i2c/samsung,s5k6a3.yaml +++ b/Documentation/devicetree/bindings/media/i2c/samsung,s5k6a3.yaml @@ -30,6 +30,7 @@ properties: clock-frequency: default: 24000000 description: extclk clock frequency + deprecated: true gpios: maxItems: 1 @@ -80,8 +81,11 @@ examples: sensor@10 { compatible = "samsung,s5k6a3"; reg = <0x10>; - clock-frequency = <24000000>; + clocks = <&camera 1>; + assigned-clocks = <&camera 1>; + assigned-clock-rates = <24000000>; + clock-names = "extclk"; gpios = <&gpm1 6 GPIO_ACTIVE_LOW>; afvdd-supply = <&ldo19_reg>; diff --git a/Documentation/devicetree/bindings/media/i2c/sony,imx258.yaml b/Documentation/devicetree/bindings/media/i2c/sony,imx258.yaml index 421b935b52bc..d105bd357dbb 100644 --- a/Documentation/devicetree/bindings/media/i2c/sony,imx258.yaml +++ b/Documentation/devicetree/bindings/media/i2c/sony,imx258.yaml @@ -81,6 +81,7 @@ properties: required: - compatible - reg + - clocks - port unevaluatedProperties: false diff --git a/Documentation/devicetree/bindings/media/i2c/sony,imx274.yaml b/Documentation/devicetree/bindings/media/i2c/sony,imx274.yaml index b397a730ee94..b06a6e75ba97 100644 --- a/Documentation/devicetree/bindings/media/i2c/sony,imx274.yaml +++ b/Documentation/devicetree/bindings/media/i2c/sony,imx274.yaml @@ -46,6 +46,8 @@ properties: required: - compatible - reg + - clocks + - clock-names - port additionalProperties: false @@ -59,6 +61,8 @@ examples: imx274: camera-sensor@1a { compatible = "sony,imx274"; reg = <0x1a>; + clocks = <&imx274_clk>; + clock-names = "inck"; reset-gpios = <&gpio_sensor 0 0>; port { diff --git a/Documentation/devicetree/bindings/media/i2c/sony,imx290.yaml b/Documentation/devicetree/bindings/media/i2c/sony,imx290.yaml index 990acf89af8f..484039671cd1 100644 --- a/Documentation/devicetree/bindings/media/i2c/sony,imx290.yaml +++ b/Documentation/devicetree/bindings/media/i2c/sony,imx290.yaml @@ -51,6 +51,7 @@ properties: clock-frequency: description: Frequency of the xclk clock in Hz + deprecated: true vdda-supply: description: Analog power supply (2.9V) @@ -100,7 +101,6 @@ required: - reg - clocks - clock-names - - clock-frequency - vdda-supply - vddd-supply - vdddo-supply @@ -125,7 +125,8 @@ examples: clocks = <&gcc 90>; clock-names = "xclk"; - clock-frequency = <37125000>; + assigned-clocks = <&clks 1>; + assigned-clock-rates = <37125000>; vdddo-supply = <&camera_vdddo_1v8>; vdda-supply = <&camera_vdda_2v8>; diff --git a/Documentation/devicetree/bindings/media/i2c/ti,ds90ub960.yaml b/Documentation/devicetree/bindings/media/i2c/ti,ds90ub960.yaml index 4dcbd2b039a5..0539d52de422 100644 --- a/Documentation/devicetree/bindings/media/i2c/ti,ds90ub960.yaml +++ b/Documentation/devicetree/bindings/media/i2c/ti,ds90ub960.yaml @@ -361,6 +361,9 @@ examples: compatible = "sony,imx274"; reg = <0x1a>; + clocks = <&serializer>; + clock-names = "inck"; + reset-gpios = <&serializer1 0 GPIO_ACTIVE_LOW>; port { diff --git a/Documentation/devicetree/bindings/media/i2c/toshiba,et8ek8.txt b/Documentation/devicetree/bindings/media/i2c/toshiba,et8ek8.txt index e80d5891b7ed..8d8e40c56872 100644 --- a/Documentation/devicetree/bindings/media/i2c/toshiba,et8ek8.txt +++ b/Documentation/devicetree/bindings/media/i2c/toshiba,et8ek8.txt @@ -13,9 +13,6 @@ Mandatory properties - reg: I2C address (0x3e, or an alternative address) - vana-supply: Analogue voltage supply (VANA), 2.8 volts - clocks: External clock to the sensor -- clock-frequency: Frequency of the external clock to the sensor. Camera - driver will set this frequency on the external clock. The clock frequency is - a pre-determined frequency known to be suitable to the board. - reset-gpios: XSHUTDOWN GPIO. The XSHUTDOWN signal is active low. The sensor is in hardware standby mode when the signal is in the low state. @@ -43,8 +40,11 @@ Example compatible = "toshiba,et8ek8"; reg = <0x3e>; vana-supply = <&vaux4>; + clocks = <&isp 0>; - clock-frequency = <9600000>; + assigned-clocks = <&isp 0>; + assigned-clock-rates = <9600000>; + reset-gpio = <&gpio4 6 GPIO_ACTIVE_HIGH>; /* 102 */ port { csi_cam1: endpoint { diff --git a/Documentation/devicetree/bindings/media/nxp,imx-mipi-csi2.yaml b/Documentation/devicetree/bindings/media/nxp,imx-mipi-csi2.yaml index 03a23a26c4f3..41ad5b84eaeb 100644 --- a/Documentation/devicetree/bindings/media/nxp,imx-mipi-csi2.yaml +++ b/Documentation/devicetree/bindings/media/nxp,imx-mipi-csi2.yaml @@ -66,6 +66,14 @@ properties: clock-frequency: description: The desired external clock ("wrap") frequency, in Hz default: 166000000 + deprecated: true + + fsl,num-channels: + $ref: /schemas/types.yaml#/definitions/uint32 + description: Number of output channels + minimum: 1 + maximum: 4 + default: 1 ports: $ref: /schemas/graph.yaml#/properties/ports @@ -147,7 +155,9 @@ examples: <&clks IMX7D_MIPI_CSI_ROOT_CLK>, <&clks IMX7D_MIPI_DPHY_ROOT_CLK>; clock-names = "pclk", "wrap", "phy"; - clock-frequency = <166000000>; + + assigned-clocks = <&clks IMX7D_MIPI_CSI_ROOT_CLK>; + assigned-clock-rates = <166000000>; power-domains = <&pgc_mipi_phy>; phy-supply = <®_1p0d>; @@ -185,12 +195,16 @@ examples: compatible = "fsl,imx8mm-mipi-csi2"; reg = <0x32e30000 0x1000>; interrupts = <GIC_SPI 17 IRQ_TYPE_LEVEL_HIGH>; - clock-frequency = <333000000>; + clocks = <&clk IMX8MM_CLK_DISP_APB_ROOT>, <&clk IMX8MM_CLK_CSI1_ROOT>, <&clk IMX8MM_CLK_CSI1_PHY_REF>, <&clk IMX8MM_CLK_DISP_AXI_ROOT>; clock-names = "pclk", "wrap", "phy", "axi"; + + assigned-clocks = <&clk IMX8MM_CLK_CSI1_ROOT>; + assigned-clock-rates = <250000000>; + power-domains = <&mipi_pd>; ports { diff --git a/Documentation/devicetree/bindings/media/qcom,qcm2290-camss.yaml b/Documentation/devicetree/bindings/media/qcom,qcm2290-camss.yaml new file mode 100644 index 000000000000..391d0f6f67ef --- /dev/null +++ b/Documentation/devicetree/bindings/media/qcom,qcm2290-camss.yaml @@ -0,0 +1,243 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/media/qcom,qcm2290-camss.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Qualcomm QCM2290 Camera Subsystem (CAMSS) + +maintainers: + - Loic Poulain <loic.poulain@oss.qualcomm.com> + +description: + The CAMSS IP is a CSI decoder and ISP present on Qualcomm platforms. + +properties: + compatible: + const: qcom,qcm2290-camss + + reg: + maxItems: 9 + + reg-names: + items: + - const: top + - const: csid0 + - const: csid1 + - const: csiphy0 + - const: csiphy1 + - const: csitpg0 + - const: csitpg1 + - const: vfe0 + - const: vfe1 + + clocks: + maxItems: 15 + + clock-names: + items: + - const: ahb + - const: axi + - const: camnoc_nrt_axi + - const: camnoc_rt_axi + - const: csi0 + - const: csi1 + - const: csiphy0 + - const: csiphy0_timer + - const: csiphy1 + - const: csiphy1_timer + - const: top_ahb + - const: vfe0 + - const: vfe0_cphy_rx + - const: vfe1 + - const: vfe1_cphy_rx + + interrupts: + maxItems: 8 + + interrupt-names: + items: + - const: csid0 + - const: csid1 + - const: csiphy0 + - const: csiphy1 + - const: csitpg0 + - const: csitpg1 + - const: vfe0 + - const: vfe1 + + interconnects: + maxItems: 3 + + interconnect-names: + items: + - const: ahb + - const: hf_mnoc + - const: sf_mnoc + + iommus: + maxItems: 4 + + power-domains: + items: + - description: GDSC CAMSS Block, Global Distributed Switch Controller. + + vdd-csiphy-1p2-supply: + description: + Phandle to a 1.2V regulator supply to CSI PHYs. + + vdd-csiphy-1p8-supply: + description: + Phandle to 1.8V regulator supply to CSI PHYs pll block. + + ports: + $ref: /schemas/graph.yaml#/properties/ports + + description: + CSI input ports. + + patternProperties: + "^port@[0-3]+$": + $ref: /schemas/graph.yaml#/$defs/port-base + unevaluatedProperties: false + + description: + Input port for receiving CSI data from a CSIPHY. + + properties: + endpoint: + $ref: video-interfaces.yaml# + unevaluatedProperties: false + + properties: + data-lanes: + minItems: 1 + maxItems: 4 + + required: + - data-lanes + +required: + - compatible + - reg + - reg-names + - clocks + - clock-names + - interrupts + - interrupt-names + - interconnects + - interconnect-names + - iommus + - power-domains + - vdd-csiphy-1p2-supply + - vdd-csiphy-1p8-supply + +additionalProperties: false + +examples: + - | + #include <dt-bindings/clock/qcom,gcc-qcm2290.h> + #include <dt-bindings/interconnect/qcom,rpm-icc.h> + #include <dt-bindings/interconnect/qcom,qcm2290.h> + #include <dt-bindings/interrupt-controller/arm-gic.h> + + soc { + #address-cells = <2>; + #size-cells = <2>; + + camss: camss@5c6e000 { + compatible = "qcom,qcm2290-camss"; + + reg = <0x0 0x5c11000 0x0 0x1000>, + <0x0 0x5c6e000 0x0 0x1000>, + <0x0 0x5c75000 0x0 0x1000>, + <0x0 0x5c52000 0x0 0x1000>, + <0x0 0x5c53000 0x0 0x1000>, + <0x0 0x5c66000 0x0 0x400>, + <0x0 0x5c68000 0x0 0x400>, + <0x0 0x5c6f000 0x0 0x4000>, + <0x0 0x5c76000 0x0 0x4000>; + reg-names = "top", + "csid0", + "csid1", + "csiphy0", + "csiphy1", + "csitpg0", + "csitpg1", + "vfe0", + "vfe1"; + + clocks = <&gcc GCC_CAMERA_AHB_CLK>, + <&gcc GCC_CAMSS_AXI_CLK>, + <&gcc GCC_CAMSS_NRT_AXI_CLK>, + <&gcc GCC_CAMSS_RT_AXI_CLK>, + <&gcc GCC_CAMSS_TFE_0_CSID_CLK>, + <&gcc GCC_CAMSS_TFE_1_CSID_CLK>, + <&gcc GCC_CAMSS_CPHY_0_CLK>, + <&gcc GCC_CAMSS_CSI0PHYTIMER_CLK>, + <&gcc GCC_CAMSS_CPHY_1_CLK>, + <&gcc GCC_CAMSS_CSI1PHYTIMER_CLK>, + <&gcc GCC_CAMSS_TOP_AHB_CLK>, + <&gcc GCC_CAMSS_TFE_0_CLK>, + <&gcc GCC_CAMSS_TFE_0_CPHY_RX_CLK>, + <&gcc GCC_CAMSS_TFE_1_CLK>, + <&gcc GCC_CAMSS_TFE_1_CPHY_RX_CLK>; + clock-names = "ahb", + "axi", + "camnoc_nrt_axi", + "camnoc_rt_axi", + "csi0", + "csi1", + "csiphy0", + "csiphy0_timer", + "csiphy1", + "csiphy1_timer", + "top_ahb", + "vfe0", + "vfe0_cphy_rx", + "vfe1", + "vfe1_cphy_rx"; + + interrupts = <GIC_SPI 210 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 212 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 72 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 73 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 309 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 310 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 211 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 213 IRQ_TYPE_EDGE_RISING>; + interrupt-names = "csid0", + "csid1", + "csiphy0", + "csiphy1", + "csitpg0", + "csitpg1", + "vfe0", + "vfe1"; + + interconnects = <&bimc MASTER_APPSS_PROC RPM_ACTIVE_TAG + &config_noc SLAVE_CAMERA_CFG RPM_ACTIVE_TAG>, + <&mmrt_virt MASTER_CAMNOC_HF RPM_ALWAYS_TAG + &bimc SLAVE_EBI1 RPM_ALWAYS_TAG>, + <&mmnrt_virt MASTER_CAMNOC_SF RPM_ALWAYS_TAG + &bimc SLAVE_EBI1 RPM_ALWAYS_TAG>; + interconnect-names = "ahb", + "hf_mnoc", + "sf_mnoc"; + + iommus = <&apps_smmu 0x400 0x0>, + <&apps_smmu 0x800 0x0>, + <&apps_smmu 0x820 0x0>, + <&apps_smmu 0x840 0x0>; + + power-domains = <&gcc GCC_CAMSS_TOP_GDSC>; + + vdd-csiphy-1p2-supply = <&pm4125_l5>; + vdd-csiphy-1p8-supply = <&pm4125_l13>; + + ports { + #address-cells = <1>; + #size-cells = <0>; + }; + }; + }; diff --git a/Documentation/devicetree/bindings/media/qcom,qcm2290-venus.yaml b/Documentation/devicetree/bindings/media/qcom,qcm2290-venus.yaml new file mode 100644 index 000000000000..3f3ee82fc878 --- /dev/null +++ b/Documentation/devicetree/bindings/media/qcom,qcm2290-venus.yaml @@ -0,0 +1,130 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/media/qcom,qcm2290-venus.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Qualcomm QCM2290 Venus video encode and decode accelerators + +maintainers: + - Jorge Ramirez-Ortiz <jorge.ramirez@oss.qualcomm.com> + +description: + The Venus AR50_LITE IP is a video encode and decode accelerator present + on Qualcomm platforms. + +allOf: + - $ref: qcom,venus-common.yaml# + +properties: + compatible: + const: qcom,qcm2290-venus + + power-domains: + maxItems: 3 + + power-domain-names: + items: + - const: venus + - const: vcodec0 + - const: cx + + clocks: + maxItems: 6 + + clock-names: + items: + - const: core + - const: iface + - const: bus + - const: throttle + - const: vcodec0_core + - const: vcodec0_bus + + iommus: + maxItems: 5 + + interconnects: + maxItems: 2 + + interconnect-names: + items: + - const: video-mem + - const: cpu-cfg + + operating-points-v2: true + opp-table: + type: object + +required: + - compatible + - power-domain-names + - iommus + +unevaluatedProperties: false + +examples: + - | + #include <dt-bindings/clock/qcom,gcc-qcm2290.h> + #include <dt-bindings/interconnect/qcom,qcm2290.h> + #include <dt-bindings/interconnect/qcom,rpm-icc.h> + #include <dt-bindings/interrupt-controller/arm-gic.h> + #include <dt-bindings/power/qcom-rpmpd.h> + + venus: video-codec@5a00000 { + compatible = "qcom,qcm2290-venus"; + reg = <0x5a00000 0xf0000>; + + interrupts = <GIC_SPI 225 IRQ_TYPE_LEVEL_HIGH>; + + power-domains = <&gcc GCC_VENUS_GDSC>, + <&gcc GCC_VCODEC0_GDSC>, + <&rpmpd QCM2290_VDDCX>; + power-domain-names = "venus", + "vcodec0", + "cx"; + + operating-points-v2 = <&venus_opp_table>; + + clocks = <&gcc GCC_VIDEO_VENUS_CTL_CLK>, + <&gcc GCC_VIDEO_AHB_CLK>, + <&gcc GCC_VENUS_CTL_AXI_CLK>, + <&gcc GCC_VIDEO_THROTTLE_CORE_CLK>, + <&gcc GCC_VIDEO_VCODEC0_SYS_CLK>, + <&gcc GCC_VCODEC0_AXI_CLK>; + clock-names = "core", + "iface", + "bus", + "throttle", + "vcodec0_core", + "vcodec0_bus"; + + memory-region = <&pil_video_mem>; + + iommus = <&apps_smmu 0x860 0x0>, + <&apps_smmu 0x880 0x0>, + <&apps_smmu 0x861 0x04>, + <&apps_smmu 0x863 0x0>, + <&apps_smmu 0x804 0xe0>; + + interconnects = <&mmnrt_virt MASTER_VIDEO_P0 RPM_ALWAYS_TAG + &bimc SLAVE_EBI1 RPM_ALWAYS_TAG>, + <&bimc MASTER_APPSS_PROC RPM_ACTIVE_TAG + &config_noc SLAVE_VENUS_CFG RPM_ACTIVE_TAG>; + interconnect-names = "video-mem", + "cpu-cfg"; + + venus_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-133333333 { + opp-hz = /bits/ 64 <133333333>; + required-opps = <&rpmpd_opp_low_svs>; + }; + + opp-240000000 { + opp-hz = /bits/ 64 <240000000>; + required-opps = <&rpmpd_opp_svs>; + }; + }; + }; diff --git a/Documentation/devicetree/bindings/media/qcom,qcs8300-camss.yaml b/Documentation/devicetree/bindings/media/qcom,qcs8300-camss.yaml new file mode 100644 index 000000000000..80a4540a22dc --- /dev/null +++ b/Documentation/devicetree/bindings/media/qcom,qcs8300-camss.yaml @@ -0,0 +1,336 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/media/qcom,qcs8300-camss.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Qualcomm QCS8300 CAMSS ISP + +maintainers: + - Vikram Sharma <quic_vikramsa@quicinc.com> + +description: + The CAMSS IP is a CSI decoder and ISP present on Qualcomm platforms. + +properties: + compatible: + const: qcom,qcs8300-camss + + reg: + maxItems: 21 + + reg-names: + items: + - const: csid_wrapper + - const: csid0 + - const: csid1 + - const: csid_lite0 + - const: csid_lite1 + - const: csid_lite2 + - const: csid_lite3 + - const: csid_lite4 + - const: csiphy0 + - const: csiphy1 + - const: csiphy2 + - const: tpg0 + - const: tpg1 + - const: tpg2 + - const: vfe0 + - const: vfe1 + - const: vfe_lite0 + - const: vfe_lite1 + - const: vfe_lite2 + - const: vfe_lite3 + - const: vfe_lite4 + + clocks: + maxItems: 26 + + clock-names: + items: + - const: camnoc_axi + - const: core_ahb + - const: cpas_ahb + - const: cpas_fast_ahb_clk + - const: cpas_vfe_lite + - const: cpas_vfe0 + - const: cpas_vfe1 + - const: csid + - const: csiphy0 + - const: csiphy0_timer + - const: csiphy1 + - const: csiphy1_timer + - const: csiphy2 + - const: csiphy2_timer + - const: csiphy_rx + - const: gcc_axi_hf + - const: gcc_axi_sf + - const: icp_ahb + - const: vfe0 + - const: vfe0_fast_ahb + - const: vfe1 + - const: vfe1_fast_ahb + - const: vfe_lite + - const: vfe_lite_ahb + - const: vfe_lite_cphy_rx + - const: vfe_lite_csid + + interrupts: + maxItems: 20 + + interrupt-names: + items: + - const: csid0 + - const: csid1 + - const: csid_lite0 + - const: csid_lite1 + - const: csid_lite2 + - const: csid_lite3 + - const: csid_lite4 + - const: csiphy0 + - const: csiphy1 + - const: csiphy2 + - const: tpg0 + - const: tpg1 + - const: tpg2 + - const: vfe0 + - const: vfe1 + - const: vfe_lite0 + - const: vfe_lite1 + - const: vfe_lite2 + - const: vfe_lite3 + - const: vfe_lite4 + + interconnects: + maxItems: 2 + + interconnect-names: + items: + - const: ahb + - const: hf_0 + + iommus: + maxItems: 1 + + power-domains: + items: + - description: Titan GDSC - Titan ISP Block, Global Distributed Switch Controller. + + power-domain-names: + items: + - const: top + + ports: + $ref: /schemas/graph.yaml#/properties/ports + + description: + CSI input ports. + + patternProperties: + "^port@[0-2]+$": + $ref: /schemas/graph.yaml#/$defs/port-base + unevaluatedProperties: false + description: + Input port for receiving CSI data on CSIPHY 0-2. + + properties: + endpoint: + $ref: video-interfaces.yaml# + unevaluatedProperties: false + + properties: + data-lanes: + minItems: 1 + maxItems: 4 + + required: + - data-lanes + +required: + - compatible + - reg + - reg-names + - clocks + - clock-names + - interrupts + - interrupt-names + - interconnects + - interconnect-names + - iommus + - power-domains + - power-domain-names + - ports + +additionalProperties: false + +examples: + - | + #include <dt-bindings/clock/qcom,sa8775p-camcc.h> + #include <dt-bindings/clock/qcom,sa8775p-gcc.h> + #include <dt-bindings/interconnect/qcom,sa8775p-rpmh.h> + #include <dt-bindings/interconnect/qcom,icc.h> + #include <dt-bindings/interrupt-controller/arm-gic.h> + #include <dt-bindings/power/qcom-rpmpd.h> + + soc { + #address-cells = <2>; + #size-cells = <2>; + + isp@ac78000 { + compatible = "qcom,qcs8300-camss"; + + reg = <0x0 0xac78000 0x0 0x1000>, + <0x0 0xac7a000 0x0 0x0f00>, + <0x0 0xac7c000 0x0 0x0f00>, + <0x0 0xac84000 0x0 0x0f00>, + <0x0 0xac88000 0x0 0x0f00>, + <0x0 0xac8c000 0x0 0x0f00>, + <0x0 0xac90000 0x0 0x0f00>, + <0x0 0xac94000 0x0 0x0f00>, + <0x0 0xac9c000 0x0 0x2000>, + <0x0 0xac9e000 0x0 0x2000>, + <0x0 0xaca0000 0x0 0x2000>, + <0x0 0xacac000 0x0 0x0400>, + <0x0 0xacad000 0x0 0x0400>, + <0x0 0xacae000 0x0 0x0400>, + <0x0 0xac4d000 0x0 0xd000>, + <0x0 0xac60000 0x0 0xd000>, + <0x0 0xac85000 0x0 0x0d00>, + <0x0 0xac89000 0x0 0x0d00>, + <0x0 0xac8d000 0x0 0x0d00>, + <0x0 0xac91000 0x0 0x0d00>, + <0x0 0xac95000 0x0 0x0d00>; + reg-names = "csid_wrapper", + "csid0", + "csid1", + "csid_lite0", + "csid_lite1", + "csid_lite2", + "csid_lite3", + "csid_lite4", + "csiphy0", + "csiphy1", + "csiphy2", + "tpg0", + "tpg1", + "tpg2", + "vfe0", + "vfe1", + "vfe_lite0", + "vfe_lite1", + "vfe_lite2", + "vfe_lite3", + "vfe_lite4"; + + clocks = <&camcc CAM_CC_CAMNOC_AXI_CLK>, + <&camcc CAM_CC_CORE_AHB_CLK>, + <&camcc CAM_CC_CPAS_AHB_CLK>, + <&camcc CAM_CC_CPAS_FAST_AHB_CLK>, + <&camcc CAM_CC_CPAS_IFE_LITE_CLK>, + <&camcc CAM_CC_CPAS_IFE_0_CLK>, + <&camcc CAM_CC_CPAS_IFE_1_CLK>, + <&camcc CAM_CC_CSID_CLK>, + <&camcc CAM_CC_CSIPHY0_CLK>, + <&camcc CAM_CC_CSI0PHYTIMER_CLK>, + <&camcc CAM_CC_CSIPHY1_CLK>, + <&camcc CAM_CC_CSI1PHYTIMER_CLK>, + <&camcc CAM_CC_CSIPHY2_CLK>, + <&camcc CAM_CC_CSI2PHYTIMER_CLK>, + <&camcc CAM_CC_CSID_CSIPHY_RX_CLK>, + <&gcc GCC_CAMERA_HF_AXI_CLK>, + <&gcc GCC_CAMERA_SF_AXI_CLK>, + <&camcc CAM_CC_ICP_AHB_CLK>, + <&camcc CAM_CC_IFE_0_CLK>, + <&camcc CAM_CC_IFE_0_FAST_AHB_CLK>, + <&camcc CAM_CC_IFE_1_CLK>, + <&camcc CAM_CC_IFE_1_FAST_AHB_CLK>, + <&camcc CAM_CC_IFE_LITE_CLK>, + <&camcc CAM_CC_IFE_LITE_AHB_CLK>, + <&camcc CAM_CC_IFE_LITE_CPHY_RX_CLK>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK>; + clock-names = "camnoc_axi", + "core_ahb", + "cpas_ahb", + "cpas_fast_ahb_clk", + "cpas_vfe_lite", + "cpas_vfe0", + "cpas_vfe1", + "csid", + "csiphy0", + "csiphy0_timer", + "csiphy1", + "csiphy1_timer", + "csiphy2", + "csiphy2_timer", + "csiphy_rx", + "gcc_axi_hf", + "gcc_axi_sf", + "icp_ahb", + "vfe0", + "vfe0_fast_ahb", + "vfe1", + "vfe1_fast_ahb", + "vfe_lite", + "vfe_lite_ahb", + "vfe_lite_cphy_rx", + "vfe_lite_csid"; + + interrupts = <GIC_SPI 565 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 564 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 468 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 359 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 759 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 758 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 604 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 477 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 478 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 479 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 545 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 546 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 547 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 465 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 467 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 469 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 360 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 761 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 760 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 605 IRQ_TYPE_EDGE_RISING>; + interrupt-names = "csid0", + "csid1", + "csid_lite0", + "csid_lite1", + "csid_lite2", + "csid_lite3", + "csid_lite4", + "csiphy0", + "csiphy1", + "csiphy2", + "tpg0", + "tpg1", + "tpg2", + "vfe0", + "vfe1", + "vfe_lite0", + "vfe_lite1", + "vfe_lite2", + "vfe_lite3", + "vfe_lite4"; + + interconnects = <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ACTIVE_ONLY + &config_noc SLAVE_CAMERA_CFG QCOM_ICC_TAG_ACTIVE_ONLY>, + <&mmss_noc MASTER_CAMNOC_HF QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>; + interconnect-names = "ahb", + "hf_0"; + + iommus = <&apps_smmu 0x2400 0x20>; + + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + power-domain-names = "top"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + }; + }; + }; diff --git a/Documentation/devicetree/bindings/media/qcom,sa8775p-camss.yaml b/Documentation/devicetree/bindings/media/qcom,sa8775p-camss.yaml new file mode 100644 index 000000000000..019caa2b09c3 --- /dev/null +++ b/Documentation/devicetree/bindings/media/qcom,sa8775p-camss.yaml @@ -0,0 +1,361 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/media/qcom,sa8775p-camss.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Qualcomm SA8775P CAMSS ISP + +maintainers: + - Vikram Sharma <quic_vikramsa@quicinc.com> + +description: + The CAMSS IP is a CSI decoder and ISP present on Qualcomm platforms. + +properties: + compatible: + const: qcom,sa8775p-camss + + reg: + maxItems: 22 + + reg-names: + items: + - const: csid_wrapper + - const: csid0 + - const: csid1 + - const: csid_lite0 + - const: csid_lite1 + - const: csid_lite2 + - const: csid_lite3 + - const: csid_lite4 + - const: csiphy0 + - const: csiphy1 + - const: csiphy2 + - const: csiphy3 + - const: tpg0 + - const: tpg1 + - const: tpg2 + - const: vfe0 + - const: vfe1 + - const: vfe_lite0 + - const: vfe_lite1 + - const: vfe_lite2 + - const: vfe_lite3 + - const: vfe_lite4 + + clocks: + maxItems: 28 + + clock-names: + items: + - const: camnoc_axi + - const: core_ahb + - const: cpas_ahb + - const: cpas_fast_ahb_clk + - const: cpas_vfe_lite + - const: cpas_vfe0 + - const: cpas_vfe1 + - const: csid + - const: csiphy0 + - const: csiphy0_timer + - const: csiphy1 + - const: csiphy1_timer + - const: csiphy2 + - const: csiphy2_timer + - const: csiphy3 + - const: csiphy3_timer + - const: csiphy_rx + - const: gcc_axi_hf + - const: gcc_axi_sf + - const: icp_ahb + - const: vfe0 + - const: vfe0_fast_ahb + - const: vfe1 + - const: vfe1_fast_ahb + - const: vfe_lite + - const: vfe_lite_ahb + - const: vfe_lite_cphy_rx + - const: vfe_lite_csid + + interrupts: + maxItems: 21 + + interrupt-names: + items: + - const: csid0 + - const: csid1 + - const: csid_lite0 + - const: csid_lite1 + - const: csid_lite2 + - const: csid_lite3 + - const: csid_lite4 + - const: csiphy0 + - const: csiphy1 + - const: csiphy2 + - const: csiphy3 + - const: tpg0 + - const: tpg1 + - const: tpg2 + - const: vfe0 + - const: vfe1 + - const: vfe_lite0 + - const: vfe_lite1 + - const: vfe_lite2 + - const: vfe_lite3 + - const: vfe_lite4 + + interconnects: + maxItems: 2 + + interconnect-names: + items: + - const: ahb + - const: hf_0 + + iommus: + maxItems: 1 + + power-domains: + items: + - description: Titan GDSC - Titan ISP Block, Global Distributed Switch Controller. + + power-domain-names: + items: + - const: top + + vdda-phy-supply: + description: + Phandle to a regulator supply to PHY core block. + + vdda-pll-supply: + description: + Phandle to 1.8V regulator supply to PHY refclk pll block. + + ports: + $ref: /schemas/graph.yaml#/properties/ports + + description: + CSI input ports. + + patternProperties: + "^port@[0-3]+$": + $ref: /schemas/graph.yaml#/$defs/port-base + unevaluatedProperties: false + description: + Input port for receiving CSI data on CSIPHY 0-3. + + properties: + endpoint: + $ref: video-interfaces.yaml# + unevaluatedProperties: false + + properties: + data-lanes: + minItems: 1 + maxItems: 4 + + required: + - data-lanes + +required: + - compatible + - reg + - reg-names + - clocks + - clock-names + - interrupts + - interrupt-names + - interconnects + - interconnect-names + - iommus + - power-domains + - power-domain-names + - vdda-phy-supply + - vdda-pll-supply + - ports + +additionalProperties: false + +examples: + - | + #include <dt-bindings/clock/qcom,sa8775p-camcc.h> + #include <dt-bindings/clock/qcom,sa8775p-gcc.h> + #include <dt-bindings/interconnect/qcom,sa8775p-rpmh.h> + #include <dt-bindings/interconnect/qcom,icc.h> + #include <dt-bindings/interrupt-controller/arm-gic.h> + #include <dt-bindings/power/qcom-rpmpd.h> + + soc { + #address-cells = <2>; + #size-cells = <2>; + + isp@ac78000 { + compatible = "qcom,sa8775p-camss"; + + reg = <0x0 0xac78000 0x0 0x1000>, + <0x0 0xac7a000 0x0 0x0f00>, + <0x0 0xac7c000 0x0 0x0f00>, + <0x0 0xac84000 0x0 0x0f00>, + <0x0 0xac88000 0x0 0x0f00>, + <0x0 0xac8c000 0x0 0x0f00>, + <0x0 0xac90000 0x0 0x0f00>, + <0x0 0xac94000 0x0 0x0f00>, + <0x0 0xac9c000 0x0 0x2000>, + <0x0 0xac9e000 0x0 0x2000>, + <0x0 0xaca0000 0x0 0x2000>, + <0x0 0xaca2000 0x0 0x2000>, + <0x0 0xacac000 0x0 0x0400>, + <0x0 0xacad000 0x0 0x0400>, + <0x0 0xacae000 0x0 0x0400>, + <0x0 0xac4d000 0x0 0xd000>, + <0x0 0xac5a000 0x0 0xd000>, + <0x0 0xac85000 0x0 0x0d00>, + <0x0 0xac89000 0x0 0x0d00>, + <0x0 0xac8d000 0x0 0x0d00>, + <0x0 0xac91000 0x0 0x0d00>, + <0x0 0xac95000 0x0 0x0d00>; + reg-names = "csid_wrapper", + "csid0", + "csid1", + "csid_lite0", + "csid_lite1", + "csid_lite2", + "csid_lite3", + "csid_lite4", + "csiphy0", + "csiphy1", + "csiphy2", + "csiphy3", + "tpg0", + "tpg1", + "tpg2", + "vfe0", + "vfe1", + "vfe_lite0", + "vfe_lite1", + "vfe_lite2", + "vfe_lite3", + "vfe_lite4"; + + clocks = <&camcc CAM_CC_CAMNOC_AXI_CLK>, + <&camcc CAM_CC_CORE_AHB_CLK>, + <&camcc CAM_CC_CPAS_AHB_CLK>, + <&camcc CAM_CC_CPAS_FAST_AHB_CLK>, + <&camcc CAM_CC_CPAS_IFE_LITE_CLK>, + <&camcc CAM_CC_CPAS_IFE_0_CLK>, + <&camcc CAM_CC_CPAS_IFE_1_CLK>, + <&camcc CAM_CC_CSID_CLK>, + <&camcc CAM_CC_CSIPHY0_CLK>, + <&camcc CAM_CC_CSI0PHYTIMER_CLK>, + <&camcc CAM_CC_CSIPHY1_CLK>, + <&camcc CAM_CC_CSI1PHYTIMER_CLK>, + <&camcc CAM_CC_CSIPHY2_CLK>, + <&camcc CAM_CC_CSI2PHYTIMER_CLK>, + <&camcc CAM_CC_CSIPHY3_CLK>, + <&camcc CAM_CC_CSI3PHYTIMER_CLK>, + <&camcc CAM_CC_CSID_CSIPHY_RX_CLK>, + <&gcc GCC_CAMERA_HF_AXI_CLK>, + <&gcc GCC_CAMERA_SF_AXI_CLK>, + <&camcc CAM_CC_ICP_AHB_CLK>, + <&camcc CAM_CC_IFE_0_CLK>, + <&camcc CAM_CC_IFE_0_FAST_AHB_CLK>, + <&camcc CAM_CC_IFE_1_CLK>, + <&camcc CAM_CC_IFE_1_FAST_AHB_CLK>, + <&camcc CAM_CC_IFE_LITE_CLK>, + <&camcc CAM_CC_IFE_LITE_AHB_CLK>, + <&camcc CAM_CC_IFE_LITE_CPHY_RX_CLK>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK>; + clock-names = "camnoc_axi", + "core_ahb", + "cpas_ahb", + "cpas_fast_ahb_clk", + "cpas_vfe_lite", + "cpas_vfe0", + "cpas_vfe1", + "csid", + "csiphy0", + "csiphy0_timer", + "csiphy1", + "csiphy1_timer", + "csiphy2", + "csiphy2_timer", + "csiphy3", + "csiphy3_timer", + "csiphy_rx", + "gcc_axi_hf", + "gcc_axi_sf", + "icp_ahb", + "vfe0", + "vfe0_fast_ahb", + "vfe1", + "vfe1_fast_ahb", + "vfe_lite", + "vfe_lite_ahb", + "vfe_lite_cphy_rx", + "vfe_lite_csid"; + + interrupts = <GIC_SPI 565 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 564 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 468 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 359 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 759 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 758 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 604 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 477 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 478 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 479 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 448 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 545 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 546 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 547 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 465 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 467 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 469 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 360 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 761 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 760 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 605 IRQ_TYPE_EDGE_RISING>; + interrupt-names = "csid0", + "csid1", + "csid_lite0", + "csid_lite1", + "csid_lite2", + "csid_lite3", + "csid_lite4", + "csiphy0", + "csiphy1", + "csiphy2", + "csiphy3", + "tpg0", + "tpg1", + "tpg2", + "vfe0", + "vfe1", + "vfe_lite0", + "vfe_lite1", + "vfe_lite2", + "vfe_lite3", + "vfe_lite4"; + + interconnects = <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ACTIVE_ONLY + &config_noc SLAVE_CAMERA_CFG QCOM_ICC_TAG_ACTIVE_ONLY>, + <&mmss_noc MASTER_CAMNOC_HF QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>; + interconnect-names = "ahb", + "hf_0"; + + iommus = <&apps_smmu 0x3400 0x20>; + + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + power-domain-names = "top"; + + vdda-phy-supply = <&vreg_l4a_0p88>; + vdda-pll-supply = <&vreg_l1c_1p2>; + + ports { + #address-cells = <1>; + #size-cells = <0>; + }; + }; + }; diff --git a/Documentation/devicetree/bindings/media/qcom,sm8550-iris.yaml b/Documentation/devicetree/bindings/media/qcom,sm8550-iris.yaml index c79bf2101812..9c4b760508b5 100644 --- a/Documentation/devicetree/bindings/media/qcom,sm8550-iris.yaml +++ b/Documentation/devicetree/bindings/media/qcom,sm8550-iris.yaml @@ -8,7 +8,7 @@ title: Qualcomm iris video encode and decode accelerators maintainers: - Vikash Garodia <quic_vgarodia@quicinc.com> - - Dikshita Agarwal <quic_dikshita@quicinc.com> + - Dikshita Agarwal <dikshita.agarwal@oss.qualcomm.com> description: The iris video processing unit is a video encode and decode accelerator @@ -20,12 +20,16 @@ properties: - items: - enum: - qcom,sa8775p-iris + - qcom,x1e80100-iris - const: qcom,sm8550-iris - enum: - qcom,qcs8300-iris - qcom,sm8550-iris - qcom,sm8650-iris + reg: + maxItems: 1 + power-domains: maxItems: 4 @@ -45,6 +49,12 @@ properties: - const: core - const: vcodec0_core + firmware-name: + maxItems: 1 + + interrupts: + maxItems: 1 + interconnects: maxItems: 2 @@ -69,6 +79,9 @@ properties: dma-coherent: true + memory-region: + maxItems: 1 + operating-points-v2: true opp-table: @@ -85,7 +98,6 @@ required: - dma-coherent allOf: - - $ref: qcom,venus-common.yaml# - if: properties: compatible: diff --git a/Documentation/devicetree/bindings/media/qcom,sm8750-iris.yaml b/Documentation/devicetree/bindings/media/qcom,sm8750-iris.yaml new file mode 100644 index 000000000000..c9a0fcafe53f --- /dev/null +++ b/Documentation/devicetree/bindings/media/qcom,sm8750-iris.yaml @@ -0,0 +1,186 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/media/qcom,sm8750-iris.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Qualcomm SM8750 SoC Iris video encoder and decoder + +maintainers: + - Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org> + +description: + The Iris video processing unit on Qualcomm SM8750 SoC is a video encode and + decode accelerator. + +properties: + compatible: + enum: + - qcom,sm8750-iris + + clocks: + maxItems: 6 + + clock-names: + items: + - const: iface # AXI0 + - const: core + - const: vcodec0_core + - const: iface1 # AXI1 + - const: core_freerun + - const: vcodec0_core_freerun + + dma-coherent: true + + interconnects: + maxItems: 2 + + interconnect-names: + items: + - const: cpu-cfg + - const: video-mem + + iommus: + maxItems: 2 + + operating-points-v2: true + opp-table: + type: object + + power-domains: + maxItems: 4 + + power-domain-names: + items: + - const: venus + - const: vcodec0 + - const: mxc + - const: mmcx + + resets: + maxItems: 4 + + reset-names: + items: + - const: bus0 + - const: bus1 + - const: core + - const: vcodec0_core + +required: + - compatible + - dma-coherent + - interconnects + - interconnect-names + - iommus + - power-domain-names + - resets + - reset-names + +allOf: + - $ref: qcom,venus-common.yaml# + +unevaluatedProperties: false + +examples: + - | + #include <dt-bindings/clock/qcom,rpmh.h> + #include <dt-bindings/clock/qcom,sm8750-gcc.h> + #include <dt-bindings/interrupt-controller/arm-gic.h> + #include <dt-bindings/interconnect/qcom,icc.h> + #include <dt-bindings/interconnect/qcom,sm8750-rpmh.h> + #include <dt-bindings/power/qcom-rpmpd.h> + #include <dt-bindings/power/qcom,rpmhpd.h> + + video-codec@aa00000 { + compatible = "qcom,sm8750-iris"; + reg = <0x0aa00000 0xf0000>; + + clocks = <&gcc GCC_VIDEO_AXI0_CLK>, + <&videocc_mvs0c_clk>, + <&videocc_mvs0_clk>, + <&gcc GCC_VIDEO_AXI1_CLK>, + <&videocc_mvs0c_freerun_clk>, + <&videocc_mvs0_freerun_clk>; + clock-names = "iface", + "core", + "vcodec0_core", + "iface1", + "core_freerun", + "vcodec0_core_freerun"; + + dma-coherent; + iommus = <&apps_smmu 0x1940 0>, + <&apps_smmu 0x1947 0>; + + interconnects = <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ACTIVE_ONLY + &config_noc SLAVE_VENUS_CFG QCOM_ICC_TAG_ACTIVE_ONLY>, + <&mmss_noc MASTER_VIDEO_MVP QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>; + interconnect-names = "cpu-cfg", + "video-mem"; + + interrupts = <GIC_SPI 174 IRQ_TYPE_LEVEL_HIGH>; + + operating-points-v2 = <&iris_opp_table>; + + memory-region = <&video_mem>; + + power-domains = <&videocc_mvs0c_gdsc>, + <&videocc_mvs0_gdsc>, + <&rpmhpd RPMHPD_MXC>, + <&rpmhpd RPMHPD_MMCX>; + power-domain-names = "venus", + "vcodec0", + "mxc", + "mmcx"; + + resets = <&gcc GCC_VIDEO_AXI0_CLK_ARES>, + <&gcc GCC_VIDEO_AXI1_CLK_ARES>, + <&videocc_mvs0c_freerun_clk_ares>, + <&videocc_mvs0_freerun_clk_ares>; + reset-names = "bus0", + "bus1", + "core", + "vcodec0_core"; + + iris_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-240000000 { + opp-hz = /bits/ 64 <240000000>; + required-opps = <&rpmhpd_opp_low_svs_d1>, + <&rpmhpd_opp_low_svs_d1>; + }; + + opp-338000000 { + opp-hz = /bits/ 64 <338000000>; + required-opps = <&rpmhpd_opp_low_svs>, + <&rpmhpd_opp_low_svs>; + }; + + opp-420000000 { + opp-hz = /bits/ 64 <420000000>; + required-opps = <&rpmhpd_opp_svs>, + <&rpmhpd_opp_svs>; + }; + + opp-444000000 { + opp-hz = /bits/ 64 <444000000>; + required-opps = <&rpmhpd_opp_svs_l1>, + <&rpmhpd_opp_svs_l1>; + }; + + opp-533333334 { + opp-hz = /bits/ 64 <533333334>; + required-opps = <&rpmhpd_opp_nom>, + <&rpmhpd_opp_nom>; + }; + + opp-630000000 { + opp-hz = /bits/ 64 <630000000>; + required-opps = <&rpmhpd_opp_turbo>, + <&rpmhpd_opp_turbo>; + }; + }; + }; diff --git a/Documentation/devicetree/bindings/media/rockchip-isp1.yaml b/Documentation/devicetree/bindings/media/rockchip-isp1.yaml index 6be00aca4181..477c21417e75 100644 --- a/Documentation/devicetree/bindings/media/rockchip-isp1.yaml +++ b/Documentation/devicetree/bindings/media/rockchip-isp1.yaml @@ -71,7 +71,16 @@ properties: const: dphy power-domains: - maxItems: 1 + minItems: 1 + items: + - description: ISP power domain + - description: MIPI CSI-2 power domain + + power-domain-names: + minItems: 1 + items: + - const: isp + - const: csi2 ports: $ref: /schemas/graph.yaml#/properties/ports @@ -155,14 +164,26 @@ allOf: const: fsl,imx8mp-isp then: properties: + clocks: + minItems: 4 + clock-names: + minItems: 4 iommus: false phys: false phy-names: false + power-domains: + minItems: 2 + power-domain-names: + minItems: 2 required: - fsl,blk-ctrl + - power-domain-names else: properties: fsl,blk-ctrl: false + power-domains: + maxItems: 1 + power-domain-names: false required: - iommus - phys diff --git a/Documentation/devicetree/bindings/media/samsung,exynos4212-fimc-is.yaml b/Documentation/devicetree/bindings/media/samsung,exynos4212-fimc-is.yaml index 3a5ff3f47060..71d63bb9abb5 100644 --- a/Documentation/devicetree/bindings/media/samsung,exynos4212-fimc-is.yaml +++ b/Documentation/devicetree/bindings/media/samsung,exynos4212-fimc-is.yaml @@ -209,9 +209,10 @@ examples: svdda-supply = <&cam_io_reg>; svddio-supply = <&ldo19_reg>; afvdd-supply = <&ldo19_reg>; - clock-frequency = <24000000>; clocks = <&camera 1>; clock-names = "extclk"; + assigned-clocks = <&camera 1>; + assigned-clock-rates = <24000000>; gpios = <&gpm1 6 GPIO_ACTIVE_LOW>; port { diff --git a/Documentation/devicetree/bindings/media/samsung,fimc.yaml b/Documentation/devicetree/bindings/media/samsung,fimc.yaml index 7808d61f1fa3..2a54379d9509 100644 --- a/Documentation/devicetree/bindings/media/samsung,fimc.yaml +++ b/Documentation/devicetree/bindings/media/samsung,fimc.yaml @@ -259,10 +259,11 @@ examples: svdda-supply = <&cam_io_reg>; svddio-supply = <&ldo19_reg>; afvdd-supply = <&ldo19_reg>; - clock-frequency = <24000000>; /* CAM_B_CLKOUT */ clocks = <&camera 1>; clock-names = "extclk"; + assigned-clocks = <&camera 1>; + assigned-clock-rates = <24000000>; gpios = <&gpm1 6 GPIO_ACTIVE_LOW>; port { diff --git a/Documentation/devicetree/bindings/media/silabs,si470x.yaml b/Documentation/devicetree/bindings/media/silabs,si470x.yaml index a3d19c562ca3..db22b88fc5bb 100644 --- a/Documentation/devicetree/bindings/media/silabs,si470x.yaml +++ b/Documentation/devicetree/bindings/media/silabs,si470x.yaml @@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml# title: Silicon Labs Si470x FM Radio Receiver maintainers: - - Hans Verkuil <hverkuil@xs4all.nl> + - Hans Verkuil <hverkuil@kernel.org> - Paweł Chmiel <pawel.mikolaj.chmiel@gmail.com> properties: diff --git a/Documentation/driver-api/media/camera-sensor.rst b/Documentation/driver-api/media/camera-sensor.rst index c290833165e6..94bd1dae82d5 100644 --- a/Documentation/driver-api/media/camera-sensor.rst +++ b/Documentation/driver-api/media/camera-sensor.rst @@ -29,21 +29,31 @@ used in the system. Using another frequency may cause harmful effects elsewhere. Therefore only the pre-determined frequencies are configurable by the user. +The external clock frequency shall be retrieved by obtaining the external clock +using the ``devm_v4l2_sensor_clk_get()`` helper function, and then getting its +frequency with ``clk_get_rate()``. Usage of the helper function guarantees +correct behaviour regardless of whether the sensor is integrated in a DT-based +or ACPI-based system. + ACPI ~~~~ -Read the ``clock-frequency`` _DSD property to denote the frequency. The driver -can rely on this frequency being used. +ACPI-based systems typically don't register the sensor external clock with the +kernel, but specify the external clock frequency in the ``clock-frequency`` +_DSD property. The ``devm_v4l2_sensor_clk_get()`` helper creates and returns a +fixed clock set at that rate. Devicetree ~~~~~~~~~~ -The preferred way to achieve this is using ``assigned-clocks``, -``assigned-clock-parents`` and ``assigned-clock-rates`` properties. See the -`clock device tree bindings +Devicetree-based systems declare the sensor external clock in the device tree +and reference it from the sensor node. The preferred way to select the external +clock frequency is to use the ``assigned-clocks``, ``assigned-clock-parents`` +and ``assigned-clock-rates`` properties in the sensor node to set the clock +rate. See the `clock device tree bindings <https://github.com/devicetree-org/dt-schema/blob/main/dtschema/schemas/clock/clock.yaml>`_ -for more information. The driver then gets the frequency using -``clk_get_rate()``. +for more information. The ``devm_v4l2_sensor_clk_get()`` helper retrieves and +returns that clock. 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 diff --git a/Documentation/driver-api/media/maintainer-entry-profile.rst b/Documentation/driver-api/media/maintainer-entry-profile.rst index ad96a89ee916..2127e5b15e8f 100644 --- a/Documentation/driver-api/media/maintainer-entry-profile.rst +++ b/Documentation/driver-api/media/maintainer-entry-profile.rst @@ -75,7 +75,7 @@ The media maintainers that work on specific areas of the subsystem are: Sean Young <sean@mess.org> - HDMI CEC: - Hans Verkuil <hverkuil@xs4all.nl> + Hans Verkuil <hverkuil@kernel.org> - Media controller drivers: Laurent Pinchart <laurent.pinchart@ideasonboard.com> @@ -84,7 +84,7 @@ The media maintainers that work on specific areas of the subsystem are: Sakari Ailus <sakari.ailus@linux.intel.com> - V4L2 drivers and core V4L2 frameworks: - Hans Verkuil <hverkuil@xs4all.nl> + Hans Verkuil <hverkuil@kernel.org> The subsystem maintainer is: Mauro Carvalho Chehab <mchehab@kernel.org> diff --git a/Documentation/driver-api/media/v4l2-fh.rst b/Documentation/driver-api/media/v4l2-fh.rst index 3eeaa8da0c9e..a934caa483a4 100644 --- a/Documentation/driver-api/media/v4l2-fh.rst +++ b/Documentation/driver-api/media/v4l2-fh.rst @@ -1,33 +1,27 @@ .. SPDX-License-Identifier: GPL-2.0 -V4L2 File handlers ------------------- +V4L2 File handles +----------------- -struct v4l2_fh provides a way to easily keep file handle specific -data that is used by the V4L2 framework. +struct v4l2_fh provides a way to easily keep file handle specific data that is +used by the V4L2 framework. Its usage is mandatory in all drivers. -.. attention:: - New drivers must use struct v4l2_fh - since it is also used to implement priority handling - (:ref:`VIDIOC_G_PRIORITY`). +struct v4l2_fh is allocated in the driver's ``open()`` file operation handler. +It is typically embedded in a larger driver-specific structure. The +:c:type:`v4l2_fh` must be initialized with a call to :c:func:`v4l2_fh_init`, +and added to the video device with :c:func:`v4l2_fh_add`. This associates the +:c:type:`v4l2_fh` with the :c:type:`file` by setting ``file->private_data`` to +point to the :c:type:`v4l2_fh`. -The users of :c:type:`v4l2_fh` (in the V4L2 framework, not the driver) know -whether a driver uses :c:type:`v4l2_fh` as its ``file->private_data`` pointer -by testing the ``V4L2_FL_USES_V4L2_FH`` bit in :c:type:`video_device`->flags. -This bit is set whenever :c:func:`v4l2_fh_init` is called. +Similarly, the struct v4l2_fh is freed in the driver's ``release()`` file +operation handler. It must be removed from the video device with +:c:func:`v4l2_fh_del` and cleaned up with :c:func:`v4l2_fh_exit` before being +freed. -struct v4l2_fh is allocated as a part of the driver's own file handle -structure and ``file->private_data`` is set to it in the driver's ``open()`` -function by the driver. - -In many cases the struct v4l2_fh will be embedded in a larger -structure. In that case you should call: - -#) :c:func:`v4l2_fh_init` and :c:func:`v4l2_fh_add` in ``open()`` -#) :c:func:`v4l2_fh_del` and :c:func:`v4l2_fh_exit` in ``release()`` - -Drivers can extract their own file handle structure by using the container_of -macro. +Drivers must not access ``file->private_data`` directly. They can retrieve the +:c:type:`v4l2_fh` associated with a :c:type:`file` by calling +:c:func:`file_to_v4l2_fh`. Drivers can extract their own file handle structure +by using the container_of macro. Example: @@ -56,18 +50,17 @@ Example: ... - file->private_data = &my_fh->fh; - v4l2_fh_add(&my_fh->fh); + v4l2_fh_add(&my_fh->fh, file); return 0; } int my_release(struct file *file) { - struct v4l2_fh *fh = file->private_data; + struct v4l2_fh *fh = file_to_v4l2_fh(file); struct my_fh *my_fh = container_of(fh, struct my_fh, fh); ... - v4l2_fh_del(&my_fh->fh); + v4l2_fh_del(&my_fh->fh, file); v4l2_fh_exit(&my_fh->fh); kfree(my_fh); return 0; @@ -78,19 +71,17 @@ Below is a short description of the :c:type:`v4l2_fh` functions used: :c:func:`v4l2_fh_init <v4l2_fh_init>` (:c:type:`fh <v4l2_fh>`, :c:type:`vdev <video_device>`) - - Initialise the file handle. This **MUST** be performed in the driver's :c:type:`v4l2_file_operations`->open() handler. - :c:func:`v4l2_fh_add <v4l2_fh_add>` -(:c:type:`fh <v4l2_fh>`) +(:c:type:`fh <v4l2_fh>`, struct file \*filp) - Add a :c:type:`v4l2_fh` to :c:type:`video_device` file handle list. Must be called once the file handle is completely initialized. :c:func:`v4l2_fh_del <v4l2_fh_del>` -(:c:type:`fh <v4l2_fh>`) +(:c:type:`fh <v4l2_fh>`, struct file \*filp) - Unassociate the file handle from :c:type:`video_device`. The file handle exit function may now be called. @@ -101,6 +92,10 @@ Below is a short description of the :c:type:`v4l2_fh` functions used: - Uninitialise the file handle. After uninitialisation the :c:type:`v4l2_fh` memory can be freed. +:c:func:`file_to_v4l2_fh <file_to_v4l2_fh>` +(struct file \*filp) + +- Retrieve the :c:type:`v4l2_fh` instance associated with a :c:type:`file`. If struct v4l2_fh is not embedded, then you can use these helper functions: diff --git a/Documentation/translations/zh_CN/admin-guide/bug-hunting.rst b/Documentation/translations/zh_CN/admin-guide/bug-hunting.rst index 4b3432753eb9..f20bf5be4cf9 100644 --- a/Documentation/translations/zh_CN/admin-guide/bug-hunting.rst +++ b/Documentation/translations/zh_CN/admin-guide/bug-hunting.rst @@ -239,7 +239,7 @@ objdump 例如,您在gspca的sonixj.c文件中发现一个缺陷,则可以通过以下方法找到它的维护者:: $ ./scripts/get_maintainer.pl -f drivers/media/usb/gspca/sonixj.c - Hans Verkuil <hverkuil@xs4all.nl> (odd fixer:GSPCA USB WEBCAM DRIVER,commit_signer:1/1=100%) + Hans Verkuil <hverkuil@kernel.org> (odd fixer:GSPCA USB WEBCAM DRIVER,commit_signer:1/1=100%) Mauro Carvalho Chehab <mchehab@kernel.org> (maintainer:MEDIA INPUT INFRASTRUCTURE (V4L/DVB),commit_signer:1/1=100%) Tejun Heo <tj@kernel.org> (commit_signer:1/1=100%) Bhaktipriya Shridhar <bhaktipriya96@gmail.com> (commit_signer:1/1=100%,authored:1/1=100%,added_lines:4/4=100%,removed_lines:9/9=100%) diff --git a/Documentation/translations/zh_CN/video4linux/v4l2-framework.txt b/Documentation/translations/zh_CN/video4linux/v4l2-framework.txt index 9cc97ec75d7a..f0be21a60a0f 100644 --- a/Documentation/translations/zh_CN/video4linux/v4l2-framework.txt +++ b/Documentation/translations/zh_CN/video4linux/v4l2-framework.txt @@ -775,11 +775,6 @@ v4l2_fh 结构体提供一个保存用于 V4L2 框架的文件句柄特定数据 如果 video_device 标志,新驱动 必须使用 v4l2_fh 结构体,因为它也用于实现优先级处理(VIDIOC_G/S_PRIORITY)。 -v4l2_fh 的用户(位于 V4l2 框架中,并非驱动)可通过测试 -video_device->flags 中的 V4L2_FL_USES_V4L2_FH 位得知驱动是否使用 -v4l2_fh 作为他的 file->private_data 指针。这个位会在调用 v4l2_fh_init() -时被设置。 - v4l2_fh 结构体作为驱动自身文件句柄结构体的一部分被分配,且驱动在 其打开函数中将 file->private_data 指向它。 @@ -812,18 +807,17 @@ int my_open(struct file *file) ... - file->private_data = &my_fh->fh; - v4l2_fh_add(&my_fh->fh); + v4l2_fh_add(&my_fh->fh, file); return 0; } int my_release(struct file *file) { - struct v4l2_fh *fh = file->private_data; + struct v4l2_fh *fh = file_to_v4l2_fh(file); struct my_fh *my_fh = container_of(fh, struct my_fh, fh); ... - v4l2_fh_del(&my_fh->fh); + v4l2_fh_del(&my_fh->fh, file); v4l2_fh_exit(&my_fh->fh); kfree(my_fh); return 0; @@ -836,12 +830,12 @@ void v4l2_fh_init(struct v4l2_fh *fh, struct video_device *vdev) 初始化文件句柄。这*必须*在驱动的 v4l2_file_operations->open() 函数中执行。 -void v4l2_fh_add(struct v4l2_fh *fh) +void v4l2_fh_add(struct v4l2_fh *fh, struct file *filp) 添加一个 v4l2_fh 到 video_device 文件句柄列表。一旦文件句柄 初始化完成就必须调用。 -void v4l2_fh_del(struct v4l2_fh *fh) +void v4l2_fh_del(struct v4l2_fh *fh, struct file *filp) 从 video_device() 中解除文件句柄的关联。文件句柄的退出函数也 将被调用。 diff --git a/Documentation/translations/zh_TW/admin-guide/bug-hunting.rst b/Documentation/translations/zh_TW/admin-guide/bug-hunting.rst index 80ea5677ee52..c677dff826f5 100644 --- a/Documentation/translations/zh_TW/admin-guide/bug-hunting.rst +++ b/Documentation/translations/zh_TW/admin-guide/bug-hunting.rst @@ -242,7 +242,7 @@ objdump 例如,您在gspca的sonixj.c文件中發現一個缺陷,則可以通過以下方法找到它的維護者:: $ ./scripts/get_maintainer.pl -f drivers/media/usb/gspca/sonixj.c - Hans Verkuil <hverkuil@xs4all.nl> (odd fixer:GSPCA USB WEBCAM DRIVER,commit_signer:1/1=100%) + Hans Verkuil <hverkuil@kernel.org> (odd fixer:GSPCA USB WEBCAM DRIVER,commit_signer:1/1=100%) Mauro Carvalho Chehab <mchehab@kernel.org> (maintainer:MEDIA INPUT INFRASTRUCTURE (V4L/DVB),commit_signer:1/1=100%) Tejun Heo <tj@kernel.org> (commit_signer:1/1=100%) Bhaktipriya Shridhar <bhaktipriya96@gmail.com> (commit_signer:1/1=100%,authored:1/1=100%,added_lines:4/4=100%,removed_lines:9/9=100%) diff --git a/Documentation/userspace-api/media/cec/cec-api.rst b/Documentation/userspace-api/media/cec/cec-api.rst index 578303d484f3..594f0ec420a2 100644 --- a/Documentation/userspace-api/media/cec/cec-api.rst +++ b/Documentation/userspace-api/media/cec/cec-api.rst @@ -26,7 +26,7 @@ Revision and Copyright ********************** Authors: -- Verkuil, Hans <hverkuil-cisco@xs4all.nl> +- Verkuil, Hans <hverkuil@kernel.org> - Initial version. diff --git a/Documentation/userspace-api/media/drivers/camera-sensor.rst b/Documentation/userspace-api/media/drivers/camera-sensor.rst index 919a50e8b9d9..75fd9166383f 100644 --- a/Documentation/userspace-api/media/drivers/camera-sensor.rst +++ b/Documentation/userspace-api/media/drivers/camera-sensor.rst @@ -10,11 +10,13 @@ used to control the camera sensor drivers. You may also find :ref:`media_writing_camera_sensor_drivers` useful. -Frame size ----------- +Sensor internal pipeline configuration +-------------------------------------- -There are two distinct ways to configure the frame size produced by camera -sensors. +Camera sensors have an internal processing pipeline including cropping and +binning functionality. The sensor drivers belong to two distinct classes, freely +configurable and register list-based drivers, depending on how the driver +configures this functionality. Freely configurable camera sensor drivers ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -26,10 +28,10 @@ of cropping and scaling operations from the device's pixel array's size. An example of such a driver is the CCS driver. -Register list based drivers +Register list-based drivers ~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Register list based drivers generally, instead of able to configure the device +Register list-based drivers generally, instead of able to configure the device they control based on user requests, are limited to a number of preset configurations that combine a number of different parameters that on hardware level are independent. How a driver picks such configuration is based on the @@ -67,7 +69,7 @@ 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 +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 device's internal processing pipeline. diff --git a/Documentation/userspace-api/media/drivers/cx2341x-uapi.rst b/Documentation/userspace-api/media/drivers/cx2341x-uapi.rst index debde65fb8cd..b617c988b915 100644 --- a/Documentation/userspace-api/media/drivers/cx2341x-uapi.rst +++ b/Documentation/userspace-api/media/drivers/cx2341x-uapi.rst @@ -130,7 +130,7 @@ Raw format c example Format of embedded V4L2_MPEG_STREAM_VBI_FMT_IVTV VBI data --------------------------------------------------------- -Author: Hans Verkuil <hverkuil@xs4all.nl> +Author: Hans Verkuil <hverkuil@kernel.org> This section describes the V4L2_MPEG_STREAM_VBI_FMT_IVTV format of the VBI data diff --git a/Documentation/userspace-api/media/dvb/fe-diseqc-send-burst.rst b/Documentation/userspace-api/media/dvb/fe-diseqc-send-burst.rst index 8fb73ee29951..6ac1e5cd50ce 100644 --- a/Documentation/userspace-api/media/dvb/fe-diseqc-send-burst.rst +++ b/Documentation/userspace-api/media/dvb/fe-diseqc-send-burst.rst @@ -26,7 +26,7 @@ Arguments File descriptor returned by :c:func:`open()`. ``tone`` - An integer enumered value described at :c:type:`fe_sec_mini_cmd`. + An integer enumerated value described at :c:type:`fe_sec_mini_cmd`. Description =========== diff --git a/Documentation/userspace-api/media/dvb/fe-set-tone.rst b/Documentation/userspace-api/media/dvb/fe-set-tone.rst index 9f44bf946183..41cd7111a243 100644 --- a/Documentation/userspace-api/media/dvb/fe-set-tone.rst +++ b/Documentation/userspace-api/media/dvb/fe-set-tone.rst @@ -26,7 +26,7 @@ Arguments File descriptor returned by :c:func:`open()`. ``tone`` - an integer enumered value described at :c:type:`fe_sec_tone_mode` + An integer enumerated value described at :c:type:`fe_sec_tone_mode` Description =========== diff --git a/Documentation/userspace-api/media/dvb/fe-set-voltage.rst b/Documentation/userspace-api/media/dvb/fe-set-voltage.rst index c66771830be1..4d09ca5876f0 100644 --- a/Documentation/userspace-api/media/dvb/fe-set-voltage.rst +++ b/Documentation/userspace-api/media/dvb/fe-set-voltage.rst @@ -26,7 +26,7 @@ Arguments File descriptor returned by :c:func:`open()`. ``voltage`` - an integer enumered value described at :c:type:`fe_sec_voltage` + An integer enumerated value described at :c:type:`fe_sec_voltage` Description =========== diff --git a/Documentation/userspace-api/media/dvb/fe_property_parameters.rst b/Documentation/userspace-api/media/dvb/fe_property_parameters.rst index 1717a0565fe8..ce962d4a02c0 100644 --- a/Documentation/userspace-api/media/dvb/fe_property_parameters.rst +++ b/Documentation/userspace-api/media/dvb/fe_property_parameters.rst @@ -72,11 +72,11 @@ DTV_MODULATION ============== Specifies the frontend modulation type for delivery systems that -supports more multiple modulations. +support multiple modulations. The modulation can be one of the types defined by enum :c:type:`fe_modulation`. -Most of the digital TV standards offers more than one possible +Most of the digital TV standards offer more than one possible modulation type. The table below presents a summary of the types of modulation types @@ -143,9 +143,8 @@ ISDB-T 5MHz, 6MHz, 7MHz and 8MHz, although most places (DTV_ISDBT_SB_SEGMENT_IDX, DTV_ISDBT_SB_SEGMENT_COUNT). #. On Satellite and Cable delivery systems, the bandwidth depends on - the symbol rate. So, the Kernel will silently ignore any setting - :ref:`DTV-BANDWIDTH-HZ`. I will however fill it back with a - bandwidth estimation. + the symbol rate. The kernel will silently ignore any :ref:`DTV-BANDWIDTH-HZ` + setting and overwrites it with bandwidth estimation. Such bandwidth estimation takes into account the symbol rate set with :ref:`DTV-SYMBOL-RATE`, and the rolloff factor, with is fixed for @@ -200,7 +199,7 @@ DTV_VOLTAGE Used on satellite delivery systems. The voltage is usually used with non-DiSEqC capable LNBs to switch the -polarzation (horizontal/vertical). When using DiSEqC epuipment this +polarization (horizontal/vertical). When using DiSEqC equipment this voltage has to be switched consistently to the DiSEqC commands as described in the DiSEqC spec. @@ -280,7 +279,7 @@ DTV_ISDBT_PARTIAL_RECEPTION Used only on ISDB. -If ``DTV_ISDBT_SOUND_BROADCASTING`` is '0' this bit-field represents +If ``DTV_ISDBT_SOUND_BROADCASTING`` is '0' this bit field represents whether the channel is in partial reception mode or not. If '1' ``DTV_ISDBT_LAYERA_*`` values are assigned to the center segment @@ -331,8 +330,8 @@ broadcaster has several possibilities to put those channels in the air: Assuming a normal 13-segment ISDB-T spectrum he can align the 8 segments from position 1-8 to 5-13 or anything in between. -The underlying layer of segments are subchannels: each segment is -consisting of several subchannels with a predefined IDs. A sub-channel +The underlying layer of segments are sub-channels: each segment is +consisting of several sub-channels with a predefined IDs. A sub-channel is used to help the demodulator to synchronize on the channel. An ISDB-T channel is always centered over all sub-channels. As for the @@ -728,7 +727,7 @@ DTV_ATSCMH_RS_FRAME_ENSEMBLE Used only on ATSC-MH. -Reed Solomon(RS) frame ensemble. +Reed Solomon (RS) frame ensemble. The acceptable values are defined by :c:type:`atscmh_rs_frame_ensemble`. @@ -954,14 +953,14 @@ DTV_ENUM_DELSYS A Multi standard frontend needs to advertise the delivery systems provided. Applications need to enumerate the provided delivery systems, -before using any other operation with the frontend. Prior to it's +before using any other operation with the frontend. Prior to its introduction, FE_GET_INFO was used to determine a frontend type. A frontend which provides more than a single delivery system, FE_GET_INFO doesn't help much. Applications which intends to use a multistandard frontend must enumerate the delivery systems associated with it, rather than trying to use FE_GET_INFO. In the case of a legacy frontend, the result is just the same as with FE_GET_INFO, but -in a more structured format +in a more structured format. The acceptable values are defined by :c:type:`fe_delivery_system`. diff --git a/Documentation/userspace-api/media/dvb/frontend-property-terrestrial-systems.rst b/Documentation/userspace-api/media/dvb/frontend-property-terrestrial-systems.rst index 8cd461ceeea7..8aad9ea817f2 100644 --- a/Documentation/userspace-api/media/dvb/frontend-property-terrestrial-systems.rst +++ b/Documentation/userspace-api/media/dvb/frontend-property-terrestrial-systems.rst @@ -52,7 +52,7 @@ DVB-T2 delivery system ====================== DVB-T2 support is currently in the early stages of development, so -expect that this section maygrow and become more detailed with time. +expect that this section may grow and become more detailed with time. The following parameters are valid for DVB-T2: diff --git a/Documentation/userspace-api/media/dvb/intro.rst b/Documentation/userspace-api/media/dvb/intro.rst index 6784ae79657c..854c2073e69a 100644 --- a/Documentation/userspace-api/media/dvb/intro.rst +++ b/Documentation/userspace-api/media/dvb/intro.rst @@ -1,6 +1,6 @@ .. SPDX-License-Identifier: GFDL-1.1-no-invariants-or-later -.. _dvb_introdution: +.. _dvb_introduction: ************ Introduction @@ -125,7 +125,7 @@ demux, CA and IP-over-DVB networking. The video and audio devices control the MPEG2 decoder hardware, the frontend device the tuner and the Digital TV demodulator. The demux device gives you control over the PES and section filters of the hardware. If the hardware does not support -filtering these filters can be implemented in software. Finally, the CA +filtering, these filters can be implemented in software. Finally, the CA device controls all the conditional access capabilities of the hardware. It can depend on the individual security requirements of the platform, if and how many of the CA functions are made available to the diff --git a/Documentation/userspace-api/media/dvb/legacy_dvb_audio.rst b/Documentation/userspace-api/media/dvb/legacy_dvb_audio.rst index b46fe2becd02..81b762ef17c4 100644 --- a/Documentation/userspace-api/media/dvb/legacy_dvb_audio.rst +++ b/Documentation/userspace-api/media/dvb/legacy_dvb_audio.rst @@ -195,7 +195,7 @@ Description ~~~~~~~~~~~ The audio channel selected via `AUDIO_CHANNEL_SELECT`_ is determined by -this values. +this value. ----- @@ -413,7 +413,7 @@ Constants - ``AUDIO_CAP_MP3`` - The hardware accepts MPEG-1 Audio Layer III. - Commomly known as .mp3. + Commonly known as .mp3. - .. diff --git a/Documentation/userspace-api/media/v4l/dev-subdev.rst b/Documentation/userspace-api/media/v4l/dev-subdev.rst index 161b43f1ce66..225a45fef994 100644 --- a/Documentation/userspace-api/media/v4l/dev-subdev.rst +++ b/Documentation/userspace-api/media/v4l/dev-subdev.rst @@ -509,7 +509,7 @@ source pads. .. _subdev-routing: Streams, multiplexed media pads and internal routing ----------------------------------------------------- +==================================================== Simple V4L2 sub-devices do not support multiple, unrelated video streams, and only a single stream can pass through a media link and a media pad. @@ -534,7 +534,7 @@ does not support streams, then only stream 0 of source end may be captured. There may be additional limitations specific to the sink device. Understanding streams -^^^^^^^^^^^^^^^^^^^^^ +--------------------- A stream is a stream of content (e.g. pixel data or metadata) flowing through the media pipeline from a source (e.g. a sensor) towards the final sink (e.g. a @@ -554,7 +554,7 @@ sub-device and a (pad, stream) pair. For sub-devices that do not support multiplexed streams the 'stream' field is always 0. Interaction between routes, streams, formats and selections -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +----------------------------------------------------------- The addition of streams to the V4L2 sub-device interface moves the sub-device formats and selections from pads to (pad, stream) pairs. Besides the @@ -573,7 +573,7 @@ are independent of similar configurations on other streams. This is subject to change in the future. Device types and routing setup -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +------------------------------ Different kinds of sub-devices have differing behaviour for route activation, depending on the hardware. In all cases, however, only routes that have the @@ -596,7 +596,7 @@ called on the sub-device. Such newly created routes have the device's default configuration for format and selection rectangles. Configuring streams -^^^^^^^^^^^^^^^^^^^ +------------------- The configuration of the streams is done individually for each sub-device and the validity of the streams between sub-devices is validated when the pipeline @@ -619,7 +619,7 @@ There are three steps in configuring the streams: :ref:`VIDIOC_SUBDEV_S_ROUTING <VIDIOC_SUBDEV_G_ROUTING>` ioctl. Multiplexed streams setup example -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +--------------------------------- A simple example of a multiplexed stream setup might be as follows: diff --git a/Documentation/userspace-api/media/v4l/metafmt-generic.rst b/Documentation/userspace-api/media/v4l/metafmt-generic.rst index 78ab56b21682..39d529c910a8 100644 --- a/Documentation/userspace-api/media/v4l/metafmt-generic.rst +++ b/Documentation/userspace-api/media/v4l/metafmt-generic.rst @@ -71,7 +71,7 @@ This format is little endian. **Byte Order Of V4L2_META_FMT_GENERIC_CSI2_10.** Each cell is one byte. "M" denotes a byte of metadata and "x" a byte of padding. -.. tabularcolumns:: |p{2.4cm}|p{1.2cm}|p{1.2cm}|p{1.2cm}|p{1.2cm}|p{.8cm}| +.. tabularcolumns:: |p{2.4cm}|p{1.2cm}|p{1.2cm}|p{1.2cm}|p{1.2cm}|p{1.8cm}| .. flat-table:: Sample 4x2 Metadata Frame :header-rows: 0 @@ -115,7 +115,7 @@ This format is little endian. **Byte Order Of V4L2_META_FMT_GENERIC_CSI2_12.** Each cell is one byte. "M" denotes a byte of metadata and "x" a byte of padding. -.. tabularcolumns:: |p{2.4cm}|p{1.2cm}|p{1.2cm}|p{1.2cm}|p{1.2cm}|p{.8cm}|p{.8cm}| +.. tabularcolumns:: |p{2.4cm}|p{1.2cm}|p{1.2cm}|p{1.8cm}|p{1.2cm}|p{1.2cm}|p{1.8cm}| .. flat-table:: Sample 4x2 Metadata Frame :header-rows: 0 @@ -156,7 +156,7 @@ This format is little endian. **Byte Order Of V4L2_META_FMT_GENERIC_CSI2_14.** Each cell is one byte. "M" denotes a byte of metadata and "x" a byte of padding. -.. tabularcolumns:: |p{2.4cm}|p{1.2cm}|p{1.2cm}|p{1.2cm}|p{1.2cm}|p{.8cm}|p{.8cm}|p{.8cm}| +.. tabularcolumns:: |p{2.4cm}|p{1.2cm}|p{1.2cm}|p{1.2cm}|p{1.2cm}|p{1.8cm}|p{1.8cm}|p{1.8cm}| .. flat-table:: Sample 4x2 Metadata Frame :header-rows: 0 @@ -252,7 +252,7 @@ This format is little endian. **Byte Order Of V4L2_META_FMT_GENERIC_CSI2_20.** Each cell is one byte. "M" denotes a byte of metadata and "x" a byte of padding. -.. tabularcolumns:: |p{2.4cm}|p{1.2cm}|p{.8cm}|p{1.2cm}|p{.8cm}|p{.8cm}|p{1.2cm}|p{.8cm}|p{1.2cm}|p{.8cm}|p{.8cm}| +.. tabularcolumns:: |p{2.4cm}|p{1.2cm}|p{1.2cm}|p{1.2cm}|p{1.2cm}|p{1.8cm}|p{1.2cm}|p{1.2cm}|p{1.2cm}|p{1.2cm}|p{1.8cm} .. flat-table:: Sample 4x2 Metadata Frame :header-rows: 0 diff --git a/Documentation/userspace-api/media/v4l/v4l2.rst b/Documentation/userspace-api/media/v4l/v4l2.rst index cf8ae56a008c..64fb264fb6c4 100644 --- a/Documentation/userspace-api/media/v4l/v4l2.rst +++ b/Documentation/userspace-api/media/v4l/v4l2.rst @@ -86,7 +86,7 @@ Authors, in alphabetical order: - Documented the fielded V4L2_MPEG_STREAM_VBI_FMT_IVTV MPEG stream embedded, sliced VBI data format in this specification. -- Verkuil, Hans <hverkuil@xs4all.nl> +- Verkuil, Hans <hverkuil@kernel.org> - Designed and documented the VIDIOC_LOG_STATUS ioctl, the extended control ioctls, major parts of the sliced VBI API, the MPEG encoder and decoder APIs and the DV Timings API. diff --git a/MAINTAINERS b/MAINTAINERS index a11caa4528eb..3a8e93fa8a52 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -717,7 +717,7 @@ S: Maintained F: drivers/scsi/aic7xxx/ AIMSLAB FM RADIO RECEIVER DRIVER -M: Hans Verkuil <hverkuil@xs4all.nl> +M: Hans Verkuil <hverkuil@kernel.org> L: linux-media@vger.kernel.org S: Maintained W: https://linuxtv.org @@ -1709,20 +1709,20 @@ F: Documentation/devicetree/bindings/media/i2c/adi,adv748x.yaml F: drivers/media/i2c/adv748x/* ANALOG DEVICES INC ADV7511 DRIVER -M: Hans Verkuil <hverkuil-cisco@xs4all.nl> +M: Hans Verkuil <hverkuil@kernel.org> L: linux-media@vger.kernel.org S: Maintained F: drivers/media/i2c/adv7511* ANALOG DEVICES INC ADV7604 DRIVER -M: Hans Verkuil <hverkuil-cisco@xs4all.nl> +M: Hans Verkuil <hverkuil@kernel.org> L: linux-media@vger.kernel.org S: Maintained F: Documentation/devicetree/bindings/media/i2c/adi,adv7604.yaml F: drivers/media/i2c/adv7604* ANALOG DEVICES INC ADV7842 DRIVER -M: Hans Verkuil <hverkuil-cisco@xs4all.nl> +M: Hans Verkuil <hverkuil@kernel.org> L: linux-media@vger.kernel.org S: Maintained F: drivers/media/i2c/adv7842* @@ -3477,7 +3477,7 @@ F: arch/arm/mach-berlin/ F: arch/arm64/boot/dts/synaptics/ ARM/TEGRA HDMI CEC SUBSYSTEM SUPPORT -M: Hans Verkuil <hverkuil-cisco@xs4all.nl> +M: Hans Verkuil <hverkuil@kernel.org> L: linux-tegra@vger.kernel.org L: linux-media@vger.kernel.org S: Maintained @@ -4178,7 +4178,7 @@ T: git git://linuxtv.org/media.git F: drivers/media/usb/dvb-usb-v2/az6007.c AZTECH FM RADIO RECEIVER DRIVER -M: Hans Verkuil <hverkuil@xs4all.nl> +M: Hans Verkuil <hverkuil@kernel.org> L: linux-media@vger.kernel.org S: Maintained W: https://linuxtv.org @@ -5404,6 +5404,7 @@ S: Maintained F: Documentation/devicetree/bindings/media/cdns,*.txt F: Documentation/devicetree/bindings/media/cdns,csi2rx.yaml F: drivers/media/platform/cadence/cdns-csi2* +F: include/media/cadence/cdns-csi2* CADENCE NAND DRIVER L: linux-mtd@lists.infradead.org @@ -5437,7 +5438,7 @@ F: drivers/usb/cdns3/ X: drivers/usb/cdns3/cdns3* CADET FM/AM RADIO RECEIVER DRIVER -M: Hans Verkuil <hverkuil@xs4all.nl> +M: Hans Verkuil <hverkuil@kernel.org> L: linux-media@vger.kernel.org S: Maintained W: https://linuxtv.org @@ -5630,7 +5631,7 @@ F: drivers/char/hw_random/cctrng.c F: drivers/char/hw_random/cctrng.h CEC FRAMEWORK -M: Hans Verkuil <hverkuil-cisco@xs4all.nl> +M: Hans Verkuil <hverkuil@kernel.org> L: linux-media@vger.kernel.org S: Supported W: http://linuxtv.org @@ -5647,7 +5648,7 @@ F: include/uapi/linux/cec-funcs.h F: include/uapi/linux/cec.h CEC GPIO DRIVER -M: Hans Verkuil <hverkuil-cisco@xs4all.nl> +M: Hans Verkuil <hverkuil@kernel.org> L: linux-media@vger.kernel.org S: Supported W: http://linuxtv.org @@ -6062,7 +6063,7 @@ S: Supported F: drivers/platform/x86/classmate-laptop.c COBALT MEDIA DRIVER -M: Hans Verkuil <hverkuil-cisco@xs4all.nl> +M: Hans Verkuil <hverkuil@kernel.org> L: linux-media@vger.kernel.org S: Supported W: https://linuxtv.org @@ -6588,7 +6589,7 @@ F: crypto/ansi_cprng.c F: crypto/rng.c CS3308 MEDIA DRIVER -M: Hans Verkuil <hverkuil@xs4all.nl> +M: Hans Verkuil <hverkuil@kernel.org> L: linux-media@vger.kernel.org S: Odd Fixes W: http://linuxtv.org @@ -6629,7 +6630,7 @@ F: drivers/media/pci/cx18/ F: include/uapi/linux/ivtv* CX2341X MPEG ENCODER HELPER MODULE -M: Hans Verkuil <hverkuil@xs4all.nl> +M: Hans Verkuil <hverkuil@kernel.org> L: linux-media@vger.kernel.org S: Maintained W: https://linuxtv.org @@ -8626,7 +8627,7 @@ T: git git://linuxtv.org/media.git F: drivers/media/radio/dsbr100.c DT3155 MEDIA DRIVER -M: Hans Verkuil <hverkuil@xs4all.nl> +M: Hans Verkuil <hverkuil@kernel.org> L: linux-media@vger.kernel.org S: Odd Fixes W: https://linuxtv.org @@ -9379,7 +9380,7 @@ F: tools/bootconfig/* F: tools/bootconfig/scripts/* EXTRON DA HD 4K PLUS CEC DRIVER -M: Hans Verkuil <hverkuil@xs4all.nl> +M: Hans Verkuil <hverkuil@kernel.org> L: linux-media@vger.kernel.org S: Maintained T: git git://linuxtv.org/media.git @@ -10253,6 +10254,12 @@ S: Maintained F: Documentation/devicetree/bindings/media/i2c/galaxycore,gc0308.yaml F: drivers/media/i2c/gc0308.c +GALAXYCORE GC0310 CAMERA SENSOR DRIVER +M: Hans de Goede <hansg@kernel.org> +L: linux-media@vger.kernel.org +S: Maintained +F: drivers/media/i2c/gc0310.c + GALAXYCORE GC05a2 CAMERA SENSOR DRIVER M: Zhi Mao <zhi.mao@mediatek.com> L: linux-media@vger.kernel.org @@ -10321,7 +10328,7 @@ S: Maintained F: drivers/crypto/gemini/ GEMTEK FM RADIO RECEIVER DRIVER -M: Hans Verkuil <hverkuil@xs4all.nl> +M: Hans Verkuil <hverkuil@kernel.org> L: linux-media@vger.kernel.org S: Maintained W: https://linuxtv.org @@ -10510,7 +10517,7 @@ F: drivers/gnss/ F: include/linux/gnss.h GO7007 MPEG CODEC -M: Hans Verkuil <hverkuil-cisco@xs4all.nl> +M: Hans Verkuil <hverkuil@kernel.org> L: linux-media@vger.kernel.org S: Maintained F: drivers/media/usb/go7007/ @@ -10770,7 +10777,7 @@ T: git git://linuxtv.org/media.git F: drivers/media/usb/gspca/m5602/ GSPCA PAC207 SONIXB SUBDRIVER -M: Hans Verkuil <hverkuil@xs4all.nl> +M: Hans Verkuil <hverkuil@kernel.org> L: linux-media@vger.kernel.org S: Odd Fixes T: git git://linuxtv.org/media.git @@ -10791,7 +10798,7 @@ T: git git://linuxtv.org/media.git F: drivers/media/usb/gspca/t613.c GSPCA USB WEBCAM DRIVER -M: Hans Verkuil <hverkuil@xs4all.nl> +M: Hans Verkuil <hverkuil@kernel.org> L: linux-media@vger.kernel.org S: Odd Fixes T: git git://linuxtv.org/media.git @@ -10908,7 +10915,7 @@ S: Maintained F: sound/parisc/harmony.* HDPVR USB VIDEO ENCODER DRIVER -M: Hans Verkuil <hverkuil@xs4all.nl> +M: Hans Verkuil <hverkuil@kernel.org> L: linux-media@vger.kernel.org S: Odd Fixes W: https://linuxtv.org @@ -12576,7 +12583,6 @@ F: drivers/media/pci/intel/ipu6/ INTEL IPU7 INPUT SYSTEM DRIVER M: Sakari Ailus <sakari.ailus@linux.intel.com> R: Bingbu Cao <bingbu.cao@intel.com> -R: Stanislaw Gruszka <stanislaw.gruszka@linux.intel.com> L: linux-media@vger.kernel.org S: Maintained T: git git://linuxtv.org/media.git @@ -12872,7 +12878,6 @@ INTEL VISION SENSING CONTROLLER DRIVER M: Sakari Ailus <sakari.ailus@linux.intel.com> R: Bingbu Cao <bingbu.cao@intel.com> R: Lixu Zhang <lixu.zhang@intel.com> -R: Stanislaw Gruszka <stanislaw.gruszka@linux.intel.com> L: linux-media@vger.kernel.org S: Maintained T: git git://linuxtv.org/media.git @@ -13119,7 +13124,7 @@ F: drivers/base/isa.c F: include/linux/isa.h ISA RADIO MODULE -M: Hans Verkuil <hverkuil@xs4all.nl> +M: Hans Verkuil <hverkuil@kernel.org> L: linux-media@vger.kernel.org S: Maintained W: https://linuxtv.org @@ -13295,7 +13300,7 @@ F: fs/jbd2/ F: include/linux/jbd2.h JPU V4L2 MEM2MEM DRIVER FOR RENESAS -M: Mikhail Ulyanov <mikhail.ulyanov@cogentembedded.com> +M: Nikita Yushchenko <nikita.yoush@cogentembedded.com> L: linux-media@vger.kernel.org L: linux-renesas-soc@vger.kernel.org S: Maintained @@ -13391,7 +13396,7 @@ F: include/uapi/linux/vmcore.h F: kernel/crash_*.c KEENE FM RADIO TRANSMITTER DRIVER -M: Hans Verkuil <hverkuil@xs4all.nl> +M: Hans Verkuil <hverkuil@kernel.org> L: linux-media@vger.kernel.org S: Maintained W: https://linuxtv.org @@ -15293,7 +15298,7 @@ F: include/linux/mfd/max77693*.h F: include/linux/mfd/max77705*.h MAXIRADIO FM RADIO RECEIVER DRIVER -M: Hans Verkuil <hverkuil@xs4all.nl> +M: Hans Verkuil <hverkuil@kernel.org> L: linux-media@vger.kernel.org S: Maintained W: https://linuxtv.org @@ -17225,7 +17230,7 @@ F: drivers/irqchip/irq-loongson* F: drivers/platform/mips/cpu_hwmon.c MIROSOUND PCM20 FM RADIO RECEIVER DRIVER -M: Hans Verkuil <hverkuil@xs4all.nl> +M: Hans Verkuil <hverkuil@kernel.org> L: linux-media@vger.kernel.org S: Odd Fixes W: https://linuxtv.org @@ -17492,7 +17497,6 @@ S: Maintained T: git git://linuxtv.org/media.git F: Documentation/devicetree/bindings/media/i2c/aptina,mt9v032.txt F: drivers/media/i2c/mt9v032.c -F: include/media/i2c/mt9v032.h MT9V111 APTINA CAMERA SENSOR M: Jacopo Mondi <jacopo@jmondi.org> @@ -18825,6 +18829,14 @@ S: Maintained F: Documentation/devicetree/bindings/media/i2c/ovti,og01a1b.yaml F: drivers/media/i2c/og01a1b.c +OMNIVISION OG0VE1B SENSOR DRIVER +M: Vladimir Zapolskiy <vladimir.zapolskiy@linaro.org> +L: linux-media@vger.kernel.org +S: Maintained +T: git git://linuxtv.org/media_tree.git +F: Documentation/devicetree/bindings/media/i2c/ovti,og0ve1b.yaml +F: drivers/media/i2c/og0ve1b.c + OMNIVISION OV01A10 SENSOR DRIVER M: Bingbu Cao <bingbu.cao@intel.com> L: linux-media@vger.kernel.org @@ -18902,6 +18914,14 @@ T: git git://linuxtv.org/media.git F: Documentation/devicetree/bindings/media/i2c/ovti,ov2685.yaml F: drivers/media/i2c/ov2685.c +OMNIVISION OV2735 SENSOR DRIVER +M: Hardevsinh Palaniya <hardevsinh.palaniya@siliconsignals.io> +M: Himanshu Bhavani <himanshu.bhavani@siliconsignals.io> +L: linux-media@vger.kernel.org +S: Maintained +F: Documentation/devicetree/bindings/media/i2c/ovti,ov2735.yaml +F: drivers/media/i2c/ov2735.c + OMNIVISION OV2740 SENSOR DRIVER M: Tianshu Qiu <tian.shu.qiu@intel.com> R: Sakari Ailus <sakari.ailus@linux.intel.com> @@ -18966,6 +18986,14 @@ S: Maintained T: git git://linuxtv.org/media.git F: drivers/media/i2c/ov5695.c +OMNIVISION OV6211 SENSOR DRIVER +M: Vladimir Zapolskiy <vladimir.zapolskiy@linaro.org> +L: linux-media@vger.kernel.org +S: Maintained +T: git git://linuxtv.org/media_tree.git +F: Documentation/devicetree/bindings/media/i2c/ovti,ov6211.yaml +F: drivers/media/i2c/ov6211.c + OMNIVISION OV64A40 SENSOR DRIVER M: Jacopo Mondi <jacopo.mondi@ideasonboard.com> L: linux-media@vger.kernel.org @@ -20579,7 +20607,7 @@ F: include/uapi/linux/ptrace.h F: kernel/ptrace.c PULSE8-CEC DRIVER -M: Hans Verkuil <hverkuil@xs4all.nl> +M: Hans Verkuil <hverkuil@kernel.org> L: linux-media@vger.kernel.org S: Maintained T: git git://linuxtv.org/media.git @@ -20602,7 +20630,7 @@ F: Documentation/driver-api/media/drivers/pvrusb2* F: drivers/media/usb/pvrusb2/ PWC WEBCAM DRIVER -M: Hans Verkuil <hverkuil@xs4all.nl> +M: Hans Verkuil <hverkuil@kernel.org> L: linux-media@vger.kernel.org S: Odd Fixes T: git git://linuxtv.org/media.git @@ -21060,10 +21088,9 @@ F: Documentation/devicetree/bindings/regulator/vqmmc-ipq4019-regulator.yaml F: drivers/regulator/vqmmc-ipq4019-regulator.c QUALCOMM IRIS VIDEO ACCELERATOR DRIVER -M: Vikash Garodia <quic_vgarodia@quicinc.com> -M: Dikshita Agarwal <quic_dikshita@quicinc.com> +M: Vikash Garodia <vikash.garodia@oss.qualcomm.com> +M: Dikshita Agarwal <dikshita.agarwal@oss.qualcomm.com> R: Abhinav Kumar <abhinav.kumar@linux.dev> -R: Bryan O'Donoghue <bryan.odonoghue@linaro.org> L: linux-media@vger.kernel.org L: linux-arm-msm@vger.kernel.org S: Maintained @@ -21078,6 +21105,17 @@ S: Maintained F: Documentation/devicetree/bindings/mtd/qcom,nandc.yaml F: drivers/mtd/nand/raw/qcom_nandc.c +QUALCOMM MEDIA PLATFORM +M: Bryan O'Donoghue <bod@kernel.org> +L: linux-media@vger.kernel.org +L: linux-arm-msm@vger.kernel.org +S: Supported +Q: https://patchwork.linuxtv.org/project/linux-media/list +T: git https://gitlab.freedesktop.org/linux-media/media-committers.git +F: Documentation/devicetree/bindings/media/*qcom* +F: drivers/media/platform/qcom +F: include/dt-bindings/media/*qcom* + QUALCOMM SMB CHARGER DRIVER M: Casey Connolly <casey.connolly@linaro.org> L: linux-arm-msm@vger.kernel.org @@ -21139,9 +21177,8 @@ F: Documentation/devicetree/bindings/usb/qcom,pmic-*.yaml F: drivers/usb/typec/tcpm/qcom/ QUALCOMM VENUS VIDEO ACCELERATOR DRIVER -M: Vikash Garodia <quic_vgarodia@quicinc.com> -M: Dikshita Agarwal <quic_dikshita@quicinc.com> -R: Bryan O'Donoghue <bryan.odonoghue@linaro.org> +M: Vikash Garodia <vikash.garodia@oss.qualcomm.com> +M: Dikshita Agarwal <dikshita.agarwal@oss.qualcomm.com> L: linux-media@vger.kernel.org L: linux-arm-msm@vger.kernel.org S: Maintained @@ -21186,14 +21223,14 @@ F: drivers/video/fbdev/aty/radeon* F: include/uapi/linux/radeonfb.h RADIOSHARK RADIO DRIVER -M: Hans Verkuil <hverkuil@xs4all.nl> +M: Hans Verkuil <hverkuil@kernel.org> L: linux-media@vger.kernel.org S: Maintained T: git git://linuxtv.org/media.git F: drivers/media/radio/radio-shark.c RADIOSHARK2 RADIO DRIVER -M: Hans Verkuil <hverkuil@xs4all.nl> +M: Hans Verkuil <hverkuil@kernel.org> L: linux-media@vger.kernel.org S: Maintained T: git git://linuxtv.org/media.git @@ -21217,7 +21254,7 @@ S: Orphan F: drivers/video/fbdev/aty/aty128fb.c RAINSHADOW-CEC DRIVER -M: Hans Verkuil <hverkuil@xs4all.nl> +M: Hans Verkuil <hverkuil@kernel.org> L: linux-media@vger.kernel.org S: Maintained T: git git://linuxtv.org/media.git @@ -22080,6 +22117,7 @@ F: drivers/media/platform/rockchip/rga/ ROCKCHIP RKVDEC VIDEO DECODER DRIVER M: Detlev Casanova <detlev.casanova@collabora.com> +M: Ezequiel Garcia <ezequiel@vanguardiasur.com.ar> L: linux-media@vger.kernel.org L: linux-rockchip@lists.infradead.org S: Maintained @@ -22100,14 +22138,6 @@ S: Maintained F: Documentation/devicetree/bindings/sound/rockchip,rk3576-sai.yaml F: sound/soc/rockchip/rockchip_sai.* -ROCKCHIP VIDEO DECODER DRIVER -M: Ezequiel Garcia <ezequiel@vanguardiasur.com.ar> -L: linux-media@vger.kernel.org -L: linux-rockchip@lists.infradead.org -S: Maintained -F: Documentation/devicetree/bindings/media/rockchip,vdec.yaml -F: drivers/staging/media/rkvdec/ - ROCKER DRIVER M: Jiri Pirko <jiri@resnulli.us> L: netdev@vger.kernel.org @@ -22527,7 +22557,7 @@ S: Supported F: drivers/s390/scsi/zfcp_* SAA6588 RDS RECEIVER DRIVER -M: Hans Verkuil <hverkuil@xs4all.nl> +M: Hans Verkuil <hverkuil@kernel.org> L: linux-media@vger.kernel.org S: Odd Fixes W: https://linuxtv.org @@ -22544,7 +22574,7 @@ F: Documentation/driver-api/media/drivers/saa7134* F: drivers/media/pci/saa7134/ SAA7146 VIDEO4LINUX-2 DRIVER -M: Hans Verkuil <hverkuil@xs4all.nl> +M: Hans Verkuil <hverkuil@kernel.org> L: linux-media@vger.kernel.org S: Maintained T: git git://linuxtv.org/media.git @@ -23270,7 +23300,7 @@ Q: http://patchwork.linuxtv.org/project/linux-media/list/ F: drivers/media/dvb-frontends/si2168* SI470X FM RADIO RECEIVER I2C DRIVER -M: Hans Verkuil <hverkuil@xs4all.nl> +M: Hans Verkuil <hverkuil@kernel.org> L: linux-media@vger.kernel.org S: Odd Fixes W: https://linuxtv.org @@ -23279,7 +23309,7 @@ F: Documentation/devicetree/bindings/media/silabs,si470x.yaml F: drivers/media/radio/si470x/radio-si470x-i2c.c SI470X FM RADIO RECEIVER USB DRIVER -M: Hans Verkuil <hverkuil@xs4all.nl> +M: Hans Verkuil <hverkuil@kernel.org> L: linux-media@vger.kernel.org S: Maintained W: https://linuxtv.org @@ -23305,7 +23335,7 @@ T: git git://linuxtv.org/media.git F: drivers/media/radio/si4713/radio-platform-si4713.c SI4713 FM RADIO TRANSMITTER USB DRIVER -M: Hans Verkuil <hverkuil@xs4all.nl> +M: Hans Verkuil <hverkuil@kernel.org> L: linux-media@vger.kernel.org S: Maintained W: https://linuxtv.org @@ -24942,7 +24972,7 @@ T: git git://linuxtv.org/mkrufky/tuners.git F: drivers/media/tuners/tda8290.* TDA9840 MEDIA DRIVER -M: Hans Verkuil <hverkuil@xs4all.nl> +M: Hans Verkuil <hverkuil@kernel.org> L: linux-media@vger.kernel.org S: Maintained W: https://linuxtv.org @@ -24966,7 +24996,7 @@ T: git git://linuxtv.org/media.git F: drivers/media/tuners/tea5767.* TEA6415C MEDIA DRIVER -M: Hans Verkuil <hverkuil@xs4all.nl> +M: Hans Verkuil <hverkuil@kernel.org> L: linux-media@vger.kernel.org S: Maintained W: https://linuxtv.org @@ -24974,7 +25004,7 @@ T: git git://linuxtv.org/media.git F: drivers/media/i2c/tea6415c* TEA6420 MEDIA DRIVER -M: Hans Verkuil <hverkuil@xs4all.nl> +M: Hans Verkuil <hverkuil@kernel.org> L: linux-media@vger.kernel.org S: Maintained W: https://linuxtv.org @@ -25283,7 +25313,7 @@ F: Documentation/devicetree/bindings/iio/temperature/ti,tmp117.yaml F: drivers/iio/temperature/tmp117.c THANKO'S RAREMONO AM/FM/SW RADIO RECEIVER USB DRIVER -M: Hans Verkuil <hverkuil@xs4all.nl> +M: Hans Verkuil <hverkuil@kernel.org> L: linux-media@vger.kernel.org S: Maintained W: https://linuxtv.org @@ -25631,7 +25661,7 @@ S: Maintained F: sound/soc/codecs/twl4030* TI VPE/CAL DRIVERS -M: Benoit Parrot <bparrot@ti.com> +M: Yemike Abhilash Chandra <y-abhilashchandra@ti.com> L: linux-media@vger.kernel.org S: Maintained W: http://linuxtv.org/ @@ -25780,7 +25810,7 @@ F: include/linux/toshiba.h F: include/uapi/linux/toshiba.h TOSHIBA TC358743 DRIVER -M: Hans Verkuil <hverkuil-cisco@xs4all.nl> +M: Hans Verkuil <hverkuil@kernel.org> L: linux-media@vger.kernel.org S: Maintained F: Documentation/devicetree/bindings/media/i2c/toshiba,tc358743.txt @@ -25989,7 +26019,7 @@ S: Supported F: drivers/media/pci/tw5864/ TW68 VIDEO4LINUX DRIVER -M: Hans Verkuil <hverkuil@xs4all.nl> +M: Hans Verkuil <hverkuil@kernel.org> L: linux-media@vger.kernel.org S: Odd Fixes W: https://linuxtv.org @@ -26792,7 +26822,7 @@ S: Maintained F: drivers/net/ethernet/via/via-velocity.* VICODEC VIRTUAL CODEC DRIVER -M: Hans Verkuil <hverkuil-cisco@xs4all.nl> +M: Hans Verkuil <hverkuil@kernel.org> L: linux-media@vger.kernel.org S: Maintained W: https://linuxtv.org @@ -27104,7 +27134,7 @@ S: Supported F: drivers/media/test-drivers/visl VIVID VIRTUAL VIDEO DRIVER -M: Hans Verkuil <hverkuil@xs4all.nl> +M: Hans Verkuil <hverkuil@kernel.org> L: linux-media@vger.kernel.org S: Maintained W: https://linuxtv.org diff --git a/drivers/gpu/drm/display/drm_dp_cec.c b/drivers/gpu/drm/display/drm_dp_cec.c index 3b50d817c839..436bfe9f9081 100644 --- a/drivers/gpu/drm/display/drm_dp_cec.c +++ b/drivers/gpu/drm/display/drm_dp_cec.c @@ -42,7 +42,7 @@ * * https://hverkuil.home.xs4all.nl/cec-status.txt * - * Please mail me (hverkuil@xs4all.nl) if you find an adapter that works + * Please mail me (hverkuil@kernel.org) if you find an adapter that works * and is not yet listed there. * * Note that the current implementation does not support CEC over an MST hub. diff --git a/drivers/media/cec/core/cec-core.c b/drivers/media/cec/core/cec-core.c index e10bd588a586..d7259599029f 100644 --- a/drivers/media/cec/core/cec-core.c +++ b/drivers/media/cec/core/cec-core.c @@ -439,6 +439,6 @@ static void __exit cec_devnode_exit(void) subsys_initcall(cec_devnode_init); module_exit(cec_devnode_exit) -MODULE_AUTHOR("Hans Verkuil <hansverk@cisco.com>"); +MODULE_AUTHOR("Hans Verkuil <hverkuil@kernel.org>"); MODULE_DESCRIPTION("Device node registration for cec drivers"); MODULE_LICENSE("GPL"); diff --git a/drivers/media/cec/platform/cec-gpio/cec-gpio.c b/drivers/media/cec/platform/cec-gpio/cec-gpio.c index 3c27789d8657..842555ed42c7 100644 --- a/drivers/media/cec/platform/cec-gpio/cec-gpio.c +++ b/drivers/media/cec/platform/cec-gpio/cec-gpio.c @@ -291,6 +291,6 @@ static struct platform_driver cec_gpio_pdrv = { module_platform_driver(cec_gpio_pdrv); -MODULE_AUTHOR("Hans Verkuil <hansverk@cisco.com>"); +MODULE_AUTHOR("Hans Verkuil <hverkuil@kernel.org>"); MODULE_LICENSE("GPL v2"); MODULE_DESCRIPTION("CEC GPIO driver"); diff --git a/drivers/media/cec/platform/stm32/stm32-cec.c b/drivers/media/cec/platform/stm32/stm32-cec.c index fea2d65acffc..1ec0cece0a5b 100644 --- a/drivers/media/cec/platform/stm32/stm32-cec.c +++ b/drivers/media/cec/platform/stm32/stm32-cec.c @@ -248,7 +248,6 @@ static const struct regmap_config stm32_cec_regmap_cfg = { .val_bits = 32, .reg_stride = sizeof(u32), .max_register = 0x14, - .fast_io = true, }; static int stm32_cec_probe(struct platform_device *pdev) diff --git a/drivers/media/cec/usb/extron-da-hd-4k-plus/Makefile b/drivers/media/cec/usb/extron-da-hd-4k-plus/Makefile index 2e8f7f60263f..08d58524419f 100644 --- a/drivers/media/cec/usb/extron-da-hd-4k-plus/Makefile +++ b/drivers/media/cec/usb/extron-da-hd-4k-plus/Makefile @@ -1,8 +1,2 @@ extron-da-hd-4k-plus-cec-objs := extron-da-hd-4k-plus.o cec-splitter.o obj-$(CONFIG_USB_EXTRON_DA_HD_4K_PLUS_CEC) := extron-da-hd-4k-plus-cec.o - -all: - $(MAKE) -C $(KDIR) M=$(shell pwd) modules - -install: - $(MAKE) -C $(KDIR) M=$(shell pwd) modules_install diff --git a/drivers/media/cec/usb/extron-da-hd-4k-plus/extron-da-hd-4k-plus.c b/drivers/media/cec/usb/extron-da-hd-4k-plus/extron-da-hd-4k-plus.c index 41d019b01ec0..e2eff17952ab 100644 --- a/drivers/media/cec/usb/extron-da-hd-4k-plus/extron-da-hd-4k-plus.c +++ b/drivers/media/cec/usb/extron-da-hd-4k-plus/extron-da-hd-4k-plus.c @@ -28,7 +28,7 @@ #include "extron-da-hd-4k-plus.h" -MODULE_AUTHOR("Hans Verkuil <hansverk@cisco.com>"); +MODULE_AUTHOR("Hans Verkuil <hverkuil@kernel.org>"); MODULE_DESCRIPTION("Extron DA HD 4K PLUS HDMI CEC driver"); MODULE_LICENSE("GPL"); @@ -1252,7 +1252,7 @@ static int extron_s_output(struct file *file, void *priv, unsigned int o) return o ? -EINVAL : 0; } -static int extron_g_edid(struct file *file, void *_fh, +static int extron_g_edid(struct file *file, void *priv, struct v4l2_edid *edid) { struct extron_port *port = video_drvdata(file); @@ -1280,7 +1280,7 @@ static int extron_g_edid(struct file *file, void *_fh, return 0; } -static int extron_s_edid(struct file *file, void *_fh, struct v4l2_edid *edid) +static int extron_s_edid(struct file *file, void *priv, struct v4l2_edid *edid) { struct extron_port *port = video_drvdata(file); diff --git a/drivers/media/cec/usb/pulse8/pulse8-cec.c b/drivers/media/cec/usb/pulse8/pulse8-cec.c index 171366fe3544..60569f1670fe 100644 --- a/drivers/media/cec/usb/pulse8/pulse8-cec.c +++ b/drivers/media/cec/usb/pulse8/pulse8-cec.c @@ -2,7 +2,7 @@ /* * Pulse Eight HDMI CEC driver * - * Copyright 2016 Hans Verkuil <hverkuil@xs4all.nl + * Copyright 2016 Hans Verkuil <hverkuil@kernel.org> */ /* @@ -41,7 +41,7 @@ #include <media/cec.h> -MODULE_AUTHOR("Hans Verkuil <hverkuil@xs4all.nl>"); +MODULE_AUTHOR("Hans Verkuil <hverkuil@kernel.org>"); MODULE_DESCRIPTION("Pulse Eight HDMI CEC driver"); MODULE_LICENSE("GPL"); diff --git a/drivers/media/cec/usb/rainshadow/rainshadow-cec.c b/drivers/media/cec/usb/rainshadow/rainshadow-cec.c index 6f8d6797c614..08f58456d682 100644 --- a/drivers/media/cec/usb/rainshadow/rainshadow-cec.c +++ b/drivers/media/cec/usb/rainshadow/rainshadow-cec.c @@ -2,7 +2,7 @@ /* * RainShadow Tech HDMI CEC driver * - * Copyright 2016 Hans Verkuil <hverkuil@xs4all.nl + * Copyright 2016 Hans Verkuil <hverkuil@kernel.org> */ /* @@ -31,7 +31,7 @@ #include <media/cec.h> -MODULE_AUTHOR("Hans Verkuil <hverkuil@xs4all.nl>"); +MODULE_AUTHOR("Hans Verkuil <hverkuil@kernel.org>"); MODULE_DESCRIPTION("RainShadow Tech HDMI CEC driver"); MODULE_LICENSE("GPL"); diff --git a/drivers/media/common/b2c2/flexcop-sram.c b/drivers/media/common/b2c2/flexcop-sram.c index d97962eb0112..dba03769f263 100644 --- a/drivers/media/common/b2c2/flexcop-sram.c +++ b/drivers/media/common/b2c2/flexcop-sram.c @@ -352,7 +352,7 @@ static int flexcop_sram_detect(struct flexcop_device *fc) sram_set_size(adapter, 0x10000); sram_init(adapter); write_reg_dw(adapter, 0x208, tmp); - dprintk("%s: SRAM detection failed. Set to 32K \n", __func__); + dprintk("%s: SRAM detection failed. Set to 32K\n", __func__); return 0; } diff --git a/drivers/media/common/b2c2/flexcop.c b/drivers/media/common/b2c2/flexcop.c index e7a88a2d248c..8506de48ba45 100644 --- a/drivers/media/common/b2c2/flexcop.c +++ b/drivers/media/common/b2c2/flexcop.c @@ -170,7 +170,7 @@ static void flexcop_reset(struct flexcop_device *fc) flexcop_ibi_value v210, v204; /* reset the flexcop itself */ - fc->write_ibi_reg(fc,ctrl_208,ibi_zero); + fc->write_ibi_reg(fc, ctrl_208, ibi_zero); v210.raw = 0; v210.sw_reset_210.reset_block_000 = 1; @@ -183,17 +183,17 @@ static void flexcop_reset(struct flexcop_device *fc) v210.sw_reset_210.reset_block_700 = 1; v210.sw_reset_210.Block_reset_enable = 0xb2; v210.sw_reset_210.Special_controls = 0xc259; - fc->write_ibi_reg(fc,sw_reset_210,v210); + fc->write_ibi_reg(fc, sw_reset_210, v210); msleep(1); /* reset the periphical devices */ - v204 = fc->read_ibi_reg(fc,misc_204); + v204 = fc->read_ibi_reg(fc, misc_204); v204.misc_204.Per_reset_sig = 0; - fc->write_ibi_reg(fc,misc_204,v204); + fc->write_ibi_reg(fc, misc_204, v204); msleep(1); v204.misc_204.Per_reset_sig = 1; - fc->write_ibi_reg(fc,misc_204,v204); + fc->write_ibi_reg(fc, misc_204, v204); } void flexcop_reset_block_300(struct flexcop_device *fc) @@ -202,13 +202,13 @@ void flexcop_reset_block_300(struct flexcop_device *fc) v210 = fc->read_ibi_reg(fc, sw_reset_210); deb_rdump("208: %08x, 210: %08x\n", v208_save.raw, v210.raw); - fc->write_ibi_reg(fc,ctrl_208,ibi_zero); + fc->write_ibi_reg(fc, ctrl_208, ibi_zero); v210.sw_reset_210.reset_block_300 = 1; v210.sw_reset_210.Block_reset_enable = 0xb2; - fc->write_ibi_reg(fc,sw_reset_210,v210); - fc->write_ibi_reg(fc,ctrl_208,v208_save); + fc->write_ibi_reg(fc, sw_reset_210, v210); + fc->write_ibi_reg(fc, ctrl_208, v208_save); } struct flexcop_device *flexcop_device_kmalloc(size_t bus_specific_len) @@ -266,8 +266,8 @@ int flexcop_device_initialize(struct flexcop_device *fc) if (fc->get_mac_addr(fc, 0) == 0) { u8 *b = fc->dvb_adapter.proposed_mac; info("MAC address = %pM", b); - flexcop_set_mac_filter(fc,b); - flexcop_mac_filter_ctrl(fc,1); + flexcop_set_mac_filter(fc, b); + flexcop_mac_filter_ctrl(fc, 1); } else warn("reading of MAC address failed.\n"); @@ -275,7 +275,7 @@ int flexcop_device_initialize(struct flexcop_device *fc) if (ret) goto error; - flexcop_device_name(fc,"initialization of","complete"); + flexcop_device_name(fc, "initialization of", "complete"); return 0; error: diff --git a/drivers/media/common/cx2341x.c b/drivers/media/common/cx2341x.c index 1392bd6b0026..1ee159ef7f38 100644 --- a/drivers/media/common/cx2341x.c +++ b/drivers/media/common/cx2341x.c @@ -2,7 +2,7 @@ /* * cx2341x - generic code for cx23415/6/8 based devices * - * Copyright (C) 2006 Hans Verkuil <hverkuil@xs4all.nl> + * Copyright (C) 2006 Hans Verkuil <hverkuil@kernel.org> */ diff --git a/drivers/media/common/videobuf2/videobuf2-v4l2.c b/drivers/media/common/videobuf2/videobuf2-v4l2.c index 1cd26faee503..d911021c1bb0 100644 --- a/drivers/media/common/videobuf2/videobuf2-v4l2.c +++ b/drivers/media/common/videobuf2/videobuf2-v4l2.c @@ -973,18 +973,14 @@ EXPORT_SYMBOL_GPL(vb2_queue_change_type); __poll_t vb2_poll(struct vb2_queue *q, struct file *file, poll_table *wait) { - struct video_device *vfd = video_devdata(file); + struct v4l2_fh *fh = file_to_v4l2_fh(file); __poll_t res; res = vb2_core_poll(q, file, wait); - if (test_bit(V4L2_FL_USES_V4L2_FH, &vfd->flags)) { - struct v4l2_fh *fh = file->private_data; - - poll_wait(file, &fh->wait, wait); - if (v4l2_event_pending(fh)) - res |= EPOLLPRI; - } + poll_wait(file, &fh->wait, wait); + if (v4l2_event_pending(fh)) + res |= EPOLLPRI; return res; } diff --git a/drivers/media/dvb-frontends/Kconfig b/drivers/media/dvb-frontends/Kconfig index 2ef2ff2a38ff..bcc97ca86ed5 100644 --- a/drivers/media/dvb-frontends/Kconfig +++ b/drivers/media/dvb-frontends/Kconfig @@ -163,7 +163,7 @@ config DVB_CX24123 A DVB-S tuner module. Say Y when you want to support this frontend. config DVB_DS3000 - tristate "Montage Tehnology DS3000 based" + tristate "Montage Technology DS3000 based" depends on DVB_CORE && I2C default m if !MEDIA_SUBDRV_AUTOSELECT help @@ -270,7 +270,7 @@ config DVB_TDA826X A DVB-S silicon tuner module. Say Y when you want to support this tuner. config DVB_TS2020 - tristate "Montage Tehnology TS2020 based tuners" + tristate "Montage Technology TS2020 based tuners" depends on DVB_CORE && I2C select REGMAP_I2C default m if !MEDIA_SUBDRV_AUTOSELECT diff --git a/drivers/media/i2c/Kconfig b/drivers/media/i2c/Kconfig index 6237fe804a5c..cdd7ba5da0d5 100644 --- a/drivers/media/i2c/Kconfig +++ b/drivers/media/i2c/Kconfig @@ -27,7 +27,7 @@ config VIDEO_IR_I2C menuconfig VIDEO_CAMERA_SENSOR bool "Camera sensor devices" - depends on MEDIA_CAMERA_SUPPORT && I2C + depends on MEDIA_CAMERA_SUPPORT && I2C && HAVE_CLK select MEDIA_CONTROLLER select V4L2_FWNODE select VIDEO_V4L2_SUBDEV_API @@ -70,6 +70,16 @@ config VIDEO_GC0308 To compile this driver as a module, choose M here: the module will be called gc0308. +config VIDEO_GC0310 + tristate "GalaxyCore GC0310 sensor support" + select V4L2_CCI_I2C + help + This is a Video4Linux2 sensor-level driver for the Galaxycore + GC0310 0.3MP sensor. + + To compile this driver as a module, choose M here: the + module will be called gc0310. + config VIDEO_GC05A2 tristate "GalaxyCore gc05a2 sensor support" select V4L2_CCI_I2C @@ -317,6 +327,7 @@ config VIDEO_MT9V011 config VIDEO_MT9V032 tristate "Micron MT9V032 sensor support" + depends on OF select REGMAP_I2C help This is a Video4Linux2 sensor driver for the Micron @@ -340,6 +351,16 @@ config VIDEO_OG01A1B To compile this driver as a module, choose M here: the module will be called og01a1b. +config VIDEO_OG0VE1B + tristate "OmniVision OG0VE1B sensor support" + select V4L2_CCI_I2C + help + This is a Video4Linux2 sensor driver for the OmniVision + OG0VE1B camera. + + To compile this driver as a module, choose M here: the + module will be called og0ve1b. + config VIDEO_OV01A10 tristate "OmniVision OV01A10 sensor support" help @@ -446,6 +467,16 @@ config VIDEO_OV2685 To compile this driver as a module, choose M here: the module will be called ov2685. +config VIDEO_OV2735 + tristate "OmniVision OV2735 sensor support" + select V4L2_CCI_I2C + help + This is a Video4Linux2 sensor driver for the Sony + OV2735 camera. + + To compile this driver as a module, choose M here: the + module will be called ov2735. + config VIDEO_OV2740 tristate "OmniVision OV2740 sensor support" depends on ACPI || COMPILE_TEST @@ -542,24 +573,25 @@ config VIDEO_OV5695 To compile this driver as a module, choose M here: the module will be called ov5695. -config VIDEO_OV64A40 - tristate "OmniVision OV64A40 sensor support" +config VIDEO_OV6211 + tristate "OmniVision OV6211 sensor support" select V4L2_CCI_I2C help This is a Video4Linux2 sensor driver for the OmniVision - OV64A40 camera. + OV6211 camera. To compile this driver as a module, choose M here: the - module will be called ov64a40. + module will be called ov6211. -config VIDEO_OV6650 - tristate "OmniVision OV6650 sensor support" +config VIDEO_OV64A40 + tristate "OmniVision OV64A40 sensor support" + select V4L2_CCI_I2C help This is a Video4Linux2 sensor driver for the OmniVision - OV6650 camera. + OV64A40 camera. To compile this driver as a module, choose M here: the - module will be called ov6650. + module will be called ov64a40. config VIDEO_OV7251 tristate "OmniVision OV7251 sensor support" diff --git a/drivers/media/i2c/Makefile b/drivers/media/i2c/Makefile index 5873d29433ee..57cdd8dc96f6 100644 --- a/drivers/media/i2c/Makefile +++ b/drivers/media/i2c/Makefile @@ -38,6 +38,7 @@ obj-$(CONFIG_VIDEO_DW9768) += dw9768.o obj-$(CONFIG_VIDEO_DW9807_VCM) += dw9807-vcm.o obj-$(CONFIG_VIDEO_ET8EK8) += et8ek8/ obj-$(CONFIG_VIDEO_GC0308) += gc0308.o +obj-$(CONFIG_VIDEO_GC0310) += gc0310.o obj-$(CONFIG_VIDEO_GC05A2) += gc05a2.o obj-$(CONFIG_VIDEO_GC08A3) += gc08a3.o obj-$(CONFIG_VIDEO_GC2145) += gc2145.o @@ -81,6 +82,7 @@ obj-$(CONFIG_VIDEO_MT9V011) += mt9v011.o obj-$(CONFIG_VIDEO_MT9V032) += mt9v032.o obj-$(CONFIG_VIDEO_MT9V111) += mt9v111.o obj-$(CONFIG_VIDEO_OG01A1B) += og01a1b.o +obj-$(CONFIG_VIDEO_OG0VE1B) += og0ve1b.o obj-$(CONFIG_VIDEO_OV01A10) += ov01a10.o obj-$(CONFIG_VIDEO_OV02A10) += ov02a10.o obj-$(CONFIG_VIDEO_OV02C10) += ov02c10.o @@ -93,6 +95,7 @@ obj-$(CONFIG_VIDEO_OV2640) += ov2640.o obj-$(CONFIG_VIDEO_OV2659) += ov2659.o obj-$(CONFIG_VIDEO_OV2680) += ov2680.o obj-$(CONFIG_VIDEO_OV2685) += ov2685.o +obj-$(CONFIG_VIDEO_OV2735) += ov2735.o obj-$(CONFIG_VIDEO_OV2740) += ov2740.o obj-$(CONFIG_VIDEO_OV4689) += ov4689.o obj-$(CONFIG_VIDEO_OV5640) += ov5640.o @@ -103,8 +106,8 @@ obj-$(CONFIG_VIDEO_OV5670) += ov5670.o obj-$(CONFIG_VIDEO_OV5675) += ov5675.o obj-$(CONFIG_VIDEO_OV5693) += ov5693.o obj-$(CONFIG_VIDEO_OV5695) += ov5695.o +obj-$(CONFIG_VIDEO_OV6211) += ov6211.o obj-$(CONFIG_VIDEO_OV64A40) += ov64a40.o -obj-$(CONFIG_VIDEO_OV6650) += ov6650.o obj-$(CONFIG_VIDEO_OV7251) += ov7251.o obj-$(CONFIG_VIDEO_OV7640) += ov7640.o obj-$(CONFIG_VIDEO_OV7670) += ov7670.o diff --git a/drivers/media/i2c/adv7180.c b/drivers/media/i2c/adv7180.c index 5d90b8ab9b6d..378f4e6af12c 100644 --- a/drivers/media/i2c/adv7180.c +++ b/drivers/media/i2c/adv7180.c @@ -214,7 +214,6 @@ struct adv7180_state { struct gpio_desc *pwdn_gpio; struct gpio_desc *rst_gpio; v4l2_std_id curr_norm; - bool powered; bool streaming; u8 input; @@ -274,6 +273,38 @@ static int adv7180_vpp_write(struct adv7180_state *state, unsigned int reg, return i2c_smbus_write_byte_data(state->vpp_client, reg, value); } +static int adv7180_set_power(struct adv7180_state *state, bool on) +{ + u8 val; + int ret; + + if (on) + val = ADV7180_PWR_MAN_ON; + else + val = ADV7180_PWR_MAN_OFF; + + ret = adv7180_write(state, ADV7180_REG_PWR_MAN, val); + if (ret) + return ret; + + if (state->chip_info->flags & ADV7180_FLAG_MIPI_CSI2) { + if (on) { + adv7180_csi_write(state, 0xDE, 0x02); + adv7180_csi_write(state, 0xD2, 0xF7); + adv7180_csi_write(state, 0xD8, 0x65); + adv7180_csi_write(state, 0xE0, 0x09); + adv7180_csi_write(state, 0x2C, 0x00); + if (state->field == V4L2_FIELD_NONE) + adv7180_csi_write(state, 0x1D, 0x80); + adv7180_csi_write(state, 0x00, 0x00); + } else { + adv7180_csi_write(state, 0x00, 0x80); + } + } + + return 0; +} + static v4l2_std_id adv7180_std_to_v4l2(u8 status1) { /* in case V4L2_IN_ST_NO_SIGNAL */ @@ -357,32 +388,27 @@ static inline struct adv7180_state *to_state(struct v4l2_subdev *sd) static int adv7180_querystd(struct v4l2_subdev *sd, v4l2_std_id *std) { struct adv7180_state *state = to_state(sd); - int err = mutex_lock_interruptible(&state->mutex); - if (err) - return err; - - if (state->streaming) { - err = -EBUSY; - goto unlock; - } + int ret; - err = adv7180_set_video_standard(state, - ADV7180_STD_AD_PAL_BG_NTSC_J_SECAM); - if (err) - goto unlock; + guard(mutex)(&state->mutex); - msleep(100); - __adv7180_status(state, NULL, std); + /* + * We can't sample the standard if the device is streaming as that would + * interfere with the capture session as the VID_SEL reg is touched. + */ + if (state->streaming) + return -EBUSY; - err = v4l2_std_to_adv7180(state->curr_norm); - if (err < 0) - goto unlock; + /* Set the standard to autodetect PAL B/G/H/I/D, NTSC J or SECAM */ + ret = adv7180_set_video_standard(state, + ADV7180_STD_AD_PAL_BG_NTSC_J_SECAM); + if (ret) + return ret; - err = adv7180_set_video_standard(state, err); + /* Allow some time for the autodetection to run. */ + msleep(100); -unlock: - mutex_unlock(&state->mutex); - return err; + return __adv7180_status(state, NULL, std); } static int adv7180_s_routing(struct v4l2_subdev *sd, u32 input, @@ -437,22 +463,18 @@ static int adv7180_program_std(struct adv7180_state *state) static int adv7180_s_std(struct v4l2_subdev *sd, v4l2_std_id std) { struct adv7180_state *state = to_state(sd); - int ret = mutex_lock_interruptible(&state->mutex); + int ret; - if (ret) - return ret; + guard(mutex)(&state->mutex); /* Make sure we can support this std */ ret = v4l2_std_to_adv7180(std); if (ret < 0) - goto out; + return ret; state->curr_norm = std; - ret = adv7180_program_std(state); -out: - mutex_unlock(&state->mutex); - return ret; + return 0; } static int adv7180_g_std(struct v4l2_subdev *sd, v4l2_std_id *norm) @@ -514,55 +536,6 @@ static void adv7180_set_reset_pin(struct adv7180_state *state, bool on) } } -static int adv7180_set_power(struct adv7180_state *state, bool on) -{ - u8 val; - int ret; - - if (on) - val = ADV7180_PWR_MAN_ON; - else - val = ADV7180_PWR_MAN_OFF; - - ret = adv7180_write(state, ADV7180_REG_PWR_MAN, val); - if (ret) - return ret; - - if (state->chip_info->flags & ADV7180_FLAG_MIPI_CSI2) { - if (on) { - adv7180_csi_write(state, 0xDE, 0x02); - adv7180_csi_write(state, 0xD2, 0xF7); - adv7180_csi_write(state, 0xD8, 0x65); - adv7180_csi_write(state, 0xE0, 0x09); - adv7180_csi_write(state, 0x2C, 0x00); - if (state->field == V4L2_FIELD_NONE) - adv7180_csi_write(state, 0x1D, 0x80); - adv7180_csi_write(state, 0x00, 0x00); - } else { - adv7180_csi_write(state, 0x00, 0x80); - } - } - - return 0; -} - -static int adv7180_s_power(struct v4l2_subdev *sd, int on) -{ - struct adv7180_state *state = to_state(sd); - int ret; - - ret = mutex_lock_interruptible(&state->mutex); - if (ret) - return ret; - - ret = adv7180_set_power(state, on); - if (ret == 0) - state->powered = on; - - mutex_unlock(&state->mutex); - return ret; -} - static const char * const test_pattern_menu[] = { "Single color", "Color bars", @@ -601,11 +574,11 @@ static int adv7180_s_ctrl(struct v4l2_ctrl *ctrl) { struct v4l2_subdev *sd = to_adv7180_sd(ctrl); struct adv7180_state *state = to_state(sd); - int ret = mutex_lock_interruptible(&state->mutex); + int ret = 0; int val; - if (ret) - return ret; + lockdep_assert_held(&state->mutex); + val = ctrl->val; switch (ctrl->id) { case V4L2_CID_BRIGHTNESS: @@ -647,7 +620,6 @@ static int adv7180_s_ctrl(struct v4l2_ctrl *ctrl) ret = -EINVAL; } - mutex_unlock(&state->mutex); return ret; } @@ -668,6 +640,7 @@ static const struct v4l2_ctrl_config adv7180_ctrl_fast_switch = { static int adv7180_init_controls(struct adv7180_state *state) { v4l2_ctrl_handler_init(&state->ctrl_hdl, 4); + state->ctrl_hdl.lock = &state->mutex; v4l2_ctrl_new_std(&state->ctrl_hdl, &adv7180_ctrl_ops, V4L2_CID_BRIGHTNESS, ADV7180_BRI_MIN, @@ -700,7 +673,6 @@ static int adv7180_init_controls(struct adv7180_state *state) v4l2_ctrl_handler_free(&state->ctrl_hdl); return err; } - v4l2_ctrl_handler_setup(&state->ctrl_hdl); return 0; } @@ -812,12 +784,7 @@ static int adv7180_set_pad_format(struct v4l2_subdev *sd, ret = adv7180_mbus_fmt(sd, &format->format); if (format->which == V4L2_SUBDEV_FORMAT_ACTIVE) { - if (state->field != format->format.field) { - state->field = format->format.field; - adv7180_set_power(state, false); - adv7180_set_field_mode(state); - adv7180_set_power(state, true); - } + state->field = format->format.field; } else { framefmt = v4l2_subdev_state_get_format(sd_state, 0); *framefmt = format->format; @@ -874,23 +841,117 @@ static int adv7180_g_tvnorms(struct v4l2_subdev *sd, v4l2_std_id *norm) return 0; } -static int adv7180_s_stream(struct v4l2_subdev *sd, int enable) +static int init_device(struct adv7180_state *state) { - struct adv7180_state *state = to_state(sd); int ret; - /* It's always safe to stop streaming, no need to take the lock */ - if (!enable) { - state->streaming = enable; - return 0; + lockdep_assert_held(&state->mutex); + + ret = adv7180_program_std(state); + if (ret) + return ret; + + adv7180_set_field_mode(state); + + __v4l2_ctrl_handler_setup(&state->ctrl_hdl); + + return ret; +} + +static int adv7180_reset_device(struct adv7180_state *state) +{ + int ret; + + lockdep_assert_held(&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); + + /* + * If the devices decoder is power on after reset, power off so the + * device can be configured. + */ + if (state->chip_info->flags & ADV7180_FLAG_RESET_POWERED) + adv7180_set_power(state, false); + + ret = state->chip_info->init(state); + if (ret) + return ret; + + ret = init_device(state); + if (ret) + return ret; + + /* register for interrupts */ + if (state->irq > 0) { + /* config the Interrupt pin to be active low */ + ret = adv7180_write(state, ADV7180_REG_ICONF1, + ADV7180_ICONF1_ACTIVE_LOW | + ADV7180_ICONF1_PSYNC_ONLY); + if (ret < 0) + return ret; + + ret = adv7180_write(state, ADV7180_REG_IMR1, 0); + if (ret < 0) + return ret; + + ret = adv7180_write(state, ADV7180_REG_IMR2, 0); + if (ret < 0) + return ret; + + /* enable AD change interrupts */ + ret = adv7180_write(state, ADV7180_REG_IMR3, + ADV7180_IRQ3_AD_CHANGE); + if (ret < 0) + return ret; + + ret = adv7180_write(state, ADV7180_REG_IMR4, 0); + if (ret < 0) + return ret; } + /* + * If the devices decoder is power on after reset, restore the power + * after configuration. This is to preserve the behavior of the driver, + * not doing this result in the first 35+ frames captured being garbage. + */ + if (state->chip_info->flags & ADV7180_FLAG_RESET_POWERED) + adv7180_set_power(state, true); + + return 0; +} + +static int adv7180_s_stream(struct v4l2_subdev *sd, int enable) +{ + struct adv7180_state *state = to_state(sd); + int ret; + /* Must wait until querystd released the lock */ - ret = mutex_lock_interruptible(&state->mutex); + guard(mutex)(&state->mutex); + + /* + * Always power off the decoder even if streaming is to be enabled, the + * decoder needs to be off for the device to be configured. + */ + ret = adv7180_set_power(state, false); if (ret) return ret; + + if (enable) { + ret = init_device(state); + if (ret) + return ret; + + ret = adv7180_set_power(state, true); + if (ret) + return ret; + } + state->streaming = enable; - mutex_unlock(&state->mutex); + return 0; } @@ -919,7 +980,6 @@ static const struct v4l2_subdev_video_ops adv7180_video_ops = { }; static const struct v4l2_subdev_core_ops adv7180_core_ops = { - .s_power = adv7180_s_power, .subscribe_event = adv7180_subscribe_event, .unsubscribe_event = v4l2_event_subdev_unsubscribe, }; @@ -1343,62 +1403,6 @@ static const struct adv7180_chip_info adv7282_m_info = { .select_input = adv7182_select_input, }; -static int init_device(struct adv7180_state *state) -{ - int ret; - - 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); - - ret = state->chip_info->init(state); - if (ret) - goto out_unlock; - - ret = adv7180_program_std(state); - if (ret) - goto out_unlock; - - adv7180_set_field_mode(state); - - /* register for interrupts */ - if (state->irq > 0) { - /* config the Interrupt pin to be active low */ - ret = adv7180_write(state, ADV7180_REG_ICONF1, - ADV7180_ICONF1_ACTIVE_LOW | - ADV7180_ICONF1_PSYNC_ONLY); - if (ret < 0) - goto out_unlock; - - ret = adv7180_write(state, ADV7180_REG_IMR1, 0); - if (ret < 0) - goto out_unlock; - - ret = adv7180_write(state, ADV7180_REG_IMR2, 0); - if (ret < 0) - goto out_unlock; - - /* enable AD change interrupts interrupts */ - ret = adv7180_write(state, ADV7180_REG_IMR3, - ADV7180_IRQ3_AD_CHANGE); - if (ret < 0) - goto out_unlock; - - ret = adv7180_write(state, ADV7180_REG_IMR4, 0); - if (ret < 0) - goto out_unlock; - } - -out_unlock: - mutex_unlock(&state->mutex); - - return ret; -} - static int adv7180_probe(struct i2c_client *client) { struct device_node *np = client->dev.of_node; @@ -1457,10 +1461,7 @@ static int adv7180_probe(struct i2c_client *client) state->irq = client->irq; mutex_init(&state->mutex); state->curr_norm = V4L2_STD_NTSC; - if (state->chip_info->flags & ADV7180_FLAG_RESET_POWERED) - state->powered = true; - else - state->powered = false; + state->input = 0; sd = &state->sd; v4l2_i2c_subdev_init(sd, client, &adv7180_ops); @@ -1477,7 +1478,9 @@ static int adv7180_probe(struct i2c_client *client) if (ret) goto err_free_ctrl; - ret = init_device(state); + mutex_lock(&state->mutex); + ret = adv7180_reset_device(state); + mutex_unlock(&state->mutex); if (ret) goto err_media_entity_cleanup; @@ -1549,6 +1552,8 @@ static int adv7180_suspend(struct device *dev) struct v4l2_subdev *sd = dev_get_drvdata(dev); struct adv7180_state *state = to_state(sd); + guard(mutex)(&state->mutex); + return adv7180_set_power(state, false); } @@ -1558,13 +1563,18 @@ static int adv7180_resume(struct device *dev) struct adv7180_state *state = to_state(sd); int ret; - ret = init_device(state); + guard(mutex)(&state->mutex); + + ret = adv7180_reset_device(state); if (ret < 0) return ret; - ret = adv7180_set_power(state, state->powered); - if (ret) - return ret; + /* If we were streaming when suspending, start decoder. */ + if (state->streaming) { + ret = adv7180_set_power(state, true); + if (ret) + return ret; + } return 0; } diff --git a/drivers/media/i2c/adv7604.c b/drivers/media/i2c/adv7604.c index afed38596362..8fe7c2f72883 100644 --- a/drivers/media/i2c/adv7604.c +++ b/drivers/media/i2c/adv7604.c @@ -42,7 +42,7 @@ module_param(debug, int, 0644); MODULE_PARM_DESC(debug, "debug level (0-2)"); MODULE_DESCRIPTION("Analog Devices ADV7604/10/11/12 video decoder driver"); -MODULE_AUTHOR("Hans Verkuil <hansverk@cisco.com>"); +MODULE_AUTHOR("Hans Verkuil <hverkuil@kernel.org>"); MODULE_AUTHOR("Mats Randgaard <mats.randgaard@cisco.com>"); MODULE_LICENSE("GPL"); diff --git a/drivers/media/i2c/adv7842.c b/drivers/media/i2c/adv7842.c index 5545cd23e113..9780082db841 100644 --- a/drivers/media/i2c/adv7842.c +++ b/drivers/media/i2c/adv7842.c @@ -38,7 +38,7 @@ module_param(debug, int, 0644); MODULE_PARM_DESC(debug, "debug level (0-2)"); MODULE_DESCRIPTION("Analog Devices ADV7842 video decoder driver"); -MODULE_AUTHOR("Hans Verkuil <hansverk@cisco.com>"); +MODULE_AUTHOR("Hans Verkuil <hverkuil@kernel.org>"); MODULE_AUTHOR("Martin Bugge <marbugge@cisco.com>"); MODULE_LICENSE("GPL"); diff --git a/drivers/media/i2c/ar0521.c b/drivers/media/i2c/ar0521.c index 24873149096c..939bf590d4b2 100644 --- a/drivers/media/i2c/ar0521.c +++ b/drivers/media/i2c/ar0521.c @@ -1077,11 +1077,10 @@ static int ar0521_probe(struct i2c_client *client) } /* Get master clock (extclk) */ - sensor->extclk = devm_clk_get(dev, "extclk"); - if (IS_ERR(sensor->extclk)) { - dev_err(dev, "failed to get extclk\n"); - return PTR_ERR(sensor->extclk); - } + sensor->extclk = devm_v4l2_sensor_clk_get(dev, "extclk"); + if (IS_ERR(sensor->extclk)) + return dev_err_probe(dev, PTR_ERR(sensor->extclk), + "failed to get extclk\n"); sensor->extclk_freq = clk_get_rate(sensor->extclk); diff --git a/drivers/media/i2c/cx25840/cx25840-core.c b/drivers/media/i2c/cx25840/cx25840-core.c index a90a9e5705a0..a86306304330 100644 --- a/drivers/media/i2c/cx25840/cx25840-core.c +++ b/drivers/media/i2c/cx25840/cx25840-core.c @@ -9,10 +9,10 @@ * Changes by Tyler Trafford <tatrafford@comcast.net> * - cleanup/rewrite for V4L2 API (2005) * - * VBI support by Hans Verkuil <hverkuil@xs4all.nl>. + * VBI support by Hans Verkuil <hverkuil@kernel.org>. * * NTSC sliced VBI support by Christopher Neufeld <television@cneufeld.ca> - * with additional fixes by Hans Verkuil <hverkuil@xs4all.nl>. + * with additional fixes by Hans Verkuil <hverkuil@kernel.org>. * * CX23885 support by Steven Toth <stoth@linuxtv.org>. * diff --git a/drivers/media/i2c/ds90ub913.c b/drivers/media/i2c/ds90ub913.c index a80da2b4a8fa..73150061ea45 100644 --- a/drivers/media/i2c/ds90ub913.c +++ b/drivers/media/i2c/ds90ub913.c @@ -333,8 +333,7 @@ static int _ub913_set_routing(struct v4l2_subdev *sd, .quantization = V4L2_QUANTIZATION_LIM_RANGE, .xfer_func = V4L2_XFER_FUNC_SRGB, }; - struct v4l2_subdev_stream_configs *stream_configs; - unsigned int i; + struct v4l2_subdev_route *route; int ret; ret = v4l2_subdev_routing_validate(sd, routing, @@ -346,13 +345,15 @@ static int _ub913_set_routing(struct v4l2_subdev *sd, if (ret) return ret; - stream_configs = &state->stream_configs; + for_each_active_route(&state->routing, route) { + struct v4l2_mbus_framefmt *fmt; - for (i = 0; i < stream_configs->num_configs; i++) { - if (stream_configs->configs[i].pad == UB913_PAD_SINK) - stream_configs->configs[i].fmt = in_format; - else - stream_configs->configs[i].fmt = out_format; + fmt = v4l2_subdev_state_get_format(state, route->sink_pad, + route->sink_stream); + *fmt = in_format; + fmt = v4l2_subdev_state_get_format(state, route->source_pad, + route->source_stream); + *fmt = out_format; } return 0; diff --git a/drivers/media/i2c/et8ek8/et8ek8_driver.c b/drivers/media/i2c/et8ek8/et8ek8_driver.c index 7519863d77b1..2cb7b718782b 100644 --- a/drivers/media/i2c/et8ek8/et8ek8_driver.c +++ b/drivers/media/i2c/et8ek8/et8ek8_driver.c @@ -816,7 +816,6 @@ static int et8ek8_power_on(struct et8ek8_sensor *sensor) { struct v4l2_subdev *subdev = &sensor->subdev; struct i2c_client *client = v4l2_get_subdevdata(subdev); - unsigned int xclk_freq; int val, rval; rval = regulator_enable(sensor->vana); @@ -825,17 +824,6 @@ static int et8ek8_power_on(struct et8ek8_sensor *sensor) return rval; } - if (sensor->current_reglist) - xclk_freq = sensor->current_reglist->mode.ext_clock; - else - xclk_freq = sensor->xclk_freq; - - rval = clk_set_rate(sensor->ext_clk, xclk_freq); - if (rval < 0) { - dev_err(&client->dev, "unable to set extclk clock freq to %u\n", - xclk_freq); - goto out; - } rval = clk_prepare_enable(sensor->ext_clk); if (rval < 0) { dev_err(&client->dev, "failed to enable extclk\n"); @@ -849,7 +837,7 @@ static int et8ek8_power_on(struct et8ek8_sensor *sensor) gpiod_set_value(sensor->reset, 1); - msleep(5000 * 1000 / xclk_freq + 1); /* Wait 5000 cycles */ + msleep(5000 * 1000 / sensor->xclk_freq + 1); /* Wait 5000 cycles */ rval = et8ek8_i2c_reglist_find_write(client, &meta_reglist, ET8EK8_REGLIST_POWERON); @@ -1085,9 +1073,6 @@ static int et8ek8_set_frame_interval(struct v4l2_subdev *subdev, if (!reglist) return -EINVAL; - if (sensor->current_reglist->mode.ext_clock != reglist->mode.ext_clock) - return -EINVAL; - sensor->current_reglist = reglist; et8ek8_update_controls(sensor); @@ -1433,18 +1418,13 @@ static int et8ek8_probe(struct i2c_client *client) return PTR_ERR(sensor->vana); } - sensor->ext_clk = devm_clk_get(dev, NULL); - if (IS_ERR(sensor->ext_clk)) { - dev_err(&client->dev, "could not get clock\n"); - return PTR_ERR(sensor->ext_clk); - } + sensor->ext_clk = devm_v4l2_sensor_clk_get_legacy(dev, NULL, true, + 9600000); + if (IS_ERR(sensor->ext_clk)) + return dev_err_probe(&client->dev, PTR_ERR(sensor->ext_clk), + "could not get clock\n"); - ret = of_property_read_u32(dev->of_node, "clock-frequency", - &sensor->xclk_freq); - if (ret) { - dev_warn(dev, "can't get clock-frequency\n"); - return ret; - } + sensor->xclk_freq = clk_get_rate(sensor->ext_clk); mutex_init(&sensor->power_lock); diff --git a/drivers/media/i2c/et8ek8/et8ek8_mode.c b/drivers/media/i2c/et8ek8/et8ek8_mode.c index c9088eb0a812..914be1007099 100644 --- a/drivers/media/i2c/et8ek8/et8ek8_mode.c +++ b/drivers/media/i2c/et8ek8/et8ek8_mode.c @@ -44,7 +44,6 @@ static struct et8ek8_reglist mode1_poweron_mode2_16vga_2592x1968_12_07fps = { .window_width = 2592, .window_height = 1968, .pixel_clock = 80000000, - .ext_clock = 9600000, .timeperframe = { .numerator = 100, .denominator = 1207 @@ -145,7 +144,6 @@ static struct et8ek8_reglist mode1_16vga_2592x1968_13_12fps_dpcm10_8 = { .window_width = 2592, .window_height = 1968, .pixel_clock = 80000000, - .ext_clock = 9600000, .timeperframe = { .numerator = 100, .denominator = 1292 @@ -201,7 +199,6 @@ static struct et8ek8_reglist mode3_4vga_1296x984_29_99fps_dpcm10_8 = { .window_width = 1296, .window_height = 984, .pixel_clock = 96533333, - .ext_clock = 9600000, .timeperframe = { .numerator = 100, .denominator = 3000 @@ -257,7 +254,6 @@ static struct et8ek8_reglist mode4_svga_864x656_29_88fps = { .window_width = 864, .window_height = 656, .pixel_clock = 80000000, - .ext_clock = 9600000, .timeperframe = { .numerator = 100, .denominator = 2988 @@ -313,7 +309,6 @@ static struct et8ek8_reglist mode5_vga_648x492_29_93fps = { .window_width = 648, .window_height = 492, .pixel_clock = 80000000, - .ext_clock = 9600000, .timeperframe = { .numerator = 100, .denominator = 2993 @@ -369,7 +364,6 @@ static struct et8ek8_reglist mode2_16vga_2592x1968_3_99fps = { .window_width = 2592, .window_height = 1968, .pixel_clock = 80000000, - .ext_clock = 9600000, .timeperframe = { .numerator = 100, .denominator = 399 @@ -424,7 +418,6 @@ static struct et8ek8_reglist mode_648x492_5fps = { .window_width = 648, .window_height = 492, .pixel_clock = 13333333, - .ext_clock = 9600000, .timeperframe = { .numerator = 100, .denominator = 499 @@ -480,7 +473,6 @@ static struct et8ek8_reglist mode3_4vga_1296x984_5fps = { .window_width = 1296, .window_height = 984, .pixel_clock = 49400000, - .ext_clock = 9600000, .timeperframe = { .numerator = 100, .denominator = 501 @@ -536,7 +528,6 @@ static struct et8ek8_reglist mode_4vga_1296x984_25fps_dpcm10_8 = { .window_width = 1296, .window_height = 984, .pixel_clock = 84266667, - .ext_clock = 9600000, .timeperframe = { .numerator = 100, .denominator = 2500 diff --git a/drivers/media/i2c/et8ek8/et8ek8_reg.h b/drivers/media/i2c/et8ek8/et8ek8_reg.h index c90e74935f12..3305986c7c9c 100644 --- a/drivers/media/i2c/et8ek8/et8ek8_reg.h +++ b/drivers/media/i2c/et8ek8/et8ek8_reg.h @@ -37,7 +37,6 @@ struct et8ek8_mode { u16 window_height; u32 pixel_clock; /* in Hz */ - u32 ext_clock; /* in Hz */ struct v4l2_fract timeperframe; u32 max_exp; /* Maximum exposure value */ u32 bus_format; /* MEDIA_BUS_FMT_ */ diff --git a/drivers/staging/media/atomisp/i2c/atomisp-gc0310.c b/drivers/media/i2c/gc0310.c index 7af4d66f42a0..7af4d66f42a0 100644 --- a/drivers/staging/media/atomisp/i2c/atomisp-gc0310.c +++ b/drivers/media/i2c/gc0310.c diff --git a/drivers/media/i2c/gc05a2.c b/drivers/media/i2c/gc05a2.c index 3f7f3d5abeeb..8ba17f80fffe 100644 --- a/drivers/media/i2c/gc05a2.c +++ b/drivers/media/i2c/gc05a2.c @@ -1235,16 +1235,12 @@ static int gc05a2_probe(struct i2c_client *client) return dev_err_probe(dev, PTR_ERR(gc05a2->regmap), "failed to init CCI\n"); - gc05a2->xclk = devm_clk_get(dev, NULL); + gc05a2->xclk = devm_v4l2_sensor_clk_get_legacy(dev, NULL, true, + GC05A2_DEFAULT_CLK_FREQ); if (IS_ERR(gc05a2->xclk)) return dev_err_probe(dev, PTR_ERR(gc05a2->xclk), "failed to get xclk\n"); - ret = clk_set_rate(gc05a2->xclk, GC05A2_DEFAULT_CLK_FREQ); - if (ret) - return dev_err_probe(dev, ret, - "failed to set xclk frequency\n"); - ret = gc05a2_get_regulators(dev, gc05a2); if (ret < 0) return dev_err_probe(dev, ret, diff --git a/drivers/media/i2c/gc08a3.c b/drivers/media/i2c/gc08a3.c index 938709a677b6..11fd936db9c3 100644 --- a/drivers/media/i2c/gc08a3.c +++ b/drivers/media/i2c/gc08a3.c @@ -1199,16 +1199,12 @@ static int gc08a3_probe(struct i2c_client *client) return dev_err_probe(dev, PTR_ERR(gc08a3->regmap), "failed to init CCI\n"); - gc08a3->xclk = devm_clk_get(dev, NULL); + gc08a3->xclk = devm_v4l2_sensor_clk_get_legacy(dev, NULL, true, + GC08A3_DEFAULT_CLK_FREQ); if (IS_ERR(gc08a3->xclk)) return dev_err_probe(dev, PTR_ERR(gc08a3->xclk), "failed to get xclk\n"); - ret = clk_set_rate(gc08a3->xclk, GC08A3_DEFAULT_CLK_FREQ); - if (ret) - return dev_err_probe(dev, ret, - "failed to set xclk frequency\n"); - ret = gc08a3_get_regulators(dev, gc08a3); if (ret < 0) return dev_err_probe(dev, ret, diff --git a/drivers/media/i2c/gc2145.c b/drivers/media/i2c/gc2145.c index 559a851669aa..b215963a2648 100644 --- a/drivers/media/i2c/gc2145.c +++ b/drivers/media/i2c/gc2145.c @@ -1331,7 +1331,7 @@ static int gc2145_probe(struct i2c_client *client) return -EINVAL; /* Get system clock (xclk) */ - gc2145->xclk = devm_clk_get(dev, NULL); + gc2145->xclk = devm_v4l2_sensor_clk_get(dev, NULL); if (IS_ERR(gc2145->xclk)) return dev_err_probe(dev, PTR_ERR(gc2145->xclk), "failed to get xclk\n"); diff --git a/drivers/media/i2c/hi556.c b/drivers/media/i2c/hi556.c index 076c19fcf99c..de573cee4451 100644 --- a/drivers/media/i2c/hi556.c +++ b/drivers/media/i2c/hi556.c @@ -1,7 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 // Copyright (c) 2019 Intel Corporation. -#include <linux/unaligned.h> #include <linux/acpi.h> #include <linux/clk.h> #include <linux/delay.h> @@ -10,6 +9,8 @@ #include <linux/module.h> #include <linux/pm_runtime.h> #include <linux/regulator/consumer.h> +#include <linux/unaligned.h> + #include <media/v4l2-ctrls.h> #include <media/v4l2-device.h> #include <media/v4l2-fwnode.h> @@ -631,6 +632,8 @@ static const char * const hi556_supply_names[] = { }; struct hi556 { + struct device *dev; + struct v4l2_subdev sd; struct media_pad pad; struct v4l2_ctrl_handler ctrl_handler; @@ -715,7 +718,6 @@ static int hi556_write_reg(struct hi556 *hi556, u16 reg, u16 len, u32 val) static int hi556_write_reg_list(struct hi556 *hi556, const struct hi556_reg_list *r_list) { - struct i2c_client *client = v4l2_get_subdevdata(&hi556->sd); unsigned int i; int ret; @@ -724,7 +726,7 @@ static int hi556_write_reg_list(struct hi556 *hi556, HI556_REG_VALUE_16BIT, r_list->regs[i].val); if (ret) { - dev_err_ratelimited(&client->dev, + dev_err_ratelimited(hi556->dev, "failed to write reg 0x%4.4x. error = %d\n", r_list->regs[i].address, ret); return ret; @@ -785,7 +787,6 @@ static int hi556_set_ctrl(struct v4l2_ctrl *ctrl) { struct hi556 *hi556 = container_of(ctrl->handler, struct hi556, ctrl_handler); - struct i2c_client *client = v4l2_get_subdevdata(&hi556->sd); s64 exposure_max; int ret = 0; @@ -801,7 +802,7 @@ static int hi556_set_ctrl(struct v4l2_ctrl *ctrl) } /* V4L2 controls values will be applied only when power is already up */ - if (!pm_runtime_get_if_in_use(&client->dev)) + if (!pm_runtime_get_if_in_use(hi556->dev)) return 0; switch (ctrl->id) { @@ -835,7 +836,7 @@ static int hi556_set_ctrl(struct v4l2_ctrl *ctrl) break; } - pm_runtime_put(&client->dev); + pm_runtime_put(hi556->dev); return ret; } @@ -921,7 +922,6 @@ static void hi556_assign_pad_format(const struct hi556_mode *mode, static int hi556_identify_module(struct hi556 *hi556) { - struct i2c_client *client = v4l2_get_subdevdata(&hi556->sd); int ret; u32 val; @@ -934,7 +934,7 @@ static int hi556_identify_module(struct hi556 *hi556) return ret; if (val != HI556_CHIP_ID) { - dev_err(&client->dev, "chip id mismatch: %x!=%x\n", + dev_err(hi556->dev, "chip id mismatch: %x!=%x\n", HI556_CHIP_ID, val); return -ENXIO; } @@ -998,7 +998,6 @@ static int hi556_get_selection(struct v4l2_subdev *sd, static int hi556_start_streaming(struct hi556 *hi556) { - struct i2c_client *client = v4l2_get_subdevdata(&hi556->sd); const struct hi556_reg_list *reg_list; int link_freq_index, ret; @@ -1010,14 +1009,14 @@ static int hi556_start_streaming(struct hi556 *hi556) reg_list = &link_freq_configs[link_freq_index].reg_list; ret = hi556_write_reg_list(hi556, reg_list); if (ret) { - dev_err(&client->dev, "failed to set plls\n"); + dev_err(hi556->dev, "failed to set plls\n"); return ret; } reg_list = &hi556->cur_mode->reg_list; ret = hi556_write_reg_list(hi556, reg_list); if (ret) { - dev_err(&client->dev, "failed to set mode\n"); + dev_err(hi556->dev, "failed to set mode\n"); return ret; } @@ -1029,7 +1028,7 @@ static int hi556_start_streaming(struct hi556 *hi556) HI556_REG_VALUE_16BIT, HI556_MODE_STREAMING); if (ret) { - dev_err(&client->dev, "failed to set stream\n"); + dev_err(hi556->dev, "failed to set stream\n"); return ret; } @@ -1038,22 +1037,19 @@ static int hi556_start_streaming(struct hi556 *hi556) static void hi556_stop_streaming(struct hi556 *hi556) { - struct i2c_client *client = v4l2_get_subdevdata(&hi556->sd); - if (hi556_write_reg(hi556, HI556_REG_MODE_SELECT, HI556_REG_VALUE_16BIT, HI556_MODE_STANDBY)) - dev_err(&client->dev, "failed to set stream\n"); + dev_err(hi556->dev, "failed to set stream\n"); } static int hi556_set_stream(struct v4l2_subdev *sd, int enable) { struct hi556 *hi556 = to_hi556(sd); - struct i2c_client *client = v4l2_get_subdevdata(sd); int ret = 0; mutex_lock(&hi556->mutex); if (enable) { - ret = pm_runtime_resume_and_get(&client->dev); + ret = pm_runtime_resume_and_get(hi556->dev); if (ret < 0) { mutex_unlock(&hi556->mutex); return ret; @@ -1062,11 +1058,11 @@ static int hi556_set_stream(struct v4l2_subdev *sd, int enable) ret = hi556_start_streaming(hi556); if (ret) { hi556_stop_streaming(hi556); - pm_runtime_put(&client->dev); + pm_runtime_put(hi556->dev); } } else { hi556_stop_streaming(hi556); - pm_runtime_put(&client->dev); + pm_runtime_put(hi556->dev); } mutex_unlock(&hi556->mutex); @@ -1217,7 +1213,6 @@ static int hi556_check_hwcfg(struct device *dev) struct v4l2_fwnode_endpoint bus_cfg = { .bus_type = V4L2_MBUS_CSI2_DPHY }; - u32 mclk; int ret = 0; unsigned int i, j; @@ -1235,18 +1230,6 @@ static int hi556_check_hwcfg(struct device *dev) if (ret) return dev_err_probe(dev, ret, "parsing endpoint failed\n"); - ret = fwnode_property_read_u32(fwnode, "clock-frequency", &mclk); - if (ret) { - dev_err(dev, "can't get clock frequency\n"); - goto check_hwcfg_error; - } - - if (mclk != HI556_MCLK) { - dev_err(dev, "external clock %d is not supported\n", mclk); - ret = -EINVAL; - goto check_hwcfg_error; - } - if (bus_cfg.bus.mipi_csi2.num_data_lanes != 2) { dev_err(dev, "number of CSI2 data lanes %d is not supported\n", bus_cfg.bus.mipi_csi2.num_data_lanes); @@ -1289,7 +1272,7 @@ static void hi556_remove(struct i2c_client *client) v4l2_async_unregister_subdev(sd); media_entity_cleanup(&sd->entity); v4l2_ctrl_handler_free(sd->ctrl_handler); - pm_runtime_disable(&client->dev); + pm_runtime_disable(hi556->dev); mutex_destroy(&hi556->mutex); } @@ -1336,6 +1319,7 @@ static int hi556_resume(struct device *dev) static int hi556_probe(struct i2c_client *client) { struct hi556 *hi556; + unsigned long freq; bool full_power; int i, ret; @@ -1347,40 +1331,48 @@ static int hi556_probe(struct i2c_client *client) if (!hi556) return -ENOMEM; + hi556->dev = &client->dev; + v4l2_i2c_subdev_init(&hi556->sd, client, &hi556_subdev_ops); - hi556->reset_gpio = devm_gpiod_get_optional(&client->dev, "reset", + hi556->reset_gpio = devm_gpiod_get_optional(hi556->dev, "reset", GPIOD_OUT_HIGH); if (IS_ERR(hi556->reset_gpio)) - return dev_err_probe(&client->dev, PTR_ERR(hi556->reset_gpio), + return dev_err_probe(hi556->dev, PTR_ERR(hi556->reset_gpio), "failed to get reset GPIO\n"); - hi556->clk = devm_clk_get_optional(&client->dev, "clk"); + hi556->clk = devm_v4l2_sensor_clk_get(hi556->dev, "clk"); if (IS_ERR(hi556->clk)) - return dev_err_probe(&client->dev, PTR_ERR(hi556->clk), + return dev_err_probe(hi556->dev, PTR_ERR(hi556->clk), "failed to get clock\n"); + freq = clk_get_rate(hi556->clk); + if (freq != HI556_MCLK) + return dev_err_probe(hi556->dev, -EINVAL, + "external clock %lu is not supported\n", + freq); + for (i = 0; i < ARRAY_SIZE(hi556_supply_names); i++) hi556->supplies[i].supply = hi556_supply_names[i]; - ret = devm_regulator_bulk_get(&client->dev, + ret = devm_regulator_bulk_get(hi556->dev, ARRAY_SIZE(hi556_supply_names), hi556->supplies); if (ret) - return dev_err_probe(&client->dev, ret, + return dev_err_probe(hi556->dev, ret, "failed to get regulators\n"); - full_power = acpi_dev_state_d0(&client->dev); + full_power = acpi_dev_state_d0(hi556->dev); if (full_power) { /* Ensure non ACPI managed resources are enabled */ - ret = hi556_resume(&client->dev); + ret = hi556_resume(hi556->dev); if (ret) - return dev_err_probe(&client->dev, ret, + return dev_err_probe(hi556->dev, ret, "failed to power on sensor\n"); ret = hi556_identify_module(hi556); if (ret) { - dev_err(&client->dev, "failed to find sensor: %d\n", ret); + dev_err(hi556->dev, "failed to find sensor: %d\n", ret); goto probe_error_power_off; } } @@ -1389,7 +1381,7 @@ static int hi556_probe(struct i2c_client *client) hi556->cur_mode = &supported_modes[0]; ret = hi556_init_controls(hi556); if (ret) { - dev_err(&client->dev, "failed to init controls: %d\n", ret); + dev_err(hi556->dev, "failed to init controls: %d\n", ret); goto probe_error_v4l2_ctrl_handler_free; } @@ -1400,22 +1392,22 @@ static int hi556_probe(struct i2c_client *client) hi556->pad.flags = MEDIA_PAD_FL_SOURCE; ret = media_entity_pads_init(&hi556->sd.entity, 1, &hi556->pad); if (ret) { - dev_err(&client->dev, "failed to init entity pads: %d\n", ret); + dev_err(hi556->dev, "failed to init entity pads: %d\n", ret); goto probe_error_v4l2_ctrl_handler_free; } ret = v4l2_async_register_subdev_sensor(&hi556->sd); if (ret < 0) { - dev_err(&client->dev, "failed to register V4L2 subdev: %d\n", + dev_err(hi556->dev, "failed to register V4L2 subdev: %d\n", ret); goto probe_error_media_entity_cleanup; } /* Set the device's state to active if it's in D0 state. */ if (full_power) - pm_runtime_set_active(&client->dev); - pm_runtime_enable(&client->dev); - pm_runtime_idle(&client->dev); + pm_runtime_set_active(hi556->dev); + pm_runtime_enable(hi556->dev); + pm_runtime_idle(hi556->dev); return 0; @@ -1428,7 +1420,7 @@ probe_error_v4l2_ctrl_handler_free: probe_error_power_off: if (full_power) - hi556_suspend(&client->dev); + hi556_suspend(hi556->dev); return ret; } diff --git a/drivers/media/i2c/hi846.c b/drivers/media/i2c/hi846.c index 172772decd3d..a3f77b8434ca 100644 --- a/drivers/media/i2c/hi846.c +++ b/drivers/media/i2c/hi846.c @@ -2052,12 +2052,11 @@ static int hi846_probe(struct i2c_client *client) return ret; } - hi846->clock = devm_clk_get(&client->dev, NULL); - if (IS_ERR(hi846->clock)) { - dev_err(&client->dev, "failed to get clock: %pe\n", - hi846->clock); - return PTR_ERR(hi846->clock); - } + hi846->clock = devm_v4l2_sensor_clk_get(&client->dev, NULL); + if (IS_ERR(hi846->clock)) + return dev_err_probe(&client->dev, PTR_ERR(hi846->clock), + "failed to get clock: %pe\n", + hi846->clock); mclk_freq = clk_get_rate(hi846->clock); if (mclk_freq != 25000000) diff --git a/drivers/media/i2c/hi847.c b/drivers/media/i2c/hi847.c index 546833f5b5f5..def01aa07b2f 100644 --- a/drivers/media/i2c/hi847.c +++ b/drivers/media/i2c/hi847.c @@ -1,12 +1,14 @@ // SPDX-License-Identifier: GPL-2.0 // Copyright (c) 2022 Intel Corporation. -#include <linux/unaligned.h> #include <linux/acpi.h> +#include <linux/clk.h> #include <linux/delay.h> #include <linux/i2c.h> #include <linux/module.h> #include <linux/pm_runtime.h> +#include <linux/unaligned.h> + #include <media/v4l2-ctrls.h> #include <media/v4l2-device.h> #include <media/v4l2-fwnode.h> @@ -2166,6 +2168,9 @@ static const struct hi847_mode supported_modes[] = { }; struct hi847 { + struct device *dev; + struct clk *clk; + struct v4l2_subdev sd; struct media_pad pad; struct v4l2_ctrl_handler ctrl_handler; @@ -2244,7 +2249,6 @@ static int hi847_write_reg(struct hi847 *hi847, u16 reg, u16 len, u32 val) static int hi847_write_reg_list(struct hi847 *hi847, const struct hi847_reg_list *r_list) { - struct i2c_client *client = v4l2_get_subdevdata(&hi847->sd); unsigned int i; int ret; @@ -2253,7 +2257,7 @@ static int hi847_write_reg_list(struct hi847 *hi847, HI847_REG_VALUE_16BIT, r_list->regs[i].val); if (ret) { - dev_err_ratelimited(&client->dev, + dev_err_ratelimited(hi847->dev, "failed to write reg 0x%4.4x. error = %d", r_list->regs[i].address, ret); return ret; @@ -2408,7 +2412,6 @@ static int hi847_set_ctrl(struct v4l2_ctrl *ctrl) { struct hi847 *hi847 = container_of(ctrl->handler, struct hi847, ctrl_handler); - struct i2c_client *client = v4l2_get_subdevdata(&hi847->sd); s64 exposure_max; int ret = 0; @@ -2424,7 +2427,7 @@ static int hi847_set_ctrl(struct v4l2_ctrl *ctrl) } /* V4L2 controls values will be applied only when power is already up */ - if (!pm_runtime_get_if_in_use(&client->dev)) + if (!pm_runtime_get_if_in_use(hi847->dev)) return 0; switch (ctrl->id) { @@ -2466,7 +2469,7 @@ static int hi847_set_ctrl(struct v4l2_ctrl *ctrl) break; } - pm_runtime_put(&client->dev); + pm_runtime_put(hi847->dev); return ret; } @@ -2557,7 +2560,6 @@ static void hi847_assign_pad_format(const struct hi847_mode *mode, static int hi847_start_streaming(struct hi847 *hi847) { - struct i2c_client *client = v4l2_get_subdevdata(&hi847->sd); const struct hi847_reg_list *reg_list; int link_freq_index, ret; @@ -2565,14 +2567,14 @@ static int hi847_start_streaming(struct hi847 *hi847) reg_list = &link_freq_configs[link_freq_index].reg_list; ret = hi847_write_reg_list(hi847, reg_list); if (ret) { - dev_err(&client->dev, "failed to set plls"); + dev_err(hi847->dev, "failed to set plls"); return ret; } reg_list = &hi847->cur_mode->reg_list; ret = hi847_write_reg_list(hi847, reg_list); if (ret) { - dev_err(&client->dev, "failed to set mode"); + dev_err(hi847->dev, "failed to set mode"); return ret; } @@ -2587,7 +2589,7 @@ static int hi847_start_streaming(struct hi847 *hi847) HI847_REG_VALUE_16BIT, HI847_MODE_STREAMING); if (ret) { - dev_err(&client->dev, "failed to set stream"); + dev_err(hi847->dev, "failed to set stream"); return ret; } @@ -2596,28 +2598,25 @@ static int hi847_start_streaming(struct hi847 *hi847) static void hi847_stop_streaming(struct hi847 *hi847) { - struct i2c_client *client = v4l2_get_subdevdata(&hi847->sd); - if (hi847_write_reg(hi847, HI847_REG_MODE_TG, HI847_REG_VALUE_16BIT, HI847_REG_MODE_TG_DISABLE)) - dev_err(&client->dev, "failed to set stream 0x%x", + dev_err(hi847->dev, "failed to set stream 0x%x", HI847_REG_MODE_TG); if (hi847_write_reg(hi847, HI847_REG_MODE_SELECT, HI847_REG_VALUE_16BIT, HI847_MODE_STANDBY)) - dev_err(&client->dev, "failed to set stream 0x%x", + dev_err(hi847->dev, "failed to set stream 0x%x", HI847_REG_MODE_SELECT); } static int hi847_set_stream(struct v4l2_subdev *sd, int enable) { struct hi847 *hi847 = to_hi847(sd); - struct i2c_client *client = v4l2_get_subdevdata(sd); int ret = 0; mutex_lock(&hi847->mutex); if (enable) { - ret = pm_runtime_resume_and_get(&client->dev); + ret = pm_runtime_resume_and_get(hi847->dev); if (ret) { mutex_unlock(&hi847->mutex); return ret; @@ -2627,11 +2626,11 @@ static int hi847_set_stream(struct v4l2_subdev *sd, int enable) if (ret) { enable = 0; hi847_stop_streaming(hi847); - pm_runtime_put(&client->dev); + pm_runtime_put(hi847->dev); } } else { hi847_stop_streaming(hi847); - pm_runtime_put(&client->dev); + pm_runtime_put(hi847->dev); } mutex_unlock(&hi847->mutex); @@ -2768,7 +2767,6 @@ static const struct v4l2_subdev_internal_ops hi847_internal_ops = { static int hi847_identify_module(struct hi847 *hi847) { - struct i2c_client *client = v4l2_get_subdevdata(&hi847->sd); int ret; u32 val; @@ -2778,7 +2776,7 @@ static int hi847_identify_module(struct hi847 *hi847) return ret; if (val != HI847_CHIP_ID) { - dev_err(&client->dev, "chip id mismatch: %x!=%x", + dev_err(hi847->dev, "chip id mismatch: %x!=%x", HI847_CHIP_ID, val); return -ENXIO; } @@ -2793,24 +2791,12 @@ static int hi847_check_hwcfg(struct device *dev) struct v4l2_fwnode_endpoint bus_cfg = { .bus_type = V4L2_MBUS_CSI2_DPHY }; - u32 mclk; int ret; unsigned int i, j; if (!fwnode) return -ENXIO; - ret = fwnode_property_read_u32(fwnode, "clock-frequency", &mclk); - if (ret) { - dev_err(dev, "can't get clock frequency"); - return ret; - } - - if (mclk != HI847_MCLK) { - dev_err(dev, "external clock %d is not supported", mclk); - return -EINVAL; - } - ep = fwnode_graph_get_next_endpoint(fwnode, NULL); if (!ep) return -ENXIO; @@ -2862,22 +2848,36 @@ static void hi847_remove(struct i2c_client *client) v4l2_async_unregister_subdev(sd); media_entity_cleanup(&sd->entity); v4l2_ctrl_handler_free(sd->ctrl_handler); - pm_runtime_disable(&client->dev); + pm_runtime_disable(hi847->dev); mutex_destroy(&hi847->mutex); } static int hi847_probe(struct i2c_client *client) { struct hi847 *hi847; + unsigned long freq; int ret; hi847 = devm_kzalloc(&client->dev, sizeof(*hi847), GFP_KERNEL); if (!hi847) return -ENOMEM; - ret = hi847_check_hwcfg(&client->dev); + hi847->dev = &client->dev; + + hi847->clk = devm_v4l2_sensor_clk_get(hi847->dev, NULL); + if (IS_ERR(hi847->clk)) + return dev_err_probe(hi847->dev, PTR_ERR(hi847->clk), + "failed to get clock\n"); + + freq = clk_get_rate(hi847->clk); + if (freq != HI847_MCLK) + return dev_err_probe(hi847->dev, -EINVAL, + "external clock %lu is not supported\n", + freq); + + ret = hi847_check_hwcfg(hi847->dev); if (ret) { - dev_err(&client->dev, "failed to get HW configuration: %d", + dev_err(hi847->dev, "failed to get HW configuration: %d", ret); return ret; } @@ -2885,7 +2885,7 @@ static int hi847_probe(struct i2c_client *client) v4l2_i2c_subdev_init(&hi847->sd, client, &hi847_subdev_ops); ret = hi847_identify_module(hi847); if (ret) { - dev_err(&client->dev, "failed to find sensor: %d", ret); + dev_err(hi847->dev, "failed to find sensor: %d", ret); return ret; } @@ -2893,7 +2893,7 @@ static int hi847_probe(struct i2c_client *client) hi847->cur_mode = &supported_modes[0]; ret = hi847_init_controls(hi847); if (ret) { - dev_err(&client->dev, "failed to init controls: %d", ret); + dev_err(hi847->dev, "failed to init controls: %d", ret); goto probe_error_v4l2_ctrl_handler_free; } @@ -2904,20 +2904,20 @@ static int hi847_probe(struct i2c_client *client) hi847->pad.flags = MEDIA_PAD_FL_SOURCE; ret = media_entity_pads_init(&hi847->sd.entity, 1, &hi847->pad); if (ret) { - dev_err(&client->dev, "failed to init entity pads: %d", ret); + dev_err(hi847->dev, "failed to init entity pads: %d", ret); goto probe_error_v4l2_ctrl_handler_free; } ret = v4l2_async_register_subdev_sensor(&hi847->sd); if (ret < 0) { - dev_err(&client->dev, "failed to register V4L2 subdev: %d", + dev_err(hi847->dev, "failed to register V4L2 subdev: %d", ret); goto probe_error_media_entity_cleanup; } - pm_runtime_set_active(&client->dev); - pm_runtime_enable(&client->dev); - pm_runtime_idle(&client->dev); + pm_runtime_set_active(hi847->dev); + pm_runtime_enable(hi847->dev); + pm_runtime_idle(hi847->dev); return 0; diff --git a/drivers/media/i2c/imx208.c b/drivers/media/i2c/imx208.c index 2b5a6ce7b1ae..d5350bb46f14 100644 --- a/drivers/media/i2c/imx208.c +++ b/drivers/media/i2c/imx208.c @@ -2,13 +2,15 @@ // Copyright (C) 2021 Intel Corporation #include <linux/acpi.h> +#include <linux/clk.h> #include <linux/delay.h> #include <linux/i2c.h> #include <linux/module.h> #include <linux/pm_runtime.h> +#include <linux/unaligned.h> + #include <media/v4l2-ctrls.h> #include <media/v4l2-device.h> -#include <linux/unaligned.h> #define IMX208_REG_MODE_SELECT 0x0100 #define IMX208_MODE_STANDBY 0x00 @@ -268,6 +270,9 @@ static const struct imx208_mode supported_modes[] = { }; struct imx208 { + struct device *dev; + struct clk *clk; + struct v4l2_subdev sd; struct media_pad pad; @@ -372,7 +377,6 @@ static int imx208_write_reg(struct imx208 *imx208, u16 reg, u32 len, u32 val) static int imx208_write_regs(struct imx208 *imx208, const struct imx208_reg *regs, u32 len) { - struct i2c_client *client = v4l2_get_subdevdata(&imx208->sd); unsigned int i; int ret; @@ -380,7 +384,7 @@ static int imx208_write_regs(struct imx208 *imx208, ret = imx208_write_reg(imx208, regs[i].address, 1, regs[i].val); if (ret) { - dev_err_ratelimited(&client->dev, + dev_err_ratelimited(imx208->dev, "Failed to write reg 0x%4.4x. error = %d\n", regs[i].address, ret); @@ -431,14 +435,13 @@ static int imx208_set_ctrl(struct v4l2_ctrl *ctrl) { struct imx208 *imx208 = container_of(ctrl->handler, struct imx208, ctrl_handler); - struct i2c_client *client = v4l2_get_subdevdata(&imx208->sd); int ret; /* * Applying V4L2 control value only happens * when power is up for streaming */ - if (!pm_runtime_get_if_in_use(&client->dev)) + if (!pm_runtime_get_if_in_use(imx208->dev)) return 0; switch (ctrl->id) { @@ -471,13 +474,13 @@ static int imx208_set_ctrl(struct v4l2_ctrl *ctrl) break; default: ret = -EINVAL; - dev_err(&client->dev, + dev_err(imx208->dev, "ctrl(id:0x%x,val:0x%x) is not handled\n", ctrl->id, ctrl->val); break; } - pm_runtime_put(&client->dev); + pm_runtime_put(imx208->dev); return ret; } @@ -620,7 +623,6 @@ static int imx208_set_pad_format(struct v4l2_subdev *sd, static int imx208_identify_module(struct imx208 *imx208) { - struct i2c_client *client = v4l2_get_subdevdata(&imx208->sd); int ret; u32 val; @@ -630,13 +632,13 @@ static int imx208_identify_module(struct imx208 *imx208) ret = imx208_read_reg(imx208, IMX208_REG_CHIP_ID, 2, &val); if (ret) { - dev_err(&client->dev, "failed to read chip id %x\n", + dev_err(imx208->dev, "failed to read chip id %x\n", IMX208_CHIP_ID); return ret; } if (val != IMX208_CHIP_ID) { - dev_err(&client->dev, "chip id mismatch: %x!=%x\n", + dev_err(imx208->dev, "chip id mismatch: %x!=%x\n", IMX208_CHIP_ID, val); return -EIO; } @@ -649,7 +651,6 @@ static int imx208_identify_module(struct imx208 *imx208) /* Start streaming */ static int imx208_start_streaming(struct imx208 *imx208) { - struct i2c_client *client = v4l2_get_subdevdata(&imx208->sd); const struct imx208_reg_list *reg_list; int ret, link_freq_index; @@ -662,7 +663,7 @@ static int imx208_start_streaming(struct imx208 *imx208) reg_list = &link_freq_configs[link_freq_index].reg_list; ret = imx208_write_regs(imx208, reg_list->regs, reg_list->num_of_regs); if (ret) { - dev_err(&client->dev, "%s failed to set plls\n", __func__); + dev_err(imx208->dev, "%s failed to set plls\n", __func__); return ret; } @@ -670,7 +671,7 @@ static int imx208_start_streaming(struct imx208 *imx208) reg_list = &imx208->cur_mode->reg_list; ret = imx208_write_regs(imx208, reg_list->regs, reg_list->num_of_regs); if (ret) { - dev_err(&client->dev, "%s failed to set mode\n", __func__); + dev_err(imx208->dev, "%s failed to set mode\n", __func__); return ret; } @@ -687,14 +688,13 @@ static int imx208_start_streaming(struct imx208 *imx208) /* Stop streaming */ static int imx208_stop_streaming(struct imx208 *imx208) { - struct i2c_client *client = v4l2_get_subdevdata(&imx208->sd); int ret; /* set stream off register */ ret = imx208_write_reg(imx208, IMX208_REG_MODE_SELECT, 1, IMX208_MODE_STANDBY); if (ret) - dev_err(&client->dev, "%s failed to set stream\n", __func__); + dev_err(imx208->dev, "%s failed to set stream\n", __func__); /* * Return success even if it was an error, as there is nothing the @@ -706,13 +706,12 @@ static int imx208_stop_streaming(struct imx208 *imx208) static int imx208_set_stream(struct v4l2_subdev *sd, int enable) { struct imx208 *imx208 = to_imx208(sd); - struct i2c_client *client = v4l2_get_subdevdata(sd); int ret = 0; mutex_lock(&imx208->imx208_mx); if (enable) { - ret = pm_runtime_resume_and_get(&client->dev); + ret = pm_runtime_resume_and_get(imx208->dev); if (ret) { mutex_unlock(&imx208->imx208_mx); return ret; @@ -727,7 +726,7 @@ static int imx208_set_stream(struct v4l2_subdev *sd, int enable) goto err_rpm_put; } else { imx208_stop_streaming(imx208); - pm_runtime_put(&client->dev); + pm_runtime_put(imx208->dev); } mutex_unlock(&imx208->imx208_mx); @@ -739,7 +738,7 @@ static int imx208_set_stream(struct v4l2_subdev *sd, int enable) return ret; err_rpm_put: - pm_runtime_put(&client->dev); + pm_runtime_put(imx208->dev); mutex_unlock(&imx208->imx208_mx); return ret; @@ -778,7 +777,7 @@ static int imx208_read_otp(struct imx208 *imx208) if (imx208->otp_read) goto out_unlock; - ret = pm_runtime_resume_and_get(&client->dev); + ret = pm_runtime_resume_and_get(imx208->dev); if (ret) goto out_unlock; @@ -805,7 +804,7 @@ static int imx208_read_otp(struct imx208 *imx208) } out_pm_put: - pm_runtime_put(&client->dev); + pm_runtime_put(imx208->dev); out_unlock: mutex_unlock(&imx208->imx208_mx); @@ -835,7 +834,6 @@ static const BIN_ATTR_RO(otp, IMX208_OTP_SIZE); /* Initialize control handlers */ static int imx208_init_controls(struct imx208 *imx208) { - struct i2c_client *client = v4l2_get_subdevdata(&imx208->sd); struct v4l2_ctrl_handler *ctrl_hdlr = &imx208->ctrl_handler; s64 exposure_max; s64 vblank_def; @@ -914,7 +912,7 @@ static int imx208_init_controls(struct imx208 *imx208) if (ctrl_hdlr->error) { ret = ctrl_hdlr->error; - dev_err(&client->dev, "%s control init failed (%d)\n", + dev_err(imx208->dev, "%s control init failed (%d)\n", __func__, ret); goto error; } @@ -938,31 +936,36 @@ static void imx208_free_controls(struct imx208 *imx208) static int imx208_probe(struct i2c_client *client) { struct imx208 *imx208; + unsigned long freq; int ret; bool full_power; - u32 val = 0; - - device_property_read_u32(&client->dev, "clock-frequency", &val); - if (val != 19200000) { - dev_err(&client->dev, - "Unsupported clock-frequency %u. Expected 19200000.\n", - val); - return -EINVAL; - } imx208 = devm_kzalloc(&client->dev, sizeof(*imx208), GFP_KERNEL); if (!imx208) return -ENOMEM; + imx208->dev = &client->dev; + + imx208->clk = devm_v4l2_sensor_clk_get(imx208->dev, NULL); + if (IS_ERR(imx208->clk)) + return dev_err_probe(imx208->dev, PTR_ERR(imx208->clk), + "failed to get clock\n"); + + freq = clk_get_rate(imx208->clk); + if (freq != 19200000) + return dev_err_probe(imx208->dev, -EINVAL, + "external clock %lu is not supported\n", + freq); + /* Initialize subdev */ v4l2_i2c_subdev_init(&imx208->sd, client, &imx208_subdev_ops); - full_power = acpi_dev_state_d0(&client->dev); + full_power = acpi_dev_state_d0(imx208->dev); if (full_power) { /* Check module identity */ ret = imx208_identify_module(imx208); if (ret) { - dev_err(&client->dev, "failed to find sensor: %d", ret); + dev_err(imx208->dev, "failed to find sensor: %d", ret); goto error_probe; } } @@ -972,7 +975,7 @@ static int imx208_probe(struct i2c_client *client) ret = imx208_init_controls(imx208); if (ret) { - dev_err(&client->dev, "failed to init controls: %d", ret); + dev_err(imx208->dev, "failed to init controls: %d", ret); goto error_probe; } @@ -985,7 +988,7 @@ static int imx208_probe(struct i2c_client *client) imx208->pad.flags = MEDIA_PAD_FL_SOURCE; ret = media_entity_pads_init(&imx208->sd.entity, 1, &imx208->pad); if (ret) { - dev_err(&client->dev, "%s failed:%d\n", __func__, ret); + dev_err(imx208->dev, "%s failed:%d\n", __func__, ret); goto error_handler_free; } @@ -993,17 +996,17 @@ static int imx208_probe(struct i2c_client *client) if (ret < 0) goto error_media_entity; - ret = device_create_bin_file(&client->dev, &bin_attr_otp); + ret = device_create_bin_file(imx208->dev, &bin_attr_otp); if (ret) { - dev_err(&client->dev, "sysfs otp creation failed\n"); + dev_err(imx208->dev, "sysfs otp creation failed\n"); goto error_async_subdev; } /* Set the device's state to active if it's in D0 state. */ if (full_power) - pm_runtime_set_active(&client->dev); - pm_runtime_enable(&client->dev); - pm_runtime_idle(&client->dev); + pm_runtime_set_active(imx208->dev); + pm_runtime_enable(imx208->dev); + pm_runtime_idle(imx208->dev); return 0; @@ -1027,13 +1030,13 @@ static void imx208_remove(struct i2c_client *client) struct v4l2_subdev *sd = i2c_get_clientdata(client); struct imx208 *imx208 = to_imx208(sd); - device_remove_bin_file(&client->dev, &bin_attr_otp); + device_remove_bin_file(imx208->dev, &bin_attr_otp); v4l2_async_unregister_subdev(sd); media_entity_cleanup(&sd->entity); imx208_free_controls(imx208); - pm_runtime_disable(&client->dev); - pm_runtime_set_suspended(&client->dev); + pm_runtime_disable(imx208->dev); + pm_runtime_set_suspended(imx208->dev); mutex_destroy(&imx208->imx208_mx); } diff --git a/drivers/media/i2c/imx214.c b/drivers/media/i2c/imx214.c index a0cef9e61b41..94ebe625c9e6 100644 --- a/drivers/media/i2c/imx214.c +++ b/drivers/media/i2c/imx214.c @@ -881,6 +881,109 @@ static const struct v4l2_ctrl_ops imx214_ctrl_ops = { .s_ctrl = imx214_set_ctrl, }; +static int imx214_pll_calculate(struct imx214 *imx214, struct ccs_pll *pll, + unsigned int link_freq) +{ + struct ccs_pll_limits limits = { + .min_ext_clk_freq_hz = 6000000, + .max_ext_clk_freq_hz = 27000000, + + .vt_fr = { + .min_pre_pll_clk_div = 1, + .max_pre_pll_clk_div = 15, + /* Value is educated guess as we don't have a spec */ + .min_pll_ip_clk_freq_hz = 6000000, + /* Value is educated guess as we don't have a spec */ + .max_pll_ip_clk_freq_hz = 12000000, + .min_pll_multiplier = 12, + .max_pll_multiplier = 1200, + .min_pll_op_clk_freq_hz = 338000000, + .max_pll_op_clk_freq_hz = 1200000000, + }, + .vt_bk = { + .min_sys_clk_div = 2, + .max_sys_clk_div = 4, + .min_pix_clk_div = 5, + .max_pix_clk_div = 10, + .min_pix_clk_freq_hz = 30000000, + .max_pix_clk_freq_hz = 120000000, + }, + .op_bk = { + .min_sys_clk_div = 1, + .max_sys_clk_div = 2, + .min_pix_clk_div = 6, + .max_pix_clk_div = 10, + .min_pix_clk_freq_hz = 30000000, + .max_pix_clk_freq_hz = 120000000, + }, + + .min_line_length_pck_bin = IMX214_PPL_DEFAULT, + .min_line_length_pck = IMX214_PPL_DEFAULT, + }; + unsigned int num_lanes = imx214->bus_cfg.bus.mipi_csi2.num_data_lanes; + + /* + * There are no documented constraints on the sys clock frequency, for + * either branch. Recover them based on the PLL output clock frequency + * and sys_clk_div limits on one hand, and the pix clock frequency and + * the pix_clk_div limits on the other hand. + */ + limits.vt_bk.min_sys_clk_freq_hz = + max(limits.vt_fr.min_pll_op_clk_freq_hz / limits.vt_bk.max_sys_clk_div, + limits.vt_bk.min_pix_clk_freq_hz * limits.vt_bk.min_pix_clk_div); + limits.vt_bk.max_sys_clk_freq_hz = + min(limits.vt_fr.max_pll_op_clk_freq_hz / limits.vt_bk.min_sys_clk_div, + limits.vt_bk.max_pix_clk_freq_hz * limits.vt_bk.max_pix_clk_div); + + limits.op_bk.min_sys_clk_freq_hz = + max(limits.vt_fr.min_pll_op_clk_freq_hz / limits.op_bk.max_sys_clk_div, + limits.op_bk.min_pix_clk_freq_hz * limits.op_bk.min_pix_clk_div); + limits.op_bk.max_sys_clk_freq_hz = + min(limits.vt_fr.max_pll_op_clk_freq_hz / limits.op_bk.min_sys_clk_div, + limits.op_bk.max_pix_clk_freq_hz * limits.op_bk.max_pix_clk_div); + + memset(pll, 0, sizeof(*pll)); + + pll->bus_type = CCS_PLL_BUS_TYPE_CSI2_DPHY; + pll->op_lanes = num_lanes; + pll->vt_lanes = num_lanes; + pll->csi2.lanes = num_lanes; + + pll->binning_horizontal = 1; + pll->binning_vertical = 1; + pll->scale_m = 1; + pll->scale_n = 1; + pll->bits_per_pixel = + IMX214_CSI_DATA_FORMAT_RAW10 & IMX214_BITS_PER_PIXEL_MASK; + pll->flags = CCS_PLL_FLAG_LANE_SPEED_MODEL; + pll->link_freq = link_freq; + pll->ext_clk_freq_hz = clk_get_rate(imx214->xclk); + + return ccs_pll_calculate(imx214->dev, &limits, pll); +} + +static int imx214_pll_update(struct imx214 *imx214) +{ + u64 link_freq; + int ret; + + link_freq = imx214->bus_cfg.link_frequencies[imx214->link_freq->val]; + ret = imx214_pll_calculate(imx214, &imx214->pll, link_freq); + if (ret) { + dev_err(imx214->dev, "PLL calculations failed: %d\n", ret); + return ret; + } + + ret = v4l2_ctrl_s_ctrl_int64(imx214->pixel_rate, + imx214->pll.pixel_rate_pixel_array); + if (ret) { + dev_err(imx214->dev, "failed to set pixel rate\n"); + return ret; + } + + return 0; +} + static int imx214_ctrls_init(struct imx214 *imx214) { static const struct v4l2_area unit_size = { @@ -1003,6 +1106,13 @@ static int imx214_ctrls_init(struct imx214 *imx214) return ret; } + ret = imx214_pll_update(imx214); + if (ret < 0) { + v4l2_ctrl_handler_free(ctrl_hdlr); + dev_err(imx214->dev, "failed to update PLL\n"); + return ret; + } + imx214->sd.ctrl_handler = ctrl_hdlr; return 0; @@ -1029,8 +1139,8 @@ static int imx214_start_streaming(struct imx214 *imx214) return ret; } - bit_rate_mbps = (imx214->pll.pixel_rate_csi / 1000000) - * imx214->pll.bits_per_pixel; + bit_rate_mbps = imx214->pll.pixel_rate_csi / 1000000 + * imx214->pll.bits_per_pixel; ret = cci_write(imx214->regmap, IMX214_REG_REQ_LINK_BIT_RATE, IMX214_LINK_BIT_RATE_MBPS(bit_rate_mbps), NULL); if (ret) { @@ -1115,109 +1225,6 @@ err_rpm_put: return ret; } -static int imx214_pll_calculate(struct imx214 *imx214, struct ccs_pll *pll, - unsigned int link_freq) -{ - struct ccs_pll_limits limits = { - .min_ext_clk_freq_hz = 6000000, - .max_ext_clk_freq_hz = 27000000, - - .vt_fr = { - .min_pre_pll_clk_div = 1, - .max_pre_pll_clk_div = 15, - /* Value is educated guess as we don't have a spec */ - .min_pll_ip_clk_freq_hz = 6000000, - /* Value is educated guess as we don't have a spec */ - .max_pll_ip_clk_freq_hz = 12000000, - .min_pll_multiplier = 12, - .max_pll_multiplier = 1200, - .min_pll_op_clk_freq_hz = 338000000, - .max_pll_op_clk_freq_hz = 1200000000, - }, - .vt_bk = { - .min_sys_clk_div = 2, - .max_sys_clk_div = 4, - .min_pix_clk_div = 5, - .max_pix_clk_div = 10, - .min_pix_clk_freq_hz = 30000000, - .max_pix_clk_freq_hz = 120000000, - }, - .op_bk = { - .min_sys_clk_div = 1, - .max_sys_clk_div = 2, - .min_pix_clk_div = 6, - .max_pix_clk_div = 10, - .min_pix_clk_freq_hz = 30000000, - .max_pix_clk_freq_hz = 120000000, - }, - - .min_line_length_pck_bin = IMX214_PPL_DEFAULT, - .min_line_length_pck = IMX214_PPL_DEFAULT, - }; - unsigned int num_lanes = imx214->bus_cfg.bus.mipi_csi2.num_data_lanes; - - /* - * There are no documented constraints on the sys clock frequency, for - * either branch. Recover them based on the PLL output clock frequency - * and sys_clk_div limits on one hand, and the pix clock frequency and - * the pix_clk_div limits on the other hand. - */ - limits.vt_bk.min_sys_clk_freq_hz = - max(limits.vt_fr.min_pll_op_clk_freq_hz / limits.vt_bk.max_sys_clk_div, - limits.vt_bk.min_pix_clk_freq_hz * limits.vt_bk.min_pix_clk_div); - limits.vt_bk.max_sys_clk_freq_hz = - min(limits.vt_fr.max_pll_op_clk_freq_hz / limits.vt_bk.min_sys_clk_div, - limits.vt_bk.max_pix_clk_freq_hz * limits.vt_bk.max_pix_clk_div); - - limits.op_bk.min_sys_clk_freq_hz = - max(limits.vt_fr.min_pll_op_clk_freq_hz / limits.op_bk.max_sys_clk_div, - limits.op_bk.min_pix_clk_freq_hz * limits.op_bk.min_pix_clk_div); - limits.op_bk.max_sys_clk_freq_hz = - min(limits.vt_fr.max_pll_op_clk_freq_hz / limits.op_bk.min_sys_clk_div, - limits.op_bk.max_pix_clk_freq_hz * limits.op_bk.max_pix_clk_div); - - memset(pll, 0, sizeof(*pll)); - - pll->bus_type = CCS_PLL_BUS_TYPE_CSI2_DPHY; - pll->op_lanes = num_lanes; - pll->vt_lanes = num_lanes; - pll->csi2.lanes = num_lanes; - - pll->binning_horizontal = 1; - pll->binning_vertical = 1; - pll->scale_m = 1; - pll->scale_n = 1; - pll->bits_per_pixel = - IMX214_CSI_DATA_FORMAT_RAW10 & IMX214_BITS_PER_PIXEL_MASK; - pll->flags = CCS_PLL_FLAG_LANE_SPEED_MODEL; - pll->link_freq = link_freq; - pll->ext_clk_freq_hz = clk_get_rate(imx214->xclk); - - return ccs_pll_calculate(imx214->dev, &limits, pll); -} - -static int imx214_pll_update(struct imx214 *imx214) -{ - u64 link_freq; - int ret; - - link_freq = imx214->bus_cfg.link_frequencies[imx214->link_freq->val]; - ret = imx214_pll_calculate(imx214, &imx214->pll, link_freq); - if (ret) { - dev_err(imx214->dev, "PLL calculations failed: %d\n", ret); - return ret; - } - - ret = v4l2_ctrl_s_ctrl_int64(imx214->pixel_rate, - imx214->pll.pixel_rate_pixel_array); - if (ret) { - dev_err(imx214->dev, "failed to set pixel rate\n"); - return ret; - } - - return 0; -} - static int imx214_get_frame_interval(struct v4l2_subdev *subdev, struct v4l2_subdev_state *sd_state, struct v4l2_subdev_frame_interval *fival) @@ -1324,10 +1331,11 @@ static int imx214_identify_module(struct imx214 *imx214) return 0; } -static int imx214_parse_fwnode(struct device *dev, struct imx214 *imx214) +static int imx214_parse_fwnode(struct imx214 *imx214) { + struct fwnode_handle *endpoint __free(fwnode_handle) = NULL; struct v4l2_fwnode_endpoint *bus_cfg = &imx214->bus_cfg; - struct fwnode_handle *endpoint; + struct device *dev = imx214->dev; unsigned int i; int ret; @@ -1337,11 +1345,8 @@ static int imx214_parse_fwnode(struct device *dev, struct imx214 *imx214) bus_cfg->bus_type = V4L2_MBUS_CSI2_DPHY; ret = v4l2_fwnode_endpoint_alloc_parse(endpoint, bus_cfg); - fwnode_handle_put(endpoint); - if (ret) { - dev_err_probe(dev, ret, "parsing endpoint node failed\n"); - goto error; - } + if (ret) + return dev_err_probe(dev, ret, "parsing endpoint node failed\n"); /* Check the number of MIPI CSI2 data lanes */ if (bus_cfg->bus.mipi_csi2.num_data_lanes != 4) { @@ -1357,18 +1362,16 @@ static int imx214_parse_fwnode(struct device *dev, struct imx214 *imx214) u64 freq = bus_cfg->link_frequencies[i]; struct ccs_pll pll; - if (!imx214_pll_calculate(imx214, &pll, freq)) - break; if (freq == IMX214_DEFAULT_LINK_FREQ_LEGACY) { dev_warn(dev, "link-frequencies %d not supported, please review your DT. Continuing anyway\n", IMX214_DEFAULT_LINK_FREQ); freq = IMX214_DEFAULT_LINK_FREQ; - if (imx214_pll_calculate(imx214, &pll, freq)) - continue; bus_cfg->link_frequencies[i] = freq; - break; } + + if (!imx214_pll_calculate(imx214, &pll, freq)) + break; } if (i == bus_cfg->nr_of_link_frequencies) @@ -1396,7 +1399,7 @@ static int imx214_probe(struct i2c_client *client) imx214->dev = dev; - imx214->xclk = devm_clk_get(dev, NULL); + imx214->xclk = devm_v4l2_sensor_clk_get(dev, NULL); if (IS_ERR(imx214->xclk)) return dev_err_probe(dev, PTR_ERR(imx214->xclk), "failed to get xclk\n"); @@ -1415,7 +1418,7 @@ static int imx214_probe(struct i2c_client *client) return dev_err_probe(dev, PTR_ERR(imx214->regmap), "failed to initialize CCI\n"); - ret = imx214_parse_fwnode(dev, imx214); + ret = imx214_parse_fwnode(imx214); if (ret) return ret; @@ -1459,12 +1462,6 @@ static int imx214_probe(struct i2c_client *client) pm_runtime_set_active(imx214->dev); pm_runtime_enable(imx214->dev); - ret = imx214_pll_update(imx214); - if (ret < 0) { - dev_err_probe(dev, ret, "failed to update PLL\n"); - goto error_subdev_cleanup; - } - ret = v4l2_async_register_subdev_sensor(&imx214->sd); if (ret < 0) { dev_err_probe(dev, ret, diff --git a/drivers/media/i2c/imx219.c b/drivers/media/i2c/imx219.c index 3faf48f34af4..c680aa6c3a55 100644 --- a/drivers/media/i2c/imx219.c +++ b/drivers/media/i2c/imx219.c @@ -1032,6 +1032,10 @@ static int imx219_power_on(struct device *dev) goto reg_off; } + /* + * Note: Misinterpretation of reset assertion - do not re-use this code. + * XCLR pin is using incorrect (for reset signal) logical level. + */ gpiod_set_value_cansleep(imx219->reset_gpio, 1); usleep_range(IMX219_XCLR_MIN_DELAY_US, IMX219_XCLR_MIN_DELAY_US + IMX219_XCLR_DELAY_RANGE_US); @@ -1186,7 +1190,7 @@ static int imx219_probe(struct i2c_client *client) "failed to initialize CCI\n"); /* Get system clock (xclk) */ - imx219->xclk = devm_clk_get(dev, NULL); + imx219->xclk = devm_v4l2_sensor_clk_get(dev, NULL); if (IS_ERR(imx219->xclk)) return dev_err_probe(dev, PTR_ERR(imx219->xclk), "failed to get xclk\n"); diff --git a/drivers/media/i2c/imx258.c b/drivers/media/i2c/imx258.c index 9e30fce1f223..e50dcfd830f5 100644 --- a/drivers/media/i2c/imx258.c +++ b/drivers/media/i2c/imx258.c @@ -8,11 +8,12 @@ #include <linux/module.h> #include <linux/pm_runtime.h> #include <linux/regulator/consumer.h> +#include <linux/unaligned.h> + #include <media/v4l2-cci.h> #include <media/v4l2-ctrls.h> #include <media/v4l2-device.h> #include <media/v4l2-fwnode.h> -#include <linux/unaligned.h> #define IMX258_REG_MODE_SELECT CCI_REG8(0x0100) #define IMX258_MODE_STANDBY 0x00 @@ -645,6 +646,8 @@ static const struct imx258_mode supported_modes[] = { }; struct imx258 { + struct device *dev; + struct v4l2_subdev sd; struct media_pad pad; struct regmap *regmap; @@ -751,7 +754,6 @@ static int imx258_set_ctrl(struct v4l2_ctrl *ctrl) { struct imx258 *imx258 = container_of(ctrl->handler, struct imx258, ctrl_handler); - struct i2c_client *client = v4l2_get_subdevdata(&imx258->sd); int ret = 0; /* @@ -765,7 +767,7 @@ static int imx258_set_ctrl(struct v4l2_ctrl *ctrl) * Applying V4L2 control value only happens * when power is up for streaming */ - if (pm_runtime_get_if_in_use(&client->dev) == 0) + if (pm_runtime_get_if_in_use(imx258->dev) == 0) return 0; switch (ctrl->id) { @@ -811,14 +813,14 @@ static int imx258_set_ctrl(struct v4l2_ctrl *ctrl) NULL); break; default: - dev_info(&client->dev, + dev_info(imx258->dev, "ctrl(id:0x%x,val:0x%x) is not handled\n", ctrl->id, ctrl->val); ret = -EINVAL; break; } - pm_runtime_put(&client->dev); + pm_runtime_put(imx258->dev); return ret; } @@ -1013,14 +1015,13 @@ static int imx258_get_selection(struct v4l2_subdev *sd, /* Start streaming */ static int imx258_start_streaming(struct imx258 *imx258) { - struct i2c_client *client = v4l2_get_subdevdata(&imx258->sd); const struct imx258_reg_list *reg_list; const struct imx258_link_freq_config *link_freq_cfg; int ret, link_freq_index; ret = cci_write(imx258->regmap, IMX258_REG_RESET, 0x01, NULL); if (ret) { - dev_err(&client->dev, "%s failed to reset sensor\n", __func__); + dev_err(imx258->dev, "%s failed to reset sensor\n", __func__); return ret; } @@ -1034,21 +1035,21 @@ static int imx258_start_streaming(struct imx258 *imx258) reg_list = &link_freq_cfg->link_cfg[imx258->lane_mode_idx].reg_list; ret = cci_multi_reg_write(imx258->regmap, reg_list->regs, reg_list->num_of_regs, NULL); if (ret) { - dev_err(&client->dev, "%s failed to set plls\n", __func__); + dev_err(imx258->dev, "%s failed to set plls\n", __func__); return ret; } ret = cci_multi_reg_write(imx258->regmap, mode_common_regs, ARRAY_SIZE(mode_common_regs), NULL); if (ret) { - dev_err(&client->dev, "%s failed to set common regs\n", __func__); + dev_err(imx258->dev, "%s failed to set common regs\n", __func__); return ret; } ret = cci_multi_reg_write(imx258->regmap, imx258->variant_cfg->regs, imx258->variant_cfg->num_regs, NULL); if (ret) { - dev_err(&client->dev, "%s failed to set variant config\n", + dev_err(imx258->dev, "%s failed to set variant config\n", __func__); return ret; } @@ -1057,7 +1058,7 @@ static int imx258_start_streaming(struct imx258 *imx258) !!(imx258->csi2_flags & V4L2_MBUS_CSI2_NONCONTINUOUS_CLOCK), NULL); if (ret) { - dev_err(&client->dev, "%s failed to set clock lane mode\n", __func__); + dev_err(imx258->dev, "%s failed to set clock lane mode\n", __func__); return ret; } @@ -1065,7 +1066,7 @@ static int imx258_start_streaming(struct imx258 *imx258) reg_list = &imx258->cur_mode->reg_list; ret = cci_multi_reg_write(imx258->regmap, reg_list->regs, reg_list->num_of_regs, NULL); if (ret) { - dev_err(&client->dev, "%s failed to set mode\n", __func__); + dev_err(imx258->dev, "%s failed to set mode\n", __func__); return ret; } @@ -1082,14 +1083,13 @@ static int imx258_start_streaming(struct imx258 *imx258) /* Stop streaming */ static int imx258_stop_streaming(struct imx258 *imx258) { - struct i2c_client *client = v4l2_get_subdevdata(&imx258->sd); int ret; /* set stream off register */ ret = cci_write(imx258->regmap, IMX258_REG_MODE_SELECT, IMX258_MODE_STANDBY, NULL); if (ret) - dev_err(&client->dev, "%s failed to set stream\n", __func__); + dev_err(imx258->dev, "%s failed to set stream\n", __func__); /* * Return success even if it was an error, as there is nothing the @@ -1135,13 +1135,12 @@ static int imx258_power_off(struct device *dev) static int imx258_set_stream(struct v4l2_subdev *sd, int enable) { struct imx258 *imx258 = to_imx258(sd); - struct i2c_client *client = v4l2_get_subdevdata(sd); int ret = 0; mutex_lock(&imx258->mutex); if (enable) { - ret = pm_runtime_resume_and_get(&client->dev); + ret = pm_runtime_resume_and_get(imx258->dev); if (ret < 0) goto err_unlock; @@ -1154,7 +1153,7 @@ static int imx258_set_stream(struct v4l2_subdev *sd, int enable) goto err_rpm_put; } else { imx258_stop_streaming(imx258); - pm_runtime_put(&client->dev); + pm_runtime_put(imx258->dev); } mutex_unlock(&imx258->mutex); @@ -1162,7 +1161,7 @@ static int imx258_set_stream(struct v4l2_subdev *sd, int enable) return ret; err_rpm_put: - pm_runtime_put(&client->dev); + pm_runtime_put(imx258->dev); err_unlock: mutex_unlock(&imx258->mutex); @@ -1172,20 +1171,19 @@ err_unlock: /* Verify chip ID */ static int imx258_identify_module(struct imx258 *imx258) { - struct i2c_client *client = v4l2_get_subdevdata(&imx258->sd); int ret; u64 val; ret = cci_read(imx258->regmap, IMX258_REG_CHIP_ID, &val, NULL); if (ret) { - dev_err(&client->dev, "failed to read chip id %x\n", + dev_err(imx258->dev, "failed to read chip id %x\n", IMX258_CHIP_ID); return ret; } if (val != IMX258_CHIP_ID) { - dev_err(&client->dev, "chip id mismatch: %x!=%llx\n", + dev_err(imx258->dev, "chip id mismatch: %x!=%llx\n", IMX258_CHIP_ID, val); return -EIO; } @@ -1217,7 +1215,6 @@ static const struct v4l2_subdev_internal_ops imx258_internal_ops = { /* Initialize control handlers */ static int imx258_init_controls(struct imx258 *imx258) { - struct i2c_client *client = v4l2_get_subdevdata(&imx258->sd); const struct imx258_link_freq_config *link_freq_cfgs; struct v4l2_fwnode_device_properties props; struct v4l2_ctrl_handler *ctrl_hdlr; @@ -1308,12 +1305,12 @@ static int imx258_init_controls(struct imx258 *imx258) if (ctrl_hdlr->error) { ret = ctrl_hdlr->error; - dev_err(&client->dev, "%s control init failed (%d)\n", + dev_err(imx258->dev, "%s control init failed (%d)\n", __func__, ret); goto error; } - ret = v4l2_fwnode_device_parse(&client->dev, &props); + ret = v4l2_fwnode_device_parse(imx258->dev, &props); if (ret) goto error; @@ -1339,15 +1336,14 @@ static void imx258_free_controls(struct imx258 *imx258) mutex_destroy(&imx258->mutex); } -static int imx258_get_regulators(struct imx258 *imx258, - struct i2c_client *client) +static int imx258_get_regulators(struct imx258 *imx258) { unsigned int i; for (i = 0; i < IMX258_NUM_SUPPLIES; i++) imx258->supplies[i].supply = imx258_supply_name[i]; - return devm_regulator_bulk_get(&client->dev, + return devm_regulator_bulk_get(imx258->dev, IMX258_NUM_SUPPLIES, imx258->supplies); } @@ -1365,30 +1361,27 @@ static int imx258_probe(struct i2c_client *client) if (!imx258) return -ENOMEM; + imx258->dev = &client->dev; + imx258->regmap = devm_cci_regmap_init_i2c(client, 16); if (IS_ERR(imx258->regmap)) { ret = PTR_ERR(imx258->regmap); - dev_err(&client->dev, "failed to initialize CCI: %d\n", ret); + dev_err(imx258->dev, "failed to initialize CCI: %d\n", ret); return ret; } - ret = imx258_get_regulators(imx258, client); + ret = imx258_get_regulators(imx258); if (ret) - return dev_err_probe(&client->dev, ret, + return dev_err_probe(imx258->dev, ret, "failed to get regulators\n"); - imx258->clk = devm_clk_get_optional(&client->dev, NULL); + imx258->clk = devm_v4l2_sensor_clk_get_legacy(imx258->dev, NULL, false, + 0); if (IS_ERR(imx258->clk)) - return dev_err_probe(&client->dev, PTR_ERR(imx258->clk), + return dev_err_probe(imx258->dev, PTR_ERR(imx258->clk), "error getting clock\n"); - if (!imx258->clk) { - dev_dbg(&client->dev, - "no clock provided, using clock-frequency property\n"); - device_property_read_u32(&client->dev, "clock-frequency", &val); - } else { - val = clk_get_rate(imx258->clk); - } + val = clk_get_rate(imx258->clk); switch (val) { case 19200000: @@ -1400,32 +1393,32 @@ static int imx258_probe(struct i2c_client *client) imx258->link_freq_menu_items = link_freq_menu_items_24; break; default: - dev_err(&client->dev, "input clock frequency of %u not supported\n", + dev_err(imx258->dev, "input clock frequency of %u not supported\n", val); return -EINVAL; } - endpoint = fwnode_graph_get_next_endpoint(dev_fwnode(&client->dev), NULL); + endpoint = fwnode_graph_get_next_endpoint(dev_fwnode(imx258->dev), NULL); if (!endpoint) { - dev_err(&client->dev, "Endpoint node not found\n"); + dev_err(imx258->dev, "Endpoint node not found\n"); return -EINVAL; } ret = v4l2_fwnode_endpoint_alloc_parse(endpoint, &ep); fwnode_handle_put(endpoint); if (ret) { - dev_err(&client->dev, "Parsing endpoint node failed\n"); + dev_err(imx258->dev, "Parsing endpoint node failed\n"); return ret; } - ret = v4l2_link_freq_to_bitmap(&client->dev, + ret = v4l2_link_freq_to_bitmap(imx258->dev, ep.link_frequencies, ep.nr_of_link_frequencies, imx258->link_freq_menu_items, ARRAY_SIZE(link_freq_menu_items_19_2), &imx258->link_freq_bitmap); if (ret) { - dev_err(&client->dev, "Link frequency not supported\n"); + dev_err(imx258->dev, "Link frequency not supported\n"); goto error_endpoint_free; } @@ -1438,7 +1431,7 @@ static int imx258_probe(struct i2c_client *client) imx258->lane_mode_idx = IMX258_4_LANE_MODE; break; default: - dev_err(&client->dev, "Invalid data lanes: %u\n", + dev_err(imx258->dev, "Invalid data lanes: %u\n", ep.bus.mipi_csi2.num_data_lanes); ret = -EINVAL; goto error_endpoint_free; @@ -1446,7 +1439,7 @@ static int imx258_probe(struct i2c_client *client) imx258->csi2_flags = ep.bus.mipi_csi2.flags; - imx258->variant_cfg = device_get_match_data(&client->dev); + imx258->variant_cfg = device_get_match_data(imx258->dev); if (!imx258->variant_cfg) imx258->variant_cfg = &imx258_cfg; @@ -1454,7 +1447,7 @@ static int imx258_probe(struct i2c_client *client) v4l2_i2c_subdev_init(&imx258->sd, client, &imx258_subdev_ops); /* Will be powered off via pm_runtime_idle */ - ret = imx258_power_on(&client->dev); + ret = imx258_power_on(imx258->dev); if (ret) goto error_endpoint_free; @@ -1486,9 +1479,9 @@ static int imx258_probe(struct i2c_client *client) if (ret < 0) goto error_media_entity; - pm_runtime_set_active(&client->dev); - pm_runtime_enable(&client->dev); - pm_runtime_idle(&client->dev); + pm_runtime_set_active(imx258->dev); + pm_runtime_enable(imx258->dev); + pm_runtime_idle(imx258->dev); v4l2_fwnode_endpoint_free(&ep); return 0; @@ -1500,7 +1493,7 @@ error_handler_free: imx258_free_controls(imx258); error_identify: - imx258_power_off(&client->dev); + imx258_power_off(imx258->dev); error_endpoint_free: v4l2_fwnode_endpoint_free(&ep); @@ -1517,10 +1510,10 @@ static void imx258_remove(struct i2c_client *client) media_entity_cleanup(&sd->entity); imx258_free_controls(imx258); - pm_runtime_disable(&client->dev); - if (!pm_runtime_status_suspended(&client->dev)) - imx258_power_off(&client->dev); - pm_runtime_set_suspended(&client->dev); + pm_runtime_disable(imx258->dev); + if (!pm_runtime_status_suspended(imx258->dev)) + imx258_power_off(imx258->dev); + pm_runtime_set_suspended(imx258->dev); } static const struct dev_pm_ops imx258_pm_ops = { diff --git a/drivers/media/i2c/imx274.c b/drivers/media/i2c/imx274.c index a2b824986027..d86d08c29174 100644 --- a/drivers/media/i2c/imx274.c +++ b/drivers/media/i2c/imx274.c @@ -826,6 +826,8 @@ static int imx274_start_stream(struct stimx274 *priv) * if rst = 0, keep it in reset; * if rst = 1, bring it out of reset. * + * Note: Misinterpretation of reset assertion - do not re-use this code. + * XCLR pin is using incorrect (for reset signal) logical level. */ static void imx274_reset(struct stimx274 *priv, int rst) { diff --git a/drivers/media/i2c/imx283.c b/drivers/media/i2c/imx283.c index 67e8bb432d10..8ab63ad8f385 100644 --- a/drivers/media/i2c/imx283.c +++ b/drivers/media/i2c/imx283.c @@ -1460,11 +1460,10 @@ static int imx283_probe(struct i2c_client *client) } /* Get system clock (xclk) */ - imx283->xclk = devm_clk_get(imx283->dev, NULL); - if (IS_ERR(imx283->xclk)) { + imx283->xclk = devm_v4l2_sensor_clk_get(imx283->dev, NULL); + if (IS_ERR(imx283->xclk)) return dev_err_probe(imx283->dev, PTR_ERR(imx283->xclk), "failed to get xclk\n"); - } xclk_freq = clk_get_rate(imx283->xclk); for (i = 0; i < ARRAY_SIZE(imx283_frequencies); i++) { diff --git a/drivers/media/i2c/imx290.c b/drivers/media/i2c/imx290.c index ec172556612e..21cbc81cb2ed 100644 --- a/drivers/media/i2c/imx290.c +++ b/drivers/media/i2c/imx290.c @@ -1422,14 +1422,14 @@ static int imx290_get_regulators(struct device *dev, struct imx290 *imx290) static int imx290_init_clk(struct imx290 *imx290) { u32 xclk_freq; - int ret; - ret = device_property_read_u32(imx290->dev, "clock-frequency", - &xclk_freq); - if (ret) { - dev_err(imx290->dev, "Could not get xclk frequency\n"); - return ret; - } + imx290->xclk = devm_v4l2_sensor_clk_get_legacy(imx290->dev, "xclk", + false, 0); + if (IS_ERR(imx290->xclk)) + return dev_err_probe(imx290->dev, PTR_ERR(imx290->xclk), + "Could not get xclk\n"); + + xclk_freq = clk_get_rate(imx290->xclk); /* external clock must be 37.125 MHz or 74.25MHz */ switch (xclk_freq) { @@ -1445,12 +1445,6 @@ static int imx290_init_clk(struct imx290 *imx290) return -EINVAL; } - ret = clk_set_rate(imx290->xclk, xclk_freq); - if (ret) { - dev_err(imx290->dev, "Could not set xclk frequency\n"); - return ret; - } - return 0; } @@ -1596,11 +1590,6 @@ static int imx290_probe(struct i2c_client *client) return ret; /* Acquire resources. */ - imx290->xclk = devm_clk_get(dev, "xclk"); - if (IS_ERR(imx290->xclk)) - return dev_err_probe(dev, PTR_ERR(imx290->xclk), - "Could not get xclk\n"); - ret = imx290_get_regulators(dev, imx290); if (ret < 0) return dev_err_probe(dev, ret, "Cannot get regulators\n"); @@ -1611,7 +1600,7 @@ static int imx290_probe(struct i2c_client *client) return dev_err_probe(dev, PTR_ERR(imx290->rst_gpio), "Cannot get reset gpio\n"); - /* Initialize external clock frequency. */ + /* Initialize external clock. */ ret = imx290_init_clk(imx290); if (ret) return ret; diff --git a/drivers/media/i2c/imx296.c b/drivers/media/i2c/imx296.c index 61116f4e3f76..69636db11a2b 100644 --- a/drivers/media/i2c/imx296.c +++ b/drivers/media/i2c/imx296.c @@ -921,7 +921,7 @@ static int imx296_read_temperature(struct imx296 *sensor, int *temp) tmdout &= IMX296_TMDOUT_MASK; - /* T(°C) = 246.312 - 0.304 * TMDOUT */; + /* T(°C) = 246.312 - 0.304 * TMDOUT */ *temp = 246312 - 304 * tmdout; return imx296_write(sensor, IMX296_TMDCTRL, 0, NULL); @@ -1043,7 +1043,7 @@ static int imx296_probe(struct i2c_client *client) return dev_err_probe(sensor->dev, PTR_ERR(sensor->reset), "failed to get reset GPIO\n"); - sensor->clk = devm_clk_get(sensor->dev, "inck"); + sensor->clk = devm_v4l2_sensor_clk_get(sensor->dev, "inck"); if (IS_ERR(sensor->clk)) return dev_err_probe(sensor->dev, PTR_ERR(sensor->clk), "failed to get clock\n"); diff --git a/drivers/media/i2c/imx319.c b/drivers/media/i2c/imx319.c index 701840f4a5cc..953310ef3046 100644 --- a/drivers/media/i2c/imx319.c +++ b/drivers/media/i2c/imx319.c @@ -1,11 +1,13 @@ // SPDX-License-Identifier: GPL-2.0 // Copyright (C) 2018 Intel Corporation -#include <linux/unaligned.h> #include <linux/acpi.h> +#include <linux/clk.h> #include <linux/i2c.h> #include <linux/module.h> #include <linux/pm_runtime.h> +#include <linux/unaligned.h> + #include <media/v4l2-ctrls.h> #include <media/v4l2-device.h> #include <media/v4l2-event.h> @@ -106,11 +108,12 @@ struct imx319_mode { }; struct imx319_hwcfg { - u32 ext_clk; /* sensor external clk */ unsigned long link_freq_bitmap; }; struct imx319 { + struct device *dev; + struct v4l2_subdev sd; struct media_pad pad; @@ -1839,14 +1842,13 @@ static int imx319_write_reg(struct imx319 *imx319, u16 reg, u32 len, u32 val) static int imx319_write_regs(struct imx319 *imx319, const struct imx319_reg *regs, u32 len) { - struct i2c_client *client = v4l2_get_subdevdata(&imx319->sd); int ret; u32 i; for (i = 0; i < len; i++) { ret = imx319_write_reg(imx319, regs[i].address, 1, regs[i].val); if (ret) { - dev_err_ratelimited(&client->dev, + dev_err_ratelimited(imx319->dev, "write reg 0x%4.4x return err %d", regs[i].address, ret); return ret; @@ -1880,7 +1882,6 @@ static int imx319_set_ctrl(struct v4l2_ctrl *ctrl) { struct imx319 *imx319 = container_of(ctrl->handler, struct imx319, ctrl_handler); - struct i2c_client *client = v4l2_get_subdevdata(&imx319->sd); s64 max; int ret; @@ -1899,7 +1900,7 @@ static int imx319_set_ctrl(struct v4l2_ctrl *ctrl) * Applying V4L2 control value only happens * when power is up for streaming */ - if (!pm_runtime_get_if_in_use(&client->dev)) + if (!pm_runtime_get_if_in_use(imx319->dev)) return 0; switch (ctrl->id) { @@ -1933,12 +1934,12 @@ static int imx319_set_ctrl(struct v4l2_ctrl *ctrl) break; default: ret = -EINVAL; - dev_info(&client->dev, "ctrl(id:0x%x,val:0x%x) is not handled", + dev_info(imx319->dev, "ctrl(id:0x%x,val:0x%x) is not handled", ctrl->id, ctrl->val); break; } - pm_runtime_put(&client->dev); + pm_runtime_put(imx319->dev); return ret; } @@ -2087,7 +2088,6 @@ imx319_set_pad_format(struct v4l2_subdev *sd, /* Verify chip ID */ static int imx319_identify_module(struct imx319 *imx319) { - struct i2c_client *client = v4l2_get_subdevdata(&imx319->sd); int ret; u32 val; @@ -2099,7 +2099,7 @@ static int imx319_identify_module(struct imx319 *imx319) return ret; if (val != IMX319_CHIP_ID) { - dev_err(&client->dev, "chip id mismatch: %x!=%x", + dev_err(imx319->dev, "chip id mismatch: %x!=%x", IMX319_CHIP_ID, val); return -EIO; } @@ -2112,7 +2112,6 @@ static int imx319_identify_module(struct imx319 *imx319) /* Start streaming */ static int imx319_start_streaming(struct imx319 *imx319) { - struct i2c_client *client = v4l2_get_subdevdata(&imx319->sd); const struct imx319_reg_list *reg_list; int ret; @@ -2124,7 +2123,7 @@ static int imx319_start_streaming(struct imx319 *imx319) reg_list = &imx319_global_setting; ret = imx319_write_regs(imx319, reg_list->regs, reg_list->num_of_regs); if (ret) { - dev_err(&client->dev, "failed to set global settings"); + dev_err(imx319->dev, "failed to set global settings"); return ret; } @@ -2132,7 +2131,7 @@ static int imx319_start_streaming(struct imx319 *imx319) reg_list = &imx319->cur_mode->reg_list; ret = imx319_write_regs(imx319, reg_list->regs, reg_list->num_of_regs); if (ret) { - dev_err(&client->dev, "failed to set mode"); + dev_err(imx319->dev, "failed to set mode"); return ret; } @@ -2160,13 +2159,12 @@ static int imx319_stop_streaming(struct imx319 *imx319) static int imx319_set_stream(struct v4l2_subdev *sd, int enable) { struct imx319 *imx319 = to_imx319(sd); - struct i2c_client *client = v4l2_get_subdevdata(sd); int ret = 0; mutex_lock(&imx319->mutex); if (enable) { - ret = pm_runtime_resume_and_get(&client->dev); + ret = pm_runtime_resume_and_get(imx319->dev); if (ret < 0) goto err_unlock; @@ -2179,7 +2177,7 @@ static int imx319_set_stream(struct v4l2_subdev *sd, int enable) goto err_rpm_put; } else { imx319_stop_streaming(imx319); - pm_runtime_put(&client->dev); + pm_runtime_put(imx319->dev); } /* vflip and hflip cannot change during streaming */ @@ -2191,7 +2189,7 @@ static int imx319_set_stream(struct v4l2_subdev *sd, int enable) return ret; err_rpm_put: - pm_runtime_put(&client->dev); + pm_runtime_put(imx319->dev); err_unlock: mutex_unlock(&imx319->mutex); @@ -2231,7 +2229,6 @@ static const struct v4l2_subdev_internal_ops imx319_internal_ops = { /* Initialize control handlers */ static int imx319_init_controls(struct imx319 *imx319) { - struct i2c_client *client = v4l2_get_subdevdata(&imx319->sd); struct v4l2_ctrl_handler *ctrl_hdlr; s64 exposure_max; s64 vblank_def; @@ -2311,7 +2308,7 @@ static int imx319_init_controls(struct imx319 *imx319) 0, 0, imx319_test_pattern_menu); if (ctrl_hdlr->error) { ret = ctrl_hdlr->error; - dev_err(&client->dev, "control init failed: %d", ret); + dev_err(imx319->dev, "control init failed: %d", ret); goto error; } @@ -2350,20 +2347,6 @@ static struct imx319_hwcfg *imx319_get_hwcfg(struct device *dev) if (!cfg) goto out_err; - ret = fwnode_property_read_u32(dev_fwnode(dev), "clock-frequency", - &cfg->ext_clk); - if (ret) { - dev_err(dev, "can't get clock frequency"); - goto out_err; - } - - dev_dbg(dev, "ext clk: %d", cfg->ext_clk); - if (cfg->ext_clk != IMX319_EXT_CLK) { - dev_err(dev, "external clock %d is not supported", - cfg->ext_clk); - goto out_err; - } - ret = v4l2_link_freq_to_bitmap(dev, bus_cfg.link_frequencies, bus_cfg.nr_of_link_frequencies, link_freq_menu_items, @@ -2385,6 +2368,8 @@ out_err: static int imx319_probe(struct i2c_client *client) { struct imx319 *imx319; + unsigned long freq; + struct clk *clk; bool full_power; int ret; @@ -2392,24 +2377,37 @@ static int imx319_probe(struct i2c_client *client) if (!imx319) return -ENOMEM; + imx319->dev = &client->dev; + mutex_init(&imx319->mutex); + clk = devm_v4l2_sensor_clk_get(imx319->dev, NULL); + if (IS_ERR(clk)) + return dev_err_probe(imx319->dev, PTR_ERR(clk), + "failed to acquire clock\n"); + + freq = clk_get_rate(clk); + if (freq != IMX319_EXT_CLK) + return dev_err_probe(imx319->dev, -EINVAL, + "external clock %lu is not supported", + freq); + /* Initialize subdev */ v4l2_i2c_subdev_init(&imx319->sd, client, &imx319_subdev_ops); - full_power = acpi_dev_state_d0(&client->dev); + full_power = acpi_dev_state_d0(imx319->dev); if (full_power) { /* Check module identity */ ret = imx319_identify_module(imx319); if (ret) { - dev_err(&client->dev, "failed to find sensor: %d", ret); + dev_err(imx319->dev, "failed to find sensor: %d", ret); goto error_probe; } } - imx319->hwcfg = imx319_get_hwcfg(&client->dev); + imx319->hwcfg = imx319_get_hwcfg(imx319->dev); if (!imx319->hwcfg) { - dev_err(&client->dev, "failed to get hwcfg"); + dev_err(imx319->dev, "failed to get hwcfg"); ret = -ENODEV; goto error_probe; } @@ -2419,7 +2417,7 @@ static int imx319_probe(struct i2c_client *client) ret = imx319_init_controls(imx319); if (ret) { - dev_err(&client->dev, "failed to init controls: %d", ret); + dev_err(imx319->dev, "failed to init controls: %d", ret); goto error_probe; } @@ -2434,27 +2432,27 @@ static int imx319_probe(struct i2c_client *client) imx319->pad.flags = MEDIA_PAD_FL_SOURCE; ret = media_entity_pads_init(&imx319->sd.entity, 1, &imx319->pad); if (ret) { - dev_err(&client->dev, "failed to init entity pads: %d", ret); + dev_err(imx319->dev, "failed to init entity pads: %d", ret); goto error_handler_free; } /* Set the device's state to active if it's in D0 state. */ if (full_power) - pm_runtime_set_active(&client->dev); - pm_runtime_enable(&client->dev); + pm_runtime_set_active(imx319->dev); + pm_runtime_enable(imx319->dev); ret = v4l2_async_register_subdev_sensor(&imx319->sd); if (ret < 0) goto error_media_entity_pm; - pm_runtime_idle(&client->dev); + pm_runtime_idle(imx319->dev); return 0; error_media_entity_pm: - pm_runtime_disable(&client->dev); + pm_runtime_disable(imx319->dev); if (full_power) - pm_runtime_set_suspended(&client->dev); + pm_runtime_set_suspended(imx319->dev); media_entity_cleanup(&imx319->sd.entity); error_handler_free: @@ -2475,9 +2473,9 @@ static void imx319_remove(struct i2c_client *client) media_entity_cleanup(&sd->entity); v4l2_ctrl_handler_free(sd->ctrl_handler); - pm_runtime_disable(&client->dev); - if (!pm_runtime_status_suspended(&client->dev)) - pm_runtime_set_suspended(&client->dev); + pm_runtime_disable(imx319->dev); + if (!pm_runtime_status_suspended(imx319->dev)) + pm_runtime_set_suspended(imx319->dev); mutex_destroy(&imx319->mutex); } diff --git a/drivers/media/i2c/imx334.c b/drivers/media/i2c/imx334.c index 846b9928d4e8..9654f9268056 100644 --- a/drivers/media/i2c/imx334.c +++ b/drivers/media/i2c/imx334.c @@ -118,6 +118,9 @@ #define IMX334_REG_TP CCI_REG8(0x329e) #define IMX334_TP_COLOR_HBARS 0xa #define IMX334_TP_COLOR_VBARS 0xb +#define IMX334_TP_BLACK 0x0 +#define IMX334_TP_WHITE 0x1 +#define IMX334_TP_BLACK_GREY 0xc #define IMX334_TPG_EN_DOUT CCI_REG8(0x329c) #define IMX334_TP_ENABLE 0x1 @@ -398,12 +401,18 @@ static const char * const imx334_test_pattern_menu[] = { "Disabled", "Vertical Color Bars", "Horizontal Color Bars", + "Black and Grey Bars", + "Black Color", + "White Color", }; static const int imx334_test_pattern_val[] = { IMX334_TP_DISABLE, IMX334_TP_COLOR_HBARS, IMX334_TP_COLOR_VBARS, + IMX334_TP_BLACK_GREY, + IMX334_TP_BLACK, + IMX334_TP_WHITE, }; static const struct cci_reg_sequence raw10_framefmt_regs[] = { @@ -997,7 +1006,7 @@ static int imx334_parse_hw_config(struct imx334 *imx334) "failed to get reset gpio\n"); /* Get sensor input clock */ - imx334->inclk = devm_clk_get(imx334->dev, NULL); + imx334->inclk = devm_v4l2_sensor_clk_get(imx334->dev, NULL); if (IS_ERR(imx334->inclk)) return dev_err_probe(imx334->dev, PTR_ERR(imx334->inclk), "could not get inclk\n"); @@ -1070,6 +1079,10 @@ static int imx334_power_on(struct device *dev) struct imx334 *imx334 = to_imx334(sd); int ret; + /* + * Note: Misinterpretation of reset assertion - do not re-use this code. + * XCLR pin is using incorrect (for reset signal) logical level. + */ gpiod_set_value_cansleep(imx334->reset_gpio, 1); ret = clk_prepare_enable(imx334->inclk); diff --git a/drivers/media/i2c/imx335.c b/drivers/media/i2c/imx335.c index 9b4db4cd4929..c043df2f15fb 100644 --- a/drivers/media/i2c/imx335.c +++ b/drivers/media/i2c/imx335.c @@ -1026,11 +1026,10 @@ static int imx335_parse_hw_config(struct imx335 *imx335) } /* Get sensor input clock */ - imx335->inclk = devm_clk_get(imx335->dev, NULL); - if (IS_ERR(imx335->inclk)) { - dev_err(imx335->dev, "could not get inclk\n"); - return PTR_ERR(imx335->inclk); - } + imx335->inclk = devm_v4l2_sensor_clk_get(imx335->dev, NULL); + if (IS_ERR(imx335->inclk)) + return dev_err_probe(imx335->dev, PTR_ERR(imx335->inclk), + "could not get inclk\n"); rate = clk_get_rate(imx335->inclk); if (rate != IMX335_INCLK_RATE) { diff --git a/drivers/media/i2c/imx355.c b/drivers/media/i2c/imx355.c index b2dce67c0b6b..776107efe386 100644 --- a/drivers/media/i2c/imx355.c +++ b/drivers/media/i2c/imx355.c @@ -1,11 +1,13 @@ // SPDX-License-Identifier: GPL-2.0 // Copyright (C) 2018 Intel Corporation -#include <linux/unaligned.h> #include <linux/acpi.h> +#include <linux/clk.h> #include <linux/i2c.h> #include <linux/module.h> #include <linux/pm_runtime.h> +#include <linux/unaligned.h> + #include <media/v4l2-ctrls.h> #include <media/v4l2-device.h> #include <media/v4l2-event.h> @@ -92,11 +94,13 @@ struct imx355_mode { }; struct imx355_hwcfg { - u32 ext_clk; /* sensor external clk */ unsigned long link_freq_bitmap; }; struct imx355 { + struct device *dev; + struct clk *clk; + struct v4l2_subdev sd; struct media_pad pad; @@ -1136,14 +1140,13 @@ static int imx355_write_reg(struct imx355 *imx355, u16 reg, u32 len, u32 val) static int imx355_write_regs(struct imx355 *imx355, const struct imx355_reg *regs, u32 len) { - struct i2c_client *client = v4l2_get_subdevdata(&imx355->sd); int ret; u32 i; for (i = 0; i < len; i++) { ret = imx355_write_reg(imx355, regs[i].address, 1, regs[i].val); if (ret) { - dev_err_ratelimited(&client->dev, + dev_err_ratelimited(imx355->dev, "write reg 0x%4.4x return err %d", regs[i].address, ret); @@ -1178,7 +1181,6 @@ static int imx355_set_ctrl(struct v4l2_ctrl *ctrl) { struct imx355 *imx355 = container_of(ctrl->handler, struct imx355, ctrl_handler); - struct i2c_client *client = v4l2_get_subdevdata(&imx355->sd); s64 max; int ret; @@ -1197,7 +1199,7 @@ static int imx355_set_ctrl(struct v4l2_ctrl *ctrl) * Applying V4L2 control value only happens * when power is up for streaming */ - if (!pm_runtime_get_if_in_use(&client->dev)) + if (!pm_runtime_get_if_in_use(imx355->dev)) return 0; switch (ctrl->id) { @@ -1231,12 +1233,12 @@ static int imx355_set_ctrl(struct v4l2_ctrl *ctrl) break; default: ret = -EINVAL; - dev_info(&client->dev, "ctrl(id:0x%x,val:0x%x) is not handled", + dev_info(imx355->dev, "ctrl(id:0x%x,val:0x%x) is not handled", ctrl->id, ctrl->val); break; } - pm_runtime_put(&client->dev); + pm_runtime_put(imx355->dev); return ret; } @@ -1385,7 +1387,6 @@ imx355_set_pad_format(struct v4l2_subdev *sd, /* Start streaming */ static int imx355_start_streaming(struct imx355 *imx355) { - struct i2c_client *client = v4l2_get_subdevdata(&imx355->sd); const struct imx355_reg_list *reg_list; int ret; @@ -1393,7 +1394,7 @@ static int imx355_start_streaming(struct imx355 *imx355) reg_list = &imx355_global_setting; ret = imx355_write_regs(imx355, reg_list->regs, reg_list->num_of_regs); if (ret) { - dev_err(&client->dev, "failed to set global settings"); + dev_err(imx355->dev, "failed to set global settings"); return ret; } @@ -1401,7 +1402,7 @@ static int imx355_start_streaming(struct imx355 *imx355) reg_list = &imx355->cur_mode->reg_list; ret = imx355_write_regs(imx355, reg_list->regs, reg_list->num_of_regs); if (ret) { - dev_err(&client->dev, "failed to set mode"); + dev_err(imx355->dev, "failed to set mode"); return ret; } @@ -1429,13 +1430,12 @@ static int imx355_stop_streaming(struct imx355 *imx355) static int imx355_set_stream(struct v4l2_subdev *sd, int enable) { struct imx355 *imx355 = to_imx355(sd); - struct i2c_client *client = v4l2_get_subdevdata(sd); int ret = 0; mutex_lock(&imx355->mutex); if (enable) { - ret = pm_runtime_resume_and_get(&client->dev); + ret = pm_runtime_resume_and_get(imx355->dev); if (ret < 0) goto err_unlock; @@ -1448,7 +1448,7 @@ static int imx355_set_stream(struct v4l2_subdev *sd, int enable) goto err_rpm_put; } else { imx355_stop_streaming(imx355); - pm_runtime_put(&client->dev); + pm_runtime_put(imx355->dev); } /* vflip and hflip cannot change during streaming */ @@ -1460,7 +1460,7 @@ static int imx355_set_stream(struct v4l2_subdev *sd, int enable) return ret; err_rpm_put: - pm_runtime_put(&client->dev); + pm_runtime_put(imx355->dev); err_unlock: mutex_unlock(&imx355->mutex); @@ -1470,7 +1470,6 @@ err_unlock: /* Verify chip ID */ static int imx355_identify_module(struct imx355 *imx355) { - struct i2c_client *client = v4l2_get_subdevdata(&imx355->sd); int ret; u32 val; @@ -1479,7 +1478,7 @@ static int imx355_identify_module(struct imx355 *imx355) return ret; if (val != IMX355_CHIP_ID) { - dev_err(&client->dev, "chip id mismatch: %x!=%x", + dev_err(imx355->dev, "chip id mismatch: %x!=%x", IMX355_CHIP_ID, val); return -EIO; } @@ -1519,7 +1518,6 @@ static const struct v4l2_subdev_internal_ops imx355_internal_ops = { /* Initialize control handlers */ static int imx355_init_controls(struct imx355 *imx355) { - struct i2c_client *client = v4l2_get_subdevdata(&imx355->sd); struct v4l2_fwnode_device_properties props; struct v4l2_ctrl_handler *ctrl_hdlr; s64 exposure_max; @@ -1600,11 +1598,11 @@ static int imx355_init_controls(struct imx355 *imx355) 0, 0, imx355_test_pattern_menu); if (ctrl_hdlr->error) { ret = ctrl_hdlr->error; - dev_err(&client->dev, "control init failed: %d", ret); + dev_err(imx355->dev, "control init failed: %d", ret); goto error; } - ret = v4l2_fwnode_device_parse(&client->dev, &props); + ret = v4l2_fwnode_device_parse(imx355->dev, &props); if (ret) goto error; @@ -1648,20 +1646,6 @@ static struct imx355_hwcfg *imx355_get_hwcfg(struct device *dev) if (!cfg) goto out_err; - ret = fwnode_property_read_u32(dev_fwnode(dev), "clock-frequency", - &cfg->ext_clk); - if (ret) { - dev_err(dev, "can't get clock frequency"); - goto out_err; - } - - dev_dbg(dev, "ext clk: %d", cfg->ext_clk); - if (cfg->ext_clk != IMX355_EXT_CLK) { - dev_err(dev, "external clock %d is not supported", - cfg->ext_clk); - goto out_err; - } - ret = v4l2_link_freq_to_bitmap(dev, bus_cfg.link_frequencies, bus_cfg.nr_of_link_frequencies, link_freq_menu_items, @@ -1683,27 +1667,41 @@ out_err: static int imx355_probe(struct i2c_client *client) { struct imx355 *imx355; + unsigned long freq; int ret; imx355 = devm_kzalloc(&client->dev, sizeof(*imx355), GFP_KERNEL); if (!imx355) return -ENOMEM; + imx355->dev = &client->dev; + mutex_init(&imx355->mutex); + imx355->clk = devm_v4l2_sensor_clk_get(imx355->dev, NULL); + if (IS_ERR(imx355->clk)) + return dev_err_probe(imx355->dev, PTR_ERR(imx355->clk), + "failed to get clock\n"); + + freq = clk_get_rate(imx355->clk); + if (freq != IMX355_EXT_CLK) + return dev_err_probe(imx355->dev, -EINVAL, + "external clock %lu is not supported\n", + freq); + /* Initialize subdev */ v4l2_i2c_subdev_init(&imx355->sd, client, &imx355_subdev_ops); /* Check module identity */ ret = imx355_identify_module(imx355); if (ret) { - dev_err(&client->dev, "failed to find sensor: %d", ret); + dev_err(imx355->dev, "failed to find sensor: %d", ret); goto error_probe; } - imx355->hwcfg = imx355_get_hwcfg(&client->dev); + imx355->hwcfg = imx355_get_hwcfg(imx355->dev); if (!imx355->hwcfg) { - dev_err(&client->dev, "failed to get hwcfg"); + dev_err(imx355->dev, "failed to get hwcfg"); ret = -ENODEV; goto error_probe; } @@ -1713,7 +1711,7 @@ static int imx355_probe(struct i2c_client *client) ret = imx355_init_controls(imx355); if (ret) { - dev_err(&client->dev, "failed to init controls: %d", ret); + dev_err(imx355->dev, "failed to init controls: %d", ret); goto error_probe; } @@ -1728,7 +1726,7 @@ static int imx355_probe(struct i2c_client *client) imx355->pad.flags = MEDIA_PAD_FL_SOURCE; ret = media_entity_pads_init(&imx355->sd.entity, 1, &imx355->pad); if (ret) { - dev_err(&client->dev, "failed to init entity pads: %d", ret); + dev_err(imx355->dev, "failed to init entity pads: %d", ret); goto error_handler_free; } @@ -1736,9 +1734,9 @@ static int imx355_probe(struct i2c_client *client) * Device is already turned on by i2c-core with ACPI domain PM. * Enable runtime PM and turn off the device. */ - pm_runtime_set_active(&client->dev); - pm_runtime_enable(&client->dev); - pm_runtime_idle(&client->dev); + pm_runtime_set_active(imx355->dev); + pm_runtime_enable(imx355->dev); + pm_runtime_idle(imx355->dev); ret = v4l2_async_register_subdev_sensor(&imx355->sd); if (ret < 0) @@ -1747,8 +1745,8 @@ static int imx355_probe(struct i2c_client *client) return 0; error_media_entity_runtime_pm: - pm_runtime_disable(&client->dev); - pm_runtime_set_suspended(&client->dev); + pm_runtime_disable(imx355->dev); + pm_runtime_set_suspended(imx355->dev); media_entity_cleanup(&imx355->sd.entity); error_handler_free: @@ -1769,8 +1767,8 @@ static void imx355_remove(struct i2c_client *client) media_entity_cleanup(&sd->entity); v4l2_ctrl_handler_free(sd->ctrl_handler); - pm_runtime_disable(&client->dev); - pm_runtime_set_suspended(&client->dev); + pm_runtime_disable(imx355->dev); + pm_runtime_set_suspended(imx355->dev); mutex_destroy(&imx355->mutex); } diff --git a/drivers/media/i2c/imx412.c b/drivers/media/i2c/imx412.c index c74097a59c42..7bbd639a9ddf 100644 --- a/drivers/media/i2c/imx412.c +++ b/drivers/media/i2c/imx412.c @@ -933,11 +933,10 @@ static int imx412_parse_hw_config(struct imx412 *imx412) } /* Get sensor input clock */ - imx412->inclk = devm_clk_get(imx412->dev, NULL); - if (IS_ERR(imx412->inclk)) { - dev_err(imx412->dev, "could not get inclk\n"); - return PTR_ERR(imx412->inclk); - } + imx412->inclk = devm_v4l2_sensor_clk_get(imx412->dev, NULL); + if (IS_ERR(imx412->inclk)) + return dev_err_probe(imx412->dev, PTR_ERR(imx412->inclk), + "could not get inclk\n"); rate = clk_get_rate(imx412->inclk); if (rate != IMX412_INCLK_RATE) { diff --git a/drivers/media/i2c/imx415.c b/drivers/media/i2c/imx415.c index 276bf4d6f39d..0b424c17e880 100644 --- a/drivers/media/i2c/imx415.c +++ b/drivers/media/i2c/imx415.c @@ -1250,7 +1250,7 @@ static int imx415_parse_hw_config(struct imx415 *sensor) return dev_err_probe(sensor->dev, PTR_ERR(sensor->reset), "failed to get reset GPIO\n"); - sensor->clk = devm_clk_get(sensor->dev, NULL); + sensor->clk = devm_v4l2_sensor_clk_get(sensor->dev, NULL); if (IS_ERR(sensor->clk)) return dev_err_probe(sensor->dev, PTR_ERR(sensor->clk), "failed to get clock\n"); diff --git a/drivers/media/i2c/ir-kbd-i2c.c b/drivers/media/i2c/ir-kbd-i2c.c index c84e1e0e6109..5588cdd7ec20 100644 --- a/drivers/media/i2c/ir-kbd-i2c.c +++ b/drivers/media/i2c/ir-kbd-i2c.c @@ -321,9 +321,9 @@ static int get_key_avermedia_cardbus(struct IR_i2c *ir, enum rc_proto *protocol, static int ir_key_poll(struct IR_i2c *ir) { - enum rc_proto protocol; - u32 scancode; - u8 toggle; + enum rc_proto protocol = 0; + u32 scancode = 0; + u8 toggle = 0; int rc; dev_dbg(&ir->rc->dev, "%s\n", __func__); diff --git a/drivers/media/i2c/mt9m001.c b/drivers/media/i2c/mt9m001.c index 12d3e86bdc0f..7a6114d18dfc 100644 --- a/drivers/media/i2c/mt9m001.c +++ b/drivers/media/i2c/mt9m001.c @@ -743,9 +743,10 @@ static int mt9m001_probe(struct i2c_client *client) if (!mt9m001) return -ENOMEM; - mt9m001->clk = devm_clk_get(&client->dev, NULL); + mt9m001->clk = devm_v4l2_sensor_clk_get(&client->dev, NULL); if (IS_ERR(mt9m001->clk)) - return PTR_ERR(mt9m001->clk); + return dev_err_probe(&client->dev, PTR_ERR(mt9m001->clk), + "failed to get the clock\n"); mt9m001->standby_gpio = devm_gpiod_get_optional(&client->dev, "standby", GPIOD_OUT_LOW); diff --git a/drivers/media/i2c/mt9m111.c b/drivers/media/i2c/mt9m111.c index 9aa5dcda3805..05dcf37c6f01 100644 --- a/drivers/media/i2c/mt9m111.c +++ b/drivers/media/i2c/mt9m111.c @@ -1279,9 +1279,10 @@ static int mt9m111_probe(struct i2c_client *client) return ret; } - mt9m111->clk = devm_clk_get(&client->dev, "mclk"); + mt9m111->clk = devm_v4l2_sensor_clk_get(&client->dev, "mclk"); if (IS_ERR(mt9m111->clk)) - return PTR_ERR(mt9m111->clk); + return dev_err_probe(&client->dev, PTR_ERR(mt9m111->clk), + "failed to get mclk\n"); mt9m111->regulator = devm_regulator_get(&client->dev, "vdd"); if (IS_ERR(mt9m111->regulator)) { diff --git a/drivers/media/i2c/mt9m114.c b/drivers/media/i2c/mt9m114.c index aa3fd6c6c76c..51ebbe7ae996 100644 --- a/drivers/media/i2c/mt9m114.c +++ b/drivers/media/i2c/mt9m114.c @@ -18,6 +18,7 @@ #include <linux/module.h> #include <linux/mutex.h> #include <linux/pm_runtime.h> +#include <linux/property.h> #include <linux/regmap.h> #include <linux/regulator/consumer.h> #include <linux/types.h> @@ -42,6 +43,9 @@ #define MT9M114_RESET_AND_MISC_CONTROL CCI_REG16(0x001a) #define MT9M114_RESET_SOC BIT(0) #define MT9M114_PAD_SLEW CCI_REG16(0x001e) +#define MT9M114_PAD_SLEW_MIN 0 +#define MT9M114_PAD_SLEW_MAX 7 +#define MT9M114_PAD_SLEW_DEFAULT 7 #define MT9M114_PAD_CONTROL CCI_REG16(0x0032) /* XDMA registers */ @@ -388,6 +392,7 @@ struct mt9m114 { unsigned int pixrate; bool streaming; + u32 pad_slew_rate; /* Pixel Array */ struct { @@ -645,9 +650,6 @@ static const struct cci_reg_sequence mt9m114_init[] = { { MT9M114_CAM_SENSOR_CFG_FINE_INTEG_TIME_MAX, 1459 }, { MT9M114_CAM_SENSOR_CFG_FINE_CORRECTION, 96 }, { MT9M114_CAM_SENSOR_CFG_REG_0_DATA, 32 }, - - /* Miscellaneous settings */ - { MT9M114_PAD_SLEW, 0x0777 }, }; /* ----------------------------------------------------------------------------- @@ -779,6 +781,13 @@ static int mt9m114_initialize(struct mt9m114 *sensor) if (ret < 0) return ret; + value = sensor->pad_slew_rate + | sensor->pad_slew_rate << 4 + | sensor->pad_slew_rate << 8; + cci_write(sensor->regmap, MT9M114_PAD_SLEW, value, &ret); + if (ret < 0) + return ret; + ret = mt9m114_set_state(sensor, MT9M114_SYS_STATE_ENTER_CONFIG_CHANGE); if (ret < 0) return ret; @@ -1283,6 +1292,7 @@ static int mt9m114_pa_set_selection(struct v4l2_subdev *sd, struct mt9m114 *sensor = pa_to_mt9m114(sd); struct v4l2_mbus_framefmt *format; struct v4l2_rect *crop; + int ret = 0; if (sel->target != V4L2_SEL_TGT_CROP) return -EINVAL; @@ -1298,25 +1308,41 @@ static int mt9m114_pa_set_selection(struct v4l2_subdev *sd, * binning, but binning is configured after setting the selection, so * we can't know tell here if it will be used. */ - crop->left = ALIGN(sel->r.left, 4); - crop->top = ALIGN(sel->r.top, 2); - crop->width = clamp_t(unsigned int, ALIGN(sel->r.width, 4), - MT9M114_PIXEL_ARRAY_MIN_OUTPUT_WIDTH, - MT9M114_PIXEL_ARRAY_WIDTH - crop->left); - crop->height = clamp_t(unsigned int, ALIGN(sel->r.height, 2), - MT9M114_PIXEL_ARRAY_MIN_OUTPUT_HEIGHT, - MT9M114_PIXEL_ARRAY_HEIGHT - crop->top); - - sel->r = *crop; + sel->r.left = ALIGN(sel->r.left, 4); + sel->r.top = ALIGN(sel->r.top, 2); + sel->r.width = clamp_t(unsigned int, ALIGN(sel->r.width, 4), + MT9M114_PIXEL_ARRAY_MIN_OUTPUT_WIDTH, + MT9M114_PIXEL_ARRAY_WIDTH - sel->r.left); + sel->r.height = clamp_t(unsigned int, ALIGN(sel->r.height, 2), + MT9M114_PIXEL_ARRAY_MIN_OUTPUT_HEIGHT, + MT9M114_PIXEL_ARRAY_HEIGHT - sel->r.top); + + /* Changing the selection size is not allowed in streaming state. */ + if (sensor->streaming && + (sel->r.height != crop->height || sel->r.width != crop->width)) + return -EBUSY; + + *crop = sel->r; /* Reset the format. */ format->width = crop->width; format->height = crop->height; - if (sel->which == V4L2_SUBDEV_FORMAT_ACTIVE) - mt9m114_pa_ctrl_update_blanking(sensor, format); + if (sel->which != V4L2_SUBDEV_FORMAT_ACTIVE) + return ret; - return 0; + mt9m114_pa_ctrl_update_blanking(sensor, format); + + /* Apply values immediately if streaming. */ + if (sensor->streaming) { + ret = mt9m114_configure_pa(sensor, state); + if (ret) + return ret; + /* Changing the cropping config requires a CONFIG_CHANGE. */ + ret = mt9m114_set_state(sensor, + MT9M114_SYS_STATE_ENTER_CONFIG_CHANGE); + } + return ret; } static const struct v4l2_subdev_pad_ops mt9m114_pa_pad_ops = { @@ -2360,6 +2386,17 @@ static int mt9m114_parse_dt(struct mt9m114 *sensor) goto error; } + sensor->pad_slew_rate = MT9M114_PAD_SLEW_DEFAULT; + device_property_read_u32(&sensor->client->dev, "slew-rate", + &sensor->pad_slew_rate); + + if (sensor->pad_slew_rate < MT9M114_PAD_SLEW_MIN || + sensor->pad_slew_rate > MT9M114_PAD_SLEW_MAX) { + dev_err(&sensor->client->dev, "Invalid slew-rate %u\n", + sensor->pad_slew_rate); + return -EINVAL; + } + return 0; error: @@ -2390,10 +2427,10 @@ static int mt9m114_probe(struct i2c_client *client) return ret; /* Acquire clocks, GPIOs and regulators. */ - sensor->clk = devm_clk_get(dev, NULL); + sensor->clk = devm_v4l2_sensor_clk_get(dev, NULL); if (IS_ERR(sensor->clk)) { - ret = PTR_ERR(sensor->clk); - dev_err_probe(dev, ret, "Failed to get clock\n"); + ret = dev_err_probe(dev, PTR_ERR(sensor->clk), + "Failed to get clock\n"); goto error_ep_free; } diff --git a/drivers/media/i2c/mt9p031.c b/drivers/media/i2c/mt9p031.c index 4ef5fb06131d..1500ee4db47e 100644 --- a/drivers/media/i2c/mt9p031.c +++ b/drivers/media/i2c/mt9p031.c @@ -233,9 +233,10 @@ static int mt9p031_clk_setup(struct mt9p031 *mt9p031) unsigned long ext_freq; int ret; - mt9p031->clk = devm_clk_get(&client->dev, NULL); + mt9p031->clk = devm_v4l2_sensor_clk_get(&client->dev, NULL); if (IS_ERR(mt9p031->clk)) - return PTR_ERR(mt9p031->clk); + return dev_err_probe(&client->dev, PTR_ERR(mt9p031->clk), + "failed to get the clock\n"); ret = clk_set_rate(mt9p031->clk, mt9p031->ext_freq); if (ret < 0) @@ -1092,6 +1093,7 @@ static int mt9p031_parse_properties(struct mt9p031 *mt9p031, struct device *dev) static int mt9p031_probe(struct i2c_client *client) { struct i2c_adapter *adapter = client->adapter; + const struct mt9p031_model_info *info; struct mt9p031 *mt9p031; unsigned int i; int ret; @@ -1112,7 +1114,8 @@ static int mt9p031_probe(struct i2c_client *client) mt9p031->output_control = MT9P031_OUTPUT_CONTROL_DEF; mt9p031->mode2 = MT9P031_READ_MODE_2_ROW_BLC; - mt9p031->code = (uintptr_t)device_get_match_data(&client->dev); + info = device_get_match_data(&client->dev); + mt9p031->code = info->code; mt9p031->regulators[0].supply = "vdd"; mt9p031->regulators[1].supply = "vdd_io"; diff --git a/drivers/media/i2c/mt9t112.c b/drivers/media/i2c/mt9t112.c index 878dff9b7577..2d2c840fc002 100644 --- a/drivers/media/i2c/mt9t112.c +++ b/drivers/media/i2c/mt9t112.c @@ -1078,13 +1078,12 @@ static int mt9t112_probe(struct i2c_client *client) v4l2_i2c_subdev_init(&priv->subdev, client, &mt9t112_subdev_ops); - priv->clk = devm_clk_get(&client->dev, "extclk"); - if (PTR_ERR(priv->clk) == -ENOENT) { + priv->clk = devm_v4l2_sensor_clk_get(&client->dev, "extclk"); + if (PTR_ERR(priv->clk) == -ENOENT) priv->clk = NULL; - } else if (IS_ERR(priv->clk)) { - dev_err(&client->dev, "Unable to get clock \"extclk\"\n"); - return PTR_ERR(priv->clk); - } + else if (IS_ERR(priv->clk)) + return dev_err_probe(&client->dev, PTR_ERR(priv->clk), + "Unable to get clock \"extclk\"\n"); priv->standby_gpio = devm_gpiod_get_optional(&client->dev, "standby", GPIOD_OUT_HIGH); diff --git a/drivers/media/i2c/mt9v032.c b/drivers/media/i2c/mt9v032.c index 302120ff125e..d4359d5b92bb 100644 --- a/drivers/media/i2c/mt9v032.c +++ b/drivers/media/i2c/mt9v032.c @@ -15,16 +15,15 @@ #include <linux/i2c.h> #include <linux/log2.h> #include <linux/mod_devicetable.h> +#include <linux/module.h> #include <linux/mutex.h> #include <linux/of.h> #include <linux/of_graph.h> #include <linux/regmap.h> #include <linux/slab.h> -#include <linux/videodev2.h> #include <linux/v4l2-mediabus.h> -#include <linux/module.h> +#include <linux/videodev2.h> -#include <media/i2c/mt9v032.h> #include <media/v4l2-ctrls.h> #include <media/v4l2-device.h> #include <media/v4l2-fwnode.h> @@ -182,7 +181,16 @@ static const struct mt9v032_model_version mt9v032_versions[] = { { MT9V034_CHIP_ID_REV1, "MT9V024/MT9V034 rev1" }, }; +struct mt9v032_platform_data { + unsigned int clk_pol:1; + + const s64 *link_freqs; + s64 link_def_freq; +}; + struct mt9v032 { + struct device *dev; + struct v4l2_subdev subdev; struct media_pad pad; @@ -205,7 +213,7 @@ struct mt9v032 { struct gpio_desc *reset_gpio; struct gpio_desc *standby_gpio; - struct mt9v032_platform_data *pdata; + struct mt9v032_platform_data pdata; const struct mt9v032_model_info *model; const struct mt9v032_model_version *version; @@ -330,7 +338,7 @@ static int __mt9v032_set_power(struct mt9v032 *mt9v032, bool on) return ret; /* Configure the pixel clock polarity */ - if (mt9v032->pdata && mt9v032->pdata->clk_pol) { + if (mt9v032->pdata.clk_pol) { ret = regmap_write(map, mt9v032->model->data->pclk_reg, MT9V032_PIXEL_CLOCK_INV_PXL_CLK); if (ret < 0) @@ -473,13 +481,12 @@ static int mt9v032_get_format(struct v4l2_subdev *subdev, static void mt9v032_configure_pixel_rate(struct mt9v032 *mt9v032) { - struct i2c_client *client = v4l2_get_subdevdata(&mt9v032->subdev); int ret; ret = v4l2_ctrl_s_ctrl_int64(mt9v032->pixel_rate, mt9v032->sysclk / mt9v032->hratio); if (ret < 0) - dev_warn(&client->dev, "failed to set pixel rate (%d)\n", ret); + dev_warn(mt9v032->dev, "failed to set pixel rate (%d)\n", ret); } static unsigned int mt9v032_calc_ratio(unsigned int input, unsigned int output) @@ -682,7 +689,7 @@ static int mt9v032_s_ctrl(struct v4l2_ctrl *ctrl) if (mt9v032->link_freq == NULL) break; - freq = mt9v032->pdata->link_freqs[mt9v032->link_freq->val]; + freq = mt9v032->pdata.link_freqs[mt9v032->link_freq->val]; *mt9v032->pixel_rate->p_new.p_s64 = freq; mt9v032->sysclk = freq; break; @@ -883,12 +890,12 @@ static int mt9v032_registered(struct v4l2_subdev *subdev) u32 version; int ret; - dev_info(&client->dev, "Probing MT9V032 at address 0x%02x\n", + dev_info(mt9v032->dev, "Probing MT9V032 at address 0x%02x\n", client->addr); ret = mt9v032_power_on(mt9v032); if (ret < 0) { - dev_err(&client->dev, "MT9V032 power up failed\n"); + dev_err(mt9v032->dev, "MT9V032 power up failed\n"); return ret; } @@ -898,7 +905,7 @@ static int mt9v032_registered(struct v4l2_subdev *subdev) mt9v032_power_off(mt9v032); if (ret < 0) { - dev_err(&client->dev, "Failed reading chip version\n"); + dev_err(mt9v032->dev, "Failed reading chip version\n"); return ret; } @@ -910,12 +917,12 @@ static int mt9v032_registered(struct v4l2_subdev *subdev) } if (mt9v032->version == NULL) { - dev_err(&client->dev, "Unsupported chip version 0x%04x\n", + dev_err(mt9v032->dev, "Unsupported chip version 0x%04x\n", version); return -ENODEV; } - dev_info(&client->dev, "%s detected at address 0x%02x\n", + dev_info(mt9v032->dev, "%s detected at address 0x%02x\n", mt9v032->version->name, client->addr); mt9v032_configure_pixel_rate(mt9v032); @@ -995,41 +1002,33 @@ static const struct regmap_config mt9v032_regmap_config = { * Driver initialization and probing */ -static struct mt9v032_platform_data * -mt9v032_get_pdata(struct i2c_client *client) +static int mt9v032_get_pdata(struct mt9v032 *mt9v032) { - struct mt9v032_platform_data *pdata = NULL; + struct mt9v032_platform_data *pdata = &mt9v032->pdata; struct v4l2_fwnode_endpoint endpoint = { .bus_type = 0 }; - struct device_node *np; + struct device_node *np __free(device_node) = NULL; struct property *prop; - if (!IS_ENABLED(CONFIG_OF) || !client->dev.of_node) - return client->dev.platform_data; - - np = of_graph_get_endpoint_by_regs(client->dev.of_node, 0, -1); + np = of_graph_get_endpoint_by_regs(mt9v032->dev->of_node, 0, -1); if (!np) - return NULL; + return -EINVAL; if (v4l2_fwnode_endpoint_parse(of_fwnode_handle(np), &endpoint) < 0) - goto done; - - pdata = devm_kzalloc(&client->dev, sizeof(*pdata), GFP_KERNEL); - if (!pdata) - goto done; + return -EINVAL; prop = of_find_property(np, "link-frequencies", NULL); if (prop) { u64 *link_freqs; size_t size = prop->length / sizeof(*link_freqs); - link_freqs = devm_kcalloc(&client->dev, size, + link_freqs = devm_kcalloc(mt9v032->dev, size, sizeof(*link_freqs), GFP_KERNEL); if (!link_freqs) - goto done; + return -EINVAL; if (of_property_read_u64_array(np, "link-frequencies", link_freqs, size) < 0) - goto done; + return -EINVAL; pdata->link_freqs = link_freqs; pdata->link_def_freq = link_freqs[0]; @@ -1038,14 +1037,11 @@ mt9v032_get_pdata(struct i2c_client *client) pdata->clk_pol = !!(endpoint.bus.parallel.flags & V4L2_MBUS_PCLK_SAMPLE_RISING); -done: - of_node_put(np); - return pdata; + return 0; } static int mt9v032_probe(struct i2c_client *client) { - struct mt9v032_platform_data *pdata = mt9v032_get_pdata(client); struct mt9v032 *mt9v032; unsigned int i; int ret; @@ -1054,27 +1050,35 @@ static int mt9v032_probe(struct i2c_client *client) if (!mt9v032) return -ENOMEM; + mt9v032->dev = &client->dev; + mt9v032->regmap = devm_regmap_init_i2c(client, &mt9v032_regmap_config); if (IS_ERR(mt9v032->regmap)) return PTR_ERR(mt9v032->regmap); - mt9v032->clk = devm_clk_get(&client->dev, NULL); + mt9v032->clk = devm_v4l2_sensor_clk_get(mt9v032->dev, NULL); if (IS_ERR(mt9v032->clk)) - return PTR_ERR(mt9v032->clk); + return dev_err_probe(mt9v032->dev, PTR_ERR(mt9v032->clk), + "failed to get the clock\n"); - mt9v032->reset_gpio = devm_gpiod_get_optional(&client->dev, "reset", + mt9v032->reset_gpio = devm_gpiod_get_optional(mt9v032->dev, "reset", GPIOD_OUT_HIGH); if (IS_ERR(mt9v032->reset_gpio)) return PTR_ERR(mt9v032->reset_gpio); - mt9v032->standby_gpio = devm_gpiod_get_optional(&client->dev, "standby", + mt9v032->standby_gpio = devm_gpiod_get_optional(mt9v032->dev, "standby", GPIOD_OUT_LOW); if (IS_ERR(mt9v032->standby_gpio)) return PTR_ERR(mt9v032->standby_gpio); mutex_init(&mt9v032->power_lock); - mt9v032->pdata = pdata; - mt9v032->model = i2c_get_match_data(client); + + ret = mt9v032_get_pdata(mt9v032); + if (ret) + return dev_err_probe(mt9v032->dev, -EINVAL, + "Failed to parse DT properties\n"); + + mt9v032->model = device_get_match_data(mt9v032->dev); v4l2_ctrl_handler_init(&mt9v032->ctrls, 11 + ARRAY_SIZE(mt9v032_aegc_controls)); @@ -1119,7 +1123,8 @@ static int mt9v032_probe(struct i2c_client *client) v4l2_ctrl_new_std(&mt9v032->ctrls, &mt9v032_ctrl_ops, V4L2_CID_PIXEL_RATE, 1, INT_MAX, 1, 1); - if (pdata && pdata->link_freqs) { + if (mt9v032->pdata.link_freqs) { + const struct mt9v032_platform_data *pdata = &mt9v032->pdata; unsigned int def = 0; for (i = 0; pdata->link_freqs[i]; ++i) { @@ -1139,7 +1144,7 @@ static int mt9v032_probe(struct i2c_client *client) mt9v032->subdev.ctrl_handler = &mt9v032->ctrls; if (mt9v032->ctrls.error) { - dev_err(&client->dev, "control initialization error %d\n", + dev_err(mt9v032->dev, "control initialization error %d\n", mt9v032->ctrls.error); ret = mt9v032->ctrls.error; goto err; @@ -1177,7 +1182,7 @@ static int mt9v032_probe(struct i2c_client *client) if (ret < 0) goto err; - mt9v032->subdev.dev = &client->dev; + mt9v032->subdev.dev = mt9v032->dev; ret = v4l2_async_register_subdev(&mt9v032->subdev); if (ret < 0) goto err; @@ -1261,19 +1266,6 @@ static const struct mt9v032_model_info mt9v032_models[] = { }, }; -static const struct i2c_device_id mt9v032_id[] = { - { "mt9v022", (kernel_ulong_t)&mt9v032_models[MT9V032_MODEL_V022_COLOR] }, - { "mt9v022m", (kernel_ulong_t)&mt9v032_models[MT9V032_MODEL_V022_MONO] }, - { "mt9v024", (kernel_ulong_t)&mt9v032_models[MT9V032_MODEL_V024_COLOR] }, - { "mt9v024m", (kernel_ulong_t)&mt9v032_models[MT9V032_MODEL_V024_MONO] }, - { "mt9v032", (kernel_ulong_t)&mt9v032_models[MT9V032_MODEL_V032_COLOR] }, - { "mt9v032m", (kernel_ulong_t)&mt9v032_models[MT9V032_MODEL_V032_MONO] }, - { "mt9v034", (kernel_ulong_t)&mt9v032_models[MT9V032_MODEL_V034_COLOR] }, - { "mt9v034m", (kernel_ulong_t)&mt9v032_models[MT9V032_MODEL_V034_MONO] }, - { /* Sentinel */ } -}; -MODULE_DEVICE_TABLE(i2c, mt9v032_id); - static const struct of_device_id mt9v032_of_match[] = { { .compatible = "aptina,mt9v022", .data = &mt9v032_models[MT9V032_MODEL_V022_COLOR] }, { .compatible = "aptina,mt9v022m", .data = &mt9v032_models[MT9V032_MODEL_V022_MONO] }, @@ -1294,7 +1286,6 @@ static struct i2c_driver mt9v032_driver = { }, .probe = mt9v032_probe, .remove = mt9v032_remove, - .id_table = mt9v032_id, }; module_i2c_driver(mt9v032_driver); diff --git a/drivers/media/i2c/mt9v111.c b/drivers/media/i2c/mt9v111.c index 723fe138e7bc..b4f2703faa18 100644 --- a/drivers/media/i2c/mt9v111.c +++ b/drivers/media/i2c/mt9v111.c @@ -365,8 +365,6 @@ static int __mt9v111_power_on(struct v4l2_subdev *sd) if (ret) return ret; - clk_set_rate(mt9v111->clk, mt9v111->sysclk); - gpiod_set_value(mt9v111->standby, 0); usleep_range(500, 1000); @@ -532,8 +530,8 @@ static int mt9v111_calc_frame_rate(struct mt9v111_dev *mt9v111, static int mt9v111_hw_config(struct mt9v111_dev *mt9v111) { struct i2c_client *c = mt9v111->client; - unsigned int ret; u16 outfmtctrl2; + int ret; /* Force device reset. */ ret = __mt9v111_hw_reset(mt9v111); @@ -1129,9 +1127,10 @@ static int mt9v111_probe(struct i2c_client *client) mt9v111->dev = &client->dev; mt9v111->client = client; - mt9v111->clk = devm_clk_get(&client->dev, NULL); + mt9v111->clk = devm_v4l2_sensor_clk_get(&client->dev, NULL); if (IS_ERR(mt9v111->clk)) - return PTR_ERR(mt9v111->clk); + return dev_err_probe(&client->dev, PTR_ERR(mt9v111->clk), + "failed to get the clock\n"); mt9v111->sysclk = clk_get_rate(mt9v111->clk); if (mt9v111->sysclk > MT9V111_MAX_CLKIN) diff --git a/drivers/media/i2c/og01a1b.c b/drivers/media/i2c/og01a1b.c index 78d5d406e4b7..c7184de6251a 100644 --- a/drivers/media/i2c/og01a1b.c +++ b/drivers/media/i2c/og01a1b.c @@ -1,7 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 // Copyright (c) 2022 Intel Corporation. -#include <linux/unaligned.h> #include <linux/acpi.h> #include <linux/clk.h> #include <linux/delay.h> @@ -10,6 +9,8 @@ #include <linux/module.h> #include <linux/pm_runtime.h> #include <linux/regulator/consumer.h> +#include <linux/unaligned.h> + #include <media/v4l2-ctrls.h> #include <media/v4l2-device.h> #include <media/v4l2-fwnode.h> @@ -421,6 +422,7 @@ static const struct og01a1b_mode supported_modes[] = { }; struct og01a1b { + struct device *dev; struct clk *xvclk; struct gpio_desc *reset_gpio; struct regulator *avdd; @@ -512,7 +514,6 @@ static int og01a1b_write_reg(struct og01a1b *og01a1b, u16 reg, u16 len, u32 val) static int og01a1b_write_reg_list(struct og01a1b *og01a1b, const struct og01a1b_reg_list *r_list) { - struct i2c_client *client = v4l2_get_subdevdata(&og01a1b->sd); unsigned int i; int ret; @@ -520,7 +521,7 @@ static int og01a1b_write_reg_list(struct og01a1b *og01a1b, ret = og01a1b_write_reg(og01a1b, r_list->regs[i].address, 1, r_list->regs[i].val); if (ret) { - dev_err_ratelimited(&client->dev, + dev_err_ratelimited(og01a1b->dev, "failed to write reg 0x%4.4x. error = %d", r_list->regs[i].address, ret); return ret; @@ -544,7 +545,6 @@ static int og01a1b_set_ctrl(struct v4l2_ctrl *ctrl) { struct og01a1b *og01a1b = container_of(ctrl->handler, struct og01a1b, ctrl_handler); - struct i2c_client *client = v4l2_get_subdevdata(&og01a1b->sd); s64 exposure_max; int ret = 0; @@ -560,7 +560,7 @@ static int og01a1b_set_ctrl(struct v4l2_ctrl *ctrl) } /* V4L2 controls values will be applied only when power is already up */ - if (!pm_runtime_get_if_in_use(&client->dev)) + if (!pm_runtime_get_if_in_use(og01a1b->dev)) return 0; switch (ctrl->id) { @@ -596,7 +596,7 @@ static int og01a1b_set_ctrl(struct v4l2_ctrl *ctrl) break; } - pm_runtime_put(&client->dev); + pm_runtime_put(og01a1b->dev); return ret; } @@ -682,13 +682,12 @@ static void og01a1b_update_pad_format(const struct og01a1b_mode *mode, { fmt->width = mode->width; fmt->height = mode->height; - fmt->code = MEDIA_BUS_FMT_SGRBG10_1X10; + fmt->code = MEDIA_BUS_FMT_Y10_1X10; fmt->field = V4L2_FIELD_NONE; } static int og01a1b_start_streaming(struct og01a1b *og01a1b) { - struct i2c_client *client = v4l2_get_subdevdata(&og01a1b->sd); const struct og01a1b_reg_list *reg_list; int link_freq_index, ret; @@ -697,14 +696,14 @@ static int og01a1b_start_streaming(struct og01a1b *og01a1b) ret = og01a1b_write_reg_list(og01a1b, reg_list); if (ret) { - dev_err(&client->dev, "failed to set plls"); + dev_err(og01a1b->dev, "failed to set plls"); return ret; } reg_list = &og01a1b->cur_mode->reg_list; ret = og01a1b_write_reg_list(og01a1b, reg_list); if (ret) { - dev_err(&client->dev, "failed to set mode"); + dev_err(og01a1b->dev, "failed to set mode"); return ret; } @@ -716,7 +715,7 @@ static int og01a1b_start_streaming(struct og01a1b *og01a1b) OG01A1B_REG_VALUE_08BIT, OG01A1B_MODE_STREAMING); if (ret) { - dev_err(&client->dev, "failed to set stream"); + dev_err(og01a1b->dev, "failed to set stream"); return ret; } @@ -725,22 +724,19 @@ static int og01a1b_start_streaming(struct og01a1b *og01a1b) static void og01a1b_stop_streaming(struct og01a1b *og01a1b) { - struct i2c_client *client = v4l2_get_subdevdata(&og01a1b->sd); - if (og01a1b_write_reg(og01a1b, OG01A1B_REG_MODE_SELECT, OG01A1B_REG_VALUE_08BIT, OG01A1B_MODE_STANDBY)) - dev_err(&client->dev, "failed to set stream"); + dev_err(og01a1b->dev, "failed to set stream"); } static int og01a1b_set_stream(struct v4l2_subdev *sd, int enable) { struct og01a1b *og01a1b = to_og01a1b(sd); - struct i2c_client *client = v4l2_get_subdevdata(sd); int ret = 0; mutex_lock(&og01a1b->mutex); if (enable) { - ret = pm_runtime_resume_and_get(&client->dev); + ret = pm_runtime_resume_and_get(og01a1b->dev); if (ret) { mutex_unlock(&og01a1b->mutex); return ret; @@ -750,11 +746,11 @@ static int og01a1b_set_stream(struct v4l2_subdev *sd, int enable) if (ret) { enable = 0; og01a1b_stop_streaming(og01a1b); - pm_runtime_put(&client->dev); + pm_runtime_put(og01a1b->dev); } } else { og01a1b_stop_streaming(og01a1b); - pm_runtime_put(&client->dev); + pm_runtime_put(og01a1b->dev); } mutex_unlock(&og01a1b->mutex); @@ -828,7 +824,7 @@ static int og01a1b_enum_mbus_code(struct v4l2_subdev *sd, if (code->index > 0) return -EINVAL; - code->code = MEDIA_BUS_FMT_SGRBG10_1X10; + code->code = MEDIA_BUS_FMT_Y10_1X10; return 0; } @@ -840,7 +836,7 @@ static int og01a1b_enum_frame_size(struct v4l2_subdev *sd, if (fse->index >= ARRAY_SIZE(supported_modes)) return -EINVAL; - if (fse->code != MEDIA_BUS_FMT_SGRBG10_1X10) + if (fse->code != MEDIA_BUS_FMT_Y10_1X10) return -EINVAL; fse->min_width = supported_modes[fse->index].width; @@ -889,7 +885,6 @@ static const struct v4l2_subdev_internal_ops og01a1b_internal_ops = { static int og01a1b_identify_module(struct og01a1b *og01a1b) { - struct i2c_client *client = v4l2_get_subdevdata(&og01a1b->sd); int ret; u32 val; @@ -899,7 +894,7 @@ static int og01a1b_identify_module(struct og01a1b *og01a1b) return ret; if (val != OG01A1B_CHIP_ID) { - dev_err(&client->dev, "chip id mismatch: %x!=%x", + dev_err(og01a1b->dev, "chip id mismatch: %x!=%x", OG01A1B_CHIP_ID, val); return -ENXIO; } @@ -909,35 +904,18 @@ static int og01a1b_identify_module(struct og01a1b *og01a1b) static int og01a1b_check_hwcfg(struct og01a1b *og01a1b) { - struct i2c_client *client = v4l2_get_subdevdata(&og01a1b->sd); - struct device *dev = &client->dev; + struct device *dev = og01a1b->dev; struct fwnode_handle *ep; struct fwnode_handle *fwnode = dev_fwnode(dev); struct v4l2_fwnode_endpoint bus_cfg = { .bus_type = V4L2_MBUS_CSI2_DPHY }; - u32 mclk; int ret; unsigned int i, j; if (!fwnode) return -ENXIO; - ret = fwnode_property_read_u32(fwnode, "clock-frequency", &mclk); - if (ret) { - if (!og01a1b->xvclk) { - dev_err(dev, "can't get clock frequency"); - return ret; - } - - mclk = clk_get_rate(og01a1b->xvclk); - } - - if (mclk != OG01A1B_MCLK) { - dev_err(dev, "external clock %d is not supported", mclk); - return -EINVAL; - } - ep = fwnode_graph_get_next_endpoint(fwnode, NULL); if (!ep) return -ENXIO; @@ -1066,47 +1044,54 @@ static void og01a1b_remove(struct i2c_client *client) v4l2_async_unregister_subdev(sd); media_entity_cleanup(&sd->entity); v4l2_ctrl_handler_free(sd->ctrl_handler); - pm_runtime_disable(&client->dev); + pm_runtime_disable(og01a1b->dev); mutex_destroy(&og01a1b->mutex); } static int og01a1b_probe(struct i2c_client *client) { struct og01a1b *og01a1b; + unsigned long freq; int ret; og01a1b = devm_kzalloc(&client->dev, sizeof(*og01a1b), GFP_KERNEL); if (!og01a1b) return -ENOMEM; + og01a1b->dev = &client->dev; + v4l2_i2c_subdev_init(&og01a1b->sd, client, &og01a1b_subdev_ops); - og01a1b->xvclk = devm_clk_get_optional(&client->dev, NULL); - if (IS_ERR(og01a1b->xvclk)) { - ret = PTR_ERR(og01a1b->xvclk); - dev_err(&client->dev, "failed to get xvclk clock: %d\n", ret); - return ret; - } + og01a1b->xvclk = devm_v4l2_sensor_clk_get(og01a1b->dev, NULL); + if (IS_ERR(og01a1b->xvclk)) + return dev_err_probe(og01a1b->dev, PTR_ERR(og01a1b->xvclk), + "failed to get xvclk clock\n"); + + freq = clk_get_rate(og01a1b->xvclk); + if (freq != OG01A1B_MCLK) + return dev_err_probe(og01a1b->dev, -EINVAL, + "external clock %lu is not supported", + freq); ret = og01a1b_check_hwcfg(og01a1b); if (ret) { - dev_err(&client->dev, "failed to check HW configuration: %d", + dev_err(og01a1b->dev, "failed to check HW configuration: %d", ret); return ret; } - og01a1b->reset_gpio = devm_gpiod_get_optional(&client->dev, "reset", + og01a1b->reset_gpio = devm_gpiod_get_optional(og01a1b->dev, "reset", GPIOD_OUT_LOW); if (IS_ERR(og01a1b->reset_gpio)) { - dev_err(&client->dev, "cannot get reset GPIO\n"); + dev_err(og01a1b->dev, "cannot get reset GPIO\n"); return PTR_ERR(og01a1b->reset_gpio); } - og01a1b->avdd = devm_regulator_get_optional(&client->dev, "avdd"); + og01a1b->avdd = devm_regulator_get_optional(og01a1b->dev, "avdd"); if (IS_ERR(og01a1b->avdd)) { ret = PTR_ERR(og01a1b->avdd); if (ret != -ENODEV) { - dev_err_probe(&client->dev, ret, + dev_err_probe(og01a1b->dev, ret, "Failed to get 'avdd' regulator\n"); return ret; } @@ -1114,11 +1099,11 @@ static int og01a1b_probe(struct i2c_client *client) og01a1b->avdd = NULL; } - og01a1b->dovdd = devm_regulator_get_optional(&client->dev, "dovdd"); + og01a1b->dovdd = devm_regulator_get_optional(og01a1b->dev, "dovdd"); if (IS_ERR(og01a1b->dovdd)) { ret = PTR_ERR(og01a1b->dovdd); if (ret != -ENODEV) { - dev_err_probe(&client->dev, ret, + dev_err_probe(og01a1b->dev, ret, "Failed to get 'dovdd' regulator\n"); return ret; } @@ -1126,11 +1111,11 @@ static int og01a1b_probe(struct i2c_client *client) og01a1b->dovdd = NULL; } - og01a1b->dvdd = devm_regulator_get_optional(&client->dev, "dvdd"); + og01a1b->dvdd = devm_regulator_get_optional(og01a1b->dev, "dvdd"); if (IS_ERR(og01a1b->dvdd)) { ret = PTR_ERR(og01a1b->dvdd); if (ret != -ENODEV) { - dev_err_probe(&client->dev, ret, + dev_err_probe(og01a1b->dev, ret, "Failed to get 'dvdd' regulator\n"); return ret; } @@ -1139,13 +1124,13 @@ static int og01a1b_probe(struct i2c_client *client) } /* The sensor must be powered on to read the CHIP_ID register */ - ret = og01a1b_power_on(&client->dev); + ret = og01a1b_power_on(og01a1b->dev); if (ret) return ret; ret = og01a1b_identify_module(og01a1b); if (ret) { - dev_err(&client->dev, "failed to find sensor: %d", ret); + dev_err(og01a1b->dev, "failed to find sensor: %d", ret); goto power_off; } @@ -1153,7 +1138,7 @@ static int og01a1b_probe(struct i2c_client *client) og01a1b->cur_mode = &supported_modes[0]; ret = og01a1b_init_controls(og01a1b); if (ret) { - dev_err(&client->dev, "failed to init controls: %d", ret); + dev_err(og01a1b->dev, "failed to init controls: %d", ret); goto probe_error_v4l2_ctrl_handler_free; } @@ -1164,21 +1149,21 @@ static int og01a1b_probe(struct i2c_client *client) og01a1b->pad.flags = MEDIA_PAD_FL_SOURCE; ret = media_entity_pads_init(&og01a1b->sd.entity, 1, &og01a1b->pad); if (ret) { - dev_err(&client->dev, "failed to init entity pads: %d", ret); + dev_err(og01a1b->dev, "failed to init entity pads: %d", ret); goto probe_error_v4l2_ctrl_handler_free; } ret = v4l2_async_register_subdev_sensor(&og01a1b->sd); if (ret < 0) { - dev_err(&client->dev, "failed to register V4L2 subdev: %d", + dev_err(og01a1b->dev, "failed to register V4L2 subdev: %d", ret); goto probe_error_media_entity_cleanup; } /* Enable runtime PM and turn off the device */ - pm_runtime_set_active(&client->dev); - pm_runtime_enable(&client->dev); - pm_runtime_idle(&client->dev); + pm_runtime_set_active(og01a1b->dev); + pm_runtime_enable(og01a1b->dev); + pm_runtime_idle(og01a1b->dev); return 0; @@ -1190,7 +1175,7 @@ probe_error_v4l2_ctrl_handler_free: mutex_destroy(&og01a1b->mutex); power_off: - og01a1b_power_off(&client->dev); + og01a1b_power_off(og01a1b->dev); return ret; } diff --git a/drivers/media/i2c/og0ve1b.c b/drivers/media/i2c/og0ve1b.c new file mode 100644 index 000000000000..262d9df766fe --- /dev/null +++ b/drivers/media/i2c/og0ve1b.c @@ -0,0 +1,816 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (c) 2024-2025 Linaro Ltd + +#include <linux/clk.h> +#include <linux/delay.h> +#include <linux/gpio/consumer.h> +#include <linux/i2c.h> +#include <linux/module.h> +#include <linux/pm_runtime.h> +#include <linux/regulator/consumer.h> +#include <linux/units.h> +#include <media/v4l2-cci.h> +#include <media/v4l2-ctrls.h> +#include <media/v4l2-device.h> +#include <media/v4l2-fwnode.h> + +#define OG0VE1B_LINK_FREQ_500MHZ (500 * HZ_PER_MHZ) +#define OG0VE1B_MCLK_FREQ_24MHZ (24 * HZ_PER_MHZ) + +#define OG0VE1B_REG_CHIP_ID CCI_REG24(0x300a) +#define OG0VE1B_CHIP_ID 0xc75645 + +#define OG0VE1B_REG_MODE_SELECT CCI_REG8(0x0100) +#define OG0VE1B_MODE_STANDBY 0x00 +#define OG0VE1B_MODE_STREAMING BIT(0) + +#define OG0VE1B_REG_SOFTWARE_RST CCI_REG8(0x0103) +#define OG0VE1B_SOFTWARE_RST BIT(0) + +/* Exposure controls from sensor */ +#define OG0VE1B_REG_EXPOSURE CCI_REG24(0x3500) +#define OG0VE1B_EXPOSURE_MIN 1 +#define OG0VE1B_EXPOSURE_MAX_MARGIN 14 +#define OG0VE1B_EXPOSURE_STEP 1 +#define OG0VE1B_EXPOSURE_DEFAULT 554 + +/* Analogue gain controls from sensor */ +#define OG0VE1B_REG_ANALOGUE_GAIN CCI_REG16(0x350a) +#define OG0VE1B_ANALOGUE_GAIN_MIN 1 +#define OG0VE1B_ANALOGUE_GAIN_MAX 0x1ff +#define OG0VE1B_ANALOGUE_GAIN_STEP 1 +#define OG0VE1B_ANALOGUE_GAIN_DEFAULT 16 + +/* Test pattern */ +#define OG0VE1B_REG_PRE_ISP CCI_REG8(0x5e00) +#define OG0VE1B_TEST_PATTERN_ENABLE BIT(7) + +#define to_og0ve1b(_sd) container_of(_sd, struct og0ve1b, sd) + +static const s64 og0ve1b_link_freq_menu[] = { + OG0VE1B_LINK_FREQ_500MHZ, +}; + +struct og0ve1b_reg_list { + const struct cci_reg_sequence *regs; + unsigned int num_regs; +}; + +struct og0ve1b_mode { + u32 width; /* Frame width in pixels */ + u32 height; /* Frame height in pixels */ + u32 hts; /* Horizontal timing size */ + u32 vts; /* Default vertical timing size */ + u32 bpp; /* Bits per pixel */ + + const struct og0ve1b_reg_list reg_list; /* Sensor register setting */ +}; + +static const char * const og0ve1b_test_pattern_menu[] = { + "Disabled", + "Vertical Colour Bars", +}; + +static const char * const og0ve1b_supply_names[] = { + "avdd", /* Analog power */ + "dovdd", /* Digital I/O power */ + "dvdd", /* Digital core power */ +}; + +#define OG0VE1B_NUM_SUPPLIES ARRAY_SIZE(og0ve1b_supply_names) + +struct og0ve1b { + struct device *dev; + struct regmap *regmap; + struct clk *xvclk; + struct gpio_desc *reset_gpio; + struct regulator_bulk_data supplies[OG0VE1B_NUM_SUPPLIES]; + + struct v4l2_subdev sd; + struct media_pad pad; + + struct v4l2_ctrl_handler ctrl_handler; + + /* Saved register value */ + u64 pre_isp; +}; + +static const struct cci_reg_sequence og0ve1b_640x480_120fps_mode[] = { + { CCI_REG8(0x30a0), 0x02 }, + { CCI_REG8(0x30a1), 0x00 }, + { CCI_REG8(0x30a2), 0x48 }, + { CCI_REG8(0x30a3), 0x34 }, + { CCI_REG8(0x30a4), 0xf7 }, + { CCI_REG8(0x30a5), 0x00 }, + { CCI_REG8(0x3082), 0x32 }, + { CCI_REG8(0x3083), 0x01 }, + { CCI_REG8(0x301c), 0xf0 }, + { CCI_REG8(0x301e), 0x0b }, + { CCI_REG8(0x3106), 0x10 }, + { CCI_REG8(0x3708), 0x77 }, + { CCI_REG8(0x3709), 0xf8 }, + { CCI_REG8(0x3717), 0x00 }, + { CCI_REG8(0x3782), 0x00 }, + { CCI_REG8(0x3783), 0x47 }, + { CCI_REG8(0x37a2), 0x00 }, + { CCI_REG8(0x3503), 0x07 }, + { CCI_REG8(0x3509), 0x10 }, + { CCI_REG8(0x3600), 0x83 }, + { CCI_REG8(0x3601), 0x21 }, + { CCI_REG8(0x3602), 0xf1 }, + { CCI_REG8(0x360a), 0x18 }, + { CCI_REG8(0x360e), 0xb3 }, + { CCI_REG8(0x3613), 0x20 }, + { CCI_REG8(0x366a), 0x78 }, + { CCI_REG8(0x3706), 0x63 }, + { CCI_REG8(0x3713), 0x00 }, + { CCI_REG8(0x3716), 0xb0 }, + { CCI_REG8(0x37a1), 0x38 }, + { CCI_REG8(0x3800), 0x00 }, + { CCI_REG8(0x3801), 0x04 }, + { CCI_REG8(0x3802), 0x00 }, + { CCI_REG8(0x3803), 0x04 }, + { CCI_REG8(0x3804), 0x02 }, + { CCI_REG8(0x3805), 0x8b }, + { CCI_REG8(0x3806), 0x01 }, + { CCI_REG8(0x3807), 0xeb }, + { CCI_REG8(0x3808), 0x02 }, /* output width */ + { CCI_REG8(0x3809), 0x80 }, + { CCI_REG8(0x380a), 0x01 }, /* output height */ + { CCI_REG8(0x380b), 0xe0 }, + { CCI_REG8(0x380c), 0x03 }, /* horizontal timing size */ + { CCI_REG8(0x380d), 0x18 }, + { CCI_REG8(0x380e), 0x02 }, /* vertical timing size */ + { CCI_REG8(0x380f), 0x38 }, + { CCI_REG8(0x3811), 0x04 }, + { CCI_REG8(0x3813), 0x04 }, + { CCI_REG8(0x3814), 0x11 }, + { CCI_REG8(0x3815), 0x11 }, + { CCI_REG8(0x3820), 0x00 }, + { CCI_REG8(0x3821), 0x00 }, + { CCI_REG8(0x3823), 0x04 }, + { CCI_REG8(0x382a), 0x00 }, + { CCI_REG8(0x382b), 0x03 }, + { CCI_REG8(0x3840), 0x00 }, + { CCI_REG8(0x389e), 0x00 }, + { CCI_REG8(0x3c05), 0x08 }, + { CCI_REG8(0x3c26), 0x02 }, + { CCI_REG8(0x3c27), 0xc0 }, + { CCI_REG8(0x3c28), 0x00 }, + { CCI_REG8(0x3c29), 0x40 }, + { CCI_REG8(0x3c2c), 0x00 }, + { CCI_REG8(0x3c2d), 0x50 }, + { CCI_REG8(0x3c2e), 0x02 }, + { CCI_REG8(0x3c2f), 0x66 }, + { CCI_REG8(0x3c33), 0x08 }, + { CCI_REG8(0x3c35), 0x00 }, + { CCI_REG8(0x3c36), 0x00 }, + { CCI_REG8(0x3c37), 0x00 }, + { CCI_REG8(0x3f52), 0x9b }, + { CCI_REG8(0x4001), 0x42 }, + { CCI_REG8(0x4004), 0x08 }, + { CCI_REG8(0x4005), 0x00 }, + { CCI_REG8(0x4007), 0x28 }, + { CCI_REG8(0x4009), 0x40 }, + { CCI_REG8(0x4307), 0x30 }, + { CCI_REG8(0x4500), 0x80 }, + { CCI_REG8(0x4501), 0x02 }, + { CCI_REG8(0x4502), 0x47 }, + { CCI_REG8(0x4504), 0x7f }, + { CCI_REG8(0x4601), 0x48 }, + { CCI_REG8(0x4800), 0x64 }, + { CCI_REG8(0x4801), 0x0f }, + { CCI_REG8(0x4806), 0x2f }, + { CCI_REG8(0x4819), 0xaa }, + { CCI_REG8(0x4823), 0x3e }, + { CCI_REG8(0x5000), 0x85 }, + { CCI_REG8(0x5e00), 0x0c }, + { CCI_REG8(0x3899), 0x09 }, + { CCI_REG8(0x4f00), 0x64 }, + { CCI_REG8(0x4f02), 0x0a }, + { CCI_REG8(0x4f05), 0x0e }, + { CCI_REG8(0x4f06), 0x11 }, + { CCI_REG8(0x4f08), 0x0b }, + { CCI_REG8(0x4f0a), 0xc4 }, + { CCI_REG8(0x4f20), 0x1f }, + { CCI_REG8(0x4f25), 0x10 }, + { CCI_REG8(0x3016), 0x10 }, + { CCI_REG8(0x3017), 0x00 }, + { CCI_REG8(0x3018), 0x00 }, + { CCI_REG8(0x3019), 0x00 }, + { CCI_REG8(0x301a), 0x00 }, + { CCI_REG8(0x301b), 0x00 }, + { CCI_REG8(0x301c), 0x72 }, + { CCI_REG8(0x3037), 0x40 }, + { CCI_REG8(0x4f2c), 0x00 }, + { CCI_REG8(0x4f21), 0x00 }, + { CCI_REG8(0x4f23), 0x00 }, + { CCI_REG8(0x4f2a), 0x00 }, + { CCI_REG8(0x3665), 0xe7 }, + { CCI_REG8(0x3668), 0x48 }, + { CCI_REG8(0x3671), 0x3c }, + { CCI_REG8(0x389a), 0x02 }, + { CCI_REG8(0x389b), 0x00 }, + { CCI_REG8(0x303c), 0xa0 }, + { CCI_REG8(0x300f), 0xf0 }, + { CCI_REG8(0x304b), 0x0f }, + { CCI_REG8(0x3662), 0x24 }, + { CCI_REG8(0x3006), 0x40 }, + { CCI_REG8(0x4f26), 0x45 }, + { CCI_REG8(0x3607), 0x34 }, + { CCI_REG8(0x3608), 0x01 }, + { CCI_REG8(0x360a), 0x0c }, + { CCI_REG8(0x360b), 0x86 }, + { CCI_REG8(0x360c), 0xcc }, + { CCI_REG8(0x3013), 0x00 }, + { CCI_REG8(0x3083), 0x02 }, + { CCI_REG8(0x3084), 0x12 }, + { CCI_REG8(0x4601), 0x38 }, + { CCI_REG8(0x366f), 0x3a }, + { CCI_REG8(0x3713), 0x19 }, + { CCI_REG8(0x37a2), 0x00 }, + { CCI_REG8(0x3f43), 0x27 }, + { CCI_REG8(0x3f45), 0x27 }, + { CCI_REG8(0x3f47), 0x32 }, + { CCI_REG8(0x3f49), 0x3e }, + { CCI_REG8(0x3f4b), 0x20 }, + { CCI_REG8(0x3f4d), 0x30 }, + { CCI_REG8(0x4300), 0x3f }, + { CCI_REG8(0x4009), 0x10 }, + { CCI_REG8(0x3f02), 0x68 }, + { CCI_REG8(0x3700), 0x8c }, + { CCI_REG8(0x370b), 0x7e }, + { CCI_REG8(0x3f47), 0x35 }, +}; + +static const struct og0ve1b_mode supported_modes[] = { + { + .width = 640, + .height = 480, + .hts = 792, + .vts = 568, + .bpp = 8, + .reg_list = { + .regs = og0ve1b_640x480_120fps_mode, + .num_regs = ARRAY_SIZE(og0ve1b_640x480_120fps_mode), + }, + }, +}; + +static int og0ve1b_enable_test_pattern(struct og0ve1b *og0ve1b, u32 pattern) +{ + u64 val = og0ve1b->pre_isp; + + if (pattern) + val |= OG0VE1B_TEST_PATTERN_ENABLE; + else + val &= ~OG0VE1B_TEST_PATTERN_ENABLE; + + return cci_write(og0ve1b->regmap, OG0VE1B_REG_PRE_ISP, val, NULL); +} + +static int og0ve1b_set_ctrl(struct v4l2_ctrl *ctrl) +{ + struct og0ve1b *og0ve1b = container_of(ctrl->handler, struct og0ve1b, + ctrl_handler); + int ret; + + /* V4L2 controls are applied, when sensor is powered up for streaming */ + if (!pm_runtime_get_if_active(og0ve1b->dev)) + return 0; + + switch (ctrl->id) { + case V4L2_CID_ANALOGUE_GAIN: + ret = cci_write(og0ve1b->regmap, OG0VE1B_REG_ANALOGUE_GAIN, + ctrl->val, NULL); + break; + case V4L2_CID_EXPOSURE: + ret = cci_write(og0ve1b->regmap, OG0VE1B_REG_EXPOSURE, + ctrl->val << 4, NULL); + break; + case V4L2_CID_TEST_PATTERN: + ret = og0ve1b_enable_test_pattern(og0ve1b, ctrl->val); + break; + default: + ret = -EINVAL; + break; + } + + pm_runtime_put(og0ve1b->dev); + + return ret; +} + +static const struct v4l2_ctrl_ops og0ve1b_ctrl_ops = { + .s_ctrl = og0ve1b_set_ctrl, +}; + +static int og0ve1b_init_controls(struct og0ve1b *og0ve1b) +{ + struct v4l2_ctrl_handler *ctrl_hdlr = &og0ve1b->ctrl_handler; + const struct og0ve1b_mode *mode = &supported_modes[0]; + struct v4l2_fwnode_device_properties props; + s64 exposure_max, pixel_rate, h_blank; + struct v4l2_ctrl *ctrl; + int ret; + + v4l2_ctrl_handler_init(ctrl_hdlr, 9); + + ctrl = v4l2_ctrl_new_int_menu(ctrl_hdlr, &og0ve1b_ctrl_ops, + V4L2_CID_LINK_FREQ, + ARRAY_SIZE(og0ve1b_link_freq_menu) - 1, + 0, og0ve1b_link_freq_menu); + if (ctrl) + ctrl->flags |= V4L2_CTRL_FLAG_READ_ONLY; + + pixel_rate = og0ve1b_link_freq_menu[0] / mode->bpp; + v4l2_ctrl_new_std(ctrl_hdlr, &og0ve1b_ctrl_ops, V4L2_CID_PIXEL_RATE, + 0, pixel_rate, 1, pixel_rate); + + h_blank = mode->hts - mode->width; + ctrl = v4l2_ctrl_new_std(ctrl_hdlr, &og0ve1b_ctrl_ops, V4L2_CID_HBLANK, + h_blank, h_blank, 1, h_blank); + if (ctrl) + ctrl->flags |= V4L2_CTRL_FLAG_READ_ONLY; + + ctrl = v4l2_ctrl_new_std(ctrl_hdlr, &og0ve1b_ctrl_ops, V4L2_CID_VBLANK, + mode->vts - mode->height, + mode->vts - mode->height, 1, + mode->vts - mode->height); + if (ctrl) + ctrl->flags |= V4L2_CTRL_FLAG_READ_ONLY; + + v4l2_ctrl_new_std(ctrl_hdlr, &og0ve1b_ctrl_ops, V4L2_CID_ANALOGUE_GAIN, + OG0VE1B_ANALOGUE_GAIN_MIN, OG0VE1B_ANALOGUE_GAIN_MAX, + OG0VE1B_ANALOGUE_GAIN_STEP, + OG0VE1B_ANALOGUE_GAIN_DEFAULT); + + exposure_max = (mode->vts - OG0VE1B_EXPOSURE_MAX_MARGIN); + v4l2_ctrl_new_std(ctrl_hdlr, &og0ve1b_ctrl_ops, + V4L2_CID_EXPOSURE, + OG0VE1B_EXPOSURE_MIN, exposure_max, + OG0VE1B_EXPOSURE_STEP, + OG0VE1B_EXPOSURE_DEFAULT); + + v4l2_ctrl_new_std_menu_items(ctrl_hdlr, &og0ve1b_ctrl_ops, + V4L2_CID_TEST_PATTERN, + ARRAY_SIZE(og0ve1b_test_pattern_menu) - 1, + 0, 0, og0ve1b_test_pattern_menu); + + if (ctrl_hdlr->error) + return ctrl_hdlr->error; + + ret = v4l2_fwnode_device_parse(og0ve1b->dev, &props); + if (ret) + goto error_free_hdlr; + + ret = v4l2_ctrl_new_fwnode_properties(ctrl_hdlr, &og0ve1b_ctrl_ops, + &props); + if (ret) + goto error_free_hdlr; + + og0ve1b->sd.ctrl_handler = ctrl_hdlr; + + return 0; + +error_free_hdlr: + v4l2_ctrl_handler_free(ctrl_hdlr); + + return ret; +} + +static void og0ve1b_update_pad_format(const struct og0ve1b_mode *mode, + struct v4l2_mbus_framefmt *fmt) +{ + fmt->code = MEDIA_BUS_FMT_Y8_1X8; + fmt->width = mode->width; + fmt->height = mode->height; + fmt->field = V4L2_FIELD_NONE; + fmt->colorspace = V4L2_COLORSPACE_RAW; + fmt->ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT; + fmt->quantization = V4L2_QUANTIZATION_FULL_RANGE; + fmt->xfer_func = V4L2_XFER_FUNC_NONE; +} + +static int og0ve1b_enable_streams(struct v4l2_subdev *sd, + struct v4l2_subdev_state *state, u32 pad, + u64 streams_mask) +{ + const struct og0ve1b_reg_list *reg_list = &supported_modes[0].reg_list; + struct og0ve1b *og0ve1b = to_og0ve1b(sd); + int ret; + + ret = pm_runtime_resume_and_get(og0ve1b->dev); + if (ret) + return ret; + + /* Skip a step of explicit entering into the standby mode */ + ret = cci_write(og0ve1b->regmap, OG0VE1B_REG_SOFTWARE_RST, + OG0VE1B_SOFTWARE_RST, NULL); + if (ret) { + dev_err(og0ve1b->dev, "failed to software reset: %d\n", ret); + goto error; + } + + ret = cci_multi_reg_write(og0ve1b->regmap, reg_list->regs, + reg_list->num_regs, NULL); + if (ret) { + dev_err(og0ve1b->dev, "failed to set mode: %d\n", ret); + goto error; + } + + ret = __v4l2_ctrl_handler_setup(og0ve1b->sd.ctrl_handler); + if (ret) + goto error; + + ret = cci_write(og0ve1b->regmap, OG0VE1B_REG_MODE_SELECT, + OG0VE1B_MODE_STREAMING, NULL); + if (ret) { + dev_err(og0ve1b->dev, "failed to start streaming: %d\n", ret); + goto error; + } + + return 0; + +error: + pm_runtime_put_autosuspend(og0ve1b->dev); + + return ret; +} + +static int og0ve1b_disable_streams(struct v4l2_subdev *sd, + struct v4l2_subdev_state *state, u32 pad, + u64 streams_mask) +{ + struct og0ve1b *og0ve1b = to_og0ve1b(sd); + int ret; + + ret = cci_write(og0ve1b->regmap, OG0VE1B_REG_MODE_SELECT, + OG0VE1B_MODE_STANDBY, NULL); + if (ret) + dev_err(og0ve1b->dev, "failed to stop streaming: %d\n", ret); + + pm_runtime_put_autosuspend(og0ve1b->dev); + + return ret; +} + +static int og0ve1b_set_pad_format(struct v4l2_subdev *sd, + struct v4l2_subdev_state *state, + struct v4l2_subdev_format *fmt) +{ + struct v4l2_mbus_framefmt *format; + const struct og0ve1b_mode *mode; + + format = v4l2_subdev_state_get_format(state, 0); + + mode = v4l2_find_nearest_size(supported_modes, + ARRAY_SIZE(supported_modes), + width, height, + fmt->format.width, + fmt->format.height); + + og0ve1b_update_pad_format(mode, &fmt->format); + *format = fmt->format; + + return 0; +} + +static int og0ve1b_enum_mbus_code(struct v4l2_subdev *sd, + struct v4l2_subdev_state *sd_state, + struct v4l2_subdev_mbus_code_enum *code) +{ + if (code->index > 0) + return -EINVAL; + + code->code = MEDIA_BUS_FMT_Y8_1X8; + + return 0; +} + +static int og0ve1b_enum_frame_size(struct v4l2_subdev *sd, + struct v4l2_subdev_state *sd_state, + struct v4l2_subdev_frame_size_enum *fse) +{ + if (fse->index >= ARRAY_SIZE(supported_modes)) + return -EINVAL; + + if (fse->code != MEDIA_BUS_FMT_Y8_1X8) + return -EINVAL; + + fse->min_width = supported_modes[fse->index].width; + fse->max_width = fse->min_width; + fse->min_height = supported_modes[fse->index].height; + fse->max_height = fse->min_height; + + return 0; +} + +static int og0ve1b_init_state(struct v4l2_subdev *sd, + struct v4l2_subdev_state *state) +{ + struct v4l2_subdev_format fmt = { + .which = V4L2_SUBDEV_FORMAT_TRY, + .pad = 0, + .format = { + .code = MEDIA_BUS_FMT_Y8_1X8, + .width = supported_modes[0].width, + .height = supported_modes[0].height, + }, + }; + + og0ve1b_set_pad_format(sd, state, &fmt); + + return 0; +} + +static const struct v4l2_subdev_video_ops og0ve1b_video_ops = { + .s_stream = v4l2_subdev_s_stream_helper, +}; + +static const struct v4l2_subdev_pad_ops og0ve1b_pad_ops = { + .set_fmt = og0ve1b_set_pad_format, + .get_fmt = v4l2_subdev_get_fmt, + .enum_mbus_code = og0ve1b_enum_mbus_code, + .enum_frame_size = og0ve1b_enum_frame_size, + .enable_streams = og0ve1b_enable_streams, + .disable_streams = og0ve1b_disable_streams, +}; + +static const struct v4l2_subdev_ops og0ve1b_subdev_ops = { + .video = &og0ve1b_video_ops, + .pad = &og0ve1b_pad_ops, +}; + +static const struct v4l2_subdev_internal_ops og0ve1b_internal_ops = { + .init_state = og0ve1b_init_state, +}; + +static const struct media_entity_operations og0ve1b_subdev_entity_ops = { + .link_validate = v4l2_subdev_link_validate, +}; + +static int og0ve1b_identify_sensor(struct og0ve1b *og0ve1b) +{ + u64 val; + int ret; + + ret = cci_read(og0ve1b->regmap, OG0VE1B_REG_CHIP_ID, &val, NULL); + if (ret) { + dev_err(og0ve1b->dev, "failed to read chip id: %d\n", ret); + return ret; + } + + if (val != OG0VE1B_CHIP_ID) { + dev_err(og0ve1b->dev, "chip id mismatch: %x!=%llx\n", + OG0VE1B_CHIP_ID, val); + return -ENODEV; + } + + ret = cci_read(og0ve1b->regmap, OG0VE1B_REG_PRE_ISP, + &og0ve1b->pre_isp, NULL); + if (ret) + dev_err(og0ve1b->dev, "failed to read pre_isp: %d\n", ret); + + return ret; +} + +static int og0ve1b_check_hwcfg(struct og0ve1b *og0ve1b) +{ + struct fwnode_handle *fwnode = dev_fwnode(og0ve1b->dev), *ep; + struct v4l2_fwnode_endpoint bus_cfg = { + .bus_type = V4L2_MBUS_CSI2_DPHY, + }; + unsigned long freq_bitmap; + int ret; + + if (!fwnode) + return -ENODEV; + + ep = fwnode_graph_get_next_endpoint(fwnode, NULL); + if (!ep) + return -EINVAL; + + ret = v4l2_fwnode_endpoint_alloc_parse(ep, &bus_cfg); + fwnode_handle_put(ep); + if (ret) + return ret; + + ret = v4l2_link_freq_to_bitmap(og0ve1b->dev, + bus_cfg.link_frequencies, + bus_cfg.nr_of_link_frequencies, + og0ve1b_link_freq_menu, + ARRAY_SIZE(og0ve1b_link_freq_menu), + &freq_bitmap); + + v4l2_fwnode_endpoint_free(&bus_cfg); + + return ret; +} + +static int og0ve1b_power_on(struct device *dev) +{ + struct v4l2_subdev *sd = dev_get_drvdata(dev); + struct og0ve1b *og0ve1b = to_og0ve1b(sd); + int ret; + + ret = regulator_bulk_enable(OG0VE1B_NUM_SUPPLIES, og0ve1b->supplies); + if (ret) + return ret; + + gpiod_set_value_cansleep(og0ve1b->reset_gpio, 0); + usleep_range(10 * USEC_PER_MSEC, 15 * USEC_PER_MSEC); + + ret = clk_prepare_enable(og0ve1b->xvclk); + if (ret) + goto reset_gpio; + + return 0; + +reset_gpio: + gpiod_set_value_cansleep(og0ve1b->reset_gpio, 1); + + regulator_bulk_disable(OG0VE1B_NUM_SUPPLIES, og0ve1b->supplies); + + return ret; +} + +static int og0ve1b_power_off(struct device *dev) +{ + struct v4l2_subdev *sd = dev_get_drvdata(dev); + struct og0ve1b *og0ve1b = to_og0ve1b(sd); + + clk_disable_unprepare(og0ve1b->xvclk); + + gpiod_set_value_cansleep(og0ve1b->reset_gpio, 1); + + regulator_bulk_disable(OG0VE1B_NUM_SUPPLIES, og0ve1b->supplies); + + return 0; +} + +static int og0ve1b_probe(struct i2c_client *client) +{ + struct og0ve1b *og0ve1b; + unsigned long freq; + unsigned int i; + int ret; + + og0ve1b = devm_kzalloc(&client->dev, sizeof(*og0ve1b), GFP_KERNEL); + if (!og0ve1b) + return -ENOMEM; + + og0ve1b->dev = &client->dev; + + v4l2_i2c_subdev_init(&og0ve1b->sd, client, &og0ve1b_subdev_ops); + + og0ve1b->regmap = devm_cci_regmap_init_i2c(client, 16); + if (IS_ERR(og0ve1b->regmap)) + return dev_err_probe(og0ve1b->dev, PTR_ERR(og0ve1b->regmap), + "failed to init CCI\n"); + + og0ve1b->xvclk = devm_v4l2_sensor_clk_get(og0ve1b->dev, NULL); + if (IS_ERR(og0ve1b->xvclk)) + return dev_err_probe(og0ve1b->dev, PTR_ERR(og0ve1b->xvclk), + "failed to get XVCLK clock\n"); + + freq = clk_get_rate(og0ve1b->xvclk); + if (freq && freq != OG0VE1B_MCLK_FREQ_24MHZ) + return dev_err_probe(og0ve1b->dev, -EINVAL, + "XVCLK clock frequency %lu is not supported\n", + freq); + + ret = og0ve1b_check_hwcfg(og0ve1b); + if (ret) + return dev_err_probe(og0ve1b->dev, ret, + "failed to check HW configuration\n"); + + og0ve1b->reset_gpio = devm_gpiod_get_optional(og0ve1b->dev, "reset", + GPIOD_OUT_HIGH); + if (IS_ERR(og0ve1b->reset_gpio)) + return dev_err_probe(og0ve1b->dev, PTR_ERR(og0ve1b->reset_gpio), + "cannot get reset GPIO\n"); + + for (i = 0; i < OG0VE1B_NUM_SUPPLIES; i++) + og0ve1b->supplies[i].supply = og0ve1b_supply_names[i]; + + ret = devm_regulator_bulk_get(og0ve1b->dev, OG0VE1B_NUM_SUPPLIES, + og0ve1b->supplies); + if (ret) + return dev_err_probe(og0ve1b->dev, ret, + "failed to get supply regulators\n"); + + /* The sensor must be powered on to read the CHIP_ID register */ + ret = og0ve1b_power_on(og0ve1b->dev); + if (ret) + return ret; + + ret = og0ve1b_identify_sensor(og0ve1b); + if (ret) { + dev_err_probe(og0ve1b->dev, ret, "failed to find sensor\n"); + goto power_off; + } + + ret = og0ve1b_init_controls(og0ve1b); + if (ret) { + dev_err_probe(og0ve1b->dev, ret, "failed to init controls\n"); + goto power_off; + } + + og0ve1b->sd.state_lock = og0ve1b->ctrl_handler.lock; + og0ve1b->sd.internal_ops = &og0ve1b_internal_ops; + og0ve1b->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; + og0ve1b->sd.entity.ops = &og0ve1b_subdev_entity_ops; + og0ve1b->sd.entity.function = MEDIA_ENT_F_CAM_SENSOR; + og0ve1b->pad.flags = MEDIA_PAD_FL_SOURCE; + + ret = media_entity_pads_init(&og0ve1b->sd.entity, 1, &og0ve1b->pad); + if (ret) { + dev_err_probe(og0ve1b->dev, ret, + "failed to init media entity pads\n"); + goto v4l2_ctrl_handler_free; + } + + ret = v4l2_subdev_init_finalize(&og0ve1b->sd); + if (ret < 0) { + dev_err_probe(og0ve1b->dev, ret, + "failed to init media entity pads\n"); + goto media_entity_cleanup; + } + + pm_runtime_set_active(og0ve1b->dev); + pm_runtime_enable(og0ve1b->dev); + + ret = v4l2_async_register_subdev_sensor(&og0ve1b->sd); + if (ret < 0) { + dev_err_probe(og0ve1b->dev, ret, + "failed to register V4L2 subdev\n"); + goto subdev_cleanup; + } + + /* Enable runtime PM and turn off the device */ + pm_runtime_idle(og0ve1b->dev); + pm_runtime_set_autosuspend_delay(og0ve1b->dev, 1000); + pm_runtime_use_autosuspend(og0ve1b->dev); + + return 0; + +subdev_cleanup: + v4l2_subdev_cleanup(&og0ve1b->sd); + pm_runtime_disable(og0ve1b->dev); + pm_runtime_set_suspended(og0ve1b->dev); + +media_entity_cleanup: + media_entity_cleanup(&og0ve1b->sd.entity); + +v4l2_ctrl_handler_free: + v4l2_ctrl_handler_free(og0ve1b->sd.ctrl_handler); + +power_off: + og0ve1b_power_off(og0ve1b->dev); + + return ret; +} + +static void og0ve1b_remove(struct i2c_client *client) +{ + struct v4l2_subdev *sd = i2c_get_clientdata(client); + struct og0ve1b *og0ve1b = to_og0ve1b(sd); + + v4l2_async_unregister_subdev(sd); + v4l2_subdev_cleanup(sd); + media_entity_cleanup(&sd->entity); + v4l2_ctrl_handler_free(sd->ctrl_handler); + pm_runtime_disable(og0ve1b->dev); + + if (!pm_runtime_status_suspended(og0ve1b->dev)) { + og0ve1b_power_off(og0ve1b->dev); + pm_runtime_set_suspended(og0ve1b->dev); + } +} + +static const struct dev_pm_ops og0ve1b_pm_ops = { + SET_RUNTIME_PM_OPS(og0ve1b_power_off, og0ve1b_power_on, NULL) +}; + +static const struct of_device_id og0ve1b_of_match[] = { + { .compatible = "ovti,og0ve1b" }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, og0ve1b_of_match); + +static struct i2c_driver og0ve1b_i2c_driver = { + .driver = { + .name = "og0ve1b", + .pm = &og0ve1b_pm_ops, + .of_match_table = og0ve1b_of_match, + }, + .probe = og0ve1b_probe, + .remove = og0ve1b_remove, +}; + +module_i2c_driver(og0ve1b_i2c_driver); + +MODULE_AUTHOR("Vladimir Zapolskiy <vladimir.zapolskiy@linaro.org>"); +MODULE_DESCRIPTION("OmniVision OG0VE1B sensor driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/media/i2c/ov02a10.c b/drivers/media/i2c/ov02a10.c index 6c30e1a0d814..70d9d7c43f18 100644 --- a/drivers/media/i2c/ov02a10.c +++ b/drivers/media/i2c/ov02a10.c @@ -100,7 +100,8 @@ struct ov02a10_mode { }; struct ov02a10 { - u32 eclk_freq; + struct device *dev; + /* Indication of MIPI transmission speed select */ u32 mipi_clock_voltage; @@ -392,7 +393,7 @@ static int ov02a10_check_sensor_id(struct ov02a10 *ov02a10) chip_id = le16_to_cpu((__force __le16)ret); if ((chip_id & OV02A10_ID_MASK) != OV02A10_ID) { - dev_err(&client->dev, "unexpected sensor id(0x%04x)\n", chip_id); + dev_err(ov02a10->dev, "unexpected sensor id(0x%04x)\n", chip_id); return -EINVAL; } @@ -481,7 +482,7 @@ static int __ov02a10_start_stream(struct ov02a10 *ov02a10) ret = i2c_smbus_write_byte_data(client, REG_MIRROR_FLIP_CONTROL, REG_MIRROR_FLIP_ENABLE); if (ret < 0) { - dev_err(&client->dev, "failed to set orientation\n"); + dev_err(ov02a10->dev, "failed to set orientation\n"); return ret; } ret = i2c_smbus_write_byte_data(client, REG_GLOBAL_EFFECTIVE, @@ -530,7 +531,6 @@ static int ov02a10_init_state(struct v4l2_subdev *sd, static int ov02a10_s_stream(struct v4l2_subdev *sd, int on) { struct ov02a10 *ov02a10 = to_ov02a10(sd); - struct i2c_client *client = v4l2_get_subdevdata(&ov02a10->subdev); int ret; mutex_lock(&ov02a10->mutex); @@ -541,7 +541,7 @@ static int ov02a10_s_stream(struct v4l2_subdev *sd, int on) } if (on) { - ret = pm_runtime_resume_and_get(&client->dev); + ret = pm_runtime_resume_and_get(ov02a10->dev); if (ret < 0) goto unlock_and_return; @@ -553,7 +553,7 @@ static int ov02a10_s_stream(struct v4l2_subdev *sd, int on) } } else { __ov02a10_stop_stream(ov02a10); - pm_runtime_put(&client->dev); + pm_runtime_put(ov02a10->dev); } ov02a10->streaming = on; @@ -562,7 +562,7 @@ static int ov02a10_s_stream(struct v4l2_subdev *sd, int on) return 0; err_rpm_put: - pm_runtime_put(&client->dev); + pm_runtime_put(ov02a10->dev); unlock_and_return: mutex_unlock(&ov02a10->mutex); @@ -662,7 +662,6 @@ static int ov02a10_set_ctrl(struct v4l2_ctrl *ctrl) { struct ov02a10 *ov02a10 = container_of(ctrl->handler, struct ov02a10, ctrl_handler); - struct i2c_client *client = v4l2_get_subdevdata(&ov02a10->subdev); s64 max_expo; int ret; @@ -678,7 +677,7 @@ static int ov02a10_set_ctrl(struct v4l2_ctrl *ctrl) } /* V4L2 controls values will be applied only when power is already up */ - if (!pm_runtime_get_if_in_use(&client->dev)) + if (!pm_runtime_get_if_in_use(ov02a10->dev)) return 0; switch (ctrl->id) { @@ -699,7 +698,7 @@ static int ov02a10_set_ctrl(struct v4l2_ctrl *ctrl) break; } - pm_runtime_put(&client->dev); + pm_runtime_put(ov02a10->dev); return ret; } @@ -734,7 +733,6 @@ static const struct v4l2_ctrl_ops ov02a10_ctrl_ops = { static int ov02a10_initialize_controls(struct ov02a10 *ov02a10) { - struct i2c_client *client = v4l2_get_subdevdata(&ov02a10->subdev); const struct ov02a10_mode *mode; struct v4l2_ctrl_handler *handler; struct v4l2_ctrl *ctrl; @@ -790,7 +788,7 @@ static int ov02a10_initialize_controls(struct ov02a10 *ov02a10) if (handler->error) { ret = handler->error; - dev_err(&client->dev, "failed to init controls(%d)\n", ret); + dev_err(ov02a10->dev, "failed to init controls(%d)\n", ret); goto err_free_handler; } @@ -866,6 +864,8 @@ static int ov02a10_probe(struct i2c_client *client) if (!ov02a10) return -ENOMEM; + ov02a10->dev = dev; + ret = ov02a10_check_hwcfg(dev, ov02a10); if (ret) return dev_err_probe(dev, ret, @@ -885,22 +885,11 @@ static int ov02a10_probe(struct i2c_client *client) ov02a10->fmt.code = MEDIA_BUS_FMT_SRGGB10_1X10; } - ov02a10->eclk = devm_clk_get(dev, "eclk"); + ov02a10->eclk = devm_v4l2_sensor_clk_get_legacy(dev, "eclk", false, 0); if (IS_ERR(ov02a10->eclk)) return dev_err_probe(dev, PTR_ERR(ov02a10->eclk), "failed to get eclk\n"); - ret = device_property_read_u32(dev, "clock-frequency", - &ov02a10->eclk_freq); - if (ret < 0) - return dev_err_probe(dev, ret, - "failed to get eclk frequency\n"); - - ret = clk_set_rate(ov02a10->eclk, ov02a10->eclk_freq); - if (ret < 0) - return dev_err_probe(dev, ret, - "failed to set eclk frequency (24MHz)\n"); - if (clk_get_rate(ov02a10->eclk) != OV02A10_ECLK_FREQ) dev_warn(dev, "eclk mismatched, mode is based on 24MHz\n"); @@ -985,10 +974,10 @@ static void ov02a10_remove(struct i2c_client *client) v4l2_async_unregister_subdev(sd); media_entity_cleanup(&sd->entity); v4l2_ctrl_handler_free(sd->ctrl_handler); - pm_runtime_disable(&client->dev); - if (!pm_runtime_status_suspended(&client->dev)) - ov02a10_power_off(&client->dev); - pm_runtime_set_suspended(&client->dev); + pm_runtime_disable(ov02a10->dev); + if (!pm_runtime_status_suspended(ov02a10->dev)) + ov02a10_power_off(ov02a10->dev); + pm_runtime_set_suspended(ov02a10->dev); mutex_destroy(&ov02a10->mutex); } diff --git a/drivers/media/i2c/ov02c10.c b/drivers/media/i2c/ov02c10.c index 089a4fd9627c..8c4d85dc7922 100644 --- a/drivers/media/i2c/ov02c10.c +++ b/drivers/media/i2c/ov02c10.c @@ -9,7 +9,6 @@ #include <linux/module.h> #include <linux/pm_runtime.h> #include <linux/regmap.h> -#include <linux/version.h> #include <media/v4l2-cci.h> #include <media/v4l2-ctrls.h> #include <media/v4l2-device.h> @@ -373,6 +372,8 @@ static const char * const ov02c10_supply_names[] = { }; struct ov02c10 { + struct device *dev; + struct v4l2_subdev sd; struct media_pad pad; struct v4l2_ctrl_handler ctrl_handler; @@ -418,7 +419,6 @@ static int ov02c10_set_ctrl(struct v4l2_ctrl *ctrl) { struct ov02c10 *ov02c10 = container_of(ctrl->handler, struct ov02c10, ctrl_handler); - struct i2c_client *client = v4l2_get_subdevdata(&ov02c10->sd); const u32 height = supported_modes[0].height; s64 exposure_max; int ret = 0; @@ -434,7 +434,7 @@ static int ov02c10_set_ctrl(struct v4l2_ctrl *ctrl) } /* V4L2 controls values will be applied only when power is already up */ - if (!pm_runtime_get_if_in_use(&client->dev)) + if (!pm_runtime_get_if_in_use(ov02c10->dev)) return 0; switch (ctrl->id) { @@ -467,7 +467,7 @@ static int ov02c10_set_ctrl(struct v4l2_ctrl *ctrl) break; } - pm_runtime_put(&client->dev); + pm_runtime_put(ov02c10->dev); return ret; } @@ -478,7 +478,6 @@ static const struct v4l2_ctrl_ops ov02c10_ctrl_ops = { static int ov02c10_init_controls(struct ov02c10 *ov02c10) { - struct i2c_client *client = v4l2_get_subdevdata(&ov02c10->sd); struct v4l2_ctrl_handler *ctrl_hdlr = &ov02c10->ctrl_handler; const struct ov02c10_mode *mode = &supported_modes[0]; u32 vblank_min, vblank_max, vblank_default, vts_def; @@ -542,7 +541,7 @@ static int ov02c10_init_controls(struct ov02c10 *ov02c10) ARRAY_SIZE(ov02c10_test_pattern_menu) - 1, 0, 0, ov02c10_test_pattern_menu); - ret = v4l2_fwnode_device_parse(&client->dev, &props); + ret = v4l2_fwnode_device_parse(ov02c10->dev, &props); if (ret) return ret; @@ -570,12 +569,11 @@ static int ov02c10_enable_streams(struct v4l2_subdev *sd, u32 pad, u64 streams_mask) { const struct ov02c10_mode *mode = &supported_modes[0]; - struct i2c_client *client = v4l2_get_subdevdata(sd); struct ov02c10 *ov02c10 = to_ov02c10(sd); const struct reg_sequence *reg_sequence; int ret, sequence_length; - ret = pm_runtime_resume_and_get(&client->dev); + ret = pm_runtime_resume_and_get(ov02c10->dev); if (ret) return ret; @@ -584,7 +582,7 @@ static int ov02c10_enable_streams(struct v4l2_subdev *sd, ret = regmap_multi_reg_write(ov02c10->regmap, reg_sequence, sequence_length); if (ret) { - dev_err(&client->dev, "failed to set mode\n"); + dev_err(ov02c10->dev, "failed to set mode\n"); goto out; } @@ -593,7 +591,7 @@ static int ov02c10_enable_streams(struct v4l2_subdev *sd, ret = regmap_multi_reg_write(ov02c10->regmap, reg_sequence, sequence_length); if (ret) { - dev_err(&client->dev, "failed to write lane settings\n"); + dev_err(ov02c10->dev, "failed to write lane settings\n"); goto out; } @@ -604,7 +602,7 @@ static int ov02c10_enable_streams(struct v4l2_subdev *sd, ret = cci_write(ov02c10->regmap, OV02C10_REG_STREAM_CONTROL, 1, NULL); out: if (ret) - pm_runtime_put(&client->dev); + pm_runtime_put(ov02c10->dev); return ret; } @@ -613,11 +611,10 @@ static int ov02c10_disable_streams(struct v4l2_subdev *sd, struct v4l2_subdev_state *state, u32 pad, u64 streams_mask) { - struct i2c_client *client = v4l2_get_subdevdata(sd); struct ov02c10 *ov02c10 = to_ov02c10(sd); cci_write(ov02c10->regmap, OV02C10_REG_STREAM_CONTROL, 0, NULL); - pm_runtime_put(&client->dev); + pm_runtime_put(ov02c10->dev); return 0; } @@ -778,7 +775,6 @@ static const struct v4l2_subdev_internal_ops ov02c10_internal_ops = { static int ov02c10_identify_module(struct ov02c10 *ov02c10) { - struct i2c_client *client = v4l2_get_subdevdata(&ov02c10->sd); u64 chip_id; int ret; @@ -787,7 +783,7 @@ static int ov02c10_identify_module(struct ov02c10 *ov02c10) return ret; if (chip_id != OV02C10_CHIP_ID) { - dev_err(&client->dev, "chip id mismatch: %x!=%llx", + dev_err(ov02c10->dev, "chip id mismatch: %x!=%llx", OV02C10_CHIP_ID, chip_id); return -ENXIO; } @@ -795,14 +791,14 @@ static int ov02c10_identify_module(struct ov02c10 *ov02c10) return 0; } -static int ov02c10_check_hwcfg(struct device *dev, struct ov02c10 *ov02c10) +static int ov02c10_check_hwcfg(struct ov02c10 *ov02c10) { struct v4l2_fwnode_endpoint bus_cfg = { .bus_type = V4L2_MBUS_CSI2_DPHY }; + struct device *dev = ov02c10->dev; struct fwnode_handle *ep, *fwnode = dev_fwnode(dev); unsigned long link_freq_bitmap; - u32 mclk; int ret; /* @@ -814,31 +810,6 @@ static int ov02c10_check_hwcfg(struct device *dev, struct ov02c10 *ov02c10) return dev_err_probe(dev, -EPROBE_DEFER, "waiting for fwnode graph endpoint\n"); - ov02c10->img_clk = devm_clk_get_optional(dev, NULL); - if (IS_ERR(ov02c10->img_clk)) { - fwnode_handle_put(ep); - return dev_err_probe(dev, PTR_ERR(ov02c10->img_clk), - "failed to get imaging clock\n"); - } - - if (ov02c10->img_clk) { - mclk = clk_get_rate(ov02c10->img_clk); - } else { - ret = fwnode_property_read_u32(fwnode, "clock-frequency", &mclk); - if (ret) { - fwnode_handle_put(ep); - return dev_err_probe(dev, ret, - "reading clock-frequency property\n"); - } - } - - if (mclk != OV02C10_MCLK) { - fwnode_handle_put(ep); - return dev_err_probe(dev, -EINVAL, - "external clock %u is not supported\n", - mclk); - } - ret = v4l2_fwnode_endpoint_alloc_parse(ep, &bus_cfg); fwnode_handle_put(ep); if (ret) @@ -873,35 +844,50 @@ check_hwcfg_error: static void ov02c10_remove(struct i2c_client *client) { struct v4l2_subdev *sd = i2c_get_clientdata(client); + struct ov02c10 *ov02c10 = to_ov02c10(sd); v4l2_async_unregister_subdev(sd); v4l2_subdev_cleanup(sd); media_entity_cleanup(&sd->entity); v4l2_ctrl_handler_free(sd->ctrl_handler); - pm_runtime_disable(&client->dev); - if (!pm_runtime_status_suspended(&client->dev)) { - ov02c10_power_off(&client->dev); - pm_runtime_set_suspended(&client->dev); + pm_runtime_disable(ov02c10->dev); + if (!pm_runtime_status_suspended(ov02c10->dev)) { + ov02c10_power_off(ov02c10->dev); + pm_runtime_set_suspended(ov02c10->dev); } } static int ov02c10_probe(struct i2c_client *client) { struct ov02c10 *ov02c10; + unsigned long freq; int ret; ov02c10 = devm_kzalloc(&client->dev, sizeof(*ov02c10), GFP_KERNEL); if (!ov02c10) return -ENOMEM; + ov02c10->dev = &client->dev; + + ov02c10->img_clk = devm_v4l2_sensor_clk_get(ov02c10->dev, NULL); + if (IS_ERR(ov02c10->img_clk)) + return dev_err_probe(ov02c10->dev, PTR_ERR(ov02c10->img_clk), + "failed to get imaging clock\n"); + + freq = clk_get_rate(ov02c10->img_clk); + if (freq != OV02C10_MCLK) + return dev_err_probe(ov02c10->dev, -EINVAL, + "external clock %lu is not supported", + freq); + v4l2_i2c_subdev_init(&ov02c10->sd, client, &ov02c10_subdev_ops); /* Check HW config */ - ret = ov02c10_check_hwcfg(&client->dev, ov02c10); + ret = ov02c10_check_hwcfg(ov02c10); if (ret) return ret; - ret = ov02c10_get_pm_resources(&client->dev); + ret = ov02c10_get_pm_resources(ov02c10->dev); if (ret) return ret; @@ -909,21 +895,21 @@ static int ov02c10_probe(struct i2c_client *client) if (IS_ERR(ov02c10->regmap)) return PTR_ERR(ov02c10->regmap); - ret = ov02c10_power_on(&client->dev); + ret = ov02c10_power_on(ov02c10->dev); if (ret) { - dev_err_probe(&client->dev, ret, "failed to power on\n"); + dev_err_probe(ov02c10->dev, ret, "failed to power on\n"); return ret; } ret = ov02c10_identify_module(ov02c10); if (ret) { - dev_err(&client->dev, "failed to find sensor: %d", ret); + dev_err(ov02c10->dev, "failed to find sensor: %d", ret); goto probe_error_power_off; } ret = ov02c10_init_controls(ov02c10); if (ret) { - dev_err(&client->dev, "failed to init controls: %d", ret); + dev_err(ov02c10->dev, "failed to init controls: %d", ret); goto probe_error_v4l2_ctrl_handler_free; } @@ -934,33 +920,33 @@ static int ov02c10_probe(struct i2c_client *client) ov02c10->pad.flags = MEDIA_PAD_FL_SOURCE; ret = media_entity_pads_init(&ov02c10->sd.entity, 1, &ov02c10->pad); if (ret) { - dev_err(&client->dev, "failed to init entity pads: %d", ret); + dev_err(ov02c10->dev, "failed to init entity pads: %d", ret); goto probe_error_v4l2_ctrl_handler_free; } ov02c10->sd.state_lock = ov02c10->ctrl_handler.lock; ret = v4l2_subdev_init_finalize(&ov02c10->sd); if (ret < 0) { - dev_err(&client->dev, "failed to init subdev: %d", ret); + dev_err(ov02c10->dev, "failed to init subdev: %d", ret); goto probe_error_media_entity_cleanup; } - pm_runtime_set_active(&client->dev); - pm_runtime_enable(&client->dev); + pm_runtime_set_active(ov02c10->dev); + pm_runtime_enable(ov02c10->dev); ret = v4l2_async_register_subdev_sensor(&ov02c10->sd); if (ret < 0) { - dev_err(&client->dev, "failed to register V4L2 subdev: %d", + dev_err(ov02c10->dev, "failed to register V4L2 subdev: %d", ret); goto probe_error_v4l2_subdev_cleanup; } - pm_runtime_idle(&client->dev); + pm_runtime_idle(ov02c10->dev); return 0; probe_error_v4l2_subdev_cleanup: - pm_runtime_disable(&client->dev); - pm_runtime_set_suspended(&client->dev); + pm_runtime_disable(ov02c10->dev); + pm_runtime_set_suspended(ov02c10->dev); v4l2_subdev_cleanup(&ov02c10->sd); probe_error_media_entity_cleanup: @@ -970,7 +956,7 @@ probe_error_v4l2_ctrl_handler_free: v4l2_ctrl_handler_free(ov02c10->sd.ctrl_handler); probe_error_power_off: - ov02c10_power_off(&client->dev); + ov02c10_power_off(ov02c10->dev); return ret; } diff --git a/drivers/media/i2c/ov02e10.c b/drivers/media/i2c/ov02e10.c index d74dc62e189d..4a64cba99991 100644 --- a/drivers/media/i2c/ov02e10.c +++ b/drivers/media/i2c/ov02e10.c @@ -226,6 +226,8 @@ static const char * const ov02e10_supply_names[] = { }; struct ov02e10 { + struct device *dev; + struct regmap *regmap; struct v4l2_subdev sd; struct media_pad pad; @@ -288,7 +290,6 @@ static int ov02e10_set_ctrl(struct v4l2_ctrl *ctrl) { struct ov02e10 *ov02e10 = container_of(ctrl->handler, struct ov02e10, ctrl_handler); - struct i2c_client *client = v4l2_get_subdevdata(&ov02e10->sd); s64 exposure_max; int ret; @@ -307,7 +308,7 @@ static int ov02e10_set_ctrl(struct v4l2_ctrl *ctrl) } /* V4L2 controls values will be applied only when power is already up */ - if (!pm_runtime_get_if_in_use(&client->dev)) + if (!pm_runtime_get_if_in_use(ov02e10->dev)) return 0; ret = cci_write(ov02e10->regmap, OV02E10_REG_COMMAND_UPDATE, @@ -363,7 +364,7 @@ static int ov02e10_set_ctrl(struct v4l2_ctrl *ctrl) cci_write(ov02e10->regmap, OV02E10_REG_COMMAND_UPDATE, OV02E10_COMMAND_UPDATE, &ret); - pm_runtime_put(&client->dev); + pm_runtime_put(ov02e10->dev); return ret; } @@ -374,7 +375,6 @@ static const struct v4l2_ctrl_ops ov02e10_ctrl_ops = { static int ov02e10_init_controls(struct ov02e10 *ov02e10) { - struct i2c_client *client = v4l2_get_subdevdata(&ov02e10->sd); struct v4l2_ctrl_handler *ctrl_hdlr = &ov02e10->ctrl_handler; const struct ov02e10_mode *mode = ov02e10->cur_mode; u32 vblank_min, vblank_max, vblank_def; @@ -442,7 +442,7 @@ static int ov02e10_init_controls(struct ov02e10 *ov02e10) ARRAY_SIZE(ov02e10_test_pattern_menu) - 1, 0, 0, ov02e10_test_pattern_menu); - ret = v4l2_fwnode_device_parse(&client->dev, &props); + ret = v4l2_fwnode_device_parse(ov02e10->dev, &props); if (ret) return ret; @@ -481,12 +481,11 @@ static int ov02e10_enable_streams(struct v4l2_subdev *sd, struct v4l2_subdev_state *state, u32 pad, u64 streams_mask) { - struct i2c_client *client = v4l2_get_subdevdata(sd); struct ov02e10 *ov02e10 = to_ov02e10(sd); const struct reg_sequence_list *reg_list; int ret; - ret = pm_runtime_resume_and_get(&client->dev); + ret = pm_runtime_resume_and_get(ov02e10->dev); if (ret) return ret; @@ -494,7 +493,7 @@ static int ov02e10_enable_streams(struct v4l2_subdev *sd, ret = regmap_multi_reg_write(ov02e10->regmap, reg_list->regs, reg_list->num_regs); if (ret) { - dev_err(&client->dev, "failed to set mode\n"); + dev_err(ov02e10->dev, "failed to set mode\n"); goto out; } @@ -506,7 +505,7 @@ static int ov02e10_enable_streams(struct v4l2_subdev *sd, out: if (ret) - pm_runtime_put(&client->dev); + pm_runtime_put(ov02e10->dev); return ret; } @@ -515,11 +514,10 @@ static int ov02e10_disable_streams(struct v4l2_subdev *sd, struct v4l2_subdev_state *state, u32 pad, u64 streams_mask) { - struct i2c_client *client = v4l2_get_subdevdata(sd); struct ov02e10 *ov02e10 = to_ov02e10(sd); ov02e10_set_stream_mode(ov02e10, 0); - pm_runtime_put(&client->dev); + pm_runtime_put(ov02e10->dev); return 0; } @@ -724,7 +722,6 @@ static const struct v4l2_subdev_internal_ops ov02e10_internal_ops = { static int ov02e10_identify_module(struct ov02e10 *ov02e10) { - struct i2c_client *client = v4l2_get_subdevdata(&ov02e10->sd); int ret; u64 val; @@ -735,7 +732,7 @@ static int ov02e10_identify_module(struct ov02e10 *ov02e10) return ret; if (val != OV02E10_CHIP_ID) { - dev_err(&client->dev, "chip id mismatch: %x!=%x\n", + dev_err(ov02e10->dev, "chip id mismatch: %x!=%x\n", OV02E10_CHIP_ID, (u32)val); return -ENXIO; } @@ -743,15 +740,15 @@ static int ov02e10_identify_module(struct ov02e10 *ov02e10) return 0; } -static int ov02e10_check_hwcfg(struct device *dev, struct ov02e10 *ov02e10) +static int ov02e10_check_hwcfg(struct ov02e10 *ov02e10) { struct v4l2_fwnode_endpoint bus_cfg = { .bus_type = V4L2_MBUS_CSI2_DPHY }; + struct device *dev = ov02e10->dev; struct fwnode_handle *ep; struct fwnode_handle *fwnode = dev_fwnode(dev); unsigned long link_freq_bitmap; - u32 ext_clk; int ret; ep = fwnode_graph_get_next_endpoint(fwnode, NULL); @@ -764,31 +761,6 @@ static int ov02e10_check_hwcfg(struct device *dev, struct ov02e10 *ov02e10) if (ret) return dev_err_probe(dev, ret, "parsing endpoint failed\n"); - ov02e10->img_clk = devm_clk_get_optional(dev, NULL); - if (IS_ERR(ov02e10->img_clk)) { - ret = dev_err_probe(dev, PTR_ERR(ov02e10->img_clk), - "failed to get imaging clock\n"); - goto out_err; - } - - if (ov02e10->img_clk) { - ext_clk = clk_get_rate(ov02e10->img_clk); - } else { - ret = fwnode_property_read_u32(dev_fwnode(dev), "clock-frequency", - &ext_clk); - if (ret) { - dev_err(dev, "can't get clock frequency\n"); - goto out_err; - } - } - - if (ext_clk != OV02E10_MCLK) { - dev_err(dev, "external clock %d is not supported\n", - ext_clk); - ret = -EINVAL; - goto out_err; - } - if (bus_cfg.bus.mipi_csi2.num_data_lanes != OV02E10_DATA_LANES) { dev_err(dev, "number of CSI2 data lanes %d is not supported\n", bus_cfg.bus.mipi_csi2.num_data_lanes); @@ -823,32 +795,47 @@ out_err: static void ov02e10_remove(struct i2c_client *client) { struct v4l2_subdev *sd = i2c_get_clientdata(client); + struct ov02e10 *ov02e10 = to_ov02e10(sd); v4l2_async_unregister_subdev(sd); v4l2_subdev_cleanup(sd); media_entity_cleanup(&sd->entity); v4l2_ctrl_handler_free(sd->ctrl_handler); - pm_runtime_disable(&client->dev); + pm_runtime_disable(ov02e10->dev); - if (!pm_runtime_status_suspended(&client->dev)) { - ov02e10_power_off(&client->dev); - pm_runtime_set_suspended(&client->dev); + if (!pm_runtime_status_suspended(ov02e10->dev)) { + ov02e10_power_off(ov02e10->dev); + pm_runtime_set_suspended(ov02e10->dev); } } static int ov02e10_probe(struct i2c_client *client) { struct ov02e10 *ov02e10; + unsigned long freq; int ret; ov02e10 = devm_kzalloc(&client->dev, sizeof(*ov02e10), GFP_KERNEL); if (!ov02e10) return -ENOMEM; + ov02e10->dev = &client->dev; + + ov02e10->img_clk = devm_v4l2_sensor_clk_get(ov02e10->dev, NULL); + if (IS_ERR(ov02e10->img_clk)) + return dev_err_probe(ov02e10->dev, PTR_ERR(ov02e10->img_clk), + "failed to get imaging clock\n"); + + freq = clk_get_rate(ov02e10->img_clk); + if (freq != OV02E10_MCLK) + return dev_err_probe(ov02e10->dev, -EINVAL, + "external clock %lu is not supported", + freq); + v4l2_i2c_subdev_init(&ov02e10->sd, client, &ov02e10_subdev_ops); /* Check HW config */ - ret = ov02e10_check_hwcfg(&client->dev, ov02e10); + ret = ov02e10_check_hwcfg(ov02e10); if (ret) return ret; @@ -857,27 +844,27 @@ static int ov02e10_probe(struct i2c_client *client) if (IS_ERR(ov02e10->regmap)) return PTR_ERR(ov02e10->regmap); - ret = ov02e10_get_pm_resources(&client->dev); + ret = ov02e10_get_pm_resources(ov02e10->dev); if (ret) return ret; - ret = ov02e10_power_on(&client->dev); + ret = ov02e10_power_on(ov02e10->dev); if (ret) { - dev_err_probe(&client->dev, ret, "failed to power on\n"); + dev_err_probe(ov02e10->dev, ret, "failed to power on\n"); return ret; } /* Check module identity */ ret = ov02e10_identify_module(ov02e10); if (ret) { - dev_err(&client->dev, "failed to find sensor: %d\n", ret); + dev_err(ov02e10->dev, "failed to find sensor: %d\n", ret); goto probe_error_power_off; } ov02e10->cur_mode = &supported_modes[0]; ret = ov02e10_init_controls(ov02e10); if (ret) { - dev_err(&client->dev, "failed to init controls: %d\n", ret); + dev_err(ov02e10->dev, "failed to init controls: %d\n", ret); goto probe_error_v4l2_ctrl_handler_free; } @@ -891,33 +878,33 @@ static int ov02e10_probe(struct i2c_client *client) ov02e10->pad.flags = MEDIA_PAD_FL_SOURCE; ret = media_entity_pads_init(&ov02e10->sd.entity, 1, &ov02e10->pad); if (ret) { - dev_err(&client->dev, "failed to init entity pads: %d", ret); + dev_err(ov02e10->dev, "failed to init entity pads: %d", ret); goto probe_error_v4l2_ctrl_handler_free; } ov02e10->sd.state_lock = ov02e10->ctrl_handler.lock; ret = v4l2_subdev_init_finalize(&ov02e10->sd); if (ret < 0) { - dev_err(&client->dev, "failed to init subdev: %d", ret); + dev_err(ov02e10->dev, "failed to init subdev: %d", ret); goto probe_error_media_entity_cleanup; } - pm_runtime_set_active(&client->dev); - pm_runtime_enable(&client->dev); + pm_runtime_set_active(ov02e10->dev); + pm_runtime_enable(ov02e10->dev); ret = v4l2_async_register_subdev_sensor(&ov02e10->sd); if (ret < 0) { - dev_err(&client->dev, "failed to register V4L2 subdev: %d", + dev_err(ov02e10->dev, "failed to register V4L2 subdev: %d", ret); goto probe_error_v4l2_subdev_cleanup; } - pm_runtime_idle(&client->dev); + pm_runtime_idle(ov02e10->dev); return 0; probe_error_v4l2_subdev_cleanup: - pm_runtime_disable(&client->dev); - pm_runtime_set_suspended(&client->dev); + pm_runtime_disable(ov02e10->dev); + pm_runtime_set_suspended(ov02e10->dev); v4l2_subdev_cleanup(&ov02e10->sd); probe_error_media_entity_cleanup: @@ -927,7 +914,7 @@ probe_error_v4l2_ctrl_handler_free: v4l2_ctrl_handler_free(ov02e10->sd.ctrl_handler); probe_error_power_off: - ov02e10_power_off(&client->dev); + ov02e10_power_off(ov02e10->dev); return ret; } @@ -961,7 +948,7 @@ static struct i2c_driver ov02e10_i2c_driver = { module_i2c_driver(ov02e10_i2c_driver); -MODULE_AUTHOR("Jingjing Xiong <jingjing.xiong@intel.com>"); +MODULE_AUTHOR("Jingjing Xiong"); MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>"); MODULE_AUTHOR("Alan Stern <stern@rowland.harvard.edu>"); MODULE_AUTHOR("Bryan O'Donoghue <bryan.odonoghue@linaro.org>"); diff --git a/drivers/media/i2c/ov08d10.c b/drivers/media/i2c/ov08d10.c index 1bacbdfa4298..43ec2a1f2fcf 100644 --- a/drivers/media/i2c/ov08d10.c +++ b/drivers/media/i2c/ov08d10.c @@ -515,12 +515,13 @@ static const char * const ov08d10_test_pattern_menu[] = { }; struct ov08d10 { + struct device *dev; + struct clk *clk; + struct v4l2_subdev sd; struct media_pad pad; struct v4l2_ctrl_handler ctrl_handler; - struct clk *xvclk; - /* V4L2 Controls */ struct v4l2_ctrl *link_freq; struct v4l2_ctrl *pixel_rate; @@ -663,7 +664,7 @@ static int ov08d10_write_reg_list(struct ov08d10 *ov08d10, ret = i2c_smbus_write_byte_data(client, r_list->regs[i].address, r_list->regs[i].val); if (ret) { - dev_err_ratelimited(&client->dev, + dev_err_ratelimited(ov08d10->dev, "failed to write reg 0x%2.2x. error = %d", r_list->regs[i].address, ret); return ret; @@ -849,7 +850,6 @@ static int ov08d10_set_ctrl(struct v4l2_ctrl *ctrl) { struct ov08d10 *ov08d10 = container_of(ctrl->handler, struct ov08d10, ctrl_handler); - struct i2c_client *client = v4l2_get_subdevdata(&ov08d10->sd); s64 exposure_max; int ret; @@ -865,7 +865,7 @@ static int ov08d10_set_ctrl(struct v4l2_ctrl *ctrl) } /* V4L2 controls values will be applied only when power is already up */ - if (!pm_runtime_get_if_in_use(&client->dev)) + if (!pm_runtime_get_if_in_use(ov08d10->dev)) return 0; switch (ctrl->id) { @@ -901,7 +901,7 @@ static int ov08d10_set_ctrl(struct v4l2_ctrl *ctrl) break; } - pm_runtime_put(&client->dev); + pm_runtime_put(ov08d10->dev); return ret; } @@ -1025,32 +1025,32 @@ static int ov08d10_start_streaming(struct ov08d10 *ov08d10) /* soft reset */ ret = i2c_smbus_write_byte_data(client, OV08D10_REG_PAGE, 0x00); if (ret < 0) { - dev_err(&client->dev, "failed to reset sensor"); + dev_err(ov08d10->dev, "failed to reset sensor"); return ret; } ret = i2c_smbus_write_byte_data(client, 0x20, 0x0e); if (ret < 0) { - dev_err(&client->dev, "failed to reset sensor"); + dev_err(ov08d10->dev, "failed to reset sensor"); return ret; } usleep_range(3000, 4000); ret = i2c_smbus_write_byte_data(client, 0x20, 0x0b); if (ret < 0) { - dev_err(&client->dev, "failed to reset sensor"); + dev_err(ov08d10->dev, "failed to reset sensor"); return ret; } /* update sensor setting */ ret = ov08d10_write_reg_list(ov08d10, reg_list); if (ret) { - dev_err(&client->dev, "failed to set plls"); + dev_err(ov08d10->dev, "failed to set plls"); return ret; } reg_list = &ov08d10->cur_mode->reg_list; ret = ov08d10_write_reg_list(ov08d10, reg_list); if (ret) { - dev_err(&client->dev, "failed to set mode"); + dev_err(ov08d10->dev, "failed to set mode"); return ret; } @@ -1077,19 +1077,19 @@ static void ov08d10_stop_streaming(struct ov08d10 *ov08d10) ret = i2c_smbus_write_byte_data(client, OV08D10_REG_PAGE, 0x00); if (ret < 0) { - dev_err(&client->dev, "failed to stop streaming"); + dev_err(ov08d10->dev, "failed to stop streaming"); return; } ret = i2c_smbus_write_byte_data(client, OV08D10_REG_MODE_SELECT, OV08D10_MODE_STANDBY); if (ret < 0) { - dev_err(&client->dev, "failed to stop streaming"); + dev_err(ov08d10->dev, "failed to stop streaming"); return; } ret = i2c_smbus_write_byte_data(client, OV08D10_REG_PAGE, 0x01); if (ret < 0) { - dev_err(&client->dev, "failed to stop streaming"); + dev_err(ov08d10->dev, "failed to stop streaming"); return; } } @@ -1097,12 +1097,11 @@ static void ov08d10_stop_streaming(struct ov08d10 *ov08d10) static int ov08d10_set_stream(struct v4l2_subdev *sd, int enable) { struct ov08d10 *ov08d10 = to_ov08d10(sd); - struct i2c_client *client = v4l2_get_subdevdata(sd); int ret = 0; mutex_lock(&ov08d10->mutex); if (enable) { - ret = pm_runtime_resume_and_get(&client->dev); + ret = pm_runtime_resume_and_get(ov08d10->dev); if (ret < 0) { mutex_unlock(&ov08d10->mutex); return ret; @@ -1112,11 +1111,11 @@ static int ov08d10_set_stream(struct v4l2_subdev *sd, int enable) if (ret) { enable = 0; ov08d10_stop_streaming(ov08d10); - pm_runtime_put(&client->dev); + pm_runtime_put(ov08d10->dev); } } else { ov08d10_stop_streaming(ov08d10); - pm_runtime_put(&client->dev); + pm_runtime_put(ov08d10->dev); } /* vflip and hflip cannot change during streaming */ @@ -1293,7 +1292,7 @@ static int ov08d10_identify_module(struct ov08d10 *ov08d10) chip_id = val | ret; if ((chip_id & OV08D10_ID_MASK) != OV08D10_CHIP_ID) { - dev_err(&client->dev, "unexpected sensor id(0x%04x)\n", + dev_err(ov08d10->dev, "unexpected sensor id(0x%04x)\n", chip_id); return -EINVAL; } @@ -1301,28 +1300,20 @@ static int ov08d10_identify_module(struct ov08d10 *ov08d10) return 0; } -static int ov08d10_get_hwcfg(struct ov08d10 *ov08d10, struct device *dev) +static int ov08d10_get_hwcfg(struct ov08d10 *ov08d10) { + struct device *dev = ov08d10->dev; struct fwnode_handle *ep; struct fwnode_handle *fwnode = dev_fwnode(dev); struct v4l2_fwnode_endpoint bus_cfg = { .bus_type = V4L2_MBUS_CSI2_DPHY }; - u32 xvclk_rate; unsigned int i, j; int ret; if (!fwnode) return -ENXIO; - ret = fwnode_property_read_u32(fwnode, "clock-frequency", &xvclk_rate); - if (ret) - return ret; - - if (xvclk_rate != OV08D10_XVCLK_19_2) - dev_warn(dev, "external clock rate %u is unsupported", - xvclk_rate); - ep = fwnode_graph_get_next_endpoint(fwnode, NULL); if (!ep) return -ENXIO; @@ -1380,22 +1371,35 @@ static void ov08d10_remove(struct i2c_client *client) v4l2_async_unregister_subdev(sd); media_entity_cleanup(&sd->entity); v4l2_ctrl_handler_free(sd->ctrl_handler); - pm_runtime_disable(&client->dev); + pm_runtime_disable(ov08d10->dev); mutex_destroy(&ov08d10->mutex); } static int ov08d10_probe(struct i2c_client *client) { struct ov08d10 *ov08d10; + unsigned long freq; int ret; ov08d10 = devm_kzalloc(&client->dev, sizeof(*ov08d10), GFP_KERNEL); if (!ov08d10) return -ENOMEM; - ret = ov08d10_get_hwcfg(ov08d10, &client->dev); + ov08d10->dev = &client->dev; + + ov08d10->clk = devm_v4l2_sensor_clk_get(ov08d10->dev, NULL); + if (IS_ERR(ov08d10->clk)) + return dev_err_probe(ov08d10->dev, PTR_ERR(ov08d10->clk), + "failed to get clock\n"); + + freq = clk_get_rate(ov08d10->clk); + if (freq != OV08D10_XVCLK_19_2) + dev_warn(ov08d10->dev, + "external clock rate %lu is not supported\n", freq); + + ret = ov08d10_get_hwcfg(ov08d10); if (ret) { - dev_err(&client->dev, "failed to get HW configuration: %d", + dev_err(ov08d10->dev, "failed to get HW configuration: %d", ret); return ret; } @@ -1404,7 +1408,7 @@ static int ov08d10_probe(struct i2c_client *client) ret = ov08d10_identify_module(ov08d10); if (ret) { - dev_err(&client->dev, "failed to find sensor: %d", ret); + dev_err(ov08d10->dev, "failed to find sensor: %d", ret); return ret; } @@ -1412,7 +1416,7 @@ static int ov08d10_probe(struct i2c_client *client) ov08d10->cur_mode = &ov08d10->priv_lane->sp_modes[0]; ret = ov08d10_init_controls(ov08d10); if (ret) { - dev_err(&client->dev, "failed to init controls: %d", ret); + dev_err(ov08d10->dev, "failed to init controls: %d", ret); goto probe_error_v4l2_ctrl_handler_free; } @@ -1422,13 +1426,13 @@ static int ov08d10_probe(struct i2c_client *client) ov08d10->pad.flags = MEDIA_PAD_FL_SOURCE; ret = media_entity_pads_init(&ov08d10->sd.entity, 1, &ov08d10->pad); if (ret) { - dev_err(&client->dev, "failed to init entity pads: %d", ret); + dev_err(ov08d10->dev, "failed to init entity pads: %d", ret); goto probe_error_v4l2_ctrl_handler_free; } ret = v4l2_async_register_subdev_sensor(&ov08d10->sd); if (ret < 0) { - dev_err(&client->dev, "failed to register V4L2 subdev: %d", + dev_err(ov08d10->dev, "failed to register V4L2 subdev: %d", ret); goto probe_error_media_entity_cleanup; } @@ -1437,9 +1441,9 @@ static int ov08d10_probe(struct i2c_client *client) * Device is already turned on by i2c-core with ACPI domain PM. * Enable runtime PM and turn off the device. */ - pm_runtime_set_active(&client->dev); - pm_runtime_enable(&client->dev); - pm_runtime_idle(&client->dev); + pm_runtime_set_active(ov08d10->dev); + pm_runtime_enable(ov08d10->dev); + pm_runtime_idle(ov08d10->dev); return 0; diff --git a/drivers/media/i2c/ov08x40.c b/drivers/media/i2c/ov08x40.c index e0094305ca2a..5eaf454f4763 100644 --- a/drivers/media/i2c/ov08x40.c +++ b/drivers/media/i2c/ov08x40.c @@ -1,15 +1,16 @@ // SPDX-License-Identifier: GPL-2.0 // Copyright (c) 2022 Intel Corporation. -#include <linux/unaligned.h> #include <linux/acpi.h> #include <linux/clk.h> -#include <linux/i2c.h> +#include <linux/delay.h> #include <linux/gpio/consumer.h> +#include <linux/i2c.h> #include <linux/module.h> -#include <linux/delay.h> #include <linux/pm_runtime.h> #include <linux/regulator/consumer.h> +#include <linux/unaligned.h> + #include <media/v4l2-common.h> #include <media/v4l2-ctrls.h> #include <media/v4l2-device.h> @@ -1305,6 +1306,8 @@ static const char * const ov08x40_supply_names[] = { }; struct ov08x40 { + struct device *dev; + struct v4l2_subdev sd; struct media_pad pad; @@ -1513,7 +1516,6 @@ static int ov08x40_write_reg(struct ov08x40 *ov08x, static int ov08x40_write_regs(struct ov08x40 *ov08x, const struct ov08x40_reg *regs, u32 len) { - struct i2c_client *client = v4l2_get_subdevdata(&ov08x->sd); int ret; u32 i; @@ -1522,7 +1524,7 @@ static int ov08x40_write_regs(struct ov08x40 *ov08x, regs[i].val); if (ret) { - dev_err_ratelimited(&client->dev, + dev_err_ratelimited(ov08x->dev, "Failed to write reg 0x%4.4x. error = %d\n", regs[i].address, ret); @@ -1648,7 +1650,7 @@ static int ov08x40_set_ctrl_hflip(struct ov08x40 *ov08x, u32 ctrl_val) return ov08x40_write_reg(ov08x, OV08X40_REG_MIRROR, OV08X40_REG_VALUE_08BIT, - ctrl_val ? val | BIT(2) : val & ~BIT(2)); + ctrl_val ? val & ~BIT(2) : val | BIT(2)); } static int ov08x40_set_ctrl_vflip(struct ov08x40 *ov08x, u32 ctrl_val) @@ -1670,7 +1672,6 @@ static int ov08x40_set_ctrl(struct v4l2_ctrl *ctrl) { struct ov08x40 *ov08x = container_of(ctrl->handler, struct ov08x40, ctrl_handler); - struct i2c_client *client = v4l2_get_subdevdata(&ov08x->sd); s64 max; int exp; int fll; @@ -1699,7 +1700,7 @@ static int ov08x40_set_ctrl(struct v4l2_ctrl *ctrl) * Applying V4L2 control value only happens * when power is up for streaming */ - if (!pm_runtime_get_if_in_use(&client->dev)) + if (!pm_runtime_get_if_in_use(ov08x->dev)) return 0; switch (ctrl->id) { @@ -1737,13 +1738,13 @@ static int ov08x40_set_ctrl(struct v4l2_ctrl *ctrl) ov08x40_set_ctrl_vflip(ov08x, ctrl->val); break; default: - dev_info(&client->dev, + dev_info(ov08x->dev, "ctrl(id:0x%x,val:0x%x) is not handled\n", ctrl->id, ctrl->val); break; } - pm_runtime_put(&client->dev); + pm_runtime_put(ov08x->dev); return ret; } @@ -1912,7 +1913,6 @@ ov08x40_set_pad_format(struct v4l2_subdev *sd, static int ov08x40_start_streaming(struct ov08x40 *ov08x) { - struct i2c_client *client = v4l2_get_subdevdata(&ov08x->sd); const struct ov08x40_reg_list *reg_list; int ret, link_freq_index; @@ -1920,7 +1920,7 @@ static int ov08x40_start_streaming(struct ov08x40 *ov08x) ret = ov08x40_write_reg(ov08x, OV08X40_REG_SOFTWARE_RST, OV08X40_REG_VALUE_08BIT, OV08X40_SOFTWARE_RST); if (ret) { - dev_err(&client->dev, "%s failed to set powerup registers\n", + dev_err(ov08x->dev, "%s failed to set powerup registers\n", __func__); return ret; } @@ -1930,14 +1930,14 @@ static int ov08x40_start_streaming(struct ov08x40 *ov08x) ret = ov08x40_write_reg_list(ov08x, reg_list); if (ret) { - dev_err(&client->dev, "%s failed to set plls\n", __func__); + dev_err(ov08x->dev, "%s failed to set plls\n", __func__); return ret; } reg_list = &ov08x40_global_setting; ret = ov08x40_write_reg_list(ov08x, reg_list); if (ret) { - dev_err(&client->dev, "%s failed to set global setting\n", + dev_err(ov08x->dev, "%s failed to set global setting\n", __func__); return ret; } @@ -1946,7 +1946,7 @@ static int ov08x40_start_streaming(struct ov08x40 *ov08x) reg_list = &ov08x->cur_mode->reg_list; ret = ov08x40_write_reg_list(ov08x, reg_list); if (ret) { - dev_err(&client->dev, "%s failed to set mode\n", __func__); + dev_err(ov08x->dev, "%s failed to set mode\n", __func__); return ret; } @@ -1962,7 +1962,7 @@ static int ov08x40_start_streaming(struct ov08x40 *ov08x) } if (ret) { - dev_err(&client->dev, "%s failed to set regs\n", __func__); + dev_err(ov08x->dev, "%s failed to set regs\n", __func__); return ret; } @@ -1986,7 +1986,6 @@ static int ov08x40_stop_streaming(struct ov08x40 *ov08x) /* Verify chip ID */ static int ov08x40_identify_module(struct ov08x40 *ov08x) { - struct i2c_client *client = v4l2_get_subdevdata(&ov08x->sd); int ret; u32 val; @@ -1996,17 +1995,17 @@ static int ov08x40_identify_module(struct ov08x40 *ov08x) ret = ov08x40_read_reg(ov08x, OV08X40_REG_CHIP_ID, OV08X40_REG_VALUE_24BIT, &val); if (ret) { - dev_err(&client->dev, "error reading chip-id register: %d\n", ret); + dev_err(ov08x->dev, "error reading chip-id register: %d\n", ret); return ret; } if (val != OV08X40_CHIP_ID) { - dev_err(&client->dev, "chip id mismatch: %x!=%x\n", + dev_err(ov08x->dev, "chip id mismatch: %x!=%x\n", OV08X40_CHIP_ID, val); return -ENXIO; } - dev_dbg(&client->dev, "chip id 0x%x\n", val); + dev_dbg(ov08x->dev, "chip id 0x%x\n", val); ov08x->identified = true; return 0; @@ -2015,13 +2014,12 @@ static int ov08x40_identify_module(struct ov08x40 *ov08x) static int ov08x40_set_stream(struct v4l2_subdev *sd, int enable) { struct ov08x40 *ov08x = to_ov08x40(sd); - struct i2c_client *client = v4l2_get_subdevdata(sd); int ret = 0; mutex_lock(&ov08x->mutex); if (enable) { - ret = pm_runtime_resume_and_get(&client->dev); + ret = pm_runtime_resume_and_get(ov08x->dev); if (ret < 0) goto err_unlock; @@ -2038,7 +2036,7 @@ static int ov08x40_set_stream(struct v4l2_subdev *sd, int enable) goto err_rpm_put; } else { ov08x40_stop_streaming(ov08x); - pm_runtime_put(&client->dev); + pm_runtime_put(ov08x->dev); } mutex_unlock(&ov08x->mutex); @@ -2046,7 +2044,7 @@ static int ov08x40_set_stream(struct v4l2_subdev *sd, int enable) return ret; err_rpm_put: - pm_runtime_put(&client->dev); + pm_runtime_put(ov08x->dev); err_unlock: mutex_unlock(&ov08x->mutex); @@ -2079,7 +2077,6 @@ static const struct v4l2_subdev_internal_ops ov08x40_internal_ops = { static int ov08x40_init_controls(struct ov08x40 *ov08x) { - struct i2c_client *client = v4l2_get_subdevdata(&ov08x->sd); struct v4l2_fwnode_device_properties props; struct v4l2_ctrl_handler *ctrl_hdlr; s64 exposure_max; @@ -2160,12 +2157,12 @@ static int ov08x40_init_controls(struct ov08x40 *ov08x) if (ctrl_hdlr->error) { ret = ctrl_hdlr->error; - dev_err(&client->dev, "%s control init failed (%d)\n", + dev_err(ov08x->dev, "%s control init failed (%d)\n", __func__, ret); goto error; } - ret = v4l2_fwnode_device_parse(&client->dev, &props); + ret = v4l2_fwnode_device_parse(ov08x->dev, &props); if (ret) goto error; @@ -2191,11 +2188,12 @@ static void ov08x40_free_controls(struct ov08x40 *ov08x) mutex_destroy(&ov08x->mutex); } -static int ov08x40_check_hwcfg(struct ov08x40 *ov08x, struct device *dev) +static int ov08x40_check_hwcfg(struct ov08x40 *ov08x) { struct v4l2_fwnode_endpoint bus_cfg = { .bus_type = V4L2_MBUS_CSI2_DPHY }; + struct device *dev = ov08x->dev; struct fwnode_handle *ep; struct fwnode_handle *fwnode = dev_fwnode(dev); unsigned int i; @@ -2232,23 +2230,14 @@ static int ov08x40_check_hwcfg(struct ov08x40 *ov08x, struct device *dev) if (ret) goto out_err; - ov08x->xvclk = devm_clk_get_optional(dev, NULL); + ov08x->xvclk = devm_v4l2_sensor_clk_get(dev, NULL); if (IS_ERR(ov08x->xvclk)) { ret = dev_err_probe(dev, PTR_ERR(ov08x->xvclk), "getting xvclk\n"); goto out_err; } - if (ov08x->xvclk) { - xvclk_rate = clk_get_rate(ov08x->xvclk); - } else { - ret = fwnode_property_read_u32(dev_fwnode(dev), "clock-frequency", - &xvclk_rate); - if (ret) { - dev_err(dev, "can't get clock frequency\n"); - goto out_err; - } - } + xvclk_rate = clk_get_rate(ov08x->xvclk); if (xvclk_rate != OV08X40_XVCLK) { dev_err(dev, "external clock %d is not supported\n", xvclk_rate); @@ -2294,19 +2283,21 @@ static int ov08x40_probe(struct i2c_client *client) if (!ov08x) return -ENOMEM; + ov08x->dev = &client->dev; + /* Check HW config */ - ret = ov08x40_check_hwcfg(ov08x, &client->dev); + ret = ov08x40_check_hwcfg(ov08x); if (ret) return ret; /* Initialize subdev */ v4l2_i2c_subdev_init(&ov08x->sd, client, &ov08x40_subdev_ops); - full_power = acpi_dev_state_d0(&client->dev); + full_power = acpi_dev_state_d0(ov08x->dev); if (full_power) { - ret = ov08x40_power_on(&client->dev); + ret = ov08x40_power_on(ov08x->dev); if (ret) { - dev_err(&client->dev, "failed to power on\n"); + dev_err(ov08x->dev, "failed to power on\n"); return ret; } @@ -2333,7 +2324,7 @@ static int ov08x40_probe(struct i2c_client *client) ov08x->pad.flags = MEDIA_PAD_FL_SOURCE; ret = media_entity_pads_init(&ov08x->sd.entity, 1, &ov08x->pad); if (ret) { - dev_err(&client->dev, "%s failed:%d\n", __func__, ret); + dev_err(ov08x->dev, "%s failed:%d\n", __func__, ret); goto error_handler_free; } @@ -2342,9 +2333,9 @@ static int ov08x40_probe(struct i2c_client *client) goto error_media_entity; if (full_power) - pm_runtime_set_active(&client->dev); - pm_runtime_enable(&client->dev); - pm_runtime_idle(&client->dev); + pm_runtime_set_active(ov08x->dev); + pm_runtime_enable(ov08x->dev); + pm_runtime_idle(ov08x->dev); return 0; @@ -2355,7 +2346,7 @@ error_handler_free: ov08x40_free_controls(ov08x); probe_power_off: - ov08x40_power_off(&client->dev); + ov08x40_power_off(ov08x->dev); return ret; } @@ -2369,10 +2360,10 @@ static void ov08x40_remove(struct i2c_client *client) media_entity_cleanup(&sd->entity); ov08x40_free_controls(ov08x); - pm_runtime_disable(&client->dev); - if (!pm_runtime_status_suspended(&client->dev)) - ov08x40_power_off(&client->dev); - pm_runtime_set_suspended(&client->dev); + pm_runtime_disable(ov08x->dev); + if (!pm_runtime_status_suspended(ov08x->dev)) + ov08x40_power_off(ov08x->dev); + pm_runtime_set_suspended(ov08x->dev); } static DEFINE_RUNTIME_DEV_PM_OPS(ov08x40_pm_ops, ov08x40_power_off, diff --git a/drivers/media/i2c/ov13858.c b/drivers/media/i2c/ov13858.c index 7a3fc1d28514..162b49046990 100644 --- a/drivers/media/i2c/ov13858.c +++ b/drivers/media/i2c/ov13858.c @@ -2,6 +2,7 @@ // Copyright (c) 2017 Intel Corporation. #include <linux/acpi.h> +#include <linux/clk.h> #include <linux/i2c.h> #include <linux/module.h> #include <linux/pm_runtime.h> @@ -1028,6 +1029,9 @@ static const struct ov13858_mode supported_modes[] = { }; struct ov13858 { + struct device *dev; + struct clk *clk; + struct v4l2_subdev sd; struct media_pad pad; @@ -1117,7 +1121,6 @@ static int ov13858_write_reg(struct ov13858 *ov13858, u16 reg, u32 len, static int ov13858_write_regs(struct ov13858 *ov13858, const struct ov13858_reg *regs, u32 len) { - struct i2c_client *client = v4l2_get_subdevdata(&ov13858->sd); int ret; u32 i; @@ -1126,7 +1129,7 @@ static int ov13858_write_regs(struct ov13858 *ov13858, regs[i].val); if (ret) { dev_err_ratelimited( - &client->dev, + ov13858->dev, "Failed to write reg 0x%4.4x. error = %d\n", regs[i].address, ret); @@ -1209,7 +1212,6 @@ static int ov13858_set_ctrl(struct v4l2_ctrl *ctrl) { struct ov13858 *ov13858 = container_of(ctrl->handler, struct ov13858, ctrl_handler); - struct i2c_client *client = v4l2_get_subdevdata(&ov13858->sd); s64 max; int ret; @@ -1228,7 +1230,7 @@ static int ov13858_set_ctrl(struct v4l2_ctrl *ctrl) * Applying V4L2 control value only happens * when power is up for streaming */ - if (!pm_runtime_get_if_in_use(&client->dev)) + if (!pm_runtime_get_if_in_use(ov13858->dev)) return 0; ret = 0; @@ -1256,13 +1258,13 @@ static int ov13858_set_ctrl(struct v4l2_ctrl *ctrl) ret = ov13858_enable_test_pattern(ov13858, ctrl->val); break; default: - dev_info(&client->dev, + dev_info(ov13858->dev, "ctrl(id:0x%x,val:0x%x) is not handled\n", ctrl->id, ctrl->val); break; } - pm_runtime_put(&client->dev); + pm_runtime_put(ov13858->dev); return ret; } @@ -1408,7 +1410,6 @@ static int ov13858_get_skip_frames(struct v4l2_subdev *sd, u32 *frames) /* Start streaming */ static int ov13858_start_streaming(struct ov13858 *ov13858) { - struct i2c_client *client = v4l2_get_subdevdata(&ov13858->sd); const struct ov13858_reg_list *reg_list; int ret, link_freq_index; @@ -1416,7 +1417,7 @@ static int ov13858_start_streaming(struct ov13858 *ov13858) ret = ov13858_write_reg(ov13858, OV13858_REG_SOFTWARE_RST, OV13858_REG_VALUE_08BIT, OV13858_SOFTWARE_RST); if (ret) { - dev_err(&client->dev, "%s failed to set powerup registers\n", + dev_err(ov13858->dev, "%s failed to set powerup registers\n", __func__); return ret; } @@ -1426,7 +1427,7 @@ static int ov13858_start_streaming(struct ov13858 *ov13858) reg_list = &link_freq_configs[link_freq_index].reg_list; ret = ov13858_write_reg_list(ov13858, reg_list); if (ret) { - dev_err(&client->dev, "%s failed to set plls\n", __func__); + dev_err(ov13858->dev, "%s failed to set plls\n", __func__); return ret; } @@ -1434,7 +1435,7 @@ static int ov13858_start_streaming(struct ov13858 *ov13858) reg_list = &ov13858->cur_mode->reg_list; ret = ov13858_write_reg_list(ov13858, reg_list); if (ret) { - dev_err(&client->dev, "%s failed to set mode\n", __func__); + dev_err(ov13858->dev, "%s failed to set mode\n", __func__); return ret; } @@ -1458,13 +1459,12 @@ static int ov13858_stop_streaming(struct ov13858 *ov13858) static int ov13858_set_stream(struct v4l2_subdev *sd, int enable) { struct ov13858 *ov13858 = to_ov13858(sd); - struct i2c_client *client = v4l2_get_subdevdata(sd); int ret = 0; mutex_lock(&ov13858->mutex); if (enable) { - ret = pm_runtime_resume_and_get(&client->dev); + ret = pm_runtime_resume_and_get(ov13858->dev); if (ret < 0) goto err_unlock; @@ -1477,7 +1477,7 @@ static int ov13858_set_stream(struct v4l2_subdev *sd, int enable) goto err_rpm_put; } else { ov13858_stop_streaming(ov13858); - pm_runtime_put(&client->dev); + pm_runtime_put(ov13858->dev); } mutex_unlock(&ov13858->mutex); @@ -1485,7 +1485,7 @@ static int ov13858_set_stream(struct v4l2_subdev *sd, int enable) return ret; err_rpm_put: - pm_runtime_put(&client->dev); + pm_runtime_put(ov13858->dev); err_unlock: mutex_unlock(&ov13858->mutex); @@ -1495,7 +1495,6 @@ err_unlock: /* Verify chip ID */ static int ov13858_identify_module(struct ov13858 *ov13858) { - struct i2c_client *client = v4l2_get_subdevdata(&ov13858->sd); int ret; u32 val; @@ -1505,7 +1504,7 @@ static int ov13858_identify_module(struct ov13858 *ov13858) return ret; if (val != OV13858_CHIP_ID) { - dev_err(&client->dev, "chip id mismatch: %x!=%x\n", + dev_err(ov13858->dev, "chip id mismatch: %x!=%x\n", OV13858_CHIP_ID, val); return -EIO; } @@ -1552,7 +1551,6 @@ static const struct v4l2_subdev_internal_ops ov13858_internal_ops = { /* Initialize control handlers */ static int ov13858_init_controls(struct ov13858 *ov13858) { - struct i2c_client *client = v4l2_get_subdevdata(&ov13858->sd); struct v4l2_fwnode_device_properties props; struct v4l2_ctrl_handler *ctrl_hdlr; s64 exposure_max; @@ -1626,12 +1624,12 @@ static int ov13858_init_controls(struct ov13858 *ov13858) 0, 0, ov13858_test_pattern_menu); if (ctrl_hdlr->error) { ret = ctrl_hdlr->error; - dev_err(&client->dev, "%s control init failed (%d)\n", + dev_err(ov13858->dev, "%s control init failed (%d)\n", __func__, ret); goto error; } - ret = v4l2_fwnode_device_parse(&client->dev, &props); + ret = v4l2_fwnode_device_parse(ov13858->dev, &props); if (ret) goto error; @@ -1660,24 +1658,33 @@ static void ov13858_free_controls(struct ov13858 *ov13858) static int ov13858_probe(struct i2c_client *client) { struct ov13858 *ov13858; + unsigned long freq; int ret; - u32 val = 0; - - device_property_read_u32(&client->dev, "clock-frequency", &val); - if (val != 19200000) - return -EINVAL; ov13858 = devm_kzalloc(&client->dev, sizeof(*ov13858), GFP_KERNEL); if (!ov13858) return -ENOMEM; + ov13858->dev = &client->dev; + + ov13858->clk = devm_v4l2_sensor_clk_get(ov13858->dev, NULL); + if (IS_ERR(ov13858->clk)) + return dev_err_probe(ov13858->dev, PTR_ERR(ov13858->clk), + "failed to get clock\n"); + + freq = clk_get_rate(ov13858->clk); + if (freq != 19200000) + return dev_err_probe(ov13858->dev, -EINVAL, + "external clock %lu is not supported\n", + freq); + /* Initialize subdev */ v4l2_i2c_subdev_init(&ov13858->sd, client, &ov13858_subdev_ops); /* Check module identity */ ret = ov13858_identify_module(ov13858); if (ret) { - dev_err(&client->dev, "failed to find sensor: %d\n", ret); + dev_err(ov13858->dev, "failed to find sensor: %d\n", ret); return ret; } @@ -1699,7 +1706,7 @@ static int ov13858_probe(struct i2c_client *client) ov13858->pad.flags = MEDIA_PAD_FL_SOURCE; ret = media_entity_pads_init(&ov13858->sd.entity, 1, &ov13858->pad); if (ret) { - dev_err(&client->dev, "%s failed:%d\n", __func__, ret); + dev_err(ov13858->dev, "%s failed:%d\n", __func__, ret); goto error_handler_free; } @@ -1711,9 +1718,9 @@ static int ov13858_probe(struct i2c_client *client) * Device is already turned on by i2c-core with ACPI domain PM. * Enable runtime PM and turn off the device. */ - pm_runtime_set_active(&client->dev); - pm_runtime_enable(&client->dev); - pm_runtime_idle(&client->dev); + pm_runtime_set_active(ov13858->dev); + pm_runtime_enable(ov13858->dev); + pm_runtime_idle(ov13858->dev); return 0; @@ -1722,7 +1729,7 @@ error_media_entity: error_handler_free: ov13858_free_controls(ov13858); - dev_err(&client->dev, "%s failed:%d\n", __func__, ret); + dev_err(ov13858->dev, "%s failed:%d\n", __func__, ret); return ret; } @@ -1736,7 +1743,7 @@ static void ov13858_remove(struct i2c_client *client) media_entity_cleanup(&sd->entity); ov13858_free_controls(ov13858); - pm_runtime_disable(&client->dev); + pm_runtime_disable(ov13858->dev); } static const struct i2c_device_id ov13858_id_table[] = { diff --git a/drivers/media/i2c/ov13b10.c b/drivers/media/i2c/ov13b10.c index e85c7d33a670..869bc78ed792 100644 --- a/drivers/media/i2c/ov13b10.c +++ b/drivers/media/i2c/ov13b10.c @@ -700,6 +700,8 @@ static const struct ov13b10_mode supported_2_lanes_modes[] = { }; struct ov13b10 { + struct device *dev; + struct v4l2_subdev sd; struct media_pad pad; @@ -805,7 +807,6 @@ static int ov13b10_write_reg(struct ov13b10 *ov13b, static int ov13b10_write_regs(struct ov13b10 *ov13b, const struct ov13b10_reg *regs, u32 len) { - struct i2c_client *client = v4l2_get_subdevdata(&ov13b->sd); int ret; u32 i; @@ -813,7 +814,7 @@ static int ov13b10_write_regs(struct ov13b10 *ov13b, ret = ov13b10_write_reg(ov13b, regs[i].address, 1, regs[i].val); if (ret) { - dev_err_ratelimited(&client->dev, + dev_err_ratelimited(ov13b->dev, "Failed to write reg 0x%4.4x. error = %d\n", regs[i].address, ret); @@ -968,7 +969,6 @@ static int ov13b10_set_ctrl(struct v4l2_ctrl *ctrl) { struct ov13b10 *ov13b = container_of(ctrl->handler, struct ov13b10, ctrl_handler); - struct i2c_client *client = v4l2_get_subdevdata(&ov13b->sd); s64 max; int ret; @@ -987,7 +987,7 @@ static int ov13b10_set_ctrl(struct v4l2_ctrl *ctrl) * Applying V4L2 control value only happens * when power is up for streaming */ - if (!pm_runtime_get_if_in_use(&client->dev)) + if (!pm_runtime_get_if_in_use(ov13b->dev)) return 0; ret = 0; @@ -1021,13 +1021,13 @@ static int ov13b10_set_ctrl(struct v4l2_ctrl *ctrl) ov13b10_set_ctrl_vflip(ov13b, ctrl->val); break; default: - dev_info(&client->dev, + dev_info(ov13b->dev, "ctrl(id:0x%x,val:0x%x) is not handled\n", ctrl->id, ctrl->val); break; } - pm_runtime_put(&client->dev); + pm_runtime_put(ov13b->dev); return ret; } @@ -1166,7 +1166,6 @@ ov13b10_set_pad_format(struct v4l2_subdev *sd, /* Verify chip ID */ static int ov13b10_identify_module(struct ov13b10 *ov13b) { - struct i2c_client *client = v4l2_get_subdevdata(&ov13b->sd); int ret; u32 val; @@ -1179,7 +1178,7 @@ static int ov13b10_identify_module(struct ov13b10 *ov13b) return ret; if (val != OV13B10_CHIP_ID) { - dev_err(&client->dev, "chip id mismatch: %x!=%x\n", + dev_err(ov13b->dev, "chip id mismatch: %x!=%x\n", OV13B10_CHIP_ID, val); return -EIO; } @@ -1234,7 +1233,6 @@ static int ov13b10_power_on(struct device *dev) static int ov13b10_start_streaming(struct ov13b10 *ov13b) { - struct i2c_client *client = v4l2_get_subdevdata(&ov13b->sd); const struct ov13b10_reg_list *reg_list; int ret, link_freq_index; @@ -1246,7 +1244,7 @@ static int ov13b10_start_streaming(struct ov13b10 *ov13b) ret = ov13b10_write_reg(ov13b, OV13B10_REG_SOFTWARE_RST, OV13B10_REG_VALUE_08BIT, OV13B10_SOFTWARE_RST); if (ret) { - dev_err(&client->dev, "%s failed to set powerup registers\n", + dev_err(ov13b->dev, "%s failed to set powerup registers\n", __func__); return ret; } @@ -1255,7 +1253,7 @@ static int ov13b10_start_streaming(struct ov13b10 *ov13b) reg_list = &link_freq_configs[link_freq_index].reg_list; ret = ov13b10_write_reg_list(ov13b, reg_list); if (ret) { - dev_err(&client->dev, "%s failed to set plls\n", __func__); + dev_err(ov13b->dev, "%s failed to set plls\n", __func__); return ret; } @@ -1263,7 +1261,7 @@ static int ov13b10_start_streaming(struct ov13b10 *ov13b) reg_list = &ov13b->cur_mode->reg_list; ret = ov13b10_write_reg_list(ov13b, reg_list); if (ret) { - dev_err(&client->dev, "%s failed to set mode\n", __func__); + dev_err(ov13b->dev, "%s failed to set mode\n", __func__); return ret; } @@ -1287,13 +1285,12 @@ static int ov13b10_stop_streaming(struct ov13b10 *ov13b) static int ov13b10_set_stream(struct v4l2_subdev *sd, int enable) { struct ov13b10 *ov13b = to_ov13b10(sd); - struct i2c_client *client = v4l2_get_subdevdata(sd); int ret = 0; mutex_lock(&ov13b->mutex); if (enable) { - ret = pm_runtime_resume_and_get(&client->dev); + ret = pm_runtime_resume_and_get(ov13b->dev); if (ret < 0) goto err_unlock; @@ -1306,7 +1303,7 @@ static int ov13b10_set_stream(struct v4l2_subdev *sd, int enable) goto err_rpm_put; } else { ov13b10_stop_streaming(ov13b); - pm_runtime_put(&client->dev); + pm_runtime_put(ov13b->dev); } mutex_unlock(&ov13b->mutex); @@ -1314,7 +1311,7 @@ static int ov13b10_set_stream(struct v4l2_subdev *sd, int enable) return ret; err_rpm_put: - pm_runtime_put(&client->dev); + pm_runtime_put(ov13b->dev); err_unlock: mutex_unlock(&ov13b->mutex); @@ -1360,7 +1357,6 @@ static const struct v4l2_subdev_internal_ops ov13b10_internal_ops = { /* Initialize control handlers */ static int ov13b10_init_controls(struct ov13b10 *ov13b) { - struct i2c_client *client = v4l2_get_subdevdata(&ov13b->sd); struct v4l2_fwnode_device_properties props; struct v4l2_ctrl_handler *ctrl_hdlr; s64 exposure_max; @@ -1443,12 +1439,12 @@ static int ov13b10_init_controls(struct ov13b10 *ov13b) if (ctrl_hdlr->error) { ret = ctrl_hdlr->error; - dev_err(&client->dev, "%s control init failed (%d)\n", + dev_err(ov13b->dev, "%s control init failed (%d)\n", __func__, ret); goto error; } - ret = v4l2_fwnode_device_parse(&client->dev, &props); + ret = v4l2_fwnode_device_parse(ov13b->dev, &props); if (ret) goto error; @@ -1474,44 +1470,49 @@ static void ov13b10_free_controls(struct ov13b10 *ov13b) mutex_destroy(&ov13b->mutex); } -static int ov13b10_get_pm_resources(struct device *dev) +static int ov13b10_get_pm_resources(struct ov13b10 *ov13b) { - struct v4l2_subdev *sd = dev_get_drvdata(dev); - struct ov13b10 *ov13b = to_ov13b10(sd); + unsigned long freq; int ret; - ov13b->reset = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW); + ov13b->reset = devm_gpiod_get_optional(ov13b->dev, "reset", GPIOD_OUT_LOW); if (IS_ERR(ov13b->reset)) - return dev_err_probe(dev, PTR_ERR(ov13b->reset), + return dev_err_probe(ov13b->dev, PTR_ERR(ov13b->reset), "failed to get reset gpio\n"); - ov13b->img_clk = devm_clk_get_optional(dev, NULL); + ov13b->img_clk = devm_v4l2_sensor_clk_get(ov13b->dev, NULL); if (IS_ERR(ov13b->img_clk)) - return dev_err_probe(dev, PTR_ERR(ov13b->img_clk), + return dev_err_probe(ov13b->dev, PTR_ERR(ov13b->img_clk), "failed to get imaging clock\n"); - ov13b->avdd = devm_regulator_get_optional(dev, "avdd"); + freq = clk_get_rate(ov13b->img_clk); + if (freq != OV13B10_EXT_CLK) + return dev_err_probe(ov13b->dev, -EINVAL, + "external clock %lu is not supported\n", + freq); + + ov13b->avdd = devm_regulator_get_optional(ov13b->dev, "avdd"); if (IS_ERR(ov13b->avdd)) { ret = PTR_ERR(ov13b->avdd); ov13b->avdd = NULL; if (ret != -ENODEV) - return dev_err_probe(dev, ret, + return dev_err_probe(ov13b->dev, ret, "failed to get avdd regulator\n"); } return 0; } -static int ov13b10_check_hwcfg(struct device *dev, struct ov13b10 *ov13b) +static int ov13b10_check_hwcfg(struct ov13b10 *ov13b) { struct v4l2_fwnode_endpoint bus_cfg = { .bus_type = V4L2_MBUS_CSI2_DPHY }; + struct device *dev = ov13b->dev; struct fwnode_handle *ep; struct fwnode_handle *fwnode = dev_fwnode(dev); unsigned int i, j; int ret; - u32 ext_clk; u8 dlane; if (!fwnode) @@ -1521,19 +1522,6 @@ static int ov13b10_check_hwcfg(struct device *dev, struct ov13b10 *ov13b) if (!ep) return -EPROBE_DEFER; - ret = fwnode_property_read_u32(dev_fwnode(dev), "clock-frequency", - &ext_clk); - if (ret) { - dev_err(dev, "can't get clock frequency"); - return ret; - } - - if (ext_clk != OV13B10_EXT_CLK) { - dev_err(dev, "external clock %d is not supported", - ext_clk); - return -EINVAL; - } - ret = v4l2_fwnode_endpoint_alloc_parse(ep, &bus_cfg); fwnode_handle_put(ep); if (ret) @@ -1602,32 +1590,34 @@ static int ov13b10_probe(struct i2c_client *client) if (!ov13b) return -ENOMEM; + ov13b->dev = &client->dev; + /* Check HW config */ - ret = ov13b10_check_hwcfg(&client->dev, ov13b); + ret = ov13b10_check_hwcfg(ov13b); if (ret) { - dev_err(&client->dev, "failed to check hwcfg: %d", ret); + dev_err(ov13b->dev, "failed to check hwcfg: %d", ret); return ret; } /* Initialize subdev */ v4l2_i2c_subdev_init(&ov13b->sd, client, &ov13b10_subdev_ops); - ret = ov13b10_get_pm_resources(&client->dev); + ret = ov13b10_get_pm_resources(ov13b); if (ret) return ret; - full_power = acpi_dev_state_d0(&client->dev); + full_power = acpi_dev_state_d0(ov13b->dev); if (full_power) { - ret = ov13b10_power_on(&client->dev); + ret = ov13b10_power_on(ov13b->dev); if (ret) { - dev_err(&client->dev, "failed to power on\n"); + dev_err(ov13b->dev, "failed to power on\n"); return ret; } /* Check module identity */ ret = ov13b10_identify_module(ov13b); if (ret) { - dev_err(&client->dev, "failed to find sensor: %d\n", ret); + dev_err(ov13b->dev, "failed to find sensor: %d\n", ret); goto error_power_off; } } @@ -1646,7 +1636,7 @@ static int ov13b10_probe(struct i2c_client *client) ov13b->pad.flags = MEDIA_PAD_FL_SOURCE; ret = media_entity_pads_init(&ov13b->sd.entity, 1, &ov13b->pad); if (ret) { - dev_err(&client->dev, "%s failed:%d\n", __func__, ret); + dev_err(ov13b->dev, "%s failed:%d\n", __func__, ret); goto error_handler_free; } @@ -1657,9 +1647,9 @@ static int ov13b10_probe(struct i2c_client *client) */ /* Set the device's state to active if it's in D0 state. */ if (full_power) - pm_runtime_set_active(&client->dev); - pm_runtime_enable(&client->dev); - pm_runtime_idle(&client->dev); + pm_runtime_set_active(ov13b->dev); + pm_runtime_enable(ov13b->dev); + pm_runtime_idle(ov13b->dev); ret = v4l2_async_register_subdev_sensor(&ov13b->sd); if (ret < 0) @@ -1668,17 +1658,17 @@ static int ov13b10_probe(struct i2c_client *client) return 0; error_media_entity_runtime_pm: - pm_runtime_disable(&client->dev); + pm_runtime_disable(ov13b->dev); if (full_power) - pm_runtime_set_suspended(&client->dev); + pm_runtime_set_suspended(ov13b->dev); media_entity_cleanup(&ov13b->sd.entity); error_handler_free: ov13b10_free_controls(ov13b); - dev_err(&client->dev, "%s failed:%d\n", __func__, ret); + dev_err(ov13b->dev, "%s failed:%d\n", __func__, ret); error_power_off: - ov13b10_power_off(&client->dev); + ov13b10_power_off(ov13b->dev); return ret; } @@ -1692,8 +1682,8 @@ static void ov13b10_remove(struct i2c_client *client) media_entity_cleanup(&sd->entity); ov13b10_free_controls(ov13b); - pm_runtime_disable(&client->dev); - pm_runtime_set_suspended(&client->dev); + pm_runtime_disable(ov13b->dev); + pm_runtime_set_suspended(ov13b->dev); } static DEFINE_RUNTIME_DEV_PM_OPS(ov13b10_pm_ops, ov13b10_suspend, diff --git a/drivers/media/i2c/ov2659.c b/drivers/media/i2c/ov2659.c index 586b31ba076b..061401b020fc 100644 --- a/drivers/media/i2c/ov2659.c +++ b/drivers/media/i2c/ov2659.c @@ -1437,9 +1437,10 @@ static int ov2659_probe(struct i2c_client *client) ov2659->pdata = pdata; ov2659->client = client; - ov2659->clk = devm_clk_get(&client->dev, "xvclk"); + ov2659->clk = devm_v4l2_sensor_clk_get(&client->dev, "xvclk"); if (IS_ERR(ov2659->clk)) - return PTR_ERR(ov2659->clk); + return dev_err_probe(&client->dev, PTR_ERR(ov2659->clk), + "failed to get xvclk\n"); ov2659->xvclk_frequency = clk_get_rate(ov2659->clk); if (ov2659->xvclk_frequency < 6000000 || diff --git a/drivers/media/i2c/ov2680.c b/drivers/media/i2c/ov2680.c index 7237fb27ecd0..78e63bd1b35b 100644 --- a/drivers/media/i2c/ov2680.c +++ b/drivers/media/i2c/ov2680.c @@ -1079,7 +1079,6 @@ static int ov2680_parse_dt(struct ov2680_dev *sensor) struct device *dev = sensor->dev; struct fwnode_handle *ep_fwnode; struct gpio_desc *gpio; - unsigned int rate = 0; int i, ret; /* @@ -1114,38 +1113,14 @@ static int ov2680_parse_dt(struct ov2680_dev *sensor) sensor->pwdn_gpio = gpio; - sensor->xvclk = devm_clk_get_optional(dev, "xvclk"); + sensor->xvclk = devm_v4l2_sensor_clk_get(dev, "xvclk"); if (IS_ERR(sensor->xvclk)) { ret = dev_err_probe(dev, PTR_ERR(sensor->xvclk), "xvclk clock missing or invalid\n"); goto out_free_bus_cfg; } - /* - * We could have either a 24MHz or 19.2MHz clock rate from either DT or - * ACPI... but we also need to support the weird IPU3 case which will - * have an external clock AND a clock-frequency property. Check for the - * clock-frequency property and if found, set that rate if we managed - * to acquire a clock. This should cover the ACPI case. If the system - * uses devicetree then the configured rate should already be set, so - * we can just read it. - */ - ret = fwnode_property_read_u32(dev_fwnode(dev), "clock-frequency", - &rate); - if (ret && !sensor->xvclk) { - dev_err_probe(dev, ret, "invalid clock config\n"); - goto out_free_bus_cfg; - } - - if (!ret && sensor->xvclk) { - ret = clk_set_rate(sensor->xvclk, rate); - if (ret) { - dev_err_probe(dev, ret, "failed to set clock rate\n"); - goto out_free_bus_cfg; - } - } - - sensor->xvclk_freq = rate ?: clk_get_rate(sensor->xvclk); + sensor->xvclk_freq = clk_get_rate(sensor->xvclk); for (i = 0; i < ARRAY_SIZE(ov2680_xvclk_freqs); i++) { if (sensor->xvclk_freq == ov2680_xvclk_freqs[i]) diff --git a/drivers/media/i2c/ov2685.c b/drivers/media/i2c/ov2685.c index 9b8481b8dcd4..4911a4eea126 100644 --- a/drivers/media/i2c/ov2685.c +++ b/drivers/media/i2c/ov2685.c @@ -783,16 +783,12 @@ static int ov2685_probe(struct i2c_client *client) ov2685->client = client; ov2685->cur_mode = &supported_modes[0]; - ov2685->xvclk = devm_clk_get(dev, "xvclk"); - if (IS_ERR(ov2685->xvclk)) { - dev_err(dev, "Failed to get xvclk\n"); - return -EINVAL; - } - ret = clk_set_rate(ov2685->xvclk, OV2685_XVCLK_FREQ); - if (ret < 0) { - dev_err(dev, "Failed to set xvclk rate (24MHz)\n"); - return ret; - } + ov2685->xvclk = devm_v4l2_sensor_clk_get_legacy(dev, "xvclk", true, + OV2685_XVCLK_FREQ); + if (IS_ERR(ov2685->xvclk)) + return dev_err_probe(dev, PTR_ERR(ov2685->xvclk), + "Failed to get xvclk\n"); + if (clk_get_rate(ov2685->xvclk) != OV2685_XVCLK_FREQ) dev_warn(dev, "xvclk mismatched, modes are based on 24MHz\n"); diff --git a/drivers/media/i2c/ov2735.c b/drivers/media/i2c/ov2735.c new file mode 100644 index 000000000000..b96600204141 --- /dev/null +++ b/drivers/media/i2c/ov2735.c @@ -0,0 +1,1109 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * V4L2 Support for the OV2735 + * + * Copyright (C) 2025 Silicon Signals Pvt. Ltd. + * + * Based on Rockchip ov2735 Camera Driver + * Copyright (C) 2017 Fuzhou Rockchip Electronics Co., Ltd. + * + * Inspired from ov8858, imx219, imx283 camera drivers. + */ + +#include <linux/array_size.h> +#include <linux/bitops.h> +#include <linux/cleanup.h> +#include <linux/clk.h> +#include <linux/container_of.h> +#include <linux/delay.h> +#include <linux/device/devres.h> +#include <linux/err.h> +#include <linux/gpio/consumer.h> +#include <linux/i2c.h> +#include <linux/module.h> +#include <linux/mutex.h> +#include <linux/pm_runtime.h> +#include <linux/property.h> +#include <linux/regulator/consumer.h> +#include <linux/units.h> +#include <linux/types.h> +#include <linux/time.h> + +#include <media/v4l2-cci.h> +#include <media/v4l2-ctrls.h> +#include <media/v4l2-device.h> +#include <media/v4l2-fwnode.h> +#include <media/v4l2-mediabus.h> + +#define OV2735_XCLK_FREQ (24 * HZ_PER_MHZ) + +/* Add page number in CCI private bits [31:28] of the register address */ +#define OV2735_PAGE_REG8(p, x) (((p) << CCI_REG_PRIVATE_SHIFT) | CCI_REG8(x)) +#define OV2735_PAGE_REG16(p, x) (((p) << CCI_REG_PRIVATE_SHIFT) | CCI_REG16(x)) + +#define OV2735_REG_PAGE_SELECT CCI_REG8(0xfd) + +/* Page 0 */ +#define OV2735_REG_CHIPID OV2735_PAGE_REG16(0x00, 0x02) +#define OV2735_CHIPID 0x2735 + +#define OV2735_REG_SOFT_RESET OV2735_PAGE_REG8(0x00, 0x20) + +/* Clock Settings */ +#define OV2735_REG_PLL_CTRL OV2735_PAGE_REG8(0x00, 0x2f) +#define OV2735_PLL_CTRL_ENABLE 0x7f +#define OV2735_REG_PLL_OUTDIV OV2735_PAGE_REG8(0x00, 0x34) +#define OV2735_REG_CLK_MODE OV2735_PAGE_REG8(0x00, 0x30) +#define OV2735_REG_CLOCK_REG1 OV2735_PAGE_REG8(0x00, 0x33) +#define OV2735_REG_CLOCK_REG2 OV2735_PAGE_REG8(0x00, 0x35) + +/* Page 1 */ +#define OV2735_REG_STREAM_CTRL OV2735_PAGE_REG8(0x01, 0xa0) +#define OV2735_STREAM_CTRL_ON 0x01 +#define OV2735_STREAM_CTRL_OFF 0x00 + +#define OV2735_REG_UPDOWN_MIRROR OV2735_PAGE_REG8(0x01, 0x3f) +#define OV2735_REG_BINNING_DAC_CODE_MODE OV2735_PAGE_REG8(0x01, 0x30) +#define OV2735_REG_FRAME_LENGTH OV2735_PAGE_REG16(0x01, 0x0e) +#define OV2735_FRAME_LENGTH_MAX 0x0fff +#define OV2735_REG_FRAME_EXP_SEPERATE_EN OV2735_PAGE_REG8(0x01, 0x0d) +#define OV2735_FRAME_EXP_SEPERATE_EN 0x10 +#define OV2735_REG_FRAME_SYNC OV2735_PAGE_REG8(0x01, 0x01) + +#define OV2735_REG_HBLANK OV2735_PAGE_REG16(0x01, 0x09) + +#define OV2735_REG_HS_MIPI OV2735_PAGE_REG8(0x01, 0xb1) +#define OV2735_REG_MIPI_CTRL1 OV2735_PAGE_REG8(0x01, 0x92) +#define OV2735_REG_MIPI_CTRL2 OV2735_PAGE_REG8(0x01, 0x94) +#define OV2735_REG_MIPI_CTRL3 OV2735_PAGE_REG8(0x01, 0xa1) +#define OV2735_REG_MIPI_CTRL4 OV2735_PAGE_REG8(0x01, 0xb2) +#define OV2735_REG_MIPI_CTRL5 OV2735_PAGE_REG8(0x01, 0xb3) +#define OV2735_REG_MIPI_CTRL6 OV2735_PAGE_REG8(0x01, 0xb4) +#define OV2735_REG_MIPI_CTRL7 OV2735_PAGE_REG8(0x01, 0xb5) +#define OV2735_REG_HIGH_SPEED OV2735_PAGE_REG8(0x01, 0x9d) +#define OV2735_REG_PREPARE OV2735_PAGE_REG8(0x01, 0x95) +#define OV2735_REG_R_HS_ZERO OV2735_PAGE_REG8(0x01, 0x96) +#define OV2735_REG_TRAIL OV2735_PAGE_REG8(0x01, 0x98) +#define OV2735_REG_R_CLK_ZERO OV2735_PAGE_REG8(0x01, 0x9c) +#define OV2735_REG_MIPI_COLOMN_NUMBER OV2735_PAGE_REG16(0x01, 0x8e) +#define OV2735_REG_MIPI_LINE_NUMBER OV2735_PAGE_REG16(0x01, 0x90) + +/* Timing control registers */ +#define OV2735_REG_TIMING_CTRL2 OV2735_PAGE_REG8(0x01, 0x1a) +#define OV2735_REG_TIMING_CTRL3 OV2735_PAGE_REG8(0x01, 0x1c) +#define OV2735_REG_TIMING_CTRL1 OV2735_PAGE_REG8(0x01, 0x16) +#define OV2735_REG_RST_NUM OV2735_PAGE_REG16(0x01, 0x10) +#define OV2735_REG_RST_NUM2 OV2735_PAGE_REG16(0x01, 0x32) +#define OV2735_REG_BOOST_EN OV2735_PAGE_REG8(0x01, 0xd0) +#define OV2735_REG_B2_NUM OV2735_PAGE_REG16(0x01, 0xd1) +#define OV2735_REG_B4_NUM OV2735_PAGE_REG16(0x01, 0xd3) +#define OV2735_REG_PIXEL_CYCLE_P0 OV2735_PAGE_REG8(0x01, 0x50) +#define OV2735_REG_PIXEL_CYCLE_P1 OV2735_PAGE_REG8(0x01, 0x51) +#define OV2735_REG_PIXEL_CYCLE_P2 OV2735_PAGE_REG8(0x01, 0x52) +#define OV2735_REG_PIXEL_CYCLE_P3 OV2735_PAGE_REG8(0x01, 0x53) +#define OV2735_REG_PIXEL_CYCLE_P5 OV2735_PAGE_REG8(0x01, 0x55) +#define OV2735_REG_PIXEL_CYCLE_P7 OV2735_PAGE_REG16(0x01, 0x57) +#define OV2735_REG_PIXEL_CYCLE_P9 OV2735_PAGE_REG8(0x01, 0x5a) +#define OV2735_REG_PIXEL_CYCLE_P10 OV2735_PAGE_REG8(0x01, 0x5b) +#define OV2735_REG_PIXEL_CYCLE_P12 OV2735_PAGE_REG8(0x01, 0x5d) +#define OV2735_REG_PIXEL_CYCLE_P18 OV2735_PAGE_REG8(0x01, 0x64) +#define OV2735_REG_PIXEL_CYCLE_P20 OV2735_PAGE_REG8(0x01, 0x66) +#define OV2735_REG_PIXEL_CYCLE_P22 OV2735_PAGE_REG8(0x01, 0x68) +#define OV2735_REG_PIXEL_CYCLE_P33 OV2735_PAGE_REG16(0x01, 0x74) +#define OV2735_REG_PIXEL_CYCLE_P34 OV2735_PAGE_REG8(0x01, 0x76) +#define OV2735_REG_PIXEL_CYCLE_P35_P36 OV2735_PAGE_REG8(0x01, 0x77) +#define OV2735_REG_PIXEL_CYCLE_P37_P38 OV2735_PAGE_REG8(0x01, 0x78) +#define OV2735_REG_PIXEL_CYCLE_P31 OV2735_PAGE_REG8(0x01, 0x72) +#define OV2735_REG_PIXEL_CYCLE_P32 OV2735_PAGE_REG8(0x01, 0x73) +#define OV2735_REG_PIXEL_CYCLE_P44 OV2735_PAGE_REG8(0x01, 0x7d) +#define OV2735_REG_PIXEL_CYCLE_P45 OV2735_PAGE_REG8(0x01, 0x7e) +#define OV2735_REG_PIXEL_BIAS_CTRL_RH_RL OV2735_PAGE_REG8(0x01, 0x8a) +#define OV2735_REG_PIXEL_BIAS_CTRL_SH_SL OV2735_PAGE_REG8(0x01, 0x8b) + +/* Analog Control registers */ +#define OV2735_REG_ICOMP OV2735_PAGE_REG8(0x01, 0x19) +#define OV2735_REG_PCP_RST_SEL OV2735_PAGE_REG8(0x01, 0x21) +#define OV2735_REG_VNCP OV2735_PAGE_REG8(0x01, 0x20) +#define OV2735_REG_ANALOG_CTRL3 OV2735_PAGE_REG8(0x01, 0x25) +#define OV2735_REG_ANALOG_CTRL4 OV2735_PAGE_REG8(0x01, 0x26) +#define OV2735_REG_ANALOG_CTRL5 OV2735_PAGE_REG8(0x01, 0x29) +#define OV2735_REG_ANALOG_CTRL6 OV2735_PAGE_REG8(0x01, 0x2a) +#define OV2735_REG_ANALOG_CTRL8 OV2735_PAGE_REG8(0x01, 0x2c) + +/* BLC registers */ +#define OV2735_REG_BLC_GAIN_BLUE OV2735_PAGE_REG8(0x01, 0x86) +#define OV2735_REG_BLC_GAIN_RED OV2735_PAGE_REG8(0x01, 0x87) +#define OV2735_REG_BLC_GAIN_GR OV2735_PAGE_REG8(0x01, 0x88) +#define OV2735_REG_BLC_GAIN_GB OV2735_PAGE_REG8(0x01, 0x89) +#define OV2735_REG_GB_SUBOFFSET OV2735_PAGE_REG8(0x01, 0xf0) +#define OV2735_REG_BLUE_SUBOFFSET OV2735_PAGE_REG8(0x01, 0xf1) +#define OV2735_REG_RED_SUBOFFSET OV2735_PAGE_REG8(0x01, 0xf2) +#define OV2735_REG_GR_SUBOFFSET OV2735_PAGE_REG8(0x01, 0xf3) +#define OV2735_REG_BLC_BPC_TH_P OV2735_PAGE_REG8(0x01, 0xfc) +#define OV2735_REG_BLC_BPC_TH_N OV2735_PAGE_REG8(0x01, 0xfe) +#define OV2735_REG_ABL OV2735_PAGE_REG8(0x01, 0xfb) + +#define OV2735_REG_TEST_PATTERN OV2735_PAGE_REG8(0x01, 0xb2) +#define OV2735_TEST_PATTERN_ENABLE 0x01 +#define OV2735_TEST_PATTERN_DISABLE 0xfe + +#define OV2735_REG_LONG_EXPOSURE OV2735_PAGE_REG16(0x01, 0x03) +#define OV2735_EXPOSURE_MIN 4 +#define OV2735_EXPOSURE_STEP 1 +#define OV2735_EXPOSURE_MARGIN 4 + +#define OV2735_REG_ANALOG_GAIN OV2735_PAGE_REG8(0x01, 0x24) +#define OV2735_ANALOG_GAIN_MIN 0x10 +#define OV2735_ANALOG_GAIN_MAX 0xff +#define OV2735_ANALOG_GAIN_STEP 1 +#define OV2735_ANALOG_GAIN_DEFAULT 0x10 + +/* Page 2 */ +#define OV2735_REG_V_START OV2735_PAGE_REG16(0x02, 0xa0) +#define OV2735_REG_V_SIZE OV2735_PAGE_REG16(0x02, 0xa2) +#define OV2735_REG_H_START OV2735_PAGE_REG16(0x02, 0xa4) +#define OV2735_REG_H_SIZE OV2735_PAGE_REG16(0x02, 0xa6) + +#define OV2735_LINK_FREQ_420MHZ (420 * HZ_PER_MHZ) +#define OV2735_PIXEL_RATE (168 * HZ_PER_MHZ) + +/* OV2735 native and active pixel array size */ +static const struct v4l2_rect ov2735_native_area = { + .top = 0, + .left = 0, + .width = 1936, + .height = 1096, +}; + +static const struct v4l2_rect ov2735_active_area = { + .top = 8, + .left = 8, + .width = 1920, + .height = 1080, +}; + +static const char * const ov2735_supply_name[] = { + "avdd", /* Analog power */ + "dovdd", /* Digital I/O power */ + "dvdd", /* Digital core power */ +}; + +/* PLL_OUT = [PLL_IN * (pll_nc +3)] / [(pll_mc + 1) * (pll_outdiv + 1)] */ +struct ov2735_pll_parameters { + u8 pll_nc; + u8 pll_mc; + u8 pll_outdiv; +}; + +struct ov2735 { + struct device *dev; + struct regmap *cci; + struct v4l2_subdev sd; + struct media_pad pad; + struct clk *xclk; + struct gpio_desc *reset_gpio; + struct gpio_desc *enable_gpio; + struct regulator_bulk_data supplies[ARRAY_SIZE(ov2735_supply_name)]; + + /* V4L2 Controls */ + struct v4l2_ctrl_handler handler; + struct v4l2_ctrl *link_freq; + struct v4l2_ctrl *pixel_rate; + struct v4l2_ctrl *hblank; + struct v4l2_ctrl *vblank; + struct v4l2_ctrl *gain; + struct v4l2_ctrl *exposure; + struct v4l2_ctrl *test_pattern; + + u32 link_freq_index; + + u8 current_page; + struct mutex page_lock; +}; + +struct ov2735_mode { + u32 width; + u32 height; + u32 hts_def; + u32 vts_def; + u32 exp_def; + struct v4l2_rect crop; +}; + +static const struct cci_reg_sequence ov2735_common_regs[] = { + { OV2735_REG_CLK_MODE, 0x15 }, + { OV2735_REG_CLOCK_REG1, 0x01 }, + { OV2735_REG_CLOCK_REG2, 0x20 }, + { OV2735_REG_BINNING_DAC_CODE_MODE, 0x00 }, + { OV2735_REG_ABL, 0x73 }, + { OV2735_REG_FRAME_SYNC, 0x01 }, + + /* Timing ctrl */ + { OV2735_REG_TIMING_CTRL2, 0x6b }, + { OV2735_REG_TIMING_CTRL3, 0xea }, + { OV2735_REG_TIMING_CTRL1, 0x0c }, + { OV2735_REG_RST_NUM, 0x0063 }, + { OV2735_REG_RST_NUM2, 0x006f }, + { OV2735_REG_BOOST_EN, 0x02 }, + { OV2735_REG_B2_NUM, 0x0120 }, + { OV2735_REG_B4_NUM, 0x042a }, + { OV2735_REG_PIXEL_CYCLE_P0, 0x00 }, + { OV2735_REG_PIXEL_CYCLE_P1, 0x2c }, + { OV2735_REG_PIXEL_CYCLE_P2, 0x29 }, + { OV2735_REG_PIXEL_CYCLE_P3, 0x00 }, + { OV2735_REG_PIXEL_CYCLE_P5, 0x44 }, + { OV2735_REG_PIXEL_CYCLE_P7, 0x0029 }, + { OV2735_REG_PIXEL_CYCLE_P9, 0x00 }, + { OV2735_REG_PIXEL_CYCLE_P10, 0x00 }, + { OV2735_REG_PIXEL_CYCLE_P12, 0x00 }, + { OV2735_REG_PIXEL_CYCLE_P18, 0x2f }, + { OV2735_REG_PIXEL_CYCLE_P20, 0x62 }, + { OV2735_REG_PIXEL_CYCLE_P22, 0x5b }, + { OV2735_REG_PIXEL_CYCLE_P33, 0x0046 }, + { OV2735_REG_PIXEL_CYCLE_P34, 0x36 }, + { OV2735_REG_PIXEL_CYCLE_P35_P36, 0x4f }, + { OV2735_REG_PIXEL_CYCLE_P37_P38, 0xef }, + { OV2735_REG_PIXEL_CYCLE_P31, 0xcf }, + { OV2735_REG_PIXEL_CYCLE_P32, 0x36 }, + { OV2735_REG_PIXEL_CYCLE_P44, 0x0d }, + { OV2735_REG_PIXEL_CYCLE_P45, 0x0d }, + { OV2735_REG_PIXEL_BIAS_CTRL_RH_RL, 0x77 }, + { OV2735_REG_PIXEL_BIAS_CTRL_SH_SL, 0x77 }, + + /* Analog ctrl */ + { OV2735_REG_ANALOG_CTRL4, 0x5a }, + { OV2735_REG_ANALOG_CTRL5, 0x01 }, + { OV2735_REG_ANALOG_CTRL6, 0xd2 }, + { OV2735_REG_ANALOG_CTRL8, 0x40 }, + { OV2735_REG_PCP_RST_SEL, 0x00 }, + { OV2735_REG_ICOMP, 0xc3 }, + + { OV2735_REG_HS_MIPI, 0x83 }, + { OV2735_REG_MIPI_CTRL5, 0x0b }, + { OV2735_REG_MIPI_CTRL6, 0x14 }, + { OV2735_REG_HIGH_SPEED, 0x40 }, + { OV2735_REG_MIPI_CTRL3, 0x05 }, + { OV2735_REG_MIPI_CTRL2, 0x44 }, + { OV2735_REG_PREPARE, 0x33 }, + { OV2735_REG_R_HS_ZERO, 0x1f }, + { OV2735_REG_TRAIL, 0x45 }, + { OV2735_REG_R_CLK_ZERO, 0x10 }, + { OV2735_REG_MIPI_CTRL7, 0x70 }, + { OV2735_REG_ANALOG_CTRL3, 0xe0 }, + { OV2735_REG_VNCP, 0x7b }, + + /* BLC */ + { OV2735_REG_BLC_GAIN_BLUE, 0x77 }, + { OV2735_REG_BLC_GAIN_GB, 0x77 }, + { OV2735_REG_BLC_GAIN_RED, 0x74 }, + { OV2735_REG_BLC_GAIN_GR, 0x74 }, + { OV2735_REG_BLC_BPC_TH_P, 0xe0 }, + { OV2735_REG_BLC_BPC_TH_N, 0xe0 }, + { OV2735_REG_GB_SUBOFFSET, 0x40 }, + { OV2735_REG_BLUE_SUBOFFSET, 0x40 }, + { OV2735_REG_RED_SUBOFFSET, 0x40 }, + { OV2735_REG_GR_SUBOFFSET, 0x40 }, +}; + +static const struct ov2735_mode supported_modes[] = { + { + .width = 1920, + .height = 1080, + .exp_def = 399, + .hts_def = 2200, + .vts_def = 2545, + .crop = { + .top = 8, + .left = 8, + .width = 1920, + .height = 1080, + }, + }, +}; + +static const s64 link_freq_menu_items[] = { + OV2735_LINK_FREQ_420MHZ, +}; + +static const struct ov2735_pll_parameters pll_configs[] = { + /* For 420MHz pll_configs */ + { + .pll_nc = 4, + .pll_mc = 0, + .pll_outdiv = 1, + }, +}; + +static const char * const ov2735_test_pattern_menu[] = { + "Disabled", + "Vertical Color", +}; + +static int ov2735_page_access(struct ov2735 *ov2735, u32 reg, int *err) +{ + u8 page = reg >> CCI_REG_PRIVATE_SHIFT; + int ret = 0; + + if (err && *err) + return *err; + + guard(mutex)(&ov2735->page_lock); + + /* Perform page access before read/write */ + if (ov2735->current_page == page) + return ret; + + ret = cci_write(ov2735->cci, OV2735_REG_PAGE_SELECT, page, err); + if (!ret) + ov2735->current_page = page; + + return ret; +} + +static int ov2735_read(struct ov2735 *ov2735, u32 reg, u64 *val, int *err) +{ + u32 addr = reg & ~CCI_REG_PRIVATE_MASK; + int ret; + + ret = ov2735_page_access(ov2735, reg, err); + if (ret) + return ret; + + return cci_read(ov2735->cci, addr, val, err); +} + +static int ov2735_write(struct ov2735 *ov2735, u32 reg, u64 val, int *err) +{ + u32 addr = reg & ~CCI_REG_PRIVATE_MASK; + int ret; + + ret = ov2735_page_access(ov2735, reg, err); + if (ret) + return ret; + + return cci_write(ov2735->cci, addr, val, err); +} + +static int ov2735_multi_reg_write(struct ov2735 *ov2735, + const struct cci_reg_sequence *regs, + unsigned int num_regs, int *err) +{ + unsigned int i; + int ret; + + for (i = 0; i < num_regs; i++) { + ret = ov2735_write(ov2735, regs[i].reg, regs[i].val, err); + if (ret) + return ret; + } + + return 0; +} + +static inline struct ov2735 *to_ov2735(struct v4l2_subdev *_sd) +{ + return container_of_const(_sd, struct ov2735, sd); +} + +static int ov2735_enable_test_pattern(struct ov2735 *ov2735, u32 pattern) +{ + int ret; + u64 val; + + ret = ov2735_read(ov2735, OV2735_REG_TEST_PATTERN, &val, NULL); + if (ret) + return ret; + + switch (pattern) { + case 0: + val &= ~OV2735_TEST_PATTERN_ENABLE; + break; + case 1: + val |= OV2735_TEST_PATTERN_ENABLE; + break; + } + + return ov2735_write(ov2735, OV2735_REG_TEST_PATTERN, val, NULL); +} + +static int ov2735_set_ctrl(struct v4l2_ctrl *ctrl) +{ + struct ov2735 *ov2735 = + container_of_const(ctrl->handler, struct ov2735, handler); + struct v4l2_mbus_framefmt *fmt; + struct v4l2_subdev_state *state; + u64 vts; + int ret = 0; + + state = v4l2_subdev_get_locked_active_state(&ov2735->sd); + fmt = v4l2_subdev_state_get_format(state, 0); + + if (ctrl->id == V4L2_CID_VBLANK) { + /* Honour the VBLANK limits when setting exposure */ + s64 max = fmt->height + ctrl->val - OV2735_EXPOSURE_MARGIN; + + ret = __v4l2_ctrl_modify_range(ov2735->exposure, + ov2735->exposure->minimum, max, + ov2735->exposure->step, + ov2735->exposure->default_value); + if (ret) + return ret; + } + + if (pm_runtime_get_if_in_use(ov2735->dev) == 0) + return 0; + + switch (ctrl->id) { + case V4L2_CID_EXPOSURE: + ov2735_write(ov2735, OV2735_REG_LONG_EXPOSURE, ctrl->val, &ret); + break; + case V4L2_CID_ANALOGUE_GAIN: + ov2735_write(ov2735, OV2735_REG_ANALOG_GAIN, ctrl->val, &ret); + break; + case V4L2_CID_HBLANK: + ov2735_write(ov2735, OV2735_REG_HBLANK, ctrl->val, &ret); + break; + case V4L2_CID_VBLANK: + vts = ctrl->val + fmt->height; + ov2735_write(ov2735, OV2735_REG_FRAME_EXP_SEPERATE_EN, + OV2735_FRAME_EXP_SEPERATE_EN, &ret); + ov2735_write(ov2735, OV2735_REG_FRAME_LENGTH, vts, &ret); + break; + case V4L2_CID_TEST_PATTERN: + ret = ov2735_enable_test_pattern(ov2735, ctrl->val); + break; + default: + ret = -EINVAL; + break; + } + ov2735_write(ov2735, OV2735_REG_FRAME_SYNC, 0x01, &ret); + + pm_runtime_put(ov2735->dev); + + return ret; +} + +static const struct v4l2_ctrl_ops ov2735_ctrl_ops = { + .s_ctrl = ov2735_set_ctrl, +}; + +static int ov2735_init_controls(struct ov2735 *ov2735) +{ + struct v4l2_ctrl_handler *ctrl_hdlr; + struct v4l2_fwnode_device_properties props; + const struct ov2735_mode *mode = &supported_modes[0]; + u64 hblank_def, vblank_def, exp_max; + int ret; + + ctrl_hdlr = &ov2735->handler; + v4l2_ctrl_handler_init(ctrl_hdlr, 9); + + ov2735->pixel_rate = v4l2_ctrl_new_std(ctrl_hdlr, &ov2735_ctrl_ops, + V4L2_CID_PIXEL_RATE, 0, + OV2735_PIXEL_RATE, 1, + OV2735_PIXEL_RATE); + + ov2735->link_freq = v4l2_ctrl_new_int_menu(ctrl_hdlr, &ov2735_ctrl_ops, + V4L2_CID_LINK_FREQ, + ov2735->link_freq_index, + 0, link_freq_menu_items); + if (ov2735->link_freq) + ov2735->link_freq->flags |= V4L2_CTRL_FLAG_READ_ONLY; + + hblank_def = mode->hts_def - mode->width; + ov2735->hblank = v4l2_ctrl_new_std(ctrl_hdlr, &ov2735_ctrl_ops, + V4L2_CID_HBLANK, hblank_def, + hblank_def, 1, hblank_def); + + vblank_def = mode->vts_def - mode->height; + ov2735->vblank = v4l2_ctrl_new_std(ctrl_hdlr, &ov2735_ctrl_ops, + V4L2_CID_VBLANK, vblank_def, + OV2735_FRAME_LENGTH_MAX - mode->height, + 1, vblank_def); + + exp_max = mode->vts_def - OV2735_EXPOSURE_MARGIN; + ov2735->exposure = + v4l2_ctrl_new_std(ctrl_hdlr, &ov2735_ctrl_ops, + V4L2_CID_EXPOSURE, + OV2735_EXPOSURE_MIN, exp_max, + OV2735_EXPOSURE_STEP, mode->exp_def); + + ov2735->gain = + v4l2_ctrl_new_std(ctrl_hdlr, &ov2735_ctrl_ops, + V4L2_CID_ANALOGUE_GAIN, OV2735_ANALOG_GAIN_MIN, + OV2735_ANALOG_GAIN_MAX, OV2735_ANALOG_GAIN_STEP, + OV2735_ANALOG_GAIN_DEFAULT); + + ov2735->test_pattern = + v4l2_ctrl_new_std_menu_items(ctrl_hdlr, &ov2735_ctrl_ops, + V4L2_CID_TEST_PATTERN, + ARRAY_SIZE(ov2735_test_pattern_menu) - 1, + 0, 0, ov2735_test_pattern_menu); + + if (ctrl_hdlr->error) { + ret = ctrl_hdlr->error; + dev_err(ov2735->dev, "control init failed (%d)\n", ret); + goto err_handler_free; + } + + ret = v4l2_fwnode_device_parse(ov2735->dev, &props); + if (ret) + goto err_handler_free; + + ret = v4l2_ctrl_new_fwnode_properties(ctrl_hdlr, + &ov2735_ctrl_ops, &props); + if (ret) + goto err_handler_free; + + ov2735->sd.ctrl_handler = ctrl_hdlr; + + return 0; + +err_handler_free: + v4l2_ctrl_handler_free(ctrl_hdlr); + + return ret; +} + +static int ov2735_set_pll_ctrl(struct ov2735 *ov2735) +{ + const struct ov2735_pll_parameters *pll_parameters; + u8 pll_ctrl; + u8 pll_outdiv; + int ret = 0; + + pll_parameters = &pll_configs[ov2735->link_freq_index]; + + /* BIT[7]: pll_clk_sel, BIT[6:2]: pll_nc, BIT[1:0]: pll_mc */ + pll_ctrl = ((pll_parameters->pll_nc << 2) | (pll_parameters->pll_mc << 0)) & + OV2735_PLL_CTRL_ENABLE; + + pll_outdiv = pll_parameters->pll_outdiv; + + ov2735_write(ov2735, OV2735_REG_PLL_CTRL, pll_ctrl, &ret); + ov2735_write(ov2735, OV2735_REG_PLL_OUTDIV, pll_outdiv, &ret); + + return ret; +} + +static int ov2735_set_framefmt(struct ov2735 *ov2735, + struct v4l2_subdev_state *state) +{ + const struct v4l2_mbus_framefmt *format; + const struct v4l2_rect *crop; + int ret = 0; + + format = v4l2_subdev_state_get_format(state, 0); + crop = v4l2_subdev_state_get_crop(state, 0); + + ov2735_write(ov2735, OV2735_REG_V_START, crop->top, &ret); + ov2735_write(ov2735, OV2735_REG_V_SIZE, format->height, &ret); + ov2735_write(ov2735, OV2735_REG_MIPI_LINE_NUMBER, format->height, &ret); + ov2735_write(ov2735, OV2735_REG_H_START, crop->left, &ret); + /* OV2735_REG_H_SIZE: Image half horizontal size */ + ov2735_write(ov2735, OV2735_REG_H_SIZE, (format->width / 2), &ret); + ov2735_write(ov2735, OV2735_REG_MIPI_COLOMN_NUMBER, format->width, &ret); + + return ret; +} + +static int ov2735_enable_streams(struct v4l2_subdev *sd, + struct v4l2_subdev_state *state, u32 pad, + u64 streams_mask) +{ + struct ov2735 *ov2735 = to_ov2735(sd); + int ret; + + ret = pm_runtime_resume_and_get(ov2735->dev); + if (ret < 0) + return ret; + + /* Apply pll settings */ + ret = ov2735_set_pll_ctrl(ov2735); + if (ret) { + dev_err(ov2735->dev, "failed to set frame format: %d\n", ret); + goto err_rpm_put; + } + + ret = ov2735_multi_reg_write(ov2735, ov2735_common_regs, + ARRAY_SIZE(ov2735_common_regs), NULL); + if (ret) { + dev_err(ov2735->dev, "failed to write common registers\n"); + goto err_rpm_put; + } + + /* Apply format settings */ + ret = ov2735_set_framefmt(ov2735, state); + if (ret) { + dev_err(ov2735->dev, "failed to set frame format: %d\n", ret); + goto err_rpm_put; + } + + /* Apply customized values from user */ + ret = __v4l2_ctrl_handler_setup(ov2735->sd.ctrl_handler); + if (ret) + goto err_rpm_put; + + ret = ov2735_write(ov2735, OV2735_REG_STREAM_CTRL, + OV2735_STREAM_CTRL_ON, NULL); + if (ret) + goto err_rpm_put; + + return 0; + +err_rpm_put: + pm_runtime_put(ov2735->dev); + return ret; +} + +static int ov2735_disable_streams(struct v4l2_subdev *sd, + struct v4l2_subdev_state *state, u32 pad, + u64 streams_mask) +{ + struct ov2735 *ov2735 = to_ov2735(sd); + int ret; + + ret = ov2735_write(ov2735, OV2735_REG_STREAM_CTRL, + OV2735_STREAM_CTRL_OFF, NULL); + if (ret) + dev_err(ov2735->dev, "%s failed to set stream\n", __func__); + + pm_runtime_put(ov2735->dev); + + return ret; +} + +static int ov2735_get_selection(struct v4l2_subdev *sd, + struct v4l2_subdev_state *sd_state, + struct v4l2_subdev_selection *sel) +{ + switch (sel->target) { + case V4L2_SEL_TGT_CROP: + sel->r = *v4l2_subdev_state_get_crop(sd_state, 0); + return 0; + case V4L2_SEL_TGT_NATIVE_SIZE: + sel->r = ov2735_native_area; + return 0; + case V4L2_SEL_TGT_CROP_DEFAULT: + case V4L2_SEL_TGT_CROP_BOUNDS: + sel->r = ov2735_active_area; + return 0; + default: + return -EINVAL; + } +} + +static int ov2735_enum_mbus_code(struct v4l2_subdev *sd, + struct v4l2_subdev_state *sd_state, + struct v4l2_subdev_mbus_code_enum *code) +{ + if (code->index) + return -EINVAL; + + code->code = MEDIA_BUS_FMT_SGRBG10_1X10; + + return 0; +} + +static int ov2735_enum_frame_size(struct v4l2_subdev *sd, + struct v4l2_subdev_state *sd_state, + struct v4l2_subdev_frame_size_enum *fse) +{ + if (fse->index >= ARRAY_SIZE(supported_modes)) + return -EINVAL; + + if (fse->code != MEDIA_BUS_FMT_SGRBG10_1X10) + return -EINVAL; + + fse->min_width = supported_modes[fse->index].width; + fse->max_width = fse->min_width; + fse->min_height = supported_modes[fse->index].height; + fse->max_height = fse->min_height; + + return 0; +} + +static int ov2735_set_framing_limits(struct ov2735 *ov2735, + const struct ov2735_mode *mode) +{ + u32 hblank, vblank_def; + int ret; + + hblank = mode->hts_def - mode->width; + ret = __v4l2_ctrl_modify_range(ov2735->hblank, hblank, hblank, 1, + hblank); + if (ret) + return ret; + + vblank_def = mode->vts_def - mode->height; + return __v4l2_ctrl_modify_range(ov2735->vblank, vblank_def, + OV2735_FRAME_LENGTH_MAX - mode->height, + 1, vblank_def); +} + +static int ov2735_set_pad_format(struct v4l2_subdev *sd, + struct v4l2_subdev_state *sd_state, + struct v4l2_subdev_format *fmt) +{ + struct v4l2_mbus_framefmt *format; + const struct ov2735_mode *mode; + struct v4l2_rect *crop; + struct ov2735 *ov2735 = to_ov2735(sd); + int ret; + + format = v4l2_subdev_state_get_format(sd_state, 0); + + mode = v4l2_find_nearest_size(supported_modes, + ARRAY_SIZE(supported_modes), + width, height, + fmt->format.width, fmt->format.height); + + fmt->format.width = mode->width; + fmt->format.height = mode->height; + fmt->format.field = V4L2_FIELD_NONE; + fmt->format.colorspace = V4L2_COLORSPACE_RAW; + fmt->format.quantization = V4L2_QUANTIZATION_FULL_RANGE; + fmt->format.xfer_func = V4L2_XFER_FUNC_NONE; + + if (fmt->which == V4L2_SUBDEV_FORMAT_ACTIVE) { + ret = ov2735_set_framing_limits(ov2735, mode); + if (ret) + return ret; + } + + *format = fmt->format; + + /* Initialize crop rectangle */ + crop = v4l2_subdev_state_get_crop(sd_state, 0); + *crop = mode->crop; + + return 0; +} + +static int ov2735_init_state(struct v4l2_subdev *sd, + struct v4l2_subdev_state *state) +{ + struct v4l2_subdev_format fmt = { + .which = V4L2_SUBDEV_FORMAT_TRY, + .format = { + .code = MEDIA_BUS_FMT_SGRBG10_1X10, + .width = supported_modes[0].width, + .height = supported_modes[0].height, + }, + }; + + ov2735_set_pad_format(sd, state, &fmt); + + return 0; +} + +static const struct v4l2_subdev_video_ops ov2735_video_ops = { + .s_stream = v4l2_subdev_s_stream_helper, +}; + +static const struct v4l2_subdev_pad_ops ov2735_pad_ops = { + .enum_mbus_code = ov2735_enum_mbus_code, + .get_fmt = v4l2_subdev_get_fmt, + .set_fmt = ov2735_set_pad_format, + .get_selection = ov2735_get_selection, + .enum_frame_size = ov2735_enum_frame_size, + .enable_streams = ov2735_enable_streams, + .disable_streams = ov2735_disable_streams, +}; + +static const struct v4l2_subdev_ops ov2735_subdev_ops = { + .video = &ov2735_video_ops, + .pad = &ov2735_pad_ops, +}; + +static const struct v4l2_subdev_internal_ops ov2735_internal_ops = { + .init_state = ov2735_init_state, +}; + +static int ov2735_power_on(struct device *dev) +{ + struct v4l2_subdev *sd = dev_get_drvdata(dev); + struct ov2735 *ov2735 = to_ov2735(sd); + int ret; + + ret = regulator_bulk_enable(ARRAY_SIZE(ov2735_supply_name), + ov2735->supplies); + if (ret) { + dev_err(ov2735->dev, "failed to enable regulators\n"); + return ret; + } + + gpiod_set_value_cansleep(ov2735->enable_gpio, 1); + /* T4: delay from PWDN pulling low to RSTB pulling high */ + fsleep(4 * USEC_PER_MSEC); + + ret = clk_prepare_enable(ov2735->xclk); + if (ret) { + dev_err(ov2735->dev, "failed to enable clock\n"); + goto err_regulator_off; + } + + gpiod_set_value_cansleep(ov2735->reset_gpio, 0); + /* T5: delay from RSTB pulling high to first I2C command */ + fsleep(5 * USEC_PER_MSEC); + + return 0; + +err_regulator_off: + regulator_bulk_disable(ARRAY_SIZE(ov2735_supply_name), ov2735->supplies); + return ret; +} + +static int ov2735_power_off(struct device *dev) +{ + struct v4l2_subdev *sd = dev_get_drvdata(dev); + struct ov2735 *ov2735 = to_ov2735(sd); + + gpiod_set_value_cansleep(ov2735->enable_gpio, 0); + clk_disable_unprepare(ov2735->xclk); + gpiod_set_value_cansleep(ov2735->reset_gpio, 1); + regulator_bulk_disable(ARRAY_SIZE(ov2735_supply_name), ov2735->supplies); + + return 0; +} + +static int ov2735_get_regulators(struct ov2735 *ov2735) +{ + unsigned int i; + + for (i = 0; i < ARRAY_SIZE(ov2735_supply_name); i++) + ov2735->supplies[i].supply = ov2735_supply_name[i]; + + return devm_regulator_bulk_get(ov2735->dev, + ARRAY_SIZE(ov2735_supply_name), + ov2735->supplies); +} + +static int ov2735_identify_module(struct ov2735 *ov2735) +{ + u64 chip_id; + int ret; + + ret = ov2735_read(ov2735, OV2735_REG_CHIPID, &chip_id, NULL); + if (ret) + return dev_err_probe(ov2735->dev, ret, + "failed to read chip id %x\n", + OV2735_CHIPID); + + if (chip_id != OV2735_CHIPID) + return dev_err_probe(ov2735->dev, -EIO, + "chip id mismatch: %x!=%llx\n", + OV2735_CHIPID, chip_id); + + return 0; +} + +static int ov2735_parse_endpoint(struct ov2735 *ov2735) +{ + struct v4l2_fwnode_endpoint bus_cfg = { + .bus_type = V4L2_MBUS_CSI2_DPHY, + }; + struct fwnode_handle *ep; + unsigned long link_freq_bitmap; + int ret; + + ep = fwnode_graph_get_next_endpoint(dev_fwnode(ov2735->dev), NULL); + if (!ep) + return dev_err_probe(ov2735->dev, -ENXIO, + "Failed to get next endpoint\n"); + + ret = v4l2_fwnode_endpoint_alloc_parse(ep, &bus_cfg); + fwnode_handle_put(ep); + if (ret) + return ret; + + if (bus_cfg.bus.mipi_csi2.num_data_lanes != 2) { + ret = dev_err_probe(ov2735->dev, -EINVAL, + "only 2 data lanes are supported\n"); + goto error_out; + } + + ret = v4l2_link_freq_to_bitmap(ov2735->dev, bus_cfg.link_frequencies, + bus_cfg.nr_of_link_frequencies, + link_freq_menu_items, + ARRAY_SIZE(link_freq_menu_items), + &link_freq_bitmap); + if (ret) { + ret = dev_err_probe(ov2735->dev, -EINVAL, + "only 420MHz frequency is available\n"); + goto error_out; + } + + ov2735->link_freq_index = __ffs(link_freq_bitmap); + +error_out: + v4l2_fwnode_endpoint_free(&bus_cfg); + + return ret; +}; + +static int ov2735_probe(struct i2c_client *client) +{ + struct ov2735 *ov2735; + unsigned int xclk_freq; + int ret; + + ov2735 = devm_kzalloc(&client->dev, sizeof(*ov2735), GFP_KERNEL); + if (!ov2735) + return -ENOMEM; + + ov2735->dev = &client->dev; + + v4l2_i2c_subdev_init(&ov2735->sd, client, &ov2735_subdev_ops); + ov2735->sd.internal_ops = &ov2735_internal_ops; + + ov2735->cci = devm_cci_regmap_init_i2c(client, 8); + if (IS_ERR(ov2735->cci)) + return dev_err_probe(ov2735->dev, PTR_ERR(ov2735->cci), + "failed to initialize CCI\n"); + + /* Set Current page to 0 */ + ov2735->current_page = 0; + + ret = devm_mutex_init(ov2735->dev, &ov2735->page_lock); + if (ret) + return dev_err_probe(ov2735->dev, ret, + "Failed to initialize lock\n"); + + /* Get system clock (xvclk) */ + ov2735->xclk = devm_v4l2_sensor_clk_get(ov2735->dev, NULL); + if (IS_ERR(ov2735->xclk)) + return dev_err_probe(ov2735->dev, PTR_ERR(ov2735->xclk), + "failed to get xclk\n"); + + xclk_freq = clk_get_rate(ov2735->xclk); + if (xclk_freq != OV2735_XCLK_FREQ) + return dev_err_probe(ov2735->dev, -EINVAL, + "xclk frequency not supported: %u Hz\n", + xclk_freq); + + ret = ov2735_get_regulators(ov2735); + if (ret) + return dev_err_probe(ov2735->dev, ret, + "failed to get regulators\n"); + + ret = ov2735_parse_endpoint(ov2735); + if (ret) + return dev_err_probe(ov2735->dev, ret, + "failed to parse endpoint configuration\n"); + + ov2735->reset_gpio = devm_gpiod_get_optional(ov2735->dev, + "reset", GPIOD_OUT_LOW); + if (IS_ERR(ov2735->reset_gpio)) + return dev_err_probe(ov2735->dev, PTR_ERR(ov2735->reset_gpio), + "failed to get reset GPIO\n"); + + ov2735->enable_gpio = devm_gpiod_get_optional(ov2735->dev, + "enable", GPIOD_OUT_LOW); + if (IS_ERR(ov2735->enable_gpio)) + return dev_err_probe(ov2735->dev, PTR_ERR(ov2735->enable_gpio), + "failed to get enable GPIO\n"); + + ret = ov2735_power_on(ov2735->dev); + if (ret) + return ret; + + ret = ov2735_identify_module(ov2735); + if (ret) + goto error_power_off; + + ret = ov2735_init_controls(ov2735); + if (ret) + goto error_power_off; + + /* Initialize subdev */ + ov2735->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; + ov2735->sd.entity.function = MEDIA_ENT_F_CAM_SENSOR; + ov2735->pad.flags = MEDIA_PAD_FL_SOURCE; + + ret = media_entity_pads_init(&ov2735->sd.entity, 1, &ov2735->pad); + if (ret) { + dev_err_probe(ov2735->dev, ret, "failed to init entity pads\n"); + goto error_handler_free; + } + + ov2735->sd.state_lock = ov2735->handler.lock; + ret = v4l2_subdev_init_finalize(&ov2735->sd); + if (ret) { + dev_err_probe(ov2735->dev, ret, "subdev init error\n"); + goto error_media_entity; + } + + ret = devm_pm_runtime_get_noresume(ov2735->dev); + if (ret) { + dev_err_probe(ov2735->dev, ret, + "failed to get runtime PM noresume\n"); + goto error_subdev_cleanup; + } + + ret = devm_pm_runtime_set_active_enabled(ov2735->dev); + if (ret) { + dev_err_probe(ov2735->dev, ret, + "failed to set runtime PM active+enabled\n"); + goto error_subdev_cleanup; + } + + ret = v4l2_async_register_subdev_sensor(&ov2735->sd); + if (ret) { + dev_err_probe(ov2735->dev, ret, + "failed to register ov2735 sub-device\n"); + goto error_subdev_cleanup; + } + + return 0; + +error_subdev_cleanup: + v4l2_subdev_cleanup(&ov2735->sd); + +error_media_entity: + media_entity_cleanup(&ov2735->sd.entity); + +error_handler_free: + v4l2_ctrl_handler_free(ov2735->sd.ctrl_handler); + +error_power_off: + ov2735_power_off(ov2735->dev); + + return ret; +} + +static void ov2735_remove(struct i2c_client *client) +{ + struct v4l2_subdev *sd = i2c_get_clientdata(client); + struct ov2735 *ov2735 = to_ov2735(sd); + + v4l2_async_unregister_subdev(sd); + v4l2_subdev_cleanup(&ov2735->sd); + media_entity_cleanup(&sd->entity); + v4l2_ctrl_handler_free(ov2735->sd.ctrl_handler); +} + +static DEFINE_RUNTIME_DEV_PM_OPS(ov2735_pm_ops, + ov2735_power_off, ov2735_power_on, NULL); + +static const struct of_device_id ov2735_id[] = { + { .compatible = "ovti,ov2735" }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, ov2735_id); + +static struct i2c_driver ov2735_driver = { + .driver = { + .name = "ov2735", + .pm = pm_ptr(&ov2735_pm_ops), + .of_match_table = ov2735_id, + }, + .probe = ov2735_probe, + .remove = ov2735_remove, +}; +module_i2c_driver(ov2735_driver); + +MODULE_DESCRIPTION("OV2735 Camera Sensor Driver"); +MODULE_AUTHOR("Hardevsinh Palaniya <hardevsinh.palaniya@siliconsignals.io>"); +MODULE_AUTHOR("Himanshu Bhavani <himanshu.bhavani@siliconsignals.io>"); +MODULE_LICENSE("GPL"); diff --git a/drivers/media/i2c/ov2740.c b/drivers/media/i2c/ov2740.c index 4e959534e6e7..fb590dfadda1 100644 --- a/drivers/media/i2c/ov2740.c +++ b/drivers/media/i2c/ov2740.c @@ -1,17 +1,17 @@ // SPDX-License-Identifier: GPL-2.0 // Copyright (c) 2020 Intel Corporation. -#include <linux/unaligned.h> #include <linux/acpi.h> #include <linux/clk.h> #include <linux/delay.h> #include <linux/gpio/consumer.h> #include <linux/i2c.h> #include <linux/module.h> -#include <linux/pm_runtime.h> #include <linux/nvmem-provider.h> +#include <linux/pm_runtime.h> #include <linux/regmap.h> #include <linux/regulator/consumer.h> +#include <linux/unaligned.h> #include <media/v4l2-ctrls.h> #include <media/v4l2-device.h> #include <media/v4l2-fwnode.h> @@ -519,6 +519,8 @@ static const struct ov2740_mode supported_modes_180mhz[] = { }; struct ov2740 { + struct device *dev; + struct v4l2_subdev sd; struct media_pad pad; struct v4l2_ctrl_handler ctrl_handler; @@ -616,7 +618,6 @@ static int ov2740_write_reg(struct ov2740 *ov2740, u16 reg, u16 len, u32 val) static int ov2740_write_reg_list(struct ov2740 *ov2740, const struct ov2740_reg_list *r_list) { - struct i2c_client *client = v4l2_get_subdevdata(&ov2740->sd); unsigned int i; int ret; @@ -624,7 +625,7 @@ static int ov2740_write_reg_list(struct ov2740 *ov2740, ret = ov2740_write_reg(ov2740, r_list->regs[i].address, 1, r_list->regs[i].val); if (ret) { - dev_err_ratelimited(&client->dev, + dev_err_ratelimited(ov2740->dev, "write reg 0x%4.4x return err = %d\n", r_list->regs[i].address, ret); return ret; @@ -636,7 +637,6 @@ static int ov2740_write_reg_list(struct ov2740 *ov2740, static int ov2740_identify_module(struct ov2740 *ov2740) { - struct i2c_client *client = v4l2_get_subdevdata(&ov2740->sd); int ret; u32 val; @@ -648,12 +648,12 @@ static int ov2740_identify_module(struct ov2740 *ov2740) return ret; if (val != OV2740_CHIP_ID) { - dev_err(&client->dev, "chip id mismatch: %x != %x\n", + dev_err(ov2740->dev, "chip id mismatch: %x != %x\n", OV2740_CHIP_ID, val); return -ENXIO; } - dev_dbg(&client->dev, "chip id: 0x%x\n", val); + dev_dbg(ov2740->dev, "chip id: 0x%x\n", val); ov2740->identified = true; @@ -704,7 +704,6 @@ static int ov2740_set_ctrl(struct v4l2_ctrl *ctrl) { struct ov2740 *ov2740 = container_of(ctrl->handler, struct ov2740, ctrl_handler); - struct i2c_client *client = v4l2_get_subdevdata(&ov2740->sd); s64 exposure_max; int ret; @@ -720,7 +719,7 @@ static int ov2740_set_ctrl(struct v4l2_ctrl *ctrl) } /* V4L2 controls values will be applied only when power is already up */ - if (!pm_runtime_get_if_in_use(&client->dev)) + if (!pm_runtime_get_if_in_use(ov2740->dev)) return 0; switch (ctrl->id) { @@ -753,7 +752,7 @@ static int ov2740_set_ctrl(struct v4l2_ctrl *ctrl) break; } - pm_runtime_put(&client->dev); + pm_runtime_put(ov2740->dev); return ret; } @@ -764,7 +763,6 @@ static const struct v4l2_ctrl_ops ov2740_ctrl_ops = { static int ov2740_init_controls(struct ov2740 *ov2740) { - struct i2c_client *client = v4l2_get_subdevdata(&ov2740->sd); struct v4l2_ctrl_handler *ctrl_hdlr; s64 exposure_max, h_blank, pixel_rate; u32 vblank_min, vblank_max, vblank_default; @@ -821,7 +819,7 @@ static int ov2740_init_controls(struct ov2740 *ov2740) ARRAY_SIZE(ov2740_test_pattern_menu) - 1, 0, 0, ov2740_test_pattern_menu); - ret = v4l2_fwnode_device_parse(&client->dev, &props); + ret = v4l2_fwnode_device_parse(ov2740->dev, &props); if (ret) { v4l2_ctrl_handler_free(ctrl_hdlr); return ret; @@ -940,7 +938,6 @@ err: static int ov2740_start_streaming(struct ov2740 *ov2740) { - struct i2c_client *client = v4l2_get_subdevdata(&ov2740->sd); const struct ov2740_reg_list *reg_list; int link_freq_index; int ret; @@ -955,7 +952,7 @@ static int ov2740_start_streaming(struct ov2740 *ov2740) /* Reset the sensor */ ret = ov2740_write_reg(ov2740, 0x0103, 1, 0x01); if (ret) { - dev_err(&client->dev, "failed to reset\n"); + dev_err(ov2740->dev, "failed to reset\n"); return ret; } @@ -965,14 +962,14 @@ static int ov2740_start_streaming(struct ov2740 *ov2740) reg_list = &link_freq_configs[link_freq_index].reg_list; ret = ov2740_write_reg_list(ov2740, reg_list); if (ret) { - dev_err(&client->dev, "failed to set plls\n"); + dev_err(ov2740->dev, "failed to set plls\n"); return ret; } reg_list = &ov2740->cur_mode->reg_list; ret = ov2740_write_reg_list(ov2740, reg_list); if (ret) { - dev_err(&client->dev, "failed to set mode\n"); + dev_err(ov2740->dev, "failed to set mode\n"); return ret; } @@ -983,31 +980,28 @@ static int ov2740_start_streaming(struct ov2740 *ov2740) ret = ov2740_write_reg(ov2740, OV2740_REG_MODE_SELECT, 1, OV2740_MODE_STREAMING); if (ret) - dev_err(&client->dev, "failed to start streaming\n"); + dev_err(ov2740->dev, "failed to start streaming\n"); return ret; } static void ov2740_stop_streaming(struct ov2740 *ov2740) { - struct i2c_client *client = v4l2_get_subdevdata(&ov2740->sd); - if (ov2740_write_reg(ov2740, OV2740_REG_MODE_SELECT, 1, OV2740_MODE_STANDBY)) - dev_err(&client->dev, "failed to stop streaming\n"); + dev_err(ov2740->dev, "failed to stop streaming\n"); } static int ov2740_set_stream(struct v4l2_subdev *sd, int enable) { struct ov2740 *ov2740 = to_ov2740(sd); - struct i2c_client *client = v4l2_get_subdevdata(sd); struct v4l2_subdev_state *sd_state; int ret = 0; sd_state = v4l2_subdev_lock_and_get_active_state(&ov2740->sd); if (enable) { - ret = pm_runtime_resume_and_get(&client->dev); + ret = pm_runtime_resume_and_get(ov2740->dev); if (ret < 0) goto out_unlock; @@ -1015,11 +1009,11 @@ static int ov2740_set_stream(struct v4l2_subdev *sd, int enable) if (ret) { enable = 0; ov2740_stop_streaming(ov2740); - pm_runtime_put(&client->dev); + pm_runtime_put(ov2740->dev); } } else { ov2740_stop_streaming(ov2740); - pm_runtime_put(&client->dev); + pm_runtime_put(ov2740->dev); } out_unlock: @@ -1131,16 +1125,14 @@ static const struct media_entity_operations ov2740_subdev_entity_ops = { .link_validate = v4l2_subdev_link_validate, }; -static int ov2740_check_hwcfg(struct device *dev) +static int ov2740_check_hwcfg(struct ov2740 *ov2740) { - struct v4l2_subdev *sd = dev_get_drvdata(dev); - struct ov2740 *ov2740 = to_ov2740(sd); + struct device *dev = ov2740->dev; struct fwnode_handle *ep; struct fwnode_handle *fwnode = dev_fwnode(dev); struct v4l2_fwnode_endpoint bus_cfg = { .bus_type = V4L2_MBUS_CSI2_DPHY }; - u32 mclk; int ret; unsigned int i, j; @@ -1153,20 +1145,6 @@ static int ov2740_check_hwcfg(struct device *dev) return dev_err_probe(dev, -EPROBE_DEFER, "waiting for fwnode graph endpoint\n"); - ret = fwnode_property_read_u32(fwnode, "clock-frequency", &mclk); - if (ret) { - fwnode_handle_put(ep); - return dev_err_probe(dev, ret, - "reading clock-frequency property\n"); - } - - if (mclk != OV2740_MCLK) { - fwnode_handle_put(ep); - return dev_err_probe(dev, -EINVAL, - "external clock %d is not supported\n", - mclk); - } - ret = v4l2_fwnode_endpoint_alloc_parse(ep, &bus_cfg); fwnode_handle_put(ep); if (ret) @@ -1270,7 +1248,7 @@ static int ov2740_register_nvmem(struct i2c_client *client, struct regmap_config regmap_config = { }; struct nvmem_config nvmem_config = { }; struct regmap *regmap; - struct device *dev = &client->dev; + struct device *dev = ov2740->dev; nvm = devm_kzalloc(dev, sizeof(*nvm), GFP_KERNEL); if (!nvm) @@ -1349,6 +1327,7 @@ static int ov2740_probe(struct i2c_client *client) { struct device *dev = &client->dev; struct ov2740 *ov2740; + unsigned long freq; bool full_power; unsigned int i; int ret; @@ -1357,10 +1336,12 @@ static int ov2740_probe(struct i2c_client *client) if (!ov2740) return -ENOMEM; + ov2740->dev = &client->dev; + v4l2_i2c_subdev_init(&ov2740->sd, client, &ov2740_subdev_ops); ov2740->sd.internal_ops = &ov2740_internal_ops; - ret = ov2740_check_hwcfg(dev); + ret = ov2740_check_hwcfg(ov2740); if (ret) return ret; @@ -1384,11 +1365,17 @@ static int ov2740_probe(struct i2c_client *client) msleep(20); } - ov2740->clk = devm_clk_get_optional(dev, "clk"); + ov2740->clk = devm_v4l2_sensor_clk_get(dev, "clk"); if (IS_ERR(ov2740->clk)) return dev_err_probe(dev, PTR_ERR(ov2740->clk), "failed to get clock\n"); + freq = clk_get_rate(ov2740->clk); + if (freq != OV2740_MCLK) + return dev_err_probe(dev, -EINVAL, + "external clock %lu is not supported\n", + freq); + for (i = 0; i < ARRAY_SIZE(ov2740_supply_name); i++) ov2740->supplies[i].supply = ov2740_supply_name[i]; @@ -1397,7 +1384,7 @@ static int ov2740_probe(struct i2c_client *client) if (ret) return dev_err_probe(dev, ret, "failed to get regulators\n"); - full_power = acpi_dev_state_d0(&client->dev); + full_power = acpi_dev_state_d0(ov2740->dev); if (full_power) { /* ACPI does not always clear the reset GPIO / enable the clock */ ret = ov2740_resume(dev); @@ -1435,9 +1422,9 @@ static int ov2740_probe(struct i2c_client *client) /* Set the device's state to active if it's in D0 state. */ if (full_power) - pm_runtime_set_active(&client->dev); - pm_runtime_enable(&client->dev); - pm_runtime_idle(&client->dev); + pm_runtime_set_active(ov2740->dev); + pm_runtime_enable(ov2740->dev); + pm_runtime_idle(ov2740->dev); ret = v4l2_async_register_subdev_sensor(&ov2740->sd); if (ret < 0) { @@ -1447,13 +1434,13 @@ static int ov2740_probe(struct i2c_client *client) ret = ov2740_register_nvmem(client, ov2740); if (ret) - dev_warn(&client->dev, "register nvmem failed, ret %d\n", ret); + dev_warn(ov2740->dev, "register nvmem failed, ret %d\n", ret); return 0; probe_error_v4l2_subdev_cleanup: - pm_runtime_disable(&client->dev); - pm_runtime_set_suspended(&client->dev); + pm_runtime_disable(ov2740->dev); + pm_runtime_set_suspended(ov2740->dev); v4l2_subdev_cleanup(&ov2740->sd); probe_error_media_entity_cleanup: diff --git a/drivers/media/i2c/ov4689.c b/drivers/media/i2c/ov4689.c index 7d740ad3926f..a59d25b09b5b 100644 --- a/drivers/media/i2c/ov4689.c +++ b/drivers/media/i2c/ov4689.c @@ -907,20 +907,12 @@ static int ov4689_probe(struct i2c_client *client) ov4689->cur_mode = &supported_modes[OV4689_MODE_2688_1520]; - ov4689->xvclk = devm_clk_get_optional(dev, NULL); + ov4689->xvclk = devm_v4l2_sensor_clk_get(dev, NULL); if (IS_ERR(ov4689->xvclk)) return dev_err_probe(dev, PTR_ERR(ov4689->xvclk), "Failed to get external clock\n"); - if (!ov4689->xvclk) { - dev_dbg(dev, - "No clock provided, using clock-frequency property\n"); - device_property_read_u32(dev, "clock-frequency", - &ov4689->clock_rate); - } else { - ov4689->clock_rate = clk_get_rate(ov4689->xvclk); - } - + ov4689->clock_rate = clk_get_rate(ov4689->xvclk); if (ov4689->clock_rate != OV4689_XVCLK_FREQ) { dev_err(dev, "External clock rate mismatch: got %d Hz, expected %d Hz\n", diff --git a/drivers/media/i2c/ov5640.c b/drivers/media/i2c/ov5640.c index 84198613381d..85ecc23b3587 100644 --- a/drivers/media/i2c/ov5640.c +++ b/drivers/media/i2c/ov5640.c @@ -3895,11 +3895,10 @@ static int ov5640_probe(struct i2c_client *client) ov5640_dvp_default_fmt; /* get system clock (xclk) */ - sensor->xclk = devm_clk_get(dev, "xclk"); - if (IS_ERR(sensor->xclk)) { - dev_err(dev, "failed to get xclk\n"); - return PTR_ERR(sensor->xclk); - } + sensor->xclk = devm_v4l2_sensor_clk_get(dev, "xclk"); + if (IS_ERR(sensor->xclk)) + return dev_err_probe(dev, PTR_ERR(sensor->xclk), + "failed to get xclk\n"); sensor->xclk_freq = clk_get_rate(sensor->xclk); if (sensor->xclk_freq < OV5640_XCLK_MIN || diff --git a/drivers/media/i2c/ov5645.c b/drivers/media/i2c/ov5645.c index 58c846a44376..b10d408034a1 100644 --- a/drivers/media/i2c/ov5645.c +++ b/drivers/media/i2c/ov5645.c @@ -1042,27 +1042,18 @@ static int ov5645_probe(struct i2c_client *client) "invalid bus type, must be CSI2\n"); /* get system clock (xclk) */ - ov5645->xclk = devm_clk_get(dev, NULL); + ov5645->xclk = devm_v4l2_sensor_clk_get_legacy(dev, NULL, false, 0); if (IS_ERR(ov5645->xclk)) return dev_err_probe(dev, PTR_ERR(ov5645->xclk), "could not get xclk"); - ret = of_property_read_u32(dev->of_node, "clock-frequency", &xclk_freq); - if (ret) - return dev_err_probe(dev, ret, - "could not get xclk frequency\n"); - /* external clock must be 24MHz, allow 1% tolerance */ + xclk_freq = clk_get_rate(ov5645->xclk); if (xclk_freq < 23760000 || xclk_freq > 24240000) return dev_err_probe(dev, -EINVAL, "unsupported xclk frequency %u\n", xclk_freq); - ret = clk_set_rate(ov5645->xclk, xclk_freq); - if (ret) - return dev_err_probe(dev, ret, - "could not set xclk frequency\n"); - for (i = 0; i < OV5645_NUM_SUPPLIES; i++) ov5645->supplies[i].supply = ov5645_supply_name[i]; diff --git a/drivers/media/i2c/ov5647.c b/drivers/media/i2c/ov5647.c index a727beb9d57e..e193fef4fced 100644 --- a/drivers/media/i2c/ov5647.c +++ b/drivers/media/i2c/ov5647.c @@ -1398,11 +1398,10 @@ static int ov5647_probe(struct i2c_client *client) } } - sensor->xclk = devm_clk_get(dev, NULL); - if (IS_ERR(sensor->xclk)) { - dev_err(dev, "could not get xclk"); - return PTR_ERR(sensor->xclk); - } + sensor->xclk = devm_v4l2_sensor_clk_get(dev, NULL); + if (IS_ERR(sensor->xclk)) + return dev_err_probe(dev, PTR_ERR(sensor->xclk), + "could not get xclk\n"); xclk_freq = clk_get_rate(sensor->xclk); if (xclk_freq != 25000000) { diff --git a/drivers/media/i2c/ov5648.c b/drivers/media/i2c/ov5648.c index 4b86d2631bd1..f0b839cd65f1 100644 --- a/drivers/media/i2c/ov5648.c +++ b/drivers/media/i2c/ov5648.c @@ -1061,8 +1061,8 @@ static int ov5648_sw_standby(struct ov5648_sensor *sensor, int standby) static int ov5648_chip_id_check(struct ov5648_sensor *sensor) { - u16 regs[] = { OV5648_CHIP_ID_H_REG, OV5648_CHIP_ID_L_REG }; - u8 values[] = { OV5648_CHIP_ID_H_VALUE, OV5648_CHIP_ID_L_VALUE }; + static const u16 regs[] = { OV5648_CHIP_ID_H_REG, OV5648_CHIP_ID_L_REG }; + static const u8 values[] = { OV5648_CHIP_ID_H_VALUE, OV5648_CHIP_ID_L_VALUE }; unsigned int i; u8 value; int ret; @@ -2521,10 +2521,10 @@ static int ov5648_probe(struct i2c_client *client) /* External Clock */ - sensor->xvclk = devm_clk_get(dev, NULL); + sensor->xvclk = devm_v4l2_sensor_clk_get(dev, NULL); if (IS_ERR(sensor->xvclk)) { - dev_err(dev, "failed to get external clock\n"); - ret = PTR_ERR(sensor->xvclk); + ret = dev_err_probe(dev, PTR_ERR(sensor->xvclk), + "failed to get external clock\n"); goto error_endpoint; } diff --git a/drivers/media/i2c/ov5670.c b/drivers/media/i2c/ov5670.c index b9efb2d2276a..04b3183b7bcb 100644 --- a/drivers/media/i2c/ov5670.c +++ b/drivers/media/i2c/ov5670.c @@ -1,7 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 // Copyright (c) 2017 Intel Corporation. -#include <linux/unaligned.h> #include <linux/acpi.h> #include <linux/clk.h> #include <linux/delay.h> @@ -12,6 +11,8 @@ #include <linux/of.h> #include <linux/pm_runtime.h> #include <linux/regulator/consumer.h> +#include <linux/unaligned.h> + #include <media/v4l2-ctrls.h> #include <media/v4l2-device.h> #include <media/v4l2-event.h> @@ -1854,6 +1855,8 @@ static const struct ov5670_mode supported_modes[] = { }; struct ov5670 { + struct device *dev; + struct v4l2_subdev sd; struct media_pad pad; struct v4l2_fwnode_endpoint endpoint; @@ -1959,7 +1962,6 @@ static int ov5670_write_reg(struct ov5670 *ov5670, u16 reg, unsigned int len, static int ov5670_write_regs(struct ov5670 *ov5670, const struct ov5670_reg *regs, unsigned int len) { - struct i2c_client *client = v4l2_get_subdevdata(&ov5670->sd); unsigned int i; int ret; @@ -1967,7 +1969,7 @@ static int ov5670_write_regs(struct ov5670 *ov5670, ret = ov5670_write_reg(ov5670, regs[i].address, 1, regs[i].val); if (ret) { dev_err_ratelimited( - &client->dev, + ov5670->dev, "Failed to write reg 0x%4.4x. error = %d\n", regs[i].address, ret); @@ -2032,7 +2034,6 @@ static int ov5670_set_ctrl(struct v4l2_ctrl *ctrl) { struct ov5670 *ov5670 = container_of(ctrl->handler, struct ov5670, ctrl_handler); - struct i2c_client *client = v4l2_get_subdevdata(&ov5670->sd); s64 max; int ret; @@ -2048,7 +2049,7 @@ static int ov5670_set_ctrl(struct v4l2_ctrl *ctrl) } /* V4L2 controls values will be applied only when power is already up */ - if (!pm_runtime_get_if_in_use(&client->dev)) + if (!pm_runtime_get_if_in_use(ov5670->dev)) return 0; switch (ctrl->id) { @@ -2080,12 +2081,12 @@ static int ov5670_set_ctrl(struct v4l2_ctrl *ctrl) break; default: ret = -EINVAL; - dev_info(&client->dev, "%s Unhandled id:0x%x, val:0x%x\n", + dev_info(ov5670->dev, "%s Unhandled id:0x%x, val:0x%x\n", __func__, ctrl->id, ctrl->val); break; } - pm_runtime_put(&client->dev); + pm_runtime_put(ov5670->dev); return ret; } @@ -2099,7 +2100,6 @@ static int ov5670_init_controls(struct ov5670 *ov5670) { struct v4l2_mbus_config_mipi_csi2 *bus_mipi_csi2 = &ov5670->endpoint.bus.mipi_csi2; - struct i2c_client *client = v4l2_get_subdevdata(&ov5670->sd); struct v4l2_fwnode_device_properties props; struct v4l2_ctrl_handler *ctrl_hdlr; unsigned int lanes_count; @@ -2177,7 +2177,7 @@ static int ov5670_init_controls(struct ov5670 *ov5670) goto error; } - ret = v4l2_fwnode_device_parse(&client->dev, &props); + ret = v4l2_fwnode_device_parse(ov5670->dev, &props); if (ret) goto error; @@ -2350,7 +2350,6 @@ static int ov5670_get_skip_frames(struct v4l2_subdev *sd, u32 *frames) /* Verify chip ID */ static int ov5670_identify_module(struct ov5670 *ov5670) { - struct i2c_client *client = v4l2_get_subdevdata(&ov5670->sd); int ret; u32 val; @@ -2363,7 +2362,7 @@ static int ov5670_identify_module(struct ov5670 *ov5670) return ret; if (val != OV5670_CHIP_ID) { - dev_err(&client->dev, "chip id mismatch: %x!=%x\n", + dev_err(ov5670->dev, "chip id mismatch: %x!=%x\n", OV5670_CHIP_ID, val); return -ENXIO; } @@ -2389,7 +2388,6 @@ static int ov5670_mipi_configure(struct ov5670 *ov5670) /* Prepare streaming by writing default values and customized values */ static int ov5670_start_streaming(struct ov5670 *ov5670) { - struct i2c_client *client = v4l2_get_subdevdata(&ov5670->sd); const struct ov5670_reg_list *reg_list; int link_freq_index; int ret; @@ -2402,7 +2400,7 @@ static int ov5670_start_streaming(struct ov5670 *ov5670) ret = ov5670_write_reg(ov5670, OV5670_REG_SOFTWARE_RST, OV5670_REG_VALUE_08BIT, OV5670_SOFTWARE_RST); if (ret) { - dev_err(&client->dev, "%s failed to set powerup registers\n", + dev_err(ov5670->dev, "%s failed to set powerup registers\n", __func__); return ret; } @@ -2412,7 +2410,7 @@ static int ov5670_start_streaming(struct ov5670 *ov5670) reg_list = &link_freq_configs[link_freq_index].reg_list; ret = ov5670_write_reg_list(ov5670, reg_list); if (ret) { - dev_err(&client->dev, "%s failed to set plls\n", __func__); + dev_err(ov5670->dev, "%s failed to set plls\n", __func__); return ret; } @@ -2420,13 +2418,13 @@ static int ov5670_start_streaming(struct ov5670 *ov5670) reg_list = &ov5670->cur_mode->reg_list; ret = ov5670_write_reg_list(ov5670, reg_list); if (ret) { - dev_err(&client->dev, "%s failed to set mode\n", __func__); + dev_err(ov5670->dev, "%s failed to set mode\n", __func__); return ret; } ret = ov5670_mipi_configure(ov5670); if (ret) { - dev_err(&client->dev, "%s failed to configure MIPI\n", __func__); + dev_err(ov5670->dev, "%s failed to configure MIPI\n", __func__); return ret; } @@ -2438,7 +2436,7 @@ static int ov5670_start_streaming(struct ov5670 *ov5670) ret = ov5670_write_reg(ov5670, OV5670_REG_MODE_SELECT, OV5670_REG_VALUE_08BIT, OV5670_MODE_STREAMING); if (ret) { - dev_err(&client->dev, "%s failed to set stream\n", __func__); + dev_err(ov5670->dev, "%s failed to set stream\n", __func__); return ret; } @@ -2447,13 +2445,12 @@ static int ov5670_start_streaming(struct ov5670 *ov5670) static int ov5670_stop_streaming(struct ov5670 *ov5670) { - struct i2c_client *client = v4l2_get_subdevdata(&ov5670->sd); int ret; ret = ov5670_write_reg(ov5670, OV5670_REG_MODE_SELECT, OV5670_REG_VALUE_08BIT, OV5670_MODE_STANDBY); if (ret) - dev_err(&client->dev, "%s failed to set stream\n", __func__); + dev_err(ov5670->dev, "%s failed to set stream\n", __func__); /* Return success even if it was an error, as there is nothing the * caller can do about it. @@ -2464,13 +2461,12 @@ static int ov5670_stop_streaming(struct ov5670 *ov5670) static int ov5670_set_stream(struct v4l2_subdev *sd, int enable) { struct ov5670 *ov5670 = to_ov5670(sd); - struct i2c_client *client = v4l2_get_subdevdata(sd); int ret = 0; mutex_lock(&ov5670->mutex); if (enable) { - ret = pm_runtime_resume_and_get(&client->dev); + ret = pm_runtime_resume_and_get(ov5670->dev); if (ret < 0) goto unlock_and_return; @@ -2479,12 +2475,12 @@ static int ov5670_set_stream(struct v4l2_subdev *sd, int enable) goto error; } else { ret = ov5670_stop_streaming(ov5670); - pm_runtime_put(&client->dev); + pm_runtime_put(ov5670->dev); } goto unlock_and_return; error: - pm_runtime_put(&client->dev); + pm_runtime_put(ov5670->dev); unlock_and_return: mutex_unlock(&ov5670->mutex); @@ -2621,26 +2617,23 @@ static const struct media_entity_operations ov5670_subdev_entity_ops = { static int ov5670_regulators_probe(struct ov5670 *ov5670) { - struct i2c_client *client = v4l2_get_subdevdata(&ov5670->sd); unsigned int i; for (i = 0; i < OV5670_NUM_SUPPLIES; i++) ov5670->supplies[i].supply = ov5670_supply_names[i]; - return devm_regulator_bulk_get(&client->dev, OV5670_NUM_SUPPLIES, + return devm_regulator_bulk_get(ov5670->dev, OV5670_NUM_SUPPLIES, ov5670->supplies); } static int ov5670_gpio_probe(struct ov5670 *ov5670) { - struct i2c_client *client = v4l2_get_subdevdata(&ov5670->sd); - - ov5670->pwdn_gpio = devm_gpiod_get_optional(&client->dev, "powerdown", + ov5670->pwdn_gpio = devm_gpiod_get_optional(ov5670->dev, "powerdown", GPIOD_OUT_LOW); if (IS_ERR(ov5670->pwdn_gpio)) return PTR_ERR(ov5670->pwdn_gpio); - ov5670->reset_gpio = devm_gpiod_get_optional(&client->dev, "reset", + ov5670->reset_gpio = devm_gpiod_get_optional(ov5670->dev, "reset", GPIOD_OUT_LOW); if (IS_ERR(ov5670->reset_gpio)) return PTR_ERR(ov5670->reset_gpio); @@ -2660,18 +2653,16 @@ static int ov5670_probe(struct i2c_client *client) if (!ov5670) return -ENOMEM; - ov5670->xvclk = devm_clk_get_optional(&client->dev, NULL); - if (!IS_ERR_OR_NULL(ov5670->xvclk)) - input_clk = clk_get_rate(ov5670->xvclk); - else if (!ov5670->xvclk || PTR_ERR(ov5670->xvclk) == -ENOENT) - device_property_read_u32(&client->dev, "clock-frequency", - &input_clk); - else - return dev_err_probe(&client->dev, PTR_ERR(ov5670->xvclk), + ov5670->dev = &client->dev; + + ov5670->xvclk = devm_v4l2_sensor_clk_get(ov5670->dev, NULL); + if (IS_ERR(ov5670->xvclk)) + return dev_err_probe(ov5670->dev, PTR_ERR(ov5670->xvclk), "error getting clock\n"); + input_clk = clk_get_rate(ov5670->xvclk); if (input_clk != OV5670_XVCLK_FREQ) { - dev_err(&client->dev, + dev_err(ov5670->dev, "Unsupported clock frequency %u\n", input_clk); return -EINVAL; } @@ -2682,20 +2673,20 @@ static int ov5670_probe(struct i2c_client *client) ret = ov5670_regulators_probe(ov5670); if (ret) - return dev_err_probe(&client->dev, ret, "Regulators probe failed\n"); + return dev_err_probe(ov5670->dev, ret, "Regulators probe failed\n"); ret = ov5670_gpio_probe(ov5670); if (ret) - return dev_err_probe(&client->dev, ret, "GPIO probe failed\n"); + return dev_err_probe(ov5670->dev, ret, "GPIO probe failed\n"); /* * Graph Endpoint. If it's missing we defer rather than fail, as this * sensor is known to co-exist on systems with the IPU3 and so it might * be created by the ipu-bridge. */ - handle = fwnode_graph_get_next_endpoint(dev_fwnode(&client->dev), NULL); + handle = fwnode_graph_get_next_endpoint(dev_fwnode(ov5670->dev), NULL); if (!handle) - return dev_err_probe(&client->dev, -EPROBE_DEFER, + return dev_err_probe(ov5670->dev, -EPROBE_DEFER, "Endpoint for node get failed\n"); ov5670->endpoint.bus_type = V4L2_MBUS_CSI2_DPHY; @@ -2704,20 +2695,20 @@ static int ov5670_probe(struct i2c_client *client) ret = v4l2_fwnode_endpoint_alloc_parse(handle, &ov5670->endpoint); fwnode_handle_put(handle); if (ret) - return dev_err_probe(&client->dev, ret, "Endpoint parse failed\n"); + return dev_err_probe(ov5670->dev, ret, "Endpoint parse failed\n"); - full_power = acpi_dev_state_d0(&client->dev); + full_power = acpi_dev_state_d0(ov5670->dev); if (full_power) { - ret = ov5670_runtime_resume(&client->dev); + ret = ov5670_runtime_resume(ov5670->dev); if (ret) { - dev_err_probe(&client->dev, ret, "Power up failed\n"); + dev_err_probe(ov5670->dev, ret, "Power up failed\n"); goto error_endpoint; } /* Check module identity */ ret = ov5670_identify_module(ov5670); if (ret) { - dev_err_probe(&client->dev, ret, "ov5670_identify_module() error\n"); + dev_err_probe(ov5670->dev, ret, "ov5670_identify_module() error\n"); goto error_power_off; } } @@ -2729,7 +2720,7 @@ static int ov5670_probe(struct i2c_client *client) ret = ov5670_init_controls(ov5670); if (ret) { - dev_err_probe(&client->dev, ret, "ov5670_init_controls() error\n"); + dev_err_probe(ov5670->dev, ret, "ov5670_init_controls() error\n"); goto error_mutex_destroy; } @@ -2742,28 +2733,28 @@ static int ov5670_probe(struct i2c_client *client) ov5670->pad.flags = MEDIA_PAD_FL_SOURCE; ret = media_entity_pads_init(&ov5670->sd.entity, 1, &ov5670->pad); if (ret) { - dev_err_probe(&client->dev, ret, "media_entity_pads_init() error\n"); + dev_err_probe(ov5670->dev, ret, "media_entity_pads_init() error\n"); goto error_handler_free; } /* Set the device's state to active if it's in D0 state. */ if (full_power) - pm_runtime_set_active(&client->dev); - pm_runtime_enable(&client->dev); + pm_runtime_set_active(ov5670->dev); + pm_runtime_enable(ov5670->dev); /* Async register for subdev */ ret = v4l2_async_register_subdev_sensor(&ov5670->sd); if (ret < 0) { - dev_err_probe(&client->dev, ret, "v4l2_async_register_subdev() error\n"); + dev_err_probe(ov5670->dev, ret, "v4l2_async_register_subdev() error\n"); goto error_pm_disable; } - pm_runtime_idle(&client->dev); + pm_runtime_idle(ov5670->dev); return 0; error_pm_disable: - pm_runtime_disable(&client->dev); + pm_runtime_disable(ov5670->dev); media_entity_cleanup(&ov5670->sd.entity); @@ -2775,7 +2766,7 @@ error_mutex_destroy: error_power_off: if (full_power) - ov5670_runtime_suspend(&client->dev); + ov5670_runtime_suspend(ov5670->dev); error_endpoint: v4l2_fwnode_endpoint_free(&ov5670->endpoint); @@ -2793,8 +2784,8 @@ static void ov5670_remove(struct i2c_client *client) v4l2_ctrl_handler_free(sd->ctrl_handler); mutex_destroy(&ov5670->mutex); - pm_runtime_disable(&client->dev); - ov5670_runtime_suspend(&client->dev); + pm_runtime_disable(ov5670->dev); + ov5670_runtime_suspend(ov5670->dev); v4l2_fwnode_endpoint_free(&ov5670->endpoint); } diff --git a/drivers/media/i2c/ov5675.c b/drivers/media/i2c/ov5675.c index e7aec281e9a4..30e27d39ee44 100644 --- a/drivers/media/i2c/ov5675.c +++ b/drivers/media/i2c/ov5675.c @@ -1,7 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 // Copyright (c) 2019 Intel Corporation. -#include <linux/unaligned.h> #include <linux/acpi.h> #include <linux/clk.h> #include <linux/delay.h> @@ -11,6 +10,8 @@ #include <linux/module.h> #include <linux/pm_runtime.h> #include <linux/regulator/consumer.h> +#include <linux/unaligned.h> + #include <media/v4l2-ctrls.h> #include <media/v4l2-device.h> #include <media/v4l2-fwnode.h> @@ -493,6 +494,8 @@ static const struct ov5675_mode supported_modes[] = { }; struct ov5675 { + struct device *dev; + struct v4l2_subdev sd; struct media_pad pad; struct v4l2_ctrl_handler ctrl_handler; @@ -584,7 +587,6 @@ static int ov5675_write_reg(struct ov5675 *ov5675, u16 reg, u16 len, u32 val) static int ov5675_write_reg_list(struct ov5675 *ov5675, const struct ov5675_reg_list *r_list) { - struct i2c_client *client = v4l2_get_subdevdata(&ov5675->sd); unsigned int i; int ret; @@ -592,7 +594,7 @@ static int ov5675_write_reg_list(struct ov5675 *ov5675, ret = ov5675_write_reg(ov5675, r_list->regs[i].address, 1, r_list->regs[i].val); if (ret) { - dev_err_ratelimited(&client->dev, + dev_err_ratelimited(ov5675->dev, "failed to write reg 0x%4.4x. error = %d", r_list->regs[i].address, ret); return ret; @@ -700,7 +702,6 @@ static int ov5675_set_ctrl(struct v4l2_ctrl *ctrl) { struct ov5675 *ov5675 = container_of(ctrl->handler, struct ov5675, ctrl_handler); - struct i2c_client *client = v4l2_get_subdevdata(&ov5675->sd); s64 exposure_max; int ret = 0; @@ -716,7 +717,7 @@ static int ov5675_set_ctrl(struct v4l2_ctrl *ctrl) } /* V4L2 controls values will be applied only when power is already up */ - if (!pm_runtime_get_if_in_use(&client->dev)) + if (!pm_runtime_get_if_in_use(ov5675->dev)) return 0; switch (ctrl->id) { @@ -765,7 +766,7 @@ static int ov5675_set_ctrl(struct v4l2_ctrl *ctrl) break; } - pm_runtime_put(&client->dev); + pm_runtime_put(ov5675->dev); return ret; } @@ -776,7 +777,6 @@ static const struct v4l2_ctrl_ops ov5675_ctrl_ops = { static int ov5675_init_controls(struct ov5675 *ov5675) { - struct i2c_client *client = v4l2_get_subdevdata(&ov5675->sd); struct v4l2_fwnode_device_properties props; struct v4l2_ctrl_handler *ctrl_hdlr; s64 exposure_max, h_blank; @@ -839,7 +839,7 @@ static int ov5675_init_controls(struct ov5675 *ov5675) return ctrl_hdlr->error; } - ret = v4l2_fwnode_device_parse(&client->dev, &props); + ret = v4l2_fwnode_device_parse(ov5675->dev, &props); if (ret) goto error; @@ -869,7 +869,6 @@ static void ov5675_update_pad_format(const struct ov5675_mode *mode, static int ov5675_identify_module(struct ov5675 *ov5675) { - struct i2c_client *client = v4l2_get_subdevdata(&ov5675->sd); int ret; u32 val; @@ -882,7 +881,7 @@ static int ov5675_identify_module(struct ov5675 *ov5675) return ret; if (val != OV5675_CHIP_ID) { - dev_err(&client->dev, "chip id mismatch: %x!=%x", + dev_err(ov5675->dev, "chip id mismatch: %x!=%x", OV5675_CHIP_ID, val); return -ENXIO; } @@ -894,7 +893,6 @@ static int ov5675_identify_module(struct ov5675 *ov5675) static int ov5675_start_streaming(struct ov5675 *ov5675) { - struct i2c_client *client = v4l2_get_subdevdata(&ov5675->sd); const struct ov5675_reg_list *reg_list; int link_freq_index, ret; @@ -906,14 +904,14 @@ static int ov5675_start_streaming(struct ov5675 *ov5675) reg_list = &link_freq_configs[link_freq_index].reg_list; ret = ov5675_write_reg_list(ov5675, reg_list); if (ret) { - dev_err(&client->dev, "failed to set plls"); + dev_err(ov5675->dev, "failed to set plls"); return ret; } reg_list = &ov5675->cur_mode->reg_list; ret = ov5675_write_reg_list(ov5675, reg_list); if (ret) { - dev_err(&client->dev, "failed to set mode"); + dev_err(ov5675->dev, "failed to set mode"); return ret; } @@ -924,7 +922,7 @@ static int ov5675_start_streaming(struct ov5675 *ov5675) ret = ov5675_write_reg(ov5675, OV5675_REG_MODE_SELECT, OV5675_REG_VALUE_08BIT, OV5675_MODE_STREAMING); if (ret) { - dev_err(&client->dev, "failed to set stream"); + dev_err(ov5675->dev, "failed to set stream"); return ret; } @@ -933,22 +931,19 @@ static int ov5675_start_streaming(struct ov5675 *ov5675) static void ov5675_stop_streaming(struct ov5675 *ov5675) { - struct i2c_client *client = v4l2_get_subdevdata(&ov5675->sd); - if (ov5675_write_reg(ov5675, OV5675_REG_MODE_SELECT, OV5675_REG_VALUE_08BIT, OV5675_MODE_STANDBY)) - dev_err(&client->dev, "failed to set stream"); + dev_err(ov5675->dev, "failed to set stream"); } static int ov5675_set_stream(struct v4l2_subdev *sd, int enable) { struct ov5675 *ov5675 = to_ov5675(sd); - struct i2c_client *client = v4l2_get_subdevdata(sd); int ret = 0; mutex_lock(&ov5675->mutex); if (enable) { - ret = pm_runtime_resume_and_get(&client->dev); + ret = pm_runtime_resume_and_get(ov5675->dev); if (ret < 0) { mutex_unlock(&ov5675->mutex); return ret; @@ -958,11 +953,11 @@ static int ov5675_set_stream(struct v4l2_subdev *sd, int enable) if (ret) { enable = 0; ov5675_stop_streaming(ov5675); - pm_runtime_put(&client->dev); + pm_runtime_put(ov5675->dev); } } else { ov5675_stop_streaming(ov5675); - pm_runtime_put(&client->dev); + pm_runtime_put(ov5675->dev); } mutex_unlock(&ov5675->mutex); @@ -1171,8 +1166,9 @@ static const struct v4l2_subdev_internal_ops ov5675_internal_ops = { .open = ov5675_open, }; -static int ov5675_get_hwcfg(struct ov5675 *ov5675, struct device *dev) +static int ov5675_get_hwcfg(struct ov5675 *ov5675) { + struct device *dev = ov5675->dev; struct fwnode_handle *ep; struct fwnode_handle *fwnode = dev_fwnode(dev); struct v4l2_fwnode_endpoint bus_cfg = { @@ -1185,24 +1181,13 @@ static int ov5675_get_hwcfg(struct ov5675 *ov5675, struct device *dev) if (!fwnode) return -ENXIO; - ov5675->xvclk = devm_clk_get_optional(dev, NULL); + ov5675->xvclk = devm_v4l2_sensor_clk_get(dev, NULL); if (IS_ERR(ov5675->xvclk)) return dev_err_probe(dev, PTR_ERR(ov5675->xvclk), "failed to get xvclk: %ld\n", PTR_ERR(ov5675->xvclk)); - if (ov5675->xvclk) { - xvclk_rate = clk_get_rate(ov5675->xvclk); - } else { - ret = fwnode_property_read_u32(fwnode, "clock-frequency", - &xvclk_rate); - - if (ret) { - dev_err(dev, "can't get clock frequency"); - return ret; - } - } - + xvclk_rate = clk_get_rate(ov5675->xvclk); if (xvclk_rate != OV5675_XVCLK_19_2) { dev_err(dev, "external clock rate %u is unsupported", xvclk_rate); @@ -1276,12 +1261,12 @@ static void ov5675_remove(struct i2c_client *client) v4l2_async_unregister_subdev(sd); media_entity_cleanup(&sd->entity); v4l2_ctrl_handler_free(sd->ctrl_handler); - pm_runtime_disable(&client->dev); + pm_runtime_disable(ov5675->dev); mutex_destroy(&ov5675->mutex); - if (!pm_runtime_status_suspended(&client->dev)) - ov5675_power_off(&client->dev); - pm_runtime_set_suspended(&client->dev); + if (!pm_runtime_status_suspended(ov5675->dev)) + ov5675_power_off(ov5675->dev); + pm_runtime_set_suspended(ov5675->dev); } static int ov5675_probe(struct i2c_client *client) @@ -1294,23 +1279,25 @@ static int ov5675_probe(struct i2c_client *client) if (!ov5675) return -ENOMEM; - ret = ov5675_get_hwcfg(ov5675, &client->dev); + ov5675->dev = &client->dev; + + ret = ov5675_get_hwcfg(ov5675); if (ret) return ret; v4l2_i2c_subdev_init(&ov5675->sd, client, &ov5675_subdev_ops); - ret = ov5675_power_on(&client->dev); + ret = ov5675_power_on(ov5675->dev); if (ret) { - dev_err(&client->dev, "failed to power on: %d\n", ret); + dev_err(ov5675->dev, "failed to power on: %d\n", ret); return ret; } - full_power = acpi_dev_state_d0(&client->dev); + full_power = acpi_dev_state_d0(ov5675->dev); if (full_power) { ret = ov5675_identify_module(ov5675); if (ret) { - dev_err(&client->dev, "failed to find sensor: %d", ret); + dev_err(ov5675->dev, "failed to find sensor: %d", ret); goto probe_power_off; } } @@ -1319,7 +1306,7 @@ static int ov5675_probe(struct i2c_client *client) ov5675->cur_mode = &supported_modes[0]; ret = ov5675_init_controls(ov5675); if (ret) { - dev_err(&client->dev, "failed to init controls: %d", ret); + dev_err(ov5675->dev, "failed to init controls: %d", ret); goto probe_error_v4l2_ctrl_handler_free; } @@ -1330,22 +1317,22 @@ static int ov5675_probe(struct i2c_client *client) ov5675->pad.flags = MEDIA_PAD_FL_SOURCE; ret = media_entity_pads_init(&ov5675->sd.entity, 1, &ov5675->pad); if (ret) { - dev_err(&client->dev, "failed to init entity pads: %d", ret); + dev_err(ov5675->dev, "failed to init entity pads: %d", ret); goto probe_error_v4l2_ctrl_handler_free; } ret = v4l2_async_register_subdev_sensor(&ov5675->sd); if (ret < 0) { - dev_err(&client->dev, "failed to register V4L2 subdev: %d", + dev_err(ov5675->dev, "failed to register V4L2 subdev: %d", ret); goto probe_error_media_entity_cleanup; } /* Set the device's state to active if it's in D0 state. */ if (full_power) - pm_runtime_set_active(&client->dev); - pm_runtime_enable(&client->dev); - pm_runtime_idle(&client->dev); + pm_runtime_set_active(ov5675->dev); + pm_runtime_enable(ov5675->dev); + pm_runtime_idle(ov5675->dev); return 0; @@ -1356,7 +1343,7 @@ probe_error_v4l2_ctrl_handler_free: v4l2_ctrl_handler_free(ov5675->sd.ctrl_handler); mutex_destroy(&ov5675->mutex); probe_power_off: - ov5675_power_off(&client->dev); + ov5675_power_off(ov5675->dev); return ret; } diff --git a/drivers/media/i2c/ov5693.c b/drivers/media/i2c/ov5693.c index 485efd15257e..d294477f9dd3 100644 --- a/drivers/media/i2c/ov5693.c +++ b/drivers/media/i2c/ov5693.c @@ -1289,25 +1289,13 @@ static int ov5693_probe(struct i2c_client *client) v4l2_i2c_subdev_init(&ov5693->sd, client, &ov5693_ops); - ov5693->xvclk = devm_clk_get_optional(&client->dev, "xvclk"); + ov5693->xvclk = devm_v4l2_sensor_clk_get(&client->dev, "xvclk"); if (IS_ERR(ov5693->xvclk)) return dev_err_probe(&client->dev, PTR_ERR(ov5693->xvclk), "failed to get xvclk: %ld\n", PTR_ERR(ov5693->xvclk)); - if (ov5693->xvclk) { - xvclk_rate = clk_get_rate(ov5693->xvclk); - } else { - ret = fwnode_property_read_u32(dev_fwnode(&client->dev), - "clock-frequency", - &xvclk_rate); - - if (ret) { - dev_err(&client->dev, "can't get clock frequency"); - return ret; - } - } - + xvclk_rate = clk_get_rate(ov5693->xvclk); if (xvclk_rate != OV5693_XVCLK_FREQ) dev_warn(&client->dev, "Found clk freq %u, expected %u\n", xvclk_rate, OV5693_XVCLK_FREQ); diff --git a/drivers/media/i2c/ov5695.c b/drivers/media/i2c/ov5695.c index 663eccdfea6a..5bb6ce7b3237 100644 --- a/drivers/media/i2c/ov5695.c +++ b/drivers/media/i2c/ov5695.c @@ -1264,16 +1264,12 @@ static int ov5695_probe(struct i2c_client *client) ov5695->client = client; ov5695->cur_mode = &supported_modes[0]; - ov5695->xvclk = devm_clk_get(dev, "xvclk"); - if (IS_ERR(ov5695->xvclk)) { - dev_err(dev, "Failed to get xvclk\n"); - return -EINVAL; - } - ret = clk_set_rate(ov5695->xvclk, OV5695_XVCLK_FREQ); - if (ret < 0) { - dev_err(dev, "Failed to set xvclk rate (24MHz)\n"); - return ret; - } + ov5695->xvclk = devm_v4l2_sensor_clk_get_legacy(dev, "xvclk", true, + OV5695_XVCLK_FREQ); + if (IS_ERR(ov5695->xvclk)) + return dev_err_probe(dev, PTR_ERR(ov5695->xvclk), + "Failed to get xvclk\n"); + if (clk_get_rate(ov5695->xvclk) != OV5695_XVCLK_FREQ) dev_warn(dev, "xvclk mismatched, modes are based on 24MHz\n"); diff --git a/drivers/media/i2c/ov6211.c b/drivers/media/i2c/ov6211.c new file mode 100644 index 000000000000..e3ac5ecf27d1 --- /dev/null +++ b/drivers/media/i2c/ov6211.c @@ -0,0 +1,793 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (c) 2024-2025 Linaro Ltd + +#include <linux/clk.h> +#include <linux/delay.h> +#include <linux/gpio/consumer.h> +#include <linux/i2c.h> +#include <linux/module.h> +#include <linux/pm_runtime.h> +#include <linux/regulator/consumer.h> +#include <linux/units.h> +#include <media/v4l2-cci.h> +#include <media/v4l2-ctrls.h> +#include <media/v4l2-device.h> +#include <media/v4l2-fwnode.h> + +#define OV6211_LINK_FREQ_480MHZ (480 * HZ_PER_MHZ) +#define OV6211_MCLK_FREQ_24MHZ (24 * HZ_PER_MHZ) + +#define OV6211_REG_CHIP_ID CCI_REG16(0x300a) +#define OV6211_CHIP_ID 0x6710 + +#define OV6211_REG_MODE_SELECT CCI_REG8(0x0100) +#define OV6211_MODE_STANDBY 0x00 +#define OV6211_MODE_STREAMING BIT(0) + +#define OV6211_REG_SOFTWARE_RST CCI_REG8(0x0103) +#define OV6211_SOFTWARE_RST BIT(0) + +/* Exposure controls from sensor */ +#define OV6211_REG_EXPOSURE CCI_REG24(0x3500) +#define OV6211_EXPOSURE_MIN 1 +#define OV6211_EXPOSURE_MAX_MARGIN 4 +#define OV6211_EXPOSURE_STEP 1 +#define OV6211_EXPOSURE_DEFAULT 210 + +/* Analogue gain controls from sensor */ +#define OV6211_REG_ANALOGUE_GAIN CCI_REG16(0x350a) +#define OV6211_ANALOGUE_GAIN_MIN 1 +#define OV6211_ANALOGUE_GAIN_MAX 0x3ff +#define OV6211_ANALOGUE_GAIN_STEP 1 +#define OV6211_ANALOGUE_GAIN_DEFAULT 160 + +/* Test pattern */ +#define OV6211_REG_PRE_ISP CCI_REG8(0x5e00) +#define OV6211_TEST_PATTERN_ENABLE BIT(7) + +#define to_ov6211(_sd) container_of(_sd, struct ov6211, sd) + +static const s64 ov6211_link_freq_menu[] = { + OV6211_LINK_FREQ_480MHZ, +}; + +struct ov6211_reg_list { + const struct cci_reg_sequence *regs; + unsigned int num_regs; +}; + +struct ov6211_mode { + u32 width; /* Frame width in pixels */ + u32 height; /* Frame height in pixels */ + u32 hts; /* Horizontal timing size */ + u32 vts; /* Default vertical timing size */ + u32 bpp; /* Bits per pixel */ + + const struct ov6211_reg_list reg_list; /* Sensor register setting */ +}; + +static const char * const ov6211_test_pattern_menu[] = { + "Disabled", + "Vertical Colour Bars", +}; + +static const char * const ov6211_supply_names[] = { + "avdd", /* Analog power */ + "dovdd", /* Digital I/O power */ + "dvdd", /* Digital core power */ +}; + +#define OV6211_NUM_SUPPLIES ARRAY_SIZE(ov6211_supply_names) + +struct ov6211 { + struct device *dev; + struct regmap *regmap; + struct clk *xvclk; + struct gpio_desc *reset_gpio; + struct regulator_bulk_data supplies[OV6211_NUM_SUPPLIES]; + + struct v4l2_subdev sd; + struct media_pad pad; + + struct v4l2_ctrl_handler ctrl_handler; + + /* Saved register values */ + u64 pre_isp; +}; + +static const struct cci_reg_sequence ov6211_400x400_120fps_mode[] = { + { CCI_REG8(0x3005), 0x00 }, + { CCI_REG8(0x3013), 0x12 }, + { CCI_REG8(0x3014), 0x04 }, + { CCI_REG8(0x3016), 0x10 }, + { CCI_REG8(0x3017), 0x00 }, + { CCI_REG8(0x3018), 0x00 }, + { CCI_REG8(0x301a), 0x00 }, + { CCI_REG8(0x301b), 0x00 }, + { CCI_REG8(0x301c), 0x00 }, + { CCI_REG8(0x3037), 0xf0 }, + { CCI_REG8(0x3080), 0x01 }, + { CCI_REG8(0x3081), 0x00 }, + { CCI_REG8(0x3082), 0x01 }, + { CCI_REG8(0x3098), 0x04 }, + { CCI_REG8(0x3099), 0x28 }, + { CCI_REG8(0x309a), 0x06 }, + { CCI_REG8(0x309b), 0x04 }, + { CCI_REG8(0x309c), 0x00 }, + { CCI_REG8(0x309d), 0x00 }, + { CCI_REG8(0x309e), 0x01 }, + { CCI_REG8(0x309f), 0x00 }, + { CCI_REG8(0x30b0), 0x08 }, + { CCI_REG8(0x30b1), 0x02 }, + { CCI_REG8(0x30b2), 0x00 }, + { CCI_REG8(0x30b3), 0x28 }, + { CCI_REG8(0x30b4), 0x02 }, + { CCI_REG8(0x30b5), 0x00 }, + { CCI_REG8(0x3106), 0xd9 }, + { CCI_REG8(0x3503), 0x07 }, + { CCI_REG8(0x3509), 0x10 }, + { CCI_REG8(0x3600), 0xfc }, + { CCI_REG8(0x3620), 0xb7 }, + { CCI_REG8(0x3621), 0x05 }, + { CCI_REG8(0x3626), 0x31 }, + { CCI_REG8(0x3627), 0x40 }, + { CCI_REG8(0x3632), 0xa3 }, + { CCI_REG8(0x3633), 0x34 }, + { CCI_REG8(0x3634), 0x40 }, + { CCI_REG8(0x3636), 0x00 }, + { CCI_REG8(0x3660), 0x80 }, + { CCI_REG8(0x3662), 0x03 }, + { CCI_REG8(0x3664), 0xf0 }, + { CCI_REG8(0x366a), 0x10 }, + { CCI_REG8(0x366b), 0x06 }, + { CCI_REG8(0x3680), 0xf4 }, + { CCI_REG8(0x3681), 0x50 }, + { CCI_REG8(0x3682), 0x00 }, + { CCI_REG8(0x3708), 0x20 }, + { CCI_REG8(0x3709), 0x40 }, + { CCI_REG8(0x370d), 0x03 }, + { CCI_REG8(0x373b), 0x02 }, + { CCI_REG8(0x373c), 0x08 }, + { CCI_REG8(0x3742), 0x00 }, + { CCI_REG8(0x3744), 0x16 }, + { CCI_REG8(0x3745), 0x08 }, + { CCI_REG8(0x3781), 0xfc }, + { CCI_REG8(0x3788), 0x00 }, + { CCI_REG8(0x3800), 0x00 }, + { CCI_REG8(0x3801), 0x04 }, + { CCI_REG8(0x3802), 0x00 }, + { CCI_REG8(0x3803), 0x04 }, + { CCI_REG8(0x3804), 0x01 }, + { CCI_REG8(0x3805), 0x9b }, + { CCI_REG8(0x3806), 0x01 }, + { CCI_REG8(0x3807), 0x9b }, + { CCI_REG8(0x3808), 0x01 }, /* output width */ + { CCI_REG8(0x3809), 0x90 }, + { CCI_REG8(0x380a), 0x01 }, /* output height */ + { CCI_REG8(0x380b), 0x90 }, + { CCI_REG8(0x380c), 0x05 }, /* horizontal timing size */ + { CCI_REG8(0x380d), 0xf2 }, + { CCI_REG8(0x380e), 0x01 }, /* vertical timing size */ + { CCI_REG8(0x380f), 0xb6 }, + { CCI_REG8(0x3810), 0x00 }, + { CCI_REG8(0x3811), 0x04 }, + { CCI_REG8(0x3812), 0x00 }, + { CCI_REG8(0x3813), 0x04 }, + { CCI_REG8(0x3814), 0x11 }, + { CCI_REG8(0x3815), 0x11 }, + { CCI_REG8(0x3820), 0x00 }, + { CCI_REG8(0x3821), 0x00 }, + { CCI_REG8(0x382b), 0xfa }, + { CCI_REG8(0x382f), 0x04 }, + { CCI_REG8(0x3832), 0x00 }, + { CCI_REG8(0x3833), 0x05 }, + { CCI_REG8(0x3834), 0x00 }, + { CCI_REG8(0x3835), 0x05 }, + { CCI_REG8(0x3882), 0x04 }, + { CCI_REG8(0x3883), 0x00 }, + { CCI_REG8(0x38a4), 0x10 }, + { CCI_REG8(0x38a5), 0x00 }, + { CCI_REG8(0x38b1), 0x03 }, + { CCI_REG8(0x3b80), 0x00 }, + { CCI_REG8(0x3b81), 0xff }, + { CCI_REG8(0x3b82), 0x10 }, + { CCI_REG8(0x3b83), 0x00 }, + { CCI_REG8(0x3b84), 0x08 }, + { CCI_REG8(0x3b85), 0x00 }, + { CCI_REG8(0x3b86), 0x01 }, + { CCI_REG8(0x3b87), 0x00 }, + { CCI_REG8(0x3b88), 0x00 }, + { CCI_REG8(0x3b89), 0x00 }, + { CCI_REG8(0x3b8a), 0x00 }, + { CCI_REG8(0x3b8b), 0x05 }, + { CCI_REG8(0x3b8c), 0x00 }, + { CCI_REG8(0x3b8d), 0x00 }, + { CCI_REG8(0x3b8e), 0x01 }, + { CCI_REG8(0x3b8f), 0xb2 }, + { CCI_REG8(0x3b94), 0x05 }, + { CCI_REG8(0x3b95), 0xf2 }, + { CCI_REG8(0x3b96), 0xc0 }, + { CCI_REG8(0x4004), 0x04 }, + { CCI_REG8(0x404e), 0x01 }, + { CCI_REG8(0x4801), 0x0f }, + { CCI_REG8(0x4806), 0x0f }, + { CCI_REG8(0x4837), 0x43 }, + { CCI_REG8(0x5a08), 0x00 }, + { CCI_REG8(0x5a01), 0x00 }, + { CCI_REG8(0x5a03), 0x00 }, + { CCI_REG8(0x5a04), 0x10 }, + { CCI_REG8(0x5a05), 0xa0 }, + { CCI_REG8(0x5a06), 0x0c }, + { CCI_REG8(0x5a07), 0x78 }, +}; + +static const struct ov6211_mode supported_modes[] = { + { + .width = 400, + .height = 400, + .hts = 1522, + .vts = 438, + .bpp = 8, + .reg_list = { + .regs = ov6211_400x400_120fps_mode, + .num_regs = ARRAY_SIZE(ov6211_400x400_120fps_mode), + }, + }, +}; + +static int ov6211_set_test_pattern(struct ov6211 *ov6211, u32 pattern) +{ + u64 val = ov6211->pre_isp; + + if (pattern) + val |= OV6211_TEST_PATTERN_ENABLE; + else + val &= ~OV6211_TEST_PATTERN_ENABLE; + + return cci_write(ov6211->regmap, OV6211_REG_PRE_ISP, val, NULL); +} + +static int ov6211_set_ctrl(struct v4l2_ctrl *ctrl) +{ + struct ov6211 *ov6211 = container_of(ctrl->handler, struct ov6211, + ctrl_handler); + int ret; + + /* V4L2 controls are applied, when sensor is powered up for streaming */ + if (!pm_runtime_get_if_active(ov6211->dev)) + return 0; + + switch (ctrl->id) { + case V4L2_CID_ANALOGUE_GAIN: + ret = cci_write(ov6211->regmap, OV6211_REG_ANALOGUE_GAIN, + ctrl->val, NULL); + break; + case V4L2_CID_EXPOSURE: + ret = cci_write(ov6211->regmap, OV6211_REG_EXPOSURE, + ctrl->val << 4, NULL); + break; + case V4L2_CID_TEST_PATTERN: + ret = ov6211_set_test_pattern(ov6211, ctrl->val); + break; + default: + ret = -EINVAL; + break; + } + + pm_runtime_put(ov6211->dev); + + return ret; +} + +static const struct v4l2_ctrl_ops ov6211_ctrl_ops = { + .s_ctrl = ov6211_set_ctrl, +}; + +static int ov6211_init_controls(struct ov6211 *ov6211) +{ + struct v4l2_ctrl_handler *ctrl_hdlr = &ov6211->ctrl_handler; + const struct ov6211_mode *mode = &supported_modes[0]; + struct v4l2_fwnode_device_properties props; + s64 exposure_max, pixel_rate, h_blank; + struct v4l2_ctrl *ctrl; + int ret; + + v4l2_ctrl_handler_init(ctrl_hdlr, 9); + + ctrl = v4l2_ctrl_new_int_menu(ctrl_hdlr, &ov6211_ctrl_ops, + V4L2_CID_LINK_FREQ, + ARRAY_SIZE(ov6211_link_freq_menu) - 1, + 0, ov6211_link_freq_menu); + if (ctrl) + ctrl->flags |= V4L2_CTRL_FLAG_READ_ONLY; + + pixel_rate = ov6211_link_freq_menu[0] / mode->bpp; + v4l2_ctrl_new_std(ctrl_hdlr, &ov6211_ctrl_ops, V4L2_CID_PIXEL_RATE, + 0, pixel_rate, 1, pixel_rate); + + h_blank = mode->hts - mode->width; + ctrl = v4l2_ctrl_new_std(ctrl_hdlr, &ov6211_ctrl_ops, V4L2_CID_HBLANK, + h_blank, h_blank, 1, h_blank); + if (ctrl) + ctrl->flags |= V4L2_CTRL_FLAG_READ_ONLY; + + ctrl = v4l2_ctrl_new_std(ctrl_hdlr, &ov6211_ctrl_ops, V4L2_CID_VBLANK, + mode->vts - mode->height, + mode->vts - mode->height, 1, + mode->vts - mode->height); + if (ctrl) + ctrl->flags |= V4L2_CTRL_FLAG_READ_ONLY; + + v4l2_ctrl_new_std(ctrl_hdlr, &ov6211_ctrl_ops, V4L2_CID_ANALOGUE_GAIN, + OV6211_ANALOGUE_GAIN_MIN, OV6211_ANALOGUE_GAIN_MAX, + OV6211_ANALOGUE_GAIN_STEP, + OV6211_ANALOGUE_GAIN_DEFAULT); + + exposure_max = (mode->vts - OV6211_EXPOSURE_MAX_MARGIN); + v4l2_ctrl_new_std(ctrl_hdlr, &ov6211_ctrl_ops, + V4L2_CID_EXPOSURE, + OV6211_EXPOSURE_MIN, exposure_max, + OV6211_EXPOSURE_STEP, + OV6211_EXPOSURE_DEFAULT); + + v4l2_ctrl_new_std_menu_items(ctrl_hdlr, &ov6211_ctrl_ops, + V4L2_CID_TEST_PATTERN, + ARRAY_SIZE(ov6211_test_pattern_menu) - 1, + 0, 0, ov6211_test_pattern_menu); + + if (ctrl_hdlr->error) + return ctrl_hdlr->error; + + ret = v4l2_fwnode_device_parse(ov6211->dev, &props); + if (ret) + goto error_free_hdlr; + + ret = v4l2_ctrl_new_fwnode_properties(ctrl_hdlr, &ov6211_ctrl_ops, + &props); + if (ret) + goto error_free_hdlr; + + ov6211->sd.ctrl_handler = ctrl_hdlr; + + return 0; + +error_free_hdlr: + v4l2_ctrl_handler_free(ctrl_hdlr); + + return ret; +} + +static void ov6211_update_pad_format(const struct ov6211_mode *mode, + struct v4l2_mbus_framefmt *fmt) +{ + fmt->code = MEDIA_BUS_FMT_Y8_1X8; + fmt->width = mode->width; + fmt->height = mode->height; + fmt->field = V4L2_FIELD_NONE; + fmt->colorspace = V4L2_COLORSPACE_RAW; + fmt->ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT; + fmt->quantization = V4L2_QUANTIZATION_FULL_RANGE; + fmt->xfer_func = V4L2_XFER_FUNC_NONE; +} + +static int ov6211_enable_streams(struct v4l2_subdev *sd, + struct v4l2_subdev_state *state, u32 pad, + u64 streams_mask) +{ + const struct ov6211_reg_list *reg_list = &supported_modes[0].reg_list; + struct ov6211 *ov6211 = to_ov6211(sd); + int ret; + + ret = pm_runtime_resume_and_get(ov6211->dev); + if (ret) + return ret; + + /* Skip a step of explicit entering into the standby mode */ + ret = cci_write(ov6211->regmap, OV6211_REG_SOFTWARE_RST, + OV6211_SOFTWARE_RST, NULL); + if (ret) { + dev_err(ov6211->dev, "failed to software reset: %d\n", ret); + goto error; + } + + ret = cci_multi_reg_write(ov6211->regmap, reg_list->regs, + reg_list->num_regs, NULL); + if (ret) { + dev_err(ov6211->dev, "failed to set mode: %d\n", ret); + goto error; + } + + ret = __v4l2_ctrl_handler_setup(ov6211->sd.ctrl_handler); + if (ret) + goto error; + + ret = cci_write(ov6211->regmap, OV6211_REG_MODE_SELECT, + OV6211_MODE_STREAMING, NULL); + if (ret) { + dev_err(ov6211->dev, "failed to start streaming: %d\n", ret); + goto error; + } + + return 0; + +error: + pm_runtime_put_autosuspend(ov6211->dev); + + return ret; +} + +static int ov6211_disable_streams(struct v4l2_subdev *sd, + struct v4l2_subdev_state *state, u32 pad, + u64 streams_mask) +{ + struct ov6211 *ov6211 = to_ov6211(sd); + int ret; + + ret = cci_write(ov6211->regmap, OV6211_REG_MODE_SELECT, + OV6211_MODE_STANDBY, NULL); + if (ret) + dev_err(ov6211->dev, "failed to stop streaming: %d\n", ret); + + pm_runtime_put_autosuspend(ov6211->dev); + + return ret; +} + +static int ov6211_set_pad_format(struct v4l2_subdev *sd, + struct v4l2_subdev_state *state, + struct v4l2_subdev_format *fmt) +{ + struct v4l2_mbus_framefmt *format; + const struct ov6211_mode *mode; + + format = v4l2_subdev_state_get_format(state, 0); + + mode = v4l2_find_nearest_size(supported_modes, + ARRAY_SIZE(supported_modes), + width, height, + fmt->format.width, + fmt->format.height); + + ov6211_update_pad_format(mode, &fmt->format); + *format = fmt->format; + + return 0; +} + +static int ov6211_enum_mbus_code(struct v4l2_subdev *sd, + struct v4l2_subdev_state *sd_state, + struct v4l2_subdev_mbus_code_enum *code) +{ + if (code->index > 0) + return -EINVAL; + + code->code = MEDIA_BUS_FMT_Y8_1X8; + + return 0; +} + +static int ov6211_enum_frame_size(struct v4l2_subdev *sd, + struct v4l2_subdev_state *sd_state, + struct v4l2_subdev_frame_size_enum *fse) +{ + if (fse->index >= ARRAY_SIZE(supported_modes)) + return -EINVAL; + + if (fse->code != MEDIA_BUS_FMT_Y8_1X8) + return -EINVAL; + + fse->min_width = supported_modes[fse->index].width; + fse->max_width = fse->min_width; + fse->min_height = supported_modes[fse->index].height; + fse->max_height = fse->min_height; + + return 0; +} + +static int ov6211_init_state(struct v4l2_subdev *sd, + struct v4l2_subdev_state *state) +{ + struct v4l2_subdev_format fmt = { + .which = V4L2_SUBDEV_FORMAT_TRY, + .pad = 0, + .format = { + .code = MEDIA_BUS_FMT_Y8_1X8, + .width = supported_modes[0].width, + .height = supported_modes[0].height, + }, + }; + + ov6211_set_pad_format(sd, state, &fmt); + + return 0; +} + +static const struct v4l2_subdev_video_ops ov6211_video_ops = { + .s_stream = v4l2_subdev_s_stream_helper, +}; + +static const struct v4l2_subdev_pad_ops ov6211_pad_ops = { + .set_fmt = ov6211_set_pad_format, + .get_fmt = v4l2_subdev_get_fmt, + .enum_mbus_code = ov6211_enum_mbus_code, + .enum_frame_size = ov6211_enum_frame_size, + .enable_streams = ov6211_enable_streams, + .disable_streams = ov6211_disable_streams, +}; + +static const struct v4l2_subdev_ops ov6211_subdev_ops = { + .video = &ov6211_video_ops, + .pad = &ov6211_pad_ops, +}; + +static const struct v4l2_subdev_internal_ops ov6211_internal_ops = { + .init_state = ov6211_init_state, +}; + +static const struct media_entity_operations ov6211_subdev_entity_ops = { + .link_validate = v4l2_subdev_link_validate, +}; + +static int ov6211_identify_sensor(struct ov6211 *ov6211) +{ + u64 val; + int ret; + + ret = cci_read(ov6211->regmap, OV6211_REG_CHIP_ID, &val, NULL); + if (ret) { + dev_err(ov6211->dev, "failed to read chip id: %d\n", ret); + return ret; + } + + if (val != OV6211_CHIP_ID) { + dev_err(ov6211->dev, "chip id mismatch: %x!=%llx\n", + OV6211_CHIP_ID, val); + return -ENODEV; + } + + ret = cci_read(ov6211->regmap, OV6211_REG_PRE_ISP, + &ov6211->pre_isp, NULL); + if (ret) + dev_err(ov6211->dev, "failed to read pre_isp: %d\n", ret); + + return ret; +} + +static int ov6211_check_hwcfg(struct ov6211 *ov6211) +{ + struct fwnode_handle *fwnode = dev_fwnode(ov6211->dev), *ep; + struct v4l2_fwnode_endpoint bus_cfg = { + .bus_type = V4L2_MBUS_CSI2_DPHY, + }; + unsigned long freq_bitmap; + int ret; + + if (!fwnode) + return -ENODEV; + + ep = fwnode_graph_get_next_endpoint(fwnode, NULL); + if (!ep) + return -EINVAL; + + ret = v4l2_fwnode_endpoint_alloc_parse(ep, &bus_cfg); + fwnode_handle_put(ep); + if (ret) + return ret; + + ret = v4l2_link_freq_to_bitmap(ov6211->dev, bus_cfg.link_frequencies, + bus_cfg.nr_of_link_frequencies, + ov6211_link_freq_menu, + ARRAY_SIZE(ov6211_link_freq_menu), + &freq_bitmap); + + v4l2_fwnode_endpoint_free(&bus_cfg); + + return ret; +} + +static int ov6211_power_on(struct device *dev) +{ + struct v4l2_subdev *sd = dev_get_drvdata(dev); + struct ov6211 *ov6211 = to_ov6211(sd); + int ret; + + ret = regulator_bulk_enable(OV6211_NUM_SUPPLIES, ov6211->supplies); + if (ret) + return ret; + + gpiod_set_value_cansleep(ov6211->reset_gpio, 0); + usleep_range(10 * USEC_PER_MSEC, 15 * USEC_PER_MSEC); + + ret = clk_prepare_enable(ov6211->xvclk); + if (ret) + goto reset_gpio; + + return 0; + +reset_gpio: + gpiod_set_value_cansleep(ov6211->reset_gpio, 1); + + regulator_bulk_disable(OV6211_NUM_SUPPLIES, ov6211->supplies); + + return ret; +} + +static int ov6211_power_off(struct device *dev) +{ + struct v4l2_subdev *sd = dev_get_drvdata(dev); + struct ov6211 *ov6211 = to_ov6211(sd); + + clk_disable_unprepare(ov6211->xvclk); + + gpiod_set_value_cansleep(ov6211->reset_gpio, 1); + + regulator_bulk_disable(OV6211_NUM_SUPPLIES, ov6211->supplies); + + return 0; +} + +static int ov6211_probe(struct i2c_client *client) +{ + struct ov6211 *ov6211; + unsigned long freq; + unsigned int i; + int ret; + + ov6211 = devm_kzalloc(&client->dev, sizeof(*ov6211), GFP_KERNEL); + if (!ov6211) + return -ENOMEM; + + ov6211->dev = &client->dev; + + v4l2_i2c_subdev_init(&ov6211->sd, client, &ov6211_subdev_ops); + + ov6211->regmap = devm_cci_regmap_init_i2c(client, 16); + if (IS_ERR(ov6211->regmap)) + return dev_err_probe(ov6211->dev, PTR_ERR(ov6211->regmap), + "failed to init CCI\n"); + + ov6211->xvclk = devm_v4l2_sensor_clk_get(ov6211->dev, NULL); + if (IS_ERR(ov6211->xvclk)) + return dev_err_probe(ov6211->dev, PTR_ERR(ov6211->xvclk), + "failed to get XVCLK clock\n"); + + freq = clk_get_rate(ov6211->xvclk); + if (freq && freq != OV6211_MCLK_FREQ_24MHZ) + return dev_err_probe(ov6211->dev, -EINVAL, + "XVCLK clock frequency %lu is not supported\n", + freq); + + ret = ov6211_check_hwcfg(ov6211); + if (ret) + return dev_err_probe(ov6211->dev, ret, + "failed to check HW configuration\n"); + + ov6211->reset_gpio = devm_gpiod_get_optional(ov6211->dev, "reset", + GPIOD_OUT_HIGH); + if (IS_ERR(ov6211->reset_gpio)) + return dev_err_probe(ov6211->dev, PTR_ERR(ov6211->reset_gpio), + "cannot get reset GPIO\n"); + + for (i = 0; i < OV6211_NUM_SUPPLIES; i++) + ov6211->supplies[i].supply = ov6211_supply_names[i]; + + ret = devm_regulator_bulk_get(ov6211->dev, OV6211_NUM_SUPPLIES, + ov6211->supplies); + if (ret) + return dev_err_probe(ov6211->dev, ret, + "failed to get supply regulators\n"); + + /* The sensor must be powered on to read the CHIP_ID register */ + ret = ov6211_power_on(ov6211->dev); + if (ret) + return ret; + + ret = ov6211_identify_sensor(ov6211); + if (ret) { + dev_err_probe(ov6211->dev, ret, "failed to find sensor\n"); + goto power_off; + } + + ret = ov6211_init_controls(ov6211); + if (ret) { + dev_err_probe(ov6211->dev, ret, "failed to init controls\n"); + goto power_off; + } + + ov6211->sd.state_lock = ov6211->ctrl_handler.lock; + ov6211->sd.internal_ops = &ov6211_internal_ops; + ov6211->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; + ov6211->sd.entity.ops = &ov6211_subdev_entity_ops; + ov6211->sd.entity.function = MEDIA_ENT_F_CAM_SENSOR; + ov6211->pad.flags = MEDIA_PAD_FL_SOURCE; + + ret = media_entity_pads_init(&ov6211->sd.entity, 1, &ov6211->pad); + if (ret) { + dev_err_probe(ov6211->dev, ret, + "failed to init media entity pads\n"); + goto v4l2_ctrl_handler_free; + } + + ret = v4l2_subdev_init_finalize(&ov6211->sd); + if (ret < 0) { + dev_err_probe(ov6211->dev, ret, + "failed to init media entity pads\n"); + goto media_entity_cleanup; + } + + pm_runtime_set_active(ov6211->dev); + pm_runtime_enable(ov6211->dev); + + ret = v4l2_async_register_subdev_sensor(&ov6211->sd); + if (ret < 0) { + dev_err_probe(ov6211->dev, ret, + "failed to register V4L2 subdev\n"); + goto subdev_cleanup; + } + + /* Enable runtime PM and turn off the device */ + pm_runtime_idle(ov6211->dev); + pm_runtime_set_autosuspend_delay(ov6211->dev, 1000); + pm_runtime_use_autosuspend(ov6211->dev); + + return 0; + +subdev_cleanup: + v4l2_subdev_cleanup(&ov6211->sd); + pm_runtime_disable(ov6211->dev); + pm_runtime_set_suspended(ov6211->dev); + +media_entity_cleanup: + media_entity_cleanup(&ov6211->sd.entity); + +v4l2_ctrl_handler_free: + v4l2_ctrl_handler_free(ov6211->sd.ctrl_handler); + +power_off: + ov6211_power_off(ov6211->dev); + + return ret; +} + +static void ov6211_remove(struct i2c_client *client) +{ + struct v4l2_subdev *sd = i2c_get_clientdata(client); + struct ov6211 *ov6211 = to_ov6211(sd); + + v4l2_async_unregister_subdev(sd); + v4l2_subdev_cleanup(sd); + media_entity_cleanup(&sd->entity); + v4l2_ctrl_handler_free(sd->ctrl_handler); + pm_runtime_disable(ov6211->dev); + + if (!pm_runtime_status_suspended(ov6211->dev)) { + ov6211_power_off(ov6211->dev); + pm_runtime_set_suspended(ov6211->dev); + } +} + +static const struct dev_pm_ops ov6211_pm_ops = { + SET_RUNTIME_PM_OPS(ov6211_power_off, ov6211_power_on, NULL) +}; + +static const struct of_device_id ov6211_of_match[] = { + { .compatible = "ovti,ov6211" }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, ov6211_of_match); + +static struct i2c_driver ov6211_i2c_driver = { + .driver = { + .name = "ov6211", + .pm = &ov6211_pm_ops, + .of_match_table = ov6211_of_match, + }, + .probe = ov6211_probe, + .remove = ov6211_remove, +}; + +module_i2c_driver(ov6211_i2c_driver); + +MODULE_AUTHOR("Vladimir Zapolskiy <vladimir.zapolskiy@linaro.org>"); +MODULE_DESCRIPTION("OmniVision OV6211 sensor driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/media/i2c/ov64a40.c b/drivers/media/i2c/ov64a40.c index 2031cbd05c26..78b62c169b99 100644 --- a/drivers/media/i2c/ov64a40.c +++ b/drivers/media/i2c/ov64a40.c @@ -3546,7 +3546,7 @@ static int ov64a40_probe(struct i2c_client *client) return PTR_ERR(ov64a40->cci); } - ov64a40->xclk = devm_clk_get(&client->dev, NULL); + ov64a40->xclk = devm_v4l2_sensor_clk_get(&client->dev, NULL); if (IS_ERR(ov64a40->xclk)) return dev_err_probe(&client->dev, PTR_ERR(ov64a40->xclk), "Failed to get clock\n"); diff --git a/drivers/media/i2c/ov6650.c b/drivers/media/i2c/ov6650.c deleted file mode 100644 index 9c7627161142..000000000000 --- a/drivers/media/i2c/ov6650.c +++ /dev/null @@ -1,1149 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * V4L2 subdevice driver for OmniVision OV6650 Camera Sensor - * - * Copyright (C) 2010 Janusz Krzysztofik <jkrzyszt@tis.icnet.pl> - * - * Based on OmniVision OV96xx Camera Driver - * Copyright (C) 2009 Marek Vasut <marek.vasut@gmail.com> - * - * Based on ov772x camera driver: - * Copyright (C) 2008 Renesas Solutions Corp. - * Kuninori Morimoto <morimoto.kuninori@renesas.com> - * - * Based on ov7670 and soc_camera_platform driver, - * Copyright 2006-7 Jonathan Corbet <corbet@lwn.net> - * Copyright (C) 2008 Magnus Damm - * Copyright (C) 2008, Guennadi Liakhovetski <kernel@pengutronix.de> - * - * Hardware specific bits initially based on former work by Matt Callow - * drivers/media/video/omap/sensor_ov6650.c - * Copyright (C) 2006 Matt Callow - */ - -#include <linux/bitops.h> -#include <linux/clk.h> -#include <linux/delay.h> -#include <linux/i2c.h> -#include <linux/slab.h> -#include <linux/v4l2-mediabus.h> -#include <linux/module.h> - -#include <media/v4l2-ctrls.h> -#include <media/v4l2-device.h> - -/* Register definitions */ -#define REG_GAIN 0x00 /* range 00 - 3F */ -#define REG_BLUE 0x01 -#define REG_RED 0x02 -#define REG_SAT 0x03 /* [7:4] saturation [0:3] reserved */ -#define REG_HUE 0x04 /* [7:6] rsrvd [5] hue en [4:0] hue */ - -#define REG_BRT 0x06 - -#define REG_PIDH 0x0a -#define REG_PIDL 0x0b - -#define REG_AECH 0x10 -#define REG_CLKRC 0x11 /* Data Format and Internal Clock */ - /* [7:6] Input system clock (MHz)*/ - /* 00=8, 01=12, 10=16, 11=24 */ - /* [5:0]: Internal Clock Pre-Scaler */ -#define REG_COMA 0x12 /* [7] Reset */ -#define REG_COMB 0x13 -#define REG_COMC 0x14 -#define REG_COMD 0x15 -#define REG_COML 0x16 -#define REG_HSTRT 0x17 -#define REG_HSTOP 0x18 -#define REG_VSTRT 0x19 -#define REG_VSTOP 0x1a -#define REG_PSHFT 0x1b -#define REG_MIDH 0x1c -#define REG_MIDL 0x1d -#define REG_HSYNS 0x1e -#define REG_HSYNE 0x1f -#define REG_COME 0x20 -#define REG_YOFF 0x21 -#define REG_UOFF 0x22 -#define REG_VOFF 0x23 -#define REG_AEW 0x24 -#define REG_AEB 0x25 -#define REG_COMF 0x26 -#define REG_COMG 0x27 -#define REG_COMH 0x28 -#define REG_COMI 0x29 - -#define REG_FRARL 0x2b -#define REG_COMJ 0x2c -#define REG_COMK 0x2d -#define REG_AVGY 0x2e -#define REG_REF0 0x2f -#define REG_REF1 0x30 -#define REG_REF2 0x31 -#define REG_FRAJH 0x32 -#define REG_FRAJL 0x33 -#define REG_FACT 0x34 -#define REG_L1AEC 0x35 -#define REG_AVGU 0x36 -#define REG_AVGV 0x37 - -#define REG_SPCB 0x60 -#define REG_SPCC 0x61 -#define REG_GAM1 0x62 -#define REG_GAM2 0x63 -#define REG_GAM3 0x64 -#define REG_SPCD 0x65 - -#define REG_SPCE 0x68 -#define REG_ADCL 0x69 - -#define REG_RMCO 0x6c -#define REG_GMCO 0x6d -#define REG_BMCO 0x6e - - -/* Register bits, values, etc. */ -#define OV6650_PIDH 0x66 /* high byte of product ID number */ -#define OV6650_PIDL 0x50 /* low byte of product ID number */ -#define OV6650_MIDH 0x7F /* high byte of mfg ID */ -#define OV6650_MIDL 0xA2 /* low byte of mfg ID */ - -#define DEF_GAIN 0x00 -#define DEF_BLUE 0x80 -#define DEF_RED 0x80 - -#define SAT_SHIFT 4 -#define SAT_MASK (0xf << SAT_SHIFT) -#define SET_SAT(x) (((x) << SAT_SHIFT) & SAT_MASK) - -#define HUE_EN BIT(5) -#define HUE_MASK 0x1f -#define DEF_HUE 0x10 -#define SET_HUE(x) (HUE_EN | ((x) & HUE_MASK)) - -#define DEF_AECH 0x4D - -#define CLKRC_8MHz 0x00 -#define CLKRC_12MHz 0x40 -#define CLKRC_16MHz 0x80 -#define CLKRC_24MHz 0xc0 -#define CLKRC_DIV_MASK 0x3f -#define GET_CLKRC_DIV(x) (((x) & CLKRC_DIV_MASK) + 1) -#define DEF_CLKRC 0x00 - -#define COMA_RESET BIT(7) -#define COMA_QCIF BIT(5) -#define COMA_RAW_RGB BIT(4) -#define COMA_RGB BIT(3) -#define COMA_BW BIT(2) -#define COMA_WORD_SWAP BIT(1) -#define COMA_BYTE_SWAP BIT(0) -#define DEF_COMA 0x00 - -#define COMB_FLIP_V BIT(7) -#define COMB_FLIP_H BIT(5) -#define COMB_BAND_FILTER BIT(4) -#define COMB_AWB BIT(2) -#define COMB_AGC BIT(1) -#define COMB_AEC BIT(0) -#define DEF_COMB 0x5f - -#define COML_ONE_CHANNEL BIT(7) - -#define DEF_HSTRT 0x24 -#define DEF_HSTOP 0xd4 -#define DEF_VSTRT 0x04 -#define DEF_VSTOP 0x94 - -#define COMF_HREF_LOW BIT(4) - -#define COMJ_PCLK_RISING BIT(4) -#define COMJ_VSYNC_HIGH BIT(0) - -/* supported resolutions */ -#define W_QCIF (DEF_HSTOP - DEF_HSTRT) -#define W_CIF (W_QCIF << 1) -#define H_QCIF (DEF_VSTOP - DEF_VSTRT) -#define H_CIF (H_QCIF << 1) - -#define FRAME_RATE_MAX 30 - - -struct ov6650_reg { - u8 reg; - u8 val; -}; - -struct ov6650 { - struct v4l2_subdev subdev; - struct v4l2_ctrl_handler hdl; - struct { - /* exposure/autoexposure cluster */ - struct v4l2_ctrl *autoexposure; - struct v4l2_ctrl *exposure; - }; - struct { - /* gain/autogain cluster */ - struct v4l2_ctrl *autogain; - struct v4l2_ctrl *gain; - }; - struct { - /* blue/red/autowhitebalance cluster */ - struct v4l2_ctrl *autowb; - struct v4l2_ctrl *blue; - struct v4l2_ctrl *red; - }; - struct clk *clk; - bool half_scale; /* scale down output by 2 */ - struct v4l2_rect rect; /* sensor cropping window */ - struct v4l2_fract tpf; /* as requested with set_frame_interval */ - u32 code; -}; - -struct ov6650_xclk { - unsigned long rate; - u8 clkrc; -}; - -static const struct ov6650_xclk ov6650_xclk[] = { -{ - .rate = 8000000, - .clkrc = CLKRC_8MHz, -}, -{ - .rate = 12000000, - .clkrc = CLKRC_12MHz, -}, -{ - .rate = 16000000, - .clkrc = CLKRC_16MHz, -}, -{ - .rate = 24000000, - .clkrc = CLKRC_24MHz, -}, -}; - -static u32 ov6650_codes[] = { - MEDIA_BUS_FMT_YUYV8_2X8, - MEDIA_BUS_FMT_UYVY8_2X8, - MEDIA_BUS_FMT_YVYU8_2X8, - MEDIA_BUS_FMT_VYUY8_2X8, - MEDIA_BUS_FMT_SBGGR8_1X8, - MEDIA_BUS_FMT_Y8_1X8, -}; - -static const struct v4l2_mbus_framefmt ov6650_def_fmt = { - .width = W_CIF, - .height = H_CIF, - .code = MEDIA_BUS_FMT_SBGGR8_1X8, - .colorspace = V4L2_COLORSPACE_SRGB, - .field = V4L2_FIELD_NONE, - .ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT, - .quantization = V4L2_QUANTIZATION_DEFAULT, - .xfer_func = V4L2_XFER_FUNC_DEFAULT, -}; - -/* read a register */ -static int ov6650_reg_read(struct i2c_client *client, u8 reg, u8 *val) -{ - int ret; - u8 data = reg; - struct i2c_msg msg = { - .addr = client->addr, - .flags = 0, - .len = 1, - .buf = &data, - }; - - ret = i2c_transfer(client->adapter, &msg, 1); - if (ret < 0) - goto err; - - msg.flags = I2C_M_RD; - ret = i2c_transfer(client->adapter, &msg, 1); - if (ret < 0) - goto err; - - *val = data; - return 0; - -err: - dev_err(&client->dev, "Failed reading register 0x%02x!\n", reg); - return ret; -} - -/* write a register */ -static int ov6650_reg_write(struct i2c_client *client, u8 reg, u8 val) -{ - int ret; - unsigned char data[2] = { reg, val }; - struct i2c_msg msg = { - .addr = client->addr, - .flags = 0, - .len = 2, - .buf = data, - }; - - ret = i2c_transfer(client->adapter, &msg, 1); - udelay(100); - - if (ret < 0) { - dev_err(&client->dev, "Failed writing register 0x%02x!\n", reg); - return ret; - } - return 0; -} - - -/* Read a register, alter its bits, write it back */ -static int ov6650_reg_rmw(struct i2c_client *client, u8 reg, u8 set, u8 mask) -{ - u8 val; - int ret; - - ret = ov6650_reg_read(client, reg, &val); - if (ret) { - dev_err(&client->dev, - "[Read]-Modify-Write of register 0x%02x failed!\n", - reg); - return ret; - } - - val &= ~mask; - val |= set; - - ret = ov6650_reg_write(client, reg, val); - if (ret) - dev_err(&client->dev, - "Read-Modify-[Write] of register 0x%02x failed!\n", - reg); - - return ret; -} - -static struct ov6650 *to_ov6650(const struct i2c_client *client) -{ - return container_of(i2c_get_clientdata(client), struct ov6650, subdev); -} - -/* Start/Stop streaming from the device */ -static int ov6650_s_stream(struct v4l2_subdev *sd, int enable) -{ - return 0; -} - -/* Get status of additional camera capabilities */ -static int ov6550_g_volatile_ctrl(struct v4l2_ctrl *ctrl) -{ - struct ov6650 *priv = container_of(ctrl->handler, struct ov6650, hdl); - struct v4l2_subdev *sd = &priv->subdev; - struct i2c_client *client = v4l2_get_subdevdata(sd); - uint8_t reg, reg2; - int ret; - - switch (ctrl->id) { - case V4L2_CID_AUTOGAIN: - ret = ov6650_reg_read(client, REG_GAIN, ®); - if (!ret) - priv->gain->val = reg; - return ret; - case V4L2_CID_AUTO_WHITE_BALANCE: - ret = ov6650_reg_read(client, REG_BLUE, ®); - if (!ret) - ret = ov6650_reg_read(client, REG_RED, ®2); - if (!ret) { - priv->blue->val = reg; - priv->red->val = reg2; - } - return ret; - case V4L2_CID_EXPOSURE_AUTO: - ret = ov6650_reg_read(client, REG_AECH, ®); - if (!ret) - priv->exposure->val = reg; - return ret; - } - return -EINVAL; -} - -/* Set status of additional camera capabilities */ -static int ov6550_s_ctrl(struct v4l2_ctrl *ctrl) -{ - struct ov6650 *priv = container_of(ctrl->handler, struct ov6650, hdl); - struct v4l2_subdev *sd = &priv->subdev; - struct i2c_client *client = v4l2_get_subdevdata(sd); - int ret; - - switch (ctrl->id) { - case V4L2_CID_AUTOGAIN: - ret = ov6650_reg_rmw(client, REG_COMB, - ctrl->val ? COMB_AGC : 0, COMB_AGC); - if (!ret && !ctrl->val) - ret = ov6650_reg_write(client, REG_GAIN, priv->gain->val); - return ret; - case V4L2_CID_AUTO_WHITE_BALANCE: - ret = ov6650_reg_rmw(client, REG_COMB, - ctrl->val ? COMB_AWB : 0, COMB_AWB); - if (!ret && !ctrl->val) { - ret = ov6650_reg_write(client, REG_BLUE, priv->blue->val); - if (!ret) - ret = ov6650_reg_write(client, REG_RED, - priv->red->val); - } - return ret; - case V4L2_CID_SATURATION: - return ov6650_reg_rmw(client, REG_SAT, SET_SAT(ctrl->val), - SAT_MASK); - case V4L2_CID_HUE: - return ov6650_reg_rmw(client, REG_HUE, SET_HUE(ctrl->val), - HUE_MASK); - case V4L2_CID_BRIGHTNESS: - return ov6650_reg_write(client, REG_BRT, ctrl->val); - case V4L2_CID_EXPOSURE_AUTO: - ret = ov6650_reg_rmw(client, REG_COMB, ctrl->val == - V4L2_EXPOSURE_AUTO ? COMB_AEC : 0, COMB_AEC); - if (!ret && ctrl->val == V4L2_EXPOSURE_MANUAL) - ret = ov6650_reg_write(client, REG_AECH, - priv->exposure->val); - return ret; - case V4L2_CID_GAMMA: - return ov6650_reg_write(client, REG_GAM1, ctrl->val); - case V4L2_CID_VFLIP: - return ov6650_reg_rmw(client, REG_COMB, - ctrl->val ? COMB_FLIP_V : 0, COMB_FLIP_V); - case V4L2_CID_HFLIP: - return ov6650_reg_rmw(client, REG_COMB, - ctrl->val ? COMB_FLIP_H : 0, COMB_FLIP_H); - } - - return -EINVAL; -} - -#ifdef CONFIG_VIDEO_ADV_DEBUG -static int ov6650_get_register(struct v4l2_subdev *sd, - struct v4l2_dbg_register *reg) -{ - struct i2c_client *client = v4l2_get_subdevdata(sd); - int ret; - u8 val; - - if (reg->reg & ~0xff) - return -EINVAL; - - reg->size = 1; - - ret = ov6650_reg_read(client, reg->reg, &val); - if (!ret) - reg->val = (__u64)val; - - return ret; -} - -static int ov6650_set_register(struct v4l2_subdev *sd, - const struct v4l2_dbg_register *reg) -{ - struct i2c_client *client = v4l2_get_subdevdata(sd); - - if (reg->reg & ~0xff || reg->val & ~0xff) - return -EINVAL; - - return ov6650_reg_write(client, reg->reg, reg->val); -} -#endif - -static int ov6650_s_power(struct v4l2_subdev *sd, int on) -{ - struct i2c_client *client = v4l2_get_subdevdata(sd); - struct ov6650 *priv = to_ov6650(client); - int ret = 0; - - if (on) - ret = clk_prepare_enable(priv->clk); - else - clk_disable_unprepare(priv->clk); - - return ret; -} - -static int ov6650_get_selection(struct v4l2_subdev *sd, - struct v4l2_subdev_state *sd_state, - struct v4l2_subdev_selection *sel) -{ - struct i2c_client *client = v4l2_get_subdevdata(sd); - struct ov6650 *priv = to_ov6650(client); - struct v4l2_rect *rect; - - if (sel->which == V4L2_SUBDEV_FORMAT_TRY) { - /* pre-select try crop rectangle */ - rect = v4l2_subdev_state_get_crop(sd_state, 0); - - } else { - /* pre-select active crop rectangle */ - rect = &priv->rect; - } - - switch (sel->target) { - case V4L2_SEL_TGT_CROP_BOUNDS: - sel->r.left = DEF_HSTRT << 1; - sel->r.top = DEF_VSTRT << 1; - sel->r.width = W_CIF; - sel->r.height = H_CIF; - return 0; - - case V4L2_SEL_TGT_CROP: - /* use selected crop rectangle */ - sel->r = *rect; - return 0; - - default: - return -EINVAL; - } -} - -static bool is_unscaled_ok(int width, int height, struct v4l2_rect *rect) -{ - return width > rect->width >> 1 || height > rect->height >> 1; -} - -static void ov6650_bind_align_crop_rectangle(struct v4l2_rect *rect) -{ - v4l_bound_align_image(&rect->width, 2, W_CIF, 1, - &rect->height, 2, H_CIF, 1, 0); - v4l_bound_align_image(&rect->left, DEF_HSTRT << 1, - (DEF_HSTRT << 1) + W_CIF - (__s32)rect->width, 1, - &rect->top, DEF_VSTRT << 1, - (DEF_VSTRT << 1) + H_CIF - (__s32)rect->height, - 1, 0); -} - -static int ov6650_set_selection(struct v4l2_subdev *sd, - struct v4l2_subdev_state *sd_state, - struct v4l2_subdev_selection *sel) -{ - struct i2c_client *client = v4l2_get_subdevdata(sd); - struct ov6650 *priv = to_ov6650(client); - int ret; - - if (sel->target != V4L2_SEL_TGT_CROP) - return -EINVAL; - - ov6650_bind_align_crop_rectangle(&sel->r); - - if (sel->which == V4L2_SUBDEV_FORMAT_TRY) { - struct v4l2_rect *crop = - v4l2_subdev_state_get_crop(sd_state, 0); - struct v4l2_mbus_framefmt *mf = - v4l2_subdev_state_get_format(sd_state, 0); - /* detect current pad config scaling factor */ - bool half_scale = !is_unscaled_ok(mf->width, mf->height, crop); - - /* store new crop rectangle */ - *crop = sel->r; - - /* adjust frame size */ - mf->width = crop->width >> half_scale; - mf->height = crop->height >> half_scale; - - return 0; - } - - /* V4L2_SUBDEV_FORMAT_ACTIVE */ - - /* apply new crop rectangle */ - ret = ov6650_reg_write(client, REG_HSTRT, sel->r.left >> 1); - if (!ret) { - priv->rect.width += priv->rect.left - sel->r.left; - priv->rect.left = sel->r.left; - ret = ov6650_reg_write(client, REG_HSTOP, - (sel->r.left + sel->r.width) >> 1); - } - if (!ret) { - priv->rect.width = sel->r.width; - ret = ov6650_reg_write(client, REG_VSTRT, sel->r.top >> 1); - } - if (!ret) { - priv->rect.height += priv->rect.top - sel->r.top; - priv->rect.top = sel->r.top; - ret = ov6650_reg_write(client, REG_VSTOP, - (sel->r.top + sel->r.height) >> 1); - } - if (!ret) - priv->rect.height = sel->r.height; - - return ret; -} - -static int ov6650_get_fmt(struct v4l2_subdev *sd, - struct v4l2_subdev_state *sd_state, - struct v4l2_subdev_format *format) -{ - struct v4l2_mbus_framefmt *mf = &format->format; - struct i2c_client *client = v4l2_get_subdevdata(sd); - struct ov6650 *priv = to_ov6650(client); - - if (format->pad) - return -EINVAL; - - /* initialize response with default media bus frame format */ - *mf = ov6650_def_fmt; - - /* update media bus format code and frame size */ - if (format->which == V4L2_SUBDEV_FORMAT_TRY) { - struct v4l2_mbus_framefmt *try_fmt = - v4l2_subdev_state_get_format(sd_state, 0); - - mf->width = try_fmt->width; - mf->height = try_fmt->height; - mf->code = try_fmt->code; - - } else { - mf->width = priv->rect.width >> priv->half_scale; - mf->height = priv->rect.height >> priv->half_scale; - mf->code = priv->code; - } - return 0; -} - -#define to_clkrc(div) ((div) - 1) - -/* set the format we will capture in */ -static int ov6650_s_fmt(struct v4l2_subdev *sd, u32 code, bool half_scale) -{ - struct i2c_client *client = v4l2_get_subdevdata(sd); - struct ov6650 *priv = to_ov6650(client); - u8 coma_set = 0, coma_mask = 0, coml_set, coml_mask; - int ret; - - /* select color matrix configuration for given color encoding */ - switch (code) { - case MEDIA_BUS_FMT_Y8_1X8: - dev_dbg(&client->dev, "pixel format GREY8_1X8\n"); - coma_mask |= COMA_RGB | COMA_WORD_SWAP | COMA_BYTE_SWAP; - coma_set |= COMA_BW; - break; - case MEDIA_BUS_FMT_YUYV8_2X8: - dev_dbg(&client->dev, "pixel format YUYV8_2X8_LE\n"); - coma_mask |= COMA_RGB | COMA_BW | COMA_BYTE_SWAP; - coma_set |= COMA_WORD_SWAP; - break; - case MEDIA_BUS_FMT_YVYU8_2X8: - dev_dbg(&client->dev, "pixel format YVYU8_2X8_LE (untested)\n"); - coma_mask |= COMA_RGB | COMA_BW | COMA_WORD_SWAP | - COMA_BYTE_SWAP; - break; - case MEDIA_BUS_FMT_UYVY8_2X8: - dev_dbg(&client->dev, "pixel format YUYV8_2X8_BE\n"); - if (half_scale) { - coma_mask |= COMA_RGB | COMA_BW | COMA_WORD_SWAP; - coma_set |= COMA_BYTE_SWAP; - } else { - coma_mask |= COMA_RGB | COMA_BW; - coma_set |= COMA_BYTE_SWAP | COMA_WORD_SWAP; - } - break; - case MEDIA_BUS_FMT_VYUY8_2X8: - dev_dbg(&client->dev, "pixel format YVYU8_2X8_BE (untested)\n"); - if (half_scale) { - coma_mask |= COMA_RGB | COMA_BW; - coma_set |= COMA_BYTE_SWAP | COMA_WORD_SWAP; - } else { - coma_mask |= COMA_RGB | COMA_BW | COMA_WORD_SWAP; - coma_set |= COMA_BYTE_SWAP; - } - break; - case MEDIA_BUS_FMT_SBGGR8_1X8: - dev_dbg(&client->dev, "pixel format SBGGR8_1X8 (untested)\n"); - coma_mask |= COMA_BW | COMA_BYTE_SWAP | COMA_WORD_SWAP; - coma_set |= COMA_RAW_RGB | COMA_RGB; - break; - default: - dev_err(&client->dev, "Pixel format not handled: 0x%x\n", code); - return -EINVAL; - } - - if (code == MEDIA_BUS_FMT_Y8_1X8 || - code == MEDIA_BUS_FMT_SBGGR8_1X8) { - coml_mask = COML_ONE_CHANNEL; - coml_set = 0; - } else { - coml_mask = 0; - coml_set = COML_ONE_CHANNEL; - } - - if (half_scale) { - dev_dbg(&client->dev, "max resolution: QCIF\n"); - coma_set |= COMA_QCIF; - } else { - dev_dbg(&client->dev, "max resolution: CIF\n"); - coma_mask |= COMA_QCIF; - } - - ret = ov6650_reg_rmw(client, REG_COMA, coma_set, coma_mask); - if (!ret) { - priv->half_scale = half_scale; - - ret = ov6650_reg_rmw(client, REG_COML, coml_set, coml_mask); - } - if (!ret) - priv->code = code; - - return ret; -} - -static int ov6650_set_fmt(struct v4l2_subdev *sd, - struct v4l2_subdev_state *sd_state, - struct v4l2_subdev_format *format) -{ - struct v4l2_mbus_framefmt *mf = &format->format; - struct i2c_client *client = v4l2_get_subdevdata(sd); - struct ov6650 *priv = to_ov6650(client); - struct v4l2_rect *crop; - bool half_scale; - - if (format->pad) - return -EINVAL; - - switch (mf->code) { - case MEDIA_BUS_FMT_Y10_1X10: - mf->code = MEDIA_BUS_FMT_Y8_1X8; - fallthrough; - case MEDIA_BUS_FMT_Y8_1X8: - case MEDIA_BUS_FMT_YVYU8_2X8: - case MEDIA_BUS_FMT_YUYV8_2X8: - case MEDIA_BUS_FMT_VYUY8_2X8: - case MEDIA_BUS_FMT_UYVY8_2X8: - break; - default: - mf->code = MEDIA_BUS_FMT_SBGGR8_1X8; - fallthrough; - case MEDIA_BUS_FMT_SBGGR8_1X8: - break; - } - - if (format->which == V4L2_SUBDEV_FORMAT_TRY) - crop = v4l2_subdev_state_get_crop(sd_state, 0); - else - crop = &priv->rect; - - half_scale = !is_unscaled_ok(mf->width, mf->height, crop); - - if (format->which == V4L2_SUBDEV_FORMAT_TRY) { - struct v4l2_mbus_framefmt *try_fmt = - v4l2_subdev_state_get_format(sd_state, 0); - - /* store new mbus frame format code and size in pad config */ - try_fmt->width = crop->width >> half_scale; - try_fmt->height = crop->height >> half_scale; - try_fmt->code = mf->code; - - /* return default mbus frame format updated with pad config */ - *mf = ov6650_def_fmt; - mf->width = try_fmt->width; - mf->height = try_fmt->height; - mf->code = try_fmt->code; - - } else { - int ret = 0; - - /* apply new media bus frame format and scaling if changed */ - if (mf->code != priv->code || half_scale != priv->half_scale) - ret = ov6650_s_fmt(sd, mf->code, half_scale); - if (ret) - return ret; - - /* return default format updated with active size and code */ - *mf = ov6650_def_fmt; - mf->width = priv->rect.width >> priv->half_scale; - mf->height = priv->rect.height >> priv->half_scale; - mf->code = priv->code; - } - return 0; -} - -static int ov6650_enum_mbus_code(struct v4l2_subdev *sd, - struct v4l2_subdev_state *sd_state, - struct v4l2_subdev_mbus_code_enum *code) -{ - if (code->pad || code->index >= ARRAY_SIZE(ov6650_codes)) - return -EINVAL; - - code->code = ov6650_codes[code->index]; - return 0; -} - -static int ov6650_enum_frame_interval(struct v4l2_subdev *sd, - struct v4l2_subdev_state *sd_state, - struct v4l2_subdev_frame_interval_enum *fie) -{ - int i; - - /* enumerate supported frame intervals not exceeding 1 second */ - if (fie->index > CLKRC_DIV_MASK || - GET_CLKRC_DIV(fie->index) > FRAME_RATE_MAX) - return -EINVAL; - - for (i = 0; i < ARRAY_SIZE(ov6650_codes); i++) - if (fie->code == ov6650_codes[i]) - break; - if (i == ARRAY_SIZE(ov6650_codes)) - return -EINVAL; - - if (!fie->width || fie->width > W_CIF || - !fie->height || fie->height > H_CIF) - return -EINVAL; - - fie->interval.numerator = GET_CLKRC_DIV(fie->index); - fie->interval.denominator = FRAME_RATE_MAX; - - return 0; -} - -static int ov6650_get_frame_interval(struct v4l2_subdev *sd, - struct v4l2_subdev_state *sd_state, - struct v4l2_subdev_frame_interval *ival) -{ - struct i2c_client *client = v4l2_get_subdevdata(sd); - struct ov6650 *priv = to_ov6650(client); - - /* - * FIXME: Implement support for V4L2_SUBDEV_FORMAT_TRY, using the V4L2 - * subdev active state API. - */ - if (ival->which != V4L2_SUBDEV_FORMAT_ACTIVE) - return -EINVAL; - - ival->interval = priv->tpf; - - dev_dbg(&client->dev, "Frame interval: %u/%u s\n", - ival->interval.numerator, ival->interval.denominator); - - return 0; -} - -static int ov6650_set_frame_interval(struct v4l2_subdev *sd, - struct v4l2_subdev_state *sd_state, - struct v4l2_subdev_frame_interval *ival) -{ - struct i2c_client *client = v4l2_get_subdevdata(sd); - struct ov6650 *priv = to_ov6650(client); - struct v4l2_fract *tpf = &ival->interval; - int div, ret; - - /* - * FIXME: Implement support for V4L2_SUBDEV_FORMAT_TRY, using the V4L2 - * subdev active state API. - */ - if (ival->which != V4L2_SUBDEV_FORMAT_ACTIVE) - return -EINVAL; - - if (tpf->numerator == 0 || tpf->denominator == 0) - div = 1; /* Reset to full rate */ - else - div = (tpf->numerator * FRAME_RATE_MAX) / tpf->denominator; - - if (div == 0) - div = 1; - else if (div > GET_CLKRC_DIV(CLKRC_DIV_MASK)) - div = GET_CLKRC_DIV(CLKRC_DIV_MASK); - - ret = ov6650_reg_rmw(client, REG_CLKRC, to_clkrc(div), CLKRC_DIV_MASK); - if (!ret) { - priv->tpf.numerator = div; - priv->tpf.denominator = FRAME_RATE_MAX; - - *tpf = priv->tpf; - } - - return ret; -} - -/* Soft reset the camera. This has nothing to do with the RESET pin! */ -static int ov6650_reset(struct i2c_client *client) -{ - int ret; - - dev_dbg(&client->dev, "reset\n"); - - ret = ov6650_reg_rmw(client, REG_COMA, COMA_RESET, 0); - if (ret) - dev_err(&client->dev, - "An error occurred while entering soft reset!\n"); - - return ret; -} - -/* program default register values */ -static int ov6650_prog_dflt(struct i2c_client *client, u8 clkrc) -{ - int ret; - - dev_dbg(&client->dev, "initializing\n"); - - ret = ov6650_reg_write(client, REG_COMA, 0); /* ~COMA_RESET */ - if (!ret) - ret = ov6650_reg_write(client, REG_CLKRC, clkrc); - if (!ret) - ret = ov6650_reg_rmw(client, REG_COMB, 0, COMB_BAND_FILTER); - - return ret; -} - -static int ov6650_video_probe(struct v4l2_subdev *sd) -{ - struct i2c_client *client = v4l2_get_subdevdata(sd); - struct ov6650 *priv = to_ov6650(client); - const struct ov6650_xclk *xclk = NULL; - unsigned long rate; - u8 pidh, pidl, midh, midl; - int i, ret = 0; - - priv->clk = devm_clk_get(&client->dev, NULL); - if (IS_ERR(priv->clk)) { - ret = PTR_ERR(priv->clk); - dev_err(&client->dev, "clk request err: %d\n", ret); - return ret; - } - - rate = clk_get_rate(priv->clk); - for (i = 0; rate && i < ARRAY_SIZE(ov6650_xclk); i++) { - if (rate != ov6650_xclk[i].rate) - continue; - - xclk = &ov6650_xclk[i]; - dev_info(&client->dev, "using host default clock rate %lukHz\n", - rate / 1000); - break; - } - for (i = 0; !xclk && i < ARRAY_SIZE(ov6650_xclk); i++) { - ret = clk_set_rate(priv->clk, ov6650_xclk[i].rate); - if (ret || clk_get_rate(priv->clk) != ov6650_xclk[i].rate) - continue; - - xclk = &ov6650_xclk[i]; - dev_info(&client->dev, "using negotiated clock rate %lukHz\n", - xclk->rate / 1000); - break; - } - if (!xclk) { - dev_err(&client->dev, "unable to get supported clock rate\n"); - if (!ret) - ret = -EINVAL; - return ret; - } - - ret = ov6650_s_power(sd, 1); - if (ret < 0) - return ret; - - msleep(20); - - /* - * check and show product ID and manufacturer ID - */ - ret = ov6650_reg_read(client, REG_PIDH, &pidh); - if (!ret) - ret = ov6650_reg_read(client, REG_PIDL, &pidl); - if (!ret) - ret = ov6650_reg_read(client, REG_MIDH, &midh); - if (!ret) - ret = ov6650_reg_read(client, REG_MIDL, &midl); - - if (ret) - goto done; - - if ((pidh != OV6650_PIDH) || (pidl != OV6650_PIDL)) { - dev_err(&client->dev, "Product ID error 0x%02x:0x%02x\n", - pidh, pidl); - ret = -ENODEV; - goto done; - } - - dev_info(&client->dev, - "ov6650 Product ID 0x%02x:0x%02x Manufacturer ID 0x%02x:0x%02x\n", - pidh, pidl, midh, midl); - - ret = ov6650_reset(client); - if (!ret) - ret = ov6650_prog_dflt(client, xclk->clkrc); - if (!ret) { - /* driver default frame format, no scaling */ - ret = ov6650_s_fmt(sd, ov6650_def_fmt.code, false); - } - if (!ret) - ret = v4l2_ctrl_handler_setup(&priv->hdl); - -done: - ov6650_s_power(sd, 0); - return ret; -} - -static const struct v4l2_ctrl_ops ov6550_ctrl_ops = { - .g_volatile_ctrl = ov6550_g_volatile_ctrl, - .s_ctrl = ov6550_s_ctrl, -}; - -static const struct v4l2_subdev_core_ops ov6650_core_ops = { -#ifdef CONFIG_VIDEO_ADV_DEBUG - .g_register = ov6650_get_register, - .s_register = ov6650_set_register, -#endif - .s_power = ov6650_s_power, -}; - -/* Request bus settings on camera side */ -static int ov6650_get_mbus_config(struct v4l2_subdev *sd, - unsigned int pad, - struct v4l2_mbus_config *cfg) -{ - struct i2c_client *client = v4l2_get_subdevdata(sd); - u8 comj, comf; - int ret; - - ret = ov6650_reg_read(client, REG_COMJ, &comj); - if (ret) - return ret; - - ret = ov6650_reg_read(client, REG_COMF, &comf); - if (ret) - return ret; - - cfg->type = V4L2_MBUS_PARALLEL; - - cfg->bus.parallel.flags = V4L2_MBUS_MASTER | V4L2_MBUS_DATA_ACTIVE_HIGH - | ((comj & COMJ_VSYNC_HIGH) ? V4L2_MBUS_VSYNC_ACTIVE_HIGH - : V4L2_MBUS_VSYNC_ACTIVE_LOW) - | ((comf & COMF_HREF_LOW) ? V4L2_MBUS_HSYNC_ACTIVE_LOW - : V4L2_MBUS_HSYNC_ACTIVE_HIGH) - | ((comj & COMJ_PCLK_RISING) ? V4L2_MBUS_PCLK_SAMPLE_RISING - : V4L2_MBUS_PCLK_SAMPLE_FALLING); - return 0; -} - -static const struct v4l2_subdev_video_ops ov6650_video_ops = { - .s_stream = ov6650_s_stream, -}; - -static const struct v4l2_subdev_pad_ops ov6650_pad_ops = { - .enum_mbus_code = ov6650_enum_mbus_code, - .enum_frame_interval = ov6650_enum_frame_interval, - .get_selection = ov6650_get_selection, - .set_selection = ov6650_set_selection, - .get_fmt = ov6650_get_fmt, - .set_fmt = ov6650_set_fmt, - .get_frame_interval = ov6650_get_frame_interval, - .set_frame_interval = ov6650_set_frame_interval, - .get_mbus_config = ov6650_get_mbus_config, -}; - -static const struct v4l2_subdev_ops ov6650_subdev_ops = { - .core = &ov6650_core_ops, - .video = &ov6650_video_ops, - .pad = &ov6650_pad_ops, -}; - -static const struct v4l2_subdev_internal_ops ov6650_internal_ops = { - .registered = ov6650_video_probe, -}; - -/* - * i2c_driver function - */ -static int ov6650_probe(struct i2c_client *client) -{ - struct ov6650 *priv; - int ret; - - priv = devm_kzalloc(&client->dev, sizeof(*priv), GFP_KERNEL); - if (!priv) - return -ENOMEM; - - v4l2_i2c_subdev_init(&priv->subdev, client, &ov6650_subdev_ops); - v4l2_ctrl_handler_init(&priv->hdl, 13); - v4l2_ctrl_new_std(&priv->hdl, &ov6550_ctrl_ops, - V4L2_CID_VFLIP, 0, 1, 1, 0); - v4l2_ctrl_new_std(&priv->hdl, &ov6550_ctrl_ops, - V4L2_CID_HFLIP, 0, 1, 1, 0); - priv->autogain = v4l2_ctrl_new_std(&priv->hdl, &ov6550_ctrl_ops, - V4L2_CID_AUTOGAIN, 0, 1, 1, 1); - priv->gain = v4l2_ctrl_new_std(&priv->hdl, &ov6550_ctrl_ops, - V4L2_CID_GAIN, 0, 0x3f, 1, DEF_GAIN); - priv->autowb = v4l2_ctrl_new_std(&priv->hdl, &ov6550_ctrl_ops, - V4L2_CID_AUTO_WHITE_BALANCE, 0, 1, 1, 1); - priv->blue = v4l2_ctrl_new_std(&priv->hdl, &ov6550_ctrl_ops, - V4L2_CID_BLUE_BALANCE, 0, 0xff, 1, DEF_BLUE); - priv->red = v4l2_ctrl_new_std(&priv->hdl, &ov6550_ctrl_ops, - V4L2_CID_RED_BALANCE, 0, 0xff, 1, DEF_RED); - v4l2_ctrl_new_std(&priv->hdl, &ov6550_ctrl_ops, - V4L2_CID_SATURATION, 0, 0xf, 1, 0x8); - v4l2_ctrl_new_std(&priv->hdl, &ov6550_ctrl_ops, - V4L2_CID_HUE, 0, HUE_MASK, 1, DEF_HUE); - v4l2_ctrl_new_std(&priv->hdl, &ov6550_ctrl_ops, - V4L2_CID_BRIGHTNESS, 0, 0xff, 1, 0x80); - priv->autoexposure = v4l2_ctrl_new_std_menu(&priv->hdl, - &ov6550_ctrl_ops, V4L2_CID_EXPOSURE_AUTO, - V4L2_EXPOSURE_MANUAL, 0, V4L2_EXPOSURE_AUTO); - priv->exposure = v4l2_ctrl_new_std(&priv->hdl, &ov6550_ctrl_ops, - V4L2_CID_EXPOSURE, 0, 0xff, 1, DEF_AECH); - v4l2_ctrl_new_std(&priv->hdl, &ov6550_ctrl_ops, - V4L2_CID_GAMMA, 0, 0xff, 1, 0x12); - - priv->subdev.ctrl_handler = &priv->hdl; - if (priv->hdl.error) { - ret = priv->hdl.error; - goto ectlhdlfree; - } - - v4l2_ctrl_auto_cluster(2, &priv->autogain, 0, true); - v4l2_ctrl_auto_cluster(3, &priv->autowb, 0, true); - v4l2_ctrl_auto_cluster(2, &priv->autoexposure, - V4L2_EXPOSURE_MANUAL, true); - - priv->rect.left = DEF_HSTRT << 1; - priv->rect.top = DEF_VSTRT << 1; - priv->rect.width = W_CIF; - priv->rect.height = H_CIF; - - /* Hardware default frame interval */ - priv->tpf.numerator = GET_CLKRC_DIV(DEF_CLKRC); - priv->tpf.denominator = FRAME_RATE_MAX; - - priv->subdev.internal_ops = &ov6650_internal_ops; - - ret = v4l2_async_register_subdev(&priv->subdev); - if (!ret) - return 0; -ectlhdlfree: - v4l2_ctrl_handler_free(&priv->hdl); - - return ret; -} - -static void ov6650_remove(struct i2c_client *client) -{ - struct ov6650 *priv = to_ov6650(client); - - v4l2_async_unregister_subdev(&priv->subdev); - v4l2_ctrl_handler_free(&priv->hdl); -} - -static const struct i2c_device_id ov6650_id[] = { - { "ov6650" }, - { } -}; -MODULE_DEVICE_TABLE(i2c, ov6650_id); - -static struct i2c_driver ov6650_i2c_driver = { - .driver = { - .name = "ov6650", - }, - .probe = ov6650_probe, - .remove = ov6650_remove, - .id_table = ov6650_id, -}; - -module_i2c_driver(ov6650_i2c_driver); - -MODULE_DESCRIPTION("V4L2 subdevice driver for OmniVision OV6650 camera sensor"); -MODULE_AUTHOR("Janusz Krzysztofik <jmkrzyszt@gmail.com"); -MODULE_LICENSE("GPL v2"); diff --git a/drivers/media/i2c/ov7251.c b/drivers/media/i2c/ov7251.c index 31a42d81e970..27afc3fc0175 100644 --- a/drivers/media/i2c/ov7251.c +++ b/drivers/media/i2c/ov7251.c @@ -1630,7 +1630,6 @@ static int ov7251_probe(struct i2c_client *client) { struct device *dev = &client->dev; struct ov7251 *ov7251; - unsigned int rate = 0, clk_rate = 0; int ret; int i; @@ -1646,33 +1645,12 @@ static int ov7251_probe(struct i2c_client *client) return ret; /* get system clock (xclk) */ - ov7251->xclk = devm_clk_get_optional(dev, NULL); + ov7251->xclk = devm_v4l2_sensor_clk_get(dev, NULL); if (IS_ERR(ov7251->xclk)) return dev_err_probe(dev, PTR_ERR(ov7251->xclk), "could not get xclk"); - /* - * We could have either a 24MHz or 19.2MHz clock rate from either DT or - * ACPI. We also need to support the IPU3 case which will have both an - * external clock AND a clock-frequency property. - */ - ret = fwnode_property_read_u32(dev_fwnode(dev), "clock-frequency", - &rate); - if (ret && !ov7251->xclk) - return dev_err_probe(dev, ret, "invalid clock config\n"); - - clk_rate = clk_get_rate(ov7251->xclk); - ov7251->xclk_freq = clk_rate ? clk_rate : rate; - - if (ov7251->xclk_freq == 0) - return dev_err_probe(dev, -EINVAL, "invalid clock frequency\n"); - - if (!ret && ov7251->xclk) { - ret = clk_set_rate(ov7251->xclk, rate); - if (ret) - return dev_err_probe(dev, ret, - "failed to set clock rate\n"); - } + ov7251->xclk_freq = clk_get_rate(ov7251->xclk); for (i = 0; i < ARRAY_SIZE(supported_xclk_rates); i++) if (ov7251->xclk_freq == supported_xclk_rates[i]) diff --git a/drivers/media/i2c/ov7740.c b/drivers/media/i2c/ov7740.c index 1f1c0de8e510..632fb80469be 100644 --- a/drivers/media/i2c/ov7740.c +++ b/drivers/media/i2c/ov7740.c @@ -1036,13 +1036,10 @@ static int ov7740_probe(struct i2c_client *client) if (!ov7740) return -ENOMEM; - ov7740->xvclk = devm_clk_get(&client->dev, "xvclk"); - if (IS_ERR(ov7740->xvclk)) { - ret = PTR_ERR(ov7740->xvclk); - dev_err(&client->dev, - "OV7740: fail to get xvclk: %d\n", ret); - return ret; - } + ov7740->xvclk = devm_v4l2_sensor_clk_get(&client->dev, "xvclk"); + if (IS_ERR(ov7740->xvclk)) + return dev_err_probe(&client->dev, PTR_ERR(ov7740->xvclk), + "OV7740: fail to get xvclk\n"); ret = ov7740_probe_dt(client, ov7740); if (ret) diff --git a/drivers/media/i2c/ov8856.c b/drivers/media/i2c/ov8856.c index 4b6874d2a104..e2998cfa0d18 100644 --- a/drivers/media/i2c/ov8856.c +++ b/drivers/media/i2c/ov8856.c @@ -1,7 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 // Copyright (c) 2019 Intel Corporation. -#include <linux/unaligned.h> #include <linux/acpi.h> #include <linux/clk.h> #include <linux/delay.h> @@ -10,6 +9,8 @@ #include <linux/module.h> #include <linux/pm_runtime.h> #include <linux/regulator/consumer.h> +#include <linux/unaligned.h> + #include <media/v4l2-ctrls.h> #include <media/v4l2-device.h> #include <media/v4l2-fwnode.h> @@ -1414,6 +1415,8 @@ static const struct ov8856_reg_list bayer_offset_configs[] = { }; struct ov8856 { + struct device *dev; + struct v4l2_subdev sd; struct media_pad pad; struct v4l2_ctrl_handler ctrl_handler; @@ -1668,7 +1671,6 @@ static int ov8856_write_reg(struct ov8856 *ov8856, u16 reg, u16 len, u32 val) static int ov8856_write_reg_list(struct ov8856 *ov8856, const struct ov8856_reg_list *r_list) { - struct i2c_client *client = v4l2_get_subdevdata(&ov8856->sd); unsigned int i; int ret; @@ -1676,7 +1678,7 @@ static int ov8856_write_reg_list(struct ov8856 *ov8856, ret = ov8856_write_reg(ov8856, r_list->regs[i].address, 1, r_list->regs[i].val); if (ret) { - dev_err_ratelimited(&client->dev, + dev_err_ratelimited(ov8856->dev, "failed to write reg 0x%4.4x. error = %d", r_list->regs[i].address, ret); return ret; @@ -1688,7 +1690,6 @@ static int ov8856_write_reg_list(struct ov8856 *ov8856, static int ov8856_identify_module(struct ov8856 *ov8856) { - struct i2c_client *client = v4l2_get_subdevdata(&ov8856->sd); int ret; u32 val; @@ -1701,7 +1702,7 @@ static int ov8856_identify_module(struct ov8856 *ov8856) return ret; if (val != OV8856_CHIP_ID) { - dev_err(&client->dev, "chip id mismatch: %x!=%x", + dev_err(ov8856->dev, "chip id mismatch: %x!=%x", OV8856_CHIP_ID, val); return -ENXIO; } @@ -1818,7 +1819,6 @@ static int ov8856_set_ctrl(struct v4l2_ctrl *ctrl) { struct ov8856 *ov8856 = container_of(ctrl->handler, struct ov8856, ctrl_handler); - struct i2c_client *client = v4l2_get_subdevdata(&ov8856->sd); s64 exposure_max; int ret = 0; @@ -1834,7 +1834,7 @@ static int ov8856_set_ctrl(struct v4l2_ctrl *ctrl) } /* V4L2 controls values will be applied only when power is already up */ - if (!pm_runtime_get_if_in_use(&client->dev)) + if (!pm_runtime_get_if_in_use(ov8856->dev)) return 0; switch (ctrl->id) { @@ -1876,7 +1876,7 @@ static int ov8856_set_ctrl(struct v4l2_ctrl *ctrl) break; } - pm_runtime_put(&client->dev); + pm_runtime_put(ov8856->dev); return ret; } @@ -1979,7 +1979,6 @@ static void ov8856_update_pad_format(struct ov8856 *ov8856, static int ov8856_start_streaming(struct ov8856 *ov8856) { - struct i2c_client *client = v4l2_get_subdevdata(&ov8856->sd); const struct ov8856_reg_list *reg_list; int link_freq_index, ret; @@ -1992,21 +1991,21 @@ static int ov8856_start_streaming(struct ov8856 *ov8856) ret = ov8856_write_reg_list(ov8856, reg_list); if (ret) { - dev_err(&client->dev, "failed to set plls"); + dev_err(ov8856->dev, "failed to set plls"); return ret; } reg_list = &ov8856->cur_mode->reg_list; ret = ov8856_write_reg_list(ov8856, reg_list); if (ret) { - dev_err(&client->dev, "failed to set mode"); + dev_err(ov8856->dev, "failed to set mode"); return ret; } reg_list = &bayer_offset_configs[ov8856->cur_mbus_index]; ret = ov8856_write_reg_list(ov8856, reg_list); if (ret) { - dev_err(&client->dev, "failed to set mbus format"); + dev_err(ov8856->dev, "failed to set mbus format"); return ret; } @@ -2017,7 +2016,7 @@ static int ov8856_start_streaming(struct ov8856 *ov8856) ret = ov8856_write_reg(ov8856, OV8856_REG_MODE_SELECT, OV8856_REG_VALUE_08BIT, OV8856_MODE_STREAMING); if (ret) { - dev_err(&client->dev, "failed to set stream"); + dev_err(ov8856->dev, "failed to set stream"); return ret; } @@ -2026,22 +2025,19 @@ static int ov8856_start_streaming(struct ov8856 *ov8856) static void ov8856_stop_streaming(struct ov8856 *ov8856) { - struct i2c_client *client = v4l2_get_subdevdata(&ov8856->sd); - if (ov8856_write_reg(ov8856, OV8856_REG_MODE_SELECT, OV8856_REG_VALUE_08BIT, OV8856_MODE_STANDBY)) - dev_err(&client->dev, "failed to set stream"); + dev_err(ov8856->dev, "failed to set stream"); } static int ov8856_set_stream(struct v4l2_subdev *sd, int enable) { struct ov8856 *ov8856 = to_ov8856(sd); - struct i2c_client *client = v4l2_get_subdevdata(sd); int ret = 0; mutex_lock(&ov8856->mutex); if (enable) { - ret = pm_runtime_resume_and_get(&client->dev); + ret = pm_runtime_resume_and_get(ov8856->dev); if (ret < 0) { mutex_unlock(&ov8856->mutex); return ret; @@ -2051,11 +2047,11 @@ static int ov8856_set_stream(struct v4l2_subdev *sd, int enable) if (ret) { enable = 0; ov8856_stop_streaming(ov8856); - pm_runtime_put(&client->dev); + pm_runtime_put(ov8856->dev); } } else { ov8856_stop_streaming(ov8856); - pm_runtime_put(&client->dev); + pm_runtime_put(ov8856->dev); } mutex_unlock(&ov8856->mutex); @@ -2255,8 +2251,9 @@ static const struct v4l2_subdev_internal_ops ov8856_internal_ops = { }; -static int ov8856_get_hwcfg(struct ov8856 *ov8856, struct device *dev) +static int ov8856_get_hwcfg(struct ov8856 *ov8856) { + struct device *dev = ov8856->dev; struct fwnode_handle *ep; struct fwnode_handle *fwnode = dev_fwnode(dev); struct v4l2_fwnode_endpoint bus_cfg = { @@ -2269,21 +2266,17 @@ static int ov8856_get_hwcfg(struct ov8856 *ov8856, struct device *dev) if (!fwnode) return -ENXIO; - ret = fwnode_property_read_u32(fwnode, "clock-frequency", &xvclk_rate); - if (ret) - return ret; - - if (!is_acpi_node(fwnode)) { - ov8856->xvclk = devm_clk_get(dev, "xvclk"); - if (IS_ERR(ov8856->xvclk)) { - dev_err_probe(dev, PTR_ERR(ov8856->xvclk), - "could not get xvclk clock\n"); - return PTR_ERR(ov8856->xvclk); - } + ov8856->xvclk = devm_v4l2_sensor_clk_get_legacy(dev, "xvclk", false, 0); + if (IS_ERR(ov8856->xvclk)) + return dev_err_probe(dev, PTR_ERR(ov8856->xvclk), + "could not get xvclk clock\n"); - clk_set_rate(ov8856->xvclk, xvclk_rate); - xvclk_rate = clk_get_rate(ov8856->xvclk); + xvclk_rate = clk_get_rate(ov8856->xvclk); + if (xvclk_rate != OV8856_XVCLK_19_2) + dev_warn(dev, "external clock rate %u is unsupported", + xvclk_rate); + if (!is_acpi_node(fwnode)) { ov8856->reset_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW); if (IS_ERR(ov8856->reset_gpio)) @@ -2299,10 +2292,6 @@ static int ov8856_get_hwcfg(struct ov8856 *ov8856, struct device *dev) return ret; } - if (xvclk_rate != OV8856_XVCLK_19_2) - dev_warn(dev, "external clock rate %u is unsupported", - xvclk_rate); - ep = fwnode_graph_get_next_endpoint(fwnode, NULL); if (!ep) return -ENXIO; @@ -2365,10 +2354,10 @@ static void ov8856_remove(struct i2c_client *client) v4l2_async_unregister_subdev(sd); media_entity_cleanup(&sd->entity); v4l2_ctrl_handler_free(sd->ctrl_handler); - pm_runtime_disable(&client->dev); + pm_runtime_disable(ov8856->dev); mutex_destroy(&ov8856->mutex); - ov8856_power_off(&client->dev); + ov8856_power_off(ov8856->dev); } static int ov8856_probe(struct i2c_client *client) @@ -2381,23 +2370,25 @@ static int ov8856_probe(struct i2c_client *client) if (!ov8856) return -ENOMEM; - ret = ov8856_get_hwcfg(ov8856, &client->dev); + ov8856->dev = &client->dev; + + ret = ov8856_get_hwcfg(ov8856); if (ret) return ret; v4l2_i2c_subdev_init(&ov8856->sd, client, &ov8856_subdev_ops); - full_power = acpi_dev_state_d0(&client->dev); + full_power = acpi_dev_state_d0(ov8856->dev); if (full_power) { - ret = ov8856_power_on(&client->dev); + ret = ov8856_power_on(ov8856->dev); if (ret) { - dev_err(&client->dev, "failed to power on\n"); + dev_err(ov8856->dev, "failed to power on\n"); return ret; } ret = ov8856_identify_module(ov8856); if (ret) { - dev_err(&client->dev, "failed to find sensor: %d", ret); + dev_err(ov8856->dev, "failed to find sensor: %d", ret); goto probe_power_off; } } @@ -2407,7 +2398,7 @@ static int ov8856_probe(struct i2c_client *client) ov8856->cur_mbus_index = ov8856->cur_mode->default_mbus_index; ret = ov8856_init_controls(ov8856); if (ret) { - dev_err(&client->dev, "failed to init controls: %d", ret); + dev_err(ov8856->dev, "failed to init controls: %d", ret); goto probe_error_v4l2_ctrl_handler_free; } @@ -2418,22 +2409,22 @@ static int ov8856_probe(struct i2c_client *client) ov8856->pad.flags = MEDIA_PAD_FL_SOURCE; ret = media_entity_pads_init(&ov8856->sd.entity, 1, &ov8856->pad); if (ret) { - dev_err(&client->dev, "failed to init entity pads: %d", ret); + dev_err(ov8856->dev, "failed to init entity pads: %d", ret); goto probe_error_v4l2_ctrl_handler_free; } ret = v4l2_async_register_subdev_sensor(&ov8856->sd); if (ret < 0) { - dev_err(&client->dev, "failed to register V4L2 subdev: %d", + dev_err(ov8856->dev, "failed to register V4L2 subdev: %d", ret); goto probe_error_media_entity_cleanup; } /* Set the device's state to active if it's in D0 state. */ if (full_power) - pm_runtime_set_active(&client->dev); - pm_runtime_enable(&client->dev); - pm_runtime_idle(&client->dev); + pm_runtime_set_active(ov8856->dev); + pm_runtime_enable(ov8856->dev); + pm_runtime_idle(ov8856->dev); return 0; @@ -2445,7 +2436,7 @@ probe_error_v4l2_ctrl_handler_free: mutex_destroy(&ov8856->mutex); probe_power_off: - ov8856_power_off(&client->dev); + ov8856_power_off(ov8856->dev); return ret; } diff --git a/drivers/media/i2c/ov8858.c b/drivers/media/i2c/ov8858.c index 6b7193eaea1f..3f45f7fab833 100644 --- a/drivers/media/i2c/ov8858.c +++ b/drivers/media/i2c/ov8858.c @@ -1876,7 +1876,7 @@ static int ov8858_probe(struct i2c_client *client) if (!ov8858) return -ENOMEM; - ov8858->xvclk = devm_clk_get(dev, "xvclk"); + ov8858->xvclk = devm_v4l2_sensor_clk_get(dev, "xvclk"); if (IS_ERR(ov8858->xvclk)) return dev_err_probe(dev, PTR_ERR(ov8858->xvclk), "Failed to get xvclk\n"); diff --git a/drivers/media/i2c/ov8865.c b/drivers/media/i2c/ov8865.c index a2138f7988aa..a8586df14f77 100644 --- a/drivers/media/i2c/ov8865.c +++ b/drivers/media/i2c/ov8865.c @@ -2304,14 +2304,6 @@ static int ov8865_state_configure(struct ov8865_sensor *sensor, if (sensor->state.streaming) return -EBUSY; - /* State will be configured at first power on otherwise. */ - if (pm_runtime_enabled(sensor->dev) && - !pm_runtime_suspended(sensor->dev)) { - ret = ov8865_mode_configure(sensor, mode, mbus_code); - if (ret) - return ret; - } - ret = ov8865_state_mipi_configure(sensor, mode, mbus_code); if (ret) return ret; @@ -2384,10 +2376,10 @@ static int ov8865_sensor_init(struct ov8865_sensor *sensor) } /* Configure current mode. */ - ret = ov8865_state_configure(sensor, sensor->state.mode, - sensor->state.mbus_code); + ret = ov8865_mode_configure(sensor, sensor->state.mode, + sensor->state.mbus_code); if (ret) { - dev_err(sensor->dev, "failed to configure state\n"); + dev_err(sensor->dev, "failed to configure mode\n"); return ret; } @@ -2956,7 +2948,6 @@ static int ov8865_probe(struct i2c_client *client) struct ov8865_sensor *sensor; struct v4l2_subdev *subdev; struct media_pad *pad; - unsigned int rate = 0; unsigned int i; int ret; @@ -3020,39 +3011,14 @@ static int ov8865_probe(struct i2c_client *client) /* External Clock */ - sensor->extclk = devm_clk_get(dev, NULL); - if (PTR_ERR(sensor->extclk) == -ENOENT) { - dev_info(dev, "no external clock found, continuing...\n"); - sensor->extclk = NULL; - } else if (IS_ERR(sensor->extclk)) { - dev_err(dev, "failed to get external clock\n"); - ret = PTR_ERR(sensor->extclk); - goto error_endpoint; - } - - /* - * We could have either a 24MHz or 19.2MHz clock rate from either dt or - * ACPI...but we also need to support the weird IPU3 case which will - * have an external clock AND a clock-frequency property. Check for the - * clock-frequency property and if found, set that rate if we managed - * to acquire a clock. This should cover the ACPI case. If the system - * uses devicetree then the configured rate should already be set, so - * we can just read it. - */ - ret = fwnode_property_read_u32(dev_fwnode(dev), "clock-frequency", - &rate); - if (!ret && sensor->extclk) { - ret = clk_set_rate(sensor->extclk, rate); - if (ret) { - dev_err_probe(dev, ret, "failed to set clock rate\n"); - goto error_endpoint; - } - } else if (ret && !sensor->extclk) { - dev_err_probe(dev, ret, "invalid clock config\n"); + sensor->extclk = devm_v4l2_sensor_clk_get(dev, NULL); + if (IS_ERR(sensor->extclk)) { + ret = dev_err_probe(dev, PTR_ERR(sensor->extclk), + "failed to get external clock\n"); goto error_endpoint; } - sensor->extclk_rate = rate ? rate : clk_get_rate(sensor->extclk); + sensor->extclk_rate = clk_get_rate(sensor->extclk); for (i = 0; i < ARRAY_SIZE(supported_extclk_rates); i++) { if (sensor->extclk_rate == supported_extclk_rates[i]) diff --git a/drivers/media/i2c/ov9282.c b/drivers/media/i2c/ov9282.c index c882a021cf18..a9f6176e9729 100644 --- a/drivers/media/i2c/ov9282.c +++ b/drivers/media/i2c/ov9282.c @@ -1135,11 +1135,10 @@ static int ov9282_parse_hw_config(struct ov9282 *ov9282) } /* Get sensor input clock */ - ov9282->inclk = devm_clk_get(ov9282->dev, NULL); - if (IS_ERR(ov9282->inclk)) { - dev_err(ov9282->dev, "could not get inclk"); - return PTR_ERR(ov9282->inclk); - } + ov9282->inclk = devm_v4l2_sensor_clk_get(ov9282->dev, NULL); + if (IS_ERR(ov9282->inclk)) + return dev_err_probe(ov9282->dev, PTR_ERR(ov9282->inclk), + "could not get inclk\n"); ret = ov9282_configure_regulators(ov9282); if (ret) diff --git a/drivers/media/i2c/ov9640.c b/drivers/media/i2c/ov9640.c index 01dbc0ba89c8..2190c52b1433 100644 --- a/drivers/media/i2c/ov9640.c +++ b/drivers/media/i2c/ov9640.c @@ -718,9 +718,10 @@ static int ov9640_probe(struct i2c_client *client) priv->subdev.ctrl_handler = &priv->hdl; - priv->clk = devm_clk_get(&client->dev, "mclk"); + priv->clk = devm_v4l2_sensor_clk_get(&client->dev, "mclk"); if (IS_ERR(priv->clk)) { - ret = PTR_ERR(priv->clk); + ret = dev_err_probe(&client->dev, PTR_ERR(priv->clk), + "failed to get mclk\n"); goto ectrlinit; } diff --git a/drivers/media/i2c/ov9650.c b/drivers/media/i2c/ov9650.c index 026ea34d6291..c94e8fe29f22 100644 --- a/drivers/media/i2c/ov9650.c +++ b/drivers/media/i2c/ov9650.c @@ -1494,9 +1494,10 @@ static int ov965x_probe(struct i2c_client *client) } if (dev_fwnode(&client->dev)) { - ov965x->clk = devm_clk_get(&client->dev, NULL); + ov965x->clk = devm_v4l2_sensor_clk_get(&client->dev, NULL); if (IS_ERR(ov965x->clk)) - return PTR_ERR(ov965x->clk); + return dev_err_probe(&client->dev, PTR_ERR(ov965x->clk), + "failed to get the clock\n"); ov965x->mclk_frequency = clk_get_rate(ov965x->clk); ret = ov965x_configure_gpios(ov965x); diff --git a/drivers/media/i2c/ov9734.c b/drivers/media/i2c/ov9734.c index cae3aeefb616..0eaf33807fc9 100644 --- a/drivers/media/i2c/ov9734.c +++ b/drivers/media/i2c/ov9734.c @@ -1,12 +1,14 @@ // SPDX-License-Identifier: GPL-2.0 // Copyright (c) 2020 Intel Corporation. -#include <linux/unaligned.h> #include <linux/acpi.h> +#include <linux/clk.h> #include <linux/delay.h> #include <linux/i2c.h> #include <linux/module.h> #include <linux/pm_runtime.h> +#include <linux/unaligned.h> + #include <media/v4l2-ctrls.h> #include <media/v4l2-device.h> #include <media/v4l2-fwnode.h> @@ -321,6 +323,9 @@ static const struct ov9734_mode supported_modes[] = { }; struct ov9734 { + struct device *dev; + struct clk *clk; + struct v4l2_subdev sd; struct media_pad pad; struct v4l2_ctrl_handler ctrl_handler; @@ -414,7 +419,6 @@ static int ov9734_write_reg(struct ov9734 *ov9734, u16 reg, u16 len, u32 val) static int ov9734_write_reg_list(struct ov9734 *ov9734, const struct ov9734_reg_list *r_list) { - struct i2c_client *client = v4l2_get_subdevdata(&ov9734->sd); unsigned int i; int ret; @@ -422,7 +426,7 @@ static int ov9734_write_reg_list(struct ov9734 *ov9734, ret = ov9734_write_reg(ov9734, r_list->regs[i].address, 1, r_list->regs[i].val); if (ret) { - dev_err_ratelimited(&client->dev, + dev_err_ratelimited(ov9734->dev, "write reg 0x%4.4x return err = %d", r_list->regs[i].address, ret); return ret; @@ -476,7 +480,6 @@ static int ov9734_set_ctrl(struct v4l2_ctrl *ctrl) { struct ov9734 *ov9734 = container_of(ctrl->handler, struct ov9734, ctrl_handler); - struct i2c_client *client = v4l2_get_subdevdata(&ov9734->sd); s64 exposure_max; int ret = 0; @@ -492,7 +495,7 @@ static int ov9734_set_ctrl(struct v4l2_ctrl *ctrl) } /* V4L2 controls values will be applied only when power is already up */ - if (!pm_runtime_get_if_in_use(&client->dev)) + if (!pm_runtime_get_if_in_use(ov9734->dev)) return 0; switch (ctrl->id) { @@ -525,7 +528,7 @@ static int ov9734_set_ctrl(struct v4l2_ctrl *ctrl) break; } - pm_runtime_put(&client->dev); + pm_runtime_put(ov9734->dev); return ret; } @@ -610,7 +613,6 @@ static void ov9734_update_pad_format(const struct ov9734_mode *mode, static int ov9734_start_streaming(struct ov9734 *ov9734) { - struct i2c_client *client = v4l2_get_subdevdata(&ov9734->sd); const struct ov9734_reg_list *reg_list; int link_freq_index, ret; @@ -618,14 +620,14 @@ static int ov9734_start_streaming(struct ov9734 *ov9734) reg_list = &link_freq_configs[link_freq_index].reg_list; ret = ov9734_write_reg_list(ov9734, reg_list); if (ret) { - dev_err(&client->dev, "failed to set plls"); + dev_err(ov9734->dev, "failed to set plls"); return ret; } reg_list = &ov9734->cur_mode->reg_list; ret = ov9734_write_reg_list(ov9734, reg_list); if (ret) { - dev_err(&client->dev, "failed to set mode"); + dev_err(ov9734->dev, "failed to set mode"); return ret; } @@ -636,30 +638,27 @@ static int ov9734_start_streaming(struct ov9734 *ov9734) ret = ov9734_write_reg(ov9734, OV9734_REG_MODE_SELECT, 1, OV9734_MODE_STREAMING); if (ret) - dev_err(&client->dev, "failed to start stream"); + dev_err(ov9734->dev, "failed to start stream"); return ret; } static void ov9734_stop_streaming(struct ov9734 *ov9734) { - struct i2c_client *client = v4l2_get_subdevdata(&ov9734->sd); - if (ov9734_write_reg(ov9734, OV9734_REG_MODE_SELECT, 1, OV9734_MODE_STANDBY)) - dev_err(&client->dev, "failed to stop stream"); + dev_err(ov9734->dev, "failed to stop stream"); } static int ov9734_set_stream(struct v4l2_subdev *sd, int enable) { struct ov9734 *ov9734 = to_ov9734(sd); - struct i2c_client *client = v4l2_get_subdevdata(sd); int ret = 0; mutex_lock(&ov9734->mutex); if (enable) { - ret = pm_runtime_resume_and_get(&client->dev); + ret = pm_runtime_resume_and_get(ov9734->dev); if (ret < 0) { mutex_unlock(&ov9734->mutex); return ret; @@ -669,11 +668,11 @@ static int ov9734_set_stream(struct v4l2_subdev *sd, int enable) if (ret) { enable = 0; ov9734_stop_streaming(ov9734); - pm_runtime_put(&client->dev); + pm_runtime_put(ov9734->dev); } } else { ov9734_stop_streaming(ov9734); - pm_runtime_put(&client->dev); + pm_runtime_put(ov9734->dev); } mutex_unlock(&ov9734->mutex); @@ -808,7 +807,6 @@ static const struct v4l2_subdev_internal_ops ov9734_internal_ops = { static int ov9734_identify_module(struct ov9734 *ov9734) { - struct i2c_client *client = v4l2_get_subdevdata(&ov9734->sd); int ret; u32 val; @@ -817,7 +815,7 @@ static int ov9734_identify_module(struct ov9734 *ov9734) return ret; if (val != OV9734_CHIP_ID) { - dev_err(&client->dev, "chip id mismatch: %x!=%x", + dev_err(ov9734->dev, "chip id mismatch: %x!=%x", OV9734_CHIP_ID, val); return -ENXIO; } @@ -832,22 +830,12 @@ static int ov9734_check_hwcfg(struct device *dev) struct v4l2_fwnode_endpoint bus_cfg = { .bus_type = V4L2_MBUS_CSI2_DPHY }; - u32 mclk; int ret; unsigned int i, j; if (!fwnode) return -ENXIO; - ret = fwnode_property_read_u32(fwnode, "clock-frequency", &mclk); - if (ret) - return ret; - - if (mclk != OV9734_MCLK) { - dev_err(dev, "external clock %d is not supported", mclk); - return -EINVAL; - } - ep = fwnode_graph_get_next_endpoint(fwnode, NULL); if (!ep) return -ENXIO; @@ -892,14 +880,15 @@ static void ov9734_remove(struct i2c_client *client) v4l2_async_unregister_subdev(sd); media_entity_cleanup(&sd->entity); v4l2_ctrl_handler_free(sd->ctrl_handler); - pm_runtime_disable(&client->dev); - pm_runtime_set_suspended(&client->dev); + pm_runtime_disable(ov9734->dev); + pm_runtime_set_suspended(ov9734->dev); mutex_destroy(&ov9734->mutex); } static int ov9734_probe(struct i2c_client *client) { struct ov9734 *ov9734; + unsigned long freq; int ret; ret = ov9734_check_hwcfg(&client->dev); @@ -913,10 +902,23 @@ static int ov9734_probe(struct i2c_client *client) if (!ov9734) return -ENOMEM; + ov9734->dev = &client->dev; + + ov9734->clk = devm_v4l2_sensor_clk_get(ov9734->dev, NULL); + if (IS_ERR(ov9734->clk)) + return dev_err_probe(ov9734->dev, PTR_ERR(ov9734->clk), + "failed to get clock\n"); + + freq = clk_get_rate(ov9734->clk); + if (freq != OV9734_MCLK) + return dev_err_probe(ov9734->dev, -EINVAL, + "external clock %lu is not supported", + freq); + v4l2_i2c_subdev_init(&ov9734->sd, client, &ov9734_subdev_ops); ret = ov9734_identify_module(ov9734); if (ret) { - dev_err(&client->dev, "failed to find sensor: %d", ret); + dev_err(ov9734->dev, "failed to find sensor: %d", ret); return ret; } @@ -924,7 +926,7 @@ static int ov9734_probe(struct i2c_client *client) ov9734->cur_mode = &supported_modes[0]; ret = ov9734_init_controls(ov9734); if (ret) { - dev_err(&client->dev, "failed to init controls: %d", ret); + dev_err(ov9734->dev, "failed to init controls: %d", ret); goto probe_error_v4l2_ctrl_handler_free; } @@ -935,7 +937,7 @@ static int ov9734_probe(struct i2c_client *client) ov9734->pad.flags = MEDIA_PAD_FL_SOURCE; ret = media_entity_pads_init(&ov9734->sd.entity, 1, &ov9734->pad); if (ret) { - dev_err(&client->dev, "failed to init entity pads: %d", ret); + dev_err(ov9734->dev, "failed to init entity pads: %d", ret); goto probe_error_v4l2_ctrl_handler_free; } @@ -943,13 +945,13 @@ static int ov9734_probe(struct i2c_client *client) * Device is already turned on by i2c-core with ACPI domain PM. * Enable runtime PM and turn off the device. */ - pm_runtime_set_active(&client->dev); - pm_runtime_enable(&client->dev); - pm_runtime_idle(&client->dev); + pm_runtime_set_active(ov9734->dev); + pm_runtime_enable(ov9734->dev); + pm_runtime_idle(ov9734->dev); ret = v4l2_async_register_subdev_sensor(&ov9734->sd); if (ret < 0) { - dev_err(&client->dev, "failed to register V4L2 subdev: %d", + dev_err(ov9734->dev, "failed to register V4L2 subdev: %d", ret); goto probe_error_media_entity_cleanup_pm; } @@ -957,8 +959,8 @@ static int ov9734_probe(struct i2c_client *client) return 0; probe_error_media_entity_cleanup_pm: - pm_runtime_disable(&client->dev); - pm_runtime_set_suspended(&client->dev); + pm_runtime_disable(ov9734->dev); + pm_runtime_set_suspended(ov9734->dev); media_entity_cleanup(&ov9734->sd.entity); probe_error_v4l2_ctrl_handler_free: diff --git a/drivers/media/i2c/rj54n1cb0c.c b/drivers/media/i2c/rj54n1cb0c.c index b7ca39f63dba..6dfc91216851 100644 --- a/drivers/media/i2c/rj54n1cb0c.c +++ b/drivers/media/i2c/rj54n1cb0c.c @@ -1329,10 +1329,13 @@ static int rj54n1_probe(struct i2c_client *client) V4L2_CID_GAIN, 0, 127, 1, 66); v4l2_ctrl_new_std(&rj54n1->hdl, &rj54n1_ctrl_ops, V4L2_CID_AUTO_WHITE_BALANCE, 0, 1, 1, 1); - rj54n1->subdev.ctrl_handler = &rj54n1->hdl; - if (rj54n1->hdl.error) - return rj54n1->hdl.error; + if (rj54n1->hdl.error) { + ret = rj54n1->hdl.error; + goto err_free_ctrl; + } + + rj54n1->subdev.ctrl_handler = &rj54n1->hdl; rj54n1->clk_div = clk_div; rj54n1->rect.left = RJ54N1_COLUMN_SKIP; rj54n1->rect.top = RJ54N1_ROW_SKIP; diff --git a/drivers/media/i2c/s5c73m3/s5c73m3-core.c b/drivers/media/i2c/s5c73m3/s5c73m3-core.c index 7716dfe2b8c9..ab31ee2b596b 100644 --- a/drivers/media/i2c/s5c73m3/s5c73m3-core.c +++ b/drivers/media/i2c/s5c73m3/s5c73m3-core.c @@ -1368,10 +1368,6 @@ static int __s5c73m3_power_on(struct s5c73m3 *state) goto err_reg_dis; } - ret = clk_set_rate(state->clock, state->mclk_frequency); - if (ret < 0) - goto err_reg_dis; - ret = clk_prepare_enable(state->clock); if (ret < 0) goto err_reg_dis; @@ -1556,16 +1552,13 @@ static int s5c73m3_get_dt_data(struct s5c73m3 *state) if (!node) return -EINVAL; - state->clock = devm_clk_get(dev, S5C73M3_CLK_NAME); + state->clock = devm_v4l2_sensor_clk_get_legacy(dev, S5C73M3_CLK_NAME, + false, + S5C73M3_DEFAULT_MCLK_FREQ); if (IS_ERR(state->clock)) - return PTR_ERR(state->clock); - - if (of_property_read_u32(node, "clock-frequency", - &state->mclk_frequency)) { - state->mclk_frequency = S5C73M3_DEFAULT_MCLK_FREQ; - dev_info(dev, "using default %u Hz clock frequency\n", - state->mclk_frequency); - } + return dev_err_probe(dev, PTR_ERR(state->clock), + "Failed to get the clock %s\n", + S5C73M3_CLK_NAME); /* Request GPIO lines asserted */ state->stby = devm_gpiod_get(dev, "standby", GPIOD_OUT_HIGH); diff --git a/drivers/media/i2c/s5c73m3/s5c73m3.h b/drivers/media/i2c/s5c73m3/s5c73m3.h index 627e80cf5b72..68a19c2c8db8 100644 --- a/drivers/media/i2c/s5c73m3/s5c73m3.h +++ b/drivers/media/i2c/s5c73m3/s5c73m3.h @@ -382,8 +382,6 @@ struct s5c73m3 { struct clk *clock; - /* External master clock frequency */ - u32 mclk_frequency; /* Video bus type - MIPI-CSI2/parallel */ enum v4l2_mbus_type bus_type; diff --git a/drivers/media/i2c/s5k5baf.c b/drivers/media/i2c/s5k5baf.c index 24f399cd2124..d1d00eca8708 100644 --- a/drivers/media/i2c/s5k5baf.c +++ b/drivers/media/i2c/s5k5baf.c @@ -284,7 +284,6 @@ struct s5k5baf { struct regulator_bulk_data supplies[S5K5BAF_NUM_SUPPLIES]; struct clk *clock; - u32 mclk_frequency; struct s5k5baf_fw *fw; @@ -576,7 +575,7 @@ static void s5k5baf_hw_patch(struct s5k5baf *state) static void s5k5baf_hw_set_clocks(struct s5k5baf *state) { - unsigned long mclk = state->mclk_frequency / 1000; + unsigned long mclk = clk_get_rate(state->clock) / 1000; u16 status; static const u16 nseq_clk_cfg[] = { NSEQ(REG_I_USE_NPVI_CLOCKS, @@ -946,10 +945,6 @@ static int s5k5baf_power_on(struct s5k5baf *state) if (ret < 0) goto err; - ret = clk_set_rate(state->clock, state->mclk_frequency); - if (ret < 0) - goto err_reg_dis; - ret = clk_prepare_enable(state->clock); if (ret < 0) goto err_reg_dis; @@ -1841,14 +1836,6 @@ static int s5k5baf_parse_device_node(struct s5k5baf *state, struct device *dev) return -EINVAL; } - ret = of_property_read_u32(node, "clock-frequency", - &state->mclk_frequency); - if (ret < 0) { - state->mclk_frequency = S5K5BAF_DEFAULT_MCLK_FREQ; - dev_info(dev, "using default %u Hz clock frequency\n", - state->mclk_frequency); - } - node_ep = of_graph_get_endpoint_by_regs(node, 0, -1); if (!node_ep) { dev_err(dev, "no endpoint defined at node %pOF\n", node); @@ -1967,9 +1954,11 @@ static int s5k5baf_probe(struct i2c_client *c) if (ret < 0) goto err_me; - state->clock = devm_clk_get(state->sd.dev, S5K5BAF_CLK_NAME); + state->clock = devm_v4l2_sensor_clk_get_legacy(state->sd.dev, + S5K5BAF_CLK_NAME, false, + S5K5BAF_DEFAULT_MCLK_FREQ); if (IS_ERR(state->clock)) { - ret = -EPROBE_DEFER; + ret = PTR_ERR(state->clock); goto err_me; } diff --git a/drivers/media/i2c/s5k6a3.c b/drivers/media/i2c/s5k6a3.c index 0c2674115b7b..ba6477e88da3 100644 --- a/drivers/media/i2c/s5k6a3.c +++ b/drivers/media/i2c/s5k6a3.c @@ -51,7 +51,6 @@ enum { * @lock: mutex protecting the structure's members below * @format: media bus format at the sensor's source pad * @clock: pointer to &struct clk. - * @clock_frequency: clock frequency * @power_count: stores state if device is powered */ struct s5k6a3 { @@ -63,7 +62,6 @@ struct s5k6a3 { struct mutex lock; struct v4l2_mbus_framefmt format; struct clk *clock; - u32 clock_frequency; int power_count; }; @@ -192,10 +190,6 @@ static int __s5k6a3_power_on(struct s5k6a3 *sensor) int i = S5K6A3_SUPP_VDDA; int ret; - ret = clk_set_rate(sensor->clock, sensor->clock_frequency); - if (ret < 0) - return ret; - ret = pm_runtime_get(sensor->dev); if (ret < 0) goto error_rpm_put; @@ -292,22 +286,18 @@ static int s5k6a3_probe(struct i2c_client *client) mutex_init(&sensor->lock); sensor->dev = dev; - sensor->clock = devm_clk_get(sensor->dev, S5K6A3_CLK_NAME); + sensor->clock = devm_v4l2_sensor_clk_get_legacy(sensor->dev, + S5K6A3_CLK_NAME, false, + S5K6A3_DEFAULT_CLK_FREQ); if (IS_ERR(sensor->clock)) - return PTR_ERR(sensor->clock); + return dev_err_probe(sensor->dev, PTR_ERR(sensor->clock), + "failed to get extclk\n"); sensor->gpio_reset = devm_gpiod_get(dev, NULL, GPIOD_OUT_HIGH); ret = PTR_ERR_OR_ZERO(sensor->gpio_reset); if (ret) return ret; - if (of_property_read_u32(dev->of_node, "clock-frequency", - &sensor->clock_frequency)) { - sensor->clock_frequency = S5K6A3_DEFAULT_CLK_FREQ; - dev_info(dev, "using default %u Hz clock frequency\n", - sensor->clock_frequency); - } - for (i = 0; i < S5K6A3_NUM_SUPPLIES; i++) sensor->supplies[i].supply = s5k6a3_supply_names[i]; diff --git a/drivers/media/i2c/saa6752hs.c b/drivers/media/i2c/saa6752hs.c index 1ed8b5edb3fb..1c0031ba43b4 100644 --- a/drivers/media/i2c/saa6752hs.c +++ b/drivers/media/i2c/saa6752hs.c @@ -6,7 +6,7 @@ AC-3 support: - Copyright (C) 2008 Hans Verkuil <hverkuil@xs4all.nl> + Copyright (C) 2008 Hans Verkuil <hverkuil@kernel.org> */ diff --git a/drivers/media/i2c/saa7115.c b/drivers/media/i2c/saa7115.c index b8b8f206ec3a..48d6730d9271 100644 --- a/drivers/media/i2c/saa7115.c +++ b/drivers/media/i2c/saa7115.c @@ -18,7 +18,7 @@ // Added saa7115 support by Kevin Thayer <nufan_wfk at yahoo.com> // (2/17/2003) // -// VBI support (2004) and cleanups (2005) by Hans Verkuil <hverkuil@xs4all.nl> +// VBI support (2004) and cleanups (2005) by Hans Verkuil <hverkuil@kernel.org> // // Copyright (c) 2005-2006 Mauro Carvalho Chehab <mchehab@kernel.org> // SAA7111, SAA7113 and SAA7118 support diff --git a/drivers/media/i2c/saa7127.c b/drivers/media/i2c/saa7127.c index 818ed19cf37b..a42a7ffe3768 100644 --- a/drivers/media/i2c/saa7127.c +++ b/drivers/media/i2c/saa7127.c @@ -25,7 +25,7 @@ * Copyright (C) 2004 Chris Kennedy <c@groovy.org> * * VBI additions & cleanup: - * Copyright (C) 2004, 2005 Hans Verkuil <hverkuil@xs4all.nl> + * Copyright (C) 2004, 2005 Hans Verkuil <hverkuil@kernel.org> * * Note: the saa7126 is identical to the saa7127, and the saa7128 is * identical to the saa7129, except that the saa7126 and saa7128 have diff --git a/drivers/media/i2c/saa717x.c b/drivers/media/i2c/saa717x.c index b0793bb0c02a..713331be947c 100644 --- a/drivers/media/i2c/saa717x.c +++ b/drivers/media/i2c/saa717x.c @@ -10,7 +10,7 @@ * Changes by T.Adachi (tadachi@tadachi-net.com) * - support audio, video scaler etc, and checked the initialize sequence. * - * Cleaned up by Hans Verkuil <hverkuil@xs4all.nl> + * Cleaned up by Hans Verkuil <hverkuil@kernel.org> * * Note: this is a reversed engineered driver based on captures from * the I2C bus under Windows. This chip is very similar to the saa7134, diff --git a/drivers/media/i2c/tc358743.c b/drivers/media/i2c/tc358743.c index 1cc7636e446d..a0ca19359c43 100644 --- a/drivers/media/i2c/tc358743.c +++ b/drivers/media/i2c/tc358743.c @@ -38,7 +38,21 @@ static int debug; module_param(debug, int, 0644); -MODULE_PARM_DESC(debug, "debug level (0-3)"); +MODULE_PARM_DESC(debug, " debug level (0-3)"); + +static int packet_type = 0x87; +module_param(packet_type, int, 0644); +MODULE_PARM_DESC(packet_type, + " Programmable Packet Type. Possible values:\n" + "\t\t 0x87: DRM InfoFrame (Default).\n" + "\t\t 0x01: Audio Clock Regeneration Packet\n" + "\t\t 0x02: Audio Sample Packet\n" + "\t\t 0x03: General Control Packet\n" + "\t\t 0x04: ACP Packet\n" + "\t\t 0x07: One Bit Audio Sample Packet\n" + "\t\t 0x08: DST Audio Packet\n" + "\t\t 0x09: High Bitrate Audio Stream Packet\n" + "\t\t 0x0a: Gamut Metadata Packet\n"); MODULE_DESCRIPTION("Toshiba TC358743 HDMI to CSI-2 bridge driver"); MODULE_AUTHOR("Ramakrishnan Muthukrishnan <ram@rkrishnan.org>"); @@ -466,10 +480,29 @@ tc358743_debugfs_if_read(u32 type, void *priv, struct file *filp, if (!is_hdmi(sd)) return 0; - if (type != V4L2_DEBUGFS_IF_AVI) + switch (type) { + case V4L2_DEBUGFS_IF_AVI: + i2c_rd(sd, PK_AVI_0HEAD, buf, PK_AVI_LEN); + break; + case V4L2_DEBUGFS_IF_AUDIO: + i2c_rd(sd, PK_AUD_0HEAD, buf, PK_AUD_LEN); + break; + case V4L2_DEBUGFS_IF_SPD: + i2c_rd(sd, PK_SPD_0HEAD, buf, PK_SPD_LEN); + break; + case V4L2_DEBUGFS_IF_HDMI: + i2c_rd(sd, PK_VS_0HEAD, buf, PK_VS_LEN); + break; + case V4L2_DEBUGFS_IF_DRM: + i2c_rd(sd, PK_ACP_0HEAD, buf, PK_ACP_LEN); + break; + default: return 0; + } + + if (!buf[2]) + return -ENOENT; - i2c_rd(sd, PK_AVI_0HEAD, buf, PK_AVI_16BYTE - PK_AVI_0HEAD + 1); len = buf[2] + 4; if (len > V4L2_DEBUGFS_IF_MAX_LEN) len = -ENOENT; @@ -478,26 +511,69 @@ tc358743_debugfs_if_read(u32 type, void *priv, struct file *filp, return len < 0 ? 0 : len; } -static void print_avi_infoframe(struct v4l2_subdev *sd) +static void print_infoframes(struct v4l2_subdev *sd) { struct i2c_client *client = v4l2_get_subdevdata(sd); struct device *dev = &client->dev; union hdmi_infoframe frame; - u8 buffer[HDMI_INFOFRAME_SIZE(AVI)] = {}; + u8 buffer[V4L2_DEBUGFS_IF_MAX_LEN] = {}; + + /* + * Updating the ACP TYPE here allows for dynamically + * changing the type you want to monitor, without having + * to reload the driver with a new packet_type module option value. + * + * Instead you can set it with the new value, then call + * VIDIOC_LOG_STATUS. + */ + i2c_wr8(sd, TYP_ACP_SET, packet_type); if (!is_hdmi(sd)) { - v4l2_info(sd, "DVI-D signal - AVI infoframe not supported\n"); + v4l2_info(sd, "DVI-D signal - InfoFrames not supported\n"); return; } - i2c_rd(sd, PK_AVI_0HEAD, buffer, HDMI_INFOFRAME_SIZE(AVI)); + i2c_rd(sd, PK_AVI_0HEAD, buffer, PK_AVI_LEN); + if (hdmi_infoframe_unpack(&frame, buffer, sizeof(buffer)) >= 0) + hdmi_infoframe_log(KERN_INFO, dev, &frame); - if (hdmi_infoframe_unpack(&frame, buffer, sizeof(buffer)) < 0) { - v4l2_err(sd, "%s: unpack of AVI infoframe failed\n", __func__); - return; + i2c_rd(sd, PK_VS_0HEAD, buffer, PK_VS_LEN); + if (hdmi_infoframe_unpack(&frame, buffer, sizeof(buffer)) >= 0) + hdmi_infoframe_log(KERN_INFO, dev, &frame); + + i2c_rd(sd, PK_AUD_0HEAD, buffer, PK_AUD_LEN); + if (hdmi_infoframe_unpack(&frame, buffer, sizeof(buffer)) >= 0) + hdmi_infoframe_log(KERN_INFO, dev, &frame); + + i2c_rd(sd, PK_SPD_0HEAD, buffer, PK_SPD_LEN); + if (hdmi_infoframe_unpack(&frame, buffer, sizeof(buffer)) >= 0) + hdmi_infoframe_log(KERN_INFO, dev, &frame); + + i2c_rd(sd, PK_ACP_0HEAD, buffer, PK_ACP_LEN); + if (buffer[0] == packet_type) { + if (packet_type < 0x80) + v4l2_info(sd, "Packet: %*ph\n", PK_ACP_LEN, buffer); + else if (packet_type != 0x87) + v4l2_info(sd, "InfoFrame: %*ph\n", PK_ACP_LEN, buffer); + else if (hdmi_infoframe_unpack(&frame, buffer, + sizeof(buffer)) >= 0) + hdmi_infoframe_log(KERN_INFO, dev, &frame); } - hdmi_infoframe_log(KERN_INFO, dev, &frame); + i2c_rd(sd, PK_MS_0HEAD, buffer, PK_MS_LEN); + if (buffer[2] && buffer[2] + 3 <= PK_MS_LEN) + v4l2_info(sd, "MPEG Source InfoFrame: %*ph\n", + buffer[2] + 3, buffer); + + i2c_rd(sd, PK_ISRC1_0HEAD, buffer, PK_ISRC1_LEN); + if (buffer[0] == 0x05) + v4l2_info(sd, "ISRC1 Packet: %*ph\n", + PK_ISRC1_LEN, buffer); + + i2c_rd(sd, PK_ISRC2_0HEAD, buffer, PK_ISRC2_LEN); + if (buffer[0] == 0x06) + v4l2_info(sd, "ISRC2 Packet: %*ph\n", + PK_ISRC2_LEN, buffer); } /* --------------- CTRLS --------------- */ @@ -1375,7 +1451,7 @@ static int tc358743_log_status(struct v4l2_subdev *sd) v4l2_info(sd, "Deep color mode: %d-bits per channel\n", deep_color_mode[(i2c_rd8(sd, VI_STATUS1) & MASK_S_DEEPCOLOR) >> 2]); - print_avi_infoframe(sd); + print_infoframes(sd); return 0; } @@ -2232,10 +2308,15 @@ static int tc358743_probe(struct i2c_client *client) if (err < 0) goto err_work_queues; + i2c_wr8(sd, TYP_ACP_SET, packet_type); + i2c_wr8(sd, PK_AUTO_CLR, 0xff); + i2c_wr8(sd, NO_PKT_CLR, MASK_NO_ACP_CLR); + state->debugfs_dir = debugfs_create_dir(sd->name, v4l2_debugfs_root()); state->infoframes = v4l2_debugfs_if_alloc(state->debugfs_dir, - V4L2_DEBUGFS_IF_AVI, sd, - tc358743_debugfs_if_read); + V4L2_DEBUGFS_IF_AVI | V4L2_DEBUGFS_IF_AUDIO | + V4L2_DEBUGFS_IF_SPD | V4L2_DEBUGFS_IF_HDMI | + V4L2_DEBUGFS_IF_DRM, sd, tc358743_debugfs_if_read); v4l2_info(sd, "%s found @ 0x%x (%s)\n", client->name, client->addr << 1, client->adapter->name); @@ -2245,10 +2326,10 @@ static int tc358743_probe(struct i2c_client *client) err_work_queues: cec_unregister_adapter(state->cec_adap); if (!state->i2c_client->irq) { - timer_delete(&state->timer); + timer_delete_sync(&state->timer); flush_work(&state->work_i2c_poll); } - cancel_delayed_work(&state->delayed_work_enable_hotplug); + cancel_delayed_work_sync(&state->delayed_work_enable_hotplug); mutex_destroy(&state->confctl_mutex); err_hdl: media_entity_cleanup(&sd->entity); diff --git a/drivers/media/i2c/tc358743_regs.h b/drivers/media/i2c/tc358743_regs.h index 2495878dc358..aae288f8add3 100644 --- a/drivers/media/i2c/tc358743_regs.h +++ b/drivers/media/i2c/tc358743_regs.h @@ -692,6 +692,8 @@ #define MASK_NCO_F0_MOD_42MHZ 0x00 #define MASK_NCO_F0_MOD_27MHZ 0x01 +#define TYP_ACP_SET 0x8706 + #define PK_INT_MODE 0x8709 #define MASK_ISRC2_INT_MODE 0x80 #define MASK_ISRC_INT_MODE 0x40 @@ -702,6 +704,8 @@ #define MASK_AUD_INT_MODE 0x02 #define MASK_AVI_INT_MODE 0x01 +#define PK_AUTO_CLR 0x870a + #define NO_PKT_LIMIT 0x870B #define MASK_NO_ACP_LIMIT 0xf0 #define SET_NO_ACP_LIMIT_MS(milliseconds) ((((milliseconds) / 80) << 4) & \ @@ -720,25 +724,44 @@ #define ERR_PK_LIMIT 0x870D #define NO_PKT_LIMIT2 0x870E #define PK_AVI_0HEAD 0x8710 -#define PK_AVI_1HEAD 0x8711 -#define PK_AVI_2HEAD 0x8712 #define PK_AVI_0BYTE 0x8713 -#define PK_AVI_1BYTE 0x8714 -#define PK_AVI_2BYTE 0x8715 -#define PK_AVI_3BYTE 0x8716 -#define PK_AVI_4BYTE 0x8717 -#define PK_AVI_5BYTE 0x8718 -#define PK_AVI_6BYTE 0x8719 -#define PK_AVI_7BYTE 0x871A -#define PK_AVI_8BYTE 0x871B -#define PK_AVI_9BYTE 0x871C -#define PK_AVI_10BYTE 0x871D -#define PK_AVI_11BYTE 0x871E -#define PK_AVI_12BYTE 0x871F -#define PK_AVI_13BYTE 0x8720 -#define PK_AVI_14BYTE 0x8721 -#define PK_AVI_15BYTE 0x8722 #define PK_AVI_16BYTE 0x8723 +#define PK_AVI_LEN (PK_AVI_16BYTE - PK_AVI_0HEAD + 1) + +#define PK_AUD_0HEAD 0x8730 +#define PK_AUD_0BYTE 0x8733 +#define PK_AUD_10BYTE 0x873d +#define PK_AUD_LEN (PK_AUD_10BYTE - PK_AUD_0HEAD + 1) + +#define PK_MS_0HEAD 0x8740 +#define PK_MS_0BYTE 0x8743 +#define PK_MS_10BYTE 0x874d +#define PK_MS_LEN (PK_MS_10BYTE - PK_MS_0HEAD + 1) + +#define PK_SPD_0HEAD 0x8750 +#define PK_SPD_0BYTE 0x8753 +#define PK_SPD_27BYTE 0x876e +#define PK_SPD_LEN (PK_SPD_27BYTE - PK_SPD_0HEAD + 1) + +#define PK_VS_0HEAD 0x8770 +#define PK_VS_0BYTE 0x8773 +#define PK_VS_27BYTE 0x878e +#define PK_VS_LEN (PK_VS_27BYTE - PK_VS_0HEAD + 1) + +#define PK_ACP_0HEAD 0x8790 +#define PK_ACP_0BYTE 0x8793 +#define PK_ACP_27BYTE 0x87ae +#define PK_ACP_LEN (PK_ACP_27BYTE - PK_ACP_0HEAD + 1) + +#define PK_ISRC1_0HEAD 0x87b0 +#define PK_ISRC1_0BYTE 0x87b3 +#define PK_ISRC1_27BYTE 0x87c2 +#define PK_ISRC1_LEN (PK_ISRC1_27BYTE - PK_ISRC1_0HEAD + 1) + +#define PK_ISRC2_0HEAD 0x87d0 +#define PK_ISRC2_0BYTE 0x87d3 +#define PK_ISRC2_27BYTE 0x87ee +#define PK_ISRC2_LEN (PK_ISRC2_27BYTE - PK_ISRC2_0HEAD + 1) #define BKSV 0x8800 diff --git a/drivers/media/i2c/tda9840.c b/drivers/media/i2c/tda9840.c index d61da811c9da..e3b266db571f 100644 --- a/drivers/media/i2c/tda9840.c +++ b/drivers/media/i2c/tda9840.c @@ -3,7 +3,7 @@ tda9840 - i2c-driver for the tda9840 by SGS Thomson Copyright (C) 1998-2003 Michael Hunold <michael@mihu.de> - Copyright (C) 2008 Hans Verkuil <hverkuil@xs4all.nl> + Copyright (C) 2008 Hans Verkuil <hverkuil@kernel.org> The tda9840 is a stereo/dual sound processor with digital identification. It can be found at address 0x84 on the i2c-bus. diff --git a/drivers/media/i2c/tea6415c.c b/drivers/media/i2c/tea6415c.c index 4aaf66353610..0cd2e6c52e20 100644 --- a/drivers/media/i2c/tea6415c.c +++ b/drivers/media/i2c/tea6415c.c @@ -3,7 +3,7 @@ tea6415c - i2c-driver for the tea6415c by SGS Thomson Copyright (C) 1998-2003 Michael Hunold <michael@mihu.de> - Copyright (C) 2008 Hans Verkuil <hverkuil@xs4all.nl> + Copyright (C) 2008 Hans Verkuil <hverkuil@kernel.org> The tea6415c is a bus controlled video-matrix-switch with 8 inputs and 6 outputs. diff --git a/drivers/media/i2c/tea6420.c b/drivers/media/i2c/tea6420.c index 5c5ea3973251..400883fc0c0f 100644 --- a/drivers/media/i2c/tea6420.c +++ b/drivers/media/i2c/tea6420.c @@ -3,7 +3,7 @@ tea6420 - i2c-driver for the tea6420 by SGS Thomson Copyright (C) 1998-2003 Michael Hunold <michael@mihu.de> - Copyright (C) 2008 Hans Verkuil <hverkuil@xs4all.nl> + Copyright (C) 2008 Hans Verkuil <hverkuil@kernel.org> The tea6420 is a bus controlled audio-matrix with 5 stereo inputs, 4 stereo outputs and gain control for each output. diff --git a/drivers/media/i2c/ths7303.c b/drivers/media/i2c/ths7303.c index b7cedc5b3e8e..ff268ebeb4d9 100644 --- a/drivers/media/i2c/ths7303.c +++ b/drivers/media/i2c/ths7303.c @@ -7,7 +7,7 @@ * Author: Chaithrika U S <chaithrika@ti.com> * * Contributors: - * Hans Verkuil <hansverk@cisco.com> + * Hans Verkuil <hverkuil@kernel.org> * Lad, Prabhakar <prabhakar.lad@ti.com> * Martin Bugge <marbugge@cisco.com> * diff --git a/drivers/media/i2c/tlv320aic23b.c b/drivers/media/i2c/tlv320aic23b.c index b7b31b6192af..6f6bc5236565 100644 --- a/drivers/media/i2c/tlv320aic23b.c +++ b/drivers/media/i2c/tlv320aic23b.c @@ -7,7 +7,7 @@ * Based on wm8775 driver * * Copyright (C) 2004 Ulf Eklund <ivtv at eklund.to> - * Copyright (C) 2005 Hans Verkuil <hverkuil@xs4all.nl> + * Copyright (C) 2005 Hans Verkuil <hverkuil@kernel.org> */ #include <linux/module.h> diff --git a/drivers/media/i2c/upd64031a.c b/drivers/media/i2c/upd64031a.c index 9d0b72a213be..a178af46e695 100644 --- a/drivers/media/i2c/upd64031a.c +++ b/drivers/media/i2c/upd64031a.c @@ -4,7 +4,7 @@ * * 2003 by T.Adachi <tadachi@tadachi-net.com> * 2003 by Takeru KOMORIYA <komoriya@paken.org> - * 2006 by Hans Verkuil <hverkuil@xs4all.nl> + * 2006 by Hans Verkuil <hverkuil@kernel.org> */ diff --git a/drivers/media/i2c/upd64083.c b/drivers/media/i2c/upd64083.c index 2e99ed5da42c..5421dc5e32c9 100644 --- a/drivers/media/i2c/upd64083.c +++ b/drivers/media/i2c/upd64083.c @@ -4,7 +4,7 @@ * * 2003 by T.Adachi (tadachi@tadachi-net.com) * 2003 by Takeru KOMORIYA <komoriya@paken.org> - * 2006 by Hans Verkuil <hverkuil@xs4all.nl> + * 2006 by Hans Verkuil <hverkuil@kernel.org> */ #include <linux/module.h> diff --git a/drivers/media/i2c/vd55g1.c b/drivers/media/i2c/vd55g1.c index 7c39183dd44b..f09d6bf32641 100644 --- a/drivers/media/i2c/vd55g1.c +++ b/drivers/media/i2c/vd55g1.c @@ -66,7 +66,7 @@ #define VD55G1_REG_READOUT_CTRL CCI_REG8(0x052e) #define VD55G1_READOUT_CTRL_BIN_MODE_NORMAL 0 #define VD55G1_READOUT_CTRL_BIN_MODE_DIGITAL_X2 1 -#define VD55G1_REG_DUSTER_CTRL CCI_REG8(0x03ea) +#define VD55G1_REG_DUSTER_CTRL CCI_REG8(0x03ae) #define VD55G1_DUSTER_ENABLE BIT(0) #define VD55G1_DUSTER_DISABLE 0 #define VD55G1_DUSTER_DYN_ENABLE BIT(1) @@ -1860,7 +1860,7 @@ static int vd55g1_probe(struct i2c_client *client) if (ret) return dev_err_probe(dev, ret, "Failed to get regulators\n"); - sensor->xclk = devm_clk_get(dev, NULL); + sensor->xclk = devm_v4l2_sensor_clk_get(dev, NULL); if (IS_ERR(sensor->xclk)) return dev_err_probe(dev, PTR_ERR(sensor->xclk), "Failed to get xclk\n"); diff --git a/drivers/media/i2c/vd56g3.c b/drivers/media/i2c/vd56g3.c index d66e21ba4498..157acea9e286 100644 --- a/drivers/media/i2c/vd56g3.c +++ b/drivers/media/i2c/vd56g3.c @@ -1471,7 +1471,7 @@ static int vd56g3_probe(struct i2c_client *client) if (ret) return dev_err_probe(dev, ret, "Failed to get regulators\n"); - sensor->xclk = devm_clk_get(dev, NULL); + sensor->xclk = devm_v4l2_sensor_clk_get(dev, NULL); if (IS_ERR(sensor->xclk)) return dev_err_probe(dev, PTR_ERR(sensor->xclk), "Failed to get xclk\n"); diff --git a/drivers/media/i2c/vgxy61.c b/drivers/media/i2c/vgxy61.c index 5b0479f3a3c0..d64d0099e6fe 100644 --- a/drivers/media/i2c/vgxy61.c +++ b/drivers/media/i2c/vgxy61.c @@ -1181,6 +1181,21 @@ static int vgxy61_s_stream(struct v4l2_subdev *sd, int enable) return ret; } +static int vgxy61_get_frame_desc(struct v4l2_subdev *sd, unsigned int pad, + struct v4l2_mbus_frame_desc *fd) +{ + struct vgxy61_dev *sensor = to_vgxy61_dev(sd); + + fd->type = V4L2_MBUS_FRAME_DESC_TYPE_CSI2; + fd->num_entries = 1; + fd->entry[0].pixelcode = sensor->fmt.code; + fd->entry[0].stream = 0; + fd->entry[0].bus.csi2.vc = 0; + fd->entry[0].bus.csi2.dt = get_data_type_by_code(sensor->fmt.code); + + return 0; +} + static int vgxy61_set_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_state *sd_state, struct v4l2_subdev_format *format) @@ -1402,6 +1417,7 @@ static const struct v4l2_subdev_pad_ops vgxy61_pad_ops = { .set_fmt = vgxy61_set_fmt, .get_selection = vgxy61_get_selection, .enum_frame_size = vgxy61_enum_frame_size, + .get_frame_desc = vgxy61_get_frame_desc, }; static const struct v4l2_subdev_ops vgxy61_subdev_ops = { @@ -1761,11 +1777,11 @@ static int vgxy61_probe(struct i2c_client *client) return ret; } - sensor->xclk = devm_clk_get(dev, NULL); - if (IS_ERR(sensor->xclk)) { - dev_err(dev, "failed to get xclk\n"); - return PTR_ERR(sensor->xclk); - } + sensor->xclk = devm_v4l2_sensor_clk_get(dev, NULL); + if (IS_ERR(sensor->xclk)) + return dev_err_probe(dev, PTR_ERR(sensor->xclk), + "failed to get xclk\n"); + sensor->clk_freq = clk_get_rate(sensor->xclk); if (sensor->clk_freq < 6 * HZ_PER_MHZ || sensor->clk_freq > 27 * HZ_PER_MHZ) { diff --git a/drivers/media/i2c/vp27smpx.c b/drivers/media/i2c/vp27smpx.c index 06fd46a63c72..df21950be24f 100644 --- a/drivers/media/i2c/vp27smpx.c +++ b/drivers/media/i2c/vp27smpx.c @@ -2,7 +2,7 @@ /* * vp27smpx - driver version 0.0.1 * - * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl> + * Copyright (C) 2007 Hans Verkuil <hverkuil@kernel.org> * * Based on a tvaudio patch from Takahiro Adachi <tadachi@tadachi-net.com> * and Kazuhiko Kawakami <kazz-0@mail.goo.ne.jp> diff --git a/drivers/media/i2c/wm8739.c b/drivers/media/i2c/wm8739.c index c091b78a5b41..72eb10339d06 100644 --- a/drivers/media/i2c/wm8739.c +++ b/drivers/media/i2c/wm8739.c @@ -4,7 +4,7 @@ * * Copyright (C) 2005 T. Adachi <tadachi@tadachi-net.com> * - * Copyright (C) 2005 Hans Verkuil <hverkuil@xs4all.nl> + * Copyright (C) 2005 Hans Verkuil <hverkuil@kernel.org> * - Cleanup */ diff --git a/drivers/media/i2c/wm8775.c b/drivers/media/i2c/wm8775.c index 619b2988577c..56778d3bc28a 100644 --- a/drivers/media/i2c/wm8775.c +++ b/drivers/media/i2c/wm8775.c @@ -6,7 +6,7 @@ * * Based on saa7115 driver * - * Copyright (C) 2005 Hans Verkuil <hverkuil@xs4all.nl> + * Copyright (C) 2005 Hans Verkuil <hverkuil@kernel.org> * - Cleanup * - V4L2 API update * - sound fixes diff --git a/drivers/media/mc/mc-devnode.c b/drivers/media/mc/mc-devnode.c index 56444edaf136..6daa7aa99442 100644 --- a/drivers/media/mc/mc-devnode.c +++ b/drivers/media/mc/mc-devnode.c @@ -50,11 +50,6 @@ static void media_devnode_release(struct device *cd) { struct media_devnode *devnode = to_media_devnode(cd); - mutex_lock(&media_devnode_lock); - /* Mark device node number as free */ - clear_bit(devnode->minor, media_devnode_nums); - mutex_unlock(&media_devnode_lock); - /* Release media_devnode and perform other cleanups as needed. */ if (devnode->release) devnode->release(devnode); @@ -281,6 +276,7 @@ void media_devnode_unregister(struct media_devnode *devnode) /* Delete the cdev on this minor as well */ cdev_device_del(&devnode->cdev, &devnode->dev); devnode->media_dev = NULL; + clear_bit(devnode->minor, media_devnode_nums); mutex_unlock(&media_devnode_lock); put_device(&devnode->dev); diff --git a/drivers/media/mc/mc-entity.c b/drivers/media/mc/mc-entity.c index 045590905582..9519a537bfa2 100644 --- a/drivers/media/mc/mc-entity.c +++ b/drivers/media/mc/mc-entity.c @@ -682,8 +682,8 @@ done: return 0; dev_dbg(walk->mdev->dev, - "media pipeline: adding unconnected pads of '%s'\n", - local->entity->name); + "media pipeline: adding unconnected pads of '%s' reachable from pad %u\n", + origin->entity->name, origin->index); media_entity_for_each_pad(origin->entity, local) { /* @@ -691,7 +691,7 @@ done: * (already discovered through iterating over links) and pads * not internally connected. */ - if (origin == local || !local->num_links || + if (origin == local || local->num_links || !media_entity_has_pad_interdep(origin->entity, origin->index, local->index)) continue; diff --git a/drivers/media/mc/mc-request.c b/drivers/media/mc/mc-request.c index 5edfc2791ce7..f66f728b1b43 100644 --- a/drivers/media/mc/mc-request.c +++ b/drivers/media/mc/mc-request.c @@ -6,7 +6,7 @@ * Copyright (C) 2018 Intel Corporation * Copyright (C) 2018 Google, Inc. * - * Author: Hans Verkuil <hansverk@cisco.com> + * Author: Hans Verkuil <hverkuil@kernel.org> * Author: Sakari Ailus <sakari.ailus@linux.intel.com> */ diff --git a/drivers/media/pci/b2c2/flexcop-pci.c b/drivers/media/pci/b2c2/flexcop-pci.c index 486c8ec0fa60..ab53c5b02c48 100644 --- a/drivers/media/pci/b2c2/flexcop-pci.c +++ b/drivers/media/pci/b2c2/flexcop-pci.c @@ -411,7 +411,7 @@ static void flexcop_pci_remove(struct pci_dev *pdev) struct flexcop_pci *fc_pci = pci_get_drvdata(pdev); if (irq_chk_intv > 0) - cancel_delayed_work(&fc_pci->irq_check_work); + cancel_delayed_work_sync(&fc_pci->irq_check_work); flexcop_pci_dma_exit(fc_pci); flexcop_device_exit(fc_pci->fc_dev); diff --git a/drivers/media/pci/bt8xx/bttv-driver.c b/drivers/media/pci/bt8xx/bttv-driver.c index 9ce67f515843..17e4529e537a 100644 --- a/drivers/media/pci/bt8xx/bttv-driver.c +++ b/drivers/media/pci/bt8xx/bttv-driver.c @@ -1620,7 +1620,7 @@ static int bttv_g_std(struct file *file, void *priv, v4l2_std_id *id) return 0; } -static int bttv_querystd(struct file *file, void *f, v4l2_std_id *id) +static int bttv_querystd(struct file *file, void *priv, v4l2_std_id *id) { struct bttv *btv = video_drvdata(file); @@ -1750,7 +1750,7 @@ static int bttv_s_frequency(struct file *file, void *priv, return 0; } -static int bttv_log_status(struct file *file, void *f) +static int bttv_log_status(struct file *file, void *priv) { struct video_device *vdev = video_devdata(file); struct bttv *btv = video_drvdata(file); @@ -1761,7 +1761,7 @@ static int bttv_log_status(struct file *file, void *f) } #ifdef CONFIG_VIDEO_ADV_DEBUG -static int bttv_g_register(struct file *file, void *f, +static int bttv_g_register(struct file *file, void *priv, struct v4l2_dbg_register *reg) { struct bttv *btv = video_drvdata(file); @@ -1774,7 +1774,7 @@ static int bttv_g_register(struct file *file, void *f, return 0; } -static int bttv_s_register(struct file *file, void *f, +static int bttv_s_register(struct file *file, void *priv, const struct v4l2_dbg_register *reg) { struct bttv *btv = video_drvdata(file); @@ -2159,7 +2159,7 @@ static int bttv_enum_fmt_vid_cap(struct file *file, void *priv, return 0; } -static int bttv_g_parm(struct file *file, void *f, +static int bttv_g_parm(struct file *file, void *priv, struct v4l2_streamparm *parm) { struct bttv *btv = video_drvdata(file); @@ -2208,7 +2208,7 @@ static int bttv_g_pixelaspect(struct file *file, void *priv, return 0; } -static int bttv_g_selection(struct file *file, void *f, struct v4l2_selection *sel) +static int bttv_g_selection(struct file *file, void *priv, struct v4l2_selection *sel) { struct bttv *btv = video_drvdata(file); @@ -2232,7 +2232,7 @@ static int bttv_g_selection(struct file *file, void *f, struct v4l2_selection *s return 0; } -static int bttv_s_selection(struct file *file, void *f, struct v4l2_selection *sel) +static int bttv_s_selection(struct file *file, void *priv, struct v4l2_selection *sel) { struct bttv *btv = video_drvdata(file); const struct v4l2_rect *b; diff --git a/drivers/media/pci/bt8xx/bttv-vbi.c b/drivers/media/pci/bt8xx/bttv-vbi.c index a71440611e46..0ca88a2400ee 100644 --- a/drivers/media/pci/bt8xx/bttv-vbi.c +++ b/drivers/media/pci/bt8xx/bttv-vbi.c @@ -241,7 +241,7 @@ static int try_fmt(struct v4l2_vbi_format *f, const struct bttv_tvnorm *tvnorm, return 0; } -int bttv_try_fmt_vbi_cap(struct file *file, void *f, struct v4l2_format *frt) +int bttv_try_fmt_vbi_cap(struct file *file, void *priv, struct v4l2_format *frt) { struct bttv *btv = video_drvdata(file); const struct bttv_tvnorm *tvnorm; @@ -258,7 +258,7 @@ int bttv_try_fmt_vbi_cap(struct file *file, void *f, struct v4l2_format *frt) } -int bttv_s_fmt_vbi_cap(struct file *file, void *f, struct v4l2_format *frt) +int bttv_s_fmt_vbi_cap(struct file *file, void *priv, struct v4l2_format *frt) { struct bttv *btv = video_drvdata(file); const struct bttv_tvnorm *tvnorm; @@ -301,7 +301,7 @@ int bttv_s_fmt_vbi_cap(struct file *file, void *f, struct v4l2_format *frt) } -int bttv_g_fmt_vbi_cap(struct file *file, void *f, struct v4l2_format *frt) +int bttv_g_fmt_vbi_cap(struct file *file, void *priv, struct v4l2_format *frt) { const struct bttv_tvnorm *tvnorm; struct bttv *btv = video_drvdata(file); diff --git a/drivers/media/pci/cobalt/cobalt-driver.c b/drivers/media/pci/cobalt/cobalt-driver.c index 39e25cc53edb..b7695705fdee 100644 --- a/drivers/media/pci/cobalt/cobalt-driver.c +++ b/drivers/media/pci/cobalt/cobalt-driver.c @@ -44,7 +44,7 @@ module_param_named(ignore_err, cobalt_ignore_err, int, 0644); MODULE_PARM_DESC(ignore_err, "If set then ignore missing i2c adapters/receivers. Default: 0\n"); -MODULE_AUTHOR("Hans Verkuil <hansverk@cisco.com> & Morten Hestnes"); +MODULE_AUTHOR("Hans Verkuil <hverkuil@kernel.org> & Morten Hestnes"); MODULE_DESCRIPTION("cobalt driver"); MODULE_LICENSE("GPL"); diff --git a/drivers/media/pci/cobalt/cobalt-v4l2.c b/drivers/media/pci/cobalt/cobalt-v4l2.c index ae82427e3479..51fd9576c6c2 100644 --- a/drivers/media/pci/cobalt/cobalt-v4l2.c +++ b/drivers/media/pci/cobalt/cobalt-v4l2.c @@ -447,7 +447,7 @@ static int cobalt_cobaltc(struct cobalt *cobalt, unsigned int cmd, void *arg) return 0; } -static int cobalt_g_register(struct file *file, void *priv_fh, +static int cobalt_g_register(struct file *file, void *priv, struct v4l2_dbg_register *reg) { struct cobalt_stream *s = video_drvdata(file); @@ -456,7 +456,7 @@ static int cobalt_g_register(struct file *file, void *priv_fh, return cobalt_cobaltc(cobalt, VIDIOC_DBG_G_REGISTER, reg); } -static int cobalt_s_register(struct file *file, void *priv_fh, +static int cobalt_s_register(struct file *file, void *priv, const struct v4l2_dbg_register *reg) { struct cobalt_stream *s = video_drvdata(file); @@ -467,7 +467,7 @@ static int cobalt_s_register(struct file *file, void *priv_fh, } #endif -static int cobalt_querycap(struct file *file, void *priv_fh, +static int cobalt_querycap(struct file *file, void *priv, struct v4l2_capability *vcap) { struct cobalt_stream *s = video_drvdata(file); @@ -562,7 +562,7 @@ static void cobalt_video_input_status_show(struct cobalt_stream *s) cobalt_info("rx%d: Packer: %x\n", rx, ioread32(&packer->control)); } -static int cobalt_log_status(struct file *file, void *priv_fh) +static int cobalt_log_status(struct file *file, void *priv) { struct cobalt_stream *s = video_drvdata(file); struct cobalt *cobalt = s->cobalt; @@ -596,7 +596,7 @@ static int cobalt_log_status(struct file *file, void *priv_fh) return 0; } -static int cobalt_enum_dv_timings(struct file *file, void *priv_fh, +static int cobalt_enum_dv_timings(struct file *file, void *priv, struct v4l2_enum_dv_timings *timings) { struct cobalt_stream *s = video_drvdata(file); @@ -613,7 +613,7 @@ static int cobalt_enum_dv_timings(struct file *file, void *priv_fh, pad, enum_dv_timings, timings); } -static int cobalt_s_dv_timings(struct file *file, void *priv_fh, +static int cobalt_s_dv_timings(struct file *file, void *priv, struct v4l2_dv_timings *timings) { struct cobalt_stream *s = video_drvdata(file); @@ -641,7 +641,7 @@ static int cobalt_s_dv_timings(struct file *file, void *priv_fh, return err; } -static int cobalt_g_dv_timings(struct file *file, void *priv_fh, +static int cobalt_g_dv_timings(struct file *file, void *priv, struct v4l2_dv_timings *timings) { struct cobalt_stream *s = video_drvdata(file); @@ -654,7 +654,7 @@ static int cobalt_g_dv_timings(struct file *file, void *priv_fh, pad, g_dv_timings, 0, timings); } -static int cobalt_query_dv_timings(struct file *file, void *priv_fh, +static int cobalt_query_dv_timings(struct file *file, void *priv, struct v4l2_dv_timings *timings) { struct cobalt_stream *s = video_drvdata(file); @@ -667,7 +667,7 @@ static int cobalt_query_dv_timings(struct file *file, void *priv_fh, pad, query_dv_timings, 0, timings); } -static int cobalt_dv_timings_cap(struct file *file, void *priv_fh, +static int cobalt_dv_timings_cap(struct file *file, void *priv, struct v4l2_dv_timings_cap *cap) { struct cobalt_stream *s = video_drvdata(file); @@ -677,7 +677,7 @@ static int cobalt_dv_timings_cap(struct file *file, void *priv_fh, pad, dv_timings_cap, cap); } -static int cobalt_enum_fmt_vid_cap(struct file *file, void *priv_fh, +static int cobalt_enum_fmt_vid_cap(struct file *file, void *priv, struct v4l2_fmtdesc *f) { switch (f->index) { @@ -697,7 +697,7 @@ static int cobalt_enum_fmt_vid_cap(struct file *file, void *priv_fh, return 0; } -static int cobalt_g_fmt_vid_cap(struct file *file, void *priv_fh, +static int cobalt_g_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *f) { struct cobalt_stream *s = video_drvdata(file); @@ -726,7 +726,7 @@ static int cobalt_g_fmt_vid_cap(struct file *file, void *priv_fh, return 0; } -static int cobalt_try_fmt_vid_cap(struct file *file, void *priv_fh, +static int cobalt_try_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *f) { struct cobalt_stream *s = video_drvdata(file); @@ -787,7 +787,7 @@ static int cobalt_try_fmt_vid_cap(struct file *file, void *priv_fh, return 0; } -static int cobalt_s_fmt_vid_cap(struct file *file, void *priv_fh, +static int cobalt_s_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *f) { struct cobalt_stream *s = video_drvdata(file); @@ -796,7 +796,7 @@ static int cobalt_s_fmt_vid_cap(struct file *file, void *priv_fh, if (vb2_is_busy(&s->q)) return -EBUSY; - if (cobalt_try_fmt_vid_cap(file, priv_fh, f)) + if (cobalt_try_fmt_vid_cap(file, priv, f)) return -EINVAL; s->width = pix->width; @@ -821,7 +821,7 @@ static int cobalt_s_fmt_vid_cap(struct file *file, void *priv_fh, return 0; } -static int cobalt_try_fmt_vid_out(struct file *file, void *priv_fh, +static int cobalt_try_fmt_vid_out(struct file *file, void *priv, struct v4l2_format *f) { struct v4l2_pix_format *pix = &f->fmt.pix; @@ -862,7 +862,7 @@ static int cobalt_try_fmt_vid_out(struct file *file, void *priv_fh, return 0; } -static int cobalt_g_fmt_vid_out(struct file *file, void *priv_fh, +static int cobalt_g_fmt_vid_out(struct file *file, void *priv, struct v4l2_format *f) { struct cobalt_stream *s = video_drvdata(file); @@ -882,7 +882,7 @@ static int cobalt_g_fmt_vid_out(struct file *file, void *priv_fh, return 0; } -static int cobalt_enum_fmt_vid_out(struct file *file, void *priv_fh, +static int cobalt_enum_fmt_vid_out(struct file *file, void *priv, struct v4l2_fmtdesc *f) { switch (f->index) { @@ -899,7 +899,7 @@ static int cobalt_enum_fmt_vid_out(struct file *file, void *priv_fh, return 0; } -static int cobalt_s_fmt_vid_out(struct file *file, void *priv_fh, +static int cobalt_s_fmt_vid_out(struct file *file, void *priv, struct v4l2_format *f) { struct cobalt_stream *s = video_drvdata(file); @@ -909,7 +909,7 @@ static int cobalt_s_fmt_vid_out(struct file *file, void *priv_fh, }; u32 code; - if (cobalt_try_fmt_vid_out(file, priv_fh, f)) + if (cobalt_try_fmt_vid_out(file, priv, f)) return -EINVAL; if (vb2_is_busy(&s->q) && (pix->pixelformat != s->pixfmt || @@ -942,7 +942,7 @@ static int cobalt_s_fmt_vid_out(struct file *file, void *priv_fh, return 0; } -static int cobalt_enum_input(struct file *file, void *priv_fh, +static int cobalt_enum_input(struct file *file, void *priv, struct v4l2_input *inp) { struct cobalt_stream *s = video_drvdata(file); @@ -963,7 +963,7 @@ static int cobalt_enum_input(struct file *file, void *priv_fh, video, g_input_status, &inp->status); } -static int cobalt_g_input(struct file *file, void *priv_fh, unsigned int *i) +static int cobalt_g_input(struct file *file, void *priv, unsigned int *i) { struct cobalt_stream *s = video_drvdata(file); @@ -971,7 +971,7 @@ static int cobalt_g_input(struct file *file, void *priv_fh, unsigned int *i) return 0; } -static int cobalt_s_input(struct file *file, void *priv_fh, unsigned int i) +static int cobalt_s_input(struct file *file, void *priv, unsigned int i) { struct cobalt_stream *s = video_drvdata(file); @@ -990,7 +990,7 @@ static int cobalt_s_input(struct file *file, void *priv_fh, unsigned int i) ADV76XX_PAD_HDMI_PORT_A, 0, 0); } -static int cobalt_enum_output(struct file *file, void *priv_fh, +static int cobalt_enum_output(struct file *file, void *priv, struct v4l2_output *out) { if (out->index) @@ -1001,18 +1001,18 @@ static int cobalt_enum_output(struct file *file, void *priv_fh, return 0; } -static int cobalt_g_output(struct file *file, void *priv_fh, unsigned int *i) +static int cobalt_g_output(struct file *file, void *priv, unsigned int *i) { *i = 0; return 0; } -static int cobalt_s_output(struct file *file, void *priv_fh, unsigned int i) +static int cobalt_s_output(struct file *file, void *priv, unsigned int i) { return i ? -EINVAL : 0; } -static int cobalt_g_edid(struct file *file, void *fh, struct v4l2_edid *edid) +static int cobalt_g_edid(struct file *file, void *priv, struct v4l2_edid *edid) { struct cobalt_stream *s = video_drvdata(file); u32 pad = edid->pad; @@ -1026,7 +1026,7 @@ static int cobalt_g_edid(struct file *file, void *fh, struct v4l2_edid *edid) return ret; } -static int cobalt_s_edid(struct file *file, void *fh, struct v4l2_edid *edid) +static int cobalt_s_edid(struct file *file, void *priv, struct v4l2_edid *edid) { struct cobalt_stream *s = video_drvdata(file); u32 pad = edid->pad; @@ -1050,7 +1050,7 @@ static int cobalt_subscribe_event(struct v4l2_fh *fh, return v4l2_ctrl_subscribe_event(fh, sub); } -static int cobalt_g_parm(struct file *file, void *fh, struct v4l2_streamparm *a) +static int cobalt_g_parm(struct file *file, void *priv, struct v4l2_streamparm *a) { struct cobalt_stream *s = video_drvdata(file); struct v4l2_fract fps; @@ -1065,7 +1065,7 @@ static int cobalt_g_parm(struct file *file, void *fh, struct v4l2_streamparm *a) return 0; } -static int cobalt_g_pixelaspect(struct file *file, void *fh, +static int cobalt_g_pixelaspect(struct file *file, void *priv, int type, struct v4l2_fract *f) { struct cobalt_stream *s = video_drvdata(file); @@ -1084,7 +1084,7 @@ static int cobalt_g_pixelaspect(struct file *file, void *fh, return err; } -static int cobalt_g_selection(struct file *file, void *fh, +static int cobalt_g_selection(struct file *file, void *priv, struct v4l2_selection *sel) { struct cobalt_stream *s = video_drvdata(file); diff --git a/drivers/media/pci/cx18/cx18-audio.c b/drivers/media/pci/cx18/cx18-audio.c index 8602d088601b..1464795619f9 100644 --- a/drivers/media/pci/cx18/cx18-audio.c +++ b/drivers/media/pci/cx18/cx18-audio.c @@ -4,7 +4,7 @@ * * Derived from ivtv-audio.c * - * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl> + * Copyright (C) 2007 Hans Verkuil <hverkuil@kernel.org> */ #include "cx18-driver.h" diff --git a/drivers/media/pci/cx18/cx18-audio.h b/drivers/media/pci/cx18/cx18-audio.h index 36ce333ab07a..29cf89d38d60 100644 --- a/drivers/media/pci/cx18/cx18-audio.h +++ b/drivers/media/pci/cx18/cx18-audio.h @@ -4,7 +4,7 @@ * * Derived from ivtv-audio.c * - * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl> + * Copyright (C) 2007 Hans Verkuil <hverkuil@kernel.org> */ int cx18_audio_set_io(struct cx18 *cx); diff --git a/drivers/media/pci/cx18/cx18-av-audio.c b/drivers/media/pci/cx18/cx18-av-audio.c index 78e05df9a7ba..644d8ca4519b 100644 --- a/drivers/media/pci/cx18/cx18-av-audio.c +++ b/drivers/media/pci/cx18/cx18-av-audio.c @@ -4,7 +4,7 @@ * * Derived from cx25840-audio.c * - * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl> + * Copyright (C) 2007 Hans Verkuil <hverkuil@kernel.org> * Copyright (C) 2008 Andy Walls <awalls@md.metrocast.net> */ diff --git a/drivers/media/pci/cx18/cx18-av-core.c b/drivers/media/pci/cx18/cx18-av-core.c index ee6e71157786..4fb19d26ee29 100644 --- a/drivers/media/pci/cx18/cx18-av-core.c +++ b/drivers/media/pci/cx18/cx18-av-core.c @@ -4,7 +4,7 @@ * * Derived from cx25840-core.c * - * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl> + * Copyright (C) 2007 Hans Verkuil <hverkuil@kernel.org> * Copyright (C) 2008 Andy Walls <awalls@md.metrocast.net> */ diff --git a/drivers/media/pci/cx18/cx18-av-core.h b/drivers/media/pci/cx18/cx18-av-core.h index 55aceb064b33..71ac9d7af28f 100644 --- a/drivers/media/pci/cx18/cx18-av-core.h +++ b/drivers/media/pci/cx18/cx18-av-core.h @@ -4,7 +4,7 @@ * * Derived from cx25840-core.h * - * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl> + * Copyright (C) 2007 Hans Verkuil <hverkuil@kernel.org> * Copyright (C) 2008 Andy Walls <awalls@md.metrocast.net> */ diff --git a/drivers/media/pci/cx18/cx18-av-firmware.c b/drivers/media/pci/cx18/cx18-av-firmware.c index 61aeb8c9af7f..02dde685a6ad 100644 --- a/drivers/media/pci/cx18/cx18-av-firmware.c +++ b/drivers/media/pci/cx18/cx18-av-firmware.c @@ -2,7 +2,7 @@ /* * cx18 ADEC firmware functions * - * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl> + * Copyright (C) 2007 Hans Verkuil <hverkuil@kernel.org> * Copyright (C) 2008 Andy Walls <awalls@md.metrocast.net> */ diff --git a/drivers/media/pci/cx18/cx18-av-vbi.c b/drivers/media/pci/cx18/cx18-av-vbi.c index 1a113aad9cd4..f9beeaeaa1cb 100644 --- a/drivers/media/pci/cx18/cx18-av-vbi.c +++ b/drivers/media/pci/cx18/cx18-av-vbi.c @@ -4,7 +4,7 @@ * * Derived from cx25840-vbi.c * - * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl> + * Copyright (C) 2007 Hans Verkuil <hverkuil@kernel.org> */ diff --git a/drivers/media/pci/cx18/cx18-cards.c b/drivers/media/pci/cx18/cx18-cards.c index f5a30959a367..bddb9e0fffe0 100644 --- a/drivers/media/pci/cx18/cx18-cards.c +++ b/drivers/media/pci/cx18/cx18-cards.c @@ -4,7 +4,7 @@ * * Derived from ivtv-cards.c * - * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl> + * Copyright (C) 2007 Hans Verkuil <hverkuil@kernel.org> * Copyright (C) 2008 Andy Walls <awalls@md.metrocast.net> */ diff --git a/drivers/media/pci/cx18/cx18-cards.h b/drivers/media/pci/cx18/cx18-cards.h index ae9cf5bfdd59..511123b741d5 100644 --- a/drivers/media/pci/cx18/cx18-cards.h +++ b/drivers/media/pci/cx18/cx18-cards.h @@ -4,7 +4,7 @@ * * Derived from ivtv-cards.c * - * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl> + * Copyright (C) 2007 Hans Verkuil <hverkuil@kernel.org> * Copyright (C) 2008 Andy Walls <awalls@md.metrocast.net> */ diff --git a/drivers/media/pci/cx18/cx18-controls.c b/drivers/media/pci/cx18/cx18-controls.c index bb5fc120473c..78eadad8b6e8 100644 --- a/drivers/media/pci/cx18/cx18-controls.c +++ b/drivers/media/pci/cx18/cx18-controls.c @@ -4,7 +4,7 @@ * * Derived from ivtv-controls.c * - * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl> + * Copyright (C) 2007 Hans Verkuil <hverkuil@kernel.org> */ #include <linux/kernel.h> #include <linux/slab.h> diff --git a/drivers/media/pci/cx18/cx18-controls.h b/drivers/media/pci/cx18/cx18-controls.h index 458a3595a2ae..99de78878a76 100644 --- a/drivers/media/pci/cx18/cx18-controls.h +++ b/drivers/media/pci/cx18/cx18-controls.h @@ -4,7 +4,7 @@ * * Derived from ivtv-controls.h * - * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl> + * Copyright (C) 2007 Hans Verkuil <hverkuil@kernel.org> */ diff --git a/drivers/media/pci/cx18/cx18-driver.c b/drivers/media/pci/cx18/cx18-driver.c index 743fcc961374..b62fd12c93c1 100644 --- a/drivers/media/pci/cx18/cx18-driver.c +++ b/drivers/media/pci/cx18/cx18-driver.c @@ -4,7 +4,7 @@ * * Derived from ivtv-driver.c * - * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl> + * Copyright (C) 2007 Hans Verkuil <hverkuil@kernel.org> * Copyright (C) 2008 Andy Walls <awalls@md.metrocast.net> */ diff --git a/drivers/media/pci/cx18/cx18-driver.h b/drivers/media/pci/cx18/cx18-driver.h index 485ca9747c4c..ef38903709d0 100644 --- a/drivers/media/pci/cx18/cx18-driver.h +++ b/drivers/media/pci/cx18/cx18-driver.h @@ -4,7 +4,7 @@ * * Derived from ivtv-driver.h * - * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl> + * Copyright (C) 2007 Hans Verkuil <hverkuil@kernel.org> * Copyright (C) 2008 Andy Walls <awalls@md.metrocast.net> */ @@ -414,7 +414,7 @@ static inline struct cx18_open_id *fh2id(struct v4l2_fh *fh) static inline struct cx18_open_id *file2id(struct file *file) { - return fh2id(file->private_data); + return fh2id(file_to_v4l2_fh(file)); } /* forward declaration of struct defined in cx18-cards.h */ diff --git a/drivers/media/pci/cx18/cx18-fileops.c b/drivers/media/pci/cx18/cx18-fileops.c index cefa91b37f89..4944033dbb20 100644 --- a/drivers/media/pci/cx18/cx18-fileops.c +++ b/drivers/media/pci/cx18/cx18-fileops.c @@ -4,7 +4,7 @@ * * Derived from ivtv-fileops.c * - * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl> + * Copyright (C) 2007 Hans Verkuil <hverkuil@kernel.org> * Copyright (C) 2008 Andy Walls <awalls@md.metrocast.net> */ @@ -678,7 +678,7 @@ void cx18_stop_capture(struct cx18_stream *s, int gop_end) int cx18_v4l2_close(struct file *filp) { - struct v4l2_fh *fh = filp->private_data; + struct v4l2_fh *fh = file_to_v4l2_fh(filp); struct cx18_open_id *id = fh2id(fh); struct cx18 *cx = id->cx; struct cx18_stream *s = &cx->streams[id->type]; @@ -709,11 +709,11 @@ int cx18_v4l2_close(struct file *filp) } if (id->type == CX18_ENC_STREAM_TYPE_YUV && - filp->private_data == vdev->queue->owner) { + file_to_v4l2_fh(filp) == vdev->queue->owner) { vb2_queue_release(vdev->queue); vdev->queue->owner = NULL; } - v4l2_fh_del(fh); + v4l2_fh_del(fh, filp); v4l2_fh_exit(fh); /* 'Unclaim' this stream */ @@ -743,8 +743,7 @@ static int cx18_serialized_open(struct cx18_stream *s, struct file *filp) item->type = s->type; item->open_id = cx->open_id++; - filp->private_data = &item->fh; - v4l2_fh_add(&item->fh); + v4l2_fh_add(&item->fh, filp); if (item->type == CX18_ENC_STREAM_TYPE_RAD && v4l2_fh_is_singular_file(filp)) { @@ -752,7 +751,7 @@ static int cx18_serialized_open(struct cx18_stream *s, struct file *filp) if (atomic_read(&cx->ana_capturing) > 0) { /* switching to radio while capture is in progress is not polite */ - v4l2_fh_del(&item->fh); + v4l2_fh_del(&item->fh, filp); v4l2_fh_exit(&item->fh); kfree(item); return -EBUSY; diff --git a/drivers/media/pci/cx18/cx18-fileops.h b/drivers/media/pci/cx18/cx18-fileops.h index 943057b83d94..bc999ea85dc2 100644 --- a/drivers/media/pci/cx18/cx18-fileops.h +++ b/drivers/media/pci/cx18/cx18-fileops.h @@ -4,7 +4,7 @@ * * Derived from ivtv-fileops.h * - * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl> + * Copyright (C) 2007 Hans Verkuil <hverkuil@kernel.org> */ /* Testing/Debugging */ diff --git a/drivers/media/pci/cx18/cx18-firmware.c b/drivers/media/pci/cx18/cx18-firmware.c index 1b038b2802bf..94e17948fb30 100644 --- a/drivers/media/pci/cx18/cx18-firmware.c +++ b/drivers/media/pci/cx18/cx18-firmware.c @@ -2,7 +2,7 @@ /* * cx18 firmware functions * - * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl> + * Copyright (C) 2007 Hans Verkuil <hverkuil@kernel.org> * Copyright (C) 2008 Andy Walls <awalls@md.metrocast.net> */ diff --git a/drivers/media/pci/cx18/cx18-firmware.h b/drivers/media/pci/cx18/cx18-firmware.h index 1357f76d613e..8e63677284bd 100644 --- a/drivers/media/pci/cx18/cx18-firmware.h +++ b/drivers/media/pci/cx18/cx18-firmware.h @@ -2,7 +2,7 @@ /* * cx18 firmware functions * - * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl> + * Copyright (C) 2007 Hans Verkuil <hverkuil@kernel.org> */ int cx18_firmware_init(struct cx18 *cx); diff --git a/drivers/media/pci/cx18/cx18-gpio.c b/drivers/media/pci/cx18/cx18-gpio.c index 485a6cbeb15a..4aea92639599 100644 --- a/drivers/media/pci/cx18/cx18-gpio.c +++ b/drivers/media/pci/cx18/cx18-gpio.c @@ -4,7 +4,7 @@ * * Derived from ivtv-gpio.c * - * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl> + * Copyright (C) 2007 Hans Verkuil <hverkuil@kernel.org> * Copyright (C) 2008 Andy Walls <awalls@md.metrocast.net> */ diff --git a/drivers/media/pci/cx18/cx18-gpio.h b/drivers/media/pci/cx18/cx18-gpio.h index 8d5797dea7f5..3eefc4644101 100644 --- a/drivers/media/pci/cx18/cx18-gpio.h +++ b/drivers/media/pci/cx18/cx18-gpio.h @@ -4,7 +4,7 @@ * * Derived from ivtv-gpio.h * - * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl> + * Copyright (C) 2007 Hans Verkuil <hverkuil@kernel.org> * Copyright (C) 2008 Andy Walls <awalls@md.metrocast.net> */ diff --git a/drivers/media/pci/cx18/cx18-i2c.c b/drivers/media/pci/cx18/cx18-i2c.c index a83435245251..a1abb0631cae 100644 --- a/drivers/media/pci/cx18/cx18-i2c.c +++ b/drivers/media/pci/cx18/cx18-i2c.c @@ -4,7 +4,7 @@ * * Derived from ivtv-i2c.c * - * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl> + * Copyright (C) 2007 Hans Verkuil <hverkuil@kernel.org> * Copyright (C) 2008 Andy Walls <awalls@md.metrocast.net> */ diff --git a/drivers/media/pci/cx18/cx18-i2c.h b/drivers/media/pci/cx18/cx18-i2c.h index 4526cb324fec..8ae3125c78c0 100644 --- a/drivers/media/pci/cx18/cx18-i2c.h +++ b/drivers/media/pci/cx18/cx18-i2c.h @@ -4,7 +4,7 @@ * * Derived from ivtv-i2c.h * - * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl> + * Copyright (C) 2007 Hans Verkuil <hverkuil@kernel.org> */ int cx18_i2c_register(struct cx18 *cx, unsigned idx); diff --git a/drivers/media/pci/cx18/cx18-io.c b/drivers/media/pci/cx18/cx18-io.c index 50e4e8a598d4..1d3d006e6329 100644 --- a/drivers/media/pci/cx18/cx18-io.c +++ b/drivers/media/pci/cx18/cx18-io.c @@ -2,7 +2,7 @@ /* * cx18 driver PCI memory mapped IO access routines * - * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl> + * Copyright (C) 2007 Hans Verkuil <hverkuil@kernel.org> * Copyright (C) 2008 Andy Walls <awalls@md.metrocast.net> */ diff --git a/drivers/media/pci/cx18/cx18-io.h b/drivers/media/pci/cx18/cx18-io.h index 190b142d047e..1f0bfad7d0f0 100644 --- a/drivers/media/pci/cx18/cx18-io.h +++ b/drivers/media/pci/cx18/cx18-io.h @@ -2,7 +2,7 @@ /* * cx18 driver PCI memory mapped IO access routines * - * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl> + * Copyright (C) 2007 Hans Verkuil <hverkuil@kernel.org> * Copyright (C) 2008 Andy Walls <awalls@md.metrocast.net> */ diff --git a/drivers/media/pci/cx18/cx18-ioctl.c b/drivers/media/pci/cx18/cx18-ioctl.c index 9a1512b1ccaa..0f3019739d03 100644 --- a/drivers/media/pci/cx18/cx18-ioctl.c +++ b/drivers/media/pci/cx18/cx18-ioctl.c @@ -4,7 +4,7 @@ * * Derived from ivtv-ioctl.c * - * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl> + * Copyright (C) 2007 Hans Verkuil <hverkuil@kernel.org> * Copyright (C) 2008 Andy Walls <awalls@md.metrocast.net> */ @@ -52,7 +52,7 @@ static const struct v4l2_fmtdesc cx18_formats_mpeg[] = { static int cx18_g_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *fmt) { - struct cx18_open_id *id = fh2id(fh); + struct cx18_open_id *id = file2id(file); struct cx18 *cx = id->cx; struct cx18_stream *s = &cx->streams[id->type]; struct v4l2_pix_format *pixfmt = &fmt->fmt.pix; @@ -76,7 +76,7 @@ static int cx18_g_fmt_vid_cap(struct file *file, void *fh, static int cx18_try_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *fmt) { - struct cx18_open_id *id = fh2id(fh); + struct cx18_open_id *id = file2id(file); struct cx18 *cx = id->cx; struct v4l2_pix_format *pixfmt = &fmt->fmt.pix; int w = pixfmt->width; @@ -121,7 +121,7 @@ static int cx18_try_fmt_vid_cap(struct file *file, void *fh, static int cx18_s_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *fmt) { - struct cx18_open_id *id = fh2id(fh); + struct cx18_open_id *id = file2id(file); struct cx18 *cx = id->cx; struct v4l2_subdev_format format = { .which = V4L2_SUBDEV_FORMAT_ACTIVE, @@ -261,7 +261,7 @@ u16 cx18_get_service_set(struct v4l2_sliced_vbi_format *fmt) static int cx18_g_fmt_vbi_cap(struct file *file, void *fh, struct v4l2_format *fmt) { - struct cx18 *cx = fh2id(fh)->cx; + struct cx18 *cx = file2id(file)->cx; struct v4l2_vbi_format *vbifmt = &fmt->fmt.vbi; vbifmt->sampling_rate = 27000000; @@ -280,7 +280,7 @@ static int cx18_g_fmt_vbi_cap(struct file *file, void *fh, static int cx18_g_fmt_sliced_vbi_cap(struct file *file, void *fh, struct v4l2_format *fmt) { - struct cx18 *cx = fh2id(fh)->cx; + struct cx18 *cx = file2id(file)->cx; struct v4l2_sliced_vbi_format *vbifmt = &fmt->fmt.sliced; /* sane, V4L2 spec compliant, defaults */ @@ -311,7 +311,7 @@ static int cx18_try_fmt_vbi_cap(struct file *file, void *fh, static int cx18_try_fmt_sliced_vbi_cap(struct file *file, void *fh, struct v4l2_format *fmt) { - struct cx18 *cx = fh2id(fh)->cx; + struct cx18 *cx = file2id(file)->cx; struct v4l2_sliced_vbi_format *vbifmt = &fmt->fmt.sliced; vbifmt->io_size = sizeof(struct v4l2_sliced_vbi_data) * 36; @@ -330,7 +330,7 @@ static int cx18_try_fmt_sliced_vbi_cap(struct file *file, void *fh, static int cx18_s_fmt_vbi_cap(struct file *file, void *fh, struct v4l2_format *fmt) { - struct cx18_open_id *id = fh2id(fh); + struct cx18_open_id *id = file2id(file); struct cx18 *cx = id->cx; int ret; @@ -360,7 +360,7 @@ static int cx18_s_fmt_vbi_cap(struct file *file, void *fh, static int cx18_s_fmt_sliced_vbi_cap(struct file *file, void *fh, struct v4l2_format *fmt) { - struct cx18_open_id *id = fh2id(fh); + struct cx18_open_id *id = file2id(file); struct cx18 *cx = id->cx; int ret; struct v4l2_sliced_vbi_format *vbifmt = &fmt->fmt.sliced; @@ -392,7 +392,7 @@ static int cx18_s_fmt_sliced_vbi_cap(struct file *file, void *fh, static int cx18_g_register(struct file *file, void *fh, struct v4l2_dbg_register *reg) { - struct cx18 *cx = fh2id(fh)->cx; + struct cx18 *cx = file2id(file)->cx; if (reg->reg & 0x3) return -EINVAL; @@ -406,7 +406,7 @@ static int cx18_g_register(struct file *file, void *fh, static int cx18_s_register(struct file *file, void *fh, const struct v4l2_dbg_register *reg) { - struct cx18 *cx = fh2id(fh)->cx; + struct cx18 *cx = file2id(file)->cx; if (reg->reg & 0x3) return -EINVAL; @@ -420,7 +420,7 @@ static int cx18_s_register(struct file *file, void *fh, static int cx18_querycap(struct file *file, void *fh, struct v4l2_capability *vcap) { - struct cx18_open_id *id = fh2id(fh); + struct cx18_open_id *id = file2id(file); struct cx18 *cx = id->cx; strscpy(vcap->driver, CX18_DRIVER_NAME, sizeof(vcap->driver)); @@ -431,14 +431,14 @@ static int cx18_querycap(struct file *file, void *fh, static int cx18_enumaudio(struct file *file, void *fh, struct v4l2_audio *vin) { - struct cx18 *cx = fh2id(fh)->cx; + struct cx18 *cx = file2id(file)->cx; return cx18_get_audio_input(cx, vin->index, vin); } static int cx18_g_audio(struct file *file, void *fh, struct v4l2_audio *vin) { - struct cx18 *cx = fh2id(fh)->cx; + struct cx18 *cx = file2id(file)->cx; vin->index = cx->audio_input; return cx18_get_audio_input(cx, vin->index, vin); @@ -446,7 +446,7 @@ static int cx18_g_audio(struct file *file, void *fh, struct v4l2_audio *vin) static int cx18_s_audio(struct file *file, void *fh, const struct v4l2_audio *vout) { - struct cx18 *cx = fh2id(fh)->cx; + struct cx18 *cx = file2id(file)->cx; if (vout->index >= cx->nof_audio_inputs) return -EINVAL; @@ -457,7 +457,7 @@ static int cx18_s_audio(struct file *file, void *fh, const struct v4l2_audio *vo static int cx18_enum_input(struct file *file, void *fh, struct v4l2_input *vin) { - struct cx18 *cx = fh2id(fh)->cx; + struct cx18 *cx = file2id(file)->cx; /* set it to defaults from our table */ return cx18_get_input(cx, vin->index, vin); @@ -466,7 +466,7 @@ static int cx18_enum_input(struct file *file, void *fh, struct v4l2_input *vin) static int cx18_g_pixelaspect(struct file *file, void *fh, int type, struct v4l2_fract *f) { - struct cx18 *cx = fh2id(fh)->cx; + struct cx18 *cx = file2id(file)->cx; if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE) return -EINVAL; @@ -479,7 +479,7 @@ static int cx18_g_pixelaspect(struct file *file, void *fh, static int cx18_g_selection(struct file *file, void *fh, struct v4l2_selection *sel) { - struct cx18 *cx = fh2id(fh)->cx; + struct cx18 *cx = file2id(file)->cx; if (sel->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) return -EINVAL; @@ -499,7 +499,7 @@ static int cx18_g_selection(struct file *file, void *fh, static int cx18_enum_fmt_vid_cap(struct file *file, void *fh, struct v4l2_fmtdesc *fmt) { - struct cx18_open_id *id = fh2id(fh); + struct cx18_open_id *id = file2id(file); if (id->type == CX18_ENC_STREAM_TYPE_YUV) { if (fmt->index >= ARRAY_SIZE(cx18_formats_yuv)) @@ -515,7 +515,7 @@ static int cx18_enum_fmt_vid_cap(struct file *file, void *fh, static int cx18_g_input(struct file *file, void *fh, unsigned int *i) { - struct cx18 *cx = fh2id(fh)->cx; + struct cx18 *cx = file2id(file)->cx; *i = cx->active_input; return 0; @@ -523,7 +523,7 @@ static int cx18_g_input(struct file *file, void *fh, unsigned int *i) int cx18_s_input(struct file *file, void *fh, unsigned int inp) { - struct cx18_open_id *id = fh2id(fh); + struct cx18_open_id *id = file2id(file); struct cx18 *cx = id->cx; v4l2_std_id std = V4L2_STD_ALL; const struct cx18_card_video_input *card_input = @@ -561,7 +561,7 @@ int cx18_s_input(struct file *file, void *fh, unsigned int inp) static int cx18_g_frequency(struct file *file, void *fh, struct v4l2_frequency *vf) { - struct cx18 *cx = fh2id(fh)->cx; + struct cx18 *cx = file2id(file)->cx; if (vf->tuner != 0) return -EINVAL; @@ -572,7 +572,7 @@ static int cx18_g_frequency(struct file *file, void *fh, int cx18_s_frequency(struct file *file, void *fh, const struct v4l2_frequency *vf) { - struct cx18_open_id *id = fh2id(fh); + struct cx18_open_id *id = file2id(file); struct cx18 *cx = id->cx; if (vf->tuner != 0) @@ -587,7 +587,7 @@ int cx18_s_frequency(struct file *file, void *fh, const struct v4l2_frequency *v static int cx18_g_std(struct file *file, void *fh, v4l2_std_id *std) { - struct cx18 *cx = fh2id(fh)->cx; + struct cx18 *cx = file2id(file)->cx; *std = cx->std; return 0; @@ -595,7 +595,7 @@ static int cx18_g_std(struct file *file, void *fh, v4l2_std_id *std) int cx18_s_std(struct file *file, void *fh, v4l2_std_id std) { - struct cx18_open_id *id = fh2id(fh); + struct cx18_open_id *id = file2id(file); struct cx18 *cx = id->cx; if ((std & V4L2_STD_ALL) == 0) @@ -644,7 +644,7 @@ int cx18_s_std(struct file *file, void *fh, v4l2_std_id std) static int cx18_s_tuner(struct file *file, void *fh, const struct v4l2_tuner *vt) { - struct cx18_open_id *id = fh2id(fh); + struct cx18_open_id *id = file2id(file); struct cx18 *cx = id->cx; if (vt->index != 0) @@ -656,7 +656,7 @@ static int cx18_s_tuner(struct file *file, void *fh, const struct v4l2_tuner *vt static int cx18_g_tuner(struct file *file, void *fh, struct v4l2_tuner *vt) { - struct cx18 *cx = fh2id(fh)->cx; + struct cx18 *cx = file2id(file)->cx; if (vt->index != 0) return -EINVAL; @@ -673,7 +673,7 @@ static int cx18_g_tuner(struct file *file, void *fh, struct v4l2_tuner *vt) static int cx18_g_sliced_vbi_cap(struct file *file, void *fh, struct v4l2_sliced_vbi_cap *cap) { - struct cx18 *cx = fh2id(fh)->cx; + struct cx18 *cx = file2id(file)->cx; int set = cx->is_50hz ? V4L2_SLICED_VBI_625 : V4L2_SLICED_VBI_525; int f, l; @@ -794,7 +794,7 @@ static int cx18_process_idx_data(struct cx18_stream *s, struct cx18_mdl *mdl, static int cx18_g_enc_index(struct file *file, void *fh, struct v4l2_enc_idx *idx) { - struct cx18 *cx = fh2id(fh)->cx; + struct cx18 *cx = file2id(file)->cx; struct cx18_stream *s = &cx->streams[CX18_ENC_STREAM_TYPE_IDX]; s32 tmp; struct cx18_mdl *mdl; @@ -841,7 +841,7 @@ static int cx18_g_enc_index(struct file *file, void *fh, static int cx18_encoder_cmd(struct file *file, void *fh, struct v4l2_encoder_cmd *enc) { - struct cx18_open_id *id = fh2id(fh); + struct cx18_open_id *id = file2id(file); struct cx18 *cx = id->cx; u32 h; @@ -900,7 +900,7 @@ static int cx18_encoder_cmd(struct file *file, void *fh, static int cx18_try_encoder_cmd(struct file *file, void *fh, struct v4l2_encoder_cmd *enc) { - struct cx18 *cx = fh2id(fh)->cx; + struct cx18 *cx = file2id(file)->cx; switch (enc->cmd) { case V4L2_ENC_CMD_START: @@ -932,7 +932,7 @@ static int cx18_try_encoder_cmd(struct file *file, void *fh, static int cx18_log_status(struct file *file, void *fh) { - struct cx18 *cx = fh2id(fh)->cx; + struct cx18 *cx = file2id(file)->cx; struct v4l2_input vidin; struct v4l2_audio audin; int i; @@ -976,7 +976,7 @@ static int cx18_log_status(struct file *file, void *fh) static long cx18_default(struct file *file, void *fh, bool valid_prio, unsigned int cmd, void *arg) { - struct cx18 *cx = fh2id(fh)->cx; + struct cx18 *cx = file2id(file)->cx; switch (cmd) { case VIDIOC_INT_RESET: { diff --git a/drivers/media/pci/cx18/cx18-ioctl.h b/drivers/media/pci/cx18/cx18-ioctl.h index 221e2400fb3e..97cd9f99e22d 100644 --- a/drivers/media/pci/cx18/cx18-ioctl.h +++ b/drivers/media/pci/cx18/cx18-ioctl.h @@ -4,7 +4,7 @@ * * Derived from ivtv-ioctl.h * - * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl> + * Copyright (C) 2007 Hans Verkuil <hverkuil@kernel.org> * Copyright (C) 2008 Andy Walls <awalls@md.metrocast.net> */ diff --git a/drivers/media/pci/cx18/cx18-irq.c b/drivers/media/pci/cx18/cx18-irq.c index db63077821b1..0ef01e98255d 100644 --- a/drivers/media/pci/cx18/cx18-irq.c +++ b/drivers/media/pci/cx18/cx18-irq.c @@ -2,7 +2,7 @@ /* * cx18 interrupt handling * - * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl> + * Copyright (C) 2007 Hans Verkuil <hverkuil@kernel.org> * Copyright (C) 2008 Andy Walls <awalls@md.metrocast.net> */ diff --git a/drivers/media/pci/cx18/cx18-irq.h b/drivers/media/pci/cx18/cx18-irq.h index fdb585a72827..c1456d69dffa 100644 --- a/drivers/media/pci/cx18/cx18-irq.h +++ b/drivers/media/pci/cx18/cx18-irq.h @@ -2,7 +2,7 @@ /* * cx18 interrupt handling * - * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl> + * Copyright (C) 2007 Hans Verkuil <hverkuil@kernel.org> * Copyright (C) 2008 Andy Walls <awalls@md.metrocast.net> */ diff --git a/drivers/media/pci/cx18/cx18-mailbox.c b/drivers/media/pci/cx18/cx18-mailbox.c index a6457c23d18c..8c70b638a40c 100644 --- a/drivers/media/pci/cx18/cx18-mailbox.c +++ b/drivers/media/pci/cx18/cx18-mailbox.c @@ -2,7 +2,7 @@ /* * cx18 mailbox functions * - * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl> + * Copyright (C) 2007 Hans Verkuil <hverkuil@kernel.org> * Copyright (C) 2008 Andy Walls <awalls@md.metrocast.net> */ diff --git a/drivers/media/pci/cx18/cx18-mailbox.h b/drivers/media/pci/cx18/cx18-mailbox.h index 971382ac0eca..1752b8e1ca13 100644 --- a/drivers/media/pci/cx18/cx18-mailbox.h +++ b/drivers/media/pci/cx18/cx18-mailbox.h @@ -2,7 +2,7 @@ /* * cx18 mailbox functions * - * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl> + * Copyright (C) 2007 Hans Verkuil <hverkuil@kernel.org> * Copyright (C) 2008 Andy Walls <awalls@md.metrocast.net> */ diff --git a/drivers/media/pci/cx18/cx18-queue.c b/drivers/media/pci/cx18/cx18-queue.c index 013694bfcb1c..eeb5513b1d52 100644 --- a/drivers/media/pci/cx18/cx18-queue.c +++ b/drivers/media/pci/cx18/cx18-queue.c @@ -4,7 +4,7 @@ * * Derived from ivtv-queue.c * - * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl> + * Copyright (C) 2007 Hans Verkuil <hverkuil@kernel.org> * Copyright (C) 2008 Andy Walls <awalls@md.metrocast.net> */ @@ -379,15 +379,22 @@ int cx18_stream_alloc(struct cx18_stream *s) break; } + buf->dma_handle = dma_map_single(&s->cx->pci_dev->dev, + buf->buf, s->buf_size, + s->dma); + if (dma_mapping_error(&s->cx->pci_dev->dev, buf->dma_handle)) { + kfree(buf->buf); + kfree(mdl); + kfree(buf); + break; + } + INIT_LIST_HEAD(&mdl->list); INIT_LIST_HEAD(&mdl->buf_list); mdl->id = s->mdl_base_idx; /* a somewhat safe value */ cx18_enqueue(s, mdl, &s->q_idle); INIT_LIST_HEAD(&buf->list); - buf->dma_handle = dma_map_single(&s->cx->pci_dev->dev, - buf->buf, s->buf_size, - s->dma); cx18_buf_sync_for_cpu(s, buf); list_add_tail(&buf->list, &s->buf_pool); } diff --git a/drivers/media/pci/cx18/cx18-queue.h b/drivers/media/pci/cx18/cx18-queue.h index 26f2097c0496..972f234ffead 100644 --- a/drivers/media/pci/cx18/cx18-queue.h +++ b/drivers/media/pci/cx18/cx18-queue.h @@ -4,7 +4,7 @@ * * Derived from ivtv-queue.h * - * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl> + * Copyright (C) 2007 Hans Verkuil <hverkuil@kernel.org> * Copyright (C) 2008 Andy Walls <awalls@md.metrocast.net> */ diff --git a/drivers/media/pci/cx18/cx18-scb.c b/drivers/media/pci/cx18/cx18-scb.c index 4a0edc1e42e7..670dd9b0a332 100644 --- a/drivers/media/pci/cx18/cx18-scb.c +++ b/drivers/media/pci/cx18/cx18-scb.c @@ -2,7 +2,7 @@ /* * cx18 System Control Block initialization * - * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl> + * Copyright (C) 2007 Hans Verkuil <hverkuil@kernel.org> * Copyright (C) 2008 Andy Walls <awalls@md.metrocast.net> */ diff --git a/drivers/media/pci/cx18/cx18-scb.h b/drivers/media/pci/cx18/cx18-scb.h index 841edc0712ab..900f7291979f 100644 --- a/drivers/media/pci/cx18/cx18-scb.h +++ b/drivers/media/pci/cx18/cx18-scb.h @@ -2,7 +2,7 @@ /* * cx18 System Control Block initialization * - * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl> + * Copyright (C) 2007 Hans Verkuil <hverkuil@kernel.org> * Copyright (C) 2008 Andy Walls <awalls@md.metrocast.net> */ diff --git a/drivers/media/pci/cx18/cx18-streams.c b/drivers/media/pci/cx18/cx18-streams.c index 42d6f7b90ede..48203ba16387 100644 --- a/drivers/media/pci/cx18/cx18-streams.c +++ b/drivers/media/pci/cx18/cx18-streams.c @@ -4,7 +4,7 @@ * * Derived from ivtv-streams.c * - * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl> + * Copyright (C) 2007 Hans Verkuil <hverkuil@kernel.org> * Copyright (C) 2008 Andy Walls <awalls@md.metrocast.net> */ diff --git a/drivers/media/pci/cx18/cx18-streams.h b/drivers/media/pci/cx18/cx18-streams.h index bba4349c5c2e..e01bed6b4827 100644 --- a/drivers/media/pci/cx18/cx18-streams.h +++ b/drivers/media/pci/cx18/cx18-streams.h @@ -4,7 +4,7 @@ * * Derived from ivtv-streams.h * - * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl> + * Copyright (C) 2007 Hans Verkuil <hverkuil@kernel.org> * Copyright (C) 2008 Andy Walls <awalls@md.metrocast.net> */ diff --git a/drivers/media/pci/cx18/cx18-vbi.c b/drivers/media/pci/cx18/cx18-vbi.c index c7cce38dd754..8dc4ce325935 100644 --- a/drivers/media/pci/cx18/cx18-vbi.c +++ b/drivers/media/pci/cx18/cx18-vbi.c @@ -4,7 +4,7 @@ * * Derived from ivtv-vbi.c * - * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl> + * Copyright (C) 2007 Hans Verkuil <hverkuil@kernel.org> */ #include "cx18-driver.h" diff --git a/drivers/media/pci/cx18/cx18-vbi.h b/drivers/media/pci/cx18/cx18-vbi.h index a5f81c6159f0..41f5026696c4 100644 --- a/drivers/media/pci/cx18/cx18-vbi.h +++ b/drivers/media/pci/cx18/cx18-vbi.h @@ -4,7 +4,7 @@ * * Derived from ivtv-vbi.h * - * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl> + * Copyright (C) 2007 Hans Verkuil <hverkuil@kernel.org> */ void cx18_process_vbi_data(struct cx18 *cx, struct cx18_mdl *mdl, diff --git a/drivers/media/pci/cx18/cx18-version.h b/drivers/media/pci/cx18/cx18-version.h index e7396182fc5a..e8636ac5d5a5 100644 --- a/drivers/media/pci/cx18/cx18-version.h +++ b/drivers/media/pci/cx18/cx18-version.h @@ -2,7 +2,7 @@ /* * cx18 driver version information * - * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl> + * Copyright (C) 2007 Hans Verkuil <hverkuil@kernel.org> */ #ifndef CX18_VERSION_H diff --git a/drivers/media/pci/cx18/cx18-video.c b/drivers/media/pci/cx18/cx18-video.c index 2fde8c2d3fdc..86cd44053d34 100644 --- a/drivers/media/pci/cx18/cx18-video.c +++ b/drivers/media/pci/cx18/cx18-video.c @@ -2,7 +2,7 @@ /* * cx18 video interface functions * - * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl> + * Copyright (C) 2007 Hans Verkuil <hverkuil@kernel.org> */ #include "cx18-driver.h" diff --git a/drivers/media/pci/cx18/cx18-video.h b/drivers/media/pci/cx18/cx18-video.h index f613975ca5f0..ef212f1c5b17 100644 --- a/drivers/media/pci/cx18/cx18-video.h +++ b/drivers/media/pci/cx18/cx18-video.h @@ -2,7 +2,7 @@ /* * cx18 video interface functions * - * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl> + * Copyright (C) 2007 Hans Verkuil <hverkuil@kernel.org> */ void cx18_video_set_io(struct cx18 *cx); diff --git a/drivers/media/pci/cx18/cx23418.h b/drivers/media/pci/cx18/cx23418.h index 8859c0e8557f..22486f39bcda 100644 --- a/drivers/media/pci/cx18/cx23418.h +++ b/drivers/media/pci/cx18/cx23418.h @@ -2,7 +2,7 @@ /* * cx18 header containing common defines. * - * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl> + * Copyright (C) 2007 Hans Verkuil <hverkuil@kernel.org> */ #ifndef CX23418_H diff --git a/drivers/media/pci/intel/ipu6/ipu6-isys-csi2.c b/drivers/media/pci/intel/ipu6/ipu6-isys-csi2.c index 6030bd23b4b9..d1fece6210ab 100644 --- a/drivers/media/pci/intel/ipu6/ipu6-isys-csi2.c +++ b/drivers/media/pci/intel/ipu6/ipu6-isys-csi2.c @@ -109,7 +109,7 @@ static int csi2_subscribe_event(struct v4l2_subdev *sd, struct v4l2_fh *fh, case V4L2_EVENT_FRAME_SYNC: return v4l2_event_subscribe(fh, sub, 10, NULL); case V4L2_EVENT_CTRL: - return v4l2_ctrl_subscribe_event(fh, sub); + return v4l2_ctrl_subdev_subscribe_event(sd, fh, sub); default: return -EINVAL; } diff --git a/drivers/media/pci/intel/ipu6/ipu6-isys-subdev.c b/drivers/media/pci/intel/ipu6/ipu6-isys-subdev.c index 0a06de5c739c..463a0adf9e13 100644 --- a/drivers/media/pci/intel/ipu6/ipu6-isys-subdev.c +++ b/drivers/media/pci/intel/ipu6/ipu6-isys-subdev.c @@ -81,6 +81,12 @@ unsigned int ipu6_isys_mbus_code_to_mipi(u32 code) case MEDIA_BUS_FMT_SGRBG8_1X8: case MEDIA_BUS_FMT_SRGGB8_1X8: return MIPI_CSI2_DT_RAW8; + case MEDIA_BUS_FMT_META_8: + case MEDIA_BUS_FMT_META_10: + case MEDIA_BUS_FMT_META_12: + case MEDIA_BUS_FMT_META_16: + case MEDIA_BUS_FMT_META_24: + return MIPI_CSI2_DT_EMBEDDED_8B; default: /* return unavailable MIPI data type - 0x3f */ WARN_ON(1); diff --git a/drivers/media/pci/intel/ipu6/ipu6-isys-video.c b/drivers/media/pci/intel/ipu6/ipu6-isys-video.c index 24a2ef93474c..f3f3bc0615e5 100644 --- a/drivers/media/pci/intel/ipu6/ipu6-isys-video.c +++ b/drivers/media/pci/intel/ipu6/ipu6-isys-video.c @@ -1306,7 +1306,6 @@ int ipu6_isys_video_init(struct ipu6_isys_video *av) __ipu6_isys_vidioc_try_fmt_meta_cap(av, &format_meta); av->meta_fmt = format_meta.fmt.meta; - set_bit(V4L2_FL_USES_V4L2_FH, &av->vdev.flags); video_set_drvdata(&av->vdev, av); ret = video_register_device(&av->vdev, VFL_TYPE_VIDEO, -1); diff --git a/drivers/media/pci/ivtv/ivtv-alsa-pcm.c b/drivers/media/pci/ivtv/ivtv-alsa-pcm.c index 8f346d7da9c8..269a799ec046 100644 --- a/drivers/media/pci/ivtv/ivtv-alsa-pcm.c +++ b/drivers/media/pci/ivtv/ivtv-alsa-pcm.c @@ -148,14 +148,12 @@ static int snd_ivtv_pcm_capture_open(struct snd_pcm_substream *substream) s = &itv->streams[IVTV_ENC_STREAM_TYPE_PCM]; - v4l2_fh_init(&item.fh, &s->vdev); item.itv = itv; item.type = s->type; /* See if the stream is available */ if (ivtv_claim_stream(&item, item.type)) { /* No, it's already in use */ - v4l2_fh_exit(&item.fh); snd_ivtv_unlock(itvsc); return -EBUSY; } diff --git a/drivers/media/pci/ivtv/ivtv-cards.c b/drivers/media/pci/ivtv/ivtv-cards.c index c8f4ed7ff2c6..f2ccf8e98664 100644 --- a/drivers/media/pci/ivtv/ivtv-cards.c +++ b/drivers/media/pci/ivtv/ivtv-cards.c @@ -2,7 +2,7 @@ /* Functions to query card hardware Copyright (C) 2003-2004 Kevin Thayer <nufan_wfk at yahoo.com> - Copyright (C) 2005-2007 Hans Verkuil <hverkuil@xs4all.nl> + Copyright (C) 2005-2007 Hans Verkuil <hverkuil@kernel.org> */ diff --git a/drivers/media/pci/ivtv/ivtv-cards.h b/drivers/media/pci/ivtv/ivtv-cards.h index c252733df340..af64e55d3b80 100644 --- a/drivers/media/pci/ivtv/ivtv-cards.h +++ b/drivers/media/pci/ivtv/ivtv-cards.h @@ -2,7 +2,7 @@ /* Functions to query card hardware Copyright (C) 2003-2004 Kevin Thayer <nufan_wfk at yahoo.com> - Copyright (C) 2005-2007 Hans Verkuil <hverkuil@xs4all.nl> + Copyright (C) 2005-2007 Hans Verkuil <hverkuil@kernel.org> */ diff --git a/drivers/media/pci/ivtv/ivtv-controls.c b/drivers/media/pci/ivtv/ivtv-controls.c index a0b9a5a5c7f1..f087a12c4ebd 100644 --- a/drivers/media/pci/ivtv/ivtv-controls.c +++ b/drivers/media/pci/ivtv/ivtv-controls.c @@ -2,7 +2,7 @@ /* ioctl control functions Copyright (C) 2003-2004 Kevin Thayer <nufan_wfk at yahoo.com> - Copyright (C) 2005-2007 Hans Verkuil <hverkuil@xs4all.nl> + Copyright (C) 2005-2007 Hans Verkuil <hverkuil@kernel.org> */ diff --git a/drivers/media/pci/ivtv/ivtv-controls.h b/drivers/media/pci/ivtv/ivtv-controls.h index 444c86a47e5a..d152691ea255 100644 --- a/drivers/media/pci/ivtv/ivtv-controls.h +++ b/drivers/media/pci/ivtv/ivtv-controls.h @@ -2,7 +2,7 @@ /* ioctl control functions Copyright (C) 2003-2004 Kevin Thayer <nufan_wfk at yahoo.com> - Copyright (C) 2005-2007 Hans Verkuil <hverkuil@xs4all.nl> + Copyright (C) 2005-2007 Hans Verkuil <hverkuil@kernel.org> */ diff --git a/drivers/media/pci/ivtv/ivtv-driver.c b/drivers/media/pci/ivtv/ivtv-driver.c index ecc20cd89926..72a8f76a41f4 100644 --- a/drivers/media/pci/ivtv/ivtv-driver.c +++ b/drivers/media/pci/ivtv/ivtv-driver.c @@ -1,22 +1,9 @@ +// SPDX-License-Identifier: GPL-2.0-or-later /* ivtv driver initialization and card probing Copyright (C) 2003-2004 Kevin Thayer <nufan_wfk at yahoo.com> Copyright (C) 2004 Chris Kennedy <c@groovy.org> - Copyright (C) 2005-2007 Hans Verkuil <hverkuil@xs4all.nl> - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Copyright (C) 2005-2007 Hans Verkuil <hverkuil@kernel.org> */ /* Main Driver file for the ivtv project: diff --git a/drivers/media/pci/ivtv/ivtv-driver.h b/drivers/media/pci/ivtv/ivtv-driver.h index a6ffa99e16bc..f1f18911332e 100644 --- a/drivers/media/pci/ivtv/ivtv-driver.h +++ b/drivers/media/pci/ivtv/ivtv-driver.h @@ -1,22 +1,9 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* ivtv driver internal defines and structures Copyright (C) 2003-2004 Kevin Thayer <nufan_wfk at yahoo.com> Copyright (C) 2004 Chris Kennedy <c@groovy.org> - Copyright (C) 2005-2007 Hans Verkuil <hverkuil@xs4all.nl> - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Copyright (C) 2005-2007 Hans Verkuil <hverkuil@kernel.org> */ #ifndef IVTV_DRIVER_H @@ -322,6 +309,7 @@ struct ivtv_queue { }; struct ivtv; /* forward reference */ +struct ivtv_open_id; struct ivtv_stream { /* These first four fields are always set, even if the stream @@ -331,7 +319,7 @@ struct ivtv_stream { const char *name; /* name of the stream */ int type; /* stream type */ - struct v4l2_fh *fh; /* pointer to the streaming filehandle */ + struct ivtv_open_id *id; /* pointer to the streaming ivtv_open_id */ spinlock_t qlock; /* locks access to the queues */ unsigned long s_flags; /* status flags, see above */ int dma; /* can be PCI_DMA_TODEVICE, PCI_DMA_FROMDEVICE or PCI_DMA_NONE */ @@ -383,9 +371,9 @@ struct ivtv_open_id { struct ivtv *itv; }; -static inline struct ivtv_open_id *fh2id(struct v4l2_fh *fh) +static inline struct ivtv_open_id *file2id(struct file *filp) { - return container_of(fh, struct ivtv_open_id, fh); + return container_of(file_to_v4l2_fh(filp), struct ivtv_open_id, fh); } struct yuv_frame_info diff --git a/drivers/media/pci/ivtv/ivtv-fileops.c b/drivers/media/pci/ivtv/ivtv-fileops.c index cfa28d035586..ef9ec062c03a 100644 --- a/drivers/media/pci/ivtv/ivtv-fileops.c +++ b/drivers/media/pci/ivtv/ivtv-fileops.c @@ -3,7 +3,7 @@ file operation functions Copyright (C) 2003-2004 Kevin Thayer <nufan_wfk at yahoo.com> Copyright (C) 2004 Chris Kennedy <c@groovy.org> - Copyright (C) 2005-2007 Hans Verkuil <hverkuil@xs4all.nl> + Copyright (C) 2005-2007 Hans Verkuil <hverkuil@kernel.org> */ @@ -39,16 +39,16 @@ int ivtv_claim_stream(struct ivtv_open_id *id, int type) if (test_and_set_bit(IVTV_F_S_CLAIMED, &s->s_flags)) { /* someone already claimed this stream */ - if (s->fh == &id->fh) { + if (s->id == id) { /* yes, this file descriptor did. So that's OK. */ return 0; } - if (s->fh == NULL && (type == IVTV_DEC_STREAM_TYPE_VBI || + if (s->id == NULL && (type == IVTV_DEC_STREAM_TYPE_VBI || type == IVTV_ENC_STREAM_TYPE_VBI)) { /* VBI is handled already internally, now also assign the file descriptor to this stream for external reading of the stream. */ - s->fh = &id->fh; + s->id = id; IVTV_DEBUG_INFO("Start Read VBI\n"); return 0; } @@ -56,7 +56,7 @@ int ivtv_claim_stream(struct ivtv_open_id *id, int type) IVTV_DEBUG_INFO("Stream %d is busy\n", type); return -EBUSY; } - s->fh = &id->fh; + s->id = id; if (type == IVTV_DEC_STREAM_TYPE_VBI) { /* Enable reinsertion interrupt */ ivtv_clear_irq_mask(itv, IVTV_IRQ_DEC_VBI_RE_INSERT); @@ -94,7 +94,7 @@ void ivtv_release_stream(struct ivtv_stream *s) struct ivtv *itv = s->itv; struct ivtv_stream *s_vbi; - s->fh = NULL; + s->id = NULL; if ((s->type == IVTV_DEC_STREAM_TYPE_VBI || s->type == IVTV_ENC_STREAM_TYPE_VBI) && test_bit(IVTV_F_S_INTERNAL_USE, &s->s_flags)) { /* this stream is still in use internally */ @@ -126,7 +126,7 @@ void ivtv_release_stream(struct ivtv_stream *s) /* was already cleared */ return; } - if (s_vbi->fh) { + if (s_vbi->id) { /* VBI stream still claimed by a file descriptor */ return; } @@ -359,7 +359,7 @@ static ssize_t ivtv_read(struct ivtv_stream *s, char __user *ubuf, size_t tot_co size_t tot_written = 0; int single_frame = 0; - if (atomic_read(&itv->capturing) == 0 && s->fh == NULL) { + if (atomic_read(&itv->capturing) == 0 && s->id == NULL) { /* shouldn't happen */ IVTV_DEBUG_WARN("Stream %s not initialized before read\n", s->name); return -EIO; @@ -502,7 +502,7 @@ int ivtv_start_capture(struct ivtv_open_id *id) ssize_t ivtv_v4l2_read(struct file * filp, char __user *buf, size_t count, loff_t * pos) { - struct ivtv_open_id *id = fh2id(filp->private_data); + struct ivtv_open_id *id = file2id(filp); struct ivtv *itv = id->itv; struct ivtv_stream *s = &itv->streams[id->type]; ssize_t rc; @@ -564,7 +564,7 @@ static int ivtv_schedule_dma(struct ivtv_stream *s) static ssize_t ivtv_write(struct file *filp, const char __user *user_buf, size_t count, loff_t *pos) { - struct ivtv_open_id *id = fh2id(filp->private_data); + struct ivtv_open_id *id = file2id(filp); struct ivtv *itv = id->itv; struct ivtv_stream *s = &itv->streams[id->type]; struct yuv_playback_info *yi = &itv->yuv_info; @@ -719,7 +719,7 @@ retry: ssize_t ivtv_v4l2_write(struct file *filp, const char __user *user_buf, size_t count, loff_t *pos) { - struct ivtv_open_id *id = fh2id(filp->private_data); + struct ivtv_open_id *id = file2id(filp); struct ivtv *itv = id->itv; ssize_t res; @@ -732,7 +732,7 @@ ssize_t ivtv_v4l2_write(struct file *filp, const char __user *user_buf, size_t c __poll_t ivtv_v4l2_dec_poll(struct file *filp, poll_table *wait) { - struct ivtv_open_id *id = fh2id(filp->private_data); + struct ivtv_open_id *id = file2id(filp); struct ivtv *itv = id->itv; struct ivtv_stream *s = &itv->streams[id->type]; __poll_t res = 0; @@ -767,7 +767,7 @@ __poll_t ivtv_v4l2_dec_poll(struct file *filp, poll_table *wait) __poll_t ivtv_v4l2_enc_poll(struct file *filp, poll_table *wait) { __poll_t req_events = poll_requested_events(wait); - struct ivtv_open_id *id = fh2id(filp->private_data); + struct ivtv_open_id *id = file2id(filp); struct ivtv *itv = id->itv; struct ivtv_stream *s = &itv->streams[id->type]; int eof = test_bit(IVTV_F_S_STREAMOFF, &s->s_flags); @@ -831,7 +831,7 @@ void ivtv_stop_capture(struct ivtv_open_id *id, int gop_end) id->type == IVTV_ENC_STREAM_TYPE_VBI) && test_bit(IVTV_F_S_INTERNAL_USE, &s->s_flags)) { /* Also used internally, don't stop capturing */ - s->fh = NULL; + s->id = NULL; } else { ivtv_stop_v4l2_encode_stream(s, gop_end); @@ -877,8 +877,8 @@ static void ivtv_stop_decoding(struct ivtv_open_id *id, int flags, u64 pts) int ivtv_v4l2_close(struct file *filp) { - struct v4l2_fh *fh = filp->private_data; - struct ivtv_open_id *id = fh2id(fh); + struct v4l2_fh *fh = file_to_v4l2_fh(filp); + struct ivtv_open_id *id = file2id(filp); struct ivtv *itv = id->itv; struct ivtv_stream *s = &itv->streams[id->type]; @@ -911,11 +911,11 @@ int ivtv_v4l2_close(struct file *filp) ivtv_unmute(itv); } - v4l2_fh_del(fh); + v4l2_fh_del(fh, filp); v4l2_fh_exit(fh); /* Easy case first: this stream was never claimed by us */ - if (s->fh != &id->fh) + if (s->id != id) goto close_done; /* 'Unclaim' this stream */ @@ -998,9 +998,7 @@ static int ivtv_open(struct file *filp) v4l2_fh_init(&item->fh, &s->vdev); item->itv = itv; item->type = s->type; - - filp->private_data = &item->fh; - v4l2_fh_add(&item->fh); + v4l2_fh_add(&item->fh, filp); if (item->type == IVTV_ENC_STREAM_TYPE_RAD && v4l2_fh_is_singular_file(filp)) { @@ -1008,7 +1006,7 @@ static int ivtv_open(struct file *filp) if (atomic_read(&itv->capturing) > 0) { /* switching to radio while capture is in progress is not polite */ - v4l2_fh_del(&item->fh); + v4l2_fh_del(&item->fh, filp); v4l2_fh_exit(&item->fh); kfree(item); return -EBUSY; diff --git a/drivers/media/pci/ivtv/ivtv-fileops.h b/drivers/media/pci/ivtv/ivtv-fileops.h index c2c01bba5d03..7bbe42b0030c 100644 --- a/drivers/media/pci/ivtv/ivtv-fileops.h +++ b/drivers/media/pci/ivtv/ivtv-fileops.h @@ -2,7 +2,7 @@ /* file operation functions Copyright (C) 2003-2004 Kevin Thayer <nufan_wfk at yahoo.com> - Copyright (C) 2005-2007 Hans Verkuil <hverkuil@xs4all.nl> + Copyright (C) 2005-2007 Hans Verkuil <hverkuil@kernel.org> */ diff --git a/drivers/media/pci/ivtv/ivtv-firmware.c b/drivers/media/pci/ivtv/ivtv-firmware.c index 56b25255faf5..1bc873ebef73 100644 --- a/drivers/media/pci/ivtv/ivtv-firmware.c +++ b/drivers/media/pci/ivtv/ivtv-firmware.c @@ -3,7 +3,7 @@ ivtv firmware functions. Copyright (C) 2003-2004 Kevin Thayer <nufan_wfk at yahoo.com> Copyright (C) 2004 Chris Kennedy <c@groovy.org> - Copyright (C) 2005-2007 Hans Verkuil <hverkuil@xs4all.nl> + Copyright (C) 2005-2007 Hans Verkuil <hverkuil@kernel.org> */ diff --git a/drivers/media/pci/ivtv/ivtv-firmware.h b/drivers/media/pci/ivtv/ivtv-firmware.h index 393e94a8d0e4..ce94b6c385de 100644 --- a/drivers/media/pci/ivtv/ivtv-firmware.h +++ b/drivers/media/pci/ivtv/ivtv-firmware.h @@ -3,7 +3,7 @@ ivtv firmware functions. Copyright (C) 2003-2004 Kevin Thayer <nufan_wfk at yahoo.com> Copyright (C) 2004 Chris Kennedy <c@groovy.org> - Copyright (C) 2005-2007 Hans Verkuil <hverkuil@xs4all.nl> + Copyright (C) 2005-2007 Hans Verkuil <hverkuil@kernel.org> */ diff --git a/drivers/media/pci/ivtv/ivtv-gpio.c b/drivers/media/pci/ivtv/ivtv-gpio.c index 6434c0d03a6d..d3477e1529c9 100644 --- a/drivers/media/pci/ivtv/ivtv-gpio.c +++ b/drivers/media/pci/ivtv/ivtv-gpio.c @@ -3,7 +3,7 @@ gpio functions. Merging GPIO support into driver: Copyright (C) 2004 Chris Kennedy <c@groovy.org> - Copyright (C) 2005-2007 Hans Verkuil <hverkuil@xs4all.nl> + Copyright (C) 2005-2007 Hans Verkuil <hverkuil@kernel.org> */ diff --git a/drivers/media/pci/ivtv/ivtv-gpio.h b/drivers/media/pci/ivtv/ivtv-gpio.h index 4ad817173f04..686c9b5e9c19 100644 --- a/drivers/media/pci/ivtv/ivtv-gpio.h +++ b/drivers/media/pci/ivtv/ivtv-gpio.h @@ -2,7 +2,7 @@ /* gpio functions. Copyright (C) 2004 Chris Kennedy <c@groovy.org> - Copyright (C) 2005-2007 Hans Verkuil <hverkuil@xs4all.nl> + Copyright (C) 2005-2007 Hans Verkuil <hverkuil@kernel.org> */ diff --git a/drivers/media/pci/ivtv/ivtv-i2c.c b/drivers/media/pci/ivtv/ivtv-i2c.c index c052c57c6dce..28cb22d6a892 100644 --- a/drivers/media/pci/ivtv/ivtv-i2c.c +++ b/drivers/media/pci/ivtv/ivtv-i2c.c @@ -2,7 +2,7 @@ /* I2C functions Copyright (C) 2003-2004 Kevin Thayer <nufan_wfk at yahoo.com> - Copyright (C) 2005-2007 Hans Verkuil <hverkuil@xs4all.nl> + Copyright (C) 2005-2007 Hans Verkuil <hverkuil@kernel.org> */ diff --git a/drivers/media/pci/ivtv/ivtv-i2c.h b/drivers/media/pci/ivtv/ivtv-i2c.h index 2d9cdaa682c5..504bbc1dee25 100644 --- a/drivers/media/pci/ivtv/ivtv-i2c.h +++ b/drivers/media/pci/ivtv/ivtv-i2c.h @@ -2,7 +2,7 @@ /* I2C functions Copyright (C) 2003-2004 Kevin Thayer <nufan_wfk at yahoo.com> - Copyright (C) 2005-2007 Hans Verkuil <hverkuil@xs4all.nl> + Copyright (C) 2005-2007 Hans Verkuil <hverkuil@kernel.org> */ diff --git a/drivers/media/pci/ivtv/ivtv-ioctl.c b/drivers/media/pci/ivtv/ivtv-ioctl.c index 7947dcd615e8..84c73bd22f2d 100644 --- a/drivers/media/pci/ivtv/ivtv-ioctl.c +++ b/drivers/media/pci/ivtv/ivtv-ioctl.c @@ -2,7 +2,7 @@ /* ioctl system call Copyright (C) 2003-2004 Kevin Thayer <nufan_wfk at yahoo.com> - Copyright (C) 2005-2007 Hans Verkuil <hverkuil@xs4all.nl> + Copyright (C) 2005-2007 Hans Verkuil <hverkuil@kernel.org> */ @@ -308,7 +308,7 @@ static int ivtv_video_command(struct ivtv *itv, struct ivtv_open_id *id, static int ivtv_g_fmt_sliced_vbi_out(struct file *file, void *fh, struct v4l2_format *fmt) { - struct ivtv *itv = fh2id(fh)->itv; + struct ivtv *itv = file2id(file)->itv; struct v4l2_sliced_vbi_format *vbifmt = &fmt->fmt.sliced; vbifmt->reserved[0] = 0; @@ -330,7 +330,7 @@ static int ivtv_g_fmt_sliced_vbi_out(struct file *file, void *fh, struct v4l2_fo static int ivtv_g_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *fmt) { - struct ivtv_open_id *id = fh2id(fh); + struct ivtv_open_id *id = file2id(file); struct ivtv *itv = id->itv; struct v4l2_pix_format *pixfmt = &fmt->fmt.pix; @@ -353,7 +353,7 @@ static int ivtv_g_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *f static int ivtv_g_fmt_vbi_cap(struct file *file, void *fh, struct v4l2_format *fmt) { - struct ivtv *itv = fh2id(fh)->itv; + struct ivtv *itv = file2id(file)->itv; struct v4l2_vbi_format *vbifmt = &fmt->fmt.vbi; vbifmt->sampling_rate = 27000000; @@ -372,7 +372,7 @@ static int ivtv_g_fmt_vbi_cap(struct file *file, void *fh, struct v4l2_format *f static int ivtv_g_fmt_sliced_vbi_cap(struct file *file, void *fh, struct v4l2_format *fmt) { struct v4l2_sliced_vbi_format *vbifmt = &fmt->fmt.sliced; - struct ivtv_open_id *id = fh2id(fh); + struct ivtv_open_id *id = file2id(file); struct ivtv *itv = id->itv; vbifmt->reserved[0] = 0; @@ -394,7 +394,7 @@ static int ivtv_g_fmt_sliced_vbi_cap(struct file *file, void *fh, struct v4l2_fo static int ivtv_g_fmt_vid_out(struct file *file, void *fh, struct v4l2_format *fmt) { - struct ivtv_open_id *id = fh2id(fh); + struct ivtv_open_id *id = file2id(file); struct ivtv *itv = id->itv; struct v4l2_pix_format *pixfmt = &fmt->fmt.pix; @@ -434,8 +434,8 @@ static int ivtv_g_fmt_vid_out(struct file *file, void *fh, struct v4l2_format *f static int ivtv_g_fmt_vid_out_overlay(struct file *file, void *fh, struct v4l2_format *fmt) { - struct ivtv *itv = fh2id(fh)->itv; - struct ivtv_stream *s = &itv->streams[fh2id(fh)->type]; + struct ivtv *itv = file2id(file)->itv; + struct ivtv_stream *s = &itv->streams[file2id(file)->type]; struct v4l2_window *winfmt = &fmt->fmt.win; if (!(s->vdev.device_caps & V4L2_CAP_VIDEO_OUTPUT_OVERLAY)) @@ -461,7 +461,7 @@ static int ivtv_try_fmt_sliced_vbi_out(struct file *file, void *fh, struct v4l2_ static int ivtv_try_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *fmt) { - struct ivtv_open_id *id = fh2id(fh); + struct ivtv_open_id *id = file2id(file); struct ivtv *itv = id->itv; int w = fmt->fmt.pix.width; int h = fmt->fmt.pix.height; @@ -490,7 +490,7 @@ static int ivtv_try_fmt_vbi_cap(struct file *file, void *fh, struct v4l2_format static int ivtv_try_fmt_sliced_vbi_cap(struct file *file, void *fh, struct v4l2_format *fmt) { struct v4l2_sliced_vbi_format *vbifmt = &fmt->fmt.sliced; - struct ivtv_open_id *id = fh2id(fh); + struct ivtv_open_id *id = file2id(file); struct ivtv *itv = id->itv; if (id->type == IVTV_DEC_STREAM_TYPE_VBI) @@ -510,7 +510,7 @@ static int ivtv_try_fmt_sliced_vbi_cap(struct file *file, void *fh, struct v4l2_ static int ivtv_try_fmt_vid_out(struct file *file, void *fh, struct v4l2_format *fmt) { - struct ivtv_open_id *id = fh2id(fh); + struct ivtv_open_id *id = file2id(file); s32 w = fmt->fmt.pix.width; s32 h = fmt->fmt.pix.height; int field = fmt->fmt.pix.field; @@ -544,8 +544,8 @@ static int ivtv_try_fmt_vid_out(struct file *file, void *fh, struct v4l2_format static int ivtv_try_fmt_vid_out_overlay(struct file *file, void *fh, struct v4l2_format *fmt) { - struct ivtv *itv = fh2id(fh)->itv; - struct ivtv_stream *s = &itv->streams[fh2id(fh)->type]; + struct ivtv *itv = file2id(file)->itv; + struct ivtv_stream *s = &itv->streams[file2id(file)->type]; u32 chromakey = fmt->fmt.win.chromakey; u8 global_alpha = fmt->fmt.win.global_alpha; @@ -566,7 +566,7 @@ static int ivtv_s_fmt_sliced_vbi_out(struct file *file, void *fh, struct v4l2_fo static int ivtv_s_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *fmt) { - struct ivtv_open_id *id = fh2id(fh); + struct ivtv_open_id *id = file2id(file); struct ivtv *itv = id->itv; struct v4l2_subdev_format format = { .which = V4L2_SUBDEV_FORMAT_ACTIVE, @@ -597,7 +597,7 @@ static int ivtv_s_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *f static int ivtv_s_fmt_vbi_cap(struct file *file, void *fh, struct v4l2_format *fmt) { - struct ivtv *itv = fh2id(fh)->itv; + struct ivtv *itv = file2id(file)->itv; if (!ivtv_raw_vbi(itv) && atomic_read(&itv->capturing) > 0) return -EBUSY; @@ -610,7 +610,7 @@ static int ivtv_s_fmt_vbi_cap(struct file *file, void *fh, struct v4l2_format *f static int ivtv_s_fmt_sliced_vbi_cap(struct file *file, void *fh, struct v4l2_format *fmt) { struct v4l2_sliced_vbi_format *vbifmt = &fmt->fmt.sliced; - struct ivtv_open_id *id = fh2id(fh); + struct ivtv_open_id *id = file2id(file); struct ivtv *itv = id->itv; int ret = ivtv_try_fmt_sliced_vbi_cap(file, fh, fmt); @@ -628,7 +628,7 @@ static int ivtv_s_fmt_sliced_vbi_cap(struct file *file, void *fh, struct v4l2_fo static int ivtv_s_fmt_vid_out(struct file *file, void *fh, struct v4l2_format *fmt) { - struct ivtv_open_id *id = fh2id(fh); + struct ivtv_open_id *id = file2id(file); struct ivtv *itv = id->itv; struct yuv_playback_info *yi = &itv->yuv_info; int ret = ivtv_try_fmt_vid_out(file, fh, fmt); @@ -673,7 +673,7 @@ static int ivtv_s_fmt_vid_out(struct file *file, void *fh, struct v4l2_format *f static int ivtv_s_fmt_vid_out_overlay(struct file *file, void *fh, struct v4l2_format *fmt) { - struct ivtv *itv = fh2id(fh)->itv; + struct ivtv *itv = file2id(file)->itv; int ret = ivtv_try_fmt_vid_out_overlay(file, fh, fmt); if (ret == 0) { @@ -710,7 +710,7 @@ static int ivtv_itvc(struct ivtv *itv, bool get, u64 reg, u64 *val) static int ivtv_g_register(struct file *file, void *fh, struct v4l2_dbg_register *reg) { - struct ivtv *itv = fh2id(fh)->itv; + struct ivtv *itv = file2id(file)->itv; reg->size = 4; return ivtv_itvc(itv, true, reg->reg, ®->val); @@ -718,7 +718,7 @@ static int ivtv_g_register(struct file *file, void *fh, struct v4l2_dbg_register static int ivtv_s_register(struct file *file, void *fh, const struct v4l2_dbg_register *reg) { - struct ivtv *itv = fh2id(fh)->itv; + struct ivtv *itv = file2id(file)->itv; u64 val = reg->val; return ivtv_itvc(itv, false, reg->reg, &val); @@ -727,7 +727,7 @@ static int ivtv_s_register(struct file *file, void *fh, const struct v4l2_dbg_re static int ivtv_querycap(struct file *file, void *fh, struct v4l2_capability *vcap) { - struct ivtv_open_id *id = fh2id(file->private_data); + struct ivtv_open_id *id = file2id(file); struct ivtv *itv = id->itv; strscpy(vcap->driver, IVTV_DRIVER_NAME, sizeof(vcap->driver)); @@ -738,14 +738,14 @@ static int ivtv_querycap(struct file *file, void *fh, struct v4l2_capability *vc static int ivtv_enumaudio(struct file *file, void *fh, struct v4l2_audio *vin) { - struct ivtv *itv = fh2id(fh)->itv; + struct ivtv *itv = file2id(file)->itv; return ivtv_get_audio_input(itv, vin->index, vin); } static int ivtv_g_audio(struct file *file, void *fh, struct v4l2_audio *vin) { - struct ivtv *itv = fh2id(fh)->itv; + struct ivtv *itv = file2id(file)->itv; vin->index = itv->audio_input; return ivtv_get_audio_input(itv, vin->index, vin); @@ -753,7 +753,7 @@ static int ivtv_g_audio(struct file *file, void *fh, struct v4l2_audio *vin) static int ivtv_s_audio(struct file *file, void *fh, const struct v4l2_audio *vout) { - struct ivtv *itv = fh2id(fh)->itv; + struct ivtv *itv = file2id(file)->itv; if (vout->index >= itv->nof_audio_inputs) return -EINVAL; @@ -766,7 +766,7 @@ static int ivtv_s_audio(struct file *file, void *fh, const struct v4l2_audio *vo static int ivtv_enumaudout(struct file *file, void *fh, struct v4l2_audioout *vin) { - struct ivtv *itv = fh2id(fh)->itv; + struct ivtv *itv = file2id(file)->itv; /* set it to defaults from our table */ return ivtv_get_audio_output(itv, vin->index, vin); @@ -774,7 +774,7 @@ static int ivtv_enumaudout(struct file *file, void *fh, struct v4l2_audioout *vi static int ivtv_g_audout(struct file *file, void *fh, struct v4l2_audioout *vin) { - struct ivtv *itv = fh2id(fh)->itv; + struct ivtv *itv = file2id(file)->itv; vin->index = 0; return ivtv_get_audio_output(itv, vin->index, vin); @@ -782,7 +782,7 @@ static int ivtv_g_audout(struct file *file, void *fh, struct v4l2_audioout *vin) static int ivtv_s_audout(struct file *file, void *fh, const struct v4l2_audioout *vout) { - struct ivtv *itv = fh2id(fh)->itv; + struct ivtv *itv = file2id(file)->itv; if (itv->card->video_outputs == NULL || vout->index != 0) return -EINVAL; @@ -791,7 +791,7 @@ static int ivtv_s_audout(struct file *file, void *fh, const struct v4l2_audioout static int ivtv_enum_input(struct file *file, void *fh, struct v4l2_input *vin) { - struct ivtv *itv = fh2id(fh)->itv; + struct ivtv *itv = file2id(file)->itv; /* set it to defaults from our table */ return ivtv_get_input(itv, vin->index, vin); @@ -799,7 +799,7 @@ static int ivtv_enum_input(struct file *file, void *fh, struct v4l2_input *vin) static int ivtv_enum_output(struct file *file, void *fh, struct v4l2_output *vout) { - struct ivtv *itv = fh2id(fh)->itv; + struct ivtv *itv = file2id(file)->itv; return ivtv_get_output(itv, vout->index, vout); } @@ -807,7 +807,7 @@ static int ivtv_enum_output(struct file *file, void *fh, struct v4l2_output *vou static int ivtv_g_pixelaspect(struct file *file, void *fh, int type, struct v4l2_fract *f) { - struct ivtv_open_id *id = fh2id(fh); + struct ivtv_open_id *id = file2id(file); struct ivtv *itv = id->itv; if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE) { @@ -825,7 +825,7 @@ static int ivtv_g_pixelaspect(struct file *file, void *fh, static int ivtv_s_selection(struct file *file, void *fh, struct v4l2_selection *sel) { - struct ivtv_open_id *id = fh2id(fh); + struct ivtv_open_id *id = file2id(file); struct ivtv *itv = id->itv; struct yuv_playback_info *yi = &itv->yuv_info; struct v4l2_rect r = { 0, 0, 720, 0 }; @@ -868,7 +868,7 @@ static int ivtv_s_selection(struct file *file, void *fh, static int ivtv_g_selection(struct file *file, void *fh, struct v4l2_selection *sel) { - struct ivtv_open_id *id = fh2id(fh); + struct ivtv_open_id *id = file2id(file); struct ivtv *itv = id->itv; struct yuv_playback_info *yi = &itv->yuv_info; struct v4l2_rect r = { 0, 0, 720, 0 }; @@ -924,8 +924,8 @@ static int ivtv_enum_fmt_vid_cap(struct file *file, void *fh, struct v4l2_fmtdes .description = "MPEG", .pixelformat = V4L2_PIX_FMT_MPEG, }; - struct ivtv *itv = fh2id(fh)->itv; - struct ivtv_stream *s = &itv->streams[fh2id(fh)->type]; + struct ivtv *itv = file2id(file)->itv; + struct ivtv_stream *s = &itv->streams[file2id(file)->type]; if (fmt->index) return -EINVAL; @@ -951,8 +951,8 @@ static int ivtv_enum_fmt_vid_out(struct file *file, void *fh, struct v4l2_fmtdes .description = "MPEG", .pixelformat = V4L2_PIX_FMT_MPEG, }; - struct ivtv *itv = fh2id(fh)->itv; - struct ivtv_stream *s = &itv->streams[fh2id(fh)->type]; + struct ivtv *itv = file2id(file)->itv; + struct ivtv_stream *s = &itv->streams[file2id(file)->type]; if (fmt->index) return -EINVAL; @@ -967,7 +967,7 @@ static int ivtv_enum_fmt_vid_out(struct file *file, void *fh, struct v4l2_fmtdes static int ivtv_g_input(struct file *file, void *fh, unsigned int *i) { - struct ivtv *itv = fh2id(fh)->itv; + struct ivtv *itv = file2id(file)->itv; *i = itv->active_input; @@ -976,7 +976,7 @@ static int ivtv_g_input(struct file *file, void *fh, unsigned int *i) int ivtv_s_input(struct file *file, void *fh, unsigned int inp) { - struct ivtv *itv = fh2id(fh)->itv; + struct ivtv *itv = file2id(file)->itv; v4l2_std_id std; int i; @@ -1019,7 +1019,7 @@ int ivtv_s_input(struct file *file, void *fh, unsigned int inp) static int ivtv_g_output(struct file *file, void *fh, unsigned int *i) { - struct ivtv *itv = fh2id(fh)->itv; + struct ivtv *itv = file2id(file)->itv; if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) return -EINVAL; @@ -1031,7 +1031,7 @@ static int ivtv_g_output(struct file *file, void *fh, unsigned int *i) static int ivtv_s_output(struct file *file, void *fh, unsigned int outp) { - struct ivtv *itv = fh2id(fh)->itv; + struct ivtv *itv = file2id(file)->itv; if (outp >= itv->card->nof_outputs) return -EINVAL; @@ -1053,8 +1053,8 @@ static int ivtv_s_output(struct file *file, void *fh, unsigned int outp) static int ivtv_g_frequency(struct file *file, void *fh, struct v4l2_frequency *vf) { - struct ivtv *itv = fh2id(fh)->itv; - struct ivtv_stream *s = &itv->streams[fh2id(fh)->type]; + struct ivtv *itv = file2id(file)->itv; + struct ivtv_stream *s = &itv->streams[file2id(file)->type]; if (s->vdev.vfl_dir) return -ENOTTY; @@ -1067,8 +1067,8 @@ static int ivtv_g_frequency(struct file *file, void *fh, struct v4l2_frequency * int ivtv_s_frequency(struct file *file, void *fh, const struct v4l2_frequency *vf) { - struct ivtv *itv = fh2id(fh)->itv; - struct ivtv_stream *s = &itv->streams[fh2id(fh)->type]; + struct ivtv *itv = file2id(file)->itv; + struct ivtv_stream *s = &itv->streams[file2id(file)->type]; if (s->vdev.vfl_dir) return -ENOTTY; @@ -1084,7 +1084,7 @@ int ivtv_s_frequency(struct file *file, void *fh, const struct v4l2_frequency *v static int ivtv_g_std(struct file *file, void *fh, v4l2_std_id *std) { - struct ivtv *itv = fh2id(fh)->itv; + struct ivtv *itv = file2id(file)->itv; *std = itv->std; return 0; @@ -1157,7 +1157,7 @@ void ivtv_s_std_dec(struct ivtv *itv, v4l2_std_id std) static int ivtv_s_std(struct file *file, void *fh, v4l2_std_id std) { - struct ivtv *itv = fh2id(fh)->itv; + struct ivtv *itv = file2id(file)->itv; if ((std & V4L2_STD_ALL) == 0) return -EINVAL; @@ -1185,7 +1185,7 @@ static int ivtv_s_std(struct file *file, void *fh, v4l2_std_id std) static int ivtv_s_tuner(struct file *file, void *fh, const struct v4l2_tuner *vt) { - struct ivtv_open_id *id = fh2id(fh); + struct ivtv_open_id *id = file2id(file); struct ivtv *itv = id->itv; if (vt->index != 0) @@ -1198,7 +1198,7 @@ static int ivtv_s_tuner(struct file *file, void *fh, const struct v4l2_tuner *vt static int ivtv_g_tuner(struct file *file, void *fh, struct v4l2_tuner *vt) { - struct ivtv *itv = fh2id(fh)->itv; + struct ivtv *itv = file2id(file)->itv; if (vt->index != 0) return -EINVAL; @@ -1214,7 +1214,7 @@ static int ivtv_g_tuner(struct file *file, void *fh, struct v4l2_tuner *vt) static int ivtv_g_sliced_vbi_cap(struct file *file, void *fh, struct v4l2_sliced_vbi_cap *cap) { - struct ivtv *itv = fh2id(fh)->itv; + struct ivtv *itv = file2id(file)->itv; int set = itv->is_50hz ? V4L2_SLICED_VBI_625 : V4L2_SLICED_VBI_525; int f, l; @@ -1249,7 +1249,7 @@ static int ivtv_g_sliced_vbi_cap(struct file *file, void *fh, struct v4l2_sliced static int ivtv_g_enc_index(struct file *file, void *fh, struct v4l2_enc_idx *idx) { - struct ivtv *itv = fh2id(fh)->itv; + struct ivtv *itv = file2id(file)->itv; struct v4l2_enc_idx_entry *e = idx->entry; int entries; int i; @@ -1275,7 +1275,7 @@ static int ivtv_g_enc_index(struct file *file, void *fh, struct v4l2_enc_idx *id static int ivtv_encoder_cmd(struct file *file, void *fh, struct v4l2_encoder_cmd *enc) { - struct ivtv_open_id *id = fh2id(fh); + struct ivtv_open_id *id = file2id(file); struct ivtv *itv = id->itv; @@ -1327,7 +1327,7 @@ static int ivtv_encoder_cmd(struct file *file, void *fh, struct v4l2_encoder_cmd static int ivtv_try_encoder_cmd(struct file *file, void *fh, struct v4l2_encoder_cmd *enc) { - struct ivtv *itv = fh2id(fh)->itv; + struct ivtv *itv = file2id(file)->itv; switch (enc->cmd) { case V4L2_ENC_CMD_START: @@ -1357,8 +1357,8 @@ static int ivtv_try_encoder_cmd(struct file *file, void *fh, struct v4l2_encoder static int ivtv_g_fbuf(struct file *file, void *fh, struct v4l2_framebuffer *fb) { - struct ivtv *itv = fh2id(fh)->itv; - struct ivtv_stream *s = &itv->streams[fh2id(fh)->type]; + struct ivtv *itv = file2id(file)->itv; + struct ivtv_stream *s = &itv->streams[file2id(file)->type]; u32 data[CX2341X_MBOX_MAX_DATA]; struct yuv_playback_info *yi = &itv->yuv_info; @@ -1444,9 +1444,9 @@ static int ivtv_g_fbuf(struct file *file, void *fh, struct v4l2_framebuffer *fb) static int ivtv_s_fbuf(struct file *file, void *fh, const struct v4l2_framebuffer *fb) { - struct ivtv_open_id *id = fh2id(fh); + struct ivtv_open_id *id = file2id(file); struct ivtv *itv = id->itv; - struct ivtv_stream *s = &itv->streams[fh2id(fh)->type]; + struct ivtv_stream *s = &itv->streams[file2id(file)->type]; struct yuv_playback_info *yi = &itv->yuv_info; if (!(s->vdev.device_caps & V4L2_CAP_VIDEO_OUTPUT_OVERLAY)) @@ -1465,9 +1465,9 @@ static int ivtv_s_fbuf(struct file *file, void *fh, const struct v4l2_framebuffe static int ivtv_overlay(struct file *file, void *fh, unsigned int on) { - struct ivtv_open_id *id = fh2id(fh); + struct ivtv_open_id *id = file2id(file); struct ivtv *itv = id->itv; - struct ivtv_stream *s = &itv->streams[fh2id(fh)->type]; + struct ivtv_stream *s = &itv->streams[file2id(file)->type]; if (!(s->vdev.device_caps & V4L2_CAP_VIDEO_OUTPUT_OVERLAY)) return -ENOTTY; @@ -1492,7 +1492,7 @@ static int ivtv_subscribe_event(struct v4l2_fh *fh, const struct v4l2_event_subs static int ivtv_log_status(struct file *file, void *fh) { - struct ivtv *itv = fh2id(fh)->itv; + struct ivtv *itv = file2id(file)->itv; u32 data[CX2341X_MBOX_MAX_DATA]; int has_output = itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT; @@ -1584,7 +1584,7 @@ static int ivtv_log_status(struct file *file, void *fh) static int ivtv_decoder_cmd(struct file *file, void *fh, struct v4l2_decoder_cmd *dec) { - struct ivtv_open_id *id = fh2id(file->private_data); + struct ivtv_open_id *id = file2id(file); struct ivtv *itv = id->itv; IVTV_DEBUG_IOCTL("VIDIOC_DECODER_CMD %d\n", dec->cmd); @@ -1593,7 +1593,7 @@ static int ivtv_decoder_cmd(struct file *file, void *fh, struct v4l2_decoder_cmd static int ivtv_try_decoder_cmd(struct file *file, void *fh, struct v4l2_decoder_cmd *dec) { - struct ivtv_open_id *id = fh2id(file->private_data); + struct ivtv_open_id *id = file2id(file); struct ivtv *itv = id->itv; IVTV_DEBUG_IOCTL("VIDIOC_TRY_DECODER_CMD %d\n", dec->cmd); @@ -1602,7 +1602,7 @@ static int ivtv_try_decoder_cmd(struct file *file, void *fh, struct v4l2_decoder static int ivtv_decoder_ioctls(struct file *filp, unsigned int cmd, void *arg) { - struct ivtv_open_id *id = fh2id(filp->private_data); + struct ivtv_open_id *id = file2id(filp); struct ivtv *itv = id->itv; struct ivtv_stream *s = &itv->streams[id->type]; @@ -1645,7 +1645,7 @@ static int ivtv_decoder_ioctls(struct file *filp, unsigned int cmd, void *arg) static long ivtv_default(struct file *file, void *fh, bool valid_prio, unsigned int cmd, void *arg) { - struct ivtv *itv = fh2id(fh)->itv; + struct ivtv *itv = file2id(file)->itv; if (!valid_prio) { switch (cmd) { diff --git a/drivers/media/pci/ivtv/ivtv-ioctl.h b/drivers/media/pci/ivtv/ivtv-ioctl.h index 42c2516379fc..7f8c6f43d397 100644 --- a/drivers/media/pci/ivtv/ivtv-ioctl.h +++ b/drivers/media/pci/ivtv/ivtv-ioctl.h @@ -2,7 +2,7 @@ /* ioctl system call Copyright (C) 2003-2004 Kevin Thayer <nufan_wfk at yahoo.com> - Copyright (C) 2005-2007 Hans Verkuil <hverkuil@xs4all.nl> + Copyright (C) 2005-2007 Hans Verkuil <hverkuil@kernel.org> */ diff --git a/drivers/media/pci/ivtv/ivtv-irq.c b/drivers/media/pci/ivtv/ivtv-irq.c index 748c14e87963..05e0293b4d44 100644 --- a/drivers/media/pci/ivtv/ivtv-irq.c +++ b/drivers/media/pci/ivtv/ivtv-irq.c @@ -2,7 +2,7 @@ /* interrupt handling Copyright (C) 2003-2004 Kevin Thayer <nufan_wfk at yahoo.com> Copyright (C) 2004 Chris Kennedy <c@groovy.org> - Copyright (C) 2005-2007 Hans Verkuil <hverkuil@xs4all.nl> + Copyright (C) 2005-2007 Hans Verkuil <hverkuil@kernel.org> */ @@ -305,7 +305,7 @@ static void dma_post(struct ivtv_stream *s) ivtv_process_vbi_data(itv, buf, 0, s->type); s->q_dma.bytesused += buf->bytesused; } - if (s->fh == NULL) { + if (s->id == NULL) { ivtv_queue_move(s, &s->q_dma, NULL, &s->q_free, 0); return; } @@ -330,7 +330,7 @@ static void dma_post(struct ivtv_stream *s) set_bit(IVTV_F_I_HAVE_WORK, &itv->i_flags); } - if (s->fh) + if (s->id) wake_up(&s->waitq); } @@ -351,7 +351,7 @@ void ivtv_dma_stream_dec_prepare(struct ivtv_stream *s, u32 offset, int lock) /* Insert buffer block for YUV if needed */ if (s->type == IVTV_DEC_STREAM_TYPE_YUV && f->offset_y) { - if (yi->blanking_dmaptr) { + if (yi->blanking_ptr) { s->sg_pending[idx].src = yi->blanking_dmaptr; s->sg_pending[idx].dst = offset; s->sg_pending[idx].size = 720 * 16; diff --git a/drivers/media/pci/ivtv/ivtv-irq.h b/drivers/media/pci/ivtv/ivtv-irq.h index b8b0703a1c82..8a780bea7de4 100644 --- a/drivers/media/pci/ivtv/ivtv-irq.h +++ b/drivers/media/pci/ivtv/ivtv-irq.h @@ -3,7 +3,7 @@ interrupt handling Copyright (C) 2003-2004 Kevin Thayer <nufan_wfk at yahoo.com> Copyright (C) 2004 Chris Kennedy <c@groovy.org> - Copyright (C) 2005-2007 Hans Verkuil <hverkuil@xs4all.nl> + Copyright (C) 2005-2007 Hans Verkuil <hverkuil@kernel.org> */ diff --git a/drivers/media/pci/ivtv/ivtv-mailbox.c b/drivers/media/pci/ivtv/ivtv-mailbox.c index d3fdaaa903f1..cd7c9f2d473f 100644 --- a/drivers/media/pci/ivtv/ivtv-mailbox.c +++ b/drivers/media/pci/ivtv/ivtv-mailbox.c @@ -3,7 +3,7 @@ mailbox functions Copyright (C) 2003-2004 Kevin Thayer <nufan_wfk at yahoo.com> Copyright (C) 2004 Chris Kennedy <c@groovy.org> - Copyright (C) 2005-2007 Hans Verkuil <hverkuil@xs4all.nl> + Copyright (C) 2005-2007 Hans Verkuil <hverkuil@kernel.org> */ diff --git a/drivers/media/pci/ivtv/ivtv-mailbox.h b/drivers/media/pci/ivtv/ivtv-mailbox.h index 537c90437e1d..364e7f51508e 100644 --- a/drivers/media/pci/ivtv/ivtv-mailbox.h +++ b/drivers/media/pci/ivtv/ivtv-mailbox.h @@ -2,7 +2,7 @@ /* mailbox functions Copyright (C) 2003-2004 Kevin Thayer <nufan_wfk at yahoo.com> - Copyright (C) 2005-2007 Hans Verkuil <hverkuil@xs4all.nl> + Copyright (C) 2005-2007 Hans Verkuil <hverkuil@kernel.org> */ diff --git a/drivers/media/pci/ivtv/ivtv-queue.c b/drivers/media/pci/ivtv/ivtv-queue.c index f9b192ab7e7c..f7d2d159d800 100644 --- a/drivers/media/pci/ivtv/ivtv-queue.c +++ b/drivers/media/pci/ivtv/ivtv-queue.c @@ -3,7 +3,7 @@ buffer queues. Copyright (C) 2003-2004 Kevin Thayer <nufan_wfk at yahoo.com> Copyright (C) 2004 Chris Kennedy <c@groovy.org> - Copyright (C) 2005-2007 Hans Verkuil <hverkuil@xs4all.nl> + Copyright (C) 2005-2007 Hans Verkuil <hverkuil@kernel.org> */ diff --git a/drivers/media/pci/ivtv/ivtv-queue.h b/drivers/media/pci/ivtv/ivtv-queue.h index 983e99642364..9619745d6de1 100644 --- a/drivers/media/pci/ivtv/ivtv-queue.h +++ b/drivers/media/pci/ivtv/ivtv-queue.h @@ -3,7 +3,7 @@ buffer queues. Copyright (C) 2003-2004 Kevin Thayer <nufan_wfk at yahoo.com> Copyright (C) 2004 Chris Kennedy <c@groovy.org> - Copyright (C) 2005-2007 Hans Verkuil <hverkuil@xs4all.nl> + Copyright (C) 2005-2007 Hans Verkuil <hverkuil@kernel.org> */ diff --git a/drivers/media/pci/ivtv/ivtv-routing.c b/drivers/media/pci/ivtv/ivtv-routing.c index 57d4d5a3cb87..b1dfc2e96d91 100644 --- a/drivers/media/pci/ivtv/ivtv-routing.c +++ b/drivers/media/pci/ivtv/ivtv-routing.c @@ -2,7 +2,7 @@ /* Audio/video-routing-related ivtv functions. Copyright (C) 2003-2004 Kevin Thayer <nufan_wfk at yahoo.com> - Copyright (C) 2005-2007 Hans Verkuil <hverkuil@xs4all.nl> + Copyright (C) 2005-2007 Hans Verkuil <hverkuil@kernel.org> */ diff --git a/drivers/media/pci/ivtv/ivtv-routing.h b/drivers/media/pci/ivtv/ivtv-routing.h index e4a0ae0694d2..69ddb66ef26f 100644 --- a/drivers/media/pci/ivtv/ivtv-routing.h +++ b/drivers/media/pci/ivtv/ivtv-routing.h @@ -2,7 +2,7 @@ /* Audio/video-routing-related ivtv functions. Copyright (C) 2003-2004 Kevin Thayer <nufan_wfk at yahoo.com> - Copyright (C) 2005-2007 Hans Verkuil <hverkuil@xs4all.nl> + Copyright (C) 2005-2007 Hans Verkuil <hverkuil@kernel.org> */ diff --git a/drivers/media/pci/ivtv/ivtv-streams.c b/drivers/media/pci/ivtv/ivtv-streams.c index ac085925d3cb..d98fe0c9d9f1 100644 --- a/drivers/media/pci/ivtv/ivtv-streams.c +++ b/drivers/media/pci/ivtv/ivtv-streams.c @@ -1,22 +1,9 @@ +// SPDX-License-Identifier: GPL-2.0-or-later /* init/start/stop/exit stream functions Copyright (C) 2003-2004 Kevin Thayer <nufan_wfk at yahoo.com> Copyright (C) 2004 Chris Kennedy <c@groovy.org> - Copyright (C) 2005-2007 Hans Verkuil <hverkuil@xs4all.nl> - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Copyright (C) 2005-2007 Hans Verkuil <hverkuil@kernel.org> */ /* License: GPL diff --git a/drivers/media/pci/ivtv/ivtv-streams.h b/drivers/media/pci/ivtv/ivtv-streams.h index 5f35c57fcdfd..43d4ecd6dd6f 100644 --- a/drivers/media/pci/ivtv/ivtv-streams.h +++ b/drivers/media/pci/ivtv/ivtv-streams.h @@ -2,7 +2,7 @@ /* init/start/stop/exit stream functions Copyright (C) 2003-2004 Kevin Thayer <nufan_wfk at yahoo.com> - Copyright (C) 2005-2007 Hans Verkuil <hverkuil@xs4all.nl> + Copyright (C) 2005-2007 Hans Verkuil <hverkuil@kernel.org> */ diff --git a/drivers/media/pci/ivtv/ivtv-udma.c b/drivers/media/pci/ivtv/ivtv-udma.c index f467a00492f4..7dedf04f9f87 100644 --- a/drivers/media/pci/ivtv/ivtv-udma.c +++ b/drivers/media/pci/ivtv/ivtv-udma.c @@ -4,7 +4,7 @@ Copyright (C) 2003-2004 Kevin Thayer <nufan_wfk at yahoo.com> Copyright (C) 2004 Chris Kennedy <c@groovy.org> - Copyright (C) 2005-2007 Hans Verkuil <hverkuil@xs4all.nl> + Copyright (C) 2005-2007 Hans Verkuil <hverkuil@kernel.org> */ diff --git a/drivers/media/pci/ivtv/ivtv-udma.h b/drivers/media/pci/ivtv/ivtv-udma.h index 12b9426b2db2..3030fadfdbc7 100644 --- a/drivers/media/pci/ivtv/ivtv-udma.h +++ b/drivers/media/pci/ivtv/ivtv-udma.h @@ -2,7 +2,7 @@ /* Copyright (C) 2003-2004 Kevin Thayer <nufan_wfk at yahoo.com> Copyright (C) 2004 Chris Kennedy <c@groovy.org> - Copyright (C) 2006-2007 Hans Verkuil <hverkuil@xs4all.nl> + Copyright (C) 2006-2007 Hans Verkuil <hverkuil@kernel.org> */ diff --git a/drivers/media/pci/ivtv/ivtv-vbi.c b/drivers/media/pci/ivtv/ivtv-vbi.c index 80478b026d75..ae7a00f46257 100644 --- a/drivers/media/pci/ivtv/ivtv-vbi.c +++ b/drivers/media/pci/ivtv/ivtv-vbi.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-or-later /* Vertical Blank Interval support functions - Copyright (C) 2004-2007 Hans Verkuil <hverkuil@xs4all.nl> + Copyright (C) 2004-2007 Hans Verkuil <hverkuil@kernel.org> */ diff --git a/drivers/media/pci/ivtv/ivtv-vbi.h b/drivers/media/pci/ivtv/ivtv-vbi.h index 780f73d2ab6b..12fe27da544b 100644 --- a/drivers/media/pci/ivtv/ivtv-vbi.h +++ b/drivers/media/pci/ivtv/ivtv-vbi.h @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0-or-later */ /* Vertical Blank Interval support functions - Copyright (C) 2004-2007 Hans Verkuil <hverkuil@xs4all.nl> + Copyright (C) 2004-2007 Hans Verkuil <hverkuil@kernel.org> */ diff --git a/drivers/media/pci/ivtv/ivtv-version.h b/drivers/media/pci/ivtv/ivtv-version.h index 996f1871e49c..21e26d1f66b8 100644 --- a/drivers/media/pci/ivtv/ivtv-version.h +++ b/drivers/media/pci/ivtv/ivtv-version.h @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0-or-later */ /* ivtv driver version information - Copyright (C) 2005-2007 Hans Verkuil <hverkuil@xs4all.nl> + Copyright (C) 2005-2007 Hans Verkuil <hverkuil@kernel.org> */ diff --git a/drivers/media/pci/ivtv/ivtv-yuv.c b/drivers/media/pci/ivtv/ivtv-yuv.c index 2d9274537725..71f040106647 100644 --- a/drivers/media/pci/ivtv/ivtv-yuv.c +++ b/drivers/media/pci/ivtv/ivtv-yuv.c @@ -125,7 +125,7 @@ static int ivtv_yuv_prep_user_dma(struct ivtv *itv, struct ivtv_user_dma *dma, ivtv_udma_fill_sg_array(dma, y_buffer_offset, uv_buffer_offset, y_size); /* If we've offset the y plane, ensure top area is blanked */ - if (f->offset_y && yi->blanking_dmaptr) { + if (f->offset_y && yi->blanking_ptr) { dma->SGarray[dma->SG_length].size = cpu_to_le32(720*16); dma->SGarray[dma->SG_length].src = cpu_to_le32(yi->blanking_dmaptr); dma->SGarray[dma->SG_length].dst = cpu_to_le32(IVTV_DECODER_OFFSET + yuv_offset[frame]); @@ -929,6 +929,12 @@ static void ivtv_yuv_init(struct ivtv *itv) yi->blanking_dmaptr = dma_map_single(&itv->pdev->dev, yi->blanking_ptr, 720 * 16, DMA_TO_DEVICE); + if (dma_mapping_error(&itv->pdev->dev, yi->blanking_dmaptr)) { + kfree(yi->blanking_ptr); + yi->blanking_ptr = NULL; + yi->blanking_dmaptr = 0; + IVTV_DEBUG_WARN("Failed to dma_map yuv blanking buffer\n"); + } } else { yi->blanking_dmaptr = 0; IVTV_DEBUG_WARN("Failed to allocate yuv blanking buffer\n"); diff --git a/drivers/media/pci/mgb4/mgb4_trigger.c b/drivers/media/pci/mgb4/mgb4_trigger.c index 923650d53d4c..d7dddc5c8728 100644 --- a/drivers/media/pci/mgb4/mgb4_trigger.c +++ b/drivers/media/pci/mgb4/mgb4_trigger.c @@ -91,7 +91,7 @@ static irqreturn_t trigger_handler(int irq, void *p) struct { u32 data; s64 ts __aligned(8); - } scan; + } scan = { }; scan.data = mgb4_read_reg(&st->mgbdev->video, 0xA0); mgb4_write_reg(&st->mgbdev->video, 0xA0, scan.data); diff --git a/drivers/media/pci/mgb4/mgb4_vin.c b/drivers/media/pci/mgb4/mgb4_vin.c index 989e93f67f75..42c327bc50e1 100644 --- a/drivers/media/pci/mgb4/mgb4_vin.c +++ b/drivers/media/pci/mgb4/mgb4_vin.c @@ -610,8 +610,7 @@ static int vidioc_s_dv_timings(struct file *file, void *fh, timings->bt.height < video_timings_cap.bt.min_height || timings->bt.height > video_timings_cap.bt.max_height) return -EINVAL; - if (timings->bt.width == vindev->timings.bt.width && - timings->bt.height == vindev->timings.bt.height) + if (v4l2_match_dv_timings(timings, &vindev->timings, 0, false)) return 0; if (vb2_is_busy(&vindev->queue)) return -EBUSY; diff --git a/drivers/media/pci/saa7134/saa7134-video.c b/drivers/media/pci/saa7134/saa7134-video.c index c88939bce56b..4a51b873e47a 100644 --- a/drivers/media/pci/saa7134/saa7134-video.c +++ b/drivers/media/pci/saa7134/saa7134-video.c @@ -1302,7 +1302,7 @@ static int saa7134_g_pixelaspect(struct file *file, void *priv, return 0; } -static int saa7134_g_selection(struct file *file, void *f, struct v4l2_selection *sel) +static int saa7134_g_selection(struct file *file, void *priv, struct v4l2_selection *sel) { struct saa7134_dev *dev = video_drvdata(file); @@ -1325,7 +1325,7 @@ static int saa7134_g_selection(struct file *file, void *f, struct v4l2_selection return 0; } -static int saa7134_s_selection(struct file *file, void *f, struct v4l2_selection *sel) +static int saa7134_s_selection(struct file *file, void *priv, struct v4l2_selection *sel) { struct saa7134_dev *dev = video_drvdata(file); struct v4l2_rect *b = &dev->crop_bounds; diff --git a/drivers/media/pci/saa7164/saa7164-encoder.c b/drivers/media/pci/saa7164/saa7164-encoder.c index bf73e9e83f52..66d650b5f69a 100644 --- a/drivers/media/pci/saa7164/saa7164-encoder.c +++ b/drivers/media/pci/saa7164/saa7164-encoder.c @@ -219,7 +219,7 @@ int saa7164_s_std(struct saa7164_port *port, v4l2_std_id id) static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id id) { - struct saa7164_encoder_fh *fh = file->private_data; + struct saa7164_encoder_fh *fh = to_saa7164_encoder_fh(file); return saa7164_s_std(fh->port, id); } @@ -232,7 +232,7 @@ int saa7164_g_std(struct saa7164_port *port, v4l2_std_id *id) static int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *id) { - struct saa7164_encoder_fh *fh = file->private_data; + struct saa7164_encoder_fh *fh = to_saa7164_encoder_fh(file); return saa7164_g_std(fh->port, id); } @@ -277,7 +277,7 @@ int saa7164_g_input(struct saa7164_port *port, unsigned int *i) static int vidioc_g_input(struct file *file, void *priv, unsigned int *i) { - struct saa7164_encoder_fh *fh = file->private_data; + struct saa7164_encoder_fh *fh = to_saa7164_encoder_fh(file); return saa7164_g_input(fh->port, i); } @@ -301,14 +301,14 @@ int saa7164_s_input(struct saa7164_port *port, unsigned int i) static int vidioc_s_input(struct file *file, void *priv, unsigned int i) { - struct saa7164_encoder_fh *fh = file->private_data; + struct saa7164_encoder_fh *fh = to_saa7164_encoder_fh(file); return saa7164_s_input(fh->port, i); } int saa7164_g_tuner(struct file *file, void *priv, struct v4l2_tuner *t) { - struct saa7164_encoder_fh *fh = file->private_data; + struct saa7164_encoder_fh *fh = to_saa7164_encoder_fh(file); struct saa7164_port *port = fh->port; struct saa7164_dev *dev = port->dev; @@ -347,7 +347,7 @@ int saa7164_g_frequency(struct saa7164_port *port, struct v4l2_frequency *f) static int vidioc_g_frequency(struct file *file, void *priv, struct v4l2_frequency *f) { - struct saa7164_encoder_fh *fh = file->private_data; + struct saa7164_encoder_fh *fh = to_saa7164_encoder_fh(file); return saa7164_g_frequency(fh->port, f); } @@ -400,7 +400,7 @@ int saa7164_s_frequency(struct saa7164_port *port, static int vidioc_s_frequency(struct file *file, void *priv, const struct v4l2_frequency *f) { - struct saa7164_encoder_fh *fh = file->private_data; + struct saa7164_encoder_fh *fh = to_saa7164_encoder_fh(file); return saa7164_s_frequency(fh->port, f); } @@ -483,7 +483,7 @@ static int saa7164_s_ctrl(struct v4l2_ctrl *ctrl) static int vidioc_querycap(struct file *file, void *priv, struct v4l2_capability *cap) { - struct saa7164_encoder_fh *fh = file->private_data; + struct saa7164_encoder_fh *fh = to_saa7164_encoder_fh(file); struct saa7164_port *port = fh->port; struct saa7164_dev *dev = port->dev; @@ -510,7 +510,7 @@ static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv, static int vidioc_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *f) { - struct saa7164_encoder_fh *fh = file->private_data; + struct saa7164_encoder_fh *fh = to_saa7164_encoder_fh(file); struct saa7164_port *port = fh->port; f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG; @@ -725,15 +725,14 @@ static int fops_open(struct file *file) fh->port = port; v4l2_fh_init(&fh->fh, video_devdata(file)); - v4l2_fh_add(&fh->fh); - file->private_data = fh; + v4l2_fh_add(&fh->fh, file); return 0; } static int fops_release(struct file *file) { - struct saa7164_encoder_fh *fh = file->private_data; + struct saa7164_encoder_fh *fh = to_saa7164_encoder_fh(file); struct saa7164_port *port = fh->port; struct saa7164_dev *dev = port->dev; @@ -747,7 +746,7 @@ static int fops_release(struct file *file) } } - v4l2_fh_del(&fh->fh); + v4l2_fh_del(&fh->fh, file); v4l2_fh_exit(&fh->fh); kfree(fh); @@ -787,7 +786,7 @@ saa7164_user_buffer *saa7164_enc_next_buf(struct saa7164_port *port) static ssize_t fops_read(struct file *file, char __user *buffer, size_t count, loff_t *pos) { - struct saa7164_encoder_fh *fh = file->private_data; + struct saa7164_encoder_fh *fh = to_saa7164_encoder_fh(file); struct saa7164_port *port = fh->port; struct saa7164_user_buffer *ubuf = NULL; struct saa7164_dev *dev = port->dev; @@ -893,8 +892,7 @@ err: static __poll_t fops_poll(struct file *file, poll_table *wait) { __poll_t req_events = poll_requested_events(wait); - struct saa7164_encoder_fh *fh = - (struct saa7164_encoder_fh *)file->private_data; + struct saa7164_encoder_fh *fh = to_saa7164_encoder_fh(file); struct saa7164_port *port = fh->port; __poll_t mask = v4l2_ctrl_poll(file, wait); diff --git a/drivers/media/pci/saa7164/saa7164-vbi.c b/drivers/media/pci/saa7164/saa7164-vbi.c index ac958a5fca78..57e4362c0d19 100644 --- a/drivers/media/pci/saa7164/saa7164-vbi.c +++ b/drivers/media/pci/saa7164/saa7164-vbi.c @@ -144,28 +144,28 @@ static int saa7164_vbi_initialize(struct saa7164_port *port) /* -- V4L2 --------------------------------------------------------- */ static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id id) { - struct saa7164_vbi_fh *fh = file->private_data; + struct saa7164_vbi_fh *fh = to_saa7164_vbi_fh(file); return saa7164_s_std(fh->port->enc_port, id); } static int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *id) { - struct saa7164_encoder_fh *fh = file->private_data; + struct saa7164_vbi_fh *fh = to_saa7164_vbi_fh(file); return saa7164_g_std(fh->port->enc_port, id); } static int vidioc_g_input(struct file *file, void *priv, unsigned int *i) { - struct saa7164_vbi_fh *fh = file->private_data; + struct saa7164_vbi_fh *fh = to_saa7164_vbi_fh(file); return saa7164_g_input(fh->port->enc_port, i); } static int vidioc_s_input(struct file *file, void *priv, unsigned int i) { - struct saa7164_vbi_fh *fh = file->private_data; + struct saa7164_vbi_fh *fh = to_saa7164_vbi_fh(file); return saa7164_s_input(fh->port->enc_port, i); } @@ -173,7 +173,7 @@ static int vidioc_s_input(struct file *file, void *priv, unsigned int i) static int vidioc_g_frequency(struct file *file, void *priv, struct v4l2_frequency *f) { - struct saa7164_vbi_fh *fh = file->private_data; + struct saa7164_vbi_fh *fh = to_saa7164_vbi_fh(file); return saa7164_g_frequency(fh->port->enc_port, f); } @@ -181,7 +181,7 @@ static int vidioc_g_frequency(struct file *file, void *priv, static int vidioc_s_frequency(struct file *file, void *priv, const struct v4l2_frequency *f) { - struct saa7164_vbi_fh *fh = file->private_data; + struct saa7164_vbi_fh *fh = to_saa7164_vbi_fh(file); int ret = saa7164_s_frequency(fh->port->enc_port, f); if (ret == 0) @@ -192,7 +192,7 @@ static int vidioc_s_frequency(struct file *file, void *priv, static int vidioc_querycap(struct file *file, void *priv, struct v4l2_capability *cap) { - struct saa7164_vbi_fh *fh = file->private_data; + struct saa7164_vbi_fh *fh = to_saa7164_vbi_fh(file); struct saa7164_port *port = fh->port; struct saa7164_dev *dev = port->dev; @@ -428,15 +428,14 @@ static int fops_open(struct file *file) fh->port = port; v4l2_fh_init(&fh->fh, video_devdata(file)); - v4l2_fh_add(&fh->fh); - file->private_data = fh; + v4l2_fh_add(&fh->fh, file); return 0; } static int fops_release(struct file *file) { - struct saa7164_vbi_fh *fh = file->private_data; + struct saa7164_vbi_fh *fh = to_saa7164_vbi_fh(file); struct saa7164_port *port = fh->port; struct saa7164_dev *dev = port->dev; @@ -450,7 +449,7 @@ static int fops_release(struct file *file) } } - v4l2_fh_del(&fh->fh); + v4l2_fh_del(&fh->fh, file); v4l2_fh_exit(&fh->fh); kfree(fh); @@ -489,7 +488,7 @@ saa7164_user_buffer *saa7164_vbi_next_buf(struct saa7164_port *port) static ssize_t fops_read(struct file *file, char __user *buffer, size_t count, loff_t *pos) { - struct saa7164_vbi_fh *fh = file->private_data; + struct saa7164_vbi_fh *fh = to_saa7164_vbi_fh(file); struct saa7164_port *port = fh->port; struct saa7164_user_buffer *ubuf = NULL; struct saa7164_dev *dev = port->dev; @@ -596,7 +595,7 @@ err: static __poll_t fops_poll(struct file *file, poll_table *wait) { - struct saa7164_vbi_fh *fh = (struct saa7164_vbi_fh *)file->private_data; + struct saa7164_vbi_fh *fh = to_saa7164_vbi_fh(file); struct saa7164_port *port = fh->port; __poll_t mask = 0; diff --git a/drivers/media/pci/saa7164/saa7164.h b/drivers/media/pci/saa7164/saa7164.h index e1bac1fe19d3..94e987e7b5e5 100644 --- a/drivers/media/pci/saa7164/saa7164.h +++ b/drivers/media/pci/saa7164/saa7164.h @@ -180,12 +180,22 @@ struct saa7164_encoder_fh { atomic_t v4l_reading; }; +static inline struct saa7164_encoder_fh *to_saa7164_encoder_fh(struct file *filp) +{ + return container_of(file_to_v4l2_fh(filp), struct saa7164_encoder_fh, fh); +} + struct saa7164_vbi_fh { struct v4l2_fh fh; struct saa7164_port *port; atomic_t v4l_reading; }; +static inline struct saa7164_vbi_fh *to_saa7164_vbi_fh(struct file *filp) +{ + return container_of(file_to_v4l2_fh(filp), struct saa7164_vbi_fh, fh); +} + struct saa7164_histogram_bucket { u32 val; u32 count; diff --git a/drivers/media/pci/tw68/tw68-core.c b/drivers/media/pci/tw68/tw68-core.c index 35dd19b2427e..08b7ce1043aa 100644 --- a/drivers/media/pci/tw68/tw68-core.c +++ b/drivers/media/pci/tw68/tw68-core.c @@ -14,7 +14,7 @@ * * Refactored and updated to the latest v4l core frameworks: * - * Copyright (C) 2014 Hans Verkuil <hverkuil@xs4all.nl> + * Copyright (C) 2014 Hans Verkuil <hverkuil@kernel.org> */ #include <linux/init.h> @@ -37,7 +37,7 @@ MODULE_DESCRIPTION("v4l2 driver module for tw6800 based video capture cards"); MODULE_AUTHOR("William M. Brack"); -MODULE_AUTHOR("Hans Verkuil <hverkuil@xs4all.nl>"); +MODULE_AUTHOR("Hans Verkuil <hverkuil@kernel.org>"); MODULE_LICENSE("GPL"); static unsigned int latency = UNSET; diff --git a/drivers/media/pci/tw68/tw68-reg.h b/drivers/media/pci/tw68/tw68-reg.h index dcd9931b25cc..8aeef452ea8a 100644 --- a/drivers/media/pci/tw68/tw68-reg.h +++ b/drivers/media/pci/tw68/tw68-reg.h @@ -13,7 +13,7 @@ * * Refactored and updated to the latest v4l core frameworks: * - * Copyright (C) 2014 Hans Verkuil <hverkuil@xs4all.nl> + * Copyright (C) 2014 Hans Verkuil <hverkuil@kernel.org> */ #ifndef _TW68_REG_H_ diff --git a/drivers/media/pci/tw68/tw68-risc.c b/drivers/media/pci/tw68/tw68-risc.c index dacb136c4f3a..e793db6134e4 100644 --- a/drivers/media/pci/tw68/tw68-risc.c +++ b/drivers/media/pci/tw68/tw68-risc.c @@ -14,7 +14,7 @@ * * Refactored and updated to the latest v4l core frameworks: * - * Copyright (C) 2014 Hans Verkuil <hverkuil@xs4all.nl> + * Copyright (C) 2014 Hans Verkuil <hverkuil@kernel.org> */ #include "tw68.h" diff --git a/drivers/media/pci/tw68/tw68-video.c b/drivers/media/pci/tw68/tw68-video.c index 77773dec48b8..6232bac170d0 100644 --- a/drivers/media/pci/tw68/tw68-video.c +++ b/drivers/media/pci/tw68/tw68-video.c @@ -13,7 +13,7 @@ * * Refactored and updated to the latest v4l core frameworks: * - * Copyright (C) 2014 Hans Verkuil <hverkuil@xs4all.nl> + * Copyright (C) 2014 Hans Verkuil <hverkuil@kernel.org> */ #include <linux/module.h> diff --git a/drivers/media/pci/tw68/tw68.h b/drivers/media/pci/tw68/tw68.h index a1f422d6e600..66be6b3bb7b6 100644 --- a/drivers/media/pci/tw68/tw68.h +++ b/drivers/media/pci/tw68/tw68.h @@ -13,7 +13,7 @@ * * Refactored and updated to the latest v4l core frameworks: * - * Copyright (C) 2014 Hans Verkuil <hverkuil@xs4all.nl> + * Copyright (C) 2014 Hans Verkuil <hverkuil@kernel.org> */ #include <linux/pci.h> diff --git a/drivers/media/pci/zoran/zoran.h b/drivers/media/pci/zoran/zoran.h index 1cd990468d3d..d05e222b3921 100644 --- a/drivers/media/pci/zoran/zoran.h +++ b/drivers/media/pci/zoran/zoran.h @@ -154,12 +154,6 @@ struct zoran_jpg_settings { struct zoran; -/* zoran_fh contains per-open() settings */ -struct zoran_fh { - struct v4l2_fh fh; - struct zoran *zr; -}; - struct card_info { enum card_type type; char name[32]; diff --git a/drivers/media/pci/zoran/zoran_card.c b/drivers/media/pci/zoran/zoran_card.c index e31f9f19a48a..d81facf735d9 100644 --- a/drivers/media/pci/zoran/zoran_card.c +++ b/drivers/media/pci/zoran/zoran_card.c @@ -67,10 +67,6 @@ module_param(pass_through, int, 0644); MODULE_PARM_DESC(pass_through, "Pass TV signal through to TV-out when idling"); -int zr36067_debug = 1; -module_param_named(debug, zr36067_debug, int, 0644); -MODULE_PARM_DESC(debug, "Debug level (0-5)"); - #define ZORAN_VERSION "0.10.1" MODULE_DESCRIPTION("Zoran-36057/36067 JPEG codec driver"); diff --git a/drivers/media/pci/zoran/zoran_card.h b/drivers/media/pci/zoran/zoran_card.h index 518cb426b446..c4f81777e6ce 100644 --- a/drivers/media/pci/zoran/zoran_card.h +++ b/drivers/media/pci/zoran/zoran_card.h @@ -12,8 +12,6 @@ #ifndef __ZORAN_CARD_H__ #define __ZORAN_CARD_H__ -extern int zr36067_debug; - /* Anybody who uses more than four? */ #define BUZ_MAX 4 diff --git a/drivers/media/pci/zoran/zoran_driver.c b/drivers/media/pci/zoran/zoran_driver.c index f42f596d3e62..5b4d5dd06edb 100644 --- a/drivers/media/pci/zoran/zoran_driver.c +++ b/drivers/media/pci/zoran/zoran_driver.c @@ -245,7 +245,7 @@ static int zoran_set_input(struct zoran *zr, int input) * ioctl routine */ -static int zoran_querycap(struct file *file, void *__fh, struct v4l2_capability *cap) +static int zoran_querycap(struct file *file, void *fh, struct v4l2_capability *cap) { struct zoran *zr = video_drvdata(file); @@ -278,7 +278,7 @@ static int zoran_enum_fmt(struct zoran *zr, struct v4l2_fmtdesc *fmt, int flag) return -EINVAL; } -static int zoran_enum_fmt_vid_cap(struct file *file, void *__fh, +static int zoran_enum_fmt_vid_cap(struct file *file, void *fh, struct v4l2_fmtdesc *f) { struct zoran *zr = video_drvdata(file); @@ -286,7 +286,7 @@ static int zoran_enum_fmt_vid_cap(struct file *file, void *__fh, return zoran_enum_fmt(zr, f, ZORAN_FORMAT_CAPTURE); } -static int zoran_g_fmt_vid_out(struct file *file, void *__fh, +static int zoran_g_fmt_vid_out(struct file *file, void *fh, struct v4l2_format *fmt) { struct zoran *zr = video_drvdata(file); @@ -308,13 +308,13 @@ static int zoran_g_fmt_vid_out(struct file *file, void *__fh, return 0; } -static int zoran_g_fmt_vid_cap(struct file *file, void *__fh, +static int zoran_g_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *fmt) { struct zoran *zr = video_drvdata(file); if (zr->map_mode != ZORAN_MAP_MODE_RAW) - return zoran_g_fmt_vid_out(file, __fh, fmt); + return zoran_g_fmt_vid_out(file, fh, fmt); fmt->fmt.pix.width = zr->v4l_settings.width; fmt->fmt.pix.height = zr->v4l_settings.height; fmt->fmt.pix.sizeimage = zr->buffer_size; @@ -328,7 +328,7 @@ static int zoran_g_fmt_vid_cap(struct file *file, void *__fh, return 0; } -static int zoran_try_fmt_vid_out(struct file *file, void *__fh, +static int zoran_try_fmt_vid_out(struct file *file, void *fh, struct v4l2_format *fmt) { struct zoran *zr = video_drvdata(file); @@ -391,7 +391,7 @@ static int zoran_try_fmt_vid_out(struct file *file, void *__fh, return res; } -static int zoran_try_fmt_vid_cap(struct file *file, void *__fh, +static int zoran_try_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *fmt) { struct zoran *zr = video_drvdata(file); @@ -399,7 +399,7 @@ static int zoran_try_fmt_vid_cap(struct file *file, void *__fh, int i; if (fmt->fmt.pix.pixelformat == V4L2_PIX_FMT_MJPEG) - return zoran_try_fmt_vid_out(file, __fh, fmt); + return zoran_try_fmt_vid_out(file, fh, fmt); for (i = 0; i < NUM_FORMATS; i++) if (zoran_formats[i].fourcc == fmt->fmt.pix.pixelformat) @@ -427,7 +427,7 @@ static int zoran_try_fmt_vid_cap(struct file *file, void *__fh, return 0; } -static int zoran_s_fmt_vid_out(struct file *file, void *__fh, +static int zoran_s_fmt_vid_out(struct file *file, void *fh, struct v4l2_format *fmt) { struct zoran *zr = video_drvdata(file); @@ -507,11 +507,10 @@ static int zoran_s_fmt_vid_out(struct file *file, void *__fh, return res; } -static int zoran_s_fmt_vid_cap(struct file *file, void *__fh, +static int zoran_s_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *fmt) { struct zoran *zr = video_drvdata(file); - struct zoran_fh *fh = __fh; int i; int res = 0; @@ -556,7 +555,7 @@ static int zoran_s_fmt_vid_cap(struct file *file, void *__fh, return res; } -static int zoran_g_std(struct file *file, void *__fh, v4l2_std_id *std) +static int zoran_g_std(struct file *file, void *fh, v4l2_std_id *std) { struct zoran *zr = video_drvdata(file); @@ -564,7 +563,7 @@ static int zoran_g_std(struct file *file, void *__fh, v4l2_std_id *std) return 0; } -static int zoran_s_std(struct file *file, void *__fh, v4l2_std_id std) +static int zoran_s_std(struct file *file, void *fh, v4l2_std_id std) { struct zoran *zr = video_drvdata(file); int res = 0; @@ -579,7 +578,7 @@ static int zoran_s_std(struct file *file, void *__fh, v4l2_std_id std) return res; } -static int zoran_enum_input(struct file *file, void *__fh, +static int zoran_enum_input(struct file *file, void *fh, struct v4l2_input *inp) { struct zoran *zr = video_drvdata(file); @@ -596,7 +595,7 @@ static int zoran_enum_input(struct file *file, void *__fh, return 0; } -static int zoran_g_input(struct file *file, void *__fh, unsigned int *input) +static int zoran_g_input(struct file *file, void *fh, unsigned int *input) { struct zoran *zr = video_drvdata(file); @@ -605,7 +604,7 @@ static int zoran_g_input(struct file *file, void *__fh, unsigned int *input) return 0; } -static int zoran_s_input(struct file *file, void *__fh, unsigned int input) +static int zoran_s_input(struct file *file, void *fh, unsigned int input) { struct zoran *zr = video_drvdata(file); int res; @@ -618,7 +617,7 @@ static int zoran_s_input(struct file *file, void *__fh, unsigned int input) } /* cropping (sub-frame capture) */ -static int zoran_g_selection(struct file *file, void *__fh, struct v4l2_selection *sel) +static int zoran_g_selection(struct file *file, void *fh, struct v4l2_selection *sel) { struct zoran *zr = video_drvdata(file); @@ -653,7 +652,7 @@ static int zoran_g_selection(struct file *file, void *__fh, struct v4l2_selectio return 0; } -static int zoran_s_selection(struct file *file, void *__fh, struct v4l2_selection *sel) +static int zoran_s_selection(struct file *file, void *fh, struct v4l2_selection *sel) { struct zoran *zr = video_drvdata(file); struct zoran_jpg_settings settings; diff --git a/drivers/media/platform/allegro-dvt/allegro-core.c b/drivers/media/platform/allegro-dvt/allegro-core.c index eb03df0d8652..510c3c9661d9 100644 --- a/drivers/media/platform/allegro-dvt/allegro-core.c +++ b/drivers/media/platform/allegro-dvt/allegro-core.c @@ -197,8 +197,6 @@ static const struct regmap_config allegro_sram_config = { .cache_type = REGCACHE_NONE, }; -#define fh_to_channel(__fh) container_of(__fh, struct allegro_channel, fh) - struct allegro_channel { struct allegro_dev *dev; struct v4l2_fh fh; @@ -302,6 +300,11 @@ struct allegro_channel { unsigned int error; }; +static inline struct allegro_channel *file_to_channel(struct file *filp) +{ + return container_of(file_to_v4l2_fh(filp), struct allegro_channel, fh); +} + static inline int allegro_channel_get_i_frame_qp(struct allegro_channel *channel) { @@ -3214,8 +3217,7 @@ static int allegro_open(struct file *file) } list_add(&channel->list, &dev->channels); - file->private_data = &channel->fh; - v4l2_fh_add(&channel->fh); + v4l2_fh_add(&channel->fh, file); allegro_channel_adjust(channel); @@ -3229,7 +3231,7 @@ error: static int allegro_release(struct file *file) { - struct allegro_channel *channel = fh_to_channel(file->private_data); + struct allegro_channel *channel = file_to_channel(file); v4l2_m2m_ctx_release(channel->fh.m2m_ctx); @@ -3237,7 +3239,7 @@ static int allegro_release(struct file *file) v4l2_ctrl_handler_free(&channel->ctrl_handler); - v4l2_fh_del(&channel->fh); + v4l2_fh_del(&channel->fh, file); v4l2_fh_exit(&channel->fh); kfree(channel); @@ -3280,7 +3282,7 @@ static int allegro_enum_fmt_vid(struct file *file, void *fh, static int allegro_g_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *f) { - struct allegro_channel *channel = fh_to_channel(fh); + struct allegro_channel *channel = file_to_channel(file); f->fmt.pix.field = V4L2_FIELD_NONE; f->fmt.pix.width = channel->width; @@ -3322,7 +3324,7 @@ static int allegro_try_fmt_vid_cap(struct file *file, void *fh, static int allegro_s_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *f) { - struct allegro_channel *channel = fh_to_channel(fh); + struct allegro_channel *channel = file_to_channel(file); struct vb2_queue *vq; int err; @@ -3346,7 +3348,7 @@ static int allegro_s_fmt_vid_cap(struct file *file, void *fh, static int allegro_g_fmt_vid_out(struct file *file, void *fh, struct v4l2_format *f) { - struct allegro_channel *channel = fh_to_channel(fh); + struct allegro_channel *channel = file_to_channel(file); f->fmt.pix.field = V4L2_FIELD_NONE; @@ -3393,7 +3395,7 @@ static int allegro_try_fmt_vid_out(struct file *file, void *fh, static int allegro_s_fmt_vid_out(struct file *file, void *fh, struct v4l2_format *f) { - struct allegro_channel *channel = fh_to_channel(fh); + struct allegro_channel *channel = file_to_channel(file); int err; err = allegro_try_fmt_vid_out(file, fh, f); @@ -3434,7 +3436,7 @@ static int allegro_channel_cmd_start(struct allegro_channel *channel) static int allegro_encoder_cmd(struct file *file, void *fh, struct v4l2_encoder_cmd *cmd) { - struct allegro_channel *channel = fh_to_channel(fh); + struct allegro_channel *channel = file_to_channel(file); int err; err = v4l2_m2m_ioctl_try_encoder_cmd(file, fh, cmd); @@ -3483,8 +3485,7 @@ static int allegro_enum_framesizes(struct file *file, void *fh, static int allegro_ioctl_streamon(struct file *file, void *priv, enum v4l2_buf_type type) { - struct v4l2_fh *fh = file->private_data; - struct allegro_channel *channel = fh_to_channel(fh); + struct allegro_channel *channel = file_to_channel(file); int err; if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE) { @@ -3493,13 +3494,13 @@ static int allegro_ioctl_streamon(struct file *file, void *priv, return err; } - return v4l2_m2m_streamon(file, fh->m2m_ctx, type); + return v4l2_m2m_streamon(file, channel->fh.m2m_ctx, type); } static int allegro_g_parm(struct file *file, void *fh, struct v4l2_streamparm *a) { - struct allegro_channel *channel = fh_to_channel(fh); + struct allegro_channel *channel = file_to_channel(file); struct v4l2_fract *timeperframe; if (a->type != V4L2_BUF_TYPE_VIDEO_OUTPUT) @@ -3516,7 +3517,7 @@ static int allegro_g_parm(struct file *file, void *fh, static int allegro_s_parm(struct file *file, void *fh, struct v4l2_streamparm *a) { - struct allegro_channel *channel = fh_to_channel(fh); + struct allegro_channel *channel = file_to_channel(file); struct v4l2_fract *timeperframe; int div; diff --git a/drivers/media/platform/amlogic/c3/mipi-csi2/c3-mipi-csi2.c b/drivers/media/platform/amlogic/c3/mipi-csi2/c3-mipi-csi2.c index 1011ab3ebac7..b9e4ef3fc308 100644 --- a/drivers/media/platform/amlogic/c3/mipi-csi2/c3-mipi-csi2.c +++ b/drivers/media/platform/amlogic/c3/mipi-csi2/c3-mipi-csi2.c @@ -388,13 +388,12 @@ static void c3_mipi_csi_cfg_host(struct c3_csi_device *csi) c3_mipi_csi_write(csi, CSI2_HOST_N_LANES, csi->bus.num_data_lanes - 1); } -static int c3_mipi_csi_start_stream(struct c3_csi_device *csi, - struct v4l2_subdev *src_sd) +static int c3_mipi_csi_start_stream(struct c3_csi_device *csi) { s64 link_freq; s64 lane_rate; - link_freq = v4l2_get_link_freq(src_sd->ctrl_handler, 0, 0); + link_freq = v4l2_get_link_freq(csi->src_pad, 0, 0); if (link_freq < 0) { dev_err(csi->dev, "Unable to obtain link frequency: %lld\n", link_freq); @@ -434,7 +433,7 @@ static int c3_mipi_csi_enable_streams(struct v4l2_subdev *sd, pm_runtime_resume_and_get(csi->dev); - c3_mipi_csi_start_stream(csi, src_sd); + c3_mipi_csi_start_stream(csi); ret = v4l2_subdev_enable_streams(src_sd, csi->src_pad->index, BIT(0)); if (ret) { diff --git a/drivers/media/platform/amlogic/meson-ge2d/ge2d.c b/drivers/media/platform/amlogic/meson-ge2d/ge2d.c index 0c004bb8ba05..5744853a4003 100644 --- a/drivers/media/platform/amlogic/meson-ge2d/ge2d.c +++ b/drivers/media/platform/amlogic/meson-ge2d/ge2d.c @@ -82,6 +82,11 @@ struct ge2d_ctx { u32 xy_swap; }; +static inline struct ge2d_ctx *file_to_ge2d_ctx(struct file *filp) +{ + return container_of(file_to_v4l2_fh(filp), struct ge2d_ctx, fh); +} + struct meson_ge2d { struct v4l2_device v4l2_dev; struct v4l2_m2m_dev *m2m_dev; @@ -452,7 +457,7 @@ static int vidioc_enum_fmt(struct file *file, void *priv, struct v4l2_fmtdesc *f static int vidioc_g_selection(struct file *file, void *priv, struct v4l2_selection *s) { - struct ge2d_ctx *ctx = priv; + struct ge2d_ctx *ctx = file_to_ge2d_ctx(file); struct ge2d_frame *f; bool use_frame = false; @@ -502,7 +507,7 @@ static int vidioc_g_selection(struct file *file, void *priv, static int vidioc_s_selection(struct file *file, void *priv, struct v4l2_selection *s) { - struct ge2d_ctx *ctx = priv; + struct ge2d_ctx *ctx = file_to_ge2d_ctx(file); struct meson_ge2d *ge2d = ctx->ge2d; struct ge2d_frame *f; int ret = 0; @@ -569,8 +574,8 @@ static void vidioc_setup_cap_fmt(struct ge2d_ctx *ctx, struct v4l2_pix_format *f static int vidioc_try_fmt_cap(struct file *file, void *priv, struct v4l2_format *f) { + struct ge2d_ctx *ctx = file_to_ge2d_ctx(file); const struct ge2d_fmt *fmt = find_fmt(f); - struct ge2d_ctx *ctx = priv; struct v4l2_pix_format fmt_cap; vidioc_setup_cap_fmt(ctx, &fmt_cap); @@ -590,7 +595,7 @@ static int vidioc_try_fmt_cap(struct file *file, void *priv, struct v4l2_format static int vidioc_s_fmt_cap(struct file *file, void *priv, struct v4l2_format *f) { - struct ge2d_ctx *ctx = priv; + struct ge2d_ctx *ctx = file_to_ge2d_ctx(file); struct meson_ge2d *ge2d = ctx->ge2d; struct vb2_queue *vq; struct ge2d_frame *frm; @@ -626,7 +631,7 @@ static int vidioc_s_fmt_cap(struct file *file, void *priv, struct v4l2_format *f static int vidioc_g_fmt(struct file *file, void *priv, struct v4l2_format *f) { - struct ge2d_ctx *ctx = priv; + struct ge2d_ctx *ctx = file_to_ge2d_ctx(file); struct vb2_queue *vq; struct ge2d_frame *frm; @@ -665,7 +670,7 @@ static int vidioc_try_fmt_out(struct file *file, void *priv, struct v4l2_format static int vidioc_s_fmt_out(struct file *file, void *priv, struct v4l2_format *f) { - struct ge2d_ctx *ctx = priv; + struct ge2d_ctx *ctx = file_to_ge2d_ctx(file); struct meson_ge2d *ge2d = ctx->ge2d; struct vb2_queue *vq; struct ge2d_frame *frm, *frm_cap; @@ -855,8 +860,7 @@ static int ge2d_open(struct file *file) return ret; } v4l2_fh_init(&ctx->fh, video_devdata(file)); - file->private_data = &ctx->fh; - v4l2_fh_add(&ctx->fh); + v4l2_fh_add(&ctx->fh, file); ge2d_setup_ctrls(ctx); @@ -871,8 +875,7 @@ static int ge2d_open(struct file *file) static int ge2d_release(struct file *file) { - struct ge2d_ctx *ctx = - container_of(file->private_data, struct ge2d_ctx, fh); + struct ge2d_ctx *ctx = file_to_ge2d_ctx(file); struct meson_ge2d *ge2d = ctx->ge2d; mutex_lock(&ge2d->mutex); @@ -880,7 +883,7 @@ static int ge2d_release(struct file *file) v4l2_m2m_ctx_release(ctx->fh.m2m_ctx); v4l2_ctrl_handler_free(&ctx->ctrl_handler); - v4l2_fh_del(&ctx->fh); + v4l2_fh_del(&ctx->fh, file); v4l2_fh_exit(&ctx->fh); kfree(ctx); diff --git a/drivers/media/platform/amphion/vpu.h b/drivers/media/platform/amphion/vpu.h index cac0f1a64fea..bfd171a3ded4 100644 --- a/drivers/media/platform/amphion/vpu.h +++ b/drivers/media/platform/amphion/vpu.h @@ -328,7 +328,7 @@ static inline const char *vpu_core_type_desc(enum vpu_core_type type) static inline struct vpu_inst *to_inst(struct file *filp) { - return container_of(filp->private_data, struct vpu_inst, fh); + return container_of(file_to_v4l2_fh(filp), struct vpu_inst, fh); } #define ctrl_to_inst(ctrl) \ diff --git a/drivers/media/platform/amphion/vpu_v4l2.c b/drivers/media/platform/amphion/vpu_v4l2.c index 74668fa362e2..fcb2eff813ac 100644 --- a/drivers/media/platform/amphion/vpu_v4l2.c +++ b/drivers/media/platform/amphion/vpu_v4l2.c @@ -24,6 +24,11 @@ #include "vpu_msgs.h" #include "vpu_helpers.h" +static char *vpu_type_name(u32 type) +{ + return V4L2_TYPE_IS_OUTPUT(type) ? "output" : "capture"; +} + void vpu_inst_lock(struct vpu_inst *inst) { mutex_lock(&inst->lock); @@ -42,7 +47,7 @@ dma_addr_t vpu_get_vb_phy_addr(struct vb2_buffer *vb, u32 plane_no) vb->planes[plane_no].data_offset; } -unsigned int vpu_get_vb_length(struct vb2_buffer *vb, u32 plane_no) +static unsigned int vpu_get_vb_length(struct vb2_buffer *vb, u32 plane_no) { if (plane_no >= vb->num_planes) return 0; @@ -81,7 +86,7 @@ void vpu_v4l2_set_error(struct vpu_inst *inst) vpu_inst_unlock(inst); } -int vpu_notify_eos(struct vpu_inst *inst) +static int vpu_notify_eos(struct vpu_inst *inst) { static const struct v4l2_event ev = { .id = 0, @@ -573,7 +578,8 @@ static void vpu_vb2_buf_finish(struct vb2_buffer *vb) call_void_vop(inst, on_queue_empty, q->type); } -void vpu_vb2_buffers_return(struct vpu_inst *inst, unsigned int type, enum vb2_buffer_state state) +static void vpu_vb2_buffers_return(struct vpu_inst *inst, unsigned int type, + enum vb2_buffer_state state) { struct vb2_v4l2_buffer *buf; @@ -718,8 +724,6 @@ static int vpu_v4l2_release(struct vpu_inst *inst) v4l2_ctrl_handler_free(&inst->ctrl_handler); mutex_destroy(&inst->lock); - v4l2_fh_del(&inst->fh); - v4l2_fh_exit(&inst->fh); call_void_vop(inst, cleanup); @@ -756,7 +760,7 @@ int vpu_v4l2_open(struct file *file, struct vpu_inst *inst) inst->min_buffer_cap = 2; inst->min_buffer_out = 2; v4l2_fh_init(&inst->fh, func->vfd); - v4l2_fh_add(&inst->fh); + v4l2_fh_add(&inst->fh, file); ret = call_vop(inst, ctrl_init); if (ret) @@ -770,7 +774,6 @@ int vpu_v4l2_open(struct file *file, struct vpu_inst *inst) } inst->fh.ctrl_handler = &inst->ctrl_handler; - file->private_data = &inst->fh; inst->state = VPU_CODEC_STATE_DEINIT; inst->workqueue = alloc_ordered_workqueue("vpu_inst", WQ_MEM_RECLAIM); if (inst->workqueue) { @@ -788,6 +791,8 @@ int vpu_v4l2_open(struct file *file, struct vpu_inst *inst) return 0; error: + v4l2_fh_del(&inst->fh, file); + v4l2_fh_exit(&inst->fh); vpu_inst_put(inst); return ret; } @@ -807,6 +812,9 @@ int vpu_v4l2_close(struct file *file) call_void_vop(inst, release); vpu_inst_unlock(inst); + v4l2_fh_del(&inst->fh, file); + v4l2_fh_exit(&inst->fh); + vpu_inst_unregister(inst); vpu_inst_put(inst); diff --git a/drivers/media/platform/amphion/vpu_v4l2.h b/drivers/media/platform/amphion/vpu_v4l2.h index 56f2939fa84d..4a87b06ae520 100644 --- a/drivers/media/platform/amphion/vpu_v4l2.h +++ b/drivers/media/platform/amphion/vpu_v4l2.h @@ -26,15 +26,12 @@ void vpu_skip_frame(struct vpu_inst *inst, int count); struct vb2_v4l2_buffer *vpu_find_buf_by_sequence(struct vpu_inst *inst, u32 type, u32 sequence); struct vb2_v4l2_buffer *vpu_find_buf_by_idx(struct vpu_inst *inst, u32 type, u32 idx); void vpu_v4l2_set_error(struct vpu_inst *inst); -int vpu_notify_eos(struct vpu_inst *inst); int vpu_notify_source_change(struct vpu_inst *inst); int vpu_set_last_buffer_dequeued(struct vpu_inst *inst, bool eos); -void vpu_vb2_buffers_return(struct vpu_inst *inst, unsigned int type, enum vb2_buffer_state state); int vpu_get_num_buffers(struct vpu_inst *inst, u32 type); bool vpu_is_source_empty(struct vpu_inst *inst); dma_addr_t vpu_get_vb_phy_addr(struct vb2_buffer *vb, u32 plane_no); -unsigned int vpu_get_vb_length(struct vb2_buffer *vb, u32 plane_no); static inline struct vpu_format *vpu_get_format(struct vpu_inst *inst, u32 type) { if (V4L2_TYPE_IS_OUTPUT(type)) @@ -43,11 +40,6 @@ static inline struct vpu_format *vpu_get_format(struct vpu_inst *inst, u32 type) return &inst->cap_format; } -static inline char *vpu_type_name(u32 type) -{ - return V4L2_TYPE_IS_OUTPUT(type) ? "output" : "capture"; -} - static inline int vpu_vb_is_codecconfig(struct vb2_v4l2_buffer *vbuf) { #ifdef V4L2_BUF_FLAG_CODECCONFIG diff --git a/drivers/media/platform/aspeed/aspeed-video.c b/drivers/media/platform/aspeed/aspeed-video.c index 54cae0da9aca..b83e43245277 100644 --- a/drivers/media/platform/aspeed/aspeed-video.c +++ b/drivers/media/platform/aspeed/aspeed-video.c @@ -4,6 +4,7 @@ #include <linux/atomic.h> #include <linux/bitfield.h> +#include <linux/cleanup.h> #include <linux/clk.h> #include <linux/delay.h> #include <linux/device.h> @@ -25,6 +26,8 @@ #include <linux/workqueue.h> #include <linux/debugfs.h> #include <linux/ktime.h> +#include <linux/regmap.h> +#include <linux/mfd/syscon.h> #include <media/v4l2-ctrls.h> #include <media/v4l2-dev.h> #include <media/v4l2-device.h> @@ -203,6 +206,25 @@ #define VE_MEM_RESTRICT_START 0x310 #define VE_MEM_RESTRICT_END 0x314 +/* SCU's registers */ +#define SCU_MISC_CTRL 0xC0 +#define SCU_DPLL_SOURCE BIT(20) + +/* GFX's registers */ +#define GFX_CTRL 0x60 +#define GFX_CTRL_ENABLE BIT(0) +#define GFX_CTRL_FMT GENMASK(9, 7) + +#define GFX_H_DISPLAY 0x70 +#define GFX_H_DISPLAY_DE GENMASK(28, 16) +#define GFX_H_DISPLAY_TOTAL GENMASK(12, 0) + +#define GFX_V_DISPLAY 0x78 +#define GFX_V_DISPLAY_DE GENMASK(27, 16) +#define GFX_V_DISPLAY_TOTAL GENMASK(11, 0) + +#define GFX_DISPLAY_ADDR 0x80 + /* * VIDEO_MODE_DETECT_DONE: a flag raised if signal lock * VIDEO_RES_CHANGE: a flag raised if res_change work on-going @@ -262,6 +284,7 @@ struct aspeed_video_perf { /* * struct aspeed_video - driver data * + * version: holds the version of aspeed SoC * res_work: holds the delayed_work for res-detection if unlock * buffers: holds the list of buffer queued from user * flags: holds the state of video @@ -273,6 +296,7 @@ struct aspeed_video_perf { * yuv420: a flag raised if JPEG subsampling is 420 * format: holds the video format * hq_mode: a flag raised if HQ is enabled. Only for VIDEO_FMT_ASPEED + * input: holds the video input * frame_rate: holds the frame_rate * jpeg_quality: holds jpeq's quality (0~11) * jpeg_hq_quality: holds hq's quality (1~12) only if hq_mode enabled @@ -298,6 +322,9 @@ struct aspeed_video { struct video_device vdev; struct mutex video_lock; /* v4l2 and videobuf2 lock */ + struct regmap *scu; + struct regmap *gfx; + u32 version; u32 jpeg_mode; u32 comp_size_read; @@ -316,6 +343,7 @@ struct aspeed_video { bool yuv420; enum aspeed_video_format format; bool hq_mode; + enum aspeed_video_input input; unsigned int frame_rate; unsigned int jpeg_quality; unsigned int jpeg_hq_quality; @@ -331,21 +359,25 @@ struct aspeed_video { #define to_aspeed_video(x) container_of((x), struct aspeed_video, v4l2_dev) struct aspeed_video_config { + u32 version; u32 jpeg_mode; u32 comp_size_read; }; static const struct aspeed_video_config ast2400_config = { + .version = 4, .jpeg_mode = AST2400_VE_SEQ_CTRL_JPEG_MODE, .comp_size_read = AST2400_VE_COMP_SIZE_READ_BACK, }; static const struct aspeed_video_config ast2500_config = { + .version = 5, .jpeg_mode = AST2500_VE_SEQ_CTRL_JPEG_MODE, .comp_size_read = AST2400_VE_COMP_SIZE_READ_BACK, }; static const struct aspeed_video_config ast2600_config = { + .version = 6, .jpeg_mode = AST2500_VE_SEQ_CTRL_JPEG_MODE, .comp_size_read = AST2600_VE_COMP_SIZE_READ_BACK, }; @@ -485,6 +517,7 @@ static const struct v4l2_dv_timings_cap aspeed_video_timings_cap = { static const char * const format_str[] = {"Standard JPEG", "Aspeed JPEG"}; +static const char * const input_str[] = {"HOST VGA", "BMC GFX"}; static unsigned int debug; @@ -609,6 +642,14 @@ static int aspeed_video_start_frame(struct aspeed_video *video) aspeed_video_free_buf(video, &video->bcd); } + if (video->input == VIDEO_INPUT_GFX) { + u32 val; + + // update input buffer address as gfx's + regmap_read(video->gfx, GFX_DISPLAY_ADDR, &val); + aspeed_video_write(video, VE_TGS_0, val); + } + spin_lock_irqsave(&video->lock, flags); buf = list_first_entry_or_null(&video->buffers, struct aspeed_video_buffer, link); @@ -1026,9 +1067,23 @@ static void aspeed_video_get_timings(struct aspeed_video *v, } } +static void aspeed_video_get_resolution_gfx(struct aspeed_video *video, + struct v4l2_bt_timings *det) +{ + u32 h_val, v_val; + + regmap_read(video->gfx, GFX_H_DISPLAY, &h_val); + regmap_read(video->gfx, GFX_V_DISPLAY, &v_val); + + det->width = FIELD_GET(GFX_H_DISPLAY_DE, h_val) + 1; + det->height = FIELD_GET(GFX_V_DISPLAY_DE, v_val) + 1; + video->v4l2_input_status = 0; +} + #define res_check(v) test_and_clear_bit(VIDEO_MODE_DETECT_DONE, &(v)->flags) -static void aspeed_video_get_resolution(struct aspeed_video *video) +static void aspeed_video_get_resolution_vga(struct aspeed_video *video, + struct v4l2_bt_timings *det) { bool invalid_resolution = true; int rc; @@ -1036,7 +1091,6 @@ static void aspeed_video_get_resolution(struct aspeed_video *video) u32 mds; u32 src_lr_edge; u32 src_tb_edge; - struct v4l2_bt_timings *det = &video->detected_timings; det->width = MIN_WIDTH; det->height = MIN_HEIGHT; @@ -1113,14 +1167,20 @@ static void aspeed_video_get_resolution(struct aspeed_video *video) aspeed_video_get_timings(video, det); - /* - * Enable mode-detect watchdog, resolution-change watchdog and - * automatic compression after frame capture. - */ + /* Enable mode-detect watchdog, resolution-change watchdog */ aspeed_video_update(video, VE_INTERRUPT_CTRL, 0, VE_INTERRUPT_MODE_DETECT_WD); - aspeed_video_update(video, VE_SEQ_CTRL, 0, - VE_SEQ_CTRL_AUTO_COMP | VE_SEQ_CTRL_EN_WATCHDOG); + aspeed_video_update(video, VE_SEQ_CTRL, 0, VE_SEQ_CTRL_EN_WATCHDOG); +} + +static void aspeed_video_get_resolution(struct aspeed_video *video) +{ + struct v4l2_bt_timings *det = &video->detected_timings; + + if (video->input == VIDEO_INPUT_GFX) + aspeed_video_get_resolution_gfx(video, det); + else + aspeed_video_get_resolution_vga(video, det); v4l2_dbg(1, debug, &video->v4l2_dev, "Got resolution: %dx%d\n", det->width, det->height); @@ -1156,7 +1216,7 @@ static void aspeed_video_set_resolution(struct aspeed_video *video) aspeed_video_write(video, VE_SRC_SCANLINE_OFFSET, act->width * 4); /* Don't use direct mode below 1024 x 768 (irqs don't fire) */ - if (size < DIRECT_FETCH_THRESHOLD) { + if (video->input == VIDEO_INPUT_VGA && size < DIRECT_FETCH_THRESHOLD) { v4l2_dbg(1, debug, &video->v4l2_dev, "Capture: Sync Mode\n"); aspeed_video_write(video, VE_TGS_0, FIELD_PREP(VE_TGS_FIRST, @@ -1171,10 +1231,20 @@ static void aspeed_video_set_resolution(struct aspeed_video *video) VE_CTRL_INT_DE | VE_CTRL_DIRECT_FETCH, VE_CTRL_INT_DE); } else { + u32 ctrl, val, bpp; + v4l2_dbg(1, debug, &video->v4l2_dev, "Capture: Direct Mode\n"); + ctrl = VE_CTRL_DIRECT_FETCH; + if (video->input == VIDEO_INPUT_GFX) { + regmap_read(video->gfx, GFX_CTRL, &val); + bpp = FIELD_GET(GFX_CTRL_FMT, val) ? 32 : 16; + if (bpp == 16) + ctrl |= VE_CTRL_INT_DE; + aspeed_video_write(video, VE_TGS_1, act->width * (bpp >> 3)); + } aspeed_video_update(video, VE_CTRL, VE_CTRL_INT_DE | VE_CTRL_DIRECT_FETCH, - VE_CTRL_DIRECT_FETCH); + ctrl); } size *= 4; @@ -1207,6 +1277,22 @@ err_mem: aspeed_video_free_buf(video, &video->srcs[0]); } +/* + * Update relative parameters when timing changed. + * + * @video: the struct of aspeed_video + * @timings: the new timings + */ +static void aspeed_video_update_timings(struct aspeed_video *video, struct v4l2_bt_timings *timings) +{ + video->active_timings = *timings; + aspeed_video_set_resolution(video); + + video->pix_fmt.width = timings->width; + video->pix_fmt.height = timings->height; + video->pix_fmt.sizeimage = video->max_compressed_size; +} + static void aspeed_video_update_regs(struct aspeed_video *video) { u8 jpeg_hq_quality = clamp((int)video->jpeg_hq_quality - 1, 0, @@ -1219,6 +1305,8 @@ static void aspeed_video_update_regs(struct aspeed_video *video) u32 ctrl = 0; u32 seq_ctrl = 0; + v4l2_dbg(1, debug, &video->v4l2_dev, "input(%s)\n", + input_str[video->input]); v4l2_dbg(1, debug, &video->v4l2_dev, "framerate(%d)\n", video->frame_rate); v4l2_dbg(1, debug, &video->v4l2_dev, "jpeg format(%s) subsample(%s)\n", @@ -1234,6 +1322,9 @@ static void aspeed_video_update_regs(struct aspeed_video *video) else aspeed_video_update(video, VE_BCD_CTRL, VE_BCD_CTRL_EN_BCD, 0); + if (video->input == VIDEO_INPUT_VGA) + ctrl |= VE_CTRL_AUTO_OR_CURSOR; + if (video->frame_rate) ctrl |= FIELD_PREP(VE_CTRL_FRC, video->frame_rate); @@ -1252,7 +1343,9 @@ static void aspeed_video_update_regs(struct aspeed_video *video) aspeed_video_update(video, VE_SEQ_CTRL, video->jpeg_mode | VE_SEQ_CTRL_YUV420, seq_ctrl); - aspeed_video_update(video, VE_CTRL, VE_CTRL_FRC, ctrl); + aspeed_video_update(video, VE_CTRL, + VE_CTRL_FRC | VE_CTRL_AUTO_OR_CURSOR | + VE_CTRL_SOURCE, ctrl); aspeed_video_update(video, VE_COMP_CTRL, VE_COMP_CTRL_DCT_LUM | VE_COMP_CTRL_DCT_CHR | VE_COMP_CTRL_EN_HQ | VE_COMP_CTRL_HQ_DCT_LUM | @@ -1280,6 +1373,7 @@ static void aspeed_video_init_regs(struct aspeed_video *video) aspeed_video_write(video, VE_JPEG_ADDR, video->jpeg.dma); /* Set control registers */ + aspeed_video_write(video, VE_SEQ_CTRL, VE_SEQ_CTRL_AUTO_COMP); aspeed_video_write(video, VE_CTRL, ctrl); aspeed_video_write(video, VE_COMP_CTRL, VE_COMP_CTRL_RSVD); @@ -1311,12 +1405,7 @@ static void aspeed_video_start(struct aspeed_video *video) aspeed_video_get_resolution(video); /* Set timings since the device is being opened for the first time */ - video->active_timings = video->detected_timings; - aspeed_video_set_resolution(video); - - video->pix_fmt.width = video->active_timings.width; - video->pix_fmt.height = video->active_timings.height; - video->pix_fmt.sizeimage = video->max_compressed_size; + aspeed_video_update_timings(video, &video->detected_timings); } static void aspeed_video_stop(struct aspeed_video *video) @@ -1401,10 +1490,10 @@ static int aspeed_video_enum_input(struct file *file, void *fh, { struct aspeed_video *video = video_drvdata(file); - if (inp->index) + if (inp->index >= VIDEO_INPUT_MAX) return -EINVAL; - strscpy(inp->name, "Host VGA capture", sizeof(inp->name)); + sprintf(inp->name, "%s capture", input_str[inp->index]); inp->type = V4L2_INPUT_TYPE_CAMERA; inp->capabilities = V4L2_IN_CAP_DV_TIMINGS; inp->status = video->v4l2_input_status; @@ -1414,16 +1503,57 @@ static int aspeed_video_enum_input(struct file *file, void *fh, static int aspeed_video_get_input(struct file *file, void *fh, unsigned int *i) { - *i = 0; + struct aspeed_video *video = video_drvdata(file); + + *i = video->input; return 0; } static int aspeed_video_set_input(struct file *file, void *fh, unsigned int i) { - if (i) + struct aspeed_video *video = video_drvdata(file); + + if (i >= VIDEO_INPUT_MAX) return -EINVAL; + if (i == video->input) + return 0; + + if (vb2_is_busy(&video->queue)) + return -EBUSY; + + if (IS_ERR(video->scu)) { + v4l2_dbg(1, debug, &video->v4l2_dev, + "%s: scu isn't ready for input-control\n", __func__); + return -EINVAL; + } + + if (IS_ERR(video->gfx) && i == VIDEO_INPUT_GFX) { + v4l2_dbg(1, debug, &video->v4l2_dev, + "%s: gfx isn't ready for GFX input\n", __func__); + return -EINVAL; + } + + video->input = i; + + if (video->version == 6) { + /* modify dpll source per current input */ + if (video->input == VIDEO_INPUT_VGA) + regmap_update_bits(video->scu, SCU_MISC_CTRL, + SCU_DPLL_SOURCE, 0); + else + regmap_update_bits(video->scu, SCU_MISC_CTRL, + SCU_DPLL_SOURCE, SCU_DPLL_SOURCE); + } + + aspeed_video_update_regs(video); + + /* update signal status */ + aspeed_video_get_resolution(video); + if (!video->v4l2_input_status) + aspeed_video_update_timings(video, &video->detected_timings); + return 0; } @@ -1527,13 +1657,7 @@ static int aspeed_video_set_dv_timings(struct file *file, void *fh, if (vb2_is_busy(&video->queue)) return -EBUSY; - video->active_timings = timings->bt; - - aspeed_video_set_resolution(video); - - video->pix_fmt.width = timings->bt.width; - video->pix_fmt.height = timings->bt.height; - video->pix_fmt.sizeimage = video->max_compressed_size; + aspeed_video_update_timings(video, &timings->bt); timings->type = V4L2_DV_BT_656_1120; @@ -1909,6 +2033,7 @@ static int aspeed_video_debugfs_show(struct seq_file *s, void *data) val08 = aspeed_video_read(v, VE_CTRL); if (FIELD_GET(VE_CTRL_DIRECT_FETCH, val08)) { seq_printf(s, " %-20s:\tDirect fetch\n", "Mode"); + seq_printf(s, " %-20s:\t%s\n", "Input", input_str[v->input]); seq_printf(s, " %-20s:\t%s\n", "VGA bpp mode", FIELD_GET(VE_CTRL_INT_DE, val08) ? "16" : "32"); } else { @@ -2068,12 +2193,29 @@ static int aspeed_video_setup_video(struct aspeed_video *video) return 0; } +/* + * Get regmap without checking res, such as clk/reset, that could lead to + * conflict. + */ +static struct regmap *aspeed_regmap_lookup(struct device_node *np, const char *property) +{ + struct device_node *syscon_np __free(device_node) = of_parse_phandle(np, property, 0); + + if (!syscon_np) + return ERR_PTR(-ENODEV); + + return device_node_to_regmap(syscon_np); +} + static int aspeed_video_init(struct aspeed_video *video) { int irq; int rc; struct device *dev = video->dev; + video->scu = aspeed_regmap_lookup(dev->of_node, "aspeed,scu"); + video->gfx = aspeed_regmap_lookup(dev->of_node, "aspeed,gfx"); + irq = irq_of_parse_and_map(dev->of_node, 0); if (!irq) { dev_err(dev, "Unable to find IRQ\n"); @@ -2165,6 +2307,7 @@ static int aspeed_video_probe(struct platform_device *pdev) if (!config) return -ENODEV; + video->version = config->version; video->jpeg_mode = config->jpeg_mode; video->comp_size_read = config->comp_size_read; diff --git a/drivers/media/platform/cadence/cdns-csi2rx.c b/drivers/media/platform/cadence/cdns-csi2rx.c index 7f1ce95cdc3f..8c19f125da3e 100644 --- a/drivers/media/platform/cadence/cdns-csi2rx.c +++ b/drivers/media/platform/cadence/cdns-csi2rx.c @@ -5,8 +5,10 @@ * Copyright (C) 2017 Cadence Design Systems Inc. */ +#include <linux/bitfield.h> #include <linux/clk.h> #include <linux/delay.h> +#include <linux/export.h> #include <linux/io.h> #include <linux/iopoll.h> #include <linux/module.h> @@ -17,6 +19,7 @@ #include <linux/reset.h> #include <linux/slab.h> +#include <media/cadence/cdns-csi2rx.h> #include <media/v4l2-ctrls.h> #include <media/v4l2-device.h> #include <media/v4l2-fwnode.h> @@ -52,7 +55,9 @@ #define CSI2RX_STREAM_DATA_CFG_VC_SELECT(n) BIT((n) + 16) #define CSI2RX_STREAM_CFG_REG(n) (CSI2RX_STREAM_BASE(n) + 0x00c) -#define CSI2RX_STREAM_CFG_FIFO_MODE_LARGE_BUF (1 << 8) +#define CSI2RX_STREAM_CFG_FIFO_MODE_LARGE_BUF BIT(8) +#define CSI2RX_STREAM_CFG_NUM_PIXELS_MASK GENMASK(5, 4) +#define CSI2RX_STREAM_CFG_NUM_PIXELS(n) ((n) >> 1U) #define CSI2RX_LANES_MAX 4 #define CSI2RX_STREAMS_MAX 4 @@ -87,7 +92,10 @@ enum csi2rx_pads { struct csi2rx_fmt { u32 code; + /* width of a single pixel on CSI-2 bus */ u8 bpp; + /* max pixels per clock supported on output bus */ + u8 max_pixels; }; struct csi2rx_event { @@ -132,6 +140,7 @@ struct csi2rx_priv { struct reset_control *pixel_rst[CSI2RX_STREAMS_MAX]; struct phy *dphy; + u8 num_pixels[CSI2RX_STREAMS_MAX]; u8 lanes[CSI2RX_LANES_MAX]; u8 num_lanes; u8 max_lanes; @@ -149,22 +158,22 @@ struct csi2rx_priv { }; static const struct csi2rx_fmt formats[] = { - { .code = MEDIA_BUS_FMT_YUYV8_1X16, .bpp = 16, }, - { .code = MEDIA_BUS_FMT_UYVY8_1X16, .bpp = 16, }, - { .code = MEDIA_BUS_FMT_YVYU8_1X16, .bpp = 16, }, - { .code = MEDIA_BUS_FMT_VYUY8_1X16, .bpp = 16, }, - { .code = MEDIA_BUS_FMT_SBGGR8_1X8, .bpp = 8, }, - { .code = MEDIA_BUS_FMT_SGBRG8_1X8, .bpp = 8, }, - { .code = MEDIA_BUS_FMT_SGRBG8_1X8, .bpp = 8, }, - { .code = MEDIA_BUS_FMT_SRGGB8_1X8, .bpp = 8, }, - { .code = MEDIA_BUS_FMT_Y8_1X8, .bpp = 8, }, - { .code = MEDIA_BUS_FMT_SBGGR10_1X10, .bpp = 10, }, - { .code = MEDIA_BUS_FMT_SGBRG10_1X10, .bpp = 10, }, - { .code = MEDIA_BUS_FMT_SGRBG10_1X10, .bpp = 10, }, - { .code = MEDIA_BUS_FMT_SRGGB10_1X10, .bpp = 10, }, - { .code = MEDIA_BUS_FMT_RGB565_1X16, .bpp = 16, }, - { .code = MEDIA_BUS_FMT_RGB888_1X24, .bpp = 24, }, - { .code = MEDIA_BUS_FMT_BGR888_1X24, .bpp = 24, }, + { .code = MEDIA_BUS_FMT_YUYV8_1X16, .bpp = 16, .max_pixels = 2, }, + { .code = MEDIA_BUS_FMT_UYVY8_1X16, .bpp = 16, .max_pixels = 2, }, + { .code = MEDIA_BUS_FMT_YVYU8_1X16, .bpp = 16, .max_pixels = 2, }, + { .code = MEDIA_BUS_FMT_VYUY8_1X16, .bpp = 16, .max_pixels = 2, }, + { .code = MEDIA_BUS_FMT_SBGGR8_1X8, .bpp = 8, .max_pixels = 4, }, + { .code = MEDIA_BUS_FMT_SGBRG8_1X8, .bpp = 8, .max_pixels = 4, }, + { .code = MEDIA_BUS_FMT_SGRBG8_1X8, .bpp = 8, .max_pixels = 4, }, + { .code = MEDIA_BUS_FMT_SRGGB8_1X8, .bpp = 8, .max_pixels = 4, }, + { .code = MEDIA_BUS_FMT_Y8_1X8, .bpp = 8, .max_pixels = 4, }, + { .code = MEDIA_BUS_FMT_SBGGR10_1X10, .bpp = 10, .max_pixels = 2, }, + { .code = MEDIA_BUS_FMT_SGBRG10_1X10, .bpp = 10, .max_pixels = 2, }, + { .code = MEDIA_BUS_FMT_SGRBG10_1X10, .bpp = 10, .max_pixels = 2, }, + { .code = MEDIA_BUS_FMT_SRGGB10_1X10, .bpp = 10, .max_pixels = 2, }, + { .code = MEDIA_BUS_FMT_RGB565_1X16, .bpp = 16, .max_pixels = 1, }, + { .code = MEDIA_BUS_FMT_RGB888_1X24, .bpp = 24, .max_pixels = 1, }, + { .code = MEDIA_BUS_FMT_BGR888_1X24, .bpp = 24, .max_pixels = 1, }, }; static void csi2rx_configure_error_irq_mask(void __iomem *base, @@ -370,7 +379,9 @@ static int csi2rx_start(struct csi2rx_priv *csi2rx) reset_control_deassert(csi2rx->pixel_rst[i]); - writel(CSI2RX_STREAM_CFG_FIFO_MODE_LARGE_BUF, + writel(CSI2RX_STREAM_CFG_FIFO_MODE_LARGE_BUF | + FIELD_PREP(CSI2RX_STREAM_CFG_NUM_PIXELS_MASK, + csi2rx->num_pixels[i]), csi2rx->base + CSI2RX_STREAM_CFG_REG(i)); /* @@ -569,6 +580,33 @@ static int csi2rx_init_state(struct v4l2_subdev *subdev, return csi2rx_set_fmt(subdev, state, &format); } +int cdns_csi2rx_negotiate_ppc(struct v4l2_subdev *subdev, unsigned int pad, + u8 *ppc) +{ + struct csi2rx_priv *csi2rx = v4l2_subdev_to_csi2rx(subdev); + const struct csi2rx_fmt *csi_fmt; + struct v4l2_subdev_state *state; + struct v4l2_mbus_framefmt *fmt; + + if (!ppc || pad < CSI2RX_PAD_SOURCE_STREAM0 || pad >= CSI2RX_PAD_MAX) + return -EINVAL; + + state = v4l2_subdev_lock_and_get_active_state(subdev); + fmt = v4l2_subdev_state_get_format(state, pad); + csi_fmt = csi2rx_get_fmt_by_code(fmt->code); + + /* Reduce requested PPC if it is too high */ + *ppc = min(*ppc, csi_fmt->max_pixels); + + v4l2_subdev_unlock_state(state); + + csi2rx->num_pixels[pad - CSI2RX_PAD_SOURCE_STREAM0] = + CSI2RX_STREAM_CFG_NUM_PIXELS(*ppc); + + return 0; +} +EXPORT_SYMBOL_FOR_MODULES(cdns_csi2rx_negotiate_ppc, "j721e-csi2rx"); + static const struct v4l2_subdev_pad_ops csi2rx_pad_ops = { .enum_mbus_code = csi2rx_enum_mbus_code, .get_fmt = v4l2_subdev_get_fmt, @@ -595,6 +633,7 @@ static const struct v4l2_subdev_internal_ops csi2rx_internal_ops = { static const struct media_entity_operations csi2rx_media_ops = { .link_validate = v4l2_subdev_link_validate, + .get_fwnode_pad = v4l2_subdev_get_fwnode_pad_1_to_1, }; static int csi2rx_async_bound(struct v4l2_async_notifier *notifier, diff --git a/drivers/media/platform/chips-media/coda/coda-common.c b/drivers/media/platform/chips-media/coda/coda-common.c index e6e3f5ec24f6..9a57b042d9fd 100644 --- a/drivers/media/platform/chips-media/coda/coda-common.c +++ b/drivers/media/platform/chips-media/coda/coda-common.c @@ -56,6 +56,11 @@ #define fh_to_ctx(__fh) container_of(__fh, struct coda_ctx, fh) +static inline struct coda_ctx *file_to_ctx(struct file *filp) +{ + return fh_to_ctx(file_to_v4l2_fh(filp)); +} + int coda_debug; module_param(coda_debug, int, 0644); MODULE_PARM_DESC(coda_debug, "Debug level (0-2)"); @@ -422,7 +427,7 @@ out: static int coda_querycap(struct file *file, void *priv, struct v4l2_capability *cap) { - struct coda_ctx *ctx = fh_to_ctx(priv); + struct coda_ctx *ctx = file_to_ctx(file); strscpy(cap->driver, CODA_NAME, sizeof(cap->driver)); strscpy(cap->card, coda_product_name(ctx->dev->devtype->product), @@ -442,7 +447,7 @@ static int coda_enum_fmt(struct file *file, void *priv, { struct video_device *vdev = video_devdata(file); const struct coda_video_device *cvd = to_coda_video_device(vdev); - struct coda_ctx *ctx = fh_to_ctx(priv); + struct coda_ctx *ctx = file_to_ctx(file); const u32 *formats; if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) @@ -492,7 +497,7 @@ static int coda_g_fmt(struct file *file, void *priv, struct v4l2_format *f) { struct coda_q_data *q_data; - struct coda_ctx *ctx = fh_to_ctx(priv); + struct coda_ctx *ctx = file_to_ctx(file); q_data = get_q_data(ctx, f->type); if (!q_data) @@ -653,7 +658,7 @@ static int coda_try_fmt(struct coda_ctx *ctx, const struct coda_codec *codec, static int coda_try_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *f) { - struct coda_ctx *ctx = fh_to_ctx(priv); + struct coda_ctx *ctx = file_to_ctx(file); const struct coda_q_data *q_data_src; const struct coda_codec *codec; struct vb2_queue *src_vq; @@ -759,7 +764,7 @@ static void coda_set_default_colorspace(struct v4l2_pix_format *fmt) static int coda_try_fmt_vid_out(struct file *file, void *priv, struct v4l2_format *f) { - struct coda_ctx *ctx = fh_to_ctx(priv); + struct coda_ctx *ctx = file_to_ctx(file); struct coda_dev *dev = ctx->dev; const struct coda_q_data *q_data_dst; const struct coda_codec *codec; @@ -853,7 +858,7 @@ static int coda_s_fmt(struct coda_ctx *ctx, struct v4l2_format *f, static int coda_s_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *f) { - struct coda_ctx *ctx = fh_to_ctx(priv); + struct coda_ctx *ctx = file_to_ctx(file); struct coda_q_data *q_data_src; const struct coda_codec *codec; struct v4l2_rect r; @@ -905,7 +910,7 @@ static int coda_s_fmt_vid_cap(struct file *file, void *priv, static int coda_s_fmt_vid_out(struct file *file, void *priv, struct v4l2_format *f) { - struct coda_ctx *ctx = fh_to_ctx(priv); + struct coda_ctx *ctx = file_to_ctx(file); const struct coda_codec *codec; struct v4l2_format f_cap; struct vb2_queue *dst_vq; @@ -961,7 +966,7 @@ static int coda_s_fmt_vid_out(struct file *file, void *priv, static int coda_reqbufs(struct file *file, void *priv, struct v4l2_requestbuffers *rb) { - struct coda_ctx *ctx = fh_to_ctx(priv); + struct coda_ctx *ctx = file_to_ctx(file); int ret; ret = v4l2_m2m_reqbufs(file, ctx->fh.m2m_ctx, rb); @@ -981,7 +986,7 @@ static int coda_reqbufs(struct file *file, void *priv, static int coda_qbuf(struct file *file, void *priv, struct v4l2_buffer *buf) { - struct coda_ctx *ctx = fh_to_ctx(priv); + struct coda_ctx *ctx = file_to_ctx(file); if (ctx->inst_type == CODA_INST_DECODER && buf->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) @@ -992,7 +997,7 @@ static int coda_qbuf(struct file *file, void *priv, static int coda_dqbuf(struct file *file, void *priv, struct v4l2_buffer *buf) { - struct coda_ctx *ctx = fh_to_ctx(priv); + struct coda_ctx *ctx = file_to_ctx(file); int ret; ret = v4l2_m2m_dqbuf(file, ctx->fh.m2m_ctx, buf); @@ -1020,7 +1025,7 @@ void coda_m2m_buf_done(struct coda_ctx *ctx, struct vb2_v4l2_buffer *buf, static int coda_g_selection(struct file *file, void *fh, struct v4l2_selection *s) { - struct coda_ctx *ctx = fh_to_ctx(fh); + struct coda_ctx *ctx = file_to_ctx(file); struct coda_q_data *q_data; struct v4l2_rect r, *rsel; @@ -1066,7 +1071,7 @@ static int coda_g_selection(struct file *file, void *fh, static int coda_s_selection(struct file *file, void *fh, struct v4l2_selection *s) { - struct coda_ctx *ctx = fh_to_ctx(fh); + struct coda_ctx *ctx = file_to_ctx(file); struct coda_q_data *q_data; switch (s->target) { @@ -1121,7 +1126,7 @@ static void coda_wake_up_capture_queue(struct coda_ctx *ctx) static int coda_encoder_cmd(struct file *file, void *fh, struct v4l2_encoder_cmd *ec) { - struct coda_ctx *ctx = fh_to_ctx(fh); + struct coda_ctx *ctx = file_to_ctx(file); struct vb2_v4l2_buffer *buf; int ret; @@ -1202,7 +1207,7 @@ static bool coda_mark_last_dst_buf(struct coda_ctx *ctx) static int coda_decoder_cmd(struct file *file, void *fh, struct v4l2_decoder_cmd *dc) { - struct coda_ctx *ctx = fh_to_ctx(fh); + struct coda_ctx *ctx = file_to_ctx(file); struct coda_dev *dev = ctx->dev; struct vb2_v4l2_buffer *buf; struct vb2_queue *dst_vq; @@ -1281,7 +1286,7 @@ static int coda_decoder_cmd(struct file *file, void *fh, static int coda_enum_framesizes(struct file *file, void *fh, struct v4l2_frmsizeenum *fsize) { - struct coda_ctx *ctx = fh_to_ctx(fh); + struct coda_ctx *ctx = file_to_ctx(file); struct coda_q_data *q_data_dst; const struct coda_codec *codec; @@ -1314,7 +1319,7 @@ static int coda_enum_framesizes(struct file *file, void *fh, static int coda_enum_frameintervals(struct file *file, void *fh, struct v4l2_frmivalenum *f) { - struct coda_ctx *ctx = fh_to_ctx(fh); + struct coda_ctx *ctx = file_to_ctx(file); struct coda_q_data *q_data; const struct coda_codec *codec; @@ -1353,7 +1358,7 @@ static int coda_enum_frameintervals(struct file *file, void *fh, static int coda_g_parm(struct file *file, void *fh, struct v4l2_streamparm *a) { - struct coda_ctx *ctx = fh_to_ctx(fh); + struct coda_ctx *ctx = file_to_ctx(file); struct v4l2_fract *tpf; if (a->type != V4L2_BUF_TYPE_VIDEO_OUTPUT) @@ -1436,7 +1441,7 @@ static uint32_t coda_timeperframe_to_frate(struct v4l2_fract *timeperframe) static int coda_s_parm(struct file *file, void *fh, struct v4l2_streamparm *a) { - struct coda_ctx *ctx = fh_to_ctx(fh); + struct coda_ctx *ctx = file_to_ctx(file); struct v4l2_fract *tpf; if (a->type != V4L2_BUF_TYPE_VIDEO_OUTPUT) @@ -2637,8 +2642,7 @@ static int coda_open(struct file *file) if (ctx->ops->seq_end_work) INIT_WORK(&ctx->seq_end_work, ctx->ops->seq_end_work); v4l2_fh_init(&ctx->fh, video_devdata(file)); - file->private_data = &ctx->fh; - v4l2_fh_add(&ctx->fh); + v4l2_fh_add(&ctx->fh, file); ctx->dev = dev; ctx->idx = idx; @@ -2721,7 +2725,7 @@ err_clk_ahb: err_clk_enable: pm_runtime_put_sync(dev->dev); err_pm_get: - v4l2_fh_del(&ctx->fh); + v4l2_fh_del(&ctx->fh, file); v4l2_fh_exit(&ctx->fh); err_coda_name_init: ida_free(&dev->ida, ctx->idx); @@ -2733,7 +2737,7 @@ err_coda_max: static int coda_release(struct file *file) { struct coda_dev *dev = video_drvdata(file); - struct coda_ctx *ctx = fh_to_ctx(file->private_data); + struct coda_ctx *ctx = file_to_ctx(file); coda_dbg(1, ctx, "release instance (%p)\n", ctx); @@ -2759,7 +2763,7 @@ static int coda_release(struct file *file) clk_disable_unprepare(dev->clk_ahb); clk_disable_unprepare(dev->clk_per); pm_runtime_put_sync(dev->dev); - v4l2_fh_del(&ctx->fh); + v4l2_fh_del(&ctx->fh, file); v4l2_fh_exit(&ctx->fh); ida_free(&dev->ida, ctx->idx); if (ctx->ops->release) diff --git a/drivers/media/platform/chips-media/wave5/wave5-helper.c b/drivers/media/platform/chips-media/wave5/wave5-helper.c index 2c9d8cbca6e4..f03ad9c0de22 100644 --- a/drivers/media/platform/chips-media/wave5/wave5-helper.c +++ b/drivers/media/platform/chips-media/wave5/wave5-helper.c @@ -27,7 +27,7 @@ const char *state_to_str(enum vpu_instance_state state) } } -void wave5_cleanup_instance(struct vpu_instance *inst) +void wave5_cleanup_instance(struct vpu_instance *inst, struct file *filp) { int i; @@ -46,7 +46,7 @@ void wave5_cleanup_instance(struct vpu_instance *inst) wave5_vdi_free_dma_memory(inst->dev, &inst->bitstream_vbuf); v4l2_ctrl_handler_free(&inst->v4l2_ctrl_hdl); if (inst->v4l2_fh.vdev) { - v4l2_fh_del(&inst->v4l2_fh); + v4l2_fh_del(&inst->v4l2_fh, filp); v4l2_fh_exit(&inst->v4l2_fh); } list_del_init(&inst->list); @@ -59,7 +59,7 @@ int wave5_vpu_release_device(struct file *filp, int (*close_func)(struct vpu_instance *inst, u32 *fail_res), char *name) { - struct vpu_instance *inst = wave5_to_vpu_inst(filp->private_data); + struct vpu_instance *inst = file_to_vpu_inst(filp); int ret = 0; v4l2_m2m_ctx_release(inst->v4l2_fh.m2m_ctx); @@ -78,7 +78,7 @@ int wave5_vpu_release_device(struct file *filp, } } - wave5_cleanup_instance(inst); + wave5_cleanup_instance(inst, filp); return ret; } @@ -142,7 +142,7 @@ int wave5_vpu_subscribe_event(struct v4l2_fh *fh, const struct v4l2_event_subscr int wave5_vpu_g_fmt_out(struct file *file, void *fh, struct v4l2_format *f) { - struct vpu_instance *inst = wave5_to_vpu_inst(fh); + struct vpu_instance *inst = file_to_vpu_inst(file); int i; f->fmt.pix_mp.width = inst->src_fmt.width; diff --git a/drivers/media/platform/chips-media/wave5/wave5-helper.h b/drivers/media/platform/chips-media/wave5/wave5-helper.h index 9937fce553fc..976a402e426f 100644 --- a/drivers/media/platform/chips-media/wave5/wave5-helper.h +++ b/drivers/media/platform/chips-media/wave5/wave5-helper.h @@ -14,7 +14,7 @@ #define MAX_FMTS 12 const char *state_to_str(enum vpu_instance_state state); -void wave5_cleanup_instance(struct vpu_instance *inst); +void wave5_cleanup_instance(struct vpu_instance *inst, struct file *filp); int wave5_vpu_release_device(struct file *filp, int (*close_func)(struct vpu_instance *inst, u32 *fail_res), char *name); diff --git a/drivers/media/platform/chips-media/wave5/wave5-vpu-dec.c b/drivers/media/platform/chips-media/wave5/wave5-vpu-dec.c index a9ce032cc5a2..e3038c18ca36 100644 --- a/drivers/media/platform/chips-media/wave5/wave5-vpu-dec.c +++ b/drivers/media/platform/chips-media/wave5/wave5-vpu-dec.c @@ -505,7 +505,7 @@ static int wave5_vpu_dec_enum_fmt_cap(struct file *file, void *fh, struct v4l2_f static int wave5_vpu_dec_try_fmt_cap(struct file *file, void *fh, struct v4l2_format *f) { - struct vpu_instance *inst = wave5_to_vpu_inst(fh); + struct vpu_instance *inst = file_to_vpu_inst(file); struct dec_info *p_dec_info = &inst->codec_info->dec_info; const struct v4l2_frmsize_stepwise *frmsize; const struct vpu_format *vpu_fmt; @@ -546,7 +546,7 @@ static int wave5_vpu_dec_try_fmt_cap(struct file *file, void *fh, struct v4l2_fo static int wave5_vpu_dec_s_fmt_cap(struct file *file, void *fh, struct v4l2_format *f) { - struct vpu_instance *inst = wave5_to_vpu_inst(fh); + struct vpu_instance *inst = file_to_vpu_inst(file); int i, ret; dev_dbg(inst->dev->dev, @@ -605,7 +605,7 @@ static int wave5_vpu_dec_s_fmt_cap(struct file *file, void *fh, struct v4l2_form static int wave5_vpu_dec_g_fmt_cap(struct file *file, void *fh, struct v4l2_format *f) { - struct vpu_instance *inst = wave5_to_vpu_inst(fh); + struct vpu_instance *inst = file_to_vpu_inst(file); int i; f->fmt.pix_mp.width = inst->dst_fmt.width; @@ -629,7 +629,7 @@ static int wave5_vpu_dec_g_fmt_cap(struct file *file, void *fh, struct v4l2_form static int wave5_vpu_dec_enum_fmt_out(struct file *file, void *fh, struct v4l2_fmtdesc *f) { - struct vpu_instance *inst = wave5_to_vpu_inst(fh); + struct vpu_instance *inst = file_to_vpu_inst(file); const struct vpu_format *vpu_fmt; dev_dbg(inst->dev->dev, "%s: index: %u\n", __func__, f->index); @@ -646,7 +646,7 @@ static int wave5_vpu_dec_enum_fmt_out(struct file *file, void *fh, struct v4l2_f static int wave5_vpu_dec_try_fmt_out(struct file *file, void *fh, struct v4l2_format *f) { - struct vpu_instance *inst = wave5_to_vpu_inst(fh); + struct vpu_instance *inst = file_to_vpu_inst(file); const struct v4l2_frmsize_stepwise *frmsize; const struct vpu_format *vpu_fmt; int width, height; @@ -677,7 +677,7 @@ static int wave5_vpu_dec_try_fmt_out(struct file *file, void *fh, struct v4l2_fo static int wave5_vpu_dec_s_fmt_out(struct file *file, void *fh, struct v4l2_format *f) { - struct vpu_instance *inst = wave5_to_vpu_inst(fh); + struct vpu_instance *inst = file_to_vpu_inst(file); const struct vpu_format *vpu_fmt; int i, ret; @@ -726,7 +726,7 @@ static int wave5_vpu_dec_s_fmt_out(struct file *file, void *fh, struct v4l2_form static int wave5_vpu_dec_g_selection(struct file *file, void *fh, struct v4l2_selection *s) { - struct vpu_instance *inst = wave5_to_vpu_inst(fh); + struct vpu_instance *inst = file_to_vpu_inst(file); dev_dbg(inst->dev->dev, "%s: type: %u | target: %u\n", __func__, s->type, s->target); @@ -760,7 +760,7 @@ static int wave5_vpu_dec_g_selection(struct file *file, void *fh, struct v4l2_se static int wave5_vpu_dec_s_selection(struct file *file, void *fh, struct v4l2_selection *s) { - struct vpu_instance *inst = wave5_to_vpu_inst(fh); + struct vpu_instance *inst = file_to_vpu_inst(file); if (s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) return -EINVAL; @@ -871,7 +871,7 @@ unlock_and_return: static int wave5_vpu_dec_decoder_cmd(struct file *file, void *fh, struct v4l2_decoder_cmd *dc) { - struct vpu_instance *inst = wave5_to_vpu_inst(fh); + struct vpu_instance *inst = file_to_vpu_inst(file); struct v4l2_m2m_ctx *m2m_ctx = inst->v4l2_fh.m2m_ctx; int ret; @@ -1757,8 +1757,7 @@ static int wave5_vpu_open_dec(struct file *filp) return -ENOMEM; v4l2_fh_init(&inst->v4l2_fh, vdev); - filp->private_data = &inst->v4l2_fh; - v4l2_fh_add(&inst->v4l2_fh); + v4l2_fh_add(&inst->v4l2_fh, filp); INIT_LIST_HEAD(&inst->list); @@ -1836,7 +1835,7 @@ static int wave5_vpu_open_dec(struct file *filp) return 0; cleanup_inst: - wave5_cleanup_instance(inst); + wave5_cleanup_instance(inst, filp); return ret; } diff --git a/drivers/media/platform/chips-media/wave5/wave5-vpu-enc.c b/drivers/media/platform/chips-media/wave5/wave5-vpu-enc.c index 35913a7de834..9bfaa9fb3ceb 100644 --- a/drivers/media/platform/chips-media/wave5/wave5-vpu-enc.c +++ b/drivers/media/platform/chips-media/wave5/wave5-vpu-enc.c @@ -360,7 +360,7 @@ static int wave5_vpu_enc_enum_framesizes(struct file *f, void *fh, struct v4l2_f static int wave5_vpu_enc_enum_fmt_cap(struct file *file, void *fh, struct v4l2_fmtdesc *f) { - struct vpu_instance *inst = wave5_to_vpu_inst(fh); + struct vpu_instance *inst = file_to_vpu_inst(file); const struct vpu_format *vpu_fmt; dev_dbg(inst->dev->dev, "%s: index: %u\n", __func__, f->index); @@ -377,7 +377,7 @@ static int wave5_vpu_enc_enum_fmt_cap(struct file *file, void *fh, struct v4l2_f static int wave5_vpu_enc_try_fmt_cap(struct file *file, void *fh, struct v4l2_format *f) { - struct vpu_instance *inst = wave5_to_vpu_inst(fh); + struct vpu_instance *inst = file_to_vpu_inst(file); const struct v4l2_frmsize_stepwise *frmsize; const struct vpu_format *vpu_fmt; int width, height; @@ -411,7 +411,7 @@ static int wave5_vpu_enc_try_fmt_cap(struct file *file, void *fh, struct v4l2_fo static int wave5_vpu_enc_s_fmt_cap(struct file *file, void *fh, struct v4l2_format *f) { - struct vpu_instance *inst = wave5_to_vpu_inst(fh); + struct vpu_instance *inst = file_to_vpu_inst(file); int i, ret; dev_dbg(inst->dev->dev, "%s: fourcc: %u width: %u height: %u num_planes: %u field: %u\n", @@ -445,7 +445,7 @@ static int wave5_vpu_enc_s_fmt_cap(struct file *file, void *fh, struct v4l2_form static int wave5_vpu_enc_g_fmt_cap(struct file *file, void *fh, struct v4l2_format *f) { - struct vpu_instance *inst = wave5_to_vpu_inst(fh); + struct vpu_instance *inst = file_to_vpu_inst(file); int i; f->fmt.pix_mp.width = inst->dst_fmt.width; @@ -469,7 +469,7 @@ static int wave5_vpu_enc_g_fmt_cap(struct file *file, void *fh, struct v4l2_form static int wave5_vpu_enc_enum_fmt_out(struct file *file, void *fh, struct v4l2_fmtdesc *f) { - struct vpu_instance *inst = wave5_to_vpu_inst(fh); + struct vpu_instance *inst = file_to_vpu_inst(file); const struct vpu_format *vpu_fmt; dev_dbg(inst->dev->dev, "%s: index: %u\n", __func__, f->index); @@ -486,7 +486,7 @@ static int wave5_vpu_enc_enum_fmt_out(struct file *file, void *fh, struct v4l2_f static int wave5_vpu_enc_try_fmt_out(struct file *file, void *fh, struct v4l2_format *f) { - struct vpu_instance *inst = wave5_to_vpu_inst(fh); + struct vpu_instance *inst = file_to_vpu_inst(file); const struct v4l2_frmsize_stepwise *frmsize; const struct vpu_format *vpu_fmt; int width, height; @@ -515,7 +515,7 @@ static int wave5_vpu_enc_try_fmt_out(struct file *file, void *fh, struct v4l2_fo static int wave5_vpu_enc_s_fmt_out(struct file *file, void *fh, struct v4l2_format *f) { - struct vpu_instance *inst = wave5_to_vpu_inst(fh); + struct vpu_instance *inst = file_to_vpu_inst(file); const struct vpu_format *vpu_fmt; const struct v4l2_format_info *info; int i, ret; @@ -543,7 +543,7 @@ static int wave5_vpu_enc_s_fmt_out(struct file *file, void *fh, struct v4l2_form if (!info) return -EINVAL; - inst->cbcr_interleave = (info->comp_planes == 2) ? true : false; + inst->cbcr_interleave = info->comp_planes == 2; switch (inst->src_fmt.pixelformat) { case V4L2_PIX_FMT_NV21: @@ -576,7 +576,7 @@ static int wave5_vpu_enc_s_fmt_out(struct file *file, void *fh, struct v4l2_form static int wave5_vpu_enc_g_selection(struct file *file, void *fh, struct v4l2_selection *s) { - struct vpu_instance *inst = wave5_to_vpu_inst(fh); + struct vpu_instance *inst = file_to_vpu_inst(file); dev_dbg(inst->dev->dev, "%s: type: %u | target: %u\n", __func__, s->type, s->target); @@ -605,7 +605,7 @@ static int wave5_vpu_enc_g_selection(struct file *file, void *fh, struct v4l2_se static int wave5_vpu_enc_s_selection(struct file *file, void *fh, struct v4l2_selection *s) { - struct vpu_instance *inst = wave5_to_vpu_inst(fh); + struct vpu_instance *inst = file_to_vpu_inst(file); if (s->type != V4L2_BUF_TYPE_VIDEO_OUTPUT) return -EINVAL; @@ -628,7 +628,7 @@ static int wave5_vpu_enc_s_selection(struct file *file, void *fh, struct v4l2_se static int wave5_vpu_enc_encoder_cmd(struct file *file, void *fh, struct v4l2_encoder_cmd *ec) { - struct vpu_instance *inst = wave5_to_vpu_inst(fh); + struct vpu_instance *inst = file_to_vpu_inst(file); struct v4l2_m2m_ctx *m2m_ctx = inst->v4l2_fh.m2m_ctx; int ret; @@ -661,7 +661,7 @@ static int wave5_vpu_enc_encoder_cmd(struct file *file, void *fh, struct v4l2_en static int wave5_vpu_enc_g_parm(struct file *file, void *fh, struct v4l2_streamparm *a) { - struct vpu_instance *inst = wave5_to_vpu_inst(fh); + struct vpu_instance *inst = file_to_vpu_inst(file); dev_dbg(inst->dev->dev, "%s: type: %u\n", __func__, a->type); @@ -681,7 +681,7 @@ static int wave5_vpu_enc_g_parm(struct file *file, void *fh, struct v4l2_streamp static int wave5_vpu_enc_s_parm(struct file *file, void *fh, struct v4l2_streamparm *a) { - struct vpu_instance *inst = wave5_to_vpu_inst(fh); + struct vpu_instance *inst = file_to_vpu_inst(file); dev_dbg(inst->dev->dev, "%s: type: %u\n", __func__, a->type); @@ -1582,8 +1582,7 @@ static int wave5_vpu_open_enc(struct file *filp) return -ENOMEM; v4l2_fh_init(&inst->v4l2_fh, vdev); - filp->private_data = &inst->v4l2_fh; - v4l2_fh_add(&inst->v4l2_fh); + v4l2_fh_add(&inst->v4l2_fh, filp); INIT_LIST_HEAD(&inst->list); @@ -1779,7 +1778,7 @@ static int wave5_vpu_open_enc(struct file *filp) return 0; cleanup_inst: - wave5_cleanup_instance(inst); + wave5_cleanup_instance(inst, filp); return ret; } diff --git a/drivers/media/platform/chips-media/wave5/wave5-vpu.h b/drivers/media/platform/chips-media/wave5/wave5-vpu.h index 3847332551fc..5943bdaa9c4c 100644 --- a/drivers/media/platform/chips-media/wave5/wave5-vpu.h +++ b/drivers/media/platform/chips-media/wave5/wave5-vpu.h @@ -46,6 +46,11 @@ static inline struct vpu_instance *wave5_to_vpu_inst(struct v4l2_fh *vfh) return container_of(vfh, struct vpu_instance, v4l2_fh); } +static inline struct vpu_instance *file_to_vpu_inst(struct file *filp) +{ + return wave5_to_vpu_inst(file_to_v4l2_fh(filp)); +} + static inline struct vpu_instance *wave5_ctrl_to_vpu_inst(struct v4l2_ctrl *vctrl) { return container_of(vctrl->handler, struct vpu_instance, v4l2_ctrl_hdl); diff --git a/drivers/media/platform/imagination/e5010-jpeg-enc.c b/drivers/media/platform/imagination/e5010-jpeg-enc.c index ae868d9f73e1..c4e0097cb8b7 100644 --- a/drivers/media/platform/imagination/e5010-jpeg-enc.c +++ b/drivers/media/platform/imagination/e5010-jpeg-enc.c @@ -253,7 +253,7 @@ static int e5010_enum_fmt(struct file *file, void *priv, struct v4l2_fmtdesc *f) { int i, index = 0; struct e5010_fmt *fmt = NULL; - struct e5010_context *ctx = file->private_data; + struct e5010_context *ctx = to_e5010_context(file); if (!V4L2_TYPE_IS_MULTIPLANAR(f->type)) { v4l2_err(&ctx->e5010->v4l2_dev, "ENUMFMT with Invalid type: %d\n", f->type); @@ -279,7 +279,7 @@ static int e5010_enum_fmt(struct file *file, void *priv, struct v4l2_fmtdesc *f) static int e5010_g_fmt(struct file *file, void *priv, struct v4l2_format *f) { - struct e5010_context *ctx = file->private_data; + struct e5010_context *ctx = to_e5010_context(file); struct e5010_q_data *queue; int i; struct v4l2_pix_format_mplane *pix_mp = &f->fmt.pix_mp; @@ -380,14 +380,14 @@ static int e5010_jpeg_try_fmt(struct v4l2_format *f, struct e5010_context *ctx) static int e5010_try_fmt(struct file *file, void *priv, struct v4l2_format *f) { - struct e5010_context *ctx = file->private_data; + struct e5010_context *ctx = to_e5010_context(file); return e5010_jpeg_try_fmt(f, ctx); } static int e5010_s_fmt(struct file *file, void *priv, struct v4l2_format *f) { - struct e5010_context *ctx = file->private_data; + struct e5010_context *ctx = to_e5010_context(file); struct vb2_queue *vq; int ret = 0, i = 0; struct v4l2_pix_format_mplane *pix_mp = &f->fmt.pix_mp; @@ -462,7 +462,7 @@ static int e5010_enum_framesizes(struct file *file, void *priv, struct v4l2_frms static int e5010_g_selection(struct file *file, void *fh, struct v4l2_selection *s) { - struct e5010_context *ctx = file->private_data; + struct e5010_context *ctx = to_e5010_context(file); struct e5010_q_data *queue; if (s->type != V4L2_BUF_TYPE_VIDEO_OUTPUT) @@ -490,7 +490,7 @@ static int e5010_g_selection(struct file *file, void *fh, struct v4l2_selection static int e5010_s_selection(struct file *file, void *fh, struct v4l2_selection *s) { - struct e5010_context *ctx = file->private_data; + struct e5010_context *ctx = to_e5010_context(file); struct e5010_q_data *queue; struct vb2_queue *vq; struct v4l2_rect base_rect; @@ -742,8 +742,7 @@ static int e5010_open(struct file *file) } v4l2_fh_init(&ctx->fh, vdev); - file->private_data = ctx; - v4l2_fh_add(&ctx->fh); + v4l2_fh_add(&ctx->fh, file); ctx->e5010 = e5010; ctx->fh.m2m_ctx = v4l2_m2m_ctx_init(e5010->m2m_dev, ctx, queue_init); @@ -770,7 +769,7 @@ static int e5010_open(struct file *file) err_ctrls_setup: v4l2_m2m_ctx_release(ctx->fh.m2m_ctx); exit: - v4l2_fh_del(&ctx->fh); + v4l2_fh_del(&ctx->fh, file); v4l2_fh_exit(&ctx->fh); mutex_unlock(&e5010->mutex); free: @@ -781,13 +780,13 @@ free: static int e5010_release(struct file *file) { struct e5010_dev *e5010 = video_drvdata(file); - struct e5010_context *ctx = file->private_data; + struct e5010_context *ctx = to_e5010_context(file); dprintk(e5010, 1, "Releasing instance: 0x%p, m2m_ctx: 0x%p\n", ctx, ctx->fh.m2m_ctx); mutex_lock(&e5010->mutex); v4l2_ctrl_handler_free(&ctx->ctrl_handler); v4l2_m2m_ctx_release(ctx->fh.m2m_ctx); - v4l2_fh_del(&ctx->fh); + v4l2_fh_del(&ctx->fh, file); v4l2_fh_exit(&ctx->fh); kfree(ctx); mutex_unlock(&e5010->mutex); @@ -1262,7 +1261,7 @@ static void e5010_buf_queue(struct vb2_buffer *vb) static int e5010_encoder_cmd(struct file *file, void *priv, struct v4l2_encoder_cmd *cmd) { - struct e5010_context *ctx = file->private_data; + struct e5010_context *ctx = to_e5010_context(file); int ret; struct vb2_queue *cap_vq; diff --git a/drivers/media/platform/imagination/e5010-jpeg-enc.h b/drivers/media/platform/imagination/e5010-jpeg-enc.h index 71f49ead6898..da57bc1baa46 100644 --- a/drivers/media/platform/imagination/e5010-jpeg-enc.h +++ b/drivers/media/platform/imagination/e5010-jpeg-enc.h @@ -120,6 +120,11 @@ struct e5010_context { u8 chroma_qp[QP_TABLE_SIZE]; }; +static inline struct e5010_context *to_e5010_context(struct file *filp) +{ + return container_of(file_to_v4l2_fh(filp), struct e5010_context, fh); +} + /* * Buffer structure * Contains info for all buffers diff --git a/drivers/media/platform/m2m-deinterlace.c b/drivers/media/platform/m2m-deinterlace.c index 5188f3189096..e07e57d4206b 100644 --- a/drivers/media/platform/m2m-deinterlace.c +++ b/drivers/media/platform/m2m-deinterlace.c @@ -142,6 +142,11 @@ struct deinterlace_ctx { struct dma_interleaved_template *xt; }; +static inline struct deinterlace_ctx *file_to_ctx(struct file *filp) +{ + return container_of(file_to_v4l2_fh(filp), struct deinterlace_ctx, fh); +} + /* * mem2mem callbacks */ @@ -512,13 +517,13 @@ static int vidioc_g_fmt(struct deinterlace_ctx *ctx, struct v4l2_format *f) static int vidioc_g_fmt_vid_out(struct file *file, void *priv, struct v4l2_format *f) { - return vidioc_g_fmt(priv, f); + return vidioc_g_fmt(file_to_ctx(file), f); } static int vidioc_g_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *f) { - return vidioc_g_fmt(priv, f); + return vidioc_g_fmt(file_to_ctx(file), f); } static int vidioc_try_fmt(struct v4l2_format *f, struct deinterlace_fmt *fmt) @@ -539,8 +544,8 @@ static int vidioc_try_fmt(struct v4l2_format *f, struct deinterlace_fmt *fmt) static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *f) { + struct deinterlace_ctx *ctx = file_to_ctx(file); struct deinterlace_fmt *fmt; - struct deinterlace_ctx *ctx = priv; fmt = find_format(f); if (!fmt || !(fmt->types & MEM2MEM_CAPTURE)) @@ -633,20 +638,20 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, ret = vidioc_try_fmt_vid_cap(file, priv, f); if (ret) return ret; - return vidioc_s_fmt(priv, f); + return vidioc_s_fmt(file_to_ctx(file), f); } static int vidioc_s_fmt_vid_out(struct file *file, void *priv, struct v4l2_format *f) { - struct deinterlace_ctx *ctx = priv; + struct deinterlace_ctx *ctx = file_to_ctx(file); int ret; ret = vidioc_try_fmt_vid_out(file, priv, f); if (ret) return ret; - ret = vidioc_s_fmt(priv, f); + ret = vidioc_s_fmt(ctx, f); if (!ret) ctx->colorspace = f->fmt.pix.colorspace; @@ -656,8 +661,8 @@ static int vidioc_s_fmt_vid_out(struct file *file, void *priv, static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type type) { + struct deinterlace_ctx *ctx = file_to_ctx(file); struct deinterlace_q_data *s_q_data, *d_q_data; - struct deinterlace_ctx *ctx = priv; s_q_data = get_q_data(V4L2_BUF_TYPE_VIDEO_OUTPUT); d_q_data = get_q_data(V4L2_BUF_TYPE_VIDEO_CAPTURE); @@ -842,7 +847,6 @@ static int deinterlace_open(struct file *file) return -ENOMEM; v4l2_fh_init(&ctx->fh, video_devdata(file)); - file->private_data = &ctx->fh; ctx->dev = pcdev; ctx->fh.m2m_ctx = v4l2_m2m_ctx_init(pcdev->m2m_dev, ctx, &queue_init); @@ -861,7 +865,7 @@ static int deinterlace_open(struct file *file) } ctx->colorspace = V4L2_COLORSPACE_REC709; - v4l2_fh_add(&ctx->fh); + v4l2_fh_add(&ctx->fh, file); dprintk(pcdev, "Created instance %p, m2m_ctx: %p\n", ctx, ctx->fh.m2m_ctx); @@ -872,11 +876,11 @@ static int deinterlace_open(struct file *file) static int deinterlace_release(struct file *file) { struct deinterlace_dev *pcdev = video_drvdata(file); - struct deinterlace_ctx *ctx = file->private_data; + struct deinterlace_ctx *ctx = file_to_ctx(file); dprintk(pcdev, "Releasing instance %p\n", ctx); - v4l2_fh_del(&ctx->fh); + v4l2_fh_del(&ctx->fh, file); v4l2_fh_exit(&ctx->fh); v4l2_m2m_ctx_release(ctx->fh.m2m_ctx); kfree(ctx->xt); diff --git a/drivers/media/platform/marvell/cafe-driver.c b/drivers/media/platform/marvell/cafe-driver.c index ef810249def6..f9796de92aa7 100644 --- a/drivers/media/platform/marvell/cafe-driver.c +++ b/drivers/media/platform/marvell/cafe-driver.c @@ -14,7 +14,7 @@ * Written by Jonathan Corbet, corbet@lwn.net. * * v4l2_device/v4l2_subdev conversion by: - * Copyright (C) 2009 Hans Verkuil <hverkuil@xs4all.nl> + * Copyright (C) 2009 Hans Verkuil <hverkuil@kernel.org> */ #include <linux/kernel.h> #include <linux/module.h> diff --git a/drivers/media/platform/mediatek/jpeg/mtk_jpeg_core.c b/drivers/media/platform/mediatek/jpeg/mtk_jpeg_core.c index 7eb12449b63a..6268d651bdcf 100644 --- a/drivers/media/platform/mediatek/jpeg/mtk_jpeg_core.c +++ b/drivers/media/platform/mediatek/jpeg/mtk_jpeg_core.c @@ -119,9 +119,9 @@ static inline struct mtk_jpeg_ctx *ctrl_to_ctx(struct v4l2_ctrl *ctrl) return container_of(ctrl->handler, struct mtk_jpeg_ctx, ctrl_hdl); } -static inline struct mtk_jpeg_ctx *mtk_jpeg_fh_to_ctx(struct v4l2_fh *fh) +static inline struct mtk_jpeg_ctx *mtk_jpeg_file_to_ctx(struct file *filp) { - return container_of(fh, struct mtk_jpeg_ctx, fh); + return container_of(file_to_v4l2_fh(filp), struct mtk_jpeg_ctx, fh); } static inline struct mtk_jpeg_src_buf *mtk_jpeg_vb2_to_srcbuf( @@ -212,7 +212,7 @@ static int mtk_jpeg_enum_fmt(struct mtk_jpeg_fmt *mtk_jpeg_formats, int n, static int mtk_jpeg_enum_fmt_vid_cap(struct file *file, void *priv, struct v4l2_fmtdesc *f) { - struct mtk_jpeg_ctx *ctx = mtk_jpeg_fh_to_ctx(priv); + struct mtk_jpeg_ctx *ctx = mtk_jpeg_file_to_ctx(file); struct mtk_jpeg_dev *jpeg = ctx->jpeg; return mtk_jpeg_enum_fmt(jpeg->variant->formats, @@ -223,7 +223,7 @@ static int mtk_jpeg_enum_fmt_vid_cap(struct file *file, void *priv, static int mtk_jpeg_enum_fmt_vid_out(struct file *file, void *priv, struct v4l2_fmtdesc *f) { - struct mtk_jpeg_ctx *ctx = mtk_jpeg_fh_to_ctx(priv); + struct mtk_jpeg_ctx *ctx = mtk_jpeg_file_to_ctx(file); struct mtk_jpeg_dev *jpeg = ctx->jpeg; return mtk_jpeg_enum_fmt(jpeg->variant->formats, @@ -305,7 +305,7 @@ static int mtk_jpeg_g_fmt_vid_mplane(struct file *file, void *priv, struct vb2_queue *vq; struct mtk_jpeg_q_data *q_data = NULL; struct v4l2_pix_format_mplane *pix_mp = &f->fmt.pix_mp; - struct mtk_jpeg_ctx *ctx = mtk_jpeg_fh_to_ctx(priv); + struct mtk_jpeg_ctx *ctx = mtk_jpeg_file_to_ctx(file); struct mtk_jpeg_dev *jpeg = ctx->jpeg; int i; @@ -351,7 +351,7 @@ static int mtk_jpeg_g_fmt_vid_mplane(struct file *file, void *priv, static int mtk_jpeg_try_fmt_vid_cap_mplane(struct file *file, void *priv, struct v4l2_format *f) { - struct mtk_jpeg_ctx *ctx = mtk_jpeg_fh_to_ctx(priv); + struct mtk_jpeg_ctx *ctx = mtk_jpeg_file_to_ctx(file); struct mtk_jpeg_dev *jpeg = ctx->jpeg; struct mtk_jpeg_fmt *fmt; @@ -380,7 +380,7 @@ static int mtk_jpeg_try_fmt_vid_cap_mplane(struct file *file, void *priv, static int mtk_jpeg_try_fmt_vid_out_mplane(struct file *file, void *priv, struct v4l2_format *f) { - struct mtk_jpeg_ctx *ctx = mtk_jpeg_fh_to_ctx(priv); + struct mtk_jpeg_ctx *ctx = mtk_jpeg_file_to_ctx(file); struct mtk_jpeg_dev *jpeg = ctx->jpeg; struct mtk_jpeg_fmt *fmt; @@ -470,7 +470,7 @@ static int mtk_jpeg_s_fmt_vid_out_mplane(struct file *file, void *priv, if (ret) return ret; - return mtk_jpeg_s_fmt_mplane(mtk_jpeg_fh_to_ctx(priv), f, + return mtk_jpeg_s_fmt_mplane(mtk_jpeg_file_to_ctx(file), f, MTK_JPEG_FMT_FLAG_OUTPUT); } @@ -483,7 +483,7 @@ static int mtk_jpeg_s_fmt_vid_cap_mplane(struct file *file, void *priv, if (ret) return ret; - return mtk_jpeg_s_fmt_mplane(mtk_jpeg_fh_to_ctx(priv), f, + return mtk_jpeg_s_fmt_mplane(mtk_jpeg_file_to_ctx(file), f, MTK_JPEG_FMT_FLAG_CAPTURE); } @@ -512,7 +512,7 @@ static int mtk_jpeg_subscribe_event(struct v4l2_fh *fh, static int mtk_jpeg_enc_g_selection(struct file *file, void *priv, struct v4l2_selection *s) { - struct mtk_jpeg_ctx *ctx = mtk_jpeg_fh_to_ctx(priv); + struct mtk_jpeg_ctx *ctx = mtk_jpeg_file_to_ctx(file); if (s->type != V4L2_BUF_TYPE_VIDEO_OUTPUT) return -EINVAL; @@ -537,7 +537,7 @@ static int mtk_jpeg_enc_g_selection(struct file *file, void *priv, static int mtk_jpeg_dec_g_selection(struct file *file, void *priv, struct v4l2_selection *s) { - struct mtk_jpeg_ctx *ctx = mtk_jpeg_fh_to_ctx(priv); + struct mtk_jpeg_ctx *ctx = mtk_jpeg_file_to_ctx(file); if (s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) return -EINVAL; @@ -566,7 +566,7 @@ static int mtk_jpeg_dec_g_selection(struct file *file, void *priv, static int mtk_jpeg_enc_s_selection(struct file *file, void *priv, struct v4l2_selection *s) { - struct mtk_jpeg_ctx *ctx = mtk_jpeg_fh_to_ctx(priv); + struct mtk_jpeg_ctx *ctx = mtk_jpeg_file_to_ctx(file); if (s->type != V4L2_BUF_TYPE_VIDEO_OUTPUT) return -EINVAL; @@ -588,8 +588,8 @@ static int mtk_jpeg_enc_s_selection(struct file *file, void *priv, static int mtk_jpeg_qbuf(struct file *file, void *priv, struct v4l2_buffer *buf) { - struct v4l2_fh *fh = file->private_data; - struct mtk_jpeg_ctx *ctx = mtk_jpeg_fh_to_ctx(priv); + struct v4l2_fh *fh = file_to_v4l2_fh(file); + struct mtk_jpeg_ctx *ctx = mtk_jpeg_file_to_ctx(file); struct vb2_queue *vq; struct vb2_buffer *vb; struct mtk_jpeg_src_buf *jpeg_src_buf; @@ -1171,8 +1171,7 @@ static int mtk_jpeg_open(struct file *file) INIT_LIST_HEAD(&ctx->dst_done_queue); spin_lock_init(&ctx->done_queue_lock); v4l2_fh_init(&ctx->fh, vfd); - file->private_data = &ctx->fh; - v4l2_fh_add(&ctx->fh); + v4l2_fh_add(&ctx->fh, file); ctx->jpeg = jpeg; ctx->fh.m2m_ctx = v4l2_m2m_ctx_init(jpeg->m2m_dev, ctx, @@ -1197,7 +1196,7 @@ static int mtk_jpeg_open(struct file *file) return 0; error: - v4l2_fh_del(&ctx->fh); + v4l2_fh_del(&ctx->fh, file); v4l2_fh_exit(&ctx->fh); mutex_unlock(&jpeg->lock); free: @@ -1208,12 +1207,12 @@ free: static int mtk_jpeg_release(struct file *file) { struct mtk_jpeg_dev *jpeg = video_drvdata(file); - struct mtk_jpeg_ctx *ctx = mtk_jpeg_fh_to_ctx(file->private_data); + struct mtk_jpeg_ctx *ctx = mtk_jpeg_file_to_ctx(file); mutex_lock(&jpeg->lock); v4l2_m2m_ctx_release(ctx->fh.m2m_ctx); v4l2_ctrl_handler_free(&ctx->ctrl_hdl); - v4l2_fh_del(&ctx->fh); + v4l2_fh_del(&ctx->fh, file); v4l2_fh_exit(&ctx->fh); kfree(ctx); mutex_unlock(&jpeg->lock); diff --git a/drivers/media/platform/mediatek/mdp/mtk_mdp_m2m.c b/drivers/media/platform/mediatek/mdp/mtk_mdp_m2m.c index d0fd77dcf8e2..03c07948dfdd 100644 --- a/drivers/media/platform/mediatek/mdp/mtk_mdp_m2m.c +++ b/drivers/media/platform/mediatek/mdp/mtk_mdp_m2m.c @@ -348,9 +348,9 @@ static int mtk_mdp_try_crop(struct mtk_mdp_ctx *ctx, u32 type, return 0; } -static inline struct mtk_mdp_ctx *fh_to_ctx(struct v4l2_fh *fh) +static inline struct mtk_mdp_ctx *file_to_ctx(struct file *filp) { - return container_of(fh, struct mtk_mdp_ctx, fh); + return container_of(file_to_v4l2_fh(filp), struct mtk_mdp_ctx, fh); } static inline struct mtk_mdp_ctx *ctrl_to_ctx(struct v4l2_ctrl *ctrl) @@ -589,7 +589,7 @@ static const struct vb2_ops mtk_mdp_m2m_qops = { static int mtk_mdp_m2m_querycap(struct file *file, void *fh, struct v4l2_capability *cap) { - struct mtk_mdp_ctx *ctx = fh_to_ctx(fh); + struct mtk_mdp_ctx *ctx = file_to_ctx(file); struct mtk_mdp_dev *mdp = ctx->mdp_dev; strscpy(cap->driver, MTK_MDP_MODULE_NAME, sizeof(cap->driver)); @@ -627,7 +627,7 @@ static int mtk_mdp_m2m_enum_fmt_vid_out(struct file *file, void *priv, static int mtk_mdp_m2m_g_fmt_mplane(struct file *file, void *fh, struct v4l2_format *f) { - struct mtk_mdp_ctx *ctx = fh_to_ctx(fh); + struct mtk_mdp_ctx *ctx = file_to_ctx(file); struct mtk_mdp_frame *frame; struct v4l2_pix_format_mplane *pix_mp; int i; @@ -666,7 +666,7 @@ static int mtk_mdp_m2m_g_fmt_mplane(struct file *file, void *fh, static int mtk_mdp_m2m_try_fmt_mplane(struct file *file, void *fh, struct v4l2_format *f) { - struct mtk_mdp_ctx *ctx = fh_to_ctx(fh); + struct mtk_mdp_ctx *ctx = file_to_ctx(file); if (!mtk_mdp_try_fmt_mplane(ctx, f)) return -EINVAL; @@ -676,7 +676,7 @@ static int mtk_mdp_m2m_try_fmt_mplane(struct file *file, void *fh, static int mtk_mdp_m2m_s_fmt_mplane(struct file *file, void *fh, struct v4l2_format *f) { - struct mtk_mdp_ctx *ctx = fh_to_ctx(fh); + struct mtk_mdp_ctx *ctx = file_to_ctx(file); struct vb2_queue *vq; struct mtk_mdp_frame *frame; struct v4l2_pix_format_mplane *pix_mp; @@ -722,7 +722,7 @@ static int mtk_mdp_m2m_s_fmt_mplane(struct file *file, void *fh, static int mtk_mdp_m2m_reqbufs(struct file *file, void *fh, struct v4l2_requestbuffers *reqbufs) { - struct mtk_mdp_ctx *ctx = fh_to_ctx(fh); + struct mtk_mdp_ctx *ctx = file_to_ctx(file); return v4l2_m2m_reqbufs(file, ctx->m2m_ctx, reqbufs); } @@ -730,7 +730,7 @@ static int mtk_mdp_m2m_reqbufs(struct file *file, void *fh, static int mtk_mdp_m2m_streamon(struct file *file, void *fh, enum v4l2_buf_type type) { - struct mtk_mdp_ctx *ctx = fh_to_ctx(fh); + struct mtk_mdp_ctx *ctx = file_to_ctx(file); int ret; if (!mtk_mdp_ctx_state_is_set(ctx, MTK_MDP_VPU_INIT)) { @@ -768,8 +768,8 @@ static inline bool mtk_mdp_is_target_crop(u32 target) static int mtk_mdp_m2m_g_selection(struct file *file, void *fh, struct v4l2_selection *s) { + struct mtk_mdp_ctx *ctx = file_to_ctx(file); struct mtk_mdp_frame *frame; - struct mtk_mdp_ctx *ctx = fh_to_ctx(fh); bool valid = false; if (s->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) { @@ -835,8 +835,8 @@ static int mtk_mdp_check_scaler_ratio(struct mtk_mdp_variant *var, int src_w, static int mtk_mdp_m2m_s_selection(struct file *file, void *fh, struct v4l2_selection *s) { + struct mtk_mdp_ctx *ctx = file_to_ctx(file); struct mtk_mdp_frame *frame; - struct mtk_mdp_ctx *ctx = fh_to_ctx(fh); struct v4l2_rect new_r; struct mtk_mdp_variant *variant = ctx->mdp_dev->variant; int ret; @@ -1065,14 +1065,13 @@ static int mtk_mdp_m2m_open(struct file *file) mutex_init(&ctx->slock); ctx->id = mdp->id_counter++; v4l2_fh_init(&ctx->fh, vfd); - file->private_data = &ctx->fh; ret = mtk_mdp_ctrls_create(ctx); if (ret) goto error_ctrls; /* Use separate control handler per file handle */ ctx->fh.ctrl_handler = &ctx->ctrl_handler; - v4l2_fh_add(&ctx->fh); + v4l2_fh_add(&ctx->fh, file); INIT_LIST_HEAD(&ctx->list); ctx->mdp_dev = mdp; @@ -1126,7 +1125,7 @@ err_load_vpu: error_m2m_ctx: v4l2_ctrl_handler_free(&ctx->ctrl_handler); error_ctrls: - v4l2_fh_del(&ctx->fh); + v4l2_fh_del(&ctx->fh, file); v4l2_fh_exit(&ctx->fh); mutex_unlock(&mdp->lock); err_lock: @@ -1137,14 +1136,14 @@ err_lock: static int mtk_mdp_m2m_release(struct file *file) { - struct mtk_mdp_ctx *ctx = fh_to_ctx(file->private_data); + struct mtk_mdp_ctx *ctx = file_to_ctx(file); struct mtk_mdp_dev *mdp = ctx->mdp_dev; flush_workqueue(mdp->job_wq); mutex_lock(&mdp->lock); v4l2_m2m_ctx_release(ctx->m2m_ctx); v4l2_ctrl_handler_free(&ctx->ctrl_handler); - v4l2_fh_del(&ctx->fh); + v4l2_fh_del(&ctx->fh, file); v4l2_fh_exit(&ctx->fh); mtk_mdp_vpu_deinit(&ctx->vpu); mdp->ctx_num--; diff --git a/drivers/media/platform/mediatek/mdp3/mtk-mdp3-comp.c b/drivers/media/platform/mediatek/mdp3/mtk-mdp3-comp.c index 683c066ed975..7fcb2fbdd64e 100644 --- a/drivers/media/platform/mediatek/mdp3/mtk-mdp3-comp.c +++ b/drivers/media/platform/mediatek/mdp3/mtk-mdp3-comp.c @@ -1530,6 +1530,9 @@ static const struct of_device_id mdp_comp_dt_ids[] __maybe_unused = { }, { .compatible = "mediatek,mt8195-mdp3-tcc", .data = (void *)MDP_COMP_TYPE_TCC, + }, { + .compatible = "mediatek,mt8188-mdp3-rdma", + .data = (void *)MDP_COMP_TYPE_RDMA, }, {} }; diff --git a/drivers/media/platform/mediatek/mdp3/mtk-mdp3-core.c b/drivers/media/platform/mediatek/mdp3/mtk-mdp3-core.c index 8de2c8e4d333..6559d72d5d42 100644 --- a/drivers/media/platform/mediatek/mdp3/mtk-mdp3-core.c +++ b/drivers/media/platform/mediatek/mdp3/mtk-mdp3-core.c @@ -282,7 +282,7 @@ static int mdp_probe(struct platform_device *pdev) } mdp->rproc_handle = scp_get_rproc(mdp->scp); - dev_dbg(&pdev->dev, "MDP rproc_handle: %pK", mdp->rproc_handle); + dev_dbg(&pdev->dev, "MDP rproc_handle: %p", mdp->rproc_handle); mutex_init(&mdp->vpu_lock); mutex_init(&mdp->m2m_lock); diff --git a/drivers/media/platform/mediatek/mdp3/mtk-mdp3-m2m.c b/drivers/media/platform/mediatek/mdp3/mtk-mdp3-m2m.c index 59ce5cce0698..9ef956b565a7 100644 --- a/drivers/media/platform/mediatek/mdp3/mtk-mdp3-m2m.c +++ b/drivers/media/platform/mediatek/mdp3/mtk-mdp3-m2m.c @@ -10,9 +10,9 @@ #include <media/videobuf2-dma-contig.h> #include "mtk-mdp3-m2m.h" -static inline struct mdp_m2m_ctx *fh_to_ctx(struct v4l2_fh *fh) +static inline struct mdp_m2m_ctx *file_to_ctx(struct file *filp) { - return container_of(fh, struct mdp_m2m_ctx, fh); + return container_of(file_to_v4l2_fh(filp), struct mdp_m2m_ctx, fh); } static inline struct mdp_m2m_ctx *ctrl_to_ctx(struct v4l2_ctrl *ctrl) @@ -285,7 +285,7 @@ static int mdp_m2m_querycap(struct file *file, void *fh, static int mdp_m2m_enum_fmt_mplane(struct file *file, void *fh, struct v4l2_fmtdesc *f) { - struct mdp_m2m_ctx *ctx = fh_to_ctx(fh); + struct mdp_m2m_ctx *ctx = file_to_ctx(file); return mdp_enum_fmt_mplane(ctx->mdp_dev, f); } @@ -293,7 +293,7 @@ static int mdp_m2m_enum_fmt_mplane(struct file *file, void *fh, static int mdp_m2m_g_fmt_mplane(struct file *file, void *fh, struct v4l2_format *f) { - struct mdp_m2m_ctx *ctx = fh_to_ctx(fh); + struct mdp_m2m_ctx *ctx = file_to_ctx(file); struct mdp_frame *frame; struct v4l2_pix_format_mplane *pix_mp; @@ -311,7 +311,7 @@ static int mdp_m2m_g_fmt_mplane(struct file *file, void *fh, static int mdp_m2m_s_fmt_mplane(struct file *file, void *fh, struct v4l2_format *f) { - struct mdp_m2m_ctx *ctx = fh_to_ctx(fh); + struct mdp_m2m_ctx *ctx = file_to_ctx(file); struct mdp_frame *frame = ctx_get_frame(ctx, f->type); struct mdp_frame *capture; const struct mdp_format *fmt; @@ -354,7 +354,7 @@ static int mdp_m2m_s_fmt_mplane(struct file *file, void *fh, static int mdp_m2m_try_fmt_mplane(struct file *file, void *fh, struct v4l2_format *f) { - struct mdp_m2m_ctx *ctx = fh_to_ctx(fh); + struct mdp_m2m_ctx *ctx = file_to_ctx(file); if (!mdp_try_fmt_mplane(ctx->mdp_dev, f, &ctx->curr_param, ctx->id)) return -EINVAL; @@ -365,7 +365,7 @@ static int mdp_m2m_try_fmt_mplane(struct file *file, void *fh, static int mdp_m2m_g_selection(struct file *file, void *fh, struct v4l2_selection *s) { - struct mdp_m2m_ctx *ctx = fh_to_ctx(fh); + struct mdp_m2m_ctx *ctx = file_to_ctx(file); struct mdp_frame *frame; bool valid = false; @@ -417,7 +417,7 @@ static int mdp_m2m_g_selection(struct file *file, void *fh, static int mdp_m2m_s_selection(struct file *file, void *fh, struct v4l2_selection *s) { - struct mdp_m2m_ctx *ctx = fh_to_ctx(fh); + struct mdp_m2m_ctx *ctx = file_to_ctx(file); struct mdp_frame *frame = ctx_get_frame(ctx, s->type); struct mdp_frame *capture; struct v4l2_rect r; @@ -585,14 +585,13 @@ static int mdp_m2m_open(struct file *file) ctx->mdp_dev = mdp; v4l2_fh_init(&ctx->fh, vdev); - file->private_data = &ctx->fh; ret = mdp_m2m_ctrls_create(ctx); if (ret) goto err_exit_fh; /* Use separate control handler per file handle */ ctx->fh.ctrl_handler = &ctx->ctrl_handler; - v4l2_fh_add(&ctx->fh); + v4l2_fh_add(&ctx->fh, file); mutex_init(&ctx->ctx_lock); ctx->m2m_ctx = v4l2_m2m_ctx_init(mdp->m2m_dev, ctx, mdp_m2m_queue_init); @@ -629,7 +628,7 @@ err_release_m2m_ctx: v4l2_m2m_ctx_release(ctx->m2m_ctx); err_release_handler: v4l2_ctrl_handler_free(&ctx->ctrl_handler); - v4l2_fh_del(&ctx->fh); + v4l2_fh_del(&ctx->fh, file); err_exit_fh: v4l2_fh_exit(&ctx->fh); ida_free(&mdp->mdp_ida, ctx->id); @@ -643,7 +642,7 @@ err_free_ctx: static int mdp_m2m_release(struct file *file) { - struct mdp_m2m_ctx *ctx = fh_to_ctx(file->private_data); + struct mdp_m2m_ctx *ctx = file_to_ctx(file); struct mdp_dev *mdp = video_drvdata(file); struct device *dev = &mdp->pdev->dev; @@ -653,7 +652,7 @@ static int mdp_m2m_release(struct file *file) mdp_vpu_put_locked(mdp); v4l2_ctrl_handler_free(&ctx->ctrl_handler); - v4l2_fh_del(&ctx->fh); + v4l2_fh_del(&ctx->fh, file); v4l2_fh_exit(&ctx->fh); ida_free(&mdp->mdp_ida, ctx->id); mutex_unlock(&mdp->m2m_lock); diff --git a/drivers/media/platform/mediatek/mdp3/mtk-mdp3-vpu.c b/drivers/media/platform/mediatek/mdp3/mtk-mdp3-vpu.c index da3a892ad867..fae3e1ad2df7 100644 --- a/drivers/media/platform/mediatek/mdp3/mtk-mdp3-vpu.c +++ b/drivers/media/platform/mediatek/mdp3/mtk-mdp3-vpu.c @@ -221,7 +221,7 @@ int mdp_vpu_dev_init(struct mdp_vpu_dev *vpu, struct mtk_scp *scp, } dev_dbg(&mdp->pdev->dev, - "VPU param:%pK pa:%pad sz:%zx, work:%pK pa:%pad sz:%zx, config:%pK pa:%pad sz:%zx", + "VPU param:%p pa:%pad sz:%zx, work:%p pa:%pad sz:%zx, config:%p pa:%pad sz:%zx", vpu->param, &vpu->param_addr, vpu->param_size, vpu->work, &vpu->work_addr, vpu->work_size, vpu->config, &vpu->config_addr, vpu->config_size); diff --git a/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec.c b/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec.c index 98838217b97d..d691bd533103 100644 --- a/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec.c +++ b/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec.c @@ -87,7 +87,7 @@ static int stateful_try_decoder_cmd(struct file *file, void *priv, struct v4l2_d static int stateful_decoder_cmd(struct file *file, void *priv, struct v4l2_decoder_cmd *cmd) { - struct mtk_vcodec_dec_ctx *ctx = fh_to_dec_ctx(priv); + struct mtk_vcodec_dec_ctx *ctx = file_to_dec_ctx(file); struct vb2_queue *src_vq, *dst_vq; int ret; @@ -132,7 +132,7 @@ static int stateless_try_decoder_cmd(struct file *file, void *priv, struct v4l2_ static int stateless_decoder_cmd(struct file *file, void *priv, struct v4l2_decoder_cmd *cmd) { - struct mtk_vcodec_dec_ctx *ctx = fh_to_dec_ctx(priv); + struct mtk_vcodec_dec_ctx *ctx = file_to_dec_ctx(file); int ret; ret = v4l2_m2m_ioctl_stateless_try_decoder_cmd(file, priv, cmd); @@ -158,7 +158,7 @@ static int stateless_decoder_cmd(struct file *file, void *priv, struct v4l2_deco static int vidioc_try_decoder_cmd(struct file *file, void *priv, struct v4l2_decoder_cmd *cmd) { - struct mtk_vcodec_dec_ctx *ctx = fh_to_dec_ctx(priv); + struct mtk_vcodec_dec_ctx *ctx = file_to_dec_ctx(file); if (ctx->dev->vdec_pdata->uses_stateless_api) return stateless_try_decoder_cmd(file, priv, cmd); @@ -168,7 +168,7 @@ static int vidioc_try_decoder_cmd(struct file *file, void *priv, struct v4l2_dec static int vidioc_decoder_cmd(struct file *file, void *priv, struct v4l2_decoder_cmd *cmd) { - struct mtk_vcodec_dec_ctx *ctx = fh_to_dec_ctx(priv); + struct mtk_vcodec_dec_ctx *ctx = file_to_dec_ctx(file); if (ctx->dev->vdec_pdata->uses_stateless_api) return stateless_decoder_cmd(file, priv, cmd); @@ -233,7 +233,7 @@ void mtk_vcodec_dec_set_default_params(struct mtk_vcodec_dec_ctx *ctx) static int vidioc_vdec_qbuf(struct file *file, void *priv, struct v4l2_buffer *buf) { - struct mtk_vcodec_dec_ctx *ctx = fh_to_dec_ctx(priv); + struct mtk_vcodec_dec_ctx *ctx = file_to_dec_ctx(file); if (ctx->state == MTK_STATE_ABORT) { mtk_v4l2_vdec_err(ctx, "[%d] Call on QBUF after unrecoverable error", ctx->id); @@ -246,7 +246,7 @@ static int vidioc_vdec_qbuf(struct file *file, void *priv, static int vidioc_vdec_dqbuf(struct file *file, void *priv, struct v4l2_buffer *buf) { - struct mtk_vcodec_dec_ctx *ctx = fh_to_dec_ctx(priv); + struct mtk_vcodec_dec_ctx *ctx = file_to_dec_ctx(file); if (ctx->state == MTK_STATE_ABORT) { mtk_v4l2_vdec_err(ctx, "[%d] Call on DQBUF after unrecoverable error", ctx->id); @@ -259,7 +259,7 @@ static int vidioc_vdec_dqbuf(struct file *file, void *priv, static int vidioc_vdec_querycap(struct file *file, void *priv, struct v4l2_capability *cap) { - struct mtk_vcodec_dec_ctx *ctx = fh_to_dec_ctx(priv); + struct mtk_vcodec_dec_ctx *ctx = file_to_dec_ctx(file); struct device *dev = &ctx->dev->plat_dev->dev; strscpy(cap->driver, dev->driver->name, sizeof(cap->driver)); @@ -354,7 +354,7 @@ static int vidioc_try_fmt_vid_cap_mplane(struct file *file, void *priv, struct v4l2_format *f) { const struct mtk_video_fmt *fmt; - struct mtk_vcodec_dec_ctx *ctx = fh_to_dec_ctx(priv); + struct mtk_vcodec_dec_ctx *ctx = file_to_dec_ctx(file); const struct mtk_vcodec_dec_pdata *dec_pdata = ctx->dev->vdec_pdata; fmt = mtk_vdec_find_format(f, dec_pdata); @@ -372,7 +372,7 @@ static int vidioc_try_fmt_vid_out_mplane(struct file *file, void *priv, { struct v4l2_pix_format_mplane *pix_fmt_mp = &f->fmt.pix_mp; const struct mtk_video_fmt *fmt; - struct mtk_vcodec_dec_ctx *ctx = fh_to_dec_ctx(priv); + struct mtk_vcodec_dec_ctx *ctx = file_to_dec_ctx(file); const struct mtk_vcodec_dec_pdata *dec_pdata = ctx->dev->vdec_pdata; fmt = mtk_vdec_find_format(f, dec_pdata); @@ -393,7 +393,7 @@ static int vidioc_try_fmt_vid_out_mplane(struct file *file, void *priv, static int vidioc_vdec_g_selection(struct file *file, void *priv, struct v4l2_selection *s) { - struct mtk_vcodec_dec_ctx *ctx = fh_to_dec_ctx(priv); + struct mtk_vcodec_dec_ctx *ctx = file_to_dec_ctx(file); struct mtk_q_data *q_data; if (s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) @@ -442,7 +442,7 @@ static int vidioc_vdec_g_selection(struct file *file, void *priv, static int vidioc_vdec_s_selection(struct file *file, void *priv, struct v4l2_selection *s) { - struct mtk_vcodec_dec_ctx *ctx = fh_to_dec_ctx(priv); + struct mtk_vcodec_dec_ctx *ctx = file_to_dec_ctx(file); if (s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) return -EINVAL; @@ -464,7 +464,7 @@ static int vidioc_vdec_s_selection(struct file *file, void *priv, static int vidioc_vdec_s_fmt(struct file *file, void *priv, struct v4l2_format *f) { - struct mtk_vcodec_dec_ctx *ctx = fh_to_dec_ctx(priv); + struct mtk_vcodec_dec_ctx *ctx = file_to_dec_ctx(file); struct v4l2_pix_format_mplane *pix_mp; struct mtk_q_data *q_data; int ret = 0; @@ -594,7 +594,7 @@ static int vidioc_enum_framesizes(struct file *file, void *priv, struct v4l2_frmsizeenum *fsize) { int i = 0; - struct mtk_vcodec_dec_ctx *ctx = fh_to_dec_ctx(priv); + struct mtk_vcodec_dec_ctx *ctx = file_to_dec_ctx(file); const struct mtk_vcodec_dec_pdata *dec_pdata = ctx->dev->vdec_pdata; if (fsize->index != 0) @@ -623,10 +623,10 @@ static int vidioc_enum_framesizes(struct file *file, void *priv, return -EINVAL; } -static int vidioc_enum_fmt(struct v4l2_fmtdesc *f, void *priv, +static int vidioc_enum_fmt(struct file *file, struct v4l2_fmtdesc *f, bool output_queue) { - struct mtk_vcodec_dec_ctx *ctx = fh_to_dec_ctx(priv); + struct mtk_vcodec_dec_ctx *ctx = file_to_dec_ctx(file); const struct mtk_vcodec_dec_pdata *dec_pdata = ctx->dev->vdec_pdata; const struct mtk_video_fmt *fmt; int i, j = 0; @@ -660,19 +660,19 @@ static int vidioc_enum_fmt(struct v4l2_fmtdesc *f, void *priv, static int vidioc_vdec_enum_fmt_vid_cap(struct file *file, void *priv, struct v4l2_fmtdesc *f) { - return vidioc_enum_fmt(f, priv, false); + return vidioc_enum_fmt(file, f, false); } static int vidioc_vdec_enum_fmt_vid_out(struct file *file, void *priv, struct v4l2_fmtdesc *f) { - return vidioc_enum_fmt(f, priv, true); + return vidioc_enum_fmt(file, f, true); } static int vidioc_vdec_g_fmt(struct file *file, void *priv, struct v4l2_format *f) { - struct mtk_vcodec_dec_ctx *ctx = fh_to_dec_ctx(priv); + struct mtk_vcodec_dec_ctx *ctx = file_to_dec_ctx(file); struct v4l2_pix_format_mplane *pix_mp = &f->fmt.pix_mp; struct vb2_queue *vq; struct mtk_q_data *q_data; diff --git a/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_drv.c b/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_drv.c index 9247d92d431d..46d176e6de63 100644 --- a/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_drv.c +++ b/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_drv.c @@ -206,8 +206,7 @@ static int fops_vcodec_open(struct file *file) mutex_lock(&dev->dev_mutex); ctx->id = dev->id_counter++; v4l2_fh_init(&ctx->fh, video_devdata(file)); - file->private_data = &ctx->fh; - v4l2_fh_add(&ctx->fh); + v4l2_fh_add(&ctx->fh, file); INIT_LIST_HEAD(&ctx->list); ctx->dev = dev; if (ctx->dev->vdec_pdata->is_subdev_supported) { @@ -283,7 +282,7 @@ err_load_fw: err_m2m_ctx_init: v4l2_ctrl_handler_free(&ctx->ctrl_hdl); err_ctrls_setup: - v4l2_fh_del(&ctx->fh); + v4l2_fh_del(&ctx->fh, file); v4l2_fh_exit(&ctx->fh); kfree(ctx); mutex_unlock(&dev->dev_mutex); @@ -294,7 +293,7 @@ err_ctrls_setup: static int fops_vcodec_release(struct file *file) { struct mtk_vcodec_dec_dev *dev = video_drvdata(file); - struct mtk_vcodec_dec_ctx *ctx = fh_to_dec_ctx(file->private_data); + struct mtk_vcodec_dec_ctx *ctx = file_to_dec_ctx(file); mtk_v4l2_vdec_dbg(0, ctx, "[%d] decoder", ctx->id); mutex_lock(&dev->dev_mutex); @@ -308,7 +307,7 @@ static int fops_vcodec_release(struct file *file) v4l2_m2m_ctx_release(ctx->m2m_ctx); mtk_vcodec_dec_release(ctx); - v4l2_fh_del(&ctx->fh); + v4l2_fh_del(&ctx->fh, file); v4l2_fh_exit(&ctx->fh); v4l2_ctrl_handler_free(&ctx->ctrl_hdl); diff --git a/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_drv.h b/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_drv.h index aececca7ecf8..d047d7c580fb 100644 --- a/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_drv.h +++ b/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_drv.h @@ -314,6 +314,11 @@ static inline struct mtk_vcodec_dec_ctx *fh_to_dec_ctx(struct v4l2_fh *fh) return container_of(fh, struct mtk_vcodec_dec_ctx, fh); } +static inline struct mtk_vcodec_dec_ctx *file_to_dec_ctx(struct file *filp) +{ + return fh_to_dec_ctx(file_to_v4l2_fh(filp)); +} + static inline struct mtk_vcodec_dec_ctx *ctrl_to_dec_ctx(struct v4l2_ctrl *ctrl) { return container_of(ctrl->handler, struct mtk_vcodec_dec_ctx, ctrl_hdl); diff --git a/drivers/media/platform/mediatek/vcodec/encoder/mtk_vcodec_enc.c b/drivers/media/platform/mediatek/vcodec/encoder/mtk_vcodec_enc.c index a01dc25a7699..d815e962ab89 100644 --- a/drivers/media/platform/mediatek/vcodec/encoder/mtk_vcodec_enc.c +++ b/drivers/media/platform/mediatek/vcodec/encoder/mtk_vcodec_enc.c @@ -159,7 +159,7 @@ static int vidioc_enum_framesizes(struct file *file, void *fh, struct v4l2_frmsizeenum *fsize) { const struct mtk_video_fmt *fmt; - struct mtk_vcodec_enc_ctx *ctx = fh_to_enc_ctx(fh); + struct mtk_vcodec_enc_ctx *ctx = file_to_enc_ctx(file); if (fsize->index != 0) return -EINVAL; @@ -183,7 +183,7 @@ static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv, struct v4l2_fmtdesc *f) { const struct mtk_vcodec_enc_pdata *pdata = - fh_to_enc_ctx(priv)->dev->venc_pdata; + file_to_enc_ctx(file)->dev->venc_pdata; return vidioc_enum_fmt(f, pdata->capture_formats, pdata->num_capture_formats); @@ -193,15 +193,14 @@ static int vidioc_enum_fmt_vid_out(struct file *file, void *priv, struct v4l2_fmtdesc *f) { const struct mtk_vcodec_enc_pdata *pdata = - fh_to_enc_ctx(priv)->dev->venc_pdata; + file_to_enc_ctx(file)->dev->venc_pdata; return vidioc_enum_fmt(f, pdata->output_formats, pdata->num_output_formats); } -static int mtk_vcodec_enc_get_chip_name(void *priv) +static int mtk_vcodec_enc_get_chip_name(struct mtk_vcodec_enc_ctx *ctx) { - struct mtk_vcodec_enc_ctx *ctx = fh_to_enc_ctx(priv); struct device *dev = &ctx->dev->plat_dev->dev; if (of_device_is_compatible(dev->of_node, "mediatek,mt8173-vcodec-enc")) @@ -221,9 +220,9 @@ static int mtk_vcodec_enc_get_chip_name(void *priv) static int vidioc_venc_querycap(struct file *file, void *priv, struct v4l2_capability *cap) { - struct mtk_vcodec_enc_ctx *ctx = fh_to_enc_ctx(priv); + struct mtk_vcodec_enc_ctx *ctx = file_to_enc_ctx(file); struct device *dev = &ctx->dev->plat_dev->dev; - int platform_name = mtk_vcodec_enc_get_chip_name(priv); + int platform_name = mtk_vcodec_enc_get_chip_name(ctx); strscpy(cap->driver, dev->driver->name, sizeof(cap->driver)); snprintf(cap->card, sizeof(cap->card), "MT%d video encoder", platform_name); @@ -234,7 +233,7 @@ static int vidioc_venc_querycap(struct file *file, void *priv, static int vidioc_venc_s_parm(struct file *file, void *priv, struct v4l2_streamparm *a) { - struct mtk_vcodec_enc_ctx *ctx = fh_to_enc_ctx(priv); + struct mtk_vcodec_enc_ctx *ctx = file_to_enc_ctx(file); struct v4l2_fract *timeperframe = &a->parm.output.timeperframe; if (a->type != V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) @@ -257,7 +256,7 @@ static int vidioc_venc_s_parm(struct file *file, void *priv, static int vidioc_venc_g_parm(struct file *file, void *priv, struct v4l2_streamparm *a) { - struct mtk_vcodec_enc_ctx *ctx = fh_to_enc_ctx(priv); + struct mtk_vcodec_enc_ctx *ctx = file_to_enc_ctx(file); if (a->type != V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) return -EINVAL; @@ -414,7 +413,7 @@ static void mtk_venc_set_param(struct mtk_vcodec_enc_ctx *ctx, static int vidioc_venc_s_fmt_cap(struct file *file, void *priv, struct v4l2_format *f) { - struct mtk_vcodec_enc_ctx *ctx = fh_to_enc_ctx(priv); + struct mtk_vcodec_enc_ctx *ctx = file_to_enc_ctx(file); const struct mtk_vcodec_enc_pdata *pdata = ctx->dev->venc_pdata; struct vb2_queue *vq; struct mtk_q_data *q_data = mtk_venc_get_q_data(ctx, f->type); @@ -469,7 +468,7 @@ static int vidioc_venc_s_fmt_cap(struct file *file, void *priv, static int vidioc_venc_s_fmt_out(struct file *file, void *priv, struct v4l2_format *f) { - struct mtk_vcodec_enc_ctx *ctx = fh_to_enc_ctx(priv); + struct mtk_vcodec_enc_ctx *ctx = file_to_enc_ctx(file); const struct mtk_vcodec_enc_pdata *pdata = ctx->dev->venc_pdata; struct vb2_queue *vq; struct mtk_q_data *q_data = mtk_venc_get_q_data(ctx, f->type); @@ -524,7 +523,7 @@ static int vidioc_venc_g_fmt(struct file *file, void *priv, struct v4l2_format *f) { struct v4l2_pix_format_mplane *pix = &f->fmt.pix_mp; - struct mtk_vcodec_enc_ctx *ctx = fh_to_enc_ctx(priv); + struct mtk_vcodec_enc_ctx *ctx = file_to_enc_ctx(file); struct vb2_queue *vq; struct mtk_q_data *q_data = mtk_venc_get_q_data(ctx, f->type); int i; @@ -557,7 +556,7 @@ static int vidioc_try_fmt_vid_cap_mplane(struct file *file, void *priv, struct v4l2_format *f) { const struct mtk_video_fmt *fmt; - struct mtk_vcodec_enc_ctx *ctx = fh_to_enc_ctx(priv); + struct mtk_vcodec_enc_ctx *ctx = file_to_enc_ctx(file); const struct mtk_vcodec_enc_pdata *pdata = ctx->dev->venc_pdata; fmt = mtk_venc_find_format(f->fmt.pix.pixelformat, pdata); @@ -579,7 +578,7 @@ static int vidioc_try_fmt_vid_out_mplane(struct file *file, void *priv, struct v4l2_format *f) { const struct mtk_video_fmt *fmt; - struct mtk_vcodec_enc_ctx *ctx = fh_to_enc_ctx(priv); + struct mtk_vcodec_enc_ctx *ctx = file_to_enc_ctx(file); const struct mtk_vcodec_enc_pdata *pdata = ctx->dev->venc_pdata; fmt = mtk_venc_find_format(f->fmt.pix.pixelformat, pdata); @@ -600,7 +599,7 @@ static int vidioc_try_fmt_vid_out_mplane(struct file *file, void *priv, static int vidioc_venc_g_selection(struct file *file, void *priv, struct v4l2_selection *s) { - struct mtk_vcodec_enc_ctx *ctx = fh_to_enc_ctx(priv); + struct mtk_vcodec_enc_ctx *ctx = file_to_enc_ctx(file); struct mtk_q_data *q_data = mtk_venc_get_q_data(ctx, s->type); if (s->type != V4L2_BUF_TYPE_VIDEO_OUTPUT) @@ -630,7 +629,7 @@ static int vidioc_venc_g_selection(struct file *file, void *priv, static int vidioc_venc_s_selection(struct file *file, void *priv, struct v4l2_selection *s) { - struct mtk_vcodec_enc_ctx *ctx = fh_to_enc_ctx(priv); + struct mtk_vcodec_enc_ctx *ctx = file_to_enc_ctx(file); struct mtk_q_data *q_data = mtk_venc_get_q_data(ctx, s->type); if (s->type != V4L2_BUF_TYPE_VIDEO_OUTPUT) @@ -655,7 +654,7 @@ static int vidioc_venc_s_selection(struct file *file, void *priv, static int vidioc_venc_qbuf(struct file *file, void *priv, struct v4l2_buffer *buf) { - struct mtk_vcodec_enc_ctx *ctx = fh_to_enc_ctx(priv); + struct mtk_vcodec_enc_ctx *ctx = file_to_enc_ctx(file); if (ctx->state == MTK_STATE_ABORT) { mtk_v4l2_venc_err(ctx, "[%d] Call on QBUF after unrecoverable error", @@ -669,7 +668,7 @@ static int vidioc_venc_qbuf(struct file *file, void *priv, static int vidioc_venc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *buf) { - struct mtk_vcodec_enc_ctx *ctx = fh_to_enc_ctx(priv); + struct mtk_vcodec_enc_ctx *ctx = file_to_enc_ctx(file); int ret; if (ctx->state == MTK_STATE_ABORT) { @@ -707,7 +706,7 @@ static int vidioc_venc_dqbuf(struct file *file, void *priv, static int vidioc_encoder_cmd(struct file *file, void *priv, struct v4l2_encoder_cmd *cmd) { - struct mtk_vcodec_enc_ctx *ctx = fh_to_enc_ctx(priv); + struct mtk_vcodec_enc_ctx *ctx = file_to_enc_ctx(file); struct vb2_queue *src_vq, *dst_vq; int ret; diff --git a/drivers/media/platform/mediatek/vcodec/encoder/mtk_vcodec_enc_drv.c b/drivers/media/platform/mediatek/vcodec/encoder/mtk_vcodec_enc_drv.c index a1e4483abcdb..fb1c3bdc2dae 100644 --- a/drivers/media/platform/mediatek/vcodec/encoder/mtk_vcodec_enc_drv.c +++ b/drivers/media/platform/mediatek/vcodec/encoder/mtk_vcodec_enc_drv.c @@ -129,8 +129,7 @@ static int fops_vcodec_open(struct file *file) */ ctx->id = dev->id_counter++; v4l2_fh_init(&ctx->fh, video_devdata(file)); - file->private_data = &ctx->fh; - v4l2_fh_add(&ctx->fh); + v4l2_fh_add(&ctx->fh, file); INIT_LIST_HEAD(&ctx->list); ctx->dev = dev; init_waitqueue_head(&ctx->queue[0]); @@ -192,7 +191,7 @@ err_load_fw: err_m2m_ctx_init: v4l2_ctrl_handler_free(&ctx->ctrl_hdl); err_ctrls_setup: - v4l2_fh_del(&ctx->fh); + v4l2_fh_del(&ctx->fh, file); v4l2_fh_exit(&ctx->fh); kfree(ctx); mutex_unlock(&dev->dev_mutex); @@ -203,14 +202,14 @@ err_ctrls_setup: static int fops_vcodec_release(struct file *file) { struct mtk_vcodec_enc_dev *dev = video_drvdata(file); - struct mtk_vcodec_enc_ctx *ctx = fh_to_enc_ctx(file->private_data); + struct mtk_vcodec_enc_ctx *ctx = file_to_enc_ctx(file); mtk_v4l2_venc_dbg(1, ctx, "[%d] encoder", ctx->id); mutex_lock(&dev->dev_mutex); v4l2_m2m_ctx_release(ctx->m2m_ctx); mtk_vcodec_enc_release(ctx); - v4l2_fh_del(&ctx->fh); + v4l2_fh_del(&ctx->fh, file); v4l2_fh_exit(&ctx->fh); v4l2_ctrl_handler_free(&ctx->ctrl_hdl); diff --git a/drivers/media/platform/mediatek/vcodec/encoder/mtk_vcodec_enc_drv.h b/drivers/media/platform/mediatek/vcodec/encoder/mtk_vcodec_enc_drv.h index 0bd85d0fb379..5b304a551236 100644 --- a/drivers/media/platform/mediatek/vcodec/encoder/mtk_vcodec_enc_drv.h +++ b/drivers/media/platform/mediatek/vcodec/encoder/mtk_vcodec_enc_drv.h @@ -217,9 +217,9 @@ struct mtk_vcodec_enc_dev { struct mtk_vcodec_dbgfs dbgfs; }; -static inline struct mtk_vcodec_enc_ctx *fh_to_enc_ctx(struct v4l2_fh *fh) +static inline struct mtk_vcodec_enc_ctx *file_to_enc_ctx(struct file *filp) { - return container_of(fh, struct mtk_vcodec_enc_ctx, fh); + return container_of(file_to_v4l2_fh(filp), struct mtk_vcodec_enc_ctx, fh); } static inline struct mtk_vcodec_enc_ctx *ctrl_to_enc_ctx(struct v4l2_ctrl *ctrl) diff --git a/drivers/media/platform/nvidia/tegra-vde/v4l2.c b/drivers/media/platform/nvidia/tegra-vde/v4l2.c index e3726cab0c82..d94978ae2baf 100644 --- a/drivers/media/platform/nvidia/tegra-vde/v4l2.c +++ b/drivers/media/platform/nvidia/tegra-vde/v4l2.c @@ -46,9 +46,9 @@ static const struct v4l2_ctrl_config ctrl_cfgs[] = { }, }; -static inline struct tegra_ctx *fh_to_tegra_ctx(struct v4l2_fh *fh) +static inline struct tegra_ctx *file_to_tegra_ctx(struct file *file) { - return container_of(fh, struct tegra_ctx, fh); + return container_of(file_to_v4l2_fh(file), struct tegra_ctx, fh); } static void tegra_set_control_data(struct tegra_ctx *ctx, void *data, u32 id) @@ -506,7 +506,7 @@ static int tegra_querycap(struct file *file, void *priv, static int tegra_enum_decoded_fmt(struct file *file, void *priv, struct v4l2_fmtdesc *f) { - struct tegra_ctx *ctx = fh_to_tegra_ctx(priv); + struct tegra_ctx *ctx = file_to_tegra_ctx(file); if (WARN_ON(!ctx->coded_fmt_desc)) return -EINVAL; @@ -522,7 +522,7 @@ static int tegra_enum_decoded_fmt(struct file *file, void *priv, static int tegra_g_decoded_fmt(struct file *file, void *priv, struct v4l2_format *f) { - struct tegra_ctx *ctx = fh_to_tegra_ctx(priv); + struct tegra_ctx *ctx = file_to_tegra_ctx(file); *f = ctx->decoded_fmt; return 0; @@ -531,8 +531,8 @@ static int tegra_g_decoded_fmt(struct file *file, void *priv, static int tegra_try_decoded_fmt(struct file *file, void *priv, struct v4l2_format *f) { + struct tegra_ctx *ctx = file_to_tegra_ctx(file); struct v4l2_pix_format_mplane *pix_mp = &f->fmt.pix_mp; - struct tegra_ctx *ctx = fh_to_tegra_ctx(priv); const struct tegra_coded_fmt_desc *coded_desc; unsigned int i; @@ -571,7 +571,7 @@ static int tegra_try_decoded_fmt(struct file *file, void *priv, static int tegra_s_decoded_fmt(struct file *file, void *priv, struct v4l2_format *f) { - struct tegra_ctx *ctx = fh_to_tegra_ctx(priv); + struct tegra_ctx *ctx = file_to_tegra_ctx(file); struct vb2_queue *vq; int err; @@ -593,7 +593,7 @@ static int tegra_s_decoded_fmt(struct file *file, void *priv, static int tegra_enum_coded_fmt(struct file *file, void *priv, struct v4l2_fmtdesc *f) { - struct tegra_ctx *ctx = fh_to_tegra_ctx(priv); + struct tegra_ctx *ctx = file_to_tegra_ctx(file); const struct tegra_vde_soc *soc = ctx->vde->soc; if (f->index >= soc->num_coded_fmts) @@ -607,7 +607,7 @@ static int tegra_enum_coded_fmt(struct file *file, void *priv, static int tegra_g_coded_fmt(struct file *file, void *priv, struct v4l2_format *f) { - struct tegra_ctx *ctx = fh_to_tegra_ctx(priv); + struct tegra_ctx *ctx = file_to_tegra_ctx(file); *f = ctx->coded_fmt; return 0; @@ -631,7 +631,7 @@ static int tegra_try_coded_fmt(struct file *file, void *priv, struct v4l2_format *f) { struct v4l2_pix_format_mplane *pix_mp = &f->fmt.pix_mp; - struct tegra_ctx *ctx = fh_to_tegra_ctx(priv); + struct tegra_ctx *ctx = file_to_tegra_ctx(file); const struct tegra_vde_soc *soc = ctx->vde->soc; int size = pix_mp->plane_fmt[0].sizeimage; const struct tegra_coded_fmt_desc *desc; @@ -656,7 +656,7 @@ static int tegra_try_coded_fmt(struct file *file, void *priv, static int tegra_s_coded_fmt(struct file *file, void *priv, struct v4l2_format *f) { - struct tegra_ctx *ctx = fh_to_tegra_ctx(priv); + struct tegra_ctx *ctx = file_to_tegra_ctx(file); struct v4l2_m2m_ctx *m2m_ctx = ctx->fh.m2m_ctx; const struct tegra_coded_fmt_desc *desc; struct vb2_queue *peer_vq, *vq; @@ -718,7 +718,7 @@ static int tegra_s_coded_fmt(struct file *file, void *priv, static int tegra_enum_framesizes(struct file *file, void *priv, struct v4l2_frmsizeenum *fsize) { - struct tegra_ctx *ctx = fh_to_tegra_ctx(priv); + struct tegra_ctx *ctx = file_to_tegra_ctx(file); const struct tegra_coded_fmt_desc *fmt; if (fsize->index) @@ -832,14 +832,13 @@ static int tegra_open(struct file *file) goto free_ctrls; } - file->private_data = &ctx->fh; - v4l2_fh_add(&ctx->fh); + v4l2_fh_add(&ctx->fh, file); tegra_reset_coded_fmt(ctx); - tegra_try_coded_fmt(file, file->private_data, &ctx->coded_fmt); + tegra_try_coded_fmt(file, &ctx->fh, &ctx->coded_fmt); tegra_reset_decoded_fmt(ctx); - tegra_try_decoded_fmt(file, file->private_data, &ctx->decoded_fmt); + tegra_try_decoded_fmt(file, &ctx->fh, &ctx->decoded_fmt); return 0; @@ -853,11 +852,11 @@ free_ctx: static int tegra_release(struct file *file) { - struct v4l2_fh *fh = file->private_data; - struct tegra_ctx *ctx = fh_to_tegra_ctx(fh); + struct tegra_ctx *ctx = file_to_tegra_ctx(file); + struct v4l2_fh *fh = file_to_v4l2_fh(file); struct tegra_vde *vde = ctx->vde; - v4l2_fh_del(fh); + v4l2_fh_del(fh, file); v4l2_m2m_ctx_release(fh->m2m_ctx); v4l2_ctrl_handler_free(&ctx->hdl); v4l2_fh_exit(fh); diff --git a/drivers/media/platform/nxp/dw100/dw100.c b/drivers/media/platform/nxp/dw100/dw100.c index 3d1db1121bf9..97744c7b7c03 100644 --- a/drivers/media/platform/nxp/dw100/dw100.c +++ b/drivers/media/platform/nxp/dw100/dw100.c @@ -266,7 +266,7 @@ static inline int dw100_dump_regs(struct seq_file *m) static inline struct dw100_ctx *dw100_file2ctx(struct file *file) { - return container_of(file->private_data, struct dw100_ctx, fh); + return container_of(file_to_v4l2_fh(file), struct dw100_ctx, fh); } static struct dw100_q_data *dw100_get_q_data(struct dw100_ctx *ctx, @@ -607,7 +607,6 @@ static int dw100_open(struct file *file) mutex_init(&ctx->vq_mutex); v4l2_fh_init(&ctx->fh, video_devdata(file)); - file->private_data = &ctx->fh; ctx->dw_dev = dw_dev; ctx->q_data[DW100_QUEUE_SRC].fmt = &formats[0]; @@ -651,7 +650,7 @@ static int dw100_open(struct file *file) goto err; } - v4l2_fh_add(&ctx->fh); + v4l2_fh_add(&ctx->fh, file); return 0; @@ -668,7 +667,7 @@ static int dw100_release(struct file *file) { struct dw100_ctx *ctx = dw100_file2ctx(file); - v4l2_fh_del(&ctx->fh); + v4l2_fh_del(&ctx->fh, file); v4l2_fh_exit(&ctx->fh); v4l2_ctrl_handler_free(&ctx->hdl); v4l2_m2m_ctx_release(ctx->fh.m2m_ctx); diff --git a/drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.c b/drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.c index 8681dd193033..df3ccdf767ba 100644 --- a/drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.c +++ b/drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.c @@ -644,9 +644,9 @@ static void print_mxc_buf(struct mxc_jpeg_dev *jpeg, struct vb2_buffer *buf, } } -static inline struct mxc_jpeg_ctx *mxc_jpeg_fh_to_ctx(struct v4l2_fh *fh) +static inline struct mxc_jpeg_ctx *mxc_jpeg_file_to_ctx(struct file *filp) { - return container_of(fh, struct mxc_jpeg_ctx, fh); + return container_of(file_to_v4l2_fh(filp), struct mxc_jpeg_ctx, fh); } static int enum_fmt(const struct mxc_jpeg_fmt *mxc_formats, int n, @@ -1604,8 +1604,8 @@ end: static int mxc_jpeg_decoder_cmd(struct file *file, void *priv, struct v4l2_decoder_cmd *cmd) { - struct v4l2_fh *fh = file->private_data; - struct mxc_jpeg_ctx *ctx = mxc_jpeg_fh_to_ctx(fh); + struct v4l2_fh *fh = file_to_v4l2_fh(file); + struct mxc_jpeg_ctx *ctx = mxc_jpeg_file_to_ctx(file); unsigned long flags; int ret; @@ -1637,8 +1637,8 @@ static int mxc_jpeg_decoder_cmd(struct file *file, void *priv, static int mxc_jpeg_encoder_cmd(struct file *file, void *priv, struct v4l2_encoder_cmd *cmd) { - struct v4l2_fh *fh = file->private_data; - struct mxc_jpeg_ctx *ctx = mxc_jpeg_fh_to_ctx(fh); + struct v4l2_fh *fh = file_to_v4l2_fh(file); + struct mxc_jpeg_ctx *ctx = mxc_jpeg_file_to_ctx(file); unsigned long flags; int ret; @@ -2200,8 +2200,7 @@ static int mxc_jpeg_open(struct file *file) } v4l2_fh_init(&ctx->fh, mxc_vfd); - file->private_data = &ctx->fh; - v4l2_fh_add(&ctx->fh); + v4l2_fh_add(&ctx->fh, file); ctx->mxc_jpeg = mxc_jpeg; @@ -2234,7 +2233,7 @@ static int mxc_jpeg_open(struct file *file) err_ctrls_setup: v4l2_m2m_ctx_release(ctx->fh.m2m_ctx); error: - v4l2_fh_del(&ctx->fh); + v4l2_fh_del(&ctx->fh, file); v4l2_fh_exit(&ctx->fh); mutex_unlock(&mxc_jpeg->lock); free: @@ -2256,7 +2255,7 @@ static int mxc_jpeg_querycap(struct file *file, void *priv, static int mxc_jpeg_enum_fmt_vid_cap(struct file *file, void *priv, struct v4l2_fmtdesc *f) { - struct mxc_jpeg_ctx *ctx = mxc_jpeg_fh_to_ctx(priv); + struct mxc_jpeg_ctx *ctx = mxc_jpeg_file_to_ctx(file); struct mxc_jpeg_q_data *q_data = mxc_jpeg_get_q_data(ctx, f->type); if (ctx->mxc_jpeg->mode == MXC_JPEG_ENCODE) { @@ -2296,7 +2295,7 @@ static int mxc_jpeg_enum_fmt_vid_cap(struct file *file, void *priv, static int mxc_jpeg_enum_fmt_vid_out(struct file *file, void *priv, struct v4l2_fmtdesc *f) { - struct mxc_jpeg_ctx *ctx = mxc_jpeg_fh_to_ctx(priv); + struct mxc_jpeg_ctx *ctx = mxc_jpeg_file_to_ctx(file); u32 type = ctx->mxc_jpeg->mode == MXC_JPEG_DECODE ? MXC_JPEG_FMT_TYPE_ENC : MXC_JPEG_FMT_TYPE_RAW; int ret; @@ -2437,7 +2436,7 @@ static int mxc_jpeg_try_fmt(struct v4l2_format *f, static int mxc_jpeg_try_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *f) { - struct mxc_jpeg_ctx *ctx = mxc_jpeg_fh_to_ctx(priv); + struct mxc_jpeg_ctx *ctx = mxc_jpeg_file_to_ctx(file); struct mxc_jpeg_dev *jpeg = ctx->mxc_jpeg; struct device *dev = jpeg->dev; struct mxc_jpeg_q_data tmp_q; @@ -2456,7 +2455,7 @@ static int mxc_jpeg_try_fmt_vid_cap(struct file *file, void *priv, static int mxc_jpeg_try_fmt_vid_out(struct file *file, void *priv, struct v4l2_format *f) { - struct mxc_jpeg_ctx *ctx = mxc_jpeg_fh_to_ctx(priv); + struct mxc_jpeg_ctx *ctx = mxc_jpeg_file_to_ctx(file); struct mxc_jpeg_dev *jpeg = ctx->mxc_jpeg; struct device *dev = jpeg->dev; struct mxc_jpeg_q_data tmp_q; @@ -2508,20 +2507,20 @@ static int mxc_jpeg_s_fmt(struct mxc_jpeg_ctx *ctx, static int mxc_jpeg_s_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *f) { - return mxc_jpeg_s_fmt(mxc_jpeg_fh_to_ctx(priv), f); + return mxc_jpeg_s_fmt(mxc_jpeg_file_to_ctx(file), f); } static int mxc_jpeg_s_fmt_vid_out(struct file *file, void *priv, struct v4l2_format *f) { int ret; - struct mxc_jpeg_ctx *ctx = mxc_jpeg_fh_to_ctx(priv); + struct mxc_jpeg_ctx *ctx = mxc_jpeg_file_to_ctx(file); struct vb2_queue *dst_vq; struct mxc_jpeg_q_data *q_data_cap; enum v4l2_buf_type cap_type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; struct v4l2_format fc; - ret = mxc_jpeg_s_fmt(mxc_jpeg_fh_to_ctx(priv), f); + ret = mxc_jpeg_s_fmt(ctx, f); if (ret) return ret; @@ -2550,7 +2549,7 @@ static int mxc_jpeg_s_fmt_vid_out(struct file *file, void *priv, static int mxc_jpeg_g_fmt_vid(struct file *file, void *priv, struct v4l2_format *f) { - struct mxc_jpeg_ctx *ctx = mxc_jpeg_fh_to_ctx(priv); + struct mxc_jpeg_ctx *ctx = mxc_jpeg_file_to_ctx(file); struct mxc_jpeg_dev *jpeg = ctx->mxc_jpeg; struct device *dev = jpeg->dev; struct v4l2_pix_format_mplane *pix_mp = &f->fmt.pix_mp; @@ -2588,7 +2587,7 @@ static int mxc_jpeg_g_fmt_vid(struct file *file, void *priv, static int mxc_jpeg_dec_g_selection(struct file *file, void *fh, struct v4l2_selection *s) { - struct mxc_jpeg_ctx *ctx = mxc_jpeg_fh_to_ctx(fh); + struct mxc_jpeg_ctx *ctx = mxc_jpeg_file_to_ctx(file); struct mxc_jpeg_q_data *q_data_cap; if (s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE && s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) @@ -2617,7 +2616,7 @@ static int mxc_jpeg_dec_g_selection(struct file *file, void *fh, struct v4l2_sel static int mxc_jpeg_enc_g_selection(struct file *file, void *fh, struct v4l2_selection *s) { - struct mxc_jpeg_ctx *ctx = mxc_jpeg_fh_to_ctx(fh); + struct mxc_jpeg_ctx *ctx = mxc_jpeg_file_to_ctx(file); struct mxc_jpeg_q_data *q_data_out; if (s->type != V4L2_BUF_TYPE_VIDEO_OUTPUT && s->type != V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) @@ -2645,7 +2644,7 @@ static int mxc_jpeg_enc_g_selection(struct file *file, void *fh, struct v4l2_sel static int mxc_jpeg_g_selection(struct file *file, void *fh, struct v4l2_selection *s) { - struct mxc_jpeg_ctx *ctx = mxc_jpeg_fh_to_ctx(fh); + struct mxc_jpeg_ctx *ctx = mxc_jpeg_file_to_ctx(file); if (ctx->mxc_jpeg->mode == MXC_JPEG_DECODE) return mxc_jpeg_dec_g_selection(file, fh, s); @@ -2655,7 +2654,7 @@ static int mxc_jpeg_g_selection(struct file *file, void *fh, struct v4l2_selecti static int mxc_jpeg_s_selection(struct file *file, void *fh, struct v4l2_selection *s) { - struct mxc_jpeg_ctx *ctx = mxc_jpeg_fh_to_ctx(fh); + struct mxc_jpeg_ctx *ctx = mxc_jpeg_file_to_ctx(file); struct mxc_jpeg_q_data *q_data_out; if (ctx->mxc_jpeg->mode != MXC_JPEG_ENCODE) @@ -2735,7 +2734,7 @@ static const struct v4l2_ioctl_ops mxc_jpeg_ioctl_ops = { static int mxc_jpeg_release(struct file *file) { struct mxc_jpeg_dev *mxc_jpeg = video_drvdata(file); - struct mxc_jpeg_ctx *ctx = mxc_jpeg_fh_to_ctx(file->private_data); + struct mxc_jpeg_ctx *ctx = mxc_jpeg_file_to_ctx(file); struct device *dev = mxc_jpeg->dev; mutex_lock(&mxc_jpeg->lock); @@ -2747,7 +2746,7 @@ static int mxc_jpeg_release(struct file *file) ctx->slot); v4l2_ctrl_handler_free(&ctx->ctrl_handler); v4l2_m2m_ctx_release(ctx->fh.m2m_ctx); - v4l2_fh_del(&ctx->fh); + v4l2_fh_del(&ctx->fh, file); v4l2_fh_exit(&ctx->fh); kfree(ctx); mutex_unlock(&mxc_jpeg->lock); diff --git a/drivers/media/platform/nxp/imx-mipi-csis.c b/drivers/media/platform/nxp/imx-mipi-csis.c index 2beb5f43c2c0..d5de7854f579 100644 --- a/drivers/media/platform/nxp/imx-mipi-csis.c +++ b/drivers/media/platform/nxp/imx-mipi-csis.c @@ -54,23 +54,19 @@ /* CSIS common control */ #define MIPI_CSIS_CMN_CTRL 0x04 -#define MIPI_CSIS_CMN_CTRL_UPDATE_SHADOW BIT(16) -#define MIPI_CSIS_CMN_CTRL_INTER_MODE BIT(10) +#define MIPI_CSIS_CMN_CTRL_UPDATE_SHADOW(n) BIT((n) + 16) +#define MIPI_CSIS_CMN_CTRL_INTERLEAVE_MODE_DT BIT(10) +#define MIPI_CSIS_CMN_CTRL_LANE_NUMBER(n) ((n) << 8) +#define MIPI_CSIS_CMN_CTRL_LANE_NUMBER_MASK GENMASK(9, 8) #define MIPI_CSIS_CMN_CTRL_UPDATE_SHADOW_CTRL BIT(2) -#define MIPI_CSIS_CMN_CTRL_RESET BIT(1) -#define MIPI_CSIS_CMN_CTRL_ENABLE BIT(0) - -#define MIPI_CSIS_CMN_CTRL_LANE_NR_OFFSET 8 -#define MIPI_CSIS_CMN_CTRL_LANE_NR_MASK (3 << 8) +#define MIPI_CSIS_CMN_CTRL_SW_RESET BIT(1) +#define MIPI_CSIS_CMN_CTRL_CSI_EN BIT(0) /* CSIS clock control */ #define MIPI_CSIS_CLK_CTRL 0x08 -#define MIPI_CSIS_CLK_CTRL_CLKGATE_TRAIL_CH3(x) ((x) << 28) -#define MIPI_CSIS_CLK_CTRL_CLKGATE_TRAIL_CH2(x) ((x) << 24) -#define MIPI_CSIS_CLK_CTRL_CLKGATE_TRAIL_CH1(x) ((x) << 20) -#define MIPI_CSIS_CLK_CTRL_CLKGATE_TRAIL_CH0(x) ((x) << 16) -#define MIPI_CSIS_CLK_CTRL_CLKGATE_EN_MSK (0xf << 4) -#define MIPI_CSIS_CLK_CTRL_WCLK_SRC BIT(0) +#define MIPI_CSIS_CLK_CTRL_CLKGATE_TRAIL(n, x) ((x) << ((n) * 4 + 16)) +#define MIPI_CSIS_CLK_CTRL_CLKGATE_EN_MASK GENMASK(7, 4) +#define MIPI_CSIS_CLK_CTRL_WCLK_SRC(n) BIT(n) /* CSIS Interrupt mask */ #define MIPI_CSIS_INT_MSK 0x10 @@ -87,7 +83,7 @@ #define MIPI_CSIS_INT_MSK_ERR_WRONG_CFG BIT(3) #define MIPI_CSIS_INT_MSK_ERR_ECC BIT(2) #define MIPI_CSIS_INT_MSK_ERR_CRC BIT(1) -#define MIPI_CSIS_INT_MSK_ERR_UNKNOWN BIT(0) +#define MIPI_CSIS_INT_MSK_ERR_ID BIT(0) /* CSIS Interrupt source */ #define MIPI_CSIS_INT_SRC 0x14 @@ -98,16 +94,16 @@ #define MIPI_CSIS_INT_SRC_ODD_AFTER BIT(28) #define MIPI_CSIS_INT_SRC_ODD (0x3 << 28) #define MIPI_CSIS_INT_SRC_NON_IMAGE_DATA (0xf << 28) -#define MIPI_CSIS_INT_SRC_FRAME_START BIT(24) -#define MIPI_CSIS_INT_SRC_FRAME_END BIT(20) -#define MIPI_CSIS_INT_SRC_ERR_SOT_HS BIT(16) -#define MIPI_CSIS_INT_SRC_ERR_LOST_FS BIT(12) -#define MIPI_CSIS_INT_SRC_ERR_LOST_FE BIT(8) -#define MIPI_CSIS_INT_SRC_ERR_OVER BIT(4) +#define MIPI_CSIS_INT_SRC_FRAME_START(n) BIT((n) + 24) +#define MIPI_CSIS_INT_SRC_FRAME_END(n) BIT((n) + 20) +#define MIPI_CSIS_INT_SRC_ERR_SOT_HS(n) BIT((n) + 16) +#define MIPI_CSIS_INT_SRC_ERR_LOST_FS(n) BIT((n) + 12) +#define MIPI_CSIS_INT_SRC_ERR_LOST_FE(n) BIT((n) + 8) +#define MIPI_CSIS_INT_SRC_ERR_OVER(n) BIT((n) + 4) #define MIPI_CSIS_INT_SRC_ERR_WRONG_CFG BIT(3) #define MIPI_CSIS_INT_SRC_ERR_ECC BIT(2) #define MIPI_CSIS_INT_SRC_ERR_CRC BIT(1) -#define MIPI_CSIS_INT_SRC_ERR_UNKNOWN BIT(0) +#define MIPI_CSIS_INT_SRC_ERR_ID BIT(0) #define MIPI_CSIS_INT_SRC_ERRORS 0xfffff /* D-PHY status control */ @@ -123,8 +119,8 @@ #define MIPI_CSIS_DPHY_CMN_CTRL_HSSETTLE_MASK GENMASK(31, 24) #define MIPI_CSIS_DPHY_CMN_CTRL_CLKSETTLE(n) ((n) << 22) #define MIPI_CSIS_DPHY_CMN_CTRL_CLKSETTLE_MASK GENMASK(23, 22) -#define MIPI_CSIS_DPHY_CMN_CTRL_DPDN_SWAP_CLK BIT(6) -#define MIPI_CSIS_DPHY_CMN_CTRL_DPDN_SWAP_DAT BIT(5) +#define MIPI_CSIS_DPHY_CMN_CTRL_S_DPDN_SWAP_CLK BIT(6) +#define MIPI_CSIS_DPHY_CMN_CTRL_S_DPDN_SWAP_DAT BIT(5) #define MIPI_CSIS_DPHY_CMN_CTRL_ENABLE_DAT BIT(1) #define MIPI_CSIS_DPHY_CMN_CTRL_ENABLE_CLK BIT(0) #define MIPI_CSIS_DPHY_CMN_CTRL_ENABLE (0x1f << 0) @@ -174,26 +170,28 @@ /* ISP Configuration register */ #define MIPI_CSIS_ISP_CONFIG_CH(n) (0x40 + (n) * 0x10) -#define MIPI_CSIS_ISPCFG_MEM_FULL_GAP_MSK (0xff << 24) +#define MIPI_CSIS_ISPCFG_MEM_FULL_GAP_MASK GENMASK(31, 24) #define MIPI_CSIS_ISPCFG_MEM_FULL_GAP(x) ((x) << 24) #define MIPI_CSIS_ISPCFG_PIXEL_MODE_SINGLE (0 << 12) #define MIPI_CSIS_ISPCFG_PIXEL_MODE_DUAL (1 << 12) #define MIPI_CSIS_ISPCFG_PIXEL_MODE_QUAD (2 << 12) /* i.MX8M[MNP] only */ -#define MIPI_CSIS_ISPCFG_PIXEL_MASK (3 << 12) -#define MIPI_CSIS_ISPCFG_ALIGN_32BIT BIT(11) -#define MIPI_CSIS_ISPCFG_FMT(fmt) ((fmt) << 2) -#define MIPI_CSIS_ISPCFG_FMT_MASK (0x3f << 2) +#define MIPI_CSIS_ISPCFG_PIXEL_MODE_MASK GENMASK(13, 12) +#define MIPI_CSIS_ISPCFG_PARALLEL BIT(11) +#define MIPI_CSIS_ISPCFG_DATAFORMAT(fmt) ((fmt) << 2) +#define MIPI_CSIS_ISPCFG_DATAFORMAT_MASK GENMASK(7, 2) /* ISP Image Resolution register */ #define MIPI_CSIS_ISP_RESOL_CH(n) (0x44 + (n) * 0x10) +#define MIPI_CSIS_ISP_RESOL_VRESOL(n) ((n) << 16) +#define MIPI_CSIS_ISP_RESOL_HRESOL(n) ((n) << 0) #define CSIS_MAX_PIX_WIDTH 0xffff #define CSIS_MAX_PIX_HEIGHT 0xffff /* ISP SYNC register */ #define MIPI_CSIS_ISP_SYNC_CH(n) (0x48 + (n) * 0x10) -#define MIPI_CSIS_ISP_SYNC_HSYNC_LINTV_OFFSET 18 -#define MIPI_CSIS_ISP_SYNC_VSYNC_SINTV_OFFSET 12 -#define MIPI_CSIS_ISP_SYNC_VSYNC_EINTV_OFFSET 0 +#define MIPI_CSIS_ISP_SYNC_HSYNC_LINTV(n) ((n) << 18) +#define MIPI_CSIS_ISP_SYNC_VSYNC_SINTV(n) ((n) << 12) +#define MIPI_CSIS_ISP_SYNC_VSYNC_EINTV(n) ((n) << 0) /* ISP shadow registers */ #define MIPI_CSIS_SDW_CONFIG_CH(n) (0x80 + (n) * 0x10) @@ -203,23 +201,23 @@ /* Debug control register */ #define MIPI_CSIS_DBG_CTRL 0xc0 #define MIPI_CSIS_DBG_INTR_MSK 0xc4 -#define MIPI_CSIS_DBG_INTR_MSK_DT_NOT_SUPPORT BIT(25) -#define MIPI_CSIS_DBG_INTR_MSK_DT_IGNORE BIT(24) -#define MIPI_CSIS_DBG_INTR_MSK_ERR_FRAME_SIZE BIT(20) -#define MIPI_CSIS_DBG_INTR_MSK_TRUNCATED_FRAME BIT(16) -#define MIPI_CSIS_DBG_INTR_MSK_EARLY_FE BIT(12) -#define MIPI_CSIS_DBG_INTR_MSK_EARLY_FS BIT(8) -#define MIPI_CSIS_DBG_INTR_MSK_CAM_VSYNC_FALL BIT(4) -#define MIPI_CSIS_DBG_INTR_MSK_CAM_VSYNC_RISE BIT(0) +#define MIPI_CSIS_DBG_INTR_MSK_DT_NOT_SUPPORT BIT(25) +#define MIPI_CSIS_DBG_INTR_MSK_DT_IGNORE BIT(24) +#define MIPI_CSIS_DBG_INTR_MSK_ERR_FRAME_SIZE(n) BIT((n) + 20) +#define MIPI_CSIS_DBG_INTR_MSK_TRUNCATED_FRAME(n) BIT((n) + 16) +#define MIPI_CSIS_DBG_INTR_MSK_EARLY_FE(n) BIT((n) + 12) +#define MIPI_CSIS_DBG_INTR_MSK_EARLY_FS(n) BIT((n) + 8) +#define MIPI_CSIS_DBG_INTR_MSK_CAM_VSYNC_FALL(n) BIT((n) + 4) +#define MIPI_CSIS_DBG_INTR_MSK_CAM_VSYNC_RISE(n) BIT((n) + 0) #define MIPI_CSIS_DBG_INTR_SRC 0xc8 -#define MIPI_CSIS_DBG_INTR_SRC_DT_NOT_SUPPORT BIT(25) -#define MIPI_CSIS_DBG_INTR_SRC_DT_IGNORE BIT(24) -#define MIPI_CSIS_DBG_INTR_SRC_ERR_FRAME_SIZE BIT(20) -#define MIPI_CSIS_DBG_INTR_SRC_TRUNCATED_FRAME BIT(16) -#define MIPI_CSIS_DBG_INTR_SRC_EARLY_FE BIT(12) -#define MIPI_CSIS_DBG_INTR_SRC_EARLY_FS BIT(8) -#define MIPI_CSIS_DBG_INTR_SRC_CAM_VSYNC_FALL BIT(4) -#define MIPI_CSIS_DBG_INTR_SRC_CAM_VSYNC_RISE BIT(0) +#define MIPI_CSIS_DBG_INTR_SRC_DT_NOT_SUPPORT BIT(25) +#define MIPI_CSIS_DBG_INTR_SRC_DT_IGNORE BIT(24) +#define MIPI_CSIS_DBG_INTR_SRC_ERR_FRAME_SIZE(n) BIT((n) + 20) +#define MIPI_CSIS_DBG_INTR_SRC_TRUNCATED_FRAME(n) BIT((n) + 16) +#define MIPI_CSIS_DBG_INTR_SRC_EARLY_FE(n) BIT((n) + 12) +#define MIPI_CSIS_DBG_INTR_SRC_EARLY_FS(n) BIT((n) + 8) +#define MIPI_CSIS_DBG_INTR_SRC_CAM_VSYNC_FALL(n) BIT((n) + 4) +#define MIPI_CSIS_DBG_INTR_SRC_CAM_VSYNC_RISE(n) BIT((n) + 0) #define MIPI_CSIS_FRAME_COUNTER_CH(n) (0x0100 + (n) * 4) @@ -228,10 +226,11 @@ #define MIPI_CSIS_PKTDATA_EVEN 0x3000 #define MIPI_CSIS_PKTDATA_SIZE SZ_4K -#define DEFAULT_SCLK_CSIS_FREQ 166000000UL +#define MIPI_CSIS_MAX_CHANNELS 4 struct mipi_csis_event { bool debug; + unsigned int channel; u32 mask; const char * const name; unsigned int counter; @@ -239,33 +238,70 @@ struct mipi_csis_event { static const struct mipi_csis_event mipi_csis_events[] = { /* Errors */ - { false, MIPI_CSIS_INT_SRC_ERR_SOT_HS, "SOT Error" }, - { false, MIPI_CSIS_INT_SRC_ERR_LOST_FS, "Lost Frame Start Error" }, - { false, MIPI_CSIS_INT_SRC_ERR_LOST_FE, "Lost Frame End Error" }, - { false, MIPI_CSIS_INT_SRC_ERR_OVER, "FIFO Overflow Error" }, - { false, MIPI_CSIS_INT_SRC_ERR_WRONG_CFG, "Wrong Configuration Error" }, - { false, MIPI_CSIS_INT_SRC_ERR_ECC, "ECC Error" }, - { false, MIPI_CSIS_INT_SRC_ERR_CRC, "CRC Error" }, - { false, MIPI_CSIS_INT_SRC_ERR_UNKNOWN, "Unknown Error" }, - { true, MIPI_CSIS_DBG_INTR_SRC_DT_NOT_SUPPORT, "Data Type Not Supported" }, - { true, MIPI_CSIS_DBG_INTR_SRC_DT_IGNORE, "Data Type Ignored" }, - { true, MIPI_CSIS_DBG_INTR_SRC_ERR_FRAME_SIZE, "Frame Size Error" }, - { true, MIPI_CSIS_DBG_INTR_SRC_TRUNCATED_FRAME, "Truncated Frame" }, - { true, MIPI_CSIS_DBG_INTR_SRC_EARLY_FE, "Early Frame End" }, - { true, MIPI_CSIS_DBG_INTR_SRC_EARLY_FS, "Early Frame Start" }, + { false, 0, MIPI_CSIS_INT_SRC_ERR_SOT_HS(0), "SOT 0 Error" }, + { false, 0, MIPI_CSIS_INT_SRC_ERR_SOT_HS(1), "SOT 1 Error" }, + { false, 0, MIPI_CSIS_INT_SRC_ERR_SOT_HS(2), "SOT 2 Error" }, + { false, 0, MIPI_CSIS_INT_SRC_ERR_SOT_HS(3), "SOT 3 Error" }, + { false, 0, MIPI_CSIS_INT_SRC_ERR_LOST_FS(0), "Lost Frame Start Error 0" }, + { false, 1, MIPI_CSIS_INT_SRC_ERR_LOST_FS(1), "Lost Frame Start Error 1" }, + { false, 2, MIPI_CSIS_INT_SRC_ERR_LOST_FS(2), "Lost Frame Start Error 2" }, + { false, 3, MIPI_CSIS_INT_SRC_ERR_LOST_FS(3), "Lost Frame Start Error 3" }, + { false, 0, MIPI_CSIS_INT_SRC_ERR_LOST_FE(0), "Lost Frame End Error 0" }, + { false, 1, MIPI_CSIS_INT_SRC_ERR_LOST_FE(1), "Lost Frame End Error 1" }, + { false, 2, MIPI_CSIS_INT_SRC_ERR_LOST_FE(2), "Lost Frame End Error 2" }, + { false, 3, MIPI_CSIS_INT_SRC_ERR_LOST_FE(3), "Lost Frame End Error 3" }, + { false, 0, MIPI_CSIS_INT_SRC_ERR_OVER(0), "FIFO Overflow Error 0" }, + { false, 1, MIPI_CSIS_INT_SRC_ERR_OVER(1), "FIFO Overflow Error 1" }, + { false, 2, MIPI_CSIS_INT_SRC_ERR_OVER(2), "FIFO Overflow Error 2" }, + { false, 3, MIPI_CSIS_INT_SRC_ERR_OVER(3), "FIFO Overflow Error 3" }, + { false, 0, MIPI_CSIS_INT_SRC_ERR_WRONG_CFG, "Wrong Configuration Error" }, + { false, 0, MIPI_CSIS_INT_SRC_ERR_ECC, "ECC Error" }, + { false, 0, MIPI_CSIS_INT_SRC_ERR_CRC, "CRC Error" }, + { false, 0, MIPI_CSIS_INT_SRC_ERR_ID, "Unknown ID Error" }, + { true, 0, MIPI_CSIS_DBG_INTR_SRC_DT_NOT_SUPPORT, "Data Type Not Supported" }, + { true, 0, MIPI_CSIS_DBG_INTR_SRC_DT_IGNORE, "Data Type Ignored" }, + { true, 0, MIPI_CSIS_DBG_INTR_SRC_ERR_FRAME_SIZE(0), "Frame Size Error 0" }, + { true, 1, MIPI_CSIS_DBG_INTR_SRC_ERR_FRAME_SIZE(1), "Frame Size Error 1" }, + { true, 2, MIPI_CSIS_DBG_INTR_SRC_ERR_FRAME_SIZE(2), "Frame Size Error 2" }, + { true, 3, MIPI_CSIS_DBG_INTR_SRC_ERR_FRAME_SIZE(3), "Frame Size Error 3" }, + { true, 0, MIPI_CSIS_DBG_INTR_SRC_TRUNCATED_FRAME(0), "Truncated Frame 0" }, + { true, 1, MIPI_CSIS_DBG_INTR_SRC_TRUNCATED_FRAME(1), "Truncated Frame 1" }, + { true, 2, MIPI_CSIS_DBG_INTR_SRC_TRUNCATED_FRAME(2), "Truncated Frame 2" }, + { true, 3, MIPI_CSIS_DBG_INTR_SRC_TRUNCATED_FRAME(3), "Truncated Frame 3" }, + { true, 0, MIPI_CSIS_DBG_INTR_SRC_EARLY_FE(0), "Early Frame End 0" }, + { true, 1, MIPI_CSIS_DBG_INTR_SRC_EARLY_FE(1), "Early Frame End 1" }, + { true, 2, MIPI_CSIS_DBG_INTR_SRC_EARLY_FE(2), "Early Frame End 2" }, + { true, 3, MIPI_CSIS_DBG_INTR_SRC_EARLY_FE(3), "Early Frame End 3" }, + { true, 0, MIPI_CSIS_DBG_INTR_SRC_EARLY_FS(0), "Early Frame Start 0" }, + { true, 1, MIPI_CSIS_DBG_INTR_SRC_EARLY_FS(1), "Early Frame Start 1" }, + { true, 2, MIPI_CSIS_DBG_INTR_SRC_EARLY_FS(2), "Early Frame Start 2" }, + { true, 3, MIPI_CSIS_DBG_INTR_SRC_EARLY_FS(3), "Early Frame Start 3" }, /* Non-image data receive events */ - { false, MIPI_CSIS_INT_SRC_EVEN_BEFORE, "Non-image data before even frame" }, - { false, MIPI_CSIS_INT_SRC_EVEN_AFTER, "Non-image data after even frame" }, - { false, MIPI_CSIS_INT_SRC_ODD_BEFORE, "Non-image data before odd frame" }, - { false, MIPI_CSIS_INT_SRC_ODD_AFTER, "Non-image data after odd frame" }, + { false, 0, MIPI_CSIS_INT_SRC_EVEN_BEFORE, "Non-image data before even frame" }, + { false, 0, MIPI_CSIS_INT_SRC_EVEN_AFTER, "Non-image data after even frame" }, + { false, 0, MIPI_CSIS_INT_SRC_ODD_BEFORE, "Non-image data before odd frame" }, + { false, 0, MIPI_CSIS_INT_SRC_ODD_AFTER, "Non-image data after odd frame" }, /* Frame start/end */ - { false, MIPI_CSIS_INT_SRC_FRAME_START, "Frame Start" }, - { false, MIPI_CSIS_INT_SRC_FRAME_END, "Frame End" }, - { true, MIPI_CSIS_DBG_INTR_SRC_CAM_VSYNC_FALL, "VSYNC Falling Edge" }, - { true, MIPI_CSIS_DBG_INTR_SRC_CAM_VSYNC_RISE, "VSYNC Rising Edge" }, + { false, 0, MIPI_CSIS_INT_SRC_FRAME_START(0), "Frame Start 0" }, + { false, 1, MIPI_CSIS_INT_SRC_FRAME_START(1), "Frame Start 1" }, + { false, 2, MIPI_CSIS_INT_SRC_FRAME_START(2), "Frame Start 2" }, + { false, 3, MIPI_CSIS_INT_SRC_FRAME_START(3), "Frame Start 3" }, + { false, 0, MIPI_CSIS_INT_SRC_FRAME_END(0), "Frame End 0" }, + { false, 1, MIPI_CSIS_INT_SRC_FRAME_END(1), "Frame End 1" }, + { false, 2, MIPI_CSIS_INT_SRC_FRAME_END(2), "Frame End 2" }, + { false, 3, MIPI_CSIS_INT_SRC_FRAME_END(3), "Frame End 3" }, + { true, 0, MIPI_CSIS_DBG_INTR_SRC_CAM_VSYNC_FALL(0), "VSYNC Falling Edge 0" }, + { true, 1, MIPI_CSIS_DBG_INTR_SRC_CAM_VSYNC_FALL(1), "VSYNC Falling Edge 1" }, + { true, 2, MIPI_CSIS_DBG_INTR_SRC_CAM_VSYNC_FALL(2), "VSYNC Falling Edge 2" }, + { true, 3, MIPI_CSIS_DBG_INTR_SRC_CAM_VSYNC_FALL(3), "VSYNC Falling Edge 3" }, + { true, 0, MIPI_CSIS_DBG_INTR_SRC_CAM_VSYNC_RISE(0), "VSYNC Rising Edge 0" }, + { true, 1, MIPI_CSIS_DBG_INTR_SRC_CAM_VSYNC_RISE(1), "VSYNC Rising Edge 1" }, + { true, 2, MIPI_CSIS_DBG_INTR_SRC_CAM_VSYNC_RISE(2), "VSYNC Rising Edge 2" }, + { true, 3, MIPI_CSIS_DBG_INTR_SRC_CAM_VSYNC_RISE(3), "VSYNC Rising Edge 3" }, }; -#define MIPI_CSIS_NUM_EVENTS ARRAY_SIZE(mipi_csis_events) +#define MIPI_CSIS_NUM_EVENTS ARRAY_SIZE(mipi_csis_events) +#define MIPI_CSIS_NUM_ERROR_EVENTS 38 enum mipi_csis_clk { MIPI_CSIS_CLK_PCLK, @@ -297,7 +333,9 @@ struct mipi_csis_device { struct clk_bulk_data *clks; struct reset_control *mrst; struct regulator *mipi_phy_regulator; + const struct mipi_csis_info *info; + unsigned int num_channels; struct v4l2_subdev sd; struct media_pad pads[CSIS_PADS_NUM]; @@ -517,7 +555,7 @@ static void mipi_csis_sw_reset(struct mipi_csis_device *csis) u32 val = mipi_csis_read(csis, MIPI_CSIS_CMN_CTRL); mipi_csis_write(csis, MIPI_CSIS_CMN_CTRL, - val | MIPI_CSIS_CMN_CTRL_RESET); + val | MIPI_CSIS_CMN_CTRL_SW_RESET); usleep_range(10, 20); } @@ -527,9 +565,9 @@ static void mipi_csis_system_enable(struct mipi_csis_device *csis, int on) val = mipi_csis_read(csis, MIPI_CSIS_CMN_CTRL); if (on) - val |= MIPI_CSIS_CMN_CTRL_ENABLE; + val |= MIPI_CSIS_CMN_CTRL_CSI_EN; else - val &= ~MIPI_CSIS_CMN_CTRL_ENABLE; + val &= ~MIPI_CSIS_CMN_CTRL_CSI_EN; mipi_csis_write(csis, MIPI_CSIS_CMN_CTRL, val); val = mipi_csis_read(csis, MIPI_CSIS_DPHY_CMN_CTRL); @@ -549,8 +587,8 @@ static void __mipi_csis_set_format(struct mipi_csis_device *csis, /* Color format */ val = mipi_csis_read(csis, MIPI_CSIS_ISP_CONFIG_CH(0)); - val &= ~(MIPI_CSIS_ISPCFG_ALIGN_32BIT | MIPI_CSIS_ISPCFG_FMT_MASK - | MIPI_CSIS_ISPCFG_PIXEL_MASK); + val &= ~(MIPI_CSIS_ISPCFG_PARALLEL | MIPI_CSIS_ISPCFG_PIXEL_MODE_MASK | + MIPI_CSIS_ISPCFG_DATAFORMAT_MASK); /* * YUV 4:2:2 can be transferred with 8 or 16 bits per clock sample @@ -568,24 +606,23 @@ static void __mipi_csis_set_format(struct mipi_csis_device *csis, if (csis_fmt->data_type == MIPI_CSI2_DT_YUV422_8B) val |= MIPI_CSIS_ISPCFG_PIXEL_MODE_DUAL; - val |= MIPI_CSIS_ISPCFG_FMT(csis_fmt->data_type); + val |= MIPI_CSIS_ISPCFG_DATAFORMAT(csis_fmt->data_type); mipi_csis_write(csis, MIPI_CSIS_ISP_CONFIG_CH(0), val); /* Pixel resolution */ - val = format->width | (format->height << 16); - mipi_csis_write(csis, MIPI_CSIS_ISP_RESOL_CH(0), val); + mipi_csis_write(csis, MIPI_CSIS_ISP_RESOL_CH(0), + MIPI_CSIS_ISP_RESOL_VRESOL(format->height) | + MIPI_CSIS_ISP_RESOL_HRESOL(format->width)); } static int mipi_csis_calculate_params(struct mipi_csis_device *csis, const struct csis_pix_format *csis_fmt) { - struct media_pad *src_pad = - &csis->source.sd->entity.pads[csis->source.pad->index]; s64 link_freq; u32 lane_rate; /* Calculate the line rate from the pixel rate. */ - link_freq = v4l2_get_link_freq(src_pad, csis_fmt->width, + link_freq = v4l2_get_link_freq(csis->source.pad, csis_fmt->width, csis->bus.num_data_lanes * 2); if (link_freq < 0) { dev_err(csis->dev, "Unable to obtain link frequency: %d\n", @@ -635,10 +672,10 @@ static void mipi_csis_set_params(struct mipi_csis_device *csis, u32 val; val = mipi_csis_read(csis, MIPI_CSIS_CMN_CTRL); - val &= ~MIPI_CSIS_CMN_CTRL_LANE_NR_MASK; - val |= (lanes - 1) << MIPI_CSIS_CMN_CTRL_LANE_NR_OFFSET; + val &= ~MIPI_CSIS_CMN_CTRL_LANE_NUMBER_MASK; + val |= MIPI_CSIS_CMN_CTRL_LANE_NUMBER(lanes - 1); if (csis->info->version == MIPI_CSIS_V3_3) - val |= MIPI_CSIS_CMN_CTRL_INTER_MODE; + val |= MIPI_CSIS_CMN_CTRL_INTERLEAVE_MODE_DT; mipi_csis_write(csis, MIPI_CSIS_CMN_CTRL, val); __mipi_csis_set_format(csis, format, csis_fmt); @@ -647,15 +684,15 @@ static void mipi_csis_set_params(struct mipi_csis_device *csis, MIPI_CSIS_DPHY_CMN_CTRL_HSSETTLE(csis->hs_settle) | MIPI_CSIS_DPHY_CMN_CTRL_CLKSETTLE(csis->clk_settle)); - val = (0 << MIPI_CSIS_ISP_SYNC_HSYNC_LINTV_OFFSET) - | (0 << MIPI_CSIS_ISP_SYNC_VSYNC_SINTV_OFFSET) - | (0 << MIPI_CSIS_ISP_SYNC_VSYNC_EINTV_OFFSET); - mipi_csis_write(csis, MIPI_CSIS_ISP_SYNC_CH(0), val); + mipi_csis_write(csis, MIPI_CSIS_ISP_SYNC_CH(0), + MIPI_CSIS_ISP_SYNC_HSYNC_LINTV(0) | + MIPI_CSIS_ISP_SYNC_VSYNC_SINTV(0) | + MIPI_CSIS_ISP_SYNC_VSYNC_EINTV(0)); val = mipi_csis_read(csis, MIPI_CSIS_CLK_CTRL); - val |= MIPI_CSIS_CLK_CTRL_WCLK_SRC; - val |= MIPI_CSIS_CLK_CTRL_CLKGATE_TRAIL_CH0(15); - val &= ~MIPI_CSIS_CLK_CTRL_CLKGATE_EN_MSK; + val |= MIPI_CSIS_CLK_CTRL_WCLK_SRC(0); + val |= MIPI_CSIS_CLK_CTRL_CLKGATE_TRAIL(0, 15); + val &= ~MIPI_CSIS_CLK_CTRL_CLKGATE_EN_MASK; mipi_csis_write(csis, MIPI_CSIS_CLK_CTRL, val); mipi_csis_write(csis, MIPI_CSIS_DPHY_BCTRL_L, @@ -671,7 +708,7 @@ static void mipi_csis_set_params(struct mipi_csis_device *csis, /* Update the shadow register. */ val = mipi_csis_read(csis, MIPI_CSIS_CMN_CTRL); mipi_csis_write(csis, MIPI_CSIS_CMN_CTRL, - val | MIPI_CSIS_CMN_CTRL_UPDATE_SHADOW | + val | MIPI_CSIS_CMN_CTRL_UPDATE_SHADOW(0) | MIPI_CSIS_CMN_CTRL_UPDATE_SHADOW_CTRL); } @@ -704,12 +741,17 @@ static int mipi_csis_clk_get(struct mipi_csis_device *csis) if (ret < 0) return ret; - /* Set clock rate */ - ret = clk_set_rate(csis->clks[MIPI_CSIS_CLK_WRAP].clk, - csis->clk_frequency); - if (ret < 0) - dev_err(csis->dev, "set rate=%d failed: %d\n", - csis->clk_frequency, ret); + if (csis->clk_frequency) { + /* + * Set the clock rate. This is deprecated, for backward + * compatibility with old device trees. + */ + ret = clk_set_rate(csis->clks[MIPI_CSIS_CLK_WRAP].clk, + csis->clk_frequency); + if (ret < 0) + dev_err(csis->dev, "set rate=%d failed: %d\n", + csis->clk_frequency, ret); + } return ret; } @@ -757,16 +799,19 @@ static irqreturn_t mipi_csis_irq_handler(int irq, void *dev_id) /* Update the event/error counters */ if ((status & MIPI_CSIS_INT_SRC_ERRORS) || csis->debug.enable) { - for (i = 0; i < MIPI_CSIS_NUM_EVENTS; i++) { + for (i = 0; i < ARRAY_SIZE(csis->events); i++) { struct mipi_csis_event *event = &csis->events[i]; + if (event->channel >= csis->num_channels) + continue; + if ((!event->debug && (status & event->mask)) || (event->debug && (dbg_status & event->mask))) event->counter++; } } - if (status & MIPI_CSIS_INT_SRC_FRAME_START) + if (status & MIPI_CSIS_INT_SRC_FRAME_START(0)) mipi_csis_queue_event_sof(csis); spin_unlock_irqrestore(&csis->slock, flags); @@ -843,7 +888,7 @@ static void mipi_csis_clear_counters(struct mipi_csis_device *csis) static void mipi_csis_log_counters(struct mipi_csis_device *csis, bool non_errors) { unsigned int num_events = non_errors ? MIPI_CSIS_NUM_EVENTS - : MIPI_CSIS_NUM_EVENTS - 8; + : MIPI_CSIS_NUM_ERROR_EVENTS; unsigned int counters[MIPI_CSIS_NUM_EVENTS]; unsigned long flags; unsigned int i; @@ -854,45 +899,67 @@ static void mipi_csis_log_counters(struct mipi_csis_device *csis, bool non_error spin_unlock_irqrestore(&csis->slock, flags); for (i = 0; i < num_events; ++i) { + const struct mipi_csis_event *event = &csis->events[i]; + + if (event->channel >= csis->num_channels) + continue; + if (counters[i] > 0 || csis->debug.enable) dev_info(csis->dev, "%s events: %d\n", - csis->events[i].name, - counters[i]); + event->name, counters[i]); } } +struct mipi_csis_reg_info { + u32 addr; + unsigned int offset; + const char * const name; +}; + +static void mipi_csis_dump_channel_reg(struct mipi_csis_device *csis, + const struct mipi_csis_reg_info *reg, + unsigned int channel) +{ + dev_info(csis->dev, "%16s%u: 0x%08x\n", reg->name, channel, + mipi_csis_read(csis, reg->addr + channel * reg->offset)); +} + static int mipi_csis_dump_regs(struct mipi_csis_device *csis) { - static const struct { - u32 offset; - const char * const name; - } registers[] = { - { MIPI_CSIS_CMN_CTRL, "CMN_CTRL" }, - { MIPI_CSIS_CLK_CTRL, "CLK_CTRL" }, - { MIPI_CSIS_INT_MSK, "INT_MSK" }, - { MIPI_CSIS_DPHY_STATUS, "DPHY_STATUS" }, - { MIPI_CSIS_DPHY_CMN_CTRL, "DPHY_CMN_CTRL" }, - { MIPI_CSIS_DPHY_SCTRL_L, "DPHY_SCTRL_L" }, - { MIPI_CSIS_DPHY_SCTRL_H, "DPHY_SCTRL_H" }, - { MIPI_CSIS_ISP_CONFIG_CH(0), "ISP_CONFIG_CH0" }, - { MIPI_CSIS_ISP_RESOL_CH(0), "ISP_RESOL_CH0" }, - { MIPI_CSIS_SDW_CONFIG_CH(0), "SDW_CONFIG_CH0" }, - { MIPI_CSIS_SDW_RESOL_CH(0), "SDW_RESOL_CH0" }, - { MIPI_CSIS_DBG_CTRL, "DBG_CTRL" }, - { MIPI_CSIS_FRAME_COUNTER_CH(0), "FRAME_COUNTER_CH0" }, + static const struct mipi_csis_reg_info common_registers[] = { + { MIPI_CSIS_CMN_CTRL, 0, "CMN_CTRL" }, + { MIPI_CSIS_CLK_CTRL, 0, "CLK_CTRL" }, + { MIPI_CSIS_INT_MSK, 0, "INT_MSK" }, + { MIPI_CSIS_DPHY_STATUS, 0, "DPHY_STATUS" }, + { MIPI_CSIS_DPHY_CMN_CTRL, 0, "DPHY_CMN_CTRL" }, + { MIPI_CSIS_DPHY_SCTRL_L, 0, "DPHY_SCTRL_L" }, + { MIPI_CSIS_DPHY_SCTRL_H, 0, "DPHY_SCTRL_H" }, + { MIPI_CSIS_DBG_CTRL, 0, "DBG_CTRL" }, + }; + static const struct mipi_csis_reg_info channel_registers[] = { + { MIPI_CSIS_ISP_CONFIG_CH(0), 0x10, "ISP_CONFIG_CH" }, + { MIPI_CSIS_ISP_RESOL_CH(0), 0x10, "ISP_RESOL_CH" }, + { MIPI_CSIS_SDW_CONFIG_CH(0), 0x10, "SDW_CONFIG_CH" }, + { MIPI_CSIS_SDW_RESOL_CH(0), 0x10, "SDW_RESOL_CH" }, + { MIPI_CSIS_FRAME_COUNTER_CH(0), 4, "FRAME_COUNTER_CH" }, }; - - unsigned int i; - u32 cfg; if (!pm_runtime_get_if_in_use(csis->dev)) return 0; dev_info(csis->dev, "--- REGISTERS ---\n"); - for (i = 0; i < ARRAY_SIZE(registers); i++) { - cfg = mipi_csis_read(csis, registers[i].offset); - dev_info(csis->dev, "%14s: 0x%08x\n", registers[i].name, cfg); + for (unsigned int i = 0; i < ARRAY_SIZE(common_registers); i++) { + const struct mipi_csis_reg_info *reg = &common_registers[i]; + + dev_info(csis->dev, "%17s: 0x%08x\n", reg->name, + mipi_csis_read(csis, reg->addr)); + } + + for (unsigned int chan = 0; chan < csis->num_channels; chan++) { + for (unsigned int i = 0; i < ARRAY_SIZE(channel_registers); ++i) + mipi_csis_dump_channel_reg(csis, &channel_registers[i], + chan); } pm_runtime_put(csis->dev); @@ -998,7 +1065,7 @@ err_unlock: } static int mipi_csis_enum_mbus_code(struct v4l2_subdev *sd, - struct v4l2_subdev_state *sd_state, + struct v4l2_subdev_state *state, struct v4l2_subdev_mbus_code_enum *code) { /* @@ -1011,7 +1078,7 @@ static int mipi_csis_enum_mbus_code(struct v4l2_subdev *sd, if (code->index > 0) return -EINVAL; - fmt = v4l2_subdev_state_get_format(sd_state, code->pad); + fmt = v4l2_subdev_state_get_format(state, code->pad); code->code = fmt->code; return 0; } @@ -1028,10 +1095,10 @@ static int mipi_csis_enum_mbus_code(struct v4l2_subdev *sd, } static int mipi_csis_set_fmt(struct v4l2_subdev *sd, - struct v4l2_subdev_state *sd_state, + struct v4l2_subdev_state *state, struct v4l2_subdev_format *sdformat) { - struct csis_pix_format const *csis_fmt; + const struct csis_pix_format *csis_fmt; struct v4l2_mbus_framefmt *fmt; unsigned int align; @@ -1040,7 +1107,7 @@ static int mipi_csis_set_fmt(struct v4l2_subdev *sd, * modified. */ if (sdformat->pad == CSIS_PAD_SOURCE) - return v4l2_subdev_get_fmt(sd, sd_state, sdformat); + return v4l2_subdev_get_fmt(sd, state, sdformat); if (sdformat->pad != CSIS_PAD_SINK) return -EINVAL; @@ -1078,7 +1145,7 @@ static int mipi_csis_set_fmt(struct v4l2_subdev *sd, &sdformat->format.height, 1, CSIS_MAX_PIX_HEIGHT, 0, 0); - fmt = v4l2_subdev_state_get_format(sd_state, sdformat->pad); + fmt = v4l2_subdev_state_get_format(state, sdformat->pad); fmt->code = csis_fmt->code; fmt->width = sdformat->format.width; @@ -1092,7 +1159,7 @@ static int mipi_csis_set_fmt(struct v4l2_subdev *sd, sdformat->format = *fmt; /* Propagate the format from sink to source. */ - fmt = v4l2_subdev_state_get_format(sd_state, CSIS_PAD_SOURCE); + fmt = v4l2_subdev_state_get_format(state, CSIS_PAD_SOURCE); *fmt = sdformat->format; /* The format on the source pad might change due to unpacking. */ @@ -1132,7 +1199,7 @@ static int mipi_csis_get_frame_desc(struct v4l2_subdev *sd, unsigned int pad, } static int mipi_csis_init_state(struct v4l2_subdev *sd, - struct v4l2_subdev_state *sd_state) + struct v4l2_subdev_state *state) { struct v4l2_subdev_format fmt = { .pad = CSIS_PAD_SINK, @@ -1149,7 +1216,7 @@ static int mipi_csis_init_state(struct v4l2_subdev *sd, V4L2_MAP_QUANTIZATION_DEFAULT(false, fmt.format.colorspace, fmt.format.ycbcr_enc); - return mipi_csis_set_fmt(sd, sd_state, &fmt); + return mipi_csis_set_fmt(sd, state, &fmt); } static int mipi_csis_log_status(struct v4l2_subdev *sd) @@ -1413,9 +1480,13 @@ static int mipi_csis_parse_dt(struct mipi_csis_device *csis) { struct device_node *node = csis->dev->of_node; - if (of_property_read_u32(node, "clock-frequency", - &csis->clk_frequency)) - csis->clk_frequency = DEFAULT_SCLK_CSIS_FREQ; + of_property_read_u32(node, "clock-frequency", &csis->clk_frequency); + + csis->num_channels = 1; + of_property_read_u32(node, "fsl,num-channels", &csis->num_channels); + if (csis->num_channels < 1 || csis->num_channels > MIPI_CSIS_MAX_CHANNELS) + return dev_err_probe(csis->dev, -EINVAL, + "Invalid fsl,num-channels value\n"); return 0; } @@ -1440,10 +1511,8 @@ static int mipi_csis_probe(struct platform_device *pdev) /* Parse DT properties. */ ret = mipi_csis_parse_dt(csis); - if (ret < 0) { - dev_err(dev, "Failed to parse device tree: %d\n", ret); + if (ret < 0) return ret; - } /* Acquire resources. */ csis->regs = devm_platform_ioremap_resource(pdev, 0); diff --git a/drivers/media/platform/nxp/imx-pxp.c b/drivers/media/platform/nxp/imx-pxp.c index 7f8ffbac582f..6cc9b07ea53a 100644 --- a/drivers/media/platform/nxp/imx-pxp.c +++ b/drivers/media/platform/nxp/imx-pxp.c @@ -248,7 +248,7 @@ struct pxp_ctx { static inline struct pxp_ctx *file2ctx(struct file *file) { - return container_of(file->private_data, struct pxp_ctx, fh); + return container_of(file_to_v4l2_fh(file), struct pxp_ctx, fh); } static struct pxp_q_data *get_q_data(struct pxp_ctx *ctx, @@ -1660,7 +1660,6 @@ static int pxp_open(struct file *file) } v4l2_fh_init(&ctx->fh, video_devdata(file)); - file->private_data = &ctx->fh; ctx->dev = dev; hdl = &ctx->hdl; v4l2_ctrl_handler_init(hdl, 4); @@ -1699,7 +1698,7 @@ static int pxp_open(struct file *file) goto open_unlock; } - v4l2_fh_add(&ctx->fh); + v4l2_fh_add(&ctx->fh, file); atomic_inc(&dev->num_inst); dprintk(dev, "Created instance: %p, m2m_ctx: %p\n", @@ -1717,7 +1716,7 @@ static int pxp_release(struct file *file) dprintk(dev, "Releasing instance %p\n", ctx); - v4l2_fh_del(&ctx->fh); + v4l2_fh_del(&ctx->fh, file); v4l2_fh_exit(&ctx->fh); v4l2_ctrl_handler_free(&ctx->hdl); mutex_lock(&dev->dev_mutex); diff --git a/drivers/media/platform/nxp/imx8-isi/imx8-isi-core.c b/drivers/media/platform/nxp/imx8-isi/imx8-isi-core.c index 981648a03113..adc8d9960bf0 100644 --- a/drivers/media/platform/nxp/imx8-isi/imx8-isi-core.c +++ b/drivers/media/platform/nxp/imx8-isi/imx8-isi-core.c @@ -374,6 +374,8 @@ static int mxc_isi_pm_suspend(struct device *dev) mxc_isi_video_suspend(pipe); } + mxc_isi_m2m_suspend(&isi->m2m); + return pm_runtime_force_suspend(dev); } @@ -403,6 +405,12 @@ static int mxc_isi_pm_resume(struct device *dev) } } + ret = mxc_isi_m2m_resume(&isi->m2m); + if (ret) { + dev_err(dev, "Failed to resume ISI (%d) for m2m\n", ret); + err = ret; + } + return err; } diff --git a/drivers/media/platform/nxp/imx8-isi/imx8-isi-core.h b/drivers/media/platform/nxp/imx8-isi/imx8-isi-core.h index 206995bedca4..e84af5127e4e 100644 --- a/drivers/media/platform/nxp/imx8-isi/imx8-isi-core.h +++ b/drivers/media/platform/nxp/imx8-isi/imx8-isi-core.h @@ -202,9 +202,8 @@ struct mxc_isi_video { struct video_device vdev; struct media_pad pad; - /* Protects is_streaming, and the vdev and vb2_q operations */ + /* Protects the vdev and vb2_q operations */ struct mutex lock; - bool is_streaming; struct v4l2_pix_format_mplane pix; const struct mxc_isi_format_info *fmtinfo; @@ -343,6 +342,8 @@ int mxc_isi_video_buffer_prepare(struct mxc_isi_dev *isi, struct vb2_buffer *vb2 #ifdef CONFIG_VIDEO_IMX8_ISI_M2M int mxc_isi_m2m_register(struct mxc_isi_dev *isi, struct v4l2_device *v4l2_dev); int mxc_isi_m2m_unregister(struct mxc_isi_dev *isi); +void mxc_isi_m2m_suspend(struct mxc_isi_m2m *m2m); +int mxc_isi_m2m_resume(struct mxc_isi_m2m *m2m); #else static inline int mxc_isi_m2m_register(struct mxc_isi_dev *isi, struct v4l2_device *v4l2_dev) @@ -353,6 +354,13 @@ static inline int mxc_isi_m2m_unregister(struct mxc_isi_dev *isi) { return 0; } +static inline void mxc_isi_m2m_suspend(struct mxc_isi_m2m *m2m) +{ +} +static inline int mxc_isi_m2m_resume(struct mxc_isi_m2m *m2m) +{ + return 0; +} #endif int mxc_isi_channel_acquire(struct mxc_isi_pipe *pipe, @@ -362,7 +370,7 @@ void mxc_isi_channel_get(struct mxc_isi_pipe *pipe); void mxc_isi_channel_put(struct mxc_isi_pipe *pipe); void mxc_isi_channel_enable(struct mxc_isi_pipe *pipe); void mxc_isi_channel_disable(struct mxc_isi_pipe *pipe); -int mxc_isi_channel_chain(struct mxc_isi_pipe *pipe, bool bypass); +int mxc_isi_channel_chain(struct mxc_isi_pipe *pipe); void mxc_isi_channel_unchain(struct mxc_isi_pipe *pipe); void mxc_isi_channel_config(struct mxc_isi_pipe *pipe, diff --git a/drivers/media/platform/nxp/imx8-isi/imx8-isi-hw.c b/drivers/media/platform/nxp/imx8-isi/imx8-isi-hw.c index 5623914f95e6..9225a7ac1c3e 100644 --- a/drivers/media/platform/nxp/imx8-isi/imx8-isi-hw.c +++ b/drivers/media/platform/nxp/imx8-isi/imx8-isi-hw.c @@ -587,7 +587,7 @@ void mxc_isi_channel_release(struct mxc_isi_pipe *pipe) * * TODO: Support secondary line buffer for downscaling YUV420 images. */ -int mxc_isi_channel_chain(struct mxc_isi_pipe *pipe, bool bypass) +int mxc_isi_channel_chain(struct mxc_isi_pipe *pipe) { /* Channel chaining requires both line and output buffer. */ const u8 resources = MXC_ISI_CHANNEL_RES_OUTPUT_BUF diff --git a/drivers/media/platform/nxp/imx8-isi/imx8-isi-m2m.c b/drivers/media/platform/nxp/imx8-isi/imx8-isi-m2m.c index 22e49d3a1287..00afcbfbdde4 100644 --- a/drivers/media/platform/nxp/imx8-isi/imx8-isi-m2m.c +++ b/drivers/media/platform/nxp/imx8-isi/imx8-isi-m2m.c @@ -43,7 +43,6 @@ struct mxc_isi_m2m_ctx_queue_data { struct v4l2_pix_format_mplane format; const struct mxc_isi_format_info *info; u32 sequence; - bool streaming; }; struct mxc_isi_m2m_ctx { @@ -74,9 +73,9 @@ to_isi_m2m_buffer(struct vb2_v4l2_buffer *buf) return container_of(buf, struct mxc_isi_m2m_buffer, buf.vb); } -static inline struct mxc_isi_m2m_ctx *to_isi_m2m_ctx(struct v4l2_fh *fh) +static inline struct mxc_isi_m2m_ctx *file_to_isi_m2m_ctx(struct file *filp) { - return container_of(fh, struct mxc_isi_m2m_ctx, fh); + return container_of(file_to_v4l2_fh(filp), struct mxc_isi_m2m_ctx, fh); } static inline struct mxc_isi_m2m_ctx_queue_data * @@ -236,6 +235,70 @@ static void mxc_isi_m2m_vb2_buffer_queue(struct vb2_buffer *vb2) v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, vbuf); } +static int mxc_isi_m2m_vb2_prepare_streaming(struct vb2_queue *q) +{ + struct mxc_isi_m2m_ctx *ctx = vb2_get_drv_priv(q); + const struct v4l2_pix_format_mplane *out_pix = &ctx->queues.out.format; + const struct v4l2_pix_format_mplane *cap_pix = &ctx->queues.cap.format; + const struct mxc_isi_format_info *cap_info = ctx->queues.cap.info; + const struct mxc_isi_format_info *out_info = ctx->queues.out.info; + struct mxc_isi_m2m *m2m = ctx->m2m; + int ret; + + guard(mutex)(&m2m->lock); + + if (m2m->usage_count == INT_MAX) + return -EOVERFLOW; + + ret = pm_runtime_resume_and_get(m2m->isi->dev); + if (ret) + return ret; + + /* + * Acquire the pipe and initialize the channel with the first user of + * the M2M device. + */ + if (m2m->usage_count == 0) { + bool bypass = cap_pix->width == out_pix->width && + cap_pix->height == out_pix->height && + cap_info->encoding == out_info->encoding; + + ret = mxc_isi_channel_acquire(m2m->pipe, + &mxc_isi_m2m_frame_write_done, + bypass); + if (ret) + goto err_pm; + + mxc_isi_channel_get(m2m->pipe); + } + + m2m->usage_count++; + + /* + * Allocate resources for the channel, counting how many users require + * buffer chaining. + */ + if (!ctx->chained && out_pix->width > MXC_ISI_MAX_WIDTH_UNCHAINED) { + ret = mxc_isi_channel_chain(m2m->pipe); + if (ret) + goto err_deinit; + + m2m->chained_count++; + ctx->chained = true; + } + + return 0; + +err_deinit: + if (--m2m->usage_count == 0) { + mxc_isi_channel_put(m2m->pipe); + mxc_isi_channel_release(m2m->pipe); + } +err_pm: + pm_runtime_put(m2m->isi->dev); + return ret; +} + static int mxc_isi_m2m_vb2_start_streaming(struct vb2_queue *q, unsigned int count) { @@ -265,13 +328,46 @@ static void mxc_isi_m2m_vb2_stop_streaming(struct vb2_queue *q) } } +static void mxc_isi_m2m_vb2_unprepare_streaming(struct vb2_queue *q) +{ + struct mxc_isi_m2m_ctx *ctx = vb2_get_drv_priv(q); + struct mxc_isi_m2m *m2m = ctx->m2m; + + guard(mutex)(&m2m->lock); + + /* + * If the last context is this one, reset it to make sure the device + * will be reconfigured when streaming is restarted. + */ + if (m2m->last_ctx == ctx) + m2m->last_ctx = NULL; + + /* Free the channel resources if this is the last chained context. */ + if (ctx->chained && --m2m->chained_count == 0) + mxc_isi_channel_unchain(m2m->pipe); + ctx->chained = false; + + /* Turn off the light with the last user. */ + if (--m2m->usage_count == 0) { + mxc_isi_channel_disable(m2m->pipe); + mxc_isi_channel_put(m2m->pipe); + mxc_isi_channel_release(m2m->pipe); + } + + WARN_ON(m2m->usage_count < 0); + + pm_runtime_put(m2m->isi->dev); +} + static const struct vb2_ops mxc_isi_m2m_vb2_qops = { .queue_setup = mxc_isi_m2m_vb2_queue_setup, .buf_init = mxc_isi_m2m_vb2_buffer_init, .buf_prepare = mxc_isi_m2m_vb2_buffer_prepare, .buf_queue = mxc_isi_m2m_vb2_buffer_queue, + .prepare_streaming = mxc_isi_m2m_vb2_prepare_streaming, .start_streaming = mxc_isi_m2m_vb2_start_streaming, .stop_streaming = mxc_isi_m2m_vb2_stop_streaming, + .unprepare_streaming = mxc_isi_m2m_vb2_unprepare_streaming, }; static int mxc_isi_m2m_queue_init(void *priv, struct vb2_queue *src_vq, @@ -427,7 +523,7 @@ static int mxc_isi_m2m_try_fmt_vid(struct file *file, void *fh, const enum mxc_isi_video_type type = f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE ? MXC_ISI_VIDEO_M2M_OUT : MXC_ISI_VIDEO_M2M_CAP; - struct mxc_isi_m2m_ctx *ctx = to_isi_m2m_ctx(fh); + struct mxc_isi_m2m_ctx *ctx = file_to_isi_m2m_ctx(file); __mxc_isi_m2m_try_fmt_vid(ctx, &f->fmt.pix_mp, type); @@ -437,7 +533,7 @@ static int mxc_isi_m2m_try_fmt_vid(struct file *file, void *fh, static int mxc_isi_m2m_g_fmt_vid(struct file *file, void *fh, struct v4l2_format *f) { - struct mxc_isi_m2m_ctx *ctx = to_isi_m2m_ctx(fh); + struct mxc_isi_m2m_ctx *ctx = file_to_isi_m2m_ctx(file); const struct mxc_isi_m2m_ctx_queue_data *qdata = mxc_isi_m2m_ctx_qdata(ctx, f->type); @@ -452,7 +548,7 @@ static int mxc_isi_m2m_s_fmt_vid(struct file *file, void *fh, const enum mxc_isi_video_type type = f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE ? MXC_ISI_VIDEO_M2M_OUT : MXC_ISI_VIDEO_M2M_CAP; - struct mxc_isi_m2m_ctx *ctx = to_isi_m2m_ctx(fh); + struct mxc_isi_m2m_ctx *ctx = file_to_isi_m2m_ctx(file); struct v4l2_pix_format_mplane *pix = &f->fmt.pix_mp; const struct mxc_isi_format_info *info; struct vb2_queue *vq; @@ -481,136 +577,6 @@ static int mxc_isi_m2m_s_fmt_vid(struct file *file, void *fh, return 0; } -static int mxc_isi_m2m_streamon(struct file *file, void *fh, - enum v4l2_buf_type type) -{ - struct mxc_isi_m2m_ctx *ctx = to_isi_m2m_ctx(fh); - struct mxc_isi_m2m_ctx_queue_data *q = mxc_isi_m2m_ctx_qdata(ctx, type); - const struct v4l2_pix_format_mplane *out_pix = &ctx->queues.out.format; - const struct v4l2_pix_format_mplane *cap_pix = &ctx->queues.cap.format; - const struct mxc_isi_format_info *cap_info = ctx->queues.cap.info; - const struct mxc_isi_format_info *out_info = ctx->queues.out.info; - struct mxc_isi_m2m *m2m = ctx->m2m; - bool bypass; - int ret; - - if (q->streaming) - return 0; - - mutex_lock(&m2m->lock); - - if (m2m->usage_count == INT_MAX) { - ret = -EOVERFLOW; - goto unlock; - } - - bypass = cap_pix->width == out_pix->width && - cap_pix->height == out_pix->height && - cap_info->encoding == out_info->encoding; - - /* - * Acquire the pipe and initialize the channel with the first user of - * the M2M device. - */ - if (m2m->usage_count == 0) { - ret = mxc_isi_channel_acquire(m2m->pipe, - &mxc_isi_m2m_frame_write_done, - bypass); - if (ret) - goto unlock; - - mxc_isi_channel_get(m2m->pipe); - } - - m2m->usage_count++; - - /* - * Allocate resources for the channel, counting how many users require - * buffer chaining. - */ - if (!ctx->chained && out_pix->width > MXC_ISI_MAX_WIDTH_UNCHAINED) { - ret = mxc_isi_channel_chain(m2m->pipe, bypass); - if (ret) - goto deinit; - - m2m->chained_count++; - ctx->chained = true; - } - - /* - * Drop the lock to start the stream, as the .device_run() operation - * needs to acquire it. - */ - mutex_unlock(&m2m->lock); - ret = v4l2_m2m_ioctl_streamon(file, fh, type); - if (ret) { - /* Reacquire the lock for the cleanup path. */ - mutex_lock(&m2m->lock); - goto unchain; - } - - q->streaming = true; - - return 0; - -unchain: - if (ctx->chained && --m2m->chained_count == 0) - mxc_isi_channel_unchain(m2m->pipe); - ctx->chained = false; - -deinit: - if (--m2m->usage_count == 0) { - mxc_isi_channel_put(m2m->pipe); - mxc_isi_channel_release(m2m->pipe); - } - -unlock: - mutex_unlock(&m2m->lock); - return ret; -} - -static int mxc_isi_m2m_streamoff(struct file *file, void *fh, - enum v4l2_buf_type type) -{ - struct mxc_isi_m2m_ctx *ctx = to_isi_m2m_ctx(fh); - struct mxc_isi_m2m_ctx_queue_data *q = mxc_isi_m2m_ctx_qdata(ctx, type); - struct mxc_isi_m2m *m2m = ctx->m2m; - - v4l2_m2m_ioctl_streamoff(file, fh, type); - - if (!q->streaming) - return 0; - - mutex_lock(&m2m->lock); - - /* - * If the last context is this one, reset it to make sure the device - * will be reconfigured when streaming is restarted. - */ - if (m2m->last_ctx == ctx) - m2m->last_ctx = NULL; - - /* Free the channel resources if this is the last chained context. */ - if (ctx->chained && --m2m->chained_count == 0) - mxc_isi_channel_unchain(m2m->pipe); - ctx->chained = false; - - /* Turn off the light with the last user. */ - if (--m2m->usage_count == 0) { - mxc_isi_channel_disable(m2m->pipe); - mxc_isi_channel_put(m2m->pipe); - mxc_isi_channel_release(m2m->pipe); - } - - WARN_ON(m2m->usage_count < 0); - - mutex_unlock(&m2m->lock); - - q->streaming = false; - - return 0; -} - static const struct v4l2_ioctl_ops mxc_isi_m2m_ioctl_ops = { .vidioc_querycap = mxc_isi_m2m_querycap, @@ -631,8 +597,8 @@ static const struct v4l2_ioctl_ops mxc_isi_m2m_ioctl_ops = { .vidioc_prepare_buf = v4l2_m2m_ioctl_prepare_buf, .vidioc_create_bufs = v4l2_m2m_ioctl_create_bufs, - .vidioc_streamon = mxc_isi_m2m_streamon, - .vidioc_streamoff = mxc_isi_m2m_streamoff, + .vidioc_streamon = v4l2_m2m_ioctl_streamon, + .vidioc_streamoff = v4l2_m2m_ioctl_streamoff, .vidioc_subscribe_event = v4l2_ctrl_subscribe_event, .vidioc_unsubscribe_event = v4l2_event_unsubscribe, @@ -668,7 +634,6 @@ static int mxc_isi_m2m_open(struct file *file) mutex_init(&ctx->vb2_lock); v4l2_fh_init(&ctx->fh, vdev); - file->private_data = &ctx->fh; ctx->fh.m2m_ctx = v4l2_m2m_ctx_init(m2m->m2m_dev, ctx, &mxc_isi_m2m_queue_init); @@ -685,16 +650,10 @@ static int mxc_isi_m2m_open(struct file *file) if (ret) goto err_ctx; - ret = pm_runtime_resume_and_get(m2m->isi->dev); - if (ret) - goto err_ctrls; - - v4l2_fh_add(&ctx->fh); + v4l2_fh_add(&ctx->fh, file); return 0; -err_ctrls: - mxc_isi_m2m_ctx_ctrls_delete(ctx); err_ctx: v4l2_m2m_ctx_release(ctx->fh.m2m_ctx); err_fh: @@ -706,20 +665,17 @@ err_fh: static int mxc_isi_m2m_release(struct file *file) { - struct mxc_isi_m2m *m2m = video_drvdata(file); - struct mxc_isi_m2m_ctx *ctx = to_isi_m2m_ctx(file->private_data); + struct mxc_isi_m2m_ctx *ctx = file_to_isi_m2m_ctx(file); v4l2_m2m_ctx_release(ctx->fh.m2m_ctx); mxc_isi_m2m_ctx_ctrls_delete(ctx); - v4l2_fh_del(&ctx->fh); + v4l2_fh_del(&ctx->fh, file); v4l2_fh_exit(&ctx->fh); mutex_destroy(&ctx->vb2_lock); kfree(ctx); - pm_runtime_put(m2m->isi->dev); - return 0; } @@ -733,6 +689,40 @@ static const struct v4l2_file_operations mxc_isi_m2m_fops = { }; /* ----------------------------------------------------------------------------- + * Suspend & resume + */ + +void mxc_isi_m2m_suspend(struct mxc_isi_m2m *m2m) +{ + if (m2m->usage_count == 0) + return; + + v4l2_m2m_suspend(m2m->m2m_dev); + + if (m2m->chained_count > 0) + mxc_isi_channel_unchain(m2m->pipe); + + mxc_isi_channel_disable(m2m->pipe); + mxc_isi_channel_put(m2m->pipe); +} + +int mxc_isi_m2m_resume(struct mxc_isi_m2m *m2m) +{ + if (m2m->usage_count == 0) + return 0; + + mxc_isi_channel_get(m2m->pipe); + + if (m2m->chained_count > 0) + mxc_isi_channel_chain(m2m->pipe); + + m2m->last_ctx = NULL; + v4l2_m2m_resume(m2m->m2m_dev); + + return 0; +} + +/* ----------------------------------------------------------------------------- * Registration */ diff --git a/drivers/media/platform/nxp/imx8-isi/imx8-isi-pipe.c b/drivers/media/platform/nxp/imx8-isi/imx8-isi-pipe.c index d76eb58deb09..a41c51dd9ce0 100644 --- a/drivers/media/platform/nxp/imx8-isi/imx8-isi-pipe.c +++ b/drivers/media/platform/nxp/imx8-isi/imx8-isi-pipe.c @@ -855,7 +855,7 @@ int mxc_isi_pipe_acquire(struct mxc_isi_pipe *pipe, /* Chain the channel if needed for wide resolutions. */ if (sink_fmt->width > MXC_ISI_MAX_WIDTH_UNCHAINED) { - ret = mxc_isi_channel_chain(pipe, bypass); + ret = mxc_isi_channel_chain(pipe); if (ret) mxc_isi_channel_release(pipe); } diff --git a/drivers/media/platform/nxp/imx8-isi/imx8-isi-video.c b/drivers/media/platform/nxp/imx8-isi/imx8-isi-video.c index 8654150728a8..13682bf6e9f8 100644 --- a/drivers/media/platform/nxp/imx8-isi/imx8-isi-video.c +++ b/drivers/media/platform/nxp/imx8-isi/imx8-isi-video.c @@ -937,6 +937,47 @@ static void mxc_isi_video_init_channel(struct mxc_isi_video *video) mxc_isi_channel_set_output_format(pipe, video->fmtinfo, &video->pix); } +static int mxc_isi_vb2_prepare_streaming(struct vb2_queue *q) +{ + struct mxc_isi_video *video = vb2_get_drv_priv(q); + struct media_device *mdev = &video->pipe->isi->media_dev; + struct media_pipeline *pipe; + int ret; + + /* Get a pipeline for the video node and start it. */ + scoped_guard(mutex, &mdev->graph_mutex) { + ret = mxc_isi_pipe_acquire(video->pipe, + &mxc_isi_video_frame_write_done); + if (ret) + return ret; + + pipe = media_entity_pipeline(&video->vdev.entity) + ? : &video->pipe->pipe; + + ret = __video_device_pipeline_start(&video->vdev, pipe); + if (ret) + goto err_release; + } + + /* Verify that the video format matches the output of the subdev. */ + ret = mxc_isi_video_validate_format(video); + if (ret) + goto err_stop; + + /* Allocate buffers for discard operation. */ + ret = mxc_isi_video_alloc_discard_buffers(video); + if (ret) + goto err_stop; + + return 0; + +err_stop: + video_device_pipeline_stop(&video->vdev); +err_release: + mxc_isi_pipe_release(video->pipe); + return ret; +} + static int mxc_isi_vb2_start_streaming(struct vb2_queue *q, unsigned int count) { struct mxc_isi_video *video = vb2_get_drv_priv(q); @@ -985,13 +1026,24 @@ static void mxc_isi_vb2_stop_streaming(struct vb2_queue *q) mxc_isi_video_return_buffers(video, VB2_BUF_STATE_ERROR); } +static void mxc_isi_vb2_unprepare_streaming(struct vb2_queue *q) +{ + struct mxc_isi_video *video = vb2_get_drv_priv(q); + + mxc_isi_video_free_discard_buffers(video); + video_device_pipeline_stop(&video->vdev); + mxc_isi_pipe_release(video->pipe); +} + static const struct vb2_ops mxc_isi_vb2_qops = { .queue_setup = mxc_isi_vb2_queue_setup, .buf_init = mxc_isi_vb2_buffer_init, .buf_prepare = mxc_isi_vb2_buffer_prepare, .buf_queue = mxc_isi_vb2_buffer_queue, + .prepare_streaming = mxc_isi_vb2_prepare_streaming, .start_streaming = mxc_isi_vb2_start_streaming, .stop_streaming = mxc_isi_vb2_stop_streaming, + .unprepare_streaming = mxc_isi_vb2_unprepare_streaming, }; /* ----------------------------------------------------------------------------- @@ -1145,97 +1197,6 @@ static int mxc_isi_video_s_fmt(struct file *file, void *priv, return 0; } -static int mxc_isi_video_streamon(struct file *file, void *priv, - enum v4l2_buf_type type) -{ - struct mxc_isi_video *video = video_drvdata(file); - struct media_device *mdev = &video->pipe->isi->media_dev; - struct media_pipeline *pipe; - int ret; - - if (vb2_queue_is_busy(&video->vb2_q, file)) - return -EBUSY; - - /* - * Get a pipeline for the video node and start it. This must be done - * here and not in the queue .start_streaming() handler, so that - * pipeline start errors can be reported from VIDIOC_STREAMON and not - * delayed until subsequent VIDIOC_QBUF calls. - */ - mutex_lock(&mdev->graph_mutex); - - ret = mxc_isi_pipe_acquire(video->pipe, &mxc_isi_video_frame_write_done); - if (ret) { - mutex_unlock(&mdev->graph_mutex); - return ret; - } - - pipe = media_entity_pipeline(&video->vdev.entity) ? : &video->pipe->pipe; - - ret = __video_device_pipeline_start(&video->vdev, pipe); - if (ret) { - mutex_unlock(&mdev->graph_mutex); - goto err_release; - } - - mutex_unlock(&mdev->graph_mutex); - - /* Verify that the video format matches the output of the subdev. */ - ret = mxc_isi_video_validate_format(video); - if (ret) - goto err_stop; - - /* Allocate buffers for discard operation. */ - ret = mxc_isi_video_alloc_discard_buffers(video); - if (ret) - goto err_stop; - - ret = vb2_streamon(&video->vb2_q, type); - if (ret) - goto err_free; - - video->is_streaming = true; - - return 0; - -err_free: - mxc_isi_video_free_discard_buffers(video); -err_stop: - video_device_pipeline_stop(&video->vdev); -err_release: - mxc_isi_pipe_release(video->pipe); - return ret; -} - -static void mxc_isi_video_cleanup_streaming(struct mxc_isi_video *video) -{ - lockdep_assert_held(&video->lock); - - if (!video->is_streaming) - return; - - mxc_isi_video_free_discard_buffers(video); - video_device_pipeline_stop(&video->vdev); - mxc_isi_pipe_release(video->pipe); - - video->is_streaming = false; -} - -static int mxc_isi_video_streamoff(struct file *file, void *priv, - enum v4l2_buf_type type) -{ - struct mxc_isi_video *video = video_drvdata(file); - int ret; - - ret = vb2_ioctl_streamoff(file, priv, type); - if (ret) - return ret; - - mxc_isi_video_cleanup_streaming(video); - - return 0; -} - static int mxc_isi_video_enum_framesizes(struct file *file, void *priv, struct v4l2_frmsizeenum *fsize) { @@ -1291,9 +1252,8 @@ static const struct v4l2_ioctl_ops mxc_isi_video_ioctl_ops = { .vidioc_expbuf = vb2_ioctl_expbuf, .vidioc_prepare_buf = vb2_ioctl_prepare_buf, .vidioc_create_bufs = vb2_ioctl_create_bufs, - - .vidioc_streamon = mxc_isi_video_streamon, - .vidioc_streamoff = mxc_isi_video_streamoff, + .vidioc_streamon = vb2_ioctl_streamon, + .vidioc_streamoff = vb2_ioctl_streamoff, .vidioc_enum_framesizes = mxc_isi_video_enum_framesizes, @@ -1332,10 +1292,6 @@ static int mxc_isi_video_release(struct file *file) if (ret) dev_err(video->pipe->isi->dev, "%s fail\n", __func__); - mutex_lock(&video->lock); - mxc_isi_video_cleanup_streaming(video); - mutex_unlock(&video->lock); - pm_runtime_put(video->pipe->isi->dev); return ret; } @@ -1357,7 +1313,7 @@ void mxc_isi_video_suspend(struct mxc_isi_pipe *pipe) { struct mxc_isi_video *video = &pipe->video; - if (!video->is_streaming) + if (!vb2_is_streaming(&video->vb2_q)) return; mxc_isi_pipe_disable(pipe); @@ -1388,7 +1344,7 @@ int mxc_isi_video_resume(struct mxc_isi_pipe *pipe) { struct mxc_isi_video *video = &pipe->video; - if (!video->is_streaming) + if (!vb2_is_streaming(&video->vb2_q)) return 0; mxc_isi_video_init_channel(video); diff --git a/drivers/media/platform/nxp/mx2_emmaprp.c b/drivers/media/platform/nxp/mx2_emmaprp.c index 0c6cc120fd2a..3aae8c0b690c 100644 --- a/drivers/media/platform/nxp/mx2_emmaprp.c +++ b/drivers/media/platform/nxp/mx2_emmaprp.c @@ -214,6 +214,11 @@ struct emmaprp_ctx { struct emmaprp_q_data q_data[2]; }; +static inline struct emmaprp_ctx *file_to_emmaprp_ctx(struct file *filp) +{ + return container_of(file_to_v4l2_fh(filp), struct emmaprp_ctx, fh); +} + static struct emmaprp_q_data *get_q_data(struct emmaprp_ctx *ctx, enum v4l2_buf_type type) { @@ -451,13 +456,13 @@ static int vidioc_g_fmt(struct emmaprp_ctx *ctx, struct v4l2_format *f) static int vidioc_g_fmt_vid_out(struct file *file, void *priv, struct v4l2_format *f) { - return vidioc_g_fmt(priv, f); + return vidioc_g_fmt(file_to_emmaprp_ctx(file), f); } static int vidioc_g_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *f) { - return vidioc_g_fmt(priv, f); + return vidioc_g_fmt(file_to_emmaprp_ctx(file), f); } static int vidioc_try_fmt(struct v4l2_format *f) @@ -497,8 +502,8 @@ static int vidioc_try_fmt(struct v4l2_format *f) static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *f) { + struct emmaprp_ctx *ctx = file_to_emmaprp_ctx(file); struct emmaprp_fmt *fmt; - struct emmaprp_ctx *ctx = priv; fmt = find_format(f); if (!fmt || !(fmt->types & MEM2MEM_CAPTURE)) { @@ -514,8 +519,8 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, static int vidioc_try_fmt_vid_out(struct file *file, void *priv, struct v4l2_format *f) { + struct emmaprp_ctx *ctx = file_to_emmaprp_ctx(file); struct emmaprp_fmt *fmt; - struct emmaprp_ctx *ctx = priv; fmt = find_format(f); if (!fmt || !(fmt->types & MEM2MEM_OUTPUT)) { @@ -575,7 +580,7 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, if (ret) return ret; - return vidioc_s_fmt(priv, f); + return vidioc_s_fmt(file_to_emmaprp_ctx(file), f); } static int vidioc_s_fmt_vid_out(struct file *file, void *priv, @@ -587,7 +592,7 @@ static int vidioc_s_fmt_vid_out(struct file *file, void *priv, if (ret) return ret; - return vidioc_s_fmt(priv, f); + return vidioc_s_fmt(file_to_emmaprp_ctx(file), f); } static const struct v4l2_ioctl_ops emmaprp_ioctl_ops = { @@ -725,7 +730,6 @@ static int emmaprp_open(struct file *file) return -ENOMEM; v4l2_fh_init(&ctx->fh, video_devdata(file)); - file->private_data = &ctx->fh; ctx->dev = pcdev; if (mutex_lock_interruptible(&pcdev->dev_mutex)) { @@ -747,7 +751,7 @@ static int emmaprp_open(struct file *file) clk_prepare_enable(pcdev->clk_emma_ahb); ctx->q_data[V4L2_M2M_SRC].fmt = &formats[1]; ctx->q_data[V4L2_M2M_DST].fmt = &formats[0]; - v4l2_fh_add(&ctx->fh); + v4l2_fh_add(&ctx->fh, file); mutex_unlock(&pcdev->dev_mutex); dprintk(pcdev, "Created instance %p, m2m_ctx: %p\n", ctx, ctx->fh.m2m_ctx); @@ -758,14 +762,14 @@ static int emmaprp_open(struct file *file) static int emmaprp_release(struct file *file) { struct emmaprp_dev *pcdev = video_drvdata(file); - struct emmaprp_ctx *ctx = file->private_data; + struct emmaprp_ctx *ctx = file_to_emmaprp_ctx(file); dprintk(pcdev, "Releasing instance %p\n", ctx); mutex_lock(&pcdev->dev_mutex); clk_disable_unprepare(pcdev->clk_emma_ahb); clk_disable_unprepare(pcdev->clk_emma_ipg); - v4l2_fh_del(&ctx->fh); + v4l2_fh_del(&ctx->fh, file); v4l2_fh_exit(&ctx->fh); v4l2_m2m_ctx_release(ctx->fh.m2m_ctx); mutex_unlock(&pcdev->dev_mutex); diff --git a/drivers/media/platform/qcom/camss/Makefile b/drivers/media/platform/qcom/camss/Makefile index d26a9c24a430..23960d02877d 100644 --- a/drivers/media/platform/qcom/camss/Makefile +++ b/drivers/media/platform/qcom/camss/Makefile @@ -6,9 +6,10 @@ qcom-camss-objs += \ camss-csid.o \ camss-csid-4-1.o \ camss-csid-4-7.o \ + camss-csid-340.o \ camss-csid-680.o \ camss-csid-gen2.o \ - camss-csid-780.o \ + camss-csid-gen3.o \ camss-csiphy-2ph-1-0.o \ camss-csiphy-3ph-1-0.o \ camss-csiphy.o \ @@ -17,9 +18,10 @@ qcom-camss-objs += \ camss-vfe-4-7.o \ camss-vfe-4-8.o \ camss-vfe-17x.o \ + camss-vfe-340.o \ camss-vfe-480.o \ camss-vfe-680.o \ - camss-vfe-780.o \ + camss-vfe-gen3.o \ camss-vfe-gen1.o \ camss-vfe.o \ camss-video.o \ diff --git a/drivers/media/platform/qcom/camss/camss-csid-340.c b/drivers/media/platform/qcom/camss/camss-csid-340.c new file mode 100644 index 000000000000..22a30510fb79 --- /dev/null +++ b/drivers/media/platform/qcom/camss/camss-csid-340.c @@ -0,0 +1,190 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Qualcomm MSM Camera Subsystem - CSID (CSI Decoder) Module 340 + * + * Copyright (c) 2025 Qualcomm Innovation Center, Inc. All rights reserved. + */ + +#include <linux/completion.h> +#include <linux/bitfield.h> +#include <linux/interrupt.h> +#include <linux/io.h> +#include <linux/kernel.h> + +#include "camss.h" +#include "camss-csid.h" +#include "camss-csid-gen2.h" + +#define CSID_RST_STROBES (0x010) +#define CSID_RST_SW_REGS BIT(0) +#define CSID_RST_IRQ BIT(1) +#define CSID_RST_IFE_CLK BIT(2) +#define CSID_RST_PHY_CLK BIT(3) +#define CSID_RST_CSID_CLK BIT(4) + +#define CSID_IRQ_STATUS (0x070) +#define CSID_IRQ_MASK (0x074) +#define CSID_IRQ_MASK_RST_DONE BIT(0) +#define CSID_IRQ_CLEAR (0x078) +#define CSID_IRQ_CMD (0x080) +#define CSID_IRQ_CMD_CLEAR BIT(0) + +#define CSID_CSI2_RX_CFG0 (0x100) +#define CSI2_RX_CFG0_NUM_ACTIVE_LANES_MASK GENMASK(1, 0) +#define CSI2_RX_CFG0_DLX_INPUT_SEL_MASK GENMASK(17, 4) +#define CSI2_RX_CFG0_PHY_NUM_SEL_MASK GENMASK(21, 20) +#define CSI2_RX_CFG0_PHY_NUM_SEL_BASE_IDX 1 +#define CSI2_RX_CFG0_PHY_TYPE_SEL BIT(24) + +#define CSID_CSI2_RX_CFG1 (0x104) +#define CSI2_RX_CFG1_PACKET_ECC_CORRECTION_EN BIT(0) +#define CSI2_RX_CFG1_MISR_EN BIT(6) +#define CSI2_RX_CFG1_CGC_MODE BIT(7) + +#define CSID_RDI_CFG0(rdi) (0x300 + 0x100 * (rdi)) +#define CSID_RDI_CFG0_BYTE_CNTR_EN BIT(0) +#define CSID_RDI_CFG0_TIMESTAMP_EN BIT(1) +#define CSID_RDI_CFG0_DECODE_FORMAT_MASK GENMASK(15, 12) +#define CSID_RDI_CFG0_DECODE_FORMAT_NOP CSID_RDI_CFG0_DECODE_FORMAT_MASK +#define CSID_RDI_CFG0_DT_MASK GENMASK(21, 16) +#define CSID_RDI_CFG0_VC_MASK GENMASK(23, 22) +#define CSID_RDI_CFG0_DTID_MASK GENMASK(28, 27) +#define CSID_RDI_CFG0_ENABLE BIT(31) + +#define CSID_RDI_CTRL(rdi) (0x308 + 0x100 * (rdi)) +#define CSID_RDI_CTRL_HALT_AT_FRAME_BOUNDARY 0 +#define CSID_RDI_CTRL_RESUME_AT_FRAME_BOUNDARY 1 + +static void __csid_configure_rx(struct csid_device *csid, + struct csid_phy_config *phy, int vc) +{ + u32 val; + + val = FIELD_PREP(CSI2_RX_CFG0_NUM_ACTIVE_LANES_MASK, phy->lane_cnt - 1); + val |= FIELD_PREP(CSI2_RX_CFG0_DLX_INPUT_SEL_MASK, phy->lane_assign); + val |= FIELD_PREP(CSI2_RX_CFG0_PHY_NUM_SEL_MASK, + phy->csiphy_id + CSI2_RX_CFG0_PHY_NUM_SEL_BASE_IDX); + writel_relaxed(val, csid->base + CSID_CSI2_RX_CFG0); + + val = CSI2_RX_CFG1_PACKET_ECC_CORRECTION_EN; + writel_relaxed(val, csid->base + CSID_CSI2_RX_CFG1); +} + +static void __csid_ctrl_rdi(struct csid_device *csid, int enable, u8 rdi) +{ + writel_relaxed(!!enable, csid->base + CSID_RDI_CTRL(rdi)); +} + +static void __csid_configure_rdi_stream(struct csid_device *csid, u8 enable, u8 vc) +{ + struct v4l2_mbus_framefmt *input_format = &csid->fmt[MSM_CSID_PAD_FIRST_SRC + vc]; + const struct csid_format_info *format = csid_get_fmt_entry(csid->res->formats->formats, + csid->res->formats->nformats, + input_format->code); + u8 lane_cnt = csid->phy.lane_cnt; + u8 dt_id; + u32 val; + + if (!lane_cnt) + lane_cnt = 4; + + /* + * DT_ID is a two bit bitfield that is concatenated with + * the four least significant bits of the five bit VC + * bitfield to generate an internal CID value. + * + * CSID_RDI_CFG0(vc) + * DT_ID : 28:27 + * VC : 26:22 + * DT : 21:16 + * + * CID : VC 3:0 << 2 | DT_ID 1:0 + */ + dt_id = vc & 0x03; + + val = CSID_RDI_CFG0_DECODE_FORMAT_NOP; /* only for RDI path */ + val |= FIELD_PREP(CSID_RDI_CFG0_DT_MASK, format->data_type); + val |= FIELD_PREP(CSID_RDI_CFG0_VC_MASK, vc); + val |= FIELD_PREP(CSID_RDI_CFG0_DTID_MASK, dt_id); + + if (enable) + val |= CSID_RDI_CFG0_ENABLE; + + dev_dbg(csid->camss->dev, "CSID%u: Stream %s (dt:0x%x vc=%u)\n", + csid->id, enable ? "enable" : "disable", format->data_type, vc); + + writel_relaxed(val, csid->base + CSID_RDI_CFG0(vc)); +} + +static void csid_configure_stream(struct csid_device *csid, u8 enable) +{ + int i; + + for (i = 0; i < MSM_CSID_MAX_SRC_STREAMS; i++) { + if (csid->phy.en_vc & BIT(i)) { + __csid_configure_rdi_stream(csid, enable, i); + __csid_configure_rx(csid, &csid->phy, i); + __csid_ctrl_rdi(csid, enable, i); + } + } +} + +static int csid_reset(struct csid_device *csid) +{ + unsigned long time; + + writel_relaxed(CSID_IRQ_MASK_RST_DONE, csid->base + CSID_IRQ_MASK); + writel_relaxed(CSID_IRQ_MASK_RST_DONE, csid->base + CSID_IRQ_CLEAR); + writel_relaxed(CSID_IRQ_CMD_CLEAR, csid->base + CSID_IRQ_CMD); + + reinit_completion(&csid->reset_complete); + + /* Reset with registers preserved */ + writel(CSID_RST_IRQ | CSID_RST_IFE_CLK | CSID_RST_PHY_CLK | CSID_RST_CSID_CLK, + csid->base + CSID_RST_STROBES); + + time = wait_for_completion_timeout(&csid->reset_complete, + msecs_to_jiffies(CSID_RESET_TIMEOUT_MS)); + if (!time) { + dev_err(csid->camss->dev, "CSID%u: reset timeout\n", csid->id); + return -EIO; + } + + dev_dbg(csid->camss->dev, "CSID%u: reset done\n", csid->id); + + return 0; +} + +static irqreturn_t csid_isr(int irq, void *dev) +{ + struct csid_device *csid = dev; + u32 val; + + val = readl_relaxed(csid->base + CSID_IRQ_STATUS); + writel_relaxed(val, csid->base + CSID_IRQ_CLEAR); + writel_relaxed(CSID_IRQ_CMD_CLEAR, csid->base + CSID_IRQ_CMD); + + if (val & CSID_IRQ_MASK_RST_DONE) + complete(&csid->reset_complete); + else + dev_warn_ratelimited(csid->camss->dev, "Spurious CSID interrupt\n"); + + return IRQ_HANDLED; +} + +static int csid_configure_testgen_pattern(struct csid_device *csid, s32 val) +{ + return -EOPNOTSUPP; /* Not part of CSID */ +} + +static void csid_subdev_init(struct csid_device *csid) {} + +const struct csid_hw_ops csid_ops_340 = { + .configure_testgen_pattern = csid_configure_testgen_pattern, + .configure_stream = csid_configure_stream, + .hw_version = csid_hw_version, + .isr = csid_isr, + .reset = csid_reset, + .src_pad_code = csid_src_pad_code, + .subdev_init = csid_subdev_init, +}; diff --git a/drivers/media/platform/qcom/camss/camss-csid-780.c b/drivers/media/platform/qcom/camss/camss-csid-gen3.c index 4c720d177731..664245cf6eb0 100644 --- a/drivers/media/platform/qcom/camss/camss-csid-780.c +++ b/drivers/media/platform/qcom/camss/camss-csid-gen3.c @@ -13,7 +13,7 @@ #include "camss.h" #include "camss-csid.h" -#include "camss-csid-780.h" +#include "camss-csid-gen3.h" #define CSID_IO_PATH_CFG0(csid) (0x4 * (csid)) #define OUTPUT_IFE_EN 0x100 @@ -45,8 +45,12 @@ #define CSID_CSI2_RX_IRQ_CLEAR 0xA4 #define CSID_CSI2_RX_IRQ_SET 0xA8 +#define IS_CSID_690(csid) ((csid->camss->res->version == CAMSS_8775P) \ + || (csid->camss->res->version == CAMSS_8300)) #define CSID_BUF_DONE_IRQ_STATUS 0x8C -#define BUF_DONE_IRQ_STATUS_RDI_OFFSET (csid_is_lite(csid) ? 1 : 14) +#define BUF_DONE_IRQ_STATUS_RDI_OFFSET (csid_is_lite(csid) ?\ + 1 : (IS_CSID_690(csid) ?\ + 13 : 14)) #define CSID_BUF_DONE_IRQ_MASK 0x90 #define CSID_BUF_DONE_IRQ_CLEAR 0x94 #define CSID_BUF_DONE_IRQ_SET 0x98 @@ -59,6 +63,7 @@ #define CSID_CSI2_RX_CFG0 0x200 #define CSI2_RX_CFG0_NUM_ACTIVE_LANES 0 +#define CSI2_RX_CFG0_VC_MODE 3 #define CSI2_RX_CFG0_DL0_INPUT_SEL 4 #define CSI2_RX_CFG0_PHY_NUM_SEL 20 @@ -66,7 +71,9 @@ #define CSI2_RX_CFG1_ECC_CORRECTION_EN BIT(0) #define CSI2_RX_CFG1_VC_MODE BIT(2) -#define CSID_RDI_CFG0(rdi) (0x500 + 0x100 * (rdi)) +#define CSID_RDI_CFG0(rdi) (csid_is_lite(csid) && IS_CSID_690(csid) ?\ + (0x300 + 0x100 * (rdi)) :\ + (0x500 + 0x100 * (rdi))) #define RDI_CFG0_TIMESTAMP_EN BIT(6) #define RDI_CFG0_TIMESTAMP_STB_SEL BIT(8) #define RDI_CFG0_DECODE_FORMAT 12 @@ -75,10 +82,14 @@ #define RDI_CFG0_DT_ID 27 #define RDI_CFG0_EN BIT(31) -#define CSID_RDI_CTRL(rdi) (0x504 + 0x100 * (rdi)) +#define CSID_RDI_CTRL(rdi) (csid_is_lite(csid) && IS_CSID_690(csid) ?\ + (0x304 + 0x100 * (rdi)) :\ + (0x504 + 0x100 * (rdi))) #define RDI_CTRL_START_CMD BIT(0) -#define CSID_RDI_CFG1(rdi) (0x510 + 0x100 * (rdi)) +#define CSID_RDI_CFG1(rdi) (csid_is_lite(csid) && IS_CSID_690(csid) ?\ + (0x310 + 0x100 * (rdi)) :\ + (0x510 + 0x100 * (rdi))) #define RDI_CFG1_DROP_H_EN BIT(5) #define RDI_CFG1_DROP_V_EN BIT(6) #define RDI_CFG1_CROP_H_EN BIT(7) @@ -86,9 +97,12 @@ #define RDI_CFG1_PIX_STORE BIT(10) #define RDI_CFG1_PACKING_FORMAT_MIPI BIT(15) -#define CSID_RDI_IRQ_SUBSAMPLE_PATTERN(rdi) (0x548 + 0x100 * (rdi)) -#define CSID_RDI_IRQ_SUBSAMPLE_PERIOD(rdi) (0x54C + 0x100 * (rdi)) - +#define CSID_RDI_IRQ_SUBSAMPLE_PATTERN(rdi) (csid_is_lite(csid) && IS_CSID_690(csid) ?\ + (0x348 + 0x100 * (rdi)) :\ + (0x548 + 0x100 * (rdi))) +#define CSID_RDI_IRQ_SUBSAMPLE_PERIOD(rdi) (csid_is_lite(csid) && IS_CSID_690(csid) ?\ + (0x34C + 0x100 * (rdi)) :\ + (0x54C + 0x100 * (rdi))) #define CSI2_RX_CFG0_PHY_SEL_BASE_IDX 1 static void __csid_configure_rx(struct csid_device *csid, @@ -259,7 +273,7 @@ static irqreturn_t csid_isr(int irq, void *dev) if (buf_done_val & BIT(BUF_DONE_IRQ_STATUS_RDI_OFFSET + i)) { /* - * For Titan 780, bus done and RUP IRQ have been moved to + * For Titan Gen3, bus done and RUP IRQ have been moved to * CSID from VFE. Once CSID received bus done, need notify * VFE of this event. Trigger VFE to handle bus done process. */ @@ -325,7 +339,7 @@ static void csid_subdev_init(struct csid_device *csid) csid->testgen.nmodes = CSID_PAYLOAD_MODE_DISABLED; } -const struct csid_hw_ops csid_ops_780 = { +const struct csid_hw_ops csid_ops_gen3 = { .configure_stream = csid_configure_stream, .configure_testgen_pattern = csid_configure_testgen_pattern, .hw_version = csid_hw_version, diff --git a/drivers/media/platform/qcom/camss/camss-csid-780.h b/drivers/media/platform/qcom/camss/camss-csid-gen3.h index a990c66a60ff..6ee62da770c1 100644 --- a/drivers/media/platform/qcom/camss/camss-csid-780.h +++ b/drivers/media/platform/qcom/camss/camss-csid-gen3.h @@ -1,13 +1,13 @@ /* SPDX-License-Identifier: GPL-2.0 */ /* - * camss-csid-780.h + * camss-csid-gen3.h * * Qualcomm MSM Camera Subsystem - CSID (CSI Decoder) Module Generation 3 * * Copyright (c) 2024 Qualcomm Technologies, Inc. */ -#ifndef __QC_MSM_CAMSS_CSID_780_H__ -#define __QC_MSM_CAMSS_CSID_780_H__ +#ifndef __QC_MSM_CAMSS_CSID_GEN3_H__ +#define __QC_MSM_CAMSS_CSID_GEN3_H__ #define DECODE_FORMAT_UNCOMPRESSED_8_BIT 0x1 #define DECODE_FORMAT_UNCOMPRESSED_10_BIT 0x2 @@ -22,4 +22,4 @@ #define PLAIN_FORMAT_PLAIN16 0x1 /* supports DPCM, UNCOMPRESSED_10/16_BIT */ #define PLAIN_FORMAT_PLAIN32 0x2 /* supports UNCOMPRESSED_20_BIT */ -#endif /* __QC_MSM_CAMSS_CSID_780_H__ */ +#endif /* __QC_MSM_CAMSS_CSID_GEN3_H__ */ diff --git a/drivers/media/platform/qcom/camss/camss-csid.h b/drivers/media/platform/qcom/camss/camss-csid.h index 9dc826d8c8f6..aedc96ed84b2 100644 --- a/drivers/media/platform/qcom/camss/camss-csid.h +++ b/drivers/media/platform/qcom/camss/camss-csid.h @@ -213,9 +213,10 @@ extern const struct csid_formats csid_formats_gen2; extern const struct csid_hw_ops csid_ops_4_1; extern const struct csid_hw_ops csid_ops_4_7; +extern const struct csid_hw_ops csid_ops_340; extern const struct csid_hw_ops csid_ops_680; extern const struct csid_hw_ops csid_ops_gen2; -extern const struct csid_hw_ops csid_ops_780; +extern const struct csid_hw_ops csid_ops_gen3; /* * csid_is_lite - Check if CSID is CSID lite. diff --git a/drivers/media/platform/qcom/camss/camss-csiphy-3ph-1-0.c b/drivers/media/platform/qcom/camss/camss-csiphy-3ph-1-0.c index 88c0ba495c32..a229ba04b158 100644 --- a/drivers/media/platform/qcom/camss/camss-csiphy-3ph-1-0.c +++ b/drivers/media/platform/qcom/camss/camss-csiphy-3ph-1-0.c @@ -64,6 +64,85 @@ struct csiphy_lane_regs { u32 csiphy_param_type; }; +/* 5nm 2PH v 1.3.0 2p5Gbps 4 lane DPHY mode */ +static const struct +csiphy_lane_regs lane_regs_sa8775p[] = { + {0x0724, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0728, 0x04, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0700, 0x80, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x070C, 0xFF, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0738, 0x1F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x072C, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0734, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0710, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x071C, 0x0A, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0714, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x073C, 0xB8, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0704, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0720, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0708, 0x10, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x0024, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0000, 0x8D, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0038, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x002C, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0034, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0010, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x001C, 0x0A, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0014, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x003C, 0xB8, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0004, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0020, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0008, 0x10, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x0224, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0200, 0x8D, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0238, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x022C, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0234, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0210, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x021C, 0x0A, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0214, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x023C, 0xB8, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0204, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0220, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0208, 0x10, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x0424, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0400, 0x8D, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0438, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x042C, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0434, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0410, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x041C, 0x0A, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0414, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x043C, 0xB8, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0404, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0420, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0408, 0x10, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x0624, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0600, 0x8D, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0638, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x062C, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0634, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0610, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x061C, 0x0A, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0614, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x063C, 0xB8, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0604, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0620, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0608, 0x10, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x005C, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0060, 0xFD, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0064, 0x7F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x025C, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0260, 0xFD, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0264, 0x7F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x045C, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0460, 0xFD, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0464, 0x7F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x065C, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0660, 0xFD, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0664, 0x7F, 0x00, CSIPHY_DEFAULT_PARAMS}, +}; + /* GEN2 1.0 2PH */ static const struct csiphy_lane_regs lane_regs_sdm845[] = { @@ -319,6 +398,90 @@ csiphy_lane_regs lane_regs_sm8250[] = { {0x0884, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, }; +/* 14nm 2PH v 2.0.1 2p5Gbps 4 lane DPHY mode */ +static const struct +csiphy_lane_regs lane_regs_qcm2290[] = { + {0x0030, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x002c, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0034, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0028, 0x04, 0x00, CSIPHY_DNP_PARAMS}, + {0x003c, 0xb8, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x001c, 0x0a, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0000, 0xd7, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0004, 0x08, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0020, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0008, 0x04, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x000c, 0xff, 0x00, CSIPHY_DNP_PARAMS}, + {0x0010, 0x50, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0038, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0060, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0064, 0x3f, 0x00, CSIPHY_DEFAULT_PARAMS}, + + {0x0730, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x072c, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0734, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0728, 0x04, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x073c, 0xb8, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x071c, 0x0a, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0700, 0xc0, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0704, 0x08, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0720, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0708, 0x04, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x070c, 0xff, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0710, 0x50, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0738, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0760, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0764, 0x3f, 0x00, CSIPHY_DEFAULT_PARAMS}, + + {0x0230, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x022c, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0234, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0228, 0x04, 0x00, CSIPHY_DNP_PARAMS}, + {0x023c, 0xb8, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x021c, 0x0a, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0200, 0xd7, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0204, 0x08, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0220, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0208, 0x04, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x020c, 0xff, 0x00, CSIPHY_DNP_PARAMS}, + {0x0210, 0x50, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0238, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0260, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0264, 0x3f, 0x00, CSIPHY_DEFAULT_PARAMS}, + + {0x0430, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x042c, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0434, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0428, 0x04, 0x00, CSIPHY_DNP_PARAMS}, + {0x043c, 0xb8, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x041c, 0x0a, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0400, 0xd7, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0404, 0x08, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0420, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0408, 0x04, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x040C, 0xff, 0x00, CSIPHY_DNP_PARAMS}, + {0x0410, 0x50, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0438, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0460, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0464, 0x3f, 0x00, CSIPHY_DEFAULT_PARAMS}, + + {0x0630, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x062c, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0634, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0628, 0x04, 0x00, CSIPHY_DNP_PARAMS}, + {0x063c, 0xb8, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x061c, 0x0a, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0600, 0xd7, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0604, 0x08, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0620, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0608, 0x04, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x060C, 0xff, 0x00, CSIPHY_DNP_PARAMS}, + {0x0610, 0x50, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0638, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0660, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0664, 0x3f, 0x00, CSIPHY_DEFAULT_PARAMS}, +}; + /* GEN2 2.1.2 2PH DPHY mode */ static const struct csiphy_lane_regs lane_regs_sm8550[] = { @@ -744,11 +907,14 @@ static bool csiphy_is_gen2(u32 version) bool ret = false; switch (version) { + case CAMSS_2290: case CAMSS_7280: case CAMSS_8250: case CAMSS_8280XP: + case CAMSS_8300: case CAMSS_845: case CAMSS_8550: + case CAMSS_8775P: case CAMSS_X1E80100: ret = true; break; @@ -829,6 +995,10 @@ static int csiphy_init(struct csiphy_device *csiphy) regs->lane_regs = &lane_regs_sdm845[0]; regs->lane_array_size = ARRAY_SIZE(lane_regs_sdm845); break; + case CAMSS_2290: + regs->lane_regs = &lane_regs_qcm2290[0]; + regs->lane_array_size = ARRAY_SIZE(lane_regs_qcm2290); + break; case CAMSS_7280: case CAMSS_8250: regs->lane_regs = &lane_regs_sm8250[0]; @@ -848,6 +1018,11 @@ static int csiphy_init(struct csiphy_device *csiphy) regs->lane_array_size = ARRAY_SIZE(lane_regs_sm8550); regs->offset = 0x1000; break; + case CAMSS_8300: + case CAMSS_8775P: + regs->lane_regs = &lane_regs_sa8775p[0]; + regs->lane_array_size = ARRAY_SIZE(lane_regs_sa8775p); + break; default: break; } diff --git a/drivers/media/platform/qcom/camss/camss-vfe-340.c b/drivers/media/platform/qcom/camss/camss-vfe-340.c new file mode 100644 index 000000000000..30d7630b3e8b --- /dev/null +++ b/drivers/media/platform/qcom/camss/camss-vfe-340.c @@ -0,0 +1,320 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Qualcomm MSM Camera Subsystem - VFE (Video Front End) Module 340 (TFE) + * + * Copyright (c) 2025 Qualcomm Innovation Center, Inc. All rights reserved. + */ + +#include <linux/delay.h> +#include <linux/bitfield.h> +#include <linux/interrupt.h> +#include <linux/io.h> +#include <linux/iopoll.h> + +#include "camss.h" +#include "camss-vfe.h" + +#define TFE_GLOBAL_RESET_CMD (0x014) +#define TFE_GLOBAL_RESET_CMD_CORE BIT(0) + +#define TFE_REG_UPDATE_CMD (0x02c) + +#define TFE_IRQ_CMD (0x030) +#define TFE_IRQ_CMD_CLEAR BIT(0) +#define TFE_IRQ_MASK_0 (0x034) +#define TFE_IRQ_MASK_0_RST_DONE BIT(0) +#define TFE_IRQ_MASK_0_BUS_WR BIT(1) +#define TFE_IRQ_MASK_1 (0x038) +#define TFE_IRQ_MASK_2 (0x03c) +#define TFE_IRQ_CLEAR_0 (0x040) + +#define TFE_IRQ_STATUS_0 (0x04c) + +#define BUS_REG(a) (0xa00 + (a)) + +#define TFE_BUS_IRQ_MASK_0 BUS_REG(0x18) +#define TFE_BUS_IRQ_MASK_RUP_DONE_MASK GENMASK(3, 0) +#define TFE_BUS_IRQ_MASK_RUP_DONE(sc) FIELD_PREP(TFE_BUS_IRQ_MASK_RUP_DONE_MASK, BIT(sc)) +#define TFE_BUS_IRQ_MASK_BUF_DONE_MASK GENMASK(15, 8) +#define TFE_BUS_IRQ_MASK_BUF_DONE(sg) FIELD_PREP(TFE_BUS_IRQ_MASK_BUF_DONE_MASK, BIT(sg)) +#define TFE_BUS_IRQ_MASK_0_CONS_VIOL BIT(28) +#define TFE_BUS_IRQ_MASK_0_VIOL BIT(30) +#define TFE_BUS_IRQ_MASK_0_IMG_VIOL BIT(31) + +#define TFE_BUS_IRQ_MASK_1 BUS_REG(0x1c) +#define TFE_BUS_IRQ_CLEAR_0 BUS_REG(0x20) +#define TFE_BUS_IRQ_STATUS_0 BUS_REG(0x28) +#define TFE_BUS_IRQ_CMD BUS_REG(0x30) +#define TFE_BUS_IRQ_CMD_CLEAR BIT(0) + +#define TFE_BUS_STATUS_CLEAR BUS_REG(0x60) +#define TFE_BUS_VIOLATION_STATUS BUS_REG(0x64) +#define TFE_BUS_OVERFLOW_STATUS BUS_REG(0x68) +#define TFE_BUS_IMAGE_SZ_VIOLATION_STATUS BUS_REG(0x70) + +#define TFE_BUS_CLIENT_CFG(c) BUS_REG(0x200 + (c) * 0x100) +#define TFE_BUS_CLIENT_CFG_EN BIT(0) +#define TFE_BUS_CLIENT_CFG_MODE_FRAME BIT(16) +#define TFE_BUS_IMAGE_ADDR(c) BUS_REG(0x204 + (c) * 0x100) +#define TFE_BUS_FRAME_INCR(c) BUS_REG(0x208 + (c) * 0x100) +#define TFE_BUS_IMAGE_CFG_0(c) BUS_REG(0x20c + (c) * 0x100) +#define TFE_BUS_IMAGE_CFG_0_DEFAULT 0xffff +#define TFE_BUS_IMAGE_CFG_1(c) BUS_REG(0x210 + (c) * 0x100) +#define TFE_BUS_IMAGE_CFG_2(c) BUS_REG(0x214 + (c) * 0x100) +#define TFE_BUS_IMAGE_CFG_2_DEFAULT 0xffff +#define TFE_BUS_PACKER_CFG(c) BUS_REG(0x218 + (c) * 0x100) +#define TFE_BUS_PACKER_CFG_FMT_PLAIN64 0xa +#define TFE_BUS_IRQ_SUBSAMPLE_CFG_0(c) BUS_REG(0x230 + (c) * 0x100) +#define TFE_BUS_IRQ_SUBSAMPLE_CFG_1(c) BUS_REG(0x234 + (c) * 0x100) +#define TFE_BUS_FRAMEDROP_CFG_0(c) BUS_REG(0x238 + (c) * 0x100) +#define TFE_BUS_FRAMEDROP_CFG_1(c) BUS_REG(0x23c + (c) * 0x100) + +/* + * TODO: differentiate the port id based on requested type of RDI, BHIST etc + * + * TFE write master IDs (clients) + * + * BAYER 0 + * IDEAL_RAW 1 + * STATS_TINTLESS_BG 2 + * STATS_BHIST 3 + * STATS_AWB_BG 4 + * STATS_AEC_BG 5 + * STATS_BAF 6 + * RDI0 7 + * RDI1 8 + * RDI2 9 + */ +#define RDI_WM(n) (7 + (n)) +#define TFE_WM_NUM 10 + +enum tfe_iface { + TFE_IFACE_PIX, + TFE_IFACE_RDI0, + TFE_IFACE_RDI1, + TFE_IFACE_RDI2, + TFE_IFACE_NUM +}; + +enum tfe_subgroups { + TFE_SUBGROUP_BAYER, + TFE_SUBGROUP_IDEAL_RAW, + TFE_SUBGROUP_HDR, + TFE_SUBGROUP_BG, + TFE_SUBGROUP_BAF, + TFE_SUBGROUP_RDI0, + TFE_SUBGROUP_RDI1, + TFE_SUBGROUP_RDI2, + TFE_SUBGROUP_NUM +}; + +static enum tfe_iface tfe_line_iface_map[VFE_LINE_NUM_MAX] = { + [VFE_LINE_RDI0] = TFE_IFACE_RDI0, + [VFE_LINE_RDI1] = TFE_IFACE_RDI1, + [VFE_LINE_RDI2] = TFE_IFACE_RDI2, + [VFE_LINE_PIX] = TFE_IFACE_PIX, +}; + +static enum vfe_line_id tfe_subgroup_line_map[TFE_SUBGROUP_NUM] = { + [TFE_SUBGROUP_BAYER] = VFE_LINE_PIX, + [TFE_SUBGROUP_IDEAL_RAW] = VFE_LINE_PIX, + [TFE_SUBGROUP_HDR] = VFE_LINE_PIX, + [TFE_SUBGROUP_BG] = VFE_LINE_PIX, + [TFE_SUBGROUP_BAF] = VFE_LINE_PIX, + [TFE_SUBGROUP_RDI0] = VFE_LINE_RDI0, + [TFE_SUBGROUP_RDI1] = VFE_LINE_RDI1, + [TFE_SUBGROUP_RDI2] = VFE_LINE_RDI2, +}; + +static inline enum tfe_iface __line_to_iface(enum vfe_line_id line_id) +{ + if (line_id <= VFE_LINE_NONE || line_id >= VFE_LINE_NUM_MAX) { + pr_warn("VFE: Invalid line %d\n", line_id); + return TFE_IFACE_RDI0; + } + + return tfe_line_iface_map[line_id]; +} + +static inline enum vfe_line_id __iface_to_line(unsigned int iface) +{ + int i; + + for (i = 0; i < VFE_LINE_NUM_MAX; i++) { + if (tfe_line_iface_map[i] == iface) + return i; + } + + return VFE_LINE_NONE; +} + +static inline enum vfe_line_id __subgroup_to_line(enum tfe_subgroups sg) +{ + if (sg >= TFE_SUBGROUP_NUM) + return VFE_LINE_NONE; + + return tfe_subgroup_line_map[sg]; +} + +static void vfe_global_reset(struct vfe_device *vfe) +{ + writel(TFE_IRQ_MASK_0_RST_DONE, vfe->base + TFE_IRQ_MASK_0); + writel(TFE_GLOBAL_RESET_CMD_CORE, vfe->base + TFE_GLOBAL_RESET_CMD); +} + +static irqreturn_t vfe_isr(int irq, void *dev) +{ + struct vfe_device *vfe = dev; + u32 status; + int i; + + status = readl_relaxed(vfe->base + TFE_IRQ_STATUS_0); + writel_relaxed(status, vfe->base + TFE_IRQ_CLEAR_0); + writel_relaxed(TFE_IRQ_CMD_CLEAR, vfe->base + TFE_IRQ_CMD); + + if (status & TFE_IRQ_MASK_0_RST_DONE) { + dev_dbg(vfe->camss->dev, "VFE%u: Reset done!", vfe->id); + vfe_isr_reset_ack(vfe); + } + + if (status & TFE_IRQ_MASK_0_BUS_WR) { + u32 bus_status = readl_relaxed(vfe->base + TFE_BUS_IRQ_STATUS_0); + + writel_relaxed(bus_status, vfe->base + TFE_BUS_IRQ_CLEAR_0); + writel_relaxed(TFE_BUS_IRQ_CMD_CLEAR, vfe->base + TFE_BUS_IRQ_CMD); + + for (i = 0; i < TFE_IFACE_NUM; i++) { + if (bus_status & TFE_BUS_IRQ_MASK_RUP_DONE(i)) + vfe->res->hw_ops->reg_update_clear(vfe, __iface_to_line(i)); + } + + for (i = 0; i < TFE_SUBGROUP_NUM; i++) { + if (bus_status & TFE_BUS_IRQ_MASK_BUF_DONE(i)) + vfe_buf_done(vfe, __subgroup_to_line(i)); + } + + if (bus_status & TFE_BUS_IRQ_MASK_0_CONS_VIOL) + dev_err_ratelimited(vfe->camss->dev, "VFE%u: Bad config violation", + vfe->id); + + if (bus_status & TFE_BUS_IRQ_MASK_0_VIOL) + dev_err_ratelimited(vfe->camss->dev, "VFE%u: Input data violation", + vfe->id); + + if (bus_status & TFE_BUS_IRQ_MASK_0_IMG_VIOL) + dev_err_ratelimited(vfe->camss->dev, "VFE%u: Image size violation", + vfe->id); + } + + status = readl_relaxed(vfe->base + TFE_BUS_OVERFLOW_STATUS); + if (status) { + writel_relaxed(status, vfe->base + TFE_BUS_STATUS_CLEAR); + for (i = 0; i < TFE_WM_NUM; i++) { + if (status & BIT(i)) + dev_err_ratelimited(vfe->camss->dev, + "VFE%u: bus overflow for wm %u\n", + vfe->id, i); + } + } + + return IRQ_HANDLED; +} + +static int vfe_halt(struct vfe_device *vfe) +{ + /* rely on vfe_disable_output() to stop the VFE */ + return 0; +} + +static void vfe_enable_irq(struct vfe_device *vfe) +{ + writel(TFE_IRQ_MASK_0_RST_DONE | TFE_IRQ_MASK_0_BUS_WR, + vfe->base + TFE_IRQ_MASK_0); + writel(TFE_BUS_IRQ_MASK_RUP_DONE_MASK | TFE_BUS_IRQ_MASK_BUF_DONE_MASK | + TFE_BUS_IRQ_MASK_0_CONS_VIOL | TFE_BUS_IRQ_MASK_0_VIOL | + TFE_BUS_IRQ_MASK_0_IMG_VIOL, vfe->base + TFE_BUS_IRQ_MASK_0); +} + +static void vfe_wm_update(struct vfe_device *vfe, u8 rdi, u32 addr, + struct vfe_line *line) +{ + u8 wm = RDI_WM(rdi); + + writel_relaxed(addr, vfe->base + TFE_BUS_IMAGE_ADDR(wm)); +} + +static void vfe_wm_start(struct vfe_device *vfe, u8 rdi, struct vfe_line *line) +{ + struct v4l2_pix_format_mplane *pix = &line->video_out.active_fmt.fmt.pix_mp; + u32 stride = pix->plane_fmt[0].bytesperline; + u8 wm = RDI_WM(rdi); + + /* Configuration for plain RDI frames */ + writel_relaxed(TFE_BUS_IMAGE_CFG_0_DEFAULT, vfe->base + TFE_BUS_IMAGE_CFG_0(wm)); + writel_relaxed(0u, vfe->base + TFE_BUS_IMAGE_CFG_1(wm)); + writel_relaxed(TFE_BUS_IMAGE_CFG_2_DEFAULT, vfe->base + TFE_BUS_IMAGE_CFG_2(wm)); + writel_relaxed(stride * pix->height, vfe->base + TFE_BUS_FRAME_INCR(wm)); + writel_relaxed(TFE_BUS_PACKER_CFG_FMT_PLAIN64, vfe->base + TFE_BUS_PACKER_CFG(wm)); + + /* No dropped frames, one irq per frame */ + writel_relaxed(0, vfe->base + TFE_BUS_FRAMEDROP_CFG_0(wm)); + writel_relaxed(1, vfe->base + TFE_BUS_FRAMEDROP_CFG_1(wm)); + writel_relaxed(0, vfe->base + TFE_BUS_IRQ_SUBSAMPLE_CFG_0(wm)); + writel_relaxed(1, vfe->base + TFE_BUS_IRQ_SUBSAMPLE_CFG_1(wm)); + + vfe_enable_irq(vfe); + + writel(TFE_BUS_CLIENT_CFG_EN | TFE_BUS_CLIENT_CFG_MODE_FRAME, + vfe->base + TFE_BUS_CLIENT_CFG(wm)); + + dev_dbg(vfe->camss->dev, "VFE%u: Started RDI%u width %u height %u stride %u\n", + vfe->id, rdi, pix->width, pix->height, stride); +} + +static void vfe_wm_stop(struct vfe_device *vfe, u8 rdi) +{ + u8 wm = RDI_WM(rdi); + + writel(0, vfe->base + TFE_BUS_CLIENT_CFG(wm)); + + dev_dbg(vfe->camss->dev, "VFE%u: Stopped RDI%u\n", vfe->id, rdi); +} + +static const struct camss_video_ops vfe_video_ops_520 = { + .queue_buffer = vfe_queue_buffer_v2, + .flush_buffers = vfe_flush_buffers, +}; + +static void vfe_subdev_init(struct device *dev, struct vfe_device *vfe) +{ + vfe->video_ops = vfe_video_ops_520; +} + +static void vfe_reg_update(struct vfe_device *vfe, enum vfe_line_id line_id) +{ + vfe->reg_update |= BIT(__line_to_iface(line_id)); + writel_relaxed(vfe->reg_update, vfe->base + TFE_REG_UPDATE_CMD); +} + +static void vfe_reg_update_clear(struct vfe_device *vfe, enum vfe_line_id line_id) +{ + vfe->reg_update &= ~BIT(__line_to_iface(line_id)); +} + +const struct vfe_hw_ops vfe_ops_340 = { + .global_reset = vfe_global_reset, + .hw_version = vfe_hw_version, + .isr = vfe_isr, + .pm_domain_off = vfe_pm_domain_off, + .pm_domain_on = vfe_pm_domain_on, + .subdev_init = vfe_subdev_init, + .vfe_disable = vfe_disable, + .vfe_enable = vfe_enable_v2, + .vfe_halt = vfe_halt, + .vfe_wm_start = vfe_wm_start, + .vfe_wm_stop = vfe_wm_stop, + .vfe_buf_done = vfe_buf_done, + .vfe_wm_update = vfe_wm_update, + .reg_update = vfe_reg_update, + .reg_update_clear = vfe_reg_update_clear, +}; diff --git a/drivers/media/platform/qcom/camss/camss-vfe-780.c b/drivers/media/platform/qcom/camss/camss-vfe-gen3.c index b9812d70f91b..22579617def7 100644 --- a/drivers/media/platform/qcom/camss/camss-vfe-780.c +++ b/drivers/media/platform/qcom/camss/camss-vfe-gen3.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 /* - * Qualcomm MSM Camera Subsystem - VFE (Video Front End) Module v780 (SM8550) + * Qualcomm MSM Camera Subsystem - VFE (Video Front End) Module gen3 * * Copyright (c) 2024 Qualcomm Technologies, Inc. */ @@ -12,13 +12,44 @@ #include "camss.h" #include "camss-vfe.h" -#define BUS_REG_BASE (vfe_is_lite(vfe) ? 0x200 : 0xC00) +#define IS_VFE_690(vfe) \ + ((vfe->camss->res->version == CAMSS_8775P) \ + || (vfe->camss->res->version == CAMSS_8300)) + +#define BUS_REG_BASE_690 \ + (vfe_is_lite(vfe) ? 0x480 : 0x400) +#define BUS_REG_BASE_780 \ + (vfe_is_lite(vfe) ? 0x200 : 0xC00) +#define BUS_REG_BASE \ + (IS_VFE_690(vfe) ? BUS_REG_BASE_690 : BUS_REG_BASE_780) + +#define VFE_TOP_CORE_CFG (0x24) +#define VFE_DISABLE_DSCALING_DS4 BIT(21) +#define VFE_DISABLE_DSCALING_DS16 BIT(22) + +#define VFE_BUS_WM_TEST_BUS_CTRL_690 (BUS_REG_BASE + 0xFC) +#define VFE_BUS_WM_TEST_BUS_CTRL_780 (BUS_REG_BASE + 0xDC) +#define VFE_BUS_WM_TEST_BUS_CTRL \ + (IS_VFE_690(vfe) ? VFE_BUS_WM_TEST_BUS_CTRL_690 \ + : VFE_BUS_WM_TEST_BUS_CTRL_780) +/* + * Bus client mapping: + * + * Full VFE: + * VFE_690: 16 = RDI0, 17 = RDI1, 18 = RDI2 + * VFE_780: 23 = RDI0, 24 = RDI1, 25 = RDI2 + * + * VFE LITE: + * VFE_690 : 0 = RDI0, 1 = RDI1, 2 = RDI2, 3 = RDI3, 4 = RDI4, 5 = RDI5 + * VFE_780 : 0 = RDI0, 1 = RDI1, 2 = RDI2, 3 = RDI3, 4 = RDI4 + */ +#define RDI_WM_690(n) ((vfe_is_lite(vfe) ? 0x0 : 0x10) + (n)) +#define RDI_WM_780(n) ((vfe_is_lite(vfe) ? 0x0 : 0x17) + (n)) +#define RDI_WM(n) (IS_VFE_690(vfe) ? RDI_WM_690(n) : RDI_WM_780(n)) #define VFE_BUS_WM_CGC_OVERRIDE (BUS_REG_BASE + 0x08) #define WM_CGC_OVERRIDE_ALL (0x7FFFFFF) -#define VFE_BUS_WM_TEST_BUS_CTRL (BUS_REG_BASE + 0xDC) - #define VFE_BUS_WM_CFG(n) (BUS_REG_BASE + 0x200 + (n) * 0x100) #define WM_CFG_EN BIT(0) #define WM_VIR_FRM_EN BIT(1) @@ -39,17 +70,6 @@ #define VFE_BUS_WM_MMU_PREFETCH_CFG(n) (BUS_REG_BASE + 0x260 + (n) * 0x100) #define VFE_BUS_WM_MMU_PREFETCH_MAX_OFFSET(n) (BUS_REG_BASE + 0x264 + (n) * 0x100) -/* - * Bus client mapping: - * - * Full VFE: - * 23 = RDI0, 24 = RDI1, 25 = RDI2 - * - * VFE LITE: - * 0 = RDI0, 1 = RDI1, 2 = RDI3, 4 = RDI4 - */ -#define RDI_WM(n) ((vfe_is_lite(vfe) ? 0x0 : 0x17) + (n)) - static void vfe_wm_start(struct vfe_device *vfe, u8 wm, struct vfe_line *line) { struct v4l2_pix_format_mplane *pix = @@ -62,14 +82,24 @@ static void vfe_wm_start(struct vfe_device *vfe, u8 wm, struct vfe_line *line) writel(0x0, vfe->base + VFE_BUS_WM_TEST_BUS_CTRL); - writel(ALIGN(pix->plane_fmt[0].bytesperline, 16) * pix->height >> 8, - vfe->base + VFE_BUS_WM_FRAME_INCR(wm)); + if (IS_VFE_690(vfe)) + writel(ALIGN(pix->plane_fmt[0].bytesperline, 16) * pix->height, + vfe->base + VFE_BUS_WM_FRAME_INCR(wm)); + else + writel(ALIGN(pix->plane_fmt[0].bytesperline, 16) * pix->height >> 8, + vfe->base + VFE_BUS_WM_FRAME_INCR(wm)); + writel((WM_IMAGE_CFG_0_DEFAULT_WIDTH & 0xFFFF), vfe->base + VFE_BUS_WM_IMAGE_CFG_0(wm)); writel(WM_IMAGE_CFG_2_DEFAULT_STRIDE, vfe->base + VFE_BUS_WM_IMAGE_CFG_2(wm)); writel(0, vfe->base + VFE_BUS_WM_PACKER_CFG(wm)); + /* TOP CORE CFG */ + if (IS_VFE_690(vfe)) + writel(VFE_DISABLE_DSCALING_DS4 | VFE_DISABLE_DSCALING_DS16, + vfe->base + VFE_TOP_CORE_CFG); + /* no dropped frames, one irq per frame */ writel(0, vfe->base + VFE_BUS_WM_FRAMEDROP_PERIOD(wm)); writel(1, vfe->base + VFE_BUS_WM_FRAMEDROP_PATTERN(wm)); @@ -92,7 +122,11 @@ static void vfe_wm_update(struct vfe_device *vfe, u8 wm, u32 addr, struct vfe_line *line) { wm = RDI_WM(wm); - writel((addr >> 8) & 0xFFFFFFFF, vfe->base + VFE_BUS_WM_IMAGE_ADDR(wm)); + + if (IS_VFE_690(vfe)) + writel(addr, vfe->base + VFE_BUS_WM_IMAGE_ADDR(wm)); + else + writel((addr >> 8), vfe->base + VFE_BUS_WM_IMAGE_ADDR(wm)); dev_dbg(vfe->camss->dev, "wm:%d, image buf addr:0x%x\n", wm, addr); @@ -113,14 +147,14 @@ static inline void vfe_reg_update_clear(struct vfe_device *vfe, camss_reg_update(vfe->camss, vfe->id, port_id, true); } -static const struct camss_video_ops vfe_video_ops_780 = { +static const struct camss_video_ops vfe_video_ops_gen3 = { .queue_buffer = vfe_queue_buffer_v2, .flush_buffers = vfe_flush_buffers, }; static void vfe_subdev_init(struct device *dev, struct vfe_device *vfe) { - vfe->video_ops = vfe_video_ops_780; + vfe->video_ops = vfe_video_ops_gen3; } static void vfe_global_reset(struct vfe_device *vfe) @@ -140,7 +174,7 @@ static int vfe_halt(struct vfe_device *vfe) return 0; } -const struct vfe_hw_ops vfe_ops_780 = { +const struct vfe_hw_ops vfe_ops_gen3 = { .global_reset = vfe_global_reset, .hw_version = vfe_hw_version, .isr = vfe_isr, diff --git a/drivers/media/platform/qcom/camss/camss-vfe.c b/drivers/media/platform/qcom/camss/camss-vfe.c index 4bca6c3abaff..dff8d0a1e8c2 100644 --- a/drivers/media/platform/qcom/camss/camss-vfe.c +++ b/drivers/media/platform/qcom/camss/camss-vfe.c @@ -340,12 +340,15 @@ static u32 vfe_src_pad_code(struct vfe_line *line, u32 sink_code, } break; case CAMSS_660: + case CAMSS_2290: case CAMSS_7280: case CAMSS_8x96: case CAMSS_8250: case CAMSS_8280XP: + case CAMSS_8300: case CAMSS_845: case CAMSS_8550: + case CAMSS_8775P: case CAMSS_X1E80100: switch (sink_code) { case MEDIA_BUS_FMT_YUYV8_1X16: @@ -910,7 +913,24 @@ static int vfe_match_clock_names(struct vfe_device *vfe, return (!strcmp(clock->name, vfe_name) || !strcmp(clock->name, vfe_lite_name) || - !strcmp(clock->name, "vfe_lite")); + !strcmp(clock->name, "vfe_lite") || + !strcmp(clock->name, "camnoc_axi")); +} + +/* + * vfe_check_clock_levels - Calculate and set clock rates on VFE module + * @clock: clocks data + * + * Return false if there is no non-zero clock level and true otherwise. + */ +static bool vfe_check_clock_levels(struct camss_clock *clock) +{ + int i; + + for (i = 0; i < clock->nfreqs; i++) + if (clock->freq[i]) + return true; + return false; } /* @@ -936,7 +956,7 @@ static int vfe_set_clock_rates(struct vfe_device *vfe) for (i = 0; i < vfe->nclocks; i++) { struct camss_clock *clock = &vfe->clock[i]; - if (vfe_match_clock_names(vfe, clock)) { + if (vfe_match_clock_names(vfe, clock) && vfe_check_clock_levels(clock)) { u64 min_rate = 0; long rate; @@ -1017,7 +1037,7 @@ static int vfe_check_clock_rates(struct vfe_device *vfe) for (i = 0; i < vfe->nclocks; i++) { struct camss_clock *clock = &vfe->clock[i]; - if (vfe_match_clock_names(vfe, clock)) { + if (vfe_match_clock_names(vfe, clock) && vfe_check_clock_levels(clock)) { u64 min_rate = 0; unsigned long rate; @@ -1972,8 +1992,10 @@ static int vfe_bpl_align(struct vfe_device *vfe) case CAMSS_7280: case CAMSS_8250: case CAMSS_8280XP: + case CAMSS_8300: case CAMSS_845: case CAMSS_8550: + case CAMSS_8775P: case CAMSS_X1E80100: ret = 16; break; diff --git a/drivers/media/platform/qcom/camss/camss-vfe.h b/drivers/media/platform/qcom/camss/camss-vfe.h index a23f666be753..0300efdb1c46 100644 --- a/drivers/media/platform/qcom/camss/camss-vfe.h +++ b/drivers/media/platform/qcom/camss/camss-vfe.h @@ -242,9 +242,10 @@ extern const struct vfe_hw_ops vfe_ops_4_1; extern const struct vfe_hw_ops vfe_ops_4_7; extern const struct vfe_hw_ops vfe_ops_4_8; extern const struct vfe_hw_ops vfe_ops_170; +extern const struct vfe_hw_ops vfe_ops_340; extern const struct vfe_hw_ops vfe_ops_480; extern const struct vfe_hw_ops vfe_ops_680; -extern const struct vfe_hw_ops vfe_ops_780; +extern const struct vfe_hw_ops vfe_ops_gen3; int vfe_get(struct vfe_device *vfe); void vfe_put(struct vfe_device *vfe); diff --git a/drivers/media/platform/qcom/camss/camss-video.c b/drivers/media/platform/qcom/camss/camss-video.c index 8d05802d1735..831486e14754 100644 --- a/drivers/media/platform/qcom/camss/camss-video.c +++ b/drivers/media/platform/qcom/camss/camss-video.c @@ -604,50 +604,11 @@ static const struct v4l2_ioctl_ops msm_vid_ioctl_ops = { * V4L2 file operations */ -static int video_open(struct file *file) -{ - struct video_device *vdev = video_devdata(file); - struct camss_video *video = video_drvdata(file); - struct v4l2_fh *vfh; - int ret; - - mutex_lock(&video->lock); - - vfh = kzalloc(sizeof(*vfh), GFP_KERNEL); - if (vfh == NULL) { - ret = -ENOMEM; - goto error_alloc; - } - - v4l2_fh_init(vfh, vdev); - v4l2_fh_add(vfh); - - file->private_data = vfh; - - mutex_unlock(&video->lock); - - return 0; - -error_alloc: - mutex_unlock(&video->lock); - - return ret; -} - -static int video_release(struct file *file) -{ - vb2_fop_release(file); - - file->private_data = NULL; - - return 0; -} - static const struct v4l2_file_operations msm_vid_fops = { .owner = THIS_MODULE, .unlocked_ioctl = video_ioctl2, - .open = video_open, - .release = video_release, + .open = v4l2_fh_open, + .release = vb2_fop_release, .poll = vb2_fop_poll, .mmap = vb2_fop_mmap, .read = vb2_fop_read, diff --git a/drivers/media/platform/qcom/camss/camss.c b/drivers/media/platform/qcom/camss/camss.c index e08e70b93824..2fbcd0e343aa 100644 --- a/drivers/media/platform/qcom/camss/camss.c +++ b/drivers/media/platform/qcom/camss/camss.c @@ -515,6 +515,140 @@ static const struct camss_subdev_resources vfe_res_8x96[] = { } }; +static const struct camss_subdev_resources csiphy_res_2290[] = { + /* CSIPHY0 */ + { + .regulators = { "vdd-csiphy-1p2", "vdd-csiphy-1p8" }, + .clock = { "top_ahb", "ahb", "csiphy0", "csiphy0_timer" }, + .clock_rate = { { 0 }, + { 0 }, + { 240000000, 341330000, 384000000 }, + { 100000000, 200000000, 268800000 } }, + .reg = { "csiphy0" }, + .interrupt = { "csiphy0" }, + .csiphy = { + .id = 0, + .hw_ops = &csiphy_ops_3ph_1_0, + .formats = &csiphy_formats_sdm845 + } + }, + + /* CSIPHY1 */ + { + .regulators = { "vdd-csiphy-1p2", "vdd-csiphy-1p8" }, + .clock = { "top_ahb", "ahb", "csiphy1", "csiphy1_timer" }, + .clock_rate = { { 0 }, + { 0 }, + { 240000000, 341330000, 384000000 }, + { 100000000, 200000000, 268800000 } }, + .reg = { "csiphy1" }, + .interrupt = { "csiphy1" }, + .csiphy = { + .id = 1, + .hw_ops = &csiphy_ops_3ph_1_0, + .formats = &csiphy_formats_sdm845 + } + } +}; + +static const struct camss_subdev_resources csid_res_2290[] = { + /* CSID0 */ + { + .regulators = {}, + .clock = { "top_ahb", "ahb", "csi0", "vfe0_cphy_rx", "vfe0" }, + .clock_rate = { { 0 }, + { 0 }, + { 192000000, 240000000, 384000000, 426400000 }, + { 0 }, + { 0 } }, + .reg = { "csid0" }, + .interrupt = { "csid0" }, + .csid = { + .hw_ops = &csid_ops_340, + .parent_dev_ops = &vfe_parent_dev_ops, + .formats = &csid_formats_gen2 + } + }, + + /* CSID1 */ + { + .regulators = {}, + .clock = { "top_ahb", "ahb", "csi1", "vfe1_cphy_rx", "vfe1" }, + .clock_rate = { { 0 }, + { 0 }, + { 192000000, 240000000, 384000000, 426400000 }, + { 0 }, + { 0 } }, + .reg = { "csid1" }, + .interrupt = { "csid1" }, + .csid = { + .hw_ops = &csid_ops_340, + .parent_dev_ops = &vfe_parent_dev_ops, + .formats = &csid_formats_gen2 + } + } +}; + +static const struct camss_subdev_resources vfe_res_2290[] = { + /* VFE0 */ + { + .regulators = {}, + .clock = { "top_ahb", "ahb", "axi", "vfe0", "camnoc_rt_axi", "camnoc_nrt_axi" }, + .clock_rate = { { 0 }, + { 0 }, + { 0 }, + { 19200000, 153600000, 192000000, 256000000, 384000000, 460800000 }, + { 0 }, + { 0 }, }, + .reg = { "vfe0" }, + .interrupt = { "vfe0" }, + .vfe = { + .line_num = 4, + .hw_ops = &vfe_ops_340, + .formats_rdi = &vfe_formats_rdi_845, + .formats_pix = &vfe_formats_pix_845 + } + }, + + /* VFE1 */ + { + .regulators = {}, + .clock = { "top_ahb", "ahb", "axi", "vfe1", "camnoc_rt_axi", "camnoc_nrt_axi" }, + .clock_rate = { { 0 }, + { 0 }, + { 0 }, + { 19200000, 153600000, 192000000, 256000000, 384000000, 460800000 }, + { 0 }, + { 0 }, }, + .reg = { "vfe1" }, + .interrupt = { "vfe1" }, + .vfe = { + .line_num = 4, + .hw_ops = &vfe_ops_340, + .formats_rdi = &vfe_formats_rdi_845, + .formats_pix = &vfe_formats_pix_845 + } + }, +}; + +static const struct resources_icc icc_res_2290[] = { + { + .name = "ahb", + .icc_bw_tbl.avg = 150000, + .icc_bw_tbl.peak = 300000, + }, + { + .name = "hf_mnoc", + .icc_bw_tbl.avg = 2097152, + .icc_bw_tbl.peak = 3000000, + }, + { + .name = "sf_mnoc", + .icc_bw_tbl.avg = 2097152, + .icc_bw_tbl.peak = 3000000, + }, +}; + static const struct camss_subdev_resources csiphy_res_660[] = { /* CSIPHY0 */ { @@ -2285,7 +2419,7 @@ static const struct camss_subdev_resources csid_res_8550[] = { .csid = { .is_lite = false, .parent_dev_ops = &vfe_parent_dev_ops, - .hw_ops = &csid_ops_780, + .hw_ops = &csid_ops_gen3, .formats = &csid_formats_gen2 } }, @@ -2300,7 +2434,7 @@ static const struct camss_subdev_resources csid_res_8550[] = { .csid = { .is_lite = false, .parent_dev_ops = &vfe_parent_dev_ops, - .hw_ops = &csid_ops_780, + .hw_ops = &csid_ops_gen3, .formats = &csid_formats_gen2 } }, @@ -2315,7 +2449,7 @@ static const struct camss_subdev_resources csid_res_8550[] = { .csid = { .is_lite = false, .parent_dev_ops = &vfe_parent_dev_ops, - .hw_ops = &csid_ops_780, + .hw_ops = &csid_ops_gen3, .formats = &csid_formats_gen2 } }, @@ -2330,7 +2464,7 @@ static const struct camss_subdev_resources csid_res_8550[] = { .csid = { .is_lite = true, .parent_dev_ops = &vfe_parent_dev_ops, - .hw_ops = &csid_ops_780, + .hw_ops = &csid_ops_gen3, .formats = &csid_formats_gen2 } }, @@ -2345,7 +2479,7 @@ static const struct camss_subdev_resources csid_res_8550[] = { .csid = { .is_lite = true, .parent_dev_ops = &vfe_parent_dev_ops, - .hw_ops = &csid_ops_780, + .hw_ops = &csid_ops_gen3, .formats = &csid_formats_gen2 } } @@ -2371,7 +2505,7 @@ static const struct camss_subdev_resources vfe_res_8550[] = { .is_lite = false, .has_pd = true, .pd_name = "ife0", - .hw_ops = &vfe_ops_780, + .hw_ops = &vfe_ops_gen3, .formats_rdi = &vfe_formats_rdi_845, .formats_pix = &vfe_formats_pix_845 } @@ -2395,7 +2529,7 @@ static const struct camss_subdev_resources vfe_res_8550[] = { .is_lite = false, .has_pd = true, .pd_name = "ife1", - .hw_ops = &vfe_ops_780, + .hw_ops = &vfe_ops_gen3, .formats_rdi = &vfe_formats_rdi_845, .formats_pix = &vfe_formats_pix_845 } @@ -2419,7 +2553,7 @@ static const struct camss_subdev_resources vfe_res_8550[] = { .is_lite = false, .has_pd = true, .pd_name = "ife2", - .hw_ops = &vfe_ops_780, + .hw_ops = &vfe_ops_gen3, .formats_rdi = &vfe_formats_rdi_845, .formats_pix = &vfe_formats_pix_845 } @@ -2441,7 +2575,7 @@ static const struct camss_subdev_resources vfe_res_8550[] = { .vfe = { .line_num = 4, .is_lite = true, - .hw_ops = &vfe_ops_780, + .hw_ops = &vfe_ops_gen3, .formats_rdi = &vfe_formats_rdi_845, .formats_pix = &vfe_formats_pix_845 } @@ -2463,7 +2597,7 @@ static const struct camss_subdev_resources vfe_res_8550[] = { .vfe = { .line_num = 4, .is_lite = true, - .hw_ops = &vfe_ops_780, + .hw_ops = &vfe_ops_gen3, .formats_rdi = &vfe_formats_rdi_845, .formats_pix = &vfe_formats_pix_845 } @@ -2483,6 +2617,467 @@ static const struct resources_icc icc_res_sm8550[] = { }, }; +static const struct camss_subdev_resources csiphy_res_8300[] = { + /* CSIPHY0 */ + { + .regulators = { "vdda-phy", "vdda-pll" }, + + .clock = { "csiphy_rx", "csiphy0", "csiphy0_timer" }, + .clock_rate = { + { 400000000 }, + { 0 }, + { 400000000 }, + }, + .reg = { "csiphy0" }, + .interrupt = { "csiphy0" }, + .csiphy = { + .id = 0, + .hw_ops = &csiphy_ops_3ph_1_0, + .formats = &csiphy_formats_sdm845, + } + }, + /* CSIPHY1 */ + { + .regulators = { "vdda-phy", "vdda-pll" }, + + .clock = { "csiphy_rx", "csiphy1", "csiphy1_timer" }, + .clock_rate = { + { 400000000 }, + { 0 }, + { 400000000 }, + }, + .reg = { "csiphy1" }, + .interrupt = { "csiphy1" }, + .csiphy = { + .id = 1, + .hw_ops = &csiphy_ops_3ph_1_0, + .formats = &csiphy_formats_sdm845, + } + }, + /* CSIPHY2 */ + { + .regulators = { "vdda-phy", "vdda-pll" }, + + .clock = { "csiphy_rx", "csiphy2", "csiphy2_timer" }, + .clock_rate = { + { 400000000 }, + { 0 }, + { 400000000 }, + }, + .reg = { "csiphy2" }, + .interrupt = { "csiphy2" }, + .csiphy = { + .id = 2, + .hw_ops = &csiphy_ops_3ph_1_0, + .formats = &csiphy_formats_sdm845, + } + }, +}; + +static const struct camss_subdev_resources csiphy_res_8775p[] = { + /* CSIPHY0 */ + { + .regulators = { "vdda-phy", "vdda-pll" }, + .clock = { "csiphy_rx", "csiphy0", "csiphy0_timer"}, + .clock_rate = { + { 400000000 }, + { 0 }, + { 400000000 }, + }, + .reg = { "csiphy0" }, + .interrupt = { "csiphy0" }, + .csiphy = { + .id = 0, + .hw_ops = &csiphy_ops_3ph_1_0, + .formats = &csiphy_formats_sdm845 + } + }, + /* CSIPHY1 */ + { + .regulators = { "vdda-phy", "vdda-pll" }, + .clock = { "csiphy_rx", "csiphy1", "csiphy1_timer"}, + .clock_rate = { + { 400000000 }, + { 0 }, + { 400000000 }, + }, + .reg = { "csiphy1" }, + .interrupt = { "csiphy1" }, + .csiphy = { + .id = 1, + .hw_ops = &csiphy_ops_3ph_1_0, + .formats = &csiphy_formats_sdm845 + } + }, + /* CSIPHY2 */ + { + .regulators = { "vdda-phy", "vdda-pll" }, + .clock = { "csiphy_rx", "csiphy2", "csiphy2_timer"}, + .clock_rate = { + { 400000000 }, + { 0 }, + { 400000000 }, + }, + .reg = { "csiphy2" }, + .interrupt = { "csiphy2" }, + .csiphy = { + .id = 2, + .hw_ops = &csiphy_ops_3ph_1_0, + .formats = &csiphy_formats_sdm845 + } + }, + /* CSIPHY3 */ + { + .regulators = { "vdda-phy", "vdda-pll" }, + .clock = { "csiphy_rx", "csiphy3", "csiphy3_timer"}, + .clock_rate = { + { 400000000 }, + { 0 }, + { 400000000 }, + }, + .reg = { "csiphy3" }, + .interrupt = { "csiphy3" }, + .csiphy = { + .id = 3, + .hw_ops = &csiphy_ops_3ph_1_0, + .formats = &csiphy_formats_sdm845 + } + }, +}; + +static const struct camss_subdev_resources csid_res_8775p[] = { + /* CSID0 */ + { + .regulators = {}, + .clock = { "csid", "csiphy_rx"}, + .clock_rate = { + { 400000000, 400000000}, + { 400000000, 400000000} + }, + .reg = { "csid0" }, + .interrupt = { "csid0" }, + .csid = { + .is_lite = false, + .hw_ops = &csid_ops_gen3, + .parent_dev_ops = &vfe_parent_dev_ops, + .formats = &csid_formats_gen2 + } + }, + /* CSID1 */ + { + .regulators = {}, + .clock = { "csid", "csiphy_rx"}, + .clock_rate = { + { 400000000, 400000000}, + { 400000000, 400000000} + }, + .reg = { "csid1" }, + .interrupt = { "csid1" }, + .csid = { + .is_lite = false, + .hw_ops = &csid_ops_gen3, + .parent_dev_ops = &vfe_parent_dev_ops, + .formats = &csid_formats_gen2 + } + }, + + /* CSID2 (lite) */ + { + .regulators = {}, + .clock = { "cpas_vfe_lite", "vfe_lite_ahb", + "vfe_lite_csid", "vfe_lite_cphy_rx", + "vfe_lite"}, + .clock_rate = { + { 0, 0, 400000000, 400000000, 0}, + { 0, 0, 400000000, 480000000, 0} + }, + .reg = { "csid_lite0" }, + .interrupt = { "csid_lite0" }, + .csid = { + .is_lite = true, + .hw_ops = &csid_ops_gen3, + .parent_dev_ops = &vfe_parent_dev_ops, + .formats = &csid_formats_gen2 + } + }, + /* CSID3 (lite) */ + { + .regulators = {}, + .clock = { "cpas_vfe_lite", "vfe_lite_ahb", + "vfe_lite_csid", "vfe_lite_cphy_rx", + "vfe_lite"}, + .clock_rate = { + { 0, 0, 400000000, 400000000, 0}, + { 0, 0, 400000000, 480000000, 0} + }, + .reg = { "csid_lite1" }, + .interrupt = { "csid_lite1" }, + .csid = { + .is_lite = true, + .hw_ops = &csid_ops_gen3, + .parent_dev_ops = &vfe_parent_dev_ops, + .formats = &csid_formats_gen2 + } + }, + /* CSID4 (lite) */ + { + .regulators = {}, + .clock = { "cpas_vfe_lite", "vfe_lite_ahb", + "vfe_lite_csid", "vfe_lite_cphy_rx", + "vfe_lite"}, + .clock_rate = { + { 0, 0, 400000000, 400000000, 0}, + { 0, 0, 400000000, 480000000, 0} + }, + .reg = { "csid_lite2" }, + .interrupt = { "csid_lite2" }, + .csid = { + .is_lite = true, + .hw_ops = &csid_ops_gen3, + .parent_dev_ops = &vfe_parent_dev_ops, + .formats = &csid_formats_gen2 + } + }, + /* CSID5 (lite) */ + { + .regulators = {}, + .clock = { "cpas_vfe_lite", "vfe_lite_ahb", + "vfe_lite_csid", "vfe_lite_cphy_rx", + "vfe_lite"}, + .clock_rate = { + { 0, 0, 400000000, 400000000, 0}, + { 0, 0, 400000000, 480000000, 0} + }, + .reg = { "csid_lite3" }, + .interrupt = { "csid_lite3" }, + .csid = { + .is_lite = true, + .hw_ops = &csid_ops_gen3, + .parent_dev_ops = &vfe_parent_dev_ops, + .formats = &csid_formats_gen2 + } + }, + /* CSID6 (lite) */ + { + .regulators = {}, + .clock = { "cpas_vfe_lite", "vfe_lite_ahb", + "vfe_lite_csid", "vfe_lite_cphy_rx", + "vfe_lite"}, + .clock_rate = { + { 0, 0, 400000000, 400000000, 0}, + { 0, 0, 400000000, 480000000, 0} + }, + .reg = { "csid_lite4" }, + .interrupt = { "csid_lite4" }, + .csid = { + .is_lite = true, + .hw_ops = &csid_ops_gen3, + .parent_dev_ops = &vfe_parent_dev_ops, + .formats = &csid_formats_gen2 + } + }, +}; + +static const struct camss_subdev_resources vfe_res_8775p[] = { + /* VFE0 */ + { + .regulators = {}, + .clock = { "cpas_vfe0", "vfe0", "vfe0_fast_ahb", + "cpas_ahb", "gcc_axi_hf", + "cpas_fast_ahb_clk", + "camnoc_axi"}, + .clock_rate = { + { 0 }, + { 480000000 }, + { 300000000, 400000000 }, + { 300000000, 400000000 }, + { 0 }, + { 300000000, 400000000 }, + { 400000000 }, + }, + .reg = { "vfe0" }, + .interrupt = { "vfe0" }, + .vfe = { + .line_num = 3, + .is_lite = false, + .has_pd = false, + .pd_name = NULL, + .hw_ops = &vfe_ops_gen3, + .formats_rdi = &vfe_formats_rdi_845, + .formats_pix = &vfe_formats_pix_845 + } + }, + /* VFE1 */ + { + .regulators = {}, + .clock = { "cpas_vfe1", "vfe1", "vfe1_fast_ahb", + "cpas_ahb", "gcc_axi_hf", + "cpas_fast_ahb_clk", + "camnoc_axi"}, + .clock_rate = { + { 0 }, + { 480000000 }, + { 300000000, 400000000 }, + { 300000000, 400000000 }, + { 0 }, + { 300000000, 400000000 }, + { 400000000 }, + }, + .reg = { "vfe1" }, + .interrupt = { "vfe1" }, + .vfe = { + .line_num = 3, + .is_lite = false, + .has_pd = false, + .pd_name = NULL, + .hw_ops = &vfe_ops_gen3, + .formats_rdi = &vfe_formats_rdi_845, + .formats_pix = &vfe_formats_pix_845 + } + }, + /* VFE2 (lite) */ + { + .regulators = {}, + .clock = { "cpas_vfe_lite", "vfe_lite_ahb", + "vfe_lite_csid", "vfe_lite_cphy_rx", + "vfe_lite"}, + .clock_rate = { + { 0, 0, 0, 0 }, + { 300000000, 400000000, 400000000, 400000000 }, + { 400000000, 400000000, 400000000, 400000000 }, + { 400000000, 400000000, 400000000, 400000000 }, + { 480000000, 600000000, 600000000, 600000000 }, + }, + .reg = { "vfe_lite0" }, + .interrupt = { "vfe_lite0" }, + .vfe = { + .line_num = 4, + .is_lite = true, + .hw_ops = &vfe_ops_gen3, + .formats_rdi = &vfe_formats_rdi_845, + .formats_pix = &vfe_formats_pix_845 + } + }, + /* VFE3 (lite) */ + { + .regulators = {}, + .clock = { "cpas_vfe_lite", "vfe_lite_ahb", + "vfe_lite_csid", "vfe_lite_cphy_rx", + "vfe_lite"}, + .clock_rate = { + { 0, 0, 0, 0 }, + { 300000000, 400000000, 400000000, 400000000 }, + { 400000000, 400000000, 400000000, 400000000 }, + { 400000000, 400000000, 400000000, 400000000 }, + { 480000000, 600000000, 600000000, 600000000 }, + }, + .reg = { "vfe_lite1" }, + .interrupt = { "vfe_lite1" }, + .vfe = { + .line_num = 4, + .is_lite = true, + .hw_ops = &vfe_ops_gen3, + .formats_rdi = &vfe_formats_rdi_845, + .formats_pix = &vfe_formats_pix_845 + } + }, + /* VFE4 (lite) */ + { + .regulators = {}, + .clock = { "cpas_vfe_lite", "vfe_lite_ahb", + "vfe_lite_csid", "vfe_lite_cphy_rx", + "vfe_lite"}, + .clock_rate = { + { 0, 0, 0, 0 }, + { 300000000, 400000000, 400000000, 400000000 }, + { 400000000, 400000000, 400000000, 400000000 }, + { 400000000, 400000000, 400000000, 400000000 }, + { 480000000, 600000000, 600000000, 600000000 }, + }, + .reg = { "vfe_lite2" }, + .interrupt = { "vfe_lite2" }, + .vfe = { + .line_num = 4, + .is_lite = true, + .hw_ops = &vfe_ops_gen3, + .formats_rdi = &vfe_formats_rdi_845, + .formats_pix = &vfe_formats_pix_845 + } + }, + /* VFE5 (lite) */ + { + .regulators = {}, + .clock = { "cpas_vfe_lite", "vfe_lite_ahb", + "vfe_lite_csid", "vfe_lite_cphy_rx", + "vfe_lite"}, + .clock_rate = { + { 0, 0, 0, 0 }, + { 300000000, 400000000, 400000000, 400000000 }, + { 400000000, 400000000, 400000000, 400000000 }, + { 400000000, 400000000, 400000000, 400000000 }, + { 480000000, 600000000, 600000000, 600000000 }, + }, + .reg = { "vfe_lite3" }, + .interrupt = { "vfe_lite3" }, + .vfe = { + .line_num = 4, + .is_lite = true, + .hw_ops = &vfe_ops_gen3, + .formats_rdi = &vfe_formats_rdi_845, + .formats_pix = &vfe_formats_pix_845 + } + }, + /* VFE6 (lite) */ + { + .regulators = {}, + .clock = { "cpas_vfe_lite", "vfe_lite_ahb", + "vfe_lite_csid", "vfe_lite_cphy_rx", + "vfe_lite"}, + .clock_rate = { + { 0, 0, 0, 0 }, + { 300000000, 400000000, 400000000, 400000000 }, + { 400000000, 400000000, 400000000, 400000000 }, + { 400000000, 400000000, 400000000, 400000000 }, + { 480000000, 600000000, 600000000, 600000000 }, + }, + .reg = { "vfe_lite4" }, + .interrupt = { "vfe_lite4" }, + .vfe = { + .line_num = 4, + .is_lite = true, + .hw_ops = &vfe_ops_gen3, + .formats_rdi = &vfe_formats_rdi_845, + .formats_pix = &vfe_formats_pix_845 + } + }, +}; + +static const struct resources_icc icc_res_qcs8300[] = { + { + .name = "ahb", + .icc_bw_tbl.avg = 38400, + .icc_bw_tbl.peak = 76800, + }, + { + .name = "hf_0", + .icc_bw_tbl.avg = 2097152, + .icc_bw_tbl.peak = 2097152, + }, +}; + +static const struct resources_icc icc_res_sa8775p[] = { + { + .name = "ahb", + .icc_bw_tbl.avg = 38400, + .icc_bw_tbl.peak = 76800, + }, + { + .name = "hf_0", + .icc_bw_tbl.avg = 2097152, + .icc_bw_tbl.peak = 2097152, + }, +}; + static const struct camss_subdev_resources csiphy_res_x1e80100[] = { /* CSIPHY0 */ { @@ -3041,9 +3636,6 @@ static int camss_of_parse_ports(struct camss *camss) for_each_endpoint_of_node(dev->of_node, node) { struct camss_async_subdev *csd; - if (!of_device_is_available(node)) - continue; - remote = of_graph_get_remote_port_parent(node); if (!remote) { dev_err(dev, "Cannot get remote parent\n"); @@ -3143,7 +3735,6 @@ static int camss_init_subdevices(struct camss *camss) } /* - * camss_link_entities - Register subdev nodes and create links * camss_link_err - print error in case link creation fails * @src_name: name for source of the link * @sink_name: name for sink of the link @@ -3557,7 +4148,6 @@ static int camss_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct camss *camss; - int num_subdevs; int ret; camss = devm_kzalloc(dev, sizeof(*camss), GFP_KERNEL); @@ -3628,17 +4218,15 @@ static int camss_probe(struct platform_device *pdev) pm_runtime_enable(dev); - num_subdevs = camss_of_parse_ports(camss); - if (num_subdevs < 0) { - ret = num_subdevs; + ret = camss_of_parse_ports(camss); + if (ret < 0) goto err_v4l2_device_unregister; - } ret = camss_register_entities(camss); if (ret < 0) goto err_v4l2_device_unregister; - ret = camss->res->link_entities(camss); + ret = camss_link_entities(camss); if (ret < 0) goto err_register_subdevs; @@ -3648,23 +4236,12 @@ static int camss_probe(struct platform_device *pdev) goto err_register_subdevs; } - if (num_subdevs) { - camss->notifier.ops = &camss_subdev_notifier_ops; - - ret = v4l2_async_nf_register(&camss->notifier); - if (ret) { - dev_err(dev, - "Failed to register async subdev nodes: %d\n", - ret); - goto err_media_device_unregister; - } - } else { - ret = v4l2_device_register_subdev_nodes(&camss->v4l2_dev); - if (ret < 0) { - dev_err(dev, "Failed to register subdev nodes: %d\n", - ret); - goto err_media_device_unregister; - } + camss->notifier.ops = &camss_subdev_notifier_ops; + ret = v4l2_async_nf_register(&camss->notifier); + if (ret) { + dev_err(dev, + "Failed to register async subdev nodes: %d\n", ret); + goto err_media_device_unregister; } return 0; @@ -3723,7 +4300,6 @@ static const struct camss_resources msm8916_resources = { .csiphy_num = ARRAY_SIZE(csiphy_res_8x16), .csid_num = ARRAY_SIZE(csid_res_8x16), .vfe_num = ARRAY_SIZE(vfe_res_8x16), - .link_entities = camss_link_entities }; static const struct camss_resources msm8953_resources = { @@ -3737,7 +4313,6 @@ static const struct camss_resources msm8953_resources = { .csiphy_num = ARRAY_SIZE(csiphy_res_8x96), .csid_num = ARRAY_SIZE(csid_res_8x53), .vfe_num = ARRAY_SIZE(vfe_res_8x53), - .link_entities = camss_link_entities }; static const struct camss_resources msm8996_resources = { @@ -3749,7 +4324,46 @@ static const struct camss_resources msm8996_resources = { .csiphy_num = ARRAY_SIZE(csiphy_res_8x96), .csid_num = ARRAY_SIZE(csid_res_8x96), .vfe_num = ARRAY_SIZE(vfe_res_8x96), - .link_entities = camss_link_entities +}; + +static const struct camss_resources qcm2290_resources = { + .version = CAMSS_2290, + .csiphy_res = csiphy_res_2290, + .csid_res = csid_res_2290, + .vfe_res = vfe_res_2290, + .icc_res = icc_res_2290, + .icc_path_num = ARRAY_SIZE(icc_res_2290), + .csiphy_num = ARRAY_SIZE(csiphy_res_2290), + .csid_num = ARRAY_SIZE(csid_res_2290), + .vfe_num = ARRAY_SIZE(vfe_res_2290), +}; + +static const struct camss_resources qcs8300_resources = { + .version = CAMSS_8300, + .pd_name = "top", + .csiphy_res = csiphy_res_8300, + .csid_res = csid_res_8775p, + .csid_wrapper_res = &csid_wrapper_res_sm8550, + .vfe_res = vfe_res_8775p, + .icc_res = icc_res_qcs8300, + .csiphy_num = ARRAY_SIZE(csiphy_res_8300), + .csid_num = ARRAY_SIZE(csid_res_8775p), + .vfe_num = ARRAY_SIZE(vfe_res_8775p), + .icc_path_num = ARRAY_SIZE(icc_res_qcs8300), +}; + +static const struct camss_resources sa8775p_resources = { + .version = CAMSS_8775P, + .pd_name = "top", + .csiphy_res = csiphy_res_8775p, + .csid_res = csid_res_8775p, + .csid_wrapper_res = &csid_wrapper_res_sm8550, + .vfe_res = vfe_res_8775p, + .icc_res = icc_res_sa8775p, + .csiphy_num = ARRAY_SIZE(csiphy_res_8775p), + .csid_num = ARRAY_SIZE(csid_res_8775p), + .vfe_num = ARRAY_SIZE(vfe_res_8775p), + .icc_path_num = ARRAY_SIZE(icc_res_sa8775p), }; static const struct camss_resources sdm660_resources = { @@ -3761,7 +4375,6 @@ static const struct camss_resources sdm660_resources = { .csiphy_num = ARRAY_SIZE(csiphy_res_660), .csid_num = ARRAY_SIZE(csid_res_660), .vfe_num = ARRAY_SIZE(vfe_res_660), - .link_entities = camss_link_entities }; static const struct camss_resources sdm670_resources = { @@ -3772,7 +4385,6 @@ static const struct camss_resources sdm670_resources = { .csiphy_num = ARRAY_SIZE(csiphy_res_670), .csid_num = ARRAY_SIZE(csid_res_670), .vfe_num = ARRAY_SIZE(vfe_res_670), - .link_entities = camss_link_entities }; static const struct camss_resources sdm845_resources = { @@ -3784,7 +4396,6 @@ static const struct camss_resources sdm845_resources = { .csiphy_num = ARRAY_SIZE(csiphy_res_845), .csid_num = ARRAY_SIZE(csid_res_845), .vfe_num = ARRAY_SIZE(vfe_res_845), - .link_entities = camss_link_entities }; static const struct camss_resources sm8250_resources = { @@ -3798,7 +4409,6 @@ static const struct camss_resources sm8250_resources = { .csiphy_num = ARRAY_SIZE(csiphy_res_8250), .csid_num = ARRAY_SIZE(csid_res_8250), .vfe_num = ARRAY_SIZE(vfe_res_8250), - .link_entities = camss_link_entities }; static const struct camss_resources sc8280xp_resources = { @@ -3813,7 +4423,6 @@ static const struct camss_resources sc8280xp_resources = { .csiphy_num = ARRAY_SIZE(csiphy_res_sc8280xp), .csid_num = ARRAY_SIZE(csid_res_sc8280xp), .vfe_num = ARRAY_SIZE(vfe_res_sc8280xp), - .link_entities = camss_link_entities }; static const struct camss_resources sc7280_resources = { @@ -3827,7 +4436,6 @@ static const struct camss_resources sc7280_resources = { .csiphy_num = ARRAY_SIZE(csiphy_res_7280), .csid_num = ARRAY_SIZE(csid_res_7280), .vfe_num = ARRAY_SIZE(vfe_res_7280), - .link_entities = camss_link_entities }; static const struct camss_resources sm8550_resources = { @@ -3842,7 +4450,6 @@ static const struct camss_resources sm8550_resources = { .csiphy_num = ARRAY_SIZE(csiphy_res_8550), .csid_num = ARRAY_SIZE(csid_res_8550), .vfe_num = ARRAY_SIZE(vfe_res_8550), - .link_entities = camss_link_entities }; static const struct camss_resources x1e80100_resources = { @@ -3857,13 +4464,15 @@ static const struct camss_resources x1e80100_resources = { .csiphy_num = ARRAY_SIZE(csiphy_res_x1e80100), .csid_num = ARRAY_SIZE(csid_res_x1e80100), .vfe_num = ARRAY_SIZE(vfe_res_x1e80100), - .link_entities = camss_link_entities }; static const struct of_device_id camss_dt_match[] = { { .compatible = "qcom,msm8916-camss", .data = &msm8916_resources }, { .compatible = "qcom,msm8953-camss", .data = &msm8953_resources }, { .compatible = "qcom,msm8996-camss", .data = &msm8996_resources }, + { .compatible = "qcom,qcm2290-camss", .data = &qcm2290_resources }, + { .compatible = "qcom,qcs8300-camss", .data = &qcs8300_resources }, + { .compatible = "qcom,sa8775p-camss", .data = &sa8775p_resources }, { .compatible = "qcom,sc7280-camss", .data = &sc7280_resources }, { .compatible = "qcom,sc8280xp-camss", .data = &sc8280xp_resources }, { .compatible = "qcom,sdm660-camss", .data = &sdm660_resources }, diff --git a/drivers/media/platform/qcom/camss/camss.h b/drivers/media/platform/qcom/camss/camss.h index 63c0afee154a..a70fbc78ccc3 100644 --- a/drivers/media/platform/qcom/camss/camss.h +++ b/drivers/media/platform/qcom/camss/camss.h @@ -78,14 +78,17 @@ enum pm_domain { enum camss_version { CAMSS_660, + CAMSS_2290, CAMSS_7280, CAMSS_8x16, CAMSS_8x53, CAMSS_8x96, CAMSS_8250, CAMSS_8280XP, + CAMSS_8300, CAMSS_845, CAMSS_8550, + CAMSS_8775P, CAMSS_X1E80100, }; @@ -107,7 +110,6 @@ struct camss_resources { const unsigned int csiphy_num; const unsigned int csid_num; const unsigned int vfe_num; - int (*link_entities)(struct camss *camss); }; struct camss { diff --git a/drivers/media/platform/qcom/iris/Makefile b/drivers/media/platform/qcom/iris/Makefile index e86d00ee6f15..13270cd6d899 100644 --- a/drivers/media/platform/qcom/iris/Makefile +++ b/drivers/media/platform/qcom/iris/Makefile @@ -1,5 +1,5 @@ -qcom-iris-objs += \ - iris_buffer.o \ +qcom-iris-objs += iris_buffer.o \ + iris_common.o \ iris_core.o \ iris_ctrls.o \ iris_firmware.o \ @@ -19,6 +19,7 @@ qcom-iris-objs += \ iris_vidc.o \ iris_vb2.o \ iris_vdec.o \ + iris_venc.o \ iris_vpu2.o \ iris_vpu3x.o \ iris_vpu_buffer.o \ diff --git a/drivers/media/platform/qcom/iris/iris_buffer.c b/drivers/media/platform/qcom/iris/iris_buffer.c index 6425e4919e3b..c0900038e7de 100644 --- a/drivers/media/platform/qcom/iris/iris_buffer.c +++ b/drivers/media/platform/qcom/iris/iris_buffer.c @@ -63,7 +63,12 @@ static u32 iris_yuv_buffer_size_nv12(struct iris_inst *inst) { u32 y_plane, uv_plane, y_stride, uv_stride, y_scanlines, uv_scanlines; - struct v4l2_format *f = inst->fmt_dst; + struct v4l2_format *f; + + if (inst->domain == DECODER) + f = inst->fmt_dst; + else + f = inst->fmt_src; y_stride = ALIGN(f->fmt.pix_mp.width, Y_STRIDE_ALIGN); uv_stride = ALIGN(f->fmt.pix_mp.width, UV_STRIDE_ALIGN); @@ -194,7 +199,7 @@ static u32 iris_yuv_buffer_size_qc08c(struct iris_inst *inst) return ALIGN(y_meta_plane + y_plane + uv_meta_plane + uv_plane, PIXELS_4K); } -static u32 iris_bitstream_buffer_size(struct iris_inst *inst) +static u32 iris_dec_bitstream_buffer_size(struct iris_inst *inst) { struct platform_inst_caps *caps = inst->core->iris_platform_data->inst_caps; u32 base_res_mbs = NUM_MBS_4K; @@ -219,18 +224,58 @@ static u32 iris_bitstream_buffer_size(struct iris_inst *inst) return ALIGN(frame_size, PIXELS_4K); } +static u32 iris_enc_bitstream_buffer_size(struct iris_inst *inst) +{ + u32 aligned_width, aligned_height, bitstream_size, yuv_size; + int bitrate_mode, frame_rc; + struct v4l2_format *f; + + f = inst->fmt_dst; + + bitrate_mode = inst->fw_caps[BITRATE_MODE].value; + frame_rc = inst->fw_caps[FRAME_RC_ENABLE].value; + + aligned_width = ALIGN(f->fmt.pix_mp.width, 32); + aligned_height = ALIGN(f->fmt.pix_mp.height, 32); + bitstream_size = aligned_width * aligned_height * 3; + yuv_size = (aligned_width * aligned_height * 3) >> 1; + if (aligned_width * aligned_height > (4096 * 2176)) + /* bitstream_size = 0.25 * yuv_size; */ + bitstream_size = (bitstream_size >> 3); + else if (aligned_width * aligned_height > (1280 * 720)) + /* bitstream_size = 0.5 * yuv_size; */ + bitstream_size = (bitstream_size >> 2); + + if ((!frame_rc || bitrate_mode == V4L2_MPEG_VIDEO_BITRATE_MODE_CQ) && + bitstream_size < yuv_size) + bitstream_size = (bitstream_size << 1); + + return ALIGN(bitstream_size, 4096); +} + int iris_get_buffer_size(struct iris_inst *inst, enum iris_buffer_type buffer_type) { - switch (buffer_type) { - case BUF_INPUT: - return iris_bitstream_buffer_size(inst); - case BUF_OUTPUT: - return iris_yuv_buffer_size_nv12(inst); - case BUF_DPB: - return iris_yuv_buffer_size_qc08c(inst); - default: - return 0; + if (inst->domain == DECODER) { + switch (buffer_type) { + case BUF_INPUT: + return iris_dec_bitstream_buffer_size(inst); + case BUF_OUTPUT: + return iris_yuv_buffer_size_nv12(inst); + case BUF_DPB: + return iris_yuv_buffer_size_qc08c(inst); + default: + return 0; + } + } else { + switch (buffer_type) { + case BUF_INPUT: + return iris_yuv_buffer_size_nv12(inst); + case BUF_OUTPUT: + return iris_enc_bitstream_buffer_size(inst); + default: + return 0; + } } } @@ -239,7 +284,7 @@ static void iris_fill_internal_buf_info(struct iris_inst *inst, { struct iris_buffers *buffers = &inst->buffers[buffer_type]; - buffers->size = iris_vpu_buf_size(inst, buffer_type); + buffers->size = inst->core->iris_platform_data->get_vpu_buffer_size(inst, buffer_type); buffers->min_count = iris_vpu_buf_count(inst, buffer_type); } @@ -249,16 +294,30 @@ void iris_get_internal_buffers(struct iris_inst *inst, u32 plane) const u32 *internal_buf_type; u32 internal_buffer_count, i; - if (V4L2_TYPE_IS_OUTPUT(plane)) { - internal_buf_type = platform_data->dec_ip_int_buf_tbl; - internal_buffer_count = platform_data->dec_ip_int_buf_tbl_size; - for (i = 0; i < internal_buffer_count; i++) - iris_fill_internal_buf_info(inst, internal_buf_type[i]); + if (inst->domain == DECODER) { + if (V4L2_TYPE_IS_OUTPUT(plane)) { + internal_buf_type = platform_data->dec_ip_int_buf_tbl; + internal_buffer_count = platform_data->dec_ip_int_buf_tbl_size; + for (i = 0; i < internal_buffer_count; i++) + iris_fill_internal_buf_info(inst, internal_buf_type[i]); + } else { + internal_buf_type = platform_data->dec_op_int_buf_tbl; + internal_buffer_count = platform_data->dec_op_int_buf_tbl_size; + for (i = 0; i < internal_buffer_count; i++) + iris_fill_internal_buf_info(inst, internal_buf_type[i]); + } } else { - internal_buf_type = platform_data->dec_op_int_buf_tbl; - internal_buffer_count = platform_data->dec_op_int_buf_tbl_size; - for (i = 0; i < internal_buffer_count; i++) - iris_fill_internal_buf_info(inst, internal_buf_type[i]); + if (V4L2_TYPE_IS_OUTPUT(plane)) { + internal_buf_type = platform_data->enc_ip_int_buf_tbl; + internal_buffer_count = platform_data->enc_ip_int_buf_tbl_size; + for (i = 0; i < internal_buffer_count; i++) + iris_fill_internal_buf_info(inst, internal_buf_type[i]); + } else { + internal_buf_type = platform_data->enc_op_int_buf_tbl; + internal_buffer_count = platform_data->enc_op_int_buf_tbl_size; + for (i = 0; i < internal_buffer_count; i++) + iris_fill_internal_buf_info(inst, internal_buf_type[i]); + } } } @@ -299,12 +358,22 @@ int iris_create_internal_buffers(struct iris_inst *inst, u32 plane) const u32 *internal_buf_type; int ret; - if (V4L2_TYPE_IS_OUTPUT(plane)) { - internal_buf_type = platform_data->dec_ip_int_buf_tbl; - internal_buffer_count = platform_data->dec_ip_int_buf_tbl_size; + if (inst->domain == DECODER) { + if (V4L2_TYPE_IS_OUTPUT(plane)) { + internal_buf_type = platform_data->dec_ip_int_buf_tbl; + internal_buffer_count = platform_data->dec_ip_int_buf_tbl_size; + } else { + internal_buf_type = platform_data->dec_op_int_buf_tbl; + internal_buffer_count = platform_data->dec_op_int_buf_tbl_size; + } } else { - internal_buf_type = platform_data->dec_op_int_buf_tbl; - internal_buffer_count = platform_data->dec_op_int_buf_tbl_size; + if (V4L2_TYPE_IS_OUTPUT(plane)) { + internal_buf_type = platform_data->enc_ip_int_buf_tbl; + internal_buffer_count = platform_data->enc_ip_int_buf_tbl_size; + } else { + internal_buf_type = platform_data->enc_op_int_buf_tbl; + internal_buffer_count = platform_data->enc_op_int_buf_tbl_size; + } } for (i = 0; i < internal_buffer_count; i++) { @@ -334,6 +403,29 @@ int iris_queue_buffer(struct iris_inst *inst, struct iris_buffer *buf) return 0; } +int iris_queue_internal_deferred_buffers(struct iris_inst *inst, enum iris_buffer_type buffer_type) +{ + struct iris_buffer *buffer, *next; + struct iris_buffers *buffers; + int ret = 0; + + buffers = &inst->buffers[buffer_type]; + list_for_each_entry_safe(buffer, next, &buffers->list, list) { + if (buffer->attr & BUF_ATTR_PENDING_RELEASE) + continue; + if (buffer->attr & BUF_ATTR_QUEUED) + continue; + + if (buffer->attr & BUF_ATTR_DEFERRED) { + ret = iris_queue_buffer(inst, buffer); + if (ret) + return ret; + } + } + + return ret; +} + int iris_queue_internal_buffers(struct iris_inst *inst, u32 plane) { const struct iris_platform_data *platform_data = inst->core->iris_platform_data; @@ -343,12 +435,22 @@ int iris_queue_internal_buffers(struct iris_inst *inst, u32 plane) u32 internal_buffer_count, i; int ret; - if (V4L2_TYPE_IS_OUTPUT(plane)) { - internal_buf_type = platform_data->dec_ip_int_buf_tbl; - internal_buffer_count = platform_data->dec_ip_int_buf_tbl_size; + if (inst->domain == DECODER) { + if (V4L2_TYPE_IS_OUTPUT(plane)) { + internal_buf_type = platform_data->dec_ip_int_buf_tbl; + internal_buffer_count = platform_data->dec_ip_int_buf_tbl_size; + } else { + internal_buf_type = platform_data->dec_op_int_buf_tbl; + internal_buffer_count = platform_data->dec_op_int_buf_tbl_size; + } } else { - internal_buf_type = platform_data->dec_op_int_buf_tbl; - internal_buffer_count = platform_data->dec_op_int_buf_tbl_size; + if (V4L2_TYPE_IS_OUTPUT(plane)) { + internal_buf_type = platform_data->enc_ip_int_buf_tbl; + internal_buffer_count = platform_data->enc_ip_int_buf_tbl_size; + } else { + internal_buf_type = platform_data->enc_op_int_buf_tbl; + internal_buffer_count = platform_data->enc_op_int_buf_tbl_size; + } } for (i = 0; i < internal_buffer_count; i++) { @@ -358,6 +460,10 @@ int iris_queue_internal_buffers(struct iris_inst *inst, u32 plane) continue; if (buffer->attr & BUF_ATTR_QUEUED) continue; + if (buffer->type == BUF_DPB && inst->state != IRIS_INST_STREAMING) { + buffer->attr |= BUF_ATTR_DEFERRED; + continue; + } ret = iris_queue_buffer(inst, buffer); if (ret) return ret; @@ -388,12 +494,22 @@ static int iris_destroy_internal_buffers(struct iris_inst *inst, u32 plane, bool u32 i, len; int ret; - if (V4L2_TYPE_IS_OUTPUT(plane)) { - internal_buf_type = platform_data->dec_ip_int_buf_tbl; - len = platform_data->dec_ip_int_buf_tbl_size; + if (inst->domain == DECODER) { + if (V4L2_TYPE_IS_OUTPUT(plane)) { + internal_buf_type = platform_data->dec_ip_int_buf_tbl; + len = platform_data->dec_ip_int_buf_tbl_size; + } else { + internal_buf_type = platform_data->dec_op_int_buf_tbl; + len = platform_data->dec_op_int_buf_tbl_size; + } } else { - internal_buf_type = platform_data->dec_op_int_buf_tbl; - len = platform_data->dec_op_int_buf_tbl_size; + if (V4L2_TYPE_IS_OUTPUT(plane)) { + internal_buf_type = platform_data->enc_ip_int_buf_tbl; + len = platform_data->enc_ip_int_buf_tbl_size; + } else { + internal_buf_type = platform_data->enc_op_int_buf_tbl; + len = platform_data->enc_op_int_buf_tbl_size; + } } for (i = 0; i < len; i++) { @@ -413,6 +529,19 @@ static int iris_destroy_internal_buffers(struct iris_inst *inst, u32 plane, bool } } + if (force) { + if (inst->domain == DECODER) + buffers = &inst->buffers[BUF_PERSIST]; + else + buffers = &inst->buffers[BUF_ARP]; + + list_for_each_entry_safe(buf, next, &buffers->list, list) { + ret = iris_destroy_internal_buffer(inst, buf); + if (ret) + return ret; + } + } + return 0; } @@ -455,8 +584,13 @@ static int iris_release_input_internal_buffers(struct iris_inst *inst) u32 internal_buffer_count, i; int ret; - internal_buf_type = platform_data->dec_ip_int_buf_tbl; - internal_buffer_count = platform_data->dec_ip_int_buf_tbl_size; + if (inst->domain == DECODER) { + internal_buf_type = platform_data->dec_ip_int_buf_tbl; + internal_buffer_count = platform_data->dec_ip_int_buf_tbl_size; + } else { + internal_buf_type = platform_data->enc_ip_int_buf_tbl; + internal_buffer_count = platform_data->enc_ip_int_buf_tbl_size; + } for (i = 0; i < internal_buffer_count; i++) { ret = iris_release_internal_buffers(inst, internal_buf_type[i]); @@ -467,9 +601,9 @@ static int iris_release_input_internal_buffers(struct iris_inst *inst) return 0; } -int iris_alloc_and_queue_persist_bufs(struct iris_inst *inst) +int iris_alloc_and_queue_persist_bufs(struct iris_inst *inst, enum iris_buffer_type buffer_type) { - struct iris_buffers *buffers = &inst->buffers[BUF_PERSIST]; + struct iris_buffers *buffers = &inst->buffers[buffer_type]; struct iris_buffer *buffer, *next; int ret; u32 i; @@ -477,10 +611,10 @@ int iris_alloc_and_queue_persist_bufs(struct iris_inst *inst) if (!list_empty(&buffers->list)) return 0; - iris_fill_internal_buf_info(inst, BUF_PERSIST); + iris_fill_internal_buf_info(inst, buffer_type); for (i = 0; i < buffers->min_count; i++) { - ret = iris_create_internal_buffer(inst, BUF_PERSIST, i); + ret = iris_create_internal_buffer(inst, buffer_type, i); if (ret) return ret; } @@ -614,6 +748,8 @@ int iris_vb2_buffer_done(struct iris_inst *inst, struct iris_buffer *buf) vb2 = &vbuf->vb2_buf; + vbuf->flags |= buf->flags; + if (buf->flags & V4L2_BUF_FLAG_ERROR) { state = VB2_BUF_STATE_ERROR; vb2_set_plane_payload(vb2, 0, 0); @@ -622,8 +758,6 @@ int iris_vb2_buffer_done(struct iris_inst *inst, struct iris_buffer *buf) return 0; } - vbuf->flags |= buf->flags; - if (V4L2_TYPE_IS_CAPTURE(type)) { vb2_set_plane_payload(vb2, 0, buf->data_size); vbuf->sequence = inst->sequence_cap++; diff --git a/drivers/media/platform/qcom/iris/iris_buffer.h b/drivers/media/platform/qcom/iris/iris_buffer.h index 00825ad2dc3a..325d30fce5c9 100644 --- a/drivers/media/platform/qcom/iris/iris_buffer.h +++ b/drivers/media/platform/qcom/iris/iris_buffer.h @@ -25,6 +25,8 @@ struct iris_inst; * @BUF_DPB: buffer to store display picture buffers for reference * @BUF_PERSIST: buffer to store session context data * @BUF_SCRATCH_1: buffer to store decoding/encoding context data for HW + * @BUF_SCRATCH_2: buffer to store encoding context data for HW + * @BUF_VPSS: buffer to store VPSS context data for HW * @BUF_TYPE_MAX: max buffer types */ enum iris_buffer_type { @@ -38,6 +40,8 @@ enum iris_buffer_type { BUF_DPB, BUF_PERSIST, BUF_SCRATCH_1, + BUF_SCRATCH_2, + BUF_VPSS, BUF_TYPE_MAX, }; @@ -105,10 +109,11 @@ int iris_get_buffer_size(struct iris_inst *inst, enum iris_buffer_type buffer_ty void iris_get_internal_buffers(struct iris_inst *inst, u32 plane); int iris_create_internal_buffers(struct iris_inst *inst, u32 plane); int iris_queue_internal_buffers(struct iris_inst *inst, u32 plane); +int iris_queue_internal_deferred_buffers(struct iris_inst *inst, enum iris_buffer_type buffer_type); int iris_destroy_internal_buffer(struct iris_inst *inst, struct iris_buffer *buffer); int iris_destroy_all_internal_buffers(struct iris_inst *inst, u32 plane); int iris_destroy_dequeued_internal_buffers(struct iris_inst *inst, u32 plane); -int iris_alloc_and_queue_persist_bufs(struct iris_inst *inst); +int iris_alloc_and_queue_persist_bufs(struct iris_inst *inst, enum iris_buffer_type buf_type); int iris_alloc_and_queue_input_int_bufs(struct iris_inst *inst); int iris_queue_buffer(struct iris_inst *inst, struct iris_buffer *buf); int iris_queue_deferred_buffers(struct iris_inst *inst, enum iris_buffer_type buf_type); diff --git a/drivers/media/platform/qcom/iris/iris_common.c b/drivers/media/platform/qcom/iris/iris_common.c new file mode 100644 index 000000000000..9fc663bdaf3f --- /dev/null +++ b/drivers/media/platform/qcom/iris/iris_common.c @@ -0,0 +1,232 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2022-2025 Qualcomm Innovation Center, Inc. All rights reserved. + */ + +#include <media/v4l2-mem2mem.h> + +#include "iris_common.h" +#include "iris_ctrls.h" +#include "iris_instance.h" +#include "iris_power.h" + +int iris_vb2_buffer_to_driver(struct vb2_buffer *vb2, struct iris_buffer *buf) +{ + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb2); + + buf->type = iris_v4l2_type_to_driver(vb2->type); + buf->index = vb2->index; + buf->fd = vb2->planes[0].m.fd; + buf->buffer_size = vb2->planes[0].length; + buf->data_offset = vb2->planes[0].data_offset; + buf->data_size = vb2->planes[0].bytesused - vb2->planes[0].data_offset; + buf->flags = vbuf->flags; + buf->timestamp = vb2->timestamp; + buf->attr = 0; + + return 0; +} + +void iris_set_ts_metadata(struct iris_inst *inst, struct vb2_v4l2_buffer *vbuf) +{ + u32 mask = V4L2_BUF_FLAG_TIMECODE | V4L2_BUF_FLAG_TSTAMP_SRC_MASK; + struct vb2_buffer *vb = &vbuf->vb2_buf; + u64 ts_us = vb->timestamp; + + if (inst->metadata_idx >= ARRAY_SIZE(inst->tss)) + inst->metadata_idx = 0; + + do_div(ts_us, NSEC_PER_USEC); + + inst->tss[inst->metadata_idx].flags = vbuf->flags & mask; + inst->tss[inst->metadata_idx].tc = vbuf->timecode; + inst->tss[inst->metadata_idx].ts_us = ts_us; + inst->tss[inst->metadata_idx].ts_ns = vb->timestamp; + + inst->metadata_idx++; +} + +int iris_process_streamon_input(struct iris_inst *inst) +{ + const struct iris_hfi_command_ops *hfi_ops = inst->core->hfi_ops; + enum iris_inst_sub_state set_sub_state = 0; + int ret; + + iris_scale_power(inst); + + ret = hfi_ops->session_start(inst, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); + if (ret) + return ret; + + if (inst->sub_state & IRIS_INST_SUB_INPUT_PAUSE) { + ret = iris_inst_change_sub_state(inst, IRIS_INST_SUB_INPUT_PAUSE, 0); + if (ret) + return ret; + } + + if (inst->domain == DECODER && + (inst->sub_state & IRIS_INST_SUB_DRC || + inst->sub_state & IRIS_INST_SUB_DRAIN || + inst->sub_state & IRIS_INST_SUB_FIRST_IPSC)) { + if (!(inst->sub_state & IRIS_INST_SUB_INPUT_PAUSE)) { + if (hfi_ops->session_pause) { + ret = hfi_ops->session_pause(inst, + V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); + if (ret) + return ret; + } + set_sub_state = IRIS_INST_SUB_INPUT_PAUSE; + } + } + + ret = iris_inst_state_change_streamon(inst, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); + if (ret) + return ret; + + inst->last_buffer_dequeued = false; + + return iris_inst_change_sub_state(inst, 0, set_sub_state); +} + +int iris_process_streamon_output(struct iris_inst *inst) +{ + const struct iris_hfi_command_ops *hfi_ops = inst->core->hfi_ops; + bool drain_active = false, drc_active = false; + enum iris_inst_sub_state clear_sub_state = 0; + int ret = 0; + + iris_scale_power(inst); + + drain_active = inst->sub_state & IRIS_INST_SUB_DRAIN && + inst->sub_state & IRIS_INST_SUB_DRAIN_LAST; + + drc_active = inst->sub_state & IRIS_INST_SUB_DRC && + inst->sub_state & IRIS_INST_SUB_DRC_LAST; + + if (drc_active) + clear_sub_state = IRIS_INST_SUB_DRC | IRIS_INST_SUB_DRC_LAST; + else if (drain_active) + clear_sub_state = IRIS_INST_SUB_DRAIN | IRIS_INST_SUB_DRAIN_LAST; + + if (inst->domain == DECODER && inst->sub_state & IRIS_INST_SUB_INPUT_PAUSE) { + ret = iris_alloc_and_queue_input_int_bufs(inst); + if (ret) + return ret; + ret = iris_set_stage(inst, STAGE); + if (ret) + return ret; + ret = iris_set_pipe(inst, PIPE); + if (ret) + return ret; + } + + if (inst->state == IRIS_INST_INPUT_STREAMING && + inst->sub_state & IRIS_INST_SUB_INPUT_PAUSE) { + if (!drain_active) + ret = hfi_ops->session_resume_drc(inst, + V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); + else if (hfi_ops->session_resume_drain) + ret = hfi_ops->session_resume_drain(inst, + V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); + if (ret) + return ret; + clear_sub_state |= IRIS_INST_SUB_INPUT_PAUSE; + } + + if (inst->sub_state & IRIS_INST_SUB_FIRST_IPSC) + clear_sub_state |= IRIS_INST_SUB_FIRST_IPSC; + + ret = hfi_ops->session_start(inst, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE); + if (ret) + return ret; + + if (inst->sub_state & IRIS_INST_SUB_OUTPUT_PAUSE) + clear_sub_state |= IRIS_INST_SUB_OUTPUT_PAUSE; + + ret = iris_inst_state_change_streamon(inst, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE); + if (ret) + return ret; + + inst->last_buffer_dequeued = false; + + return iris_inst_change_sub_state(inst, clear_sub_state, 0); +} + +static void iris_flush_deferred_buffers(struct iris_inst *inst, + enum iris_buffer_type type) +{ + struct v4l2_m2m_ctx *m2m_ctx = inst->m2m_ctx; + struct v4l2_m2m_buffer *buffer, *n; + struct iris_buffer *buf; + + if (type == BUF_INPUT) { + v4l2_m2m_for_each_src_buf_safe(m2m_ctx, buffer, n) { + buf = to_iris_buffer(&buffer->vb); + if (buf->attr & BUF_ATTR_DEFERRED) { + if (!(buf->attr & BUF_ATTR_BUFFER_DONE)) { + buf->attr |= BUF_ATTR_BUFFER_DONE; + buf->data_size = 0; + iris_vb2_buffer_done(inst, buf); + } + } + } + } else { + v4l2_m2m_for_each_dst_buf_safe(m2m_ctx, buffer, n) { + buf = to_iris_buffer(&buffer->vb); + if (buf->attr & BUF_ATTR_DEFERRED) { + if (!(buf->attr & BUF_ATTR_BUFFER_DONE)) { + buf->attr |= BUF_ATTR_BUFFER_DONE; + buf->data_size = 0; + iris_vb2_buffer_done(inst, buf); + } + } + } + } +} + +static void iris_kill_session(struct iris_inst *inst) +{ + const struct iris_hfi_command_ops *hfi_ops = inst->core->hfi_ops; + + if (!inst->session_id) + return; + + hfi_ops->session_close(inst); + iris_inst_change_state(inst, IRIS_INST_ERROR); +} + +int iris_session_streamoff(struct iris_inst *inst, u32 plane) +{ + const struct iris_hfi_command_ops *hfi_ops = inst->core->hfi_ops; + enum iris_buffer_type buffer_type; + int ret; + + switch (plane) { + case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: + buffer_type = BUF_INPUT; + break; + case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: + buffer_type = BUF_OUTPUT; + break; + default: + return -EINVAL; + } + + ret = hfi_ops->session_stop(inst, plane); + if (ret) + goto error; + + ret = iris_inst_state_change_streamoff(inst, plane); + if (ret) + goto error; + + iris_flush_deferred_buffers(inst, buffer_type); + + return 0; + +error: + iris_kill_session(inst); + iris_flush_deferred_buffers(inst, buffer_type); + + return ret; +} diff --git a/drivers/media/platform/qcom/iris/iris_common.h b/drivers/media/platform/qcom/iris/iris_common.h new file mode 100644 index 000000000000..b2a27b781c9a --- /dev/null +++ b/drivers/media/platform/qcom/iris/iris_common.h @@ -0,0 +1,18 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2022-2025 Qualcomm Innovation Center, Inc. All rights reserved. + */ + +#ifndef __IRIS_COMMON_H__ +#define __IRIS_COMMON_H__ + +struct iris_inst; +struct iris_buffer; + +int iris_vb2_buffer_to_driver(struct vb2_buffer *vb2, struct iris_buffer *buf); +void iris_set_ts_metadata(struct iris_inst *inst, struct vb2_v4l2_buffer *vbuf); +int iris_process_streamon_input(struct iris_inst *inst); +int iris_process_streamon_output(struct iris_inst *inst); +int iris_session_streamoff(struct iris_inst *inst, u32 plane); + +#endif diff --git a/drivers/media/platform/qcom/iris/iris_core.c b/drivers/media/platform/qcom/iris/iris_core.c index 0fa0a3b549a2..8406c48d635b 100644 --- a/drivers/media/platform/qcom/iris/iris_core.c +++ b/drivers/media/platform/qcom/iris/iris_core.c @@ -15,10 +15,12 @@ void iris_core_deinit(struct iris_core *core) pm_runtime_resume_and_get(core->dev); mutex_lock(&core->lock); - iris_fw_unload(core); - iris_vpu_power_off(core); - iris_hfi_queues_deinit(core); - core->state = IRIS_CORE_DEINIT; + if (core->state != IRIS_CORE_DEINIT) { + iris_fw_unload(core); + iris_vpu_power_off(core); + iris_hfi_queues_deinit(core); + core->state = IRIS_CORE_DEINIT; + } mutex_unlock(&core->lock); pm_runtime_put_sync(core->dev); diff --git a/drivers/media/platform/qcom/iris/iris_core.h b/drivers/media/platform/qcom/iris/iris_core.h index aeeac32a1f6d..fb194c967ad4 100644 --- a/drivers/media/platform/qcom/iris/iris_core.h +++ b/drivers/media/platform/qcom/iris/iris_core.h @@ -25,6 +25,11 @@ struct icc_info { #define IRIS_FW_VERSION_LENGTH 128 #define IFACEQ_CORE_PKT_SIZE (1024 * 4) +enum domain_type { + ENCODER = BIT(0), + DECODER = BIT(1), +}; + /** * struct iris_core - holds core parameters valid for all instances * @@ -33,8 +38,10 @@ struct icc_info { * @irq: iris irq * @v4l2_dev: a holder for v4l2 device structure * @vdev_dec: iris video device structure for decoder + * @vdev_enc: iris video device structure for encoder * @iris_v4l2_file_ops: iris v4l2 file ops - * @iris_v4l2_ioctl_ops: iris v4l2 ioctl ops + * @iris_v4l2_ioctl_ops_dec: iris v4l2 ioctl ops for decoder + * @iris_v4l2_ioctl_ops_enc: iris v4l2 ioctl ops for encoder * @iris_vb2_ops: iris vb2 ops * @icc_tbl: table of iris interconnects * @icc_count: count of iris interconnects @@ -64,7 +71,8 @@ struct icc_info { * @intr_status: interrupt status * @sys_error_handler: a delayed work for handling system fatal error * @instances: a list_head of all instances - * @inst_fw_caps: an array of supported instance capabilities + * @inst_fw_caps_dec: an array of supported instance capabilities by decoder + * @inst_fw_caps_enc: an array of supported instance capabilities by encoder */ struct iris_core { @@ -73,8 +81,10 @@ struct iris_core { int irq; struct v4l2_device v4l2_dev; struct video_device *vdev_dec; + struct video_device *vdev_enc; const struct v4l2_file_operations *iris_v4l2_file_ops; - const struct v4l2_ioctl_ops *iris_v4l2_ioctl_ops; + const struct v4l2_ioctl_ops *iris_v4l2_ioctl_ops_dec; + const struct v4l2_ioctl_ops *iris_v4l2_ioctl_ops_enc; const struct vb2_ops *iris_vb2_ops; struct icc_bulk_data *icc_tbl; u32 icc_count; @@ -104,7 +114,9 @@ struct iris_core { u32 intr_status; struct delayed_work sys_error_handler; struct list_head instances; - struct platform_inst_fw_cap inst_fw_caps[INST_FW_CAP_MAX]; + /* encoder and decoder have overlapping caps, so two different arrays are required */ + struct platform_inst_fw_cap inst_fw_caps_dec[INST_FW_CAP_MAX]; + struct platform_inst_fw_cap inst_fw_caps_enc[INST_FW_CAP_MAX]; }; int iris_core_init(struct iris_core *core); diff --git a/drivers/media/platform/qcom/iris/iris_ctrls.c b/drivers/media/platform/qcom/iris/iris_ctrls.c index 9136b723c0f2..754a5ad718bc 100644 --- a/drivers/media/platform/qcom/iris/iris_ctrls.c +++ b/drivers/media/platform/qcom/iris/iris_ctrls.c @@ -7,8 +7,13 @@ #include <media/v4l2-mem2mem.h> #include "iris_ctrls.h" +#include "iris_hfi_gen1_defines.h" +#include "iris_hfi_gen2_defines.h" #include "iris_instance.h" +#define CABAC_MAX_BITRATE 160000000 +#define CAVLC_MAX_BITRATE 220000000 + static inline bool iris_valid_cap_id(enum platform_inst_fw_cap_type cap_id) { return cap_id >= 1 && cap_id < INST_FW_CAP_MAX; @@ -31,6 +36,68 @@ static enum platform_inst_fw_cap_type iris_get_cap_id(u32 id) return LEVEL_VP9; case V4L2_CID_MPEG_VIDEO_HEVC_TIER: return TIER; + case V4L2_CID_MPEG_VIDEO_HEADER_MODE: + return HEADER_MODE; + case V4L2_CID_MPEG_VIDEO_PREPEND_SPSPPS_TO_IDR: + return PREPEND_SPSPPS_TO_IDR; + case V4L2_CID_MPEG_VIDEO_BITRATE: + return BITRATE; + case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK: + return BITRATE_PEAK; + case V4L2_CID_MPEG_VIDEO_BITRATE_MODE: + return BITRATE_MODE; + case V4L2_CID_MPEG_VIDEO_FRAME_SKIP_MODE: + return FRAME_SKIP_MODE; + case V4L2_CID_MPEG_VIDEO_FRAME_RC_ENABLE: + return FRAME_RC_ENABLE; + case V4L2_CID_MPEG_VIDEO_GOP_SIZE: + return GOP_SIZE; + case V4L2_CID_MPEG_VIDEO_H264_ENTROPY_MODE: + return ENTROPY_MODE; + case V4L2_CID_MPEG_VIDEO_H264_MIN_QP: + return MIN_FRAME_QP_H264; + case V4L2_CID_MPEG_VIDEO_HEVC_MIN_QP: + return MIN_FRAME_QP_HEVC; + case V4L2_CID_MPEG_VIDEO_H264_MAX_QP: + return MAX_FRAME_QP_H264; + case V4L2_CID_MPEG_VIDEO_HEVC_MAX_QP: + return MAX_FRAME_QP_HEVC; + case V4L2_CID_MPEG_VIDEO_H264_I_FRAME_MIN_QP: + return I_FRAME_MIN_QP_H264; + case V4L2_CID_MPEG_VIDEO_HEVC_I_FRAME_MIN_QP: + return I_FRAME_MIN_QP_HEVC; + case V4L2_CID_MPEG_VIDEO_H264_P_FRAME_MIN_QP: + return P_FRAME_MIN_QP_H264; + case V4L2_CID_MPEG_VIDEO_HEVC_P_FRAME_MIN_QP: + return P_FRAME_MIN_QP_HEVC; + case V4L2_CID_MPEG_VIDEO_H264_B_FRAME_MIN_QP: + return B_FRAME_MIN_QP_H264; + case V4L2_CID_MPEG_VIDEO_HEVC_B_FRAME_MIN_QP: + return B_FRAME_MIN_QP_HEVC; + case V4L2_CID_MPEG_VIDEO_H264_I_FRAME_MAX_QP: + return I_FRAME_MAX_QP_H264; + case V4L2_CID_MPEG_VIDEO_HEVC_I_FRAME_MAX_QP: + return I_FRAME_MAX_QP_HEVC; + case V4L2_CID_MPEG_VIDEO_H264_P_FRAME_MAX_QP: + return P_FRAME_MAX_QP_H264; + case V4L2_CID_MPEG_VIDEO_HEVC_P_FRAME_MAX_QP: + return P_FRAME_MAX_QP_HEVC; + case V4L2_CID_MPEG_VIDEO_H264_B_FRAME_MAX_QP: + return B_FRAME_MAX_QP_H264; + case V4L2_CID_MPEG_VIDEO_HEVC_B_FRAME_MAX_QP: + return B_FRAME_MAX_QP_HEVC; + case V4L2_CID_MPEG_VIDEO_H264_I_FRAME_QP: + return I_FRAME_QP_H264; + case V4L2_CID_MPEG_VIDEO_HEVC_I_FRAME_QP: + return I_FRAME_QP_HEVC; + case V4L2_CID_MPEG_VIDEO_H264_P_FRAME_QP: + return P_FRAME_QP_H264; + case V4L2_CID_MPEG_VIDEO_HEVC_P_FRAME_QP: + return P_FRAME_QP_HEVC; + case V4L2_CID_MPEG_VIDEO_H264_B_FRAME_QP: + return B_FRAME_QP_H264; + case V4L2_CID_MPEG_VIDEO_HEVC_B_FRAME_QP: + return B_FRAME_QP_HEVC; default: return INST_FW_CAP_MAX; } @@ -56,12 +123,74 @@ static u32 iris_get_v4l2_id(enum platform_inst_fw_cap_type cap_id) return V4L2_CID_MPEG_VIDEO_VP9_LEVEL; case TIER: return V4L2_CID_MPEG_VIDEO_HEVC_TIER; + case HEADER_MODE: + return V4L2_CID_MPEG_VIDEO_HEADER_MODE; + case PREPEND_SPSPPS_TO_IDR: + return V4L2_CID_MPEG_VIDEO_PREPEND_SPSPPS_TO_IDR; + case BITRATE: + return V4L2_CID_MPEG_VIDEO_BITRATE; + case BITRATE_PEAK: + return V4L2_CID_MPEG_VIDEO_BITRATE_PEAK; + case BITRATE_MODE: + return V4L2_CID_MPEG_VIDEO_BITRATE_MODE; + case FRAME_SKIP_MODE: + return V4L2_CID_MPEG_VIDEO_FRAME_SKIP_MODE; + case FRAME_RC_ENABLE: + return V4L2_CID_MPEG_VIDEO_FRAME_RC_ENABLE; + case GOP_SIZE: + return V4L2_CID_MPEG_VIDEO_GOP_SIZE; + case ENTROPY_MODE: + return V4L2_CID_MPEG_VIDEO_H264_ENTROPY_MODE; + case MIN_FRAME_QP_H264: + return V4L2_CID_MPEG_VIDEO_H264_MIN_QP; + case MIN_FRAME_QP_HEVC: + return V4L2_CID_MPEG_VIDEO_HEVC_MIN_QP; + case MAX_FRAME_QP_H264: + return V4L2_CID_MPEG_VIDEO_H264_MAX_QP; + case MAX_FRAME_QP_HEVC: + return V4L2_CID_MPEG_VIDEO_HEVC_MAX_QP; + case I_FRAME_MIN_QP_H264: + return V4L2_CID_MPEG_VIDEO_H264_I_FRAME_MIN_QP; + case I_FRAME_MIN_QP_HEVC: + return V4L2_CID_MPEG_VIDEO_HEVC_I_FRAME_MIN_QP; + case P_FRAME_MIN_QP_H264: + return V4L2_CID_MPEG_VIDEO_H264_P_FRAME_MIN_QP; + case P_FRAME_MIN_QP_HEVC: + return V4L2_CID_MPEG_VIDEO_HEVC_P_FRAME_MIN_QP; + case B_FRAME_MIN_QP_H264: + return V4L2_CID_MPEG_VIDEO_H264_B_FRAME_MIN_QP; + case B_FRAME_MIN_QP_HEVC: + return V4L2_CID_MPEG_VIDEO_HEVC_B_FRAME_MIN_QP; + case I_FRAME_MAX_QP_H264: + return V4L2_CID_MPEG_VIDEO_H264_I_FRAME_MAX_QP; + case I_FRAME_MAX_QP_HEVC: + return V4L2_CID_MPEG_VIDEO_HEVC_I_FRAME_MAX_QP; + case P_FRAME_MAX_QP_H264: + return V4L2_CID_MPEG_VIDEO_H264_P_FRAME_MAX_QP; + case P_FRAME_MAX_QP_HEVC: + return V4L2_CID_MPEG_VIDEO_HEVC_P_FRAME_MAX_QP; + case B_FRAME_MAX_QP_H264: + return V4L2_CID_MPEG_VIDEO_H264_B_FRAME_MAX_QP; + case B_FRAME_MAX_QP_HEVC: + return V4L2_CID_MPEG_VIDEO_HEVC_B_FRAME_MAX_QP; + case I_FRAME_QP_H264: + return V4L2_CID_MPEG_VIDEO_H264_I_FRAME_QP; + case I_FRAME_QP_HEVC: + return V4L2_CID_MPEG_VIDEO_HEVC_I_FRAME_QP; + case P_FRAME_QP_H264: + return V4L2_CID_MPEG_VIDEO_H264_P_FRAME_QP; + case P_FRAME_QP_HEVC: + return V4L2_CID_MPEG_VIDEO_HEVC_P_FRAME_QP; + case B_FRAME_QP_H264: + return V4L2_CID_MPEG_VIDEO_H264_B_FRAME_QP; + case B_FRAME_QP_HEVC: + return V4L2_CID_MPEG_VIDEO_HEVC_B_FRAME_QP; default: return 0; } } -static int iris_vdec_op_s_ctrl(struct v4l2_ctrl *ctrl) +static int iris_op_s_ctrl(struct v4l2_ctrl *ctrl) { struct iris_inst *inst = container_of(ctrl->handler, struct iris_inst, ctrl_handler); enum platform_inst_fw_cap_type cap_id; @@ -82,11 +211,16 @@ static int iris_vdec_op_s_ctrl(struct v4l2_ctrl *ctrl) inst->fw_caps[cap_id].value = ctrl->val; + if (vb2_is_streaming(q)) { + if (cap[cap_id].set) + cap[cap_id].set(inst, cap_id); + } + return 0; } static const struct v4l2_ctrl_ops iris_ctrl_ops = { - .s_ctrl = iris_vdec_op_s_ctrl, + .s_ctrl = iris_op_s_ctrl, }; int iris_ctrls_init(struct iris_inst *inst) @@ -101,7 +235,10 @@ int iris_ctrls_init(struct iris_inst *inst) num_ctrls++; } - /* Adding 1 to num_ctrls to include V4L2_CID_MIN_BUFFERS_FOR_CAPTURE */ + /* Adding 1 to num_ctrls to include + * V4L2_CID_MIN_BUFFERS_FOR_CAPTURE for decoder and + * V4L2_CID_MIN_BUFFERS_FOR_OUTPUT for encoder + */ ret = v4l2_ctrl_handler_init(&inst->ctrl_handler, num_ctrls + 1); if (ret) @@ -143,8 +280,13 @@ int iris_ctrls_init(struct iris_inst *inst) ctrl_idx++; } - v4l2_ctrl_new_std(&inst->ctrl_handler, NULL, - V4L2_CID_MIN_BUFFERS_FOR_CAPTURE, 1, 32, 1, 4); + if (inst->domain == DECODER) { + v4l2_ctrl_new_std(&inst->ctrl_handler, NULL, + V4L2_CID_MIN_BUFFERS_FOR_CAPTURE, 1, 32, 1, 4); + } else { + v4l2_ctrl_new_std(&inst->ctrl_handler, NULL, + V4L2_CID_MIN_BUFFERS_FOR_OUTPUT, 1, 32, 1, 4); + } ret = inst->ctrl_handler.error; if (ret) @@ -162,32 +304,57 @@ void iris_session_init_caps(struct iris_core *core) struct platform_inst_fw_cap *caps; u32 i, num_cap, cap_id; - caps = core->iris_platform_data->inst_fw_caps; - num_cap = core->iris_platform_data->inst_fw_caps_size; + caps = core->iris_platform_data->inst_fw_caps_dec; + num_cap = core->iris_platform_data->inst_fw_caps_dec_size; + + for (i = 0; i < num_cap; i++) { + cap_id = caps[i].cap_id; + if (!iris_valid_cap_id(cap_id)) + continue; + + core->inst_fw_caps_dec[cap_id].cap_id = caps[i].cap_id; + core->inst_fw_caps_dec[cap_id].min = caps[i].min; + core->inst_fw_caps_dec[cap_id].max = caps[i].max; + core->inst_fw_caps_dec[cap_id].step_or_mask = caps[i].step_or_mask; + core->inst_fw_caps_dec[cap_id].value = caps[i].value; + core->inst_fw_caps_dec[cap_id].flags = caps[i].flags; + core->inst_fw_caps_dec[cap_id].hfi_id = caps[i].hfi_id; + core->inst_fw_caps_dec[cap_id].set = caps[i].set; + } + + caps = core->iris_platform_data->inst_fw_caps_enc; + num_cap = core->iris_platform_data->inst_fw_caps_enc_size; for (i = 0; i < num_cap; i++) { cap_id = caps[i].cap_id; if (!iris_valid_cap_id(cap_id)) continue; - core->inst_fw_caps[cap_id].cap_id = caps[i].cap_id; - core->inst_fw_caps[cap_id].min = caps[i].min; - core->inst_fw_caps[cap_id].max = caps[i].max; - core->inst_fw_caps[cap_id].step_or_mask = caps[i].step_or_mask; - core->inst_fw_caps[cap_id].value = caps[i].value; - core->inst_fw_caps[cap_id].flags = caps[i].flags; - core->inst_fw_caps[cap_id].hfi_id = caps[i].hfi_id; - core->inst_fw_caps[cap_id].set = caps[i].set; + core->inst_fw_caps_enc[cap_id].cap_id = caps[i].cap_id; + core->inst_fw_caps_enc[cap_id].min = caps[i].min; + core->inst_fw_caps_enc[cap_id].max = caps[i].max; + core->inst_fw_caps_enc[cap_id].step_or_mask = caps[i].step_or_mask; + core->inst_fw_caps_enc[cap_id].value = caps[i].value; + core->inst_fw_caps_enc[cap_id].flags = caps[i].flags; + core->inst_fw_caps_enc[cap_id].hfi_id = caps[i].hfi_id; + core->inst_fw_caps_enc[cap_id].set = caps[i].set; } } static u32 iris_get_port_info(struct iris_inst *inst, enum platform_inst_fw_cap_type cap_id) { - if (inst->fw_caps[cap_id].flags & CAP_FLAG_INPUT_PORT) - return HFI_PORT_BITSTREAM; - else if (inst->fw_caps[cap_id].flags & CAP_FLAG_OUTPUT_PORT) - return HFI_PORT_RAW; + if (inst->domain == DECODER) { + if (inst->fw_caps[cap_id].flags & CAP_FLAG_INPUT_PORT) + return HFI_PORT_BITSTREAM; + else if (inst->fw_caps[cap_id].flags & CAP_FLAG_OUTPUT_PORT) + return HFI_PORT_RAW; + } else { + if (inst->fw_caps[cap_id].flags & CAP_FLAG_INPUT_PORT) + return HFI_PORT_RAW; + else if (inst->fw_caps[cap_id].flags & CAP_FLAG_OUTPUT_PORT) + return HFI_PORT_BITSTREAM; + } return HFI_PORT_NONE; } @@ -227,8 +394,10 @@ int iris_set_stage(struct iris_inst *inst, enum platform_inst_fw_cap_type cap_id u32 width = inp_f->fmt.pix_mp.width; u32 work_mode = STAGE_2; - if (iris_res_is_less_than(width, height, 1280, 720)) - work_mode = STAGE_1; + if (inst->domain == DECODER) { + if (iris_res_is_less_than(width, height, 1280, 720)) + work_mode = STAGE_1; + } return hfi_ops->session_set_property(inst, hfi_id, HFI_HOST_FLAGS_NONE, @@ -250,6 +419,470 @@ int iris_set_pipe(struct iris_inst *inst, enum platform_inst_fw_cap_type cap_id) &work_route, sizeof(u32)); } +int iris_set_profile(struct iris_inst *inst, enum platform_inst_fw_cap_type cap_id) +{ + const struct iris_hfi_command_ops *hfi_ops = inst->core->hfi_ops; + u32 hfi_id, hfi_value; + + if (inst->codec == V4L2_PIX_FMT_H264) { + hfi_id = inst->fw_caps[PROFILE_H264].hfi_id; + hfi_value = inst->fw_caps[PROFILE_H264].value; + } else { + hfi_id = inst->fw_caps[PROFILE_HEVC].hfi_id; + hfi_value = inst->fw_caps[PROFILE_HEVC].value; + } + + return hfi_ops->session_set_property(inst, hfi_id, + HFI_HOST_FLAGS_NONE, + iris_get_port_info(inst, cap_id), + HFI_PAYLOAD_U32_ENUM, + &hfi_value, sizeof(u32)); +} + +int iris_set_level(struct iris_inst *inst, enum platform_inst_fw_cap_type cap_id) +{ + const struct iris_hfi_command_ops *hfi_ops = inst->core->hfi_ops; + u32 hfi_id, hfi_value; + + if (inst->codec == V4L2_PIX_FMT_H264) { + hfi_id = inst->fw_caps[LEVEL_H264].hfi_id; + hfi_value = inst->fw_caps[LEVEL_H264].value; + } else { + hfi_id = inst->fw_caps[LEVEL_HEVC].hfi_id; + hfi_value = inst->fw_caps[LEVEL_HEVC].value; + } + + return hfi_ops->session_set_property(inst, hfi_id, + HFI_HOST_FLAGS_NONE, + iris_get_port_info(inst, cap_id), + HFI_PAYLOAD_U32_ENUM, + &hfi_value, sizeof(u32)); +} + +int iris_set_profile_level_gen1(struct iris_inst *inst, enum platform_inst_fw_cap_type cap_id) +{ + const struct iris_hfi_command_ops *hfi_ops = inst->core->hfi_ops; + u32 hfi_id = inst->fw_caps[cap_id].hfi_id; + struct hfi_profile_level pl; + + if (inst->codec == V4L2_PIX_FMT_H264) { + pl.profile = inst->fw_caps[PROFILE_H264].value; + pl.level = inst->fw_caps[LEVEL_H264].value; + } else { + pl.profile = inst->fw_caps[PROFILE_HEVC].value; + pl.level = inst->fw_caps[LEVEL_HEVC].value; + } + + return hfi_ops->session_set_property(inst, hfi_id, + HFI_HOST_FLAGS_NONE, + iris_get_port_info(inst, cap_id), + HFI_PAYLOAD_U32_ENUM, + &pl, sizeof(u32)); +} + +int iris_set_header_mode_gen1(struct iris_inst *inst, enum platform_inst_fw_cap_type cap_id) +{ + const struct iris_hfi_command_ops *hfi_ops = inst->core->hfi_ops; + u32 header_mode = inst->fw_caps[cap_id].value; + u32 hfi_id = inst->fw_caps[cap_id].hfi_id; + u32 hfi_val; + + if (header_mode == V4L2_MPEG_VIDEO_HEADER_MODE_SEPARATE) + hfi_val = 0; + else + hfi_val = 1; + + return hfi_ops->session_set_property(inst, hfi_id, + HFI_HOST_FLAGS_NONE, + iris_get_port_info(inst, cap_id), + HFI_PAYLOAD_U32, + &hfi_val, sizeof(u32)); +} + +int iris_set_header_mode_gen2(struct iris_inst *inst, enum platform_inst_fw_cap_type cap_id) +{ + const struct iris_hfi_command_ops *hfi_ops = inst->core->hfi_ops; + u32 prepend_sps_pps = inst->fw_caps[PREPEND_SPSPPS_TO_IDR].value; + u32 header_mode = inst->fw_caps[cap_id].value; + u32 hfi_id = inst->fw_caps[cap_id].hfi_id; + u32 hfi_val; + + if (prepend_sps_pps) + hfi_val = HFI_SEQ_HEADER_PREFIX_WITH_SYNC_FRAME; + else if (header_mode == V4L2_MPEG_VIDEO_HEADER_MODE_JOINED_WITH_1ST_FRAME) + hfi_val = HFI_SEQ_HEADER_JOINED_WITH_1ST_FRAME; + else + hfi_val = HFI_SEQ_HEADER_SEPERATE_FRAME; + + return hfi_ops->session_set_property(inst, hfi_id, + HFI_HOST_FLAGS_NONE, + iris_get_port_info(inst, cap_id), + HFI_PAYLOAD_U32_ENUM, + &hfi_val, sizeof(u32)); +} + +int iris_set_bitrate(struct iris_inst *inst, enum platform_inst_fw_cap_type cap_id) +{ + const struct iris_hfi_command_ops *hfi_ops = inst->core->hfi_ops; + u32 entropy_mode = inst->fw_caps[ENTROPY_MODE].value; + u32 bitrate = inst->fw_caps[cap_id].value; + u32 hfi_id = inst->fw_caps[cap_id].hfi_id; + u32 max_bitrate; + + if (inst->codec == V4L2_PIX_FMT_HEVC) + max_bitrate = CABAC_MAX_BITRATE; + + if (entropy_mode == V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CABAC) + max_bitrate = CABAC_MAX_BITRATE; + else + max_bitrate = CAVLC_MAX_BITRATE; + + bitrate = min(bitrate, max_bitrate); + + return hfi_ops->session_set_property(inst, hfi_id, + HFI_HOST_FLAGS_NONE, + iris_get_port_info(inst, cap_id), + HFI_PAYLOAD_U32, + &bitrate, sizeof(u32)); +} + +int iris_set_peak_bitrate(struct iris_inst *inst, enum platform_inst_fw_cap_type cap_id) +{ + const struct iris_hfi_command_ops *hfi_ops = inst->core->hfi_ops; + u32 rc_mode = inst->fw_caps[BITRATE_MODE].value; + u32 peak_bitrate = inst->fw_caps[cap_id].value; + u32 bitrate = inst->fw_caps[BITRATE].value; + u32 hfi_id = inst->fw_caps[cap_id].hfi_id; + + if (rc_mode != V4L2_MPEG_VIDEO_BITRATE_MODE_CBR) + return 0; + + if (inst->fw_caps[cap_id].flags & CAP_FLAG_CLIENT_SET) { + if (peak_bitrate < bitrate) + peak_bitrate = bitrate; + } else { + peak_bitrate = bitrate; + } + + inst->fw_caps[cap_id].value = peak_bitrate; + + return hfi_ops->session_set_property(inst, hfi_id, + HFI_HOST_FLAGS_NONE, + iris_get_port_info(inst, cap_id), + HFI_PAYLOAD_U32, + &peak_bitrate, sizeof(u32)); +} + +int iris_set_bitrate_mode_gen1(struct iris_inst *inst, enum platform_inst_fw_cap_type cap_id) +{ + const struct iris_hfi_command_ops *hfi_ops = inst->core->hfi_ops; + u32 bitrate_mode = inst->fw_caps[BITRATE_MODE].value; + u32 frame_rc = inst->fw_caps[FRAME_RC_ENABLE].value; + u32 frame_skip = inst->fw_caps[FRAME_SKIP_MODE].value; + u32 hfi_id = inst->fw_caps[cap_id].hfi_id; + u32 rc_mode = 0; + + if (!frame_rc) + rc_mode = HFI_RATE_CONTROL_OFF; + else if (bitrate_mode == V4L2_MPEG_VIDEO_BITRATE_MODE_VBR) + rc_mode = frame_skip ? HFI_RATE_CONTROL_VBR_VFR : HFI_RATE_CONTROL_VBR_CFR; + else if (bitrate_mode == V4L2_MPEG_VIDEO_BITRATE_MODE_CBR) + rc_mode = frame_skip ? HFI_RATE_CONTROL_CBR_VFR : HFI_RATE_CONTROL_CBR_CFR; + else if (bitrate_mode == V4L2_MPEG_VIDEO_BITRATE_MODE_CQ) + rc_mode = HFI_RATE_CONTROL_CQ; + + inst->hfi_rc_type = rc_mode; + + return hfi_ops->session_set_property(inst, hfi_id, + HFI_HOST_FLAGS_NONE, + iris_get_port_info(inst, cap_id), + HFI_PAYLOAD_U32_ENUM, + &rc_mode, sizeof(u32)); +} + +int iris_set_bitrate_mode_gen2(struct iris_inst *inst, enum platform_inst_fw_cap_type cap_id) +{ + const struct iris_hfi_command_ops *hfi_ops = inst->core->hfi_ops; + u32 bitrate_mode = inst->fw_caps[BITRATE_MODE].value; + u32 frame_rc = inst->fw_caps[FRAME_RC_ENABLE].value; + u32 frame_skip = inst->fw_caps[FRAME_SKIP_MODE].value; + u32 hfi_id = inst->fw_caps[cap_id].hfi_id; + u32 rc_mode = 0; + + if (!frame_rc) + rc_mode = HFI_RC_OFF; + else if (bitrate_mode == V4L2_MPEG_VIDEO_BITRATE_MODE_VBR) + rc_mode = HFI_RC_VBR_CFR; + else if (bitrate_mode == V4L2_MPEG_VIDEO_BITRATE_MODE_CBR) + rc_mode = frame_skip ? HFI_RC_CBR_VFR : HFI_RC_CBR_CFR; + else if (bitrate_mode == V4L2_MPEG_VIDEO_BITRATE_MODE_CQ) + rc_mode = HFI_RC_CQ; + + inst->hfi_rc_type = rc_mode; + + return hfi_ops->session_set_property(inst, hfi_id, + HFI_HOST_FLAGS_NONE, + iris_get_port_info(inst, cap_id), + HFI_PAYLOAD_U32_ENUM, + &rc_mode, sizeof(u32)); +} + +int iris_set_entropy_mode_gen1(struct iris_inst *inst, enum platform_inst_fw_cap_type cap_id) +{ + const struct iris_hfi_command_ops *hfi_ops = inst->core->hfi_ops; + u32 entropy_mode = inst->fw_caps[cap_id].value; + u32 hfi_id = inst->fw_caps[cap_id].hfi_id; + u32 hfi_val; + + if (inst->codec != V4L2_PIX_FMT_H264) + return 0; + + hfi_val = (entropy_mode == V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CAVLC) ? + HFI_H264_ENTROPY_CAVLC : HFI_H264_ENTROPY_CABAC; + + return hfi_ops->session_set_property(inst, hfi_id, + HFI_HOST_FLAGS_NONE, + iris_get_port_info(inst, cap_id), + HFI_PAYLOAD_U32, + &hfi_val, sizeof(u32)); +} + +int iris_set_entropy_mode_gen2(struct iris_inst *inst, enum platform_inst_fw_cap_type cap_id) +{ + const struct iris_hfi_command_ops *hfi_ops = inst->core->hfi_ops; + u32 entropy_mode = inst->fw_caps[cap_id].value; + u32 hfi_id = inst->fw_caps[cap_id].hfi_id; + u32 profile; + + if (inst->codec != V4L2_PIX_FMT_H264) + return 0; + + profile = inst->fw_caps[PROFILE_H264].value; + + if (profile == V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE || + profile == V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_BASELINE) + entropy_mode = V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CAVLC; + + inst->fw_caps[cap_id].value = entropy_mode; + + return hfi_ops->session_set_property(inst, hfi_id, + HFI_HOST_FLAGS_NONE, + iris_get_port_info(inst, cap_id), + HFI_PAYLOAD_U32, + &entropy_mode, sizeof(u32)); +} + +int iris_set_min_qp(struct iris_inst *inst, enum platform_inst_fw_cap_type cap_id) +{ + const struct iris_hfi_command_ops *hfi_ops = inst->core->hfi_ops; + u32 i_qp_enable = 0, p_qp_enable = 0, b_qp_enable = 0; + u32 i_frame_qp = 0, p_frame_qp = 0, b_frame_qp = 0; + u32 min_qp_enable = 0, client_qp_enable = 0; + u32 hfi_id = inst->fw_caps[cap_id].hfi_id; + u32 hfi_val; + + if (inst->codec == V4L2_PIX_FMT_H264) { + if (inst->fw_caps[MIN_FRAME_QP_H264].flags & CAP_FLAG_CLIENT_SET) + min_qp_enable = 1; + if (min_qp_enable || + (inst->fw_caps[I_FRAME_MIN_QP_H264].flags & CAP_FLAG_CLIENT_SET)) + i_qp_enable = 1; + if (min_qp_enable || + (inst->fw_caps[P_FRAME_MIN_QP_H264].flags & CAP_FLAG_CLIENT_SET)) + p_qp_enable = 1; + if (min_qp_enable || + (inst->fw_caps[B_FRAME_MIN_QP_H264].flags & CAP_FLAG_CLIENT_SET)) + b_qp_enable = 1; + } else { + if (inst->fw_caps[MIN_FRAME_QP_HEVC].flags & CAP_FLAG_CLIENT_SET) + min_qp_enable = 1; + if (min_qp_enable || + (inst->fw_caps[I_FRAME_MIN_QP_HEVC].flags & CAP_FLAG_CLIENT_SET)) + i_qp_enable = 1; + if (min_qp_enable || + (inst->fw_caps[P_FRAME_MIN_QP_HEVC].flags & CAP_FLAG_CLIENT_SET)) + p_qp_enable = 1; + if (min_qp_enable || + (inst->fw_caps[B_FRAME_MIN_QP_HEVC].flags & CAP_FLAG_CLIENT_SET)) + b_qp_enable = 1; + } + + client_qp_enable = i_qp_enable | p_qp_enable << 1 | b_qp_enable << 2; + if (!client_qp_enable) + return 0; + + if (inst->codec == V4L2_PIX_FMT_H264) { + i_frame_qp = max(inst->fw_caps[I_FRAME_MIN_QP_H264].value, + inst->fw_caps[MIN_FRAME_QP_H264].value); + p_frame_qp = max(inst->fw_caps[P_FRAME_MIN_QP_H264].value, + inst->fw_caps[MIN_FRAME_QP_H264].value); + b_frame_qp = max(inst->fw_caps[B_FRAME_MIN_QP_H264].value, + inst->fw_caps[MIN_FRAME_QP_H264].value); + } else { + i_frame_qp = max(inst->fw_caps[I_FRAME_MIN_QP_HEVC].value, + inst->fw_caps[MIN_FRAME_QP_HEVC].value); + p_frame_qp = max(inst->fw_caps[P_FRAME_MIN_QP_HEVC].value, + inst->fw_caps[MIN_FRAME_QP_HEVC].value); + b_frame_qp = max(inst->fw_caps[B_FRAME_MIN_QP_HEVC].value, + inst->fw_caps[MIN_FRAME_QP_HEVC].value); + } + + hfi_val = i_frame_qp | p_frame_qp << 8 | b_frame_qp << 16 | client_qp_enable << 24; + + return hfi_ops->session_set_property(inst, hfi_id, + HFI_HOST_FLAGS_NONE, + iris_get_port_info(inst, cap_id), + HFI_PAYLOAD_32_PACKED, + &hfi_val, sizeof(u32)); +} + +int iris_set_max_qp(struct iris_inst *inst, enum platform_inst_fw_cap_type cap_id) +{ + const struct iris_hfi_command_ops *hfi_ops = inst->core->hfi_ops; + u32 i_qp_enable = 0, p_qp_enable = 0, b_qp_enable = 0; + u32 max_qp_enable = 0, client_qp_enable; + u32 i_frame_qp, p_frame_qp, b_frame_qp; + u32 hfi_id = inst->fw_caps[cap_id].hfi_id; + u32 hfi_val; + + if (inst->codec == V4L2_PIX_FMT_H264) { + if (inst->fw_caps[MAX_FRAME_QP_H264].flags & CAP_FLAG_CLIENT_SET) + max_qp_enable = 1; + if (max_qp_enable || + (inst->fw_caps[I_FRAME_MAX_QP_H264].flags & CAP_FLAG_CLIENT_SET)) + i_qp_enable = 1; + if (max_qp_enable || + (inst->fw_caps[P_FRAME_MAX_QP_H264].flags & CAP_FLAG_CLIENT_SET)) + p_qp_enable = 1; + if (max_qp_enable || + (inst->fw_caps[B_FRAME_MAX_QP_H264].flags & CAP_FLAG_CLIENT_SET)) + b_qp_enable = 1; + } else { + if (inst->fw_caps[MAX_FRAME_QP_HEVC].flags & CAP_FLAG_CLIENT_SET) + max_qp_enable = 1; + if (max_qp_enable || + (inst->fw_caps[I_FRAME_MAX_QP_HEVC].flags & CAP_FLAG_CLIENT_SET)) + i_qp_enable = 1; + if (max_qp_enable || + (inst->fw_caps[P_FRAME_MAX_QP_HEVC].flags & CAP_FLAG_CLIENT_SET)) + p_qp_enable = 1; + if (max_qp_enable || + (inst->fw_caps[B_FRAME_MAX_QP_HEVC].flags & CAP_FLAG_CLIENT_SET)) + b_qp_enable = 1; + } + + client_qp_enable = i_qp_enable | p_qp_enable << 1 | b_qp_enable << 2; + if (!client_qp_enable) + return 0; + + if (inst->codec == V4L2_PIX_FMT_H264) { + i_frame_qp = min(inst->fw_caps[I_FRAME_MAX_QP_H264].value, + inst->fw_caps[MAX_FRAME_QP_H264].value); + p_frame_qp = min(inst->fw_caps[P_FRAME_MAX_QP_H264].value, + inst->fw_caps[MAX_FRAME_QP_H264].value); + b_frame_qp = min(inst->fw_caps[B_FRAME_MAX_QP_H264].value, + inst->fw_caps[MAX_FRAME_QP_H264].value); + } else { + i_frame_qp = min(inst->fw_caps[I_FRAME_MAX_QP_HEVC].value, + inst->fw_caps[MAX_FRAME_QP_HEVC].value); + p_frame_qp = min(inst->fw_caps[P_FRAME_MAX_QP_HEVC].value, + inst->fw_caps[MAX_FRAME_QP_HEVC].value); + b_frame_qp = min(inst->fw_caps[B_FRAME_MAX_QP_HEVC].value, + inst->fw_caps[MAX_FRAME_QP_HEVC].value); + } + + hfi_val = i_frame_qp | p_frame_qp << 8 | b_frame_qp << 16 | + client_qp_enable << 24; + + return hfi_ops->session_set_property(inst, hfi_id, + HFI_HOST_FLAGS_NONE, + iris_get_port_info(inst, cap_id), + HFI_PAYLOAD_32_PACKED, + &hfi_val, sizeof(u32)); +} + +int iris_set_frame_qp(struct iris_inst *inst, enum platform_inst_fw_cap_type cap_id) +{ + const struct iris_hfi_command_ops *hfi_ops = inst->core->hfi_ops; + u32 i_qp_enable = 0, p_qp_enable = 0, b_qp_enable = 0, client_qp_enable; + u32 i_frame_qp, p_frame_qp, b_frame_qp; + u32 hfi_id = inst->fw_caps[cap_id].hfi_id; + struct vb2_queue *q; + u32 hfi_val; + + q = v4l2_m2m_get_dst_vq(inst->m2m_ctx); + if (vb2_is_streaming(q)) { + if (inst->hfi_rc_type != HFI_RC_OFF) + return 0; + } + + if (inst->hfi_rc_type == HFI_RC_OFF) { + i_qp_enable = 1; + p_qp_enable = 1; + b_qp_enable = 1; + } else { + if (inst->codec == V4L2_PIX_FMT_H264) { + if (inst->fw_caps[I_FRAME_QP_H264].flags & CAP_FLAG_CLIENT_SET) + i_qp_enable = 1; + if (inst->fw_caps[P_FRAME_QP_H264].flags & CAP_FLAG_CLIENT_SET) + p_qp_enable = 1; + if (inst->fw_caps[B_FRAME_QP_H264].flags & CAP_FLAG_CLIENT_SET) + b_qp_enable = 1; + } else { + if (inst->fw_caps[I_FRAME_QP_HEVC].flags & CAP_FLAG_CLIENT_SET) + i_qp_enable = 1; + if (inst->fw_caps[P_FRAME_QP_HEVC].flags & CAP_FLAG_CLIENT_SET) + p_qp_enable = 1; + if (inst->fw_caps[B_FRAME_QP_HEVC].flags & CAP_FLAG_CLIENT_SET) + b_qp_enable = 1; + } + } + + client_qp_enable = i_qp_enable | p_qp_enable << 1 | b_qp_enable << 2; + if (!client_qp_enable) + return 0; + + if (inst->codec == V4L2_PIX_FMT_H264) { + i_frame_qp = inst->fw_caps[I_FRAME_QP_H264].value; + p_frame_qp = inst->fw_caps[P_FRAME_QP_H264].value; + b_frame_qp = inst->fw_caps[B_FRAME_QP_H264].value; + } else { + i_frame_qp = inst->fw_caps[I_FRAME_QP_HEVC].value; + p_frame_qp = inst->fw_caps[P_FRAME_QP_HEVC].value; + b_frame_qp = inst->fw_caps[B_FRAME_QP_HEVC].value; + } + + hfi_val = i_frame_qp | p_frame_qp << 8 | b_frame_qp << 16 | + client_qp_enable << 24; + + return hfi_ops->session_set_property(inst, hfi_id, + HFI_HOST_FLAGS_NONE, + iris_get_port_info(inst, cap_id), + HFI_PAYLOAD_32_PACKED, + &hfi_val, sizeof(u32)); +} + +int iris_set_qp_range(struct iris_inst *inst, enum platform_inst_fw_cap_type cap_id) +{ + const struct iris_hfi_command_ops *hfi_ops = inst->core->hfi_ops; + struct hfi_quantization_range_v2 range; + u32 hfi_id = inst->fw_caps[cap_id].hfi_id; + + if (inst->codec == V4L2_PIX_FMT_HEVC) { + range.min_qp.qp_packed = inst->fw_caps[MIN_FRAME_QP_HEVC].value; + range.max_qp.qp_packed = inst->fw_caps[MAX_FRAME_QP_HEVC].value; + } else { + range.min_qp.qp_packed = inst->fw_caps[MIN_FRAME_QP_H264].value; + range.max_qp.qp_packed = inst->fw_caps[MAX_FRAME_QP_H264].value; + } + + return hfi_ops->session_set_property(inst, hfi_id, + HFI_HOST_FLAGS_NONE, + iris_get_port_info(inst, cap_id), + HFI_PAYLOAD_32_PACKED, + &range, sizeof(range)); +} + int iris_set_properties(struct iris_inst *inst, u32 plane) { const struct iris_hfi_command_ops *hfi_ops = inst->core->hfi_ops; diff --git a/drivers/media/platform/qcom/iris/iris_ctrls.h b/drivers/media/platform/qcom/iris/iris_ctrls.h index 9b5741868933..30af333cc494 100644 --- a/drivers/media/platform/qcom/iris/iris_ctrls.h +++ b/drivers/media/platform/qcom/iris/iris_ctrls.h @@ -17,6 +17,21 @@ int iris_set_u32_enum(struct iris_inst *inst, enum platform_inst_fw_cap_type cap int iris_set_stage(struct iris_inst *inst, enum platform_inst_fw_cap_type cap_id); int iris_set_pipe(struct iris_inst *inst, enum platform_inst_fw_cap_type cap_id); int iris_set_u32(struct iris_inst *inst, enum platform_inst_fw_cap_type cap_id); +int iris_set_profile(struct iris_inst *inst, enum platform_inst_fw_cap_type cap_id); +int iris_set_level(struct iris_inst *inst, enum platform_inst_fw_cap_type cap_id); +int iris_set_profile_level_gen1(struct iris_inst *inst, enum platform_inst_fw_cap_type cap_id); +int iris_set_header_mode_gen1(struct iris_inst *inst, enum platform_inst_fw_cap_type cap_id); +int iris_set_header_mode_gen2(struct iris_inst *inst, enum platform_inst_fw_cap_type cap_id); +int iris_set_bitrate(struct iris_inst *inst, enum platform_inst_fw_cap_type cap_id); +int iris_set_peak_bitrate(struct iris_inst *inst, enum platform_inst_fw_cap_type cap_id); +int iris_set_bitrate_mode_gen1(struct iris_inst *inst, enum platform_inst_fw_cap_type cap_id); +int iris_set_bitrate_mode_gen2(struct iris_inst *inst, enum platform_inst_fw_cap_type cap_id); +int iris_set_entropy_mode_gen1(struct iris_inst *inst, enum platform_inst_fw_cap_type cap_id); +int iris_set_entropy_mode_gen2(struct iris_inst *inst, enum platform_inst_fw_cap_type cap_id); +int iris_set_min_qp(struct iris_inst *inst, enum platform_inst_fw_cap_type cap_id); +int iris_set_max_qp(struct iris_inst *inst, enum platform_inst_fw_cap_type cap_id); +int iris_set_frame_qp(struct iris_inst *inst, enum platform_inst_fw_cap_type cap_id); +int iris_set_qp_range(struct iris_inst *inst, enum platform_inst_fw_cap_type cap_id); int iris_set_properties(struct iris_inst *inst, u32 plane); #endif diff --git a/drivers/media/platform/qcom/iris/iris_firmware.c b/drivers/media/platform/qcom/iris/iris_firmware.c index f1b5cd56db32..9ab499fad946 100644 --- a/drivers/media/platform/qcom/iris/iris_firmware.c +++ b/drivers/media/platform/qcom/iris/iris_firmware.c @@ -60,16 +60,7 @@ static int iris_load_fw_to_memory(struct iris_core *core, const char *fw_name) ret = qcom_mdt_load(dev, firmware, fw_name, pas_id, mem_virt, mem_phys, res_size, NULL); - if (ret) - goto err_mem_unmap; - - ret = qcom_scm_pas_auth_and_reset(pas_id); - if (ret) - goto err_mem_unmap; - - return ret; -err_mem_unmap: memunmap(mem_virt); err_release_fw: release_firmware(firmware); @@ -94,6 +85,12 @@ int iris_fw_load(struct iris_core *core) return -ENOMEM; } + ret = qcom_scm_pas_auth_and_reset(core->iris_platform_data->pas_id); + if (ret) { + dev_err(core->dev, "auth and reset failed: %d\n", ret); + return ret; + } + ret = qcom_scm_mem_protect_video_var(cp_config->cp_start, cp_config->cp_size, cp_config->cp_nonpixel_start, diff --git a/drivers/media/platform/qcom/iris/iris_hfi_common.h b/drivers/media/platform/qcom/iris/iris_hfi_common.h index 9e6aadb83783..b51471fb32c7 100644 --- a/drivers/media/platform/qcom/iris/iris_hfi_common.h +++ b/drivers/media/platform/qcom/iris/iris_hfi_common.h @@ -102,7 +102,7 @@ enum hfi_matrix_coefficients { struct iris_hfi_prop_type_handle { u32 type; - int (*handle)(struct iris_inst *inst); + int (*handle)(struct iris_inst *inst, u32 plane); }; struct iris_hfi_command_ops { diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c b/drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c index 5fc30d54af4d..e1788c266bb1 100644 --- a/drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c +++ b/drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c @@ -21,6 +21,10 @@ static u32 iris_hfi_gen1_buf_type_from_driver(enum iris_buffer_type buffer_type) return HFI_BUFFER_INTERNAL_SCRATCH; case BUF_SCRATCH_1: return HFI_BUFFER_INTERNAL_SCRATCH_1; + case BUF_SCRATCH_2: + return HFI_BUFFER_INTERNAL_SCRATCH_2; + case BUF_ARP: + return HFI_BUFFER_INTERNAL_PERSIST; default: return -EINVAL; } @@ -109,7 +113,12 @@ static int iris_hfi_gen1_session_open(struct iris_inst *inst) packet.shdr.hdr.size = sizeof(struct hfi_session_open_pkt); packet.shdr.hdr.pkt_type = HFI_CMD_SYS_SESSION_INIT; packet.shdr.session_id = inst->session_id; - packet.session_domain = HFI_SESSION_TYPE_DEC; + + if (inst->domain == DECODER) + packet.session_domain = HFI_SESSION_TYPE_DEC; + else + packet.session_domain = HFI_SESSION_TYPE_ENC; + packet.session_codec = codec; reinit_completion(&inst->completion); @@ -184,47 +193,70 @@ static int iris_hfi_gen1_session_stop(struct iris_inst *inst, u32 plane) u32 flush_type = 0; int ret = 0; - if ((V4L2_TYPE_IS_OUTPUT(plane) && - inst->state == IRIS_INST_INPUT_STREAMING) || - (V4L2_TYPE_IS_CAPTURE(plane) && - inst->state == IRIS_INST_OUTPUT_STREAMING) || - inst->state == IRIS_INST_ERROR) { - reinit_completion(&inst->completion); - iris_hfi_gen1_packet_session_cmd(inst, &pkt, HFI_CMD_SESSION_STOP); - ret = iris_hfi_queue_cmd_write(core, &pkt, pkt.shdr.hdr.size); - if (!ret) - ret = iris_wait_for_session_response(inst, false); - - reinit_completion(&inst->completion); - iris_hfi_gen1_packet_session_cmd(inst, &pkt, HFI_CMD_SESSION_RELEASE_RESOURCES); - ret = iris_hfi_queue_cmd_write(core, &pkt, pkt.shdr.hdr.size); - if (!ret) - ret = iris_wait_for_session_response(inst, false); - - iris_inst_change_sub_state(inst, IRIS_INST_SUB_LOAD_RESOURCES, 0); + if (inst->domain == DECODER) { + if (inst->state == IRIS_INST_STREAMING) { + if (V4L2_TYPE_IS_OUTPUT(plane)) + flush_type = HFI_FLUSH_ALL; + else if (V4L2_TYPE_IS_CAPTURE(plane)) + flush_type = HFI_FLUSH_OUTPUT; + + reinit_completion(&inst->flush_completion); + + flush_pkt.shdr.hdr.size = sizeof(struct hfi_session_flush_pkt); + flush_pkt.shdr.hdr.pkt_type = HFI_CMD_SESSION_FLUSH; + flush_pkt.shdr.session_id = inst->session_id; + flush_pkt.flush_type = flush_type; + + ret = iris_hfi_queue_cmd_write(core, &flush_pkt, flush_pkt.shdr.hdr.size); + if (!ret) { + inst->flush_responses_pending++; + ret = iris_wait_for_session_response(inst, true); + } + } else if (inst->sub_state & IRIS_INST_SUB_LOAD_RESOURCES) { + reinit_completion(&inst->completion); + iris_hfi_gen1_packet_session_cmd(inst, &pkt, HFI_CMD_SESSION_STOP); + ret = iris_hfi_queue_cmd_write(core, &pkt, pkt.shdr.hdr.size); + if (!ret) + ret = iris_wait_for_session_response(inst, false); + + reinit_completion(&inst->completion); + iris_hfi_gen1_packet_session_cmd(inst, &pkt, + HFI_CMD_SESSION_RELEASE_RESOURCES); + ret = iris_hfi_queue_cmd_write(core, &pkt, pkt.shdr.hdr.size); + if (!ret) + ret = iris_wait_for_session_response(inst, false); + + iris_inst_change_sub_state(inst, IRIS_INST_SUB_LOAD_RESOURCES, 0); + + iris_helper_buffers_done(inst, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, + VB2_BUF_STATE_ERROR); + iris_helper_buffers_done(inst, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE, + VB2_BUF_STATE_ERROR); + } + } else { + if (inst->state == IRIS_INST_STREAMING || + inst->state == IRIS_INST_INPUT_STREAMING || + inst->state == IRIS_INST_ERROR) { + reinit_completion(&inst->completion); + iris_hfi_gen1_packet_session_cmd(inst, &pkt, HFI_CMD_SESSION_STOP); + ret = iris_hfi_queue_cmd_write(core, &pkt, pkt.shdr.hdr.size); + if (!ret) + ret = iris_wait_for_session_response(inst, false); + + reinit_completion(&inst->completion); + iris_hfi_gen1_packet_session_cmd(inst, &pkt, + HFI_CMD_SESSION_RELEASE_RESOURCES); + ret = iris_hfi_queue_cmd_write(core, &pkt, pkt.shdr.hdr.size); + if (!ret) + ret = iris_wait_for_session_response(inst, false); + + iris_inst_change_sub_state(inst, IRIS_INST_SUB_LOAD_RESOURCES, 0); + } iris_helper_buffers_done(inst, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, VB2_BUF_STATE_ERROR); iris_helper_buffers_done(inst, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE, VB2_BUF_STATE_ERROR); - } else if (inst->state == IRIS_INST_STREAMING) { - if (V4L2_TYPE_IS_OUTPUT(plane)) - flush_type = HFI_FLUSH_ALL; - else if (V4L2_TYPE_IS_CAPTURE(plane)) - flush_type = HFI_FLUSH_OUTPUT; - - reinit_completion(&inst->flush_completion); - - flush_pkt.shdr.hdr.size = sizeof(struct hfi_session_flush_pkt); - flush_pkt.shdr.hdr.pkt_type = HFI_CMD_SESSION_FLUSH; - flush_pkt.shdr.session_id = inst->session_id; - flush_pkt.flush_type = flush_type; - - ret = iris_hfi_queue_cmd_write(core, &flush_pkt, flush_pkt.shdr.hdr.size); - if (!ret) { - inst->flush_responses_pending++; - ret = iris_wait_for_session_response(inst, true); - } } return ret; @@ -241,23 +273,44 @@ static int iris_hfi_gen1_session_continue(struct iris_inst *inst, u32 plane) static int iris_hfi_gen1_queue_input_buffer(struct iris_inst *inst, struct iris_buffer *buf) { - struct hfi_session_empty_buffer_compressed_pkt ip_pkt; - - ip_pkt.shdr.hdr.size = sizeof(struct hfi_session_empty_buffer_compressed_pkt); - ip_pkt.shdr.hdr.pkt_type = HFI_CMD_SESSION_EMPTY_BUFFER; - ip_pkt.shdr.session_id = inst->session_id; - ip_pkt.time_stamp_hi = upper_32_bits(buf->timestamp); - ip_pkt.time_stamp_lo = lower_32_bits(buf->timestamp); - ip_pkt.flags = buf->flags; - ip_pkt.mark_target = 0; - ip_pkt.mark_data = 0; - ip_pkt.offset = buf->data_offset; - ip_pkt.alloc_len = buf->buffer_size; - ip_pkt.filled_len = buf->data_size; - ip_pkt.input_tag = buf->index; - ip_pkt.packet_buffer = buf->device_addr; - - return iris_hfi_queue_cmd_write(inst->core, &ip_pkt, ip_pkt.shdr.hdr.size); + struct hfi_session_empty_buffer_compressed_pkt com_ip_pkt; + struct hfi_session_empty_buffer_uncompressed_pkt uncom_ip_pkt; + + if (inst->domain == DECODER) { + com_ip_pkt.shdr.hdr.size = sizeof(struct hfi_session_empty_buffer_compressed_pkt); + com_ip_pkt.shdr.hdr.pkt_type = HFI_CMD_SESSION_EMPTY_BUFFER; + com_ip_pkt.shdr.session_id = inst->session_id; + com_ip_pkt.time_stamp_hi = upper_32_bits(buf->timestamp); + com_ip_pkt.time_stamp_lo = lower_32_bits(buf->timestamp); + com_ip_pkt.flags = buf->flags; + com_ip_pkt.mark_target = 0; + com_ip_pkt.mark_data = 0; + com_ip_pkt.offset = buf->data_offset; + com_ip_pkt.alloc_len = buf->buffer_size; + com_ip_pkt.filled_len = buf->data_size; + com_ip_pkt.input_tag = buf->index; + com_ip_pkt.packet_buffer = buf->device_addr; + return iris_hfi_queue_cmd_write(inst->core, &com_ip_pkt, + com_ip_pkt.shdr.hdr.size); + } else { + uncom_ip_pkt.shdr.hdr.size = + sizeof(struct hfi_session_empty_buffer_uncompressed_pkt); + uncom_ip_pkt.shdr.hdr.pkt_type = HFI_CMD_SESSION_EMPTY_BUFFER; + uncom_ip_pkt.shdr.session_id = inst->session_id; + uncom_ip_pkt.time_stamp_hi = upper_32_bits(buf->timestamp); + uncom_ip_pkt.time_stamp_lo = lower_32_bits(buf->timestamp); + uncom_ip_pkt.view_id = 0; + uncom_ip_pkt.flags = buf->flags; + uncom_ip_pkt.mark_target = 0; + uncom_ip_pkt.mark_data = 0; + uncom_ip_pkt.offset = buf->data_offset; + uncom_ip_pkt.alloc_len = buf->buffer_size; + uncom_ip_pkt.filled_len = buf->data_size; + uncom_ip_pkt.input_tag = buf->index; + uncom_ip_pkt.packet_buffer = buf->device_addr; + return iris_hfi_queue_cmd_write(inst->core, &uncom_ip_pkt, + uncom_ip_pkt.shdr.hdr.size); + } } static int iris_hfi_gen1_queue_output_buffer(struct iris_inst *inst, struct iris_buffer *buf) @@ -330,6 +383,8 @@ static int iris_hfi_gen1_session_queue_buffer(struct iris_inst *inst, struct iri case BUF_PERSIST: case BUF_BIN: case BUF_SCRATCH_1: + case BUF_SCRATCH_2: + case BUF_ARP: return iris_hfi_gen1_queue_internal_buffer(inst, buf); default: return -EINVAL; @@ -395,16 +450,31 @@ exit: static int iris_hfi_gen1_session_drain(struct iris_inst *inst, u32 plane) { - struct hfi_session_empty_buffer_compressed_pkt ip_pkt = {0}; + if (inst->domain == DECODER) { + struct hfi_session_empty_buffer_compressed_pkt ip_pkt = {0}; + + ip_pkt.shdr.hdr.size = sizeof(struct hfi_session_empty_buffer_compressed_pkt); + ip_pkt.shdr.hdr.pkt_type = HFI_CMD_SESSION_EMPTY_BUFFER; + ip_pkt.shdr.session_id = inst->session_id; + ip_pkt.flags = HFI_BUFFERFLAG_EOS; + ip_pkt.packet_buffer = 0xdeadb000; + + return iris_hfi_queue_cmd_write(inst->core, &ip_pkt, ip_pkt.shdr.hdr.size); + } + + if (inst->domain == ENCODER) { + struct hfi_session_empty_buffer_uncompressed_pkt ip_pkt = {0}; - ip_pkt.shdr.hdr.size = sizeof(struct hfi_session_empty_buffer_compressed_pkt); - ip_pkt.shdr.hdr.pkt_type = HFI_CMD_SESSION_EMPTY_BUFFER; - ip_pkt.shdr.session_id = inst->session_id; - ip_pkt.flags = HFI_BUFFERFLAG_EOS; - if (inst->codec == V4L2_PIX_FMT_VP9) + ip_pkt.shdr.hdr.size = sizeof(struct hfi_session_empty_buffer_uncompressed_pkt); + ip_pkt.shdr.hdr.pkt_type = HFI_CMD_SESSION_EMPTY_BUFFER; + ip_pkt.shdr.session_id = inst->session_id; + ip_pkt.flags = HFI_BUFFERFLAG_EOS; ip_pkt.packet_buffer = 0xdeadb000; - return iris_hfi_queue_cmd_write(inst->core, &ip_pkt, ip_pkt.shdr.hdr.size); + return iris_hfi_queue_cmd_write(inst->core, &ip_pkt, ip_pkt.shdr.hdr.size); + } + + return -EINVAL; } static int @@ -507,6 +577,114 @@ iris_hfi_gen1_packet_session_set_property(struct hfi_session_set_property_pkt *p packet->shdr.hdr.size += sizeof(u32) + sizeof(*wm); break; } + case HFI_PROPERTY_PARAM_PROFILE_LEVEL_CURRENT: { + struct hfi_profile_level *in = pdata, *pl = prop_data; + + pl->level = in->level; + pl->profile = in->profile; + if (pl->profile <= 0) + /* Profile not supported, falling back to high */ + pl->profile = V4L2_MPEG_VIDEO_H264_PROFILE_HIGH; + + if (!pl->level) + /* Level not supported, falling back to 1 */ + pl->level = 1; + + packet->shdr.hdr.size += sizeof(u32) + sizeof(*pl); + break; + } + case HFI_PROPERTY_CONFIG_VENC_SYNC_FRAME_SEQUENCE_HEADER: { + struct hfi_enable *en = prop_data; + u32 *in = pdata; + + en->enable = *in; + packet->shdr.hdr.size += sizeof(u32) + sizeof(*en); + break; + } + case HFI_PROPERTY_CONFIG_VENC_TARGET_BITRATE: { + struct hfi_bitrate *brate = prop_data; + u32 *in = pdata; + + brate->bitrate = *in; + brate->layer_id = 0; + packet->shdr.hdr.size += sizeof(u32) + sizeof(*brate); + break; + } + case HFI_PROPERTY_PARAM_VENC_RATE_CONTROL: { + u32 *in = pdata; + + switch (*in) { + case HFI_RATE_CONTROL_OFF: + case HFI_RATE_CONTROL_CBR_CFR: + case HFI_RATE_CONTROL_CBR_VFR: + case HFI_RATE_CONTROL_VBR_CFR: + case HFI_RATE_CONTROL_VBR_VFR: + case HFI_RATE_CONTROL_CQ: + break; + default: + return -EINVAL; + } + + packet->data[1] = *in; + packet->shdr.hdr.size += sizeof(u32) * 2; + break; + } + case HFI_PROPERTY_PARAM_VENC_H264_ENTROPY_CONTROL: { + struct hfi_h264_entropy_control *entropy = prop_data; + u32 *in = pdata; + + entropy->entropy_mode = *in; + if (entropy->entropy_mode == HFI_H264_ENTROPY_CABAC) + entropy->cabac_model = HFI_H264_CABAC_MODEL_0; + packet->shdr.hdr.size += sizeof(u32) + sizeof(*entropy); + break; + } + case HFI_PROPERTY_PARAM_VENC_SESSION_QP_RANGE_V2: { + struct hfi_quantization_range_v2 *range = prop_data; + struct hfi_quantization_range_v2 *in = pdata; + u32 min_qp, max_qp; + + min_qp = in->min_qp.qp_packed; + max_qp = in->max_qp.qp_packed; + + /* We'll be packing in the qp, so make sure we + * won't be losing data when masking + */ + if (min_qp > 0xff || max_qp > 0xff) + return -ERANGE; + + range->min_qp.layer_id = 0xFF; + range->max_qp.layer_id = 0xFF; + range->min_qp.qp_packed = (min_qp & 0xFF) | ((min_qp & 0xFF) << 8) | + ((min_qp & 0xFF) << 16); + range->max_qp.qp_packed = (max_qp & 0xFF) | ((max_qp & 0xFF) << 8) | + ((max_qp & 0xFF) << 16); + range->min_qp.enable = 7; + range->max_qp.enable = 7; + packet->shdr.hdr.size += sizeof(u32) + sizeof(*range); + break; + } + case HFI_PROPERTY_CONFIG_FRAME_RATE: { + struct hfi_framerate *frate = prop_data; + struct hfi_framerate *in = pdata; + + frate->buffer_type = in->buffer_type; + frate->framerate = in->framerate; + packet->shdr.hdr.size += sizeof(u32) + sizeof(*frate); + break; + } + case HFI_PROPERTY_PARAM_UNCOMPRESSED_PLANE_ACTUAL_INFO: { + struct hfi_uncompressed_plane_actual_info *plane_actual_info = prop_data; + struct hfi_uncompressed_plane_actual_info *in = pdata; + + plane_actual_info->buffer_type = in->buffer_type; + plane_actual_info->num_planes = in->num_planes; + plane_actual_info->plane_format[0] = in->plane_format[0]; + if (in->num_planes > 1) + plane_actual_info->plane_format[1] = in->plane_format[1]; + packet->shdr.hdr.size += sizeof(u32) + sizeof(*plane_actual_info); + break; + } default: return -EINVAL; } @@ -549,7 +727,7 @@ static int iris_hfi_gen1_session_set_property(struct iris_inst *inst, u32 packet return hfi_gen1_set_property(inst, packet_type, payload, payload_size); } -static int iris_hfi_gen1_set_resolution(struct iris_inst *inst) +static int iris_hfi_gen1_set_resolution(struct iris_inst *inst, u32 plane) { u32 ptype = HFI_PROPERTY_PARAM_FRAME_SIZE; struct hfi_framesize fs; @@ -564,14 +742,18 @@ static int iris_hfi_gen1_set_resolution(struct iris_inst *inst) if (ret) return ret; } - fs.buffer_type = HFI_BUFFER_OUTPUT2; + if (inst->domain == DECODER) + fs.buffer_type = HFI_BUFFER_OUTPUT2; + else + fs.buffer_type = HFI_BUFFER_OUTPUT; + fs.width = inst->fmt_dst->fmt.pix_mp.width; fs.height = inst->fmt_dst->fmt.pix_mp.height; return hfi_gen1_set_property(inst, ptype, &fs, sizeof(fs)); } -static int iris_hfi_gen1_decide_core(struct iris_inst *inst) +static int iris_hfi_gen1_decide_core(struct iris_inst *inst, u32 plane) { const u32 ptype = HFI_PROPERTY_CONFIG_VIDEOCORES_USAGE; struct hfi_videocores_usage_type cu; @@ -581,36 +763,45 @@ static int iris_hfi_gen1_decide_core(struct iris_inst *inst) return hfi_gen1_set_property(inst, ptype, &cu, sizeof(cu)); } -static int iris_hfi_gen1_set_raw_format(struct iris_inst *inst) +static int iris_hfi_gen1_set_raw_format(struct iris_inst *inst, u32 plane) { const u32 ptype = HFI_PROPERTY_PARAM_UNCOMPRESSED_FORMAT_SELECT; - u32 pixelformat = inst->fmt_dst->fmt.pix_mp.pixelformat; struct hfi_uncompressed_format_select fmt; + u32 pixelformat; int ret; - if (iris_split_mode_enabled(inst)) { - fmt.buffer_type = HFI_BUFFER_OUTPUT; - fmt.format = pixelformat == V4L2_PIX_FMT_NV12 ? HFI_COLOR_FORMAT_NV12_UBWC : 0; + if (inst->domain == DECODER) { + pixelformat = inst->fmt_dst->fmt.pix_mp.pixelformat; + if (iris_split_mode_enabled(inst)) { + fmt.buffer_type = HFI_BUFFER_OUTPUT; + fmt.format = pixelformat == V4L2_PIX_FMT_NV12 ? + HFI_COLOR_FORMAT_NV12_UBWC : 0; - ret = hfi_gen1_set_property(inst, ptype, &fmt, sizeof(fmt)); - if (ret) - return ret; + ret = hfi_gen1_set_property(inst, ptype, &fmt, sizeof(fmt)); + if (ret) + return ret; - fmt.buffer_type = HFI_BUFFER_OUTPUT2; - fmt.format = pixelformat == V4L2_PIX_FMT_NV12 ? HFI_COLOR_FORMAT_NV12 : 0; + fmt.buffer_type = HFI_BUFFER_OUTPUT2; + fmt.format = pixelformat == V4L2_PIX_FMT_NV12 ? HFI_COLOR_FORMAT_NV12 : 0; - ret = hfi_gen1_set_property(inst, ptype, &fmt, sizeof(fmt)); + ret = hfi_gen1_set_property(inst, ptype, &fmt, sizeof(fmt)); + } else { + fmt.buffer_type = HFI_BUFFER_OUTPUT; + fmt.format = pixelformat == V4L2_PIX_FMT_NV12 ? HFI_COLOR_FORMAT_NV12 : 0; + + ret = hfi_gen1_set_property(inst, ptype, &fmt, sizeof(fmt)); + } } else { - fmt.buffer_type = HFI_BUFFER_OUTPUT; + pixelformat = inst->fmt_src->fmt.pix_mp.pixelformat; + fmt.buffer_type = HFI_BUFFER_INPUT; fmt.format = pixelformat == V4L2_PIX_FMT_NV12 ? HFI_COLOR_FORMAT_NV12 : 0; - ret = hfi_gen1_set_property(inst, ptype, &fmt, sizeof(fmt)); } return ret; } -static int iris_hfi_gen1_set_format_constraints(struct iris_inst *inst) +static int iris_hfi_gen1_set_format_constraints(struct iris_inst *inst, u32 plane) { const u32 ptype = HFI_PROPERTY_PARAM_UNCOMPRESSED_PLANE_ACTUAL_CONSTRAINTS_INFO; struct hfi_uncompressed_plane_actual_constraints_info pconstraint; @@ -630,7 +821,7 @@ static int iris_hfi_gen1_set_format_constraints(struct iris_inst *inst) return hfi_gen1_set_property(inst, ptype, &pconstraint, sizeof(pconstraint)); } -static int iris_hfi_gen1_set_num_bufs(struct iris_inst *inst) +static int iris_hfi_gen1_set_num_bufs(struct iris_inst *inst, u32 plane) { u32 ptype = HFI_PROPERTY_PARAM_BUFFER_COUNT_ACTUAL; struct hfi_buffer_count_actual buf_count; @@ -644,20 +835,28 @@ static int iris_hfi_gen1_set_num_bufs(struct iris_inst *inst) if (ret) return ret; - if (iris_split_mode_enabled(inst)) { - buf_count.type = HFI_BUFFER_OUTPUT; - buf_count.count_actual = VIDEO_MAX_FRAME; - buf_count.count_min_host = VIDEO_MAX_FRAME; + if (inst->domain == DECODER) { + if (iris_split_mode_enabled(inst)) { + buf_count.type = HFI_BUFFER_OUTPUT; + buf_count.count_actual = VIDEO_MAX_FRAME; + buf_count.count_min_host = VIDEO_MAX_FRAME; - ret = hfi_gen1_set_property(inst, ptype, &buf_count, sizeof(buf_count)); - if (ret) - return ret; + ret = hfi_gen1_set_property(inst, ptype, &buf_count, sizeof(buf_count)); + if (ret) + return ret; - buf_count.type = HFI_BUFFER_OUTPUT2; - buf_count.count_actual = iris_vpu_buf_count(inst, BUF_DPB); - buf_count.count_min_host = iris_vpu_buf_count(inst, BUF_DPB); + buf_count.type = HFI_BUFFER_OUTPUT2; + buf_count.count_actual = iris_vpu_buf_count(inst, BUF_DPB); + buf_count.count_min_host = iris_vpu_buf_count(inst, BUF_DPB); - ret = hfi_gen1_set_property(inst, ptype, &buf_count, sizeof(buf_count)); + ret = hfi_gen1_set_property(inst, ptype, &buf_count, sizeof(buf_count)); + } else { + buf_count.type = HFI_BUFFER_OUTPUT; + buf_count.count_actual = VIDEO_MAX_FRAME; + buf_count.count_min_host = VIDEO_MAX_FRAME; + + ret = hfi_gen1_set_property(inst, ptype, &buf_count, sizeof(buf_count)); + } } else { buf_count.type = HFI_BUFFER_OUTPUT; buf_count.count_actual = VIDEO_MAX_FRAME; @@ -669,7 +868,7 @@ static int iris_hfi_gen1_set_num_bufs(struct iris_inst *inst) return ret; } -static int iris_hfi_gen1_set_multistream(struct iris_inst *inst) +static int iris_hfi_gen1_set_multistream(struct iris_inst *inst, u32 plane) { u32 ptype = HFI_PROPERTY_PARAM_VDEC_MULTI_STREAM; struct hfi_multi_stream multi = {0}; @@ -704,7 +903,7 @@ static int iris_hfi_gen1_set_multistream(struct iris_inst *inst) return ret; } -static int iris_hfi_gen1_set_bufsize(struct iris_inst *inst) +static int iris_hfi_gen1_set_bufsize(struct iris_inst *inst, u32 plane) { const u32 ptype = HFI_PROPERTY_PARAM_BUFFER_SIZE_ACTUAL; struct hfi_buffer_size_actual bufsz; @@ -712,7 +911,7 @@ static int iris_hfi_gen1_set_bufsize(struct iris_inst *inst) if (iris_split_mode_enabled(inst)) { bufsz.type = HFI_BUFFER_OUTPUT; - bufsz.size = iris_vpu_buf_size(inst, BUF_DPB); + bufsz.size = inst->core->iris_platform_data->get_vpu_buffer_size(inst, BUF_DPB); ret = hfi_gen1_set_property(inst, ptype, &bufsz, sizeof(bufsz)); if (ret) @@ -739,14 +938,49 @@ static int iris_hfi_gen1_set_bufsize(struct iris_inst *inst) return ret; } +static int iris_hfi_gen1_set_frame_rate(struct iris_inst *inst, u32 plane) +{ + const u32 ptype = HFI_PROPERTY_CONFIG_FRAME_RATE; + struct hfi_framerate frate; + + if (V4L2_TYPE_IS_OUTPUT(plane)) + return 0; + + frate.buffer_type = HFI_BUFFER_OUTPUT; + frate.framerate = inst->frame_rate << 16; + + return hfi_gen1_set_property(inst, ptype, &frate, sizeof(frate)); +} + +static int iris_hfi_gen1_set_stride(struct iris_inst *inst, u32 plane) +{ + const u32 ptype = HFI_PROPERTY_PARAM_UNCOMPRESSED_PLANE_ACTUAL_INFO; + struct hfi_uncompressed_plane_actual_info plane_actual_info; + + plane_actual_info.buffer_type = HFI_BUFFER_INPUT; + plane_actual_info.num_planes = 2; + plane_actual_info.plane_format[0].actual_stride = + ALIGN(inst->fmt_src->fmt.pix_mp.width, 128); + plane_actual_info.plane_format[0].actual_plane_buffer_height = + ALIGN(inst->fmt_src->fmt.pix_mp.height, 32); + plane_actual_info.plane_format[1].actual_stride = + ALIGN(inst->fmt_src->fmt.pix_mp.width, 128); + plane_actual_info.plane_format[1].actual_plane_buffer_height = + (ALIGN(inst->fmt_src->fmt.pix_mp.height, 32)) / 2; + + return hfi_gen1_set_property(inst, ptype, &plane_actual_info, sizeof(plane_actual_info)); +} + static int iris_hfi_gen1_session_set_config_params(struct iris_inst *inst, u32 plane) { + struct iris_hfi_prop_type_handle const *handler = NULL; + u32 handler_size = 0; struct iris_core *core = inst->core; u32 config_params_size, i, j; const u32 *config_params; int ret; - static const struct iris_hfi_prop_type_handle prop_type_handle_inp_arr[] = { + static const struct iris_hfi_prop_type_handle vdec_prop_type_handle_inp_arr[] = { {HFI_PROPERTY_PARAM_FRAME_SIZE, iris_hfi_gen1_set_resolution}, {HFI_PROPERTY_CONFIG_VIDEOCORES_USAGE, @@ -763,7 +997,7 @@ static int iris_hfi_gen1_session_set_config_params(struct iris_inst *inst, u32 p iris_hfi_gen1_set_bufsize}, }; - static const struct iris_hfi_prop_type_handle prop_type_handle_out_arr[] = { + static const struct iris_hfi_prop_type_handle vdec_prop_type_handle_out_arr[] = { {HFI_PROPERTY_PARAM_FRAME_SIZE, iris_hfi_gen1_set_resolution}, {HFI_PROPERTY_PARAM_UNCOMPRESSED_FORMAT_SELECT, @@ -778,29 +1012,43 @@ static int iris_hfi_gen1_session_set_config_params(struct iris_inst *inst, u32 p iris_hfi_gen1_set_bufsize}, }; - config_params = core->iris_platform_data->input_config_params_default; - config_params_size = core->iris_platform_data->input_config_params_default_size; - - if (V4L2_TYPE_IS_OUTPUT(plane)) { - for (i = 0; i < config_params_size; i++) { - for (j = 0; j < ARRAY_SIZE(prop_type_handle_inp_arr); j++) { - if (prop_type_handle_inp_arr[j].type == config_params[i]) { - ret = prop_type_handle_inp_arr[j].handle(inst); - if (ret) - return ret; - break; - } - } + static const struct iris_hfi_prop_type_handle venc_prop_type_handle_inp_arr[] = { + {HFI_PROPERTY_CONFIG_FRAME_RATE, + iris_hfi_gen1_set_frame_rate}, + {HFI_PROPERTY_PARAM_UNCOMPRESSED_PLANE_ACTUAL_INFO, + iris_hfi_gen1_set_stride}, + {HFI_PROPERTY_PARAM_FRAME_SIZE, + iris_hfi_gen1_set_resolution}, + {HFI_PROPERTY_PARAM_UNCOMPRESSED_FORMAT_SELECT, + iris_hfi_gen1_set_raw_format}, + {HFI_PROPERTY_PARAM_BUFFER_COUNT_ACTUAL, + iris_hfi_gen1_set_num_bufs}, + }; + + if (inst->domain == DECODER) { + config_params = core->iris_platform_data->dec_input_config_params_default; + config_params_size = core->iris_platform_data->dec_input_config_params_default_size; + if (V4L2_TYPE_IS_OUTPUT(plane)) { + handler = vdec_prop_type_handle_inp_arr; + handler_size = ARRAY_SIZE(vdec_prop_type_handle_inp_arr); + } else if (V4L2_TYPE_IS_CAPTURE(plane)) { + handler = vdec_prop_type_handle_out_arr; + handler_size = ARRAY_SIZE(vdec_prop_type_handle_out_arr); } - } else if (V4L2_TYPE_IS_CAPTURE(plane)) { - for (i = 0; i < config_params_size; i++) { - for (j = 0; j < ARRAY_SIZE(prop_type_handle_out_arr); j++) { - if (prop_type_handle_out_arr[j].type == config_params[i]) { - ret = prop_type_handle_out_arr[j].handle(inst); - if (ret) - return ret; - break; - } + } else { + config_params = core->iris_platform_data->enc_input_config_params; + config_params_size = core->iris_platform_data->enc_input_config_params_size; + handler = venc_prop_type_handle_inp_arr; + handler_size = ARRAY_SIZE(venc_prop_type_handle_inp_arr); + } + + for (i = 0; i < config_params_size; i++) { + for (j = 0; j < handler_size; j++) { + if (handler[j].type == config_params[i]) { + ret = handler[j].handle(inst, plane); + if (ret) + return ret; + break; } } } diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen1_defines.h b/drivers/media/platform/qcom/iris/iris_hfi_gen1_defines.h index d4d119ca98b0..42226ccee3d9 100644 --- a/drivers/media/platform/qcom/iris/iris_hfi_gen1_defines.h +++ b/drivers/media/platform/qcom/iris/iris_hfi_gen1_defines.h @@ -10,6 +10,7 @@ #define HFI_VIDEO_ARCH_OX 0x1 +#define HFI_SESSION_TYPE_ENC 1 #define HFI_SESSION_TYPE_DEC 2 #define HFI_VIDEO_CODEC_H264 0x00000002 @@ -73,18 +74,22 @@ #define HFI_BUFFER_INPUT 0x1 #define HFI_BUFFER_OUTPUT 0x2 #define HFI_BUFFER_OUTPUT2 0x3 +#define HFI_BUFFER_INTERNAL_PERSIST 0x4 #define HFI_BUFFER_INTERNAL_PERSIST_1 0x5 #define HFI_BUFFER_INTERNAL_SCRATCH 0x6 #define HFI_BUFFER_INTERNAL_SCRATCH_1 0x7 +#define HFI_BUFFER_INTERNAL_SCRATCH_2 0x8 #define HFI_PROPERTY_SYS_CODEC_POWER_PLANE_CTRL 0x5 #define HFI_PROPERTY_SYS_IMAGE_VERSION 0x6 #define HFI_PROPERTY_PARAM_FRAME_SIZE 0x1001 +#define HFI_PROPERTY_PARAM_UNCOMPRESSED_PLANE_ACTUAL_INFO 0x1002 #define HFI_PROPERTY_PARAM_UNCOMPRESSED_FORMAT_SELECT 0x1003 #define HFI_PROPERTY_PARAM_PROFILE_LEVEL_CURRENT 0x1005 #define HFI_PROPERTY_PARAM_WORK_MODE 0x1015 #define HFI_PROPERTY_PARAM_WORK_ROUTE 0x1017 +#define HFI_PROPERTY_CONFIG_FRAME_RATE 0x2001 #define HFI_PROPERTY_CONFIG_VIDEOCORES_USAGE 0x2002 #define HFI_PROPERTY_PARAM_VDEC_MULTI_STREAM 0x1003001 @@ -111,15 +116,32 @@ #define HFI_MSG_SESSION_RELEASE_RESOURCES 0x22100a #define HFI_MSG_SESSION_RELEASE_BUFFERS 0x22100c -#define HFI_PICTURE_I 0x00000001 -#define HFI_PICTURE_P 0x00000002 -#define HFI_PICTURE_B 0x00000004 -#define HFI_PICTURE_IDR 0x00000008 +#define HFI_GEN1_PICTURE_I 0x00000001 +#define HFI_GEN1_PICTURE_P 0x00000002 +#define HFI_GEN1_PICTURE_B 0x00000004 +#define HFI_GEN1_PICTURE_IDR 0x00000008 #define HFI_FRAME_NOTCODED 0x7f002000 #define HFI_FRAME_YUV 0x7f004000 #define HFI_UNUSED_PICT 0x10000000 -#define HFI_BUFFERFLAG_DATACORRUPT 0x00000008 -#define HFI_BUFFERFLAG_DROP_FRAME 0x20000000 +#define HFI_BUFFERFLAG_DATACORRUPT 0x00000008 +#define HFI_BUFFERFLAG_DROP_FRAME 0x20000000 +#define HFI_RATE_CONTROL_OFF 0x1000001 +#define HFI_RATE_CONTROL_VBR_VFR 0x1000002 +#define HFI_RATE_CONTROL_VBR_CFR 0x1000003 +#define HFI_RATE_CONTROL_CBR_VFR 0x1000004 +#define HFI_RATE_CONTROL_CBR_CFR 0x1000005 +#define HFI_RATE_CONTROL_CQ 0x1000008 + +#define HFI_H264_ENTROPY_CAVLC 0x1 +#define HFI_H264_ENTROPY_CABAC 0x2 + +#define HFI_PROPERTY_PARAM_VENC_H264_ENTROPY_CONTROL 0x2005002 +#define HFI_PROPERTY_PARAM_VENC_H264_DEBLOCK_CONTROL 0x2005003 +#define HFI_PROPERTY_PARAM_VENC_RATE_CONTROL 0x2005004 +#define HFI_PROPERTY_PARAM_VENC_SESSION_QP_RANGE_V2 0x2005009 +#define HFI_PROPERTY_PARAM_VENC_MAX_NUM_B_FRAMES 0x2005020 +#define HFI_PROPERTY_CONFIG_VENC_TARGET_BITRATE 0x2006001 +#define HFI_PROPERTY_CONFIG_VENC_SYNC_FRAME_SEQUENCE_HEADER 0x2006008 struct hfi_pkt_hdr { u32 size; @@ -194,6 +216,23 @@ struct hfi_session_empty_buffer_compressed_pkt { u32 data; }; +struct hfi_session_empty_buffer_uncompressed_pkt { + struct hfi_session_hdr_pkt shdr; + u32 view_id; + u32 time_stamp_hi; + u32 time_stamp_lo; + u32 flags; + u32 mark_target; + u32 mark_data; + u32 alloc_len; + u32 filled_len; + u32 offset; + u32 input_tag; + u32 packet_buffer; + u32 extradata_buffer; + u32 data; +}; + struct hfi_session_fill_buffer_pkt { struct hfi_session_hdr_pkt shdr; u32 stream_id; @@ -340,6 +379,17 @@ struct hfi_uncompressed_plane_actual_constraints_info { struct hfi_uncompressed_plane_constraints plane_format[2]; }; +struct hfi_uncompressed_plane_actual { + int actual_stride; + u32 actual_plane_buffer_height; +}; + +struct hfi_uncompressed_plane_actual_info { + u32 buffer_type; + u32 num_planes; + struct hfi_uncompressed_plane_actual plane_format[2]; +}; + struct hfi_buffer_count_actual { u32 type; u32 count_actual; @@ -367,6 +417,36 @@ struct hfi_buffer_requirements { u32 alignment; }; +struct hfi_bitrate { + u32 bitrate; + u32 layer_id; +}; + +#define HFI_H264_CABAC_MODEL_0 0x1 + +struct hfi_h264_entropy_control { + u32 entropy_mode; + u32 cabac_model; +}; + +struct hfi_quantization_v2 { + u32 qp_packed; + u32 layer_id; + u32 enable; + u32 reserved[3]; +}; + +struct hfi_quantization_range_v2 { + struct hfi_quantization_v2 min_qp; + struct hfi_quantization_v2 max_qp; + u32 reserved[4]; +}; + +struct hfi_framerate { + u32 buffer_type; + u32 framerate; +}; + struct hfi_event_data { u32 error; u32 height; @@ -398,6 +478,26 @@ struct hfi_msg_session_empty_buffer_done_pkt { u32 data[]; }; +struct hfi_msg_session_fbd_compressed_pkt { + struct hfi_session_hdr_pkt shdr; + u32 time_stamp_hi; + u32 time_stamp_lo; + u32 error_type; + u32 flags; + u32 mark_target; + u32 mark_data; + u32 stats; + u32 offset; + u32 alloc_len; + u32 filled_len; + u32 input_tag; + u32 output_tag; + u32 picture_type; + u32 packet_buffer; + u32 extradata_buffer; + u32 data[]; +}; + struct hfi_msg_session_fbd_uncompressed_plane0_pkt { struct hfi_session_hdr_pkt shdr; u32 stream_id; diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen1_response.c b/drivers/media/platform/qcom/iris/iris_hfi_gen1_response.c index 8d1ce8a19a45..8e864c239e29 100644 --- a/drivers/media/platform/qcom/iris/iris_hfi_gen1_response.c +++ b/drivers/media/platform/qcom/iris/iris_hfi_gen1_response.c @@ -387,24 +387,43 @@ error: static void iris_hfi_gen1_session_ftb_done(struct iris_inst *inst, void *packet) { - struct hfi_msg_session_fbd_uncompressed_plane0_pkt *pkt = packet; + struct hfi_msg_session_fbd_uncompressed_plane0_pkt *uncom_pkt = packet; + struct hfi_msg_session_fbd_compressed_pkt *com_pkt = packet; struct v4l2_m2m_ctx *m2m_ctx = inst->m2m_ctx; struct v4l2_m2m_buffer *m2m_buffer, *n; struct hfi_session_flush_pkt flush_pkt; - u32 timestamp_hi = pkt->time_stamp_hi; - u32 timestamp_lo = pkt->time_stamp_lo; + u32 timestamp_hi; + u32 timestamp_lo; struct iris_core *core = inst->core; - u32 filled_len = pkt->filled_len; - u32 pic_type = pkt->picture_type; - u32 output_tag = pkt->output_tag; + u32 filled_len; + u32 pic_type; + u32 output_tag; struct iris_buffer *buf, *iter; struct iris_buffers *buffers; - u32 hfi_flags = pkt->flags; - u32 offset = pkt->offset; + u32 hfi_flags; + u32 offset; u64 timestamp_us = 0; bool found = false; u32 flags = 0; + if (inst->domain == DECODER) { + timestamp_hi = uncom_pkt->time_stamp_hi; + timestamp_lo = uncom_pkt->time_stamp_lo; + filled_len = uncom_pkt->filled_len; + pic_type = uncom_pkt->picture_type; + output_tag = uncom_pkt->output_tag; + hfi_flags = uncom_pkt->flags; + offset = uncom_pkt->offset; + } else { + timestamp_hi = com_pkt->time_stamp_hi; + timestamp_lo = com_pkt->time_stamp_lo; + filled_len = com_pkt->filled_len; + pic_type = com_pkt->picture_type; + output_tag = com_pkt->output_tag; + hfi_flags = com_pkt->flags; + offset = com_pkt->offset; + } + if ((hfi_flags & HFI_BUFFERFLAG_EOS) && !filled_len) { reinit_completion(&inst->flush_completion); @@ -416,11 +435,10 @@ static void iris_hfi_gen1_session_ftb_done(struct iris_inst *inst, void *packet) inst->flush_responses_pending++; iris_inst_sub_state_change_drain_last(inst); - - return; } - if (iris_split_mode_enabled(inst) && pkt->stream_id == 0) { + if (iris_split_mode_enabled(inst) && inst->domain == DECODER && + uncom_pkt->stream_id == 0) { buffers = &inst->buffers[BUF_DPB]; if (!buffers) goto error; @@ -461,8 +479,14 @@ static void iris_hfi_gen1_session_ftb_done(struct iris_inst *inst, void *packet) timestamp_us = timestamp_hi; timestamp_us = (timestamp_us << 32) | timestamp_lo; } else { - if (pkt->stream_id == 1 && !inst->last_buffer_dequeued) { - if (iris_drc_pending(inst)) { + if (inst->domain == DECODER && uncom_pkt->stream_id == 1 && + !inst->last_buffer_dequeued) { + if (iris_drc_pending(inst) || iris_drain_pending(inst)) { + flags |= V4L2_BUF_FLAG_LAST; + inst->last_buffer_dequeued = true; + } + } else if (inst->domain == ENCODER) { + if (!inst->last_buffer_dequeued && iris_drain_pending(inst)) { flags |= V4L2_BUF_FLAG_LAST; inst->last_buffer_dequeued = true; } @@ -471,14 +495,14 @@ static void iris_hfi_gen1_session_ftb_done(struct iris_inst *inst, void *packet) buf->timestamp = timestamp_us; switch (pic_type) { - case HFI_PICTURE_IDR: - case HFI_PICTURE_I: + case HFI_GEN1_PICTURE_IDR: + case HFI_GEN1_PICTURE_I: flags |= V4L2_BUF_FLAG_KEYFRAME; break; - case HFI_PICTURE_P: + case HFI_GEN1_PICTURE_P: flags |= V4L2_BUF_FLAG_PFRAME; break; - case HFI_PICTURE_B: + case HFI_GEN1_PICTURE_B: flags |= V4L2_BUF_FLAG_BFRAME; break; case HFI_FRAME_NOTCODED: @@ -553,7 +577,7 @@ static const struct iris_hfi_gen1_response_pkt_info pkt_infos[] = { }, { .pkt = HFI_MSG_SESSION_FILL_BUFFER, - .pkt_sz = sizeof(struct hfi_msg_session_fbd_uncompressed_plane0_pkt), + .pkt_sz = sizeof(struct hfi_msg_session_fbd_compressed_pkt), }, { .pkt = HFI_MSG_SESSION_FLUSH, diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen2_command.c b/drivers/media/platform/qcom/iris/iris_hfi_gen2_command.c index 7ca5ae13d62b..4ce71a142508 100644 --- a/drivers/media/platform/qcom/iris/iris_hfi_gen2_command.c +++ b/drivers/media/platform/qcom/iris/iris_hfi_gen2_command.c @@ -88,33 +88,63 @@ static int iris_hfi_gen2_sys_pc_prep(struct iris_core *core) return ret; } -static u32 iris_hfi_gen2_get_port(u32 plane) +static u32 iris_hfi_gen2_get_port(struct iris_inst *inst, u32 plane) { - switch (plane) { - case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: - return HFI_PORT_BITSTREAM; - case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: - return HFI_PORT_RAW; - default: - return HFI_PORT_NONE; + if (inst->domain == DECODER) { + switch (plane) { + case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: + return HFI_PORT_BITSTREAM; + case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: + return HFI_PORT_RAW; + default: + return HFI_PORT_NONE; + } + } else { + switch (plane) { + case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: + return HFI_PORT_RAW; + case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: + return HFI_PORT_BITSTREAM; + default: + return HFI_PORT_NONE; + } } } -static u32 iris_hfi_gen2_get_port_from_buf_type(enum iris_buffer_type buffer_type) +static u32 iris_hfi_gen2_get_port_from_buf_type(struct iris_inst *inst, + enum iris_buffer_type buffer_type) { - switch (buffer_type) { - case BUF_INPUT: - case BUF_BIN: - case BUF_COMV: - case BUF_NON_COMV: - case BUF_LINE: - return HFI_PORT_BITSTREAM; - case BUF_OUTPUT: - case BUF_DPB: - return HFI_PORT_RAW; - case BUF_PERSIST: - default: - return HFI_PORT_NONE; + if (inst->domain == DECODER) { + switch (buffer_type) { + case BUF_INPUT: + case BUF_BIN: + case BUF_COMV: + case BUF_NON_COMV: + case BUF_LINE: + return HFI_PORT_BITSTREAM; + case BUF_OUTPUT: + case BUF_DPB: + return HFI_PORT_RAW; + case BUF_PERSIST: + default: + return HFI_PORT_NONE; + } + } else { + switch (buffer_type) { + case BUF_INPUT: + case BUF_VPSS: + return HFI_PORT_RAW; + case BUF_OUTPUT: + case BUF_BIN: + case BUF_COMV: + case BUF_NON_COMV: + case BUF_LINE: + case BUF_SCRATCH_2: + return HFI_PORT_BITSTREAM; + case BUF_ARP: + default: + return HFI_PORT_NONE; + } } } @@ -136,34 +166,77 @@ static int iris_hfi_gen2_session_set_property(struct iris_inst *inst, u32 packet inst_hfi_gen2->packet->size); } -static int iris_hfi_gen2_set_bitstream_resolution(struct iris_inst *inst) +static int iris_hfi_gen2_set_raw_resolution(struct iris_inst *inst, u32 plane) { - struct iris_inst_hfi_gen2 *inst_hfi_gen2 = to_iris_inst_hfi_gen2(inst); - u32 port = iris_hfi_gen2_get_port(V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); u32 resolution = inst->fmt_src->fmt.pix_mp.width << 16 | inst->fmt_src->fmt.pix_mp.height; + u32 port = iris_hfi_gen2_get_port(inst, plane); - inst_hfi_gen2->src_subcr_params.bitstream_resolution = resolution; + return iris_hfi_gen2_session_set_property(inst, + HFI_PROP_RAW_RESOLUTION, + HFI_HOST_FLAGS_NONE, + port, + HFI_PAYLOAD_32_PACKED, + &resolution, + sizeof(u32)); +} + +static int iris_hfi_gen2_set_bitstream_resolution(struct iris_inst *inst, u32 plane) +{ + struct iris_inst_hfi_gen2 *inst_hfi_gen2 = to_iris_inst_hfi_gen2(inst); + u32 port = iris_hfi_gen2_get_port(inst, plane); + enum hfi_packet_payload_info payload_type; + u32 resolution, codec_align; + + if (inst->domain == DECODER) { + resolution = inst->fmt_src->fmt.pix_mp.width << 16 | + inst->fmt_src->fmt.pix_mp.height; + inst_hfi_gen2->src_subcr_params.bitstream_resolution = resolution; + payload_type = HFI_PAYLOAD_U32; + } else { + codec_align = inst->codec == V4L2_PIX_FMT_HEVC ? 32 : 16; + resolution = ALIGN(inst->fmt_dst->fmt.pix_mp.width, codec_align) << 16 | + ALIGN(inst->fmt_dst->fmt.pix_mp.height, codec_align); + inst_hfi_gen2->dst_subcr_params.bitstream_resolution = resolution; + payload_type = HFI_PAYLOAD_32_PACKED; + } return iris_hfi_gen2_session_set_property(inst, HFI_PROP_BITSTREAM_RESOLUTION, HFI_HOST_FLAGS_NONE, port, - HFI_PAYLOAD_U32, + payload_type, &resolution, sizeof(u32)); } -static int iris_hfi_gen2_set_crop_offsets(struct iris_inst *inst) +static int iris_hfi_gen2_set_crop_offsets(struct iris_inst *inst, u32 plane) { - u32 bottom_offset = (inst->fmt_src->fmt.pix_mp.height - inst->crop.height); - u32 right_offset = (inst->fmt_src->fmt.pix_mp.width - inst->crop.width); struct iris_inst_hfi_gen2 *inst_hfi_gen2 = to_iris_inst_hfi_gen2(inst); - u32 port = iris_hfi_gen2_get_port(V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); - u32 left_offset = inst->crop.left; - u32 top_offset = inst->crop.top; + u32 port = iris_hfi_gen2_get_port(inst, plane); + u32 bottom_offset, right_offset; + u32 left_offset, top_offset; u32 payload[2]; + if (inst->domain == DECODER) { + if (V4L2_TYPE_IS_OUTPUT(plane)) { + bottom_offset = (inst->fmt_src->fmt.pix_mp.height - inst->crop.height); + right_offset = (inst->fmt_src->fmt.pix_mp.width - inst->crop.width); + left_offset = inst->crop.left; + top_offset = inst->crop.top; + } else { + bottom_offset = (inst->fmt_dst->fmt.pix_mp.height - inst->compose.height); + right_offset = (inst->fmt_dst->fmt.pix_mp.width - inst->compose.width); + left_offset = inst->compose.left; + top_offset = inst->compose.top; + } + } else { + bottom_offset = (inst->fmt_src->fmt.pix_mp.height - inst->crop.height); + right_offset = (inst->fmt_src->fmt.pix_mp.width - inst->crop.width); + left_offset = inst->crop.left; + top_offset = inst->crop.top; + } + payload[0] = FIELD_PREP(GENMASK(31, 16), left_offset) | top_offset; payload[1] = FIELD_PREP(GENMASK(31, 16), right_offset) | bottom_offset; inst_hfi_gen2->src_subcr_params.crop_offsets[0] = payload[0]; @@ -178,10 +251,10 @@ static int iris_hfi_gen2_set_crop_offsets(struct iris_inst *inst) sizeof(u64)); } -static int iris_hfi_gen2_set_bit_depth(struct iris_inst *inst) +static int iris_hfi_gen2_set_bit_depth(struct iris_inst *inst, u32 plane) { struct iris_inst_hfi_gen2 *inst_hfi_gen2 = to_iris_inst_hfi_gen2(inst); - u32 port = iris_hfi_gen2_get_port(V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); + u32 port = iris_hfi_gen2_get_port(inst, plane); u32 bitdepth = BIT_DEPTH_8; inst_hfi_gen2->src_subcr_params.bit_depth = bitdepth; @@ -195,10 +268,10 @@ static int iris_hfi_gen2_set_bit_depth(struct iris_inst *inst) sizeof(u32)); } -static int iris_hfi_gen2_set_coded_frames(struct iris_inst *inst) +static int iris_hfi_gen2_set_coded_frames(struct iris_inst *inst, u32 plane) { struct iris_inst_hfi_gen2 *inst_hfi_gen2 = to_iris_inst_hfi_gen2(inst); - u32 port = iris_hfi_gen2_get_port(V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); + u32 port = iris_hfi_gen2_get_port(inst, plane); u32 coded_frames = 0; if (inst->fw_caps[CODED_FRAMES].value == CODED_FRAMES_PROGRESSIVE) @@ -214,11 +287,11 @@ static int iris_hfi_gen2_set_coded_frames(struct iris_inst *inst) sizeof(u32)); } -static int iris_hfi_gen2_set_min_output_count(struct iris_inst *inst) +static int iris_hfi_gen2_set_min_output_count(struct iris_inst *inst, u32 plane) { struct iris_inst_hfi_gen2 *inst_hfi_gen2 = to_iris_inst_hfi_gen2(inst); - u32 port = iris_hfi_gen2_get_port(V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); u32 min_output = inst->buffers[BUF_OUTPUT].min_count; + u32 port = iris_hfi_gen2_get_port(inst, plane); inst_hfi_gen2->src_subcr_params.fw_min_count = min_output; @@ -231,10 +304,10 @@ static int iris_hfi_gen2_set_min_output_count(struct iris_inst *inst) sizeof(u32)); } -static int iris_hfi_gen2_set_picture_order_count(struct iris_inst *inst) +static int iris_hfi_gen2_set_picture_order_count(struct iris_inst *inst, u32 plane) { struct iris_inst_hfi_gen2 *inst_hfi_gen2 = to_iris_inst_hfi_gen2(inst); - u32 port = iris_hfi_gen2_get_port(V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); + u32 port = iris_hfi_gen2_get_port(inst, plane); u32 poc = 0; inst_hfi_gen2->src_subcr_params.pic_order_cnt = poc; @@ -248,16 +321,16 @@ static int iris_hfi_gen2_set_picture_order_count(struct iris_inst *inst) sizeof(u32)); } -static int iris_hfi_gen2_set_colorspace(struct iris_inst *inst) +static int iris_hfi_gen2_set_colorspace(struct iris_inst *inst, u32 plane) { struct iris_inst_hfi_gen2 *inst_hfi_gen2 = to_iris_inst_hfi_gen2(inst); - u32 port = iris_hfi_gen2_get_port(V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); struct v4l2_pix_format_mplane *pixmp = &inst->fmt_src->fmt.pix_mp; u32 video_signal_type_present_flag = 0, color_info; u32 matrix_coeff = HFI_MATRIX_COEFF_RESERVED; u32 video_format = UNSPECIFIED_COLOR_FORMAT; u32 full_range = V4L2_QUANTIZATION_DEFAULT; u32 transfer_char = HFI_TRANSFER_RESERVED; + u32 port = iris_hfi_gen2_get_port(inst, plane); u32 colour_description_present_flag = 0; u32 primaries = HFI_PRIMARIES_RESERVED; @@ -291,10 +364,10 @@ static int iris_hfi_gen2_set_colorspace(struct iris_inst *inst) sizeof(u32)); } -static int iris_hfi_gen2_set_profile(struct iris_inst *inst) +static int iris_hfi_gen2_set_profile(struct iris_inst *inst, u32 plane) { struct iris_inst_hfi_gen2 *inst_hfi_gen2 = to_iris_inst_hfi_gen2(inst); - u32 port = iris_hfi_gen2_get_port(V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); + u32 port = iris_hfi_gen2_get_port(inst, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); u32 profile = 0; switch (inst->codec) { @@ -320,10 +393,10 @@ static int iris_hfi_gen2_set_profile(struct iris_inst *inst) sizeof(u32)); } -static int iris_hfi_gen2_set_level(struct iris_inst *inst) +static int iris_hfi_gen2_set_level(struct iris_inst *inst, u32 plane) { struct iris_inst_hfi_gen2 *inst_hfi_gen2 = to_iris_inst_hfi_gen2(inst); - u32 port = iris_hfi_gen2_get_port(V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); + u32 port = iris_hfi_gen2_get_port(inst, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); u32 level = 0; switch (inst->codec) { @@ -349,33 +422,47 @@ static int iris_hfi_gen2_set_level(struct iris_inst *inst) sizeof(u32)); } -static int iris_hfi_gen2_set_colorformat(struct iris_inst *inst) +static int iris_hfi_gen2_set_colorformat(struct iris_inst *inst, u32 plane) { - u32 port = iris_hfi_gen2_get_port(V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE); + u32 port = iris_hfi_gen2_get_port(inst, plane); u32 hfi_colorformat, pixelformat; - pixelformat = inst->fmt_dst->fmt.pix_mp.pixelformat; - hfi_colorformat = pixelformat == V4L2_PIX_FMT_NV12 ? HFI_COLOR_FMT_NV12 : 0; + if (inst->domain == DECODER) { + pixelformat = inst->fmt_dst->fmt.pix_mp.pixelformat; + hfi_colorformat = pixelformat == V4L2_PIX_FMT_NV12 ? HFI_COLOR_FMT_NV12 : 0; + } else { + pixelformat = inst->fmt_src->fmt.pix_mp.pixelformat; + hfi_colorformat = pixelformat == V4L2_PIX_FMT_NV12 ? HFI_COLOR_FMT_NV12 : 0; + } return iris_hfi_gen2_session_set_property(inst, HFI_PROP_COLOR_FORMAT, HFI_HOST_FLAGS_NONE, port, - HFI_PAYLOAD_U32, + HFI_PAYLOAD_U32_ENUM, &hfi_colorformat, sizeof(u32)); } -static int iris_hfi_gen2_set_linear_stride_scanline(struct iris_inst *inst) +static int iris_hfi_gen2_set_linear_stride_scanline(struct iris_inst *inst, u32 plane) { - u32 port = iris_hfi_gen2_get_port(V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE); - u32 pixelformat = inst->fmt_dst->fmt.pix_mp.pixelformat; - u32 scanline_y = inst->fmt_dst->fmt.pix_mp.height; - u32 stride_y = inst->fmt_dst->fmt.pix_mp.width; - u32 scanline_uv = scanline_y / 2; - u32 stride_uv = stride_y; + u32 pixelformat, stride_y, stride_uv, scanline_y, scanline_uv; + u32 port = iris_hfi_gen2_get_port(inst, plane); u32 payload[2]; + if (inst->domain == DECODER) { + pixelformat = inst->fmt_dst->fmt.pix_mp.pixelformat; + stride_y = inst->fmt_dst->fmt.pix_mp.width; + scanline_y = inst->fmt_dst->fmt.pix_mp.height; + } else { + pixelformat = inst->fmt_src->fmt.pix_mp.pixelformat; + stride_y = ALIGN(inst->fmt_src->fmt.pix_mp.width, 128); + scanline_y = ALIGN(inst->fmt_src->fmt.pix_mp.height, 32); + } + + stride_uv = stride_y; + scanline_uv = scanline_y / 2; + if (pixelformat != V4L2_PIX_FMT_NV12) return 0; @@ -386,15 +473,15 @@ static int iris_hfi_gen2_set_linear_stride_scanline(struct iris_inst *inst) HFI_PROP_LINEAR_STRIDE_SCANLINE, HFI_HOST_FLAGS_NONE, port, - HFI_PAYLOAD_U64, + HFI_PAYLOAD_64_PACKED, &payload, sizeof(u64)); } -static int iris_hfi_gen2_set_tier(struct iris_inst *inst) +static int iris_hfi_gen2_set_tier(struct iris_inst *inst, u32 plane) { struct iris_inst_hfi_gen2 *inst_hfi_gen2 = to_iris_inst_hfi_gen2(inst); - u32 port = iris_hfi_gen2_get_port(V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); + u32 port = iris_hfi_gen2_get_port(inst, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); u32 tier = inst->fw_caps[TIER].value; inst_hfi_gen2->src_subcr_params.tier = tier; @@ -408,14 +495,29 @@ static int iris_hfi_gen2_set_tier(struct iris_inst *inst) sizeof(u32)); } +static int iris_hfi_gen2_set_frame_rate(struct iris_inst *inst, u32 plane) +{ + u32 port = iris_hfi_gen2_get_port(inst, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE); + u32 frame_rate = inst->frame_rate << 16; + + return iris_hfi_gen2_session_set_property(inst, + HFI_PROP_FRAME_RATE, + HFI_HOST_FLAGS_NONE, + port, + HFI_PAYLOAD_Q16, + &frame_rate, + sizeof(u32)); +} + static int iris_hfi_gen2_session_set_config_params(struct iris_inst *inst, u32 plane) { - struct iris_core *core = inst->core; + const struct iris_platform_data *pdata = inst->core->iris_platform_data; u32 config_params_size = 0, i, j; const u32 *config_params = NULL; int ret; static const struct iris_hfi_prop_type_handle prop_type_handle_arr[] = { + {HFI_PROP_RAW_RESOLUTION, iris_hfi_gen2_set_raw_resolution }, {HFI_PROP_BITSTREAM_RESOLUTION, iris_hfi_gen2_set_bitstream_resolution }, {HFI_PROP_CROP_OFFSETS, iris_hfi_gen2_set_crop_offsets }, {HFI_PROP_CODED_FRAMES, iris_hfi_gen2_set_coded_frames }, @@ -428,29 +530,35 @@ static int iris_hfi_gen2_session_set_config_params(struct iris_inst *inst, u32 p {HFI_PROP_COLOR_FORMAT, iris_hfi_gen2_set_colorformat }, {HFI_PROP_LINEAR_STRIDE_SCANLINE, iris_hfi_gen2_set_linear_stride_scanline }, {HFI_PROP_TIER, iris_hfi_gen2_set_tier }, + {HFI_PROP_FRAME_RATE, iris_hfi_gen2_set_frame_rate }, }; - if (V4L2_TYPE_IS_OUTPUT(plane)) { - switch (inst->codec) { - case V4L2_PIX_FMT_H264: - config_params = core->iris_platform_data->input_config_params_default; - config_params_size = - core->iris_platform_data->input_config_params_default_size; - break; - case V4L2_PIX_FMT_HEVC: - config_params = core->iris_platform_data->input_config_params_hevc; - config_params_size = - core->iris_platform_data->input_config_params_hevc_size; - break; - case V4L2_PIX_FMT_VP9: - config_params = core->iris_platform_data->input_config_params_vp9; - config_params_size = - core->iris_platform_data->input_config_params_vp9_size; - break; + if (inst->domain == DECODER) { + if (V4L2_TYPE_IS_OUTPUT(plane)) { + if (inst->codec == V4L2_PIX_FMT_H264) { + config_params = pdata->dec_input_config_params_default; + config_params_size = pdata->dec_input_config_params_default_size; + } else if (inst->codec == V4L2_PIX_FMT_HEVC) { + config_params = pdata->dec_input_config_params_hevc; + config_params_size = pdata->dec_input_config_params_hevc_size; + } else if (inst->codec == V4L2_PIX_FMT_VP9) { + config_params = pdata->dec_input_config_params_vp9; + config_params_size = pdata->dec_input_config_params_vp9_size; + } else { + return -EINVAL; + } + } else { + config_params = pdata->dec_output_config_params; + config_params_size = pdata->dec_output_config_params_size; } } else { - config_params = core->iris_platform_data->output_config_params; - config_params_size = core->iris_platform_data->output_config_params_size; + if (V4L2_TYPE_IS_OUTPUT(plane)) { + config_params = pdata->enc_input_config_params; + config_params_size = pdata->enc_input_config_params_size; + } else { + config_params = pdata->enc_output_config_params; + config_params_size = pdata->enc_output_config_params_size; + } } if (!config_params || !config_params_size) @@ -459,7 +567,7 @@ static int iris_hfi_gen2_session_set_config_params(struct iris_inst *inst, u32 p for (i = 0; i < config_params_size; i++) { for (j = 0; j < ARRAY_SIZE(prop_type_handle_arr); j++) { if (prop_type_handle_arr[j].type == config_params[i]) { - ret = prop_type_handle_arr[j].handle(inst); + ret = prop_type_handle_arr[j].handle(inst, plane); if (ret) return ret; break; @@ -477,14 +585,19 @@ static int iris_hfi_gen2_session_set_codec(struct iris_inst *inst) switch (inst->codec) { case V4L2_PIX_FMT_H264: - codec = HFI_CODEC_DECODE_AVC; + if (inst->domain == ENCODER) + codec = HFI_CODEC_ENCODE_AVC; + else + codec = HFI_CODEC_DECODE_AVC; break; case V4L2_PIX_FMT_HEVC: - codec = HFI_CODEC_DECODE_HEVC; + if (inst->domain == ENCODER) + codec = HFI_CODEC_ENCODE_HEVC; + else + codec = HFI_CODEC_DECODE_HEVC; break; case V4L2_PIX_FMT_VP9: codec = HFI_CODEC_DECODE_VP9; - break; } iris_hfi_gen2_packet_session_property(inst, @@ -550,9 +663,11 @@ static int iris_hfi_gen2_session_open(struct iris_inst *inst) if (ret) goto fail_free_packet; - ret = iris_hfi_gen2_session_set_default_header(inst); - if (ret) - goto fail_free_packet; + if (inst->domain == DECODER) { + ret = iris_hfi_gen2_session_set_default_header(inst); + if (ret) + goto fail_free_packet; + } return 0; @@ -601,7 +716,7 @@ static int iris_hfi_gen2_session_subscribe_mode(struct iris_inst *inst, cmd, (HFI_HOST_FLAGS_RESPONSE_REQUIRED | HFI_HOST_FLAGS_INTR_REQUIRED), - iris_hfi_gen2_get_port(plane), + iris_hfi_gen2_get_port(inst, plane), inst->session_id, payload_type, payload, @@ -623,6 +738,9 @@ static int iris_hfi_gen2_subscribe_change_param(struct iris_inst *inst, u32 plan u32 hfi_port = 0, i; int ret; + if (inst->domain == ENCODER) + return 0; + if ((V4L2_TYPE_IS_OUTPUT(plane) && inst_hfi_gen2->ipsc_properties_set) || (V4L2_TYPE_IS_CAPTURE(plane) && inst_hfi_gen2->opsc_properties_set)) { dev_err(core->dev, "invalid plane\n"); @@ -631,19 +749,19 @@ static int iris_hfi_gen2_subscribe_change_param(struct iris_inst *inst, u32 plan switch (inst->codec) { case V4L2_PIX_FMT_H264: - change_param = core->iris_platform_data->input_config_params_default; + change_param = core->iris_platform_data->dec_input_config_params_default; change_param_size = - core->iris_platform_data->input_config_params_default_size; + core->iris_platform_data->dec_input_config_params_default_size; break; case V4L2_PIX_FMT_HEVC: - change_param = core->iris_platform_data->input_config_params_hevc; + change_param = core->iris_platform_data->dec_input_config_params_hevc; change_param_size = - core->iris_platform_data->input_config_params_hevc_size; + core->iris_platform_data->dec_input_config_params_hevc_size; break; case V4L2_PIX_FMT_VP9: - change_param = core->iris_platform_data->input_config_params_vp9; + change_param = core->iris_platform_data->dec_input_config_params_vp9; change_param_size = - core->iris_platform_data->input_config_params_vp9_size; + core->iris_platform_data->dec_input_config_params_vp9_size; break; } @@ -664,7 +782,7 @@ static int iris_hfi_gen2_subscribe_change_param(struct iris_inst *inst, u32 plan if (V4L2_TYPE_IS_OUTPUT(plane)) { inst_hfi_gen2->ipsc_properties_set = true; } else { - hfi_port = iris_hfi_gen2_get_port(V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE); + hfi_port = iris_hfi_gen2_get_port(inst, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE); memcpy(&inst_hfi_gen2->dst_subcr_params, &inst_hfi_gen2->src_subcr_params, sizeof(inst_hfi_gen2->src_subcr_params)); @@ -759,6 +877,9 @@ static int iris_hfi_gen2_subscribe_property(struct iris_inst *inst, u32 plane) payload[0] = HFI_MODE_PROPERTY; + if (inst->domain == ENCODER) + return 0; + if (V4L2_TYPE_IS_OUTPUT(plane)) { subscribe_prop_size = core->iris_platform_data->dec_input_prop_size; subcribe_prop = core->iris_platform_data->dec_input_prop; @@ -810,7 +931,7 @@ static int iris_hfi_gen2_session_start(struct iris_inst *inst, u32 plane) HFI_CMD_START, (HFI_HOST_FLAGS_RESPONSE_REQUIRED | HFI_HOST_FLAGS_INTR_REQUIRED), - iris_hfi_gen2_get_port(plane), + iris_hfi_gen2_get_port(inst, plane), inst->session_id, HFI_PAYLOAD_NONE, NULL, @@ -832,7 +953,7 @@ static int iris_hfi_gen2_session_stop(struct iris_inst *inst, u32 plane) (HFI_HOST_FLAGS_RESPONSE_REQUIRED | HFI_HOST_FLAGS_INTR_REQUIRED | HFI_HOST_FLAGS_NON_DISCARDABLE), - iris_hfi_gen2_get_port(plane), + iris_hfi_gen2_get_port(inst, plane), inst->session_id, HFI_PAYLOAD_NONE, NULL, @@ -854,7 +975,7 @@ static int iris_hfi_gen2_session_pause(struct iris_inst *inst, u32 plane) HFI_CMD_PAUSE, (HFI_HOST_FLAGS_RESPONSE_REQUIRED | HFI_HOST_FLAGS_INTR_REQUIRED), - iris_hfi_gen2_get_port(plane), + iris_hfi_gen2_get_port(inst, plane), inst->session_id, HFI_PAYLOAD_NONE, NULL, @@ -873,7 +994,7 @@ static int iris_hfi_gen2_session_resume_drc(struct iris_inst *inst, u32 plane) HFI_CMD_RESUME, (HFI_HOST_FLAGS_RESPONSE_REQUIRED | HFI_HOST_FLAGS_INTR_REQUIRED), - iris_hfi_gen2_get_port(plane), + iris_hfi_gen2_get_port(inst, plane), inst->session_id, HFI_PAYLOAD_U32, &payload, @@ -892,7 +1013,7 @@ static int iris_hfi_gen2_session_resume_drain(struct iris_inst *inst, u32 plane) HFI_CMD_RESUME, (HFI_HOST_FLAGS_RESPONSE_REQUIRED | HFI_HOST_FLAGS_INTR_REQUIRED), - iris_hfi_gen2_get_port(plane), + iris_hfi_gen2_get_port(inst, plane), inst->session_id, HFI_PAYLOAD_U32, &payload, @@ -914,7 +1035,7 @@ static int iris_hfi_gen2_session_drain(struct iris_inst *inst, u32 plane) (HFI_HOST_FLAGS_RESPONSE_REQUIRED | HFI_HOST_FLAGS_INTR_REQUIRED | HFI_HOST_FLAGS_NON_DISCARDABLE), - iris_hfi_gen2_get_port(plane), + iris_hfi_gen2_get_port(inst, plane), inst->session_id, HFI_PAYLOAD_NONE, NULL, @@ -924,13 +1045,19 @@ static int iris_hfi_gen2_session_drain(struct iris_inst *inst, u32 plane) inst_hfi_gen2->packet->size); } -static u32 iris_hfi_gen2_buf_type_from_driver(enum iris_buffer_type buffer_type) +static u32 iris_hfi_gen2_buf_type_from_driver(u32 domain, enum iris_buffer_type buffer_type) { switch (buffer_type) { case BUF_INPUT: - return HFI_BUFFER_BITSTREAM; + if (domain == DECODER) + return HFI_BUFFER_BITSTREAM; + else + return HFI_BUFFER_RAW; case BUF_OUTPUT: - return HFI_BUFFER_RAW; + if (domain == DECODER) + return HFI_BUFFER_RAW; + else + return HFI_BUFFER_BITSTREAM; case BUF_BIN: return HFI_BUFFER_BIN; case BUF_COMV: @@ -940,9 +1067,14 @@ static u32 iris_hfi_gen2_buf_type_from_driver(enum iris_buffer_type buffer_type) case BUF_LINE: return HFI_BUFFER_LINE; case BUF_DPB: + case BUF_SCRATCH_2: return HFI_BUFFER_DPB; case BUF_PERSIST: return HFI_BUFFER_PERSIST; + case BUF_ARP: + return HFI_BUFFER_ARP; + case BUF_VPSS: + return HFI_BUFFER_VPSS; default: return 0; } @@ -965,16 +1097,17 @@ static int iris_set_num_comv(struct iris_inst *inst) &num_comv, sizeof(u32)); } -static void iris_hfi_gen2_get_buffer(struct iris_buffer *buffer, struct iris_hfi_buffer *buf) +static void iris_hfi_gen2_get_buffer(u32 domain, struct iris_buffer *buffer, + struct iris_hfi_buffer *buf) { memset(buf, 0, sizeof(*buf)); - buf->type = iris_hfi_gen2_buf_type_from_driver(buffer->type); + buf->type = iris_hfi_gen2_buf_type_from_driver(domain, buffer->type); buf->index = buffer->index; buf->base_address = buffer->device_addr; buf->addr_offset = 0; buf->buffer_size = buffer->buffer_size; - if (buffer->type == BUF_INPUT) + if (domain == DECODER && buffer->type == BUF_INPUT) buf->buffer_size = ALIGN(buffer->buffer_size, 256); buf->data_offset = buffer->data_offset; buf->data_size = buffer->data_size; @@ -991,14 +1124,14 @@ static int iris_hfi_gen2_session_queue_buffer(struct iris_inst *inst, struct iri u32 port; int ret; - iris_hfi_gen2_get_buffer(buffer, &hfi_buffer); + iris_hfi_gen2_get_buffer(inst->domain, buffer, &hfi_buffer); if (buffer->type == BUF_COMV) { ret = iris_set_num_comv(inst); if (ret) return ret; } - port = iris_hfi_gen2_get_port_from_buf_type(buffer->type); + port = iris_hfi_gen2_get_port_from_buf_type(inst, buffer->type); iris_hfi_gen2_packet_session_command(inst, HFI_CMD_BUFFER, HFI_HOST_FLAGS_INTR_REQUIRED, @@ -1018,9 +1151,9 @@ static int iris_hfi_gen2_session_release_buffer(struct iris_inst *inst, struct i struct iris_hfi_buffer hfi_buffer; u32 port; - iris_hfi_gen2_get_buffer(buffer, &hfi_buffer); + iris_hfi_gen2_get_buffer(inst->domain, buffer, &hfi_buffer); hfi_buffer.flags |= HFI_BUF_HOST_FLAG_RELEASE; - port = iris_hfi_gen2_get_port_from_buf_type(buffer->type); + port = iris_hfi_gen2_get_port_from_buf_type(inst, buffer->type); iris_hfi_gen2_packet_session_command(inst, HFI_CMD_BUFFER, diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen2_defines.h b/drivers/media/platform/qcom/iris/iris_hfi_gen2_defines.h index 5f13dc11bea5..aa1f795f5626 100644 --- a/drivers/media/platform/qcom/iris/iris_hfi_gen2_defines.h +++ b/drivers/media/platform/qcom/iris/iris_hfi_gen2_defines.h @@ -49,18 +49,48 @@ #define HFI_PROP_TIER 0x03000109 #define HFI_PROP_STAGE 0x0300010a #define HFI_PROP_PIPE 0x0300010b +#define HFI_PROP_FRAME_RATE 0x0300010c #define HFI_PROP_LUMA_CHROMA_BIT_DEPTH 0x0300010f #define HFI_PROP_CODED_FRAMES 0x03000120 #define HFI_PROP_CABAC_SESSION 0x03000121 #define HFI_PROP_BUFFER_HOST_MAX_COUNT 0x03000123 #define HFI_PROP_BUFFER_FW_MIN_OUTPUT_COUNT 0x03000124 #define HFI_PROP_PIC_ORDER_CNT_TYPE 0x03000128 + +enum hfi_rate_control { + HFI_RC_VBR_CFR = 0x00000000, + HFI_RC_CBR_CFR = 0x00000001, + HFI_RC_CQ = 0x00000002, + HFI_RC_OFF = 0x00000003, + HFI_RC_CBR_VFR = 0x00000004, + HFI_RC_LOSSLESS = 0x00000005, +}; + +#define HFI_PROP_RATE_CONTROL 0x0300012a +#define HFI_PROP_QP_PACKED 0x0300012e +#define HFI_PROP_MIN_QP_PACKED 0x0300012f +#define HFI_PROP_MAX_QP_PACKED 0x03000130 +#define HFI_PROP_TOTAL_BITRATE 0x0300013b +#define HFI_PROP_MAX_GOP_FRAMES 0x03000146 +#define HFI_PROP_MAX_B_FRAMES 0x03000147 #define HFI_PROP_QUALITY_MODE 0x03000148 + +enum hfi_seq_header_mode { + HFI_SEQ_HEADER_SEPERATE_FRAME = 0x00000001, + HFI_SEQ_HEADER_JOINED_WITH_1ST_FRAME = 0x00000002, + HFI_SEQ_HEADER_PREFIX_WITH_SYNC_FRAME = 0x00000004, + HFI_SEQ_HEADER_METADATA = 0x00000008, +}; + +#define HFI_PROP_SEQ_HEADER_MODE 0x03000149 #define HFI_PROP_SIGNAL_COLOR_INFO 0x03000155 #define HFI_PROP_PICTURE_TYPE 0x03000162 #define HFI_PROP_DEC_DEFAULT_HEADER 0x03000168 #define HFI_PROP_DEC_START_FROM_RAP_FRAME 0x03000169 #define HFI_PROP_NO_OUTPUT 0x0300016a +#define HFI_PROP_BUFFER_MARK 0x0300016c +#define HFI_PROP_RAW_RESOLUTION 0x03000178 +#define HFI_PROP_TOTAL_PEAK_BITRATE 0x0300017C #define HFI_PROP_COMV_BUFFER_COUNT 0x03000193 #define HFI_PROP_END 0x03FFFFFF @@ -111,13 +141,13 @@ enum hfi_codec_type { }; enum hfi_picture_type { - HFI_PICTURE_IDR = 0x00000001, - HFI_PICTURE_P = 0x00000002, - HFI_PICTURE_B = 0x00000004, - HFI_PICTURE_I = 0x00000008, - HFI_PICTURE_CRA = 0x00000010, - HFI_PICTURE_BLA = 0x00000020, - HFI_PICTURE_NOSHOW = 0x00000040, + HFI_GEN2_PICTURE_IDR = 0x00000001, + HFI_GEN2_PICTURE_P = 0x00000002, + HFI_GEN2_PICTURE_B = 0x00000004, + HFI_GEN2_PICTURE_I = 0x00000008, + HFI_GEN2_PICTURE_CRA = 0x00000010, + HFI_GEN2_PICTURE_BLA = 0x00000020, + HFI_GEN2_PICTURE_NOSHOW = 0x00000040, }; enum hfi_buffer_type { diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen2_response.c b/drivers/media/platform/qcom/iris/iris_hfi_gen2_response.c index a8c30fc5c0d0..2f1f118eae4f 100644 --- a/drivers/media/platform/qcom/iris/iris_hfi_gen2_response.c +++ b/drivers/media/platform/qcom/iris/iris_hfi_gen2_response.c @@ -29,7 +29,8 @@ struct iris_hfi_gen2_packet_handle { int (*handle)(struct iris_inst *inst, struct iris_hfi_packet *pkt); }; -static u32 iris_hfi_gen2_buf_type_to_driver(enum hfi_buffer_type buf_type) +static u32 iris_hfi_gen2_buf_type_to_driver(struct iris_inst *inst, + enum hfi_buffer_type buf_type) { switch (buf_type) { case HFI_BUFFER_BITSTREAM: @@ -47,7 +48,10 @@ static u32 iris_hfi_gen2_buf_type_to_driver(enum hfi_buffer_type buf_type) case HFI_BUFFER_LINE: return BUF_LINE; case HFI_BUFFER_DPB: - return BUF_DPB; + if (inst->domain == DECODER) + return BUF_DPB; + else + return BUF_SCRATCH_2; case HFI_BUFFER_PERSIST: return BUF_PERSIST; default: @@ -87,17 +91,18 @@ static bool iris_hfi_gen2_is_valid_hfi_port(u32 port, u32 buffer_type) static int iris_hfi_gen2_get_driver_buffer_flags(struct iris_inst *inst, u32 hfi_flags) { - u32 keyframe = HFI_PICTURE_IDR | HFI_PICTURE_I | HFI_PICTURE_CRA | HFI_PICTURE_BLA; struct iris_inst_hfi_gen2 *inst_hfi_gen2 = to_iris_inst_hfi_gen2(inst); + u32 keyframe = HFI_GEN2_PICTURE_IDR | HFI_GEN2_PICTURE_I | + HFI_GEN2_PICTURE_CRA | HFI_GEN2_PICTURE_BLA; u32 driver_flags = 0; - if (inst_hfi_gen2->hfi_frame_info.picture_type & HFI_PICTURE_NOSHOW) + if (inst_hfi_gen2->hfi_frame_info.picture_type & HFI_GEN2_PICTURE_NOSHOW) driver_flags |= V4L2_BUF_FLAG_ERROR; else if (inst_hfi_gen2->hfi_frame_info.picture_type & keyframe) driver_flags |= V4L2_BUF_FLAG_KEYFRAME; - else if (inst_hfi_gen2->hfi_frame_info.picture_type & HFI_PICTURE_P) + else if (inst_hfi_gen2->hfi_frame_info.picture_type & HFI_GEN2_PICTURE_P) driver_flags |= V4L2_BUF_FLAG_PFRAME; - else if (inst_hfi_gen2->hfi_frame_info.picture_type & HFI_PICTURE_B) + else if (inst_hfi_gen2->hfi_frame_info.picture_type & HFI_GEN2_PICTURE_B) driver_flags |= V4L2_BUF_FLAG_BFRAME; if (inst_hfi_gen2->hfi_frame_info.data_corrupt || inst_hfi_gen2->hfi_frame_info.overflow) @@ -420,11 +425,10 @@ static void iris_hfi_gen2_handle_dequeue_buffers(struct iris_inst *inst) static int iris_hfi_gen2_handle_release_internal_buffer(struct iris_inst *inst, struct iris_hfi_buffer *buffer) { - u32 buf_type = iris_hfi_gen2_buf_type_to_driver(buffer->type); + u32 buf_type = iris_hfi_gen2_buf_type_to_driver(inst, buffer->type); struct iris_buffers *buffers = &inst->buffers[buf_type]; struct iris_buffer *buf, *iter; bool found = false; - int ret = 0; list_for_each_entry(iter, &buffers->list, list) { if (iter->device_addr == buffer->base_address) { @@ -437,10 +441,8 @@ static int iris_hfi_gen2_handle_release_internal_buffer(struct iris_inst *inst, return -EINVAL; buf->attr &= ~BUF_ATTR_QUEUED; - if (buf->attr & BUF_ATTR_PENDING_RELEASE) - ret = iris_destroy_internal_buffer(inst, buf); - return ret; + return iris_destroy_internal_buffer(inst, buf); } static int iris_hfi_gen2_handle_session_stop(struct iris_inst *inst, @@ -478,12 +480,22 @@ static int iris_hfi_gen2_handle_session_buffer(struct iris_inst *inst, if (!iris_hfi_gen2_is_valid_hfi_port(pkt->port, buffer->type)) return 0; - if (buffer->type == HFI_BUFFER_BITSTREAM) - return iris_hfi_gen2_handle_input_buffer(inst, buffer); - else if (buffer->type == HFI_BUFFER_RAW) - return iris_hfi_gen2_handle_output_buffer(inst, buffer); - else - return iris_hfi_gen2_handle_release_internal_buffer(inst, buffer); + if (inst->domain == DECODER) { + if (buffer->type == HFI_BUFFER_BITSTREAM) + return iris_hfi_gen2_handle_input_buffer(inst, buffer); + else if (buffer->type == HFI_BUFFER_RAW) + return iris_hfi_gen2_handle_output_buffer(inst, buffer); + else + return iris_hfi_gen2_handle_release_internal_buffer(inst, buffer); + } else { + if (buffer->type == HFI_BUFFER_RAW) + return iris_hfi_gen2_handle_input_buffer(inst, buffer); + else if (buffer->type == HFI_BUFFER_BITSTREAM) + return iris_hfi_gen2_handle_output_buffer(inst, buffer); + else + return iris_hfi_gen2_handle_release_internal_buffer(inst, buffer); + } + return 0; } static int iris_hfi_gen2_handle_session_drain(struct iris_inst *inst, diff --git a/drivers/media/platform/qcom/iris/iris_instance.h b/drivers/media/platform/qcom/iris/iris_instance.h index 0e1f5799b72d..5982d7adefea 100644 --- a/drivers/media/platform/qcom/iris/iris_instance.h +++ b/drivers/media/platform/qcom/iris/iris_instance.h @@ -12,6 +12,20 @@ #include "iris_core.h" #include "iris_utils.h" +#define DEFAULT_WIDTH 320 +#define DEFAULT_HEIGHT 240 + +enum iris_fmt_type { + IRIS_FMT_H264, + IRIS_FMT_HEVC, + IRIS_FMT_VP9, +}; + +struct iris_fmt { + u32 pixfmt; + u32 type; +}; + /** * struct iris_inst - holds per video instance parameters * @@ -24,7 +38,9 @@ * @fmt_src: structure of v4l2_format for source * @fmt_dst: structure of v4l2_format for destination * @ctrl_handler: reference of v4l2 ctrl handler + * @domain: domain type: encoder or decoder * @crop: structure of crop info + * @compose: structure of compose info * @completion: structure of signal completions * @flush_completion: structure of signal completions for flush cmd * @flush_responses_pending: counter to track number of pending flush responses @@ -45,6 +61,9 @@ * @metadata_idx: index for metadata buffer * @codec: codec type * @last_buffer_dequeued: a flag to indicate that last buffer is sent by driver + * @frame_rate: frame rate of current instance + * @operating_rate: operating rate of current instance + * @hfi_rc_type: rate control type */ struct iris_inst { @@ -57,7 +76,9 @@ struct iris_inst { struct v4l2_format *fmt_src; struct v4l2_format *fmt_dst; struct v4l2_ctrl_handler ctrl_handler; + enum domain_type domain; struct iris_hfi_rect_desc crop; + struct iris_hfi_rect_desc compose; struct completion completion; struct completion flush_completion; u32 flush_responses_pending; @@ -78,6 +99,9 @@ struct iris_inst { u32 metadata_idx; u32 codec; bool last_buffer_dequeued; + u32 frame_rate; + u32 operating_rate; + u32 hfi_rc_type; }; #endif diff --git a/drivers/media/platform/qcom/iris/iris_platform_common.h b/drivers/media/platform/qcom/iris/iris_platform_common.h index adafdce8a856..58d05e0a112e 100644 --- a/drivers/media/platform/qcom/iris/iris_platform_common.h +++ b/drivers/media/platform/qcom/iris/iris_platform_common.h @@ -7,6 +7,7 @@ #define __IRIS_PLATFORM_COMMON_H__ #include <linux/bits.h> +#include "iris_buffer.h" struct iris_core; struct iris_inst; @@ -21,7 +22,13 @@ struct iris_inst; #define DEFAULT_MAX_HOST_BUF_COUNT 64 #define DEFAULT_MAX_HOST_BURST_BUF_COUNT 256 #define DEFAULT_FPS 30 -#define NUM_MBS_8K ((8192 * 4352) / 256) +#define MAXIMUM_FPS 480 +#define NUM_MBS_8K ((8192 * 4352) / 256) +#define MIN_QP_8BIT 1 +#define MAX_QP 51 +#define MAX_QP_HEVC 63 +#define DEFAULT_QP 20 +#define BITRATE_DEFAULT 20000000 enum stage_type { STAGE_1 = 1, @@ -38,11 +45,15 @@ extern struct iris_platform_data qcs8300_data; extern struct iris_platform_data sm8250_data; extern struct iris_platform_data sm8550_data; extern struct iris_platform_data sm8650_data; +extern struct iris_platform_data sm8750_data; enum platform_clk_type { - IRIS_AXI_CLK, + IRIS_AXI_CLK, /* AXI0 in case of platforms with multiple AXI clocks */ IRIS_CTRL_CLK, IRIS_HW_CLK, + IRIS_AXI1_CLK, + IRIS_CTRL_FREERUN_CLK, + IRIS_HW_FREERUN_CLK, }; struct platform_clk_data { @@ -78,6 +89,8 @@ struct platform_inst_caps { u32 mb_cycles_fw; u32 mb_cycles_fw_vpp; u32 num_comv; + u32 max_frame_rate; + u32 max_operating_rate; }; enum platform_inst_fw_cap_type { @@ -88,6 +101,7 @@ enum platform_inst_fw_cap_type { LEVEL_HEVC, LEVEL_VP9, INPUT_BUF_HOST_MAX_COUNT, + OUTPUT_BUF_HOST_MAX_COUNT, STAGE, PIPE, POC, @@ -95,6 +109,37 @@ enum platform_inst_fw_cap_type { BIT_DEPTH, RAP_FRAME, TIER, + HEADER_MODE, + PREPEND_SPSPPS_TO_IDR, + BITRATE, + BITRATE_PEAK, + BITRATE_MODE, + FRAME_SKIP_MODE, + FRAME_RC_ENABLE, + GOP_SIZE, + ENTROPY_MODE, + MIN_FRAME_QP_H264, + MIN_FRAME_QP_HEVC, + MAX_FRAME_QP_H264, + MAX_FRAME_QP_HEVC, + I_FRAME_MIN_QP_H264, + I_FRAME_MIN_QP_HEVC, + P_FRAME_MIN_QP_H264, + P_FRAME_MIN_QP_HEVC, + B_FRAME_MIN_QP_H264, + B_FRAME_MIN_QP_HEVC, + I_FRAME_MAX_QP_H264, + I_FRAME_MAX_QP_HEVC, + P_FRAME_MAX_QP_H264, + P_FRAME_MAX_QP_HEVC, + B_FRAME_MAX_QP_H264, + B_FRAME_MAX_QP_HEVC, + I_FRAME_QP_H264, + I_FRAME_QP_HEVC, + P_FRAME_QP_H264, + P_FRAME_QP_HEVC, + B_FRAME_QP_H264, + B_FRAME_QP_HEVC, INST_FW_CAP_MAX, }; @@ -149,6 +194,7 @@ struct iris_platform_data { void (*init_hfi_command_ops)(struct iris_core *core); void (*init_hfi_response_ops)(struct iris_core *core); struct iris_inst *(*get_instance)(void); + u32 (*get_vpu_buffer_size)(struct iris_inst *inst, enum iris_buffer_type buffer_type); const struct vpu_ops *vpu_ops; void (*set_preset_registers)(struct iris_core *core); const struct icc_info *icc_tbl; @@ -169,8 +215,10 @@ struct iris_platform_data { const char *fwname; u32 pas_id; struct platform_inst_caps *inst_caps; - struct platform_inst_fw_cap *inst_fw_caps; - u32 inst_fw_caps_size; + struct platform_inst_fw_cap *inst_fw_caps_dec; + u32 inst_fw_caps_dec_size; + struct platform_inst_fw_cap *inst_fw_caps_enc; + u32 inst_fw_caps_enc_size; struct tz_cp_config *tz_cp_config_data; u32 core_arch; u32 hw_response_timeout; @@ -179,14 +227,20 @@ struct iris_platform_data { u32 max_session_count; /* max number of macroblocks per frame supported */ u32 max_core_mbpf; - const u32 *input_config_params_default; - unsigned int input_config_params_default_size; - const u32 *input_config_params_hevc; - unsigned int input_config_params_hevc_size; - const u32 *input_config_params_vp9; - unsigned int input_config_params_vp9_size; - const u32 *output_config_params; - unsigned int output_config_params_size; + /* max number of macroblocks per second supported */ + u32 max_core_mbps; + const u32 *dec_input_config_params_default; + unsigned int dec_input_config_params_default_size; + const u32 *dec_input_config_params_hevc; + unsigned int dec_input_config_params_hevc_size; + const u32 *dec_input_config_params_vp9; + unsigned int dec_input_config_params_vp9_size; + const u32 *dec_output_config_params; + unsigned int dec_output_config_params_size; + const u32 *enc_input_config_params; + unsigned int enc_input_config_params_size; + const u32 *enc_output_config_params; + unsigned int enc_output_config_params_size; const u32 *dec_input_prop; unsigned int dec_input_prop_size; const u32 *dec_output_prop_avc; @@ -199,6 +253,10 @@ struct iris_platform_data { unsigned int dec_ip_int_buf_tbl_size; const u32 *dec_op_int_buf_tbl; unsigned int dec_op_int_buf_tbl_size; + const u32 *enc_ip_int_buf_tbl; + unsigned int enc_ip_int_buf_tbl_size; + const u32 *enc_op_int_buf_tbl; + unsigned int enc_op_int_buf_tbl_size; }; #endif diff --git a/drivers/media/platform/qcom/iris/iris_platform_gen2.c b/drivers/media/platform/qcom/iris/iris_platform_gen2.c index d3026b2bcb70..36d69cc73986 100644 --- a/drivers/media/platform/qcom/iris/iris_platform_gen2.c +++ b/drivers/media/platform/qcom/iris/iris_platform_gen2.c @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) 2025 Linaro Ltd */ #include "iris_core.h" @@ -8,14 +9,17 @@ #include "iris_hfi_gen2.h" #include "iris_hfi_gen2_defines.h" #include "iris_platform_common.h" +#include "iris_vpu_buffer.h" #include "iris_vpu_common.h" #include "iris_platform_qcs8300.h" #include "iris_platform_sm8650.h" +#include "iris_platform_sm8750.h" #define VIDEO_ARCH_LX 1 +#define BITRATE_MAX 245000000 -static struct platform_inst_fw_cap inst_fw_cap_sm8550[] = { +static struct platform_inst_fw_cap inst_fw_cap_sm8550_dec[] = { { .cap_id = PROFILE_H264, .min = V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE, @@ -199,6 +203,393 @@ static struct platform_inst_fw_cap inst_fw_cap_sm8550[] = { }, }; +static struct platform_inst_fw_cap inst_fw_cap_sm8550_enc[] = { + { + .cap_id = PROFILE_H264, + .min = V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE, + .max = V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_HIGH, + .step_or_mask = BIT(V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE) | + BIT(V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_HIGH) | + BIT(V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_BASELINE) | + BIT(V4L2_MPEG_VIDEO_H264_PROFILE_MAIN) | + BIT(V4L2_MPEG_VIDEO_H264_PROFILE_HIGH), + .value = V4L2_MPEG_VIDEO_H264_PROFILE_HIGH, + .hfi_id = HFI_PROP_PROFILE, + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU, + .set = iris_set_profile, + }, + { + .cap_id = PROFILE_HEVC, + .min = V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN, + .max = V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN_10, + .step_or_mask = BIT(V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN) | + BIT(V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN_STILL_PICTURE) | + BIT(V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN_10), + .value = V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN, + .hfi_id = HFI_PROP_PROFILE, + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU, + .set = iris_set_profile, + }, + { + .cap_id = LEVEL_H264, + .min = V4L2_MPEG_VIDEO_H264_LEVEL_1_0, + .max = V4L2_MPEG_VIDEO_H264_LEVEL_6_0, + .step_or_mask = BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1_0) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1B) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1_1) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1_2) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1_3) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_2_0) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_2_1) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_2_2) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_3_0) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_3_1) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_3_2) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_4_0) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_4_1) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_4_2) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_5_0) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_5_1) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_5_2) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_6_0), + .value = V4L2_MPEG_VIDEO_H264_LEVEL_5_0, + .hfi_id = HFI_PROP_LEVEL, + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU, + .set = iris_set_level, + }, + { + .cap_id = LEVEL_HEVC, + .min = V4L2_MPEG_VIDEO_HEVC_LEVEL_1, + .max = V4L2_MPEG_VIDEO_HEVC_LEVEL_6_2, + .step_or_mask = BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_1) | + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_2) | + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_2_1) | + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_3) | + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_3_1) | + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_4) | + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_4_1) | + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_5) | + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_5_1) | + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_5_2) | + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_6) | + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_6_1) | + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_6_2), + .value = V4L2_MPEG_VIDEO_HEVC_LEVEL_5, + .hfi_id = HFI_PROP_LEVEL, + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU, + .set = iris_set_level, + }, + { + .cap_id = STAGE, + .min = STAGE_1, + .max = STAGE_2, + .step_or_mask = 1, + .value = STAGE_2, + .hfi_id = HFI_PROP_STAGE, + .set = iris_set_stage, + }, + { + .cap_id = HEADER_MODE, + .min = V4L2_MPEG_VIDEO_HEADER_MODE_SEPARATE, + .max = V4L2_MPEG_VIDEO_HEADER_MODE_JOINED_WITH_1ST_FRAME, + .step_or_mask = BIT(V4L2_MPEG_VIDEO_HEADER_MODE_SEPARATE) | + BIT(V4L2_MPEG_VIDEO_HEADER_MODE_JOINED_WITH_1ST_FRAME), + .value = V4L2_MPEG_VIDEO_HEADER_MODE_JOINED_WITH_1ST_FRAME, + .hfi_id = HFI_PROP_SEQ_HEADER_MODE, + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU, + .set = iris_set_header_mode_gen2, + }, + { + .cap_id = PREPEND_SPSPPS_TO_IDR, + .min = 0, + .max = 1, + .step_or_mask = 1, + .value = 0, + }, + { + .cap_id = BITRATE, + .min = 1, + .max = BITRATE_MAX, + .step_or_mask = 1, + .value = BITRATE_DEFAULT, + .hfi_id = HFI_PROP_TOTAL_BITRATE, + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT | + CAP_FLAG_DYNAMIC_ALLOWED, + .set = iris_set_bitrate, + }, + { + .cap_id = BITRATE_PEAK, + .min = 1, + .max = BITRATE_MAX, + .step_or_mask = 1, + .value = BITRATE_DEFAULT, + .hfi_id = HFI_PROP_TOTAL_PEAK_BITRATE, + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT | + CAP_FLAG_DYNAMIC_ALLOWED, + .set = iris_set_peak_bitrate, + }, + { + .cap_id = BITRATE_MODE, + .min = V4L2_MPEG_VIDEO_BITRATE_MODE_VBR, + .max = V4L2_MPEG_VIDEO_BITRATE_MODE_CBR, + .step_or_mask = BIT(V4L2_MPEG_VIDEO_BITRATE_MODE_VBR) | + BIT(V4L2_MPEG_VIDEO_BITRATE_MODE_CBR), + .value = V4L2_MPEG_VIDEO_BITRATE_MODE_VBR, + .hfi_id = HFI_PROP_RATE_CONTROL, + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU, + .set = iris_set_bitrate_mode_gen2, + }, + { + .cap_id = FRAME_SKIP_MODE, + .min = V4L2_MPEG_VIDEO_FRAME_SKIP_MODE_DISABLED, + .max = V4L2_MPEG_VIDEO_FRAME_SKIP_MODE_BUF_LIMIT, + .step_or_mask = BIT(V4L2_MPEG_VIDEO_FRAME_SKIP_MODE_DISABLED) | + BIT(V4L2_MPEG_VIDEO_FRAME_SKIP_MODE_LEVEL_LIMIT) | + BIT(V4L2_MPEG_VIDEO_FRAME_SKIP_MODE_BUF_LIMIT), + .value = V4L2_MPEG_VIDEO_FRAME_SKIP_MODE_DISABLED, + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU, + }, + { + .cap_id = FRAME_RC_ENABLE, + .min = 0, + .max = 1, + .step_or_mask = 1, + .value = 1, + }, + { + .cap_id = GOP_SIZE, + .min = 0, + .max = INT_MAX, + .step_or_mask = 1, + .value = 2 * DEFAULT_FPS - 1, + .hfi_id = HFI_PROP_MAX_GOP_FRAMES, + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT | + CAP_FLAG_DYNAMIC_ALLOWED, + .set = iris_set_u32, + }, + { + .cap_id = ENTROPY_MODE, + .min = V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CAVLC, + .max = V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CABAC, + .step_or_mask = BIT(V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CAVLC) | + BIT(V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CABAC), + .value = V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CABAC, + .hfi_id = HFI_PROP_CABAC_SESSION, + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU, + .set = iris_set_entropy_mode_gen2, + }, + { + .cap_id = MIN_FRAME_QP_H264, + .min = MIN_QP_8BIT, + .max = MAX_QP, + .step_or_mask = 1, + .value = MIN_QP_8BIT, + .hfi_id = HFI_PROP_MIN_QP_PACKED, + .flags = CAP_FLAG_OUTPUT_PORT, + .set = iris_set_min_qp, + }, + { + .cap_id = MIN_FRAME_QP_HEVC, + .min = MIN_QP_8BIT, + .max = MAX_QP, + .step_or_mask = 1, + .value = MIN_QP_8BIT, + .hfi_id = HFI_PROP_MIN_QP_PACKED, + .flags = CAP_FLAG_OUTPUT_PORT, + .set = iris_set_min_qp, + }, + { + .cap_id = MAX_FRAME_QP_H264, + .min = MIN_QP_8BIT, + .max = MAX_QP, + .step_or_mask = 1, + .value = MAX_QP, + .hfi_id = HFI_PROP_MAX_QP_PACKED, + .flags = CAP_FLAG_OUTPUT_PORT, + .set = iris_set_max_qp, + }, + { + .cap_id = MAX_FRAME_QP_HEVC, + .min = MIN_QP_8BIT, + .max = MAX_QP, + .step_or_mask = 1, + .value = MAX_QP, + .hfi_id = HFI_PROP_MAX_QP_PACKED, + .flags = CAP_FLAG_OUTPUT_PORT, + .set = iris_set_max_qp, + }, + { + .cap_id = I_FRAME_MIN_QP_H264, + .min = MIN_QP_8BIT, + .max = MAX_QP, + .step_or_mask = 1, + .value = MIN_QP_8BIT, + }, + { + .cap_id = I_FRAME_MIN_QP_HEVC, + .min = MIN_QP_8BIT, + .max = MAX_QP, + .step_or_mask = 1, + .value = MIN_QP_8BIT, + }, + { + .cap_id = P_FRAME_MIN_QP_H264, + .min = MIN_QP_8BIT, + .max = MAX_QP, + .step_or_mask = 1, + .value = MIN_QP_8BIT, + }, + { + .cap_id = P_FRAME_MIN_QP_HEVC, + .min = MIN_QP_8BIT, + .max = MAX_QP, + .step_or_mask = 1, + .value = MIN_QP_8BIT, + }, + { + .cap_id = B_FRAME_MIN_QP_H264, + .min = MIN_QP_8BIT, + .max = MAX_QP, + .step_or_mask = 1, + .value = MIN_QP_8BIT, + }, + { + .cap_id = B_FRAME_MIN_QP_HEVC, + .min = MIN_QP_8BIT, + .max = MAX_QP, + .step_or_mask = 1, + .value = MIN_QP_8BIT, + }, + { + .cap_id = I_FRAME_MAX_QP_H264, + .min = MIN_QP_8BIT, + .max = MAX_QP, + .step_or_mask = 1, + .value = MAX_QP, + }, + { + .cap_id = I_FRAME_MAX_QP_HEVC, + .min = MIN_QP_8BIT, + .max = MAX_QP, + .step_or_mask = 1, + .value = MAX_QP, + }, + { + .cap_id = P_FRAME_MAX_QP_H264, + .min = MIN_QP_8BIT, + .max = MAX_QP, + .step_or_mask = 1, + .value = MAX_QP, + }, + { + .cap_id = P_FRAME_MAX_QP_HEVC, + .min = MIN_QP_8BIT, + .max = MAX_QP, + .step_or_mask = 1, + .value = MAX_QP, + }, + { + .cap_id = B_FRAME_MAX_QP_H264, + .min = MIN_QP_8BIT, + .max = MAX_QP, + .step_or_mask = 1, + .value = MAX_QP, + }, + { + .cap_id = B_FRAME_MAX_QP_HEVC, + .min = MIN_QP_8BIT, + .max = MAX_QP, + .step_or_mask = 1, + .value = MAX_QP, + }, + { + .cap_id = I_FRAME_QP_H264, + .min = MIN_QP_8BIT, + .max = MAX_QP, + .step_or_mask = 1, + .value = DEFAULT_QP, + .hfi_id = HFI_PROP_QP_PACKED, + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT | + CAP_FLAG_DYNAMIC_ALLOWED, + .set = iris_set_frame_qp, + }, + { + .cap_id = I_FRAME_QP_HEVC, + .min = MIN_QP_8BIT, + .max = MAX_QP, + .step_or_mask = 1, + .value = DEFAULT_QP, + .hfi_id = HFI_PROP_QP_PACKED, + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT | + CAP_FLAG_DYNAMIC_ALLOWED, + .set = iris_set_frame_qp, + }, + { + .cap_id = P_FRAME_QP_H264, + .min = MIN_QP_8BIT, + .max = MAX_QP, + .step_or_mask = 1, + .value = DEFAULT_QP, + .hfi_id = HFI_PROP_QP_PACKED, + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT | + CAP_FLAG_DYNAMIC_ALLOWED, + .set = iris_set_frame_qp, + }, + { + .cap_id = P_FRAME_QP_HEVC, + .min = MIN_QP_8BIT, + .max = MAX_QP, + .step_or_mask = 1, + .value = DEFAULT_QP, + .hfi_id = HFI_PROP_QP_PACKED, + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT | + CAP_FLAG_DYNAMIC_ALLOWED, + .set = iris_set_frame_qp, + }, + { + .cap_id = B_FRAME_QP_H264, + .min = MIN_QP_8BIT, + .max = MAX_QP, + .step_or_mask = 1, + .value = DEFAULT_QP, + .hfi_id = HFI_PROP_QP_PACKED, + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT | + CAP_FLAG_DYNAMIC_ALLOWED, + .set = iris_set_frame_qp, + }, + { + .cap_id = B_FRAME_QP_HEVC, + .min = MIN_QP_8BIT, + .max = MAX_QP, + .step_or_mask = 1, + .value = DEFAULT_QP, + .hfi_id = HFI_PROP_QP_PACKED, + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT | + CAP_FLAG_DYNAMIC_ALLOWED, + .set = iris_set_frame_qp, + }, + { + .cap_id = INPUT_BUF_HOST_MAX_COUNT, + .min = DEFAULT_MAX_HOST_BUF_COUNT, + .max = DEFAULT_MAX_HOST_BURST_BUF_COUNT, + .step_or_mask = 1, + .value = DEFAULT_MAX_HOST_BUF_COUNT, + .hfi_id = HFI_PROP_BUFFER_HOST_MAX_COUNT, + .flags = CAP_FLAG_INPUT_PORT, + .set = iris_set_u32, + }, + { + .cap_id = OUTPUT_BUF_HOST_MAX_COUNT, + .min = DEFAULT_MAX_HOST_BUF_COUNT, + .max = DEFAULT_MAX_HOST_BURST_BUF_COUNT, + .step_or_mask = 1, + .value = DEFAULT_MAX_HOST_BUF_COUNT, + .hfi_id = HFI_PROP_BUFFER_HOST_MAX_COUNT, + .flags = CAP_FLAG_OUTPUT_PORT, + .set = iris_set_u32, + }, +}; + static struct platform_inst_caps platform_inst_cap_sm8550 = { .min_frame_width = 96, .max_frame_width = 8192, @@ -209,6 +600,8 @@ static struct platform_inst_caps platform_inst_cap_sm8550 = { .mb_cycles_fw = 489583, .mb_cycles_fw_vpp = 66234, .num_comv = 0, + .max_frame_rate = MAXIMUM_FPS, + .max_operating_rate = MAXIMUM_FPS, }; static void iris_set_sm8550_preset_registers(struct iris_core *core) @@ -289,11 +682,25 @@ static const u32 sm8550_vdec_input_config_param_vp9[] = { HFI_PROP_LEVEL, }; +static const u32 sm8550_venc_input_config_params[] = { + HFI_PROP_COLOR_FORMAT, + HFI_PROP_RAW_RESOLUTION, + HFI_PROP_CROP_OFFSETS, + HFI_PROP_LINEAR_STRIDE_SCANLINE, + HFI_PROP_SIGNAL_COLOR_INFO, +}; + static const u32 sm8550_vdec_output_config_params[] = { HFI_PROP_COLOR_FORMAT, HFI_PROP_LINEAR_STRIDE_SCANLINE, }; +static const u32 sm8550_venc_output_config_params[] = { + HFI_PROP_BITSTREAM_RESOLUTION, + HFI_PROP_CROP_OFFSETS, + HFI_PROP_FRAME_RATE, +}; + static const u32 sm8550_vdec_subscribe_input_properties[] = { HFI_PROP_NO_OUTPUT, }; @@ -322,10 +729,19 @@ static const u32 sm8550_dec_op_int_buf_tbl[] = { BUF_DPB, }; +static const u32 sm8550_enc_op_int_buf_tbl[] = { + BUF_BIN, + BUF_COMV, + BUF_NON_COMV, + BUF_LINE, + BUF_SCRATCH_2, +}; + struct iris_platform_data sm8550_data = { .get_instance = iris_hfi_gen2_get_instance, .init_hfi_command_ops = iris_hfi_gen2_command_ops_init, .init_hfi_response_ops = iris_hfi_gen2_response_ops_init, + .get_vpu_buffer_size = iris_vpu_buf_size, .vpu_ops = &iris_vpu3_ops, .set_preset_registers = iris_set_sm8550_preset_registers, .icc_tbl = sm8550_icc_table, @@ -345,8 +761,10 @@ struct iris_platform_data sm8550_data = { .fwname = "qcom/vpu/vpu30_p4.mbn", .pas_id = IRIS_PAS_ID, .inst_caps = &platform_inst_cap_sm8550, - .inst_fw_caps = inst_fw_cap_sm8550, - .inst_fw_caps_size = ARRAY_SIZE(inst_fw_cap_sm8550), + .inst_fw_caps_dec = inst_fw_cap_sm8550_dec, + .inst_fw_caps_dec_size = ARRAY_SIZE(inst_fw_cap_sm8550_dec), + .inst_fw_caps_enc = inst_fw_cap_sm8550_enc, + .inst_fw_caps_enc_size = ARRAY_SIZE(inst_fw_cap_sm8550_enc), .tz_cp_config_data = &tz_cp_config_sm8550, .core_arch = VIDEO_ARCH_LX, .hw_response_timeout = HW_RESPONSE_TIMEOUT_VALUE, @@ -354,22 +772,33 @@ struct iris_platform_data sm8550_data = { .num_vpp_pipe = 4, .max_session_count = 16, .max_core_mbpf = NUM_MBS_8K * 2, - .input_config_params_default = + .max_core_mbps = ((7680 * 4320) / 256) * 60, + .dec_input_config_params_default = sm8550_vdec_input_config_params_default, - .input_config_params_default_size = + .dec_input_config_params_default_size = ARRAY_SIZE(sm8550_vdec_input_config_params_default), - .input_config_params_hevc = + .dec_input_config_params_hevc = sm8550_vdec_input_config_param_hevc, - .input_config_params_hevc_size = + .dec_input_config_params_hevc_size = ARRAY_SIZE(sm8550_vdec_input_config_param_hevc), - .input_config_params_vp9 = + .dec_input_config_params_vp9 = sm8550_vdec_input_config_param_vp9, - .input_config_params_vp9_size = + .dec_input_config_params_vp9_size = ARRAY_SIZE(sm8550_vdec_input_config_param_vp9), - .output_config_params = + .dec_output_config_params = sm8550_vdec_output_config_params, - .output_config_params_size = + .dec_output_config_params_size = ARRAY_SIZE(sm8550_vdec_output_config_params), + + .enc_input_config_params = + sm8550_venc_input_config_params, + .enc_input_config_params_size = + ARRAY_SIZE(sm8550_venc_input_config_params), + .enc_output_config_params = + sm8550_venc_output_config_params, + .enc_output_config_params_size = + ARRAY_SIZE(sm8550_venc_output_config_params), + .dec_input_prop = sm8550_vdec_subscribe_input_properties, .dec_input_prop_size = ARRAY_SIZE(sm8550_vdec_subscribe_input_properties), .dec_output_prop_avc = sm8550_vdec_subscribe_output_properties_avc, @@ -386,6 +815,9 @@ struct iris_platform_data sm8550_data = { .dec_ip_int_buf_tbl_size = ARRAY_SIZE(sm8550_dec_ip_int_buf_tbl), .dec_op_int_buf_tbl = sm8550_dec_op_int_buf_tbl, .dec_op_int_buf_tbl_size = ARRAY_SIZE(sm8550_dec_op_int_buf_tbl), + + .enc_op_int_buf_tbl = sm8550_enc_op_int_buf_tbl, + .enc_op_int_buf_tbl_size = ARRAY_SIZE(sm8550_enc_op_int_buf_tbl), }; /* @@ -399,6 +831,7 @@ struct iris_platform_data sm8650_data = { .get_instance = iris_hfi_gen2_get_instance, .init_hfi_command_ops = iris_hfi_gen2_command_ops_init, .init_hfi_response_ops = iris_hfi_gen2_response_ops_init, + .get_vpu_buffer_size = iris_vpu33_buf_size, .vpu_ops = &iris_vpu33_ops, .set_preset_registers = iris_set_sm8550_preset_registers, .icc_tbl = sm8550_icc_table, @@ -420,8 +853,10 @@ struct iris_platform_data sm8650_data = { .fwname = "qcom/vpu/vpu33_p4.mbn", .pas_id = IRIS_PAS_ID, .inst_caps = &platform_inst_cap_sm8550, - .inst_fw_caps = inst_fw_cap_sm8550, - .inst_fw_caps_size = ARRAY_SIZE(inst_fw_cap_sm8550), + .inst_fw_caps_dec = inst_fw_cap_sm8550_dec, + .inst_fw_caps_dec_size = ARRAY_SIZE(inst_fw_cap_sm8550_dec), + .inst_fw_caps_enc = inst_fw_cap_sm8550_enc, + .inst_fw_caps_enc_size = ARRAY_SIZE(inst_fw_cap_sm8550_enc), .tz_cp_config_data = &tz_cp_config_sm8550, .core_arch = VIDEO_ARCH_LX, .hw_response_timeout = HW_RESPONSE_TIMEOUT_VALUE, @@ -429,22 +864,33 @@ struct iris_platform_data sm8650_data = { .num_vpp_pipe = 4, .max_session_count = 16, .max_core_mbpf = NUM_MBS_8K * 2, - .input_config_params_default = + .max_core_mbps = ((7680 * 4320) / 256) * 60, + .dec_input_config_params_default = sm8550_vdec_input_config_params_default, - .input_config_params_default_size = + .dec_input_config_params_default_size = ARRAY_SIZE(sm8550_vdec_input_config_params_default), - .input_config_params_hevc = + .dec_input_config_params_hevc = sm8550_vdec_input_config_param_hevc, - .input_config_params_hevc_size = + .dec_input_config_params_hevc_size = ARRAY_SIZE(sm8550_vdec_input_config_param_hevc), - .input_config_params_vp9 = + .dec_input_config_params_vp9 = sm8550_vdec_input_config_param_vp9, - .input_config_params_vp9_size = + .dec_input_config_params_vp9_size = ARRAY_SIZE(sm8550_vdec_input_config_param_vp9), - .output_config_params = + .dec_output_config_params = sm8550_vdec_output_config_params, - .output_config_params_size = + .dec_output_config_params_size = ARRAY_SIZE(sm8550_vdec_output_config_params), + + .enc_input_config_params = + sm8550_venc_input_config_params, + .enc_input_config_params_size = + ARRAY_SIZE(sm8550_venc_input_config_params), + .enc_output_config_params = + sm8550_venc_output_config_params, + .enc_output_config_params_size = + ARRAY_SIZE(sm8550_venc_output_config_params), + .dec_input_prop = sm8550_vdec_subscribe_input_properties, .dec_input_prop_size = ARRAY_SIZE(sm8550_vdec_subscribe_input_properties), .dec_output_prop_avc = sm8550_vdec_subscribe_output_properties_avc, @@ -461,6 +907,90 @@ struct iris_platform_data sm8650_data = { .dec_ip_int_buf_tbl_size = ARRAY_SIZE(sm8550_dec_ip_int_buf_tbl), .dec_op_int_buf_tbl = sm8550_dec_op_int_buf_tbl, .dec_op_int_buf_tbl_size = ARRAY_SIZE(sm8550_dec_op_int_buf_tbl), + + .enc_op_int_buf_tbl = sm8550_enc_op_int_buf_tbl, + .enc_op_int_buf_tbl_size = ARRAY_SIZE(sm8550_enc_op_int_buf_tbl), +}; + +struct iris_platform_data sm8750_data = { + .get_instance = iris_hfi_gen2_get_instance, + .init_hfi_command_ops = iris_hfi_gen2_command_ops_init, + .init_hfi_response_ops = iris_hfi_gen2_response_ops_init, + .vpu_ops = &iris_vpu35_ops, + .set_preset_registers = iris_set_sm8550_preset_registers, + .icc_tbl = sm8550_icc_table, + .icc_tbl_size = ARRAY_SIZE(sm8550_icc_table), + .clk_rst_tbl = sm8750_clk_reset_table, + .clk_rst_tbl_size = ARRAY_SIZE(sm8750_clk_reset_table), + .bw_tbl_dec = sm8550_bw_table_dec, + .bw_tbl_dec_size = ARRAY_SIZE(sm8550_bw_table_dec), + .pmdomain_tbl = sm8550_pmdomain_table, + .pmdomain_tbl_size = ARRAY_SIZE(sm8550_pmdomain_table), + .opp_pd_tbl = sm8550_opp_pd_table, + .opp_pd_tbl_size = ARRAY_SIZE(sm8550_opp_pd_table), + .clk_tbl = sm8750_clk_table, + .clk_tbl_size = ARRAY_SIZE(sm8750_clk_table), + /* Upper bound of DMA address range */ + .dma_mask = 0xe0000000 - 1, + .fwname = "qcom/vpu/vpu35_p4.mbn", + .pas_id = IRIS_PAS_ID, + .inst_caps = &platform_inst_cap_sm8550, + .inst_fw_caps_dec = inst_fw_cap_sm8550_dec, + .inst_fw_caps_dec_size = ARRAY_SIZE(inst_fw_cap_sm8550_dec), + .inst_fw_caps_enc = inst_fw_cap_sm8550_enc, + .inst_fw_caps_enc_size = ARRAY_SIZE(inst_fw_cap_sm8550_enc), + .tz_cp_config_data = &tz_cp_config_sm8550, + .core_arch = VIDEO_ARCH_LX, + .hw_response_timeout = HW_RESPONSE_TIMEOUT_VALUE, + .ubwc_config = &ubwc_config_sm8550, + .num_vpp_pipe = 4, + .max_session_count = 16, + .max_core_mbpf = NUM_MBS_8K * 2, + .dec_input_config_params_default = + sm8550_vdec_input_config_params_default, + .dec_input_config_params_default_size = + ARRAY_SIZE(sm8550_vdec_input_config_params_default), + .dec_input_config_params_hevc = + sm8550_vdec_input_config_param_hevc, + .dec_input_config_params_hevc_size = + ARRAY_SIZE(sm8550_vdec_input_config_param_hevc), + .dec_input_config_params_vp9 = + sm8550_vdec_input_config_param_vp9, + .dec_input_config_params_vp9_size = + ARRAY_SIZE(sm8550_vdec_input_config_param_vp9), + .dec_output_config_params = + sm8550_vdec_output_config_params, + .dec_output_config_params_size = + ARRAY_SIZE(sm8550_vdec_output_config_params), + + .enc_input_config_params = + sm8550_venc_input_config_params, + .enc_input_config_params_size = + ARRAY_SIZE(sm8550_venc_input_config_params), + .enc_output_config_params = + sm8550_venc_output_config_params, + .enc_output_config_params_size = + ARRAY_SIZE(sm8550_venc_output_config_params), + + .dec_input_prop = sm8550_vdec_subscribe_input_properties, + .dec_input_prop_size = ARRAY_SIZE(sm8550_vdec_subscribe_input_properties), + .dec_output_prop_avc = sm8550_vdec_subscribe_output_properties_avc, + .dec_output_prop_avc_size = + ARRAY_SIZE(sm8550_vdec_subscribe_output_properties_avc), + .dec_output_prop_hevc = sm8550_vdec_subscribe_output_properties_hevc, + .dec_output_prop_hevc_size = + ARRAY_SIZE(sm8550_vdec_subscribe_output_properties_hevc), + .dec_output_prop_vp9 = sm8550_vdec_subscribe_output_properties_vp9, + .dec_output_prop_vp9_size = + ARRAY_SIZE(sm8550_vdec_subscribe_output_properties_vp9), + + .dec_ip_int_buf_tbl = sm8550_dec_ip_int_buf_tbl, + .dec_ip_int_buf_tbl_size = ARRAY_SIZE(sm8550_dec_ip_int_buf_tbl), + .dec_op_int_buf_tbl = sm8550_dec_op_int_buf_tbl, + .dec_op_int_buf_tbl_size = ARRAY_SIZE(sm8550_dec_op_int_buf_tbl), + + .enc_op_int_buf_tbl = sm8550_enc_op_int_buf_tbl, + .enc_op_int_buf_tbl_size = ARRAY_SIZE(sm8550_enc_op_int_buf_tbl), }; /* @@ -472,6 +1002,7 @@ struct iris_platform_data qcs8300_data = { .get_instance = iris_hfi_gen2_get_instance, .init_hfi_command_ops = iris_hfi_gen2_command_ops_init, .init_hfi_response_ops = iris_hfi_gen2_response_ops_init, + .get_vpu_buffer_size = iris_vpu_buf_size, .vpu_ops = &iris_vpu3_ops, .set_preset_registers = iris_set_sm8550_preset_registers, .icc_tbl = sm8550_icc_table, @@ -491,8 +1022,10 @@ struct iris_platform_data qcs8300_data = { .fwname = "qcom/vpu/vpu30_p4_s6.mbn", .pas_id = IRIS_PAS_ID, .inst_caps = &platform_inst_cap_qcs8300, - .inst_fw_caps = inst_fw_cap_qcs8300, - .inst_fw_caps_size = ARRAY_SIZE(inst_fw_cap_qcs8300), + .inst_fw_caps_dec = inst_fw_cap_qcs8300_dec, + .inst_fw_caps_dec_size = ARRAY_SIZE(inst_fw_cap_qcs8300_dec), + .inst_fw_caps_enc = inst_fw_cap_qcs8300_enc, + .inst_fw_caps_enc_size = ARRAY_SIZE(inst_fw_cap_qcs8300_enc), .tz_cp_config_data = &tz_cp_config_sm8550, .core_arch = VIDEO_ARCH_LX, .hw_response_timeout = HW_RESPONSE_TIMEOUT_VALUE, @@ -500,22 +1033,33 @@ struct iris_platform_data qcs8300_data = { .num_vpp_pipe = 2, .max_session_count = 16, .max_core_mbpf = ((4096 * 2176) / 256) * 4, - .input_config_params_default = + .max_core_mbps = (((3840 * 2176) / 256) * 120), + .dec_input_config_params_default = sm8550_vdec_input_config_params_default, - .input_config_params_default_size = + .dec_input_config_params_default_size = ARRAY_SIZE(sm8550_vdec_input_config_params_default), - .input_config_params_hevc = + .dec_input_config_params_hevc = sm8550_vdec_input_config_param_hevc, - .input_config_params_hevc_size = + .dec_input_config_params_hevc_size = ARRAY_SIZE(sm8550_vdec_input_config_param_hevc), - .input_config_params_vp9 = + .dec_input_config_params_vp9 = sm8550_vdec_input_config_param_vp9, - .input_config_params_vp9_size = + .dec_input_config_params_vp9_size = ARRAY_SIZE(sm8550_vdec_input_config_param_vp9), - .output_config_params = + .dec_output_config_params = sm8550_vdec_output_config_params, - .output_config_params_size = + .dec_output_config_params_size = ARRAY_SIZE(sm8550_vdec_output_config_params), + + .enc_input_config_params = + sm8550_venc_input_config_params, + .enc_input_config_params_size = + ARRAY_SIZE(sm8550_venc_input_config_params), + .enc_output_config_params = + sm8550_venc_output_config_params, + .enc_output_config_params_size = + ARRAY_SIZE(sm8550_venc_output_config_params), + .dec_input_prop = sm8550_vdec_subscribe_input_properties, .dec_input_prop_size = ARRAY_SIZE(sm8550_vdec_subscribe_input_properties), .dec_output_prop_avc = sm8550_vdec_subscribe_output_properties_avc, @@ -532,4 +1076,7 @@ struct iris_platform_data qcs8300_data = { .dec_ip_int_buf_tbl_size = ARRAY_SIZE(sm8550_dec_ip_int_buf_tbl), .dec_op_int_buf_tbl = sm8550_dec_op_int_buf_tbl, .dec_op_int_buf_tbl_size = ARRAY_SIZE(sm8550_dec_op_int_buf_tbl), + + .enc_op_int_buf_tbl = sm8550_enc_op_int_buf_tbl, + .enc_op_int_buf_tbl_size = ARRAY_SIZE(sm8550_enc_op_int_buf_tbl), }; diff --git a/drivers/media/platform/qcom/iris/iris_platform_qcs8300.h b/drivers/media/platform/qcom/iris/iris_platform_qcs8300.h index a8d66ed388a3..35ea0efade73 100644 --- a/drivers/media/platform/qcom/iris/iris_platform_qcs8300.h +++ b/drivers/media/platform/qcom/iris/iris_platform_qcs8300.h @@ -3,7 +3,9 @@ * Copyright (c) 2022-2025 Qualcomm Innovation Center, Inc. All rights reserved. */ -static struct platform_inst_fw_cap inst_fw_cap_qcs8300[] = { +#define BITRATE_MAX 245000000 + +static struct platform_inst_fw_cap inst_fw_cap_qcs8300_dec[] = { { .cap_id = PROFILE_H264, .min = V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE, @@ -187,6 +189,352 @@ static struct platform_inst_fw_cap inst_fw_cap_qcs8300[] = { }, }; +static struct platform_inst_fw_cap inst_fw_cap_qcs8300_enc[] = { + { + .cap_id = PROFILE_H264, + .min = V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE, + .max = V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_HIGH, + .step_or_mask = BIT(V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE) | + BIT(V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_HIGH) | + BIT(V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_BASELINE) | + BIT(V4L2_MPEG_VIDEO_H264_PROFILE_MAIN) | + BIT(V4L2_MPEG_VIDEO_H264_PROFILE_HIGH), + .value = V4L2_MPEG_VIDEO_H264_PROFILE_HIGH, + .hfi_id = HFI_PROP_PROFILE, + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU, + }, + { + .cap_id = PROFILE_HEVC, + .min = V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN, + .max = V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN_10, + .step_or_mask = BIT(V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN) | + BIT(V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN_STILL_PICTURE) | + BIT(V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN_10), + .value = V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN, + .hfi_id = HFI_PROP_PROFILE, + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU, + }, + { + .cap_id = LEVEL_H264, + .min = V4L2_MPEG_VIDEO_H264_LEVEL_1_0, + .max = V4L2_MPEG_VIDEO_H264_LEVEL_6_0, + .step_or_mask = BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1_0) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1B) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1_1) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1_2) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1_3) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_2_0) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_2_1) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_2_2) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_3_0) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_3_1) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_3_2) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_4_0) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_4_1) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_4_2) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_5_0) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_5_1) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_5_2) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_6_0), + .value = V4L2_MPEG_VIDEO_H264_LEVEL_5_0, + .hfi_id = HFI_PROP_LEVEL, + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU, + }, + { + .cap_id = LEVEL_HEVC, + .min = V4L2_MPEG_VIDEO_HEVC_LEVEL_1, + .max = V4L2_MPEG_VIDEO_HEVC_LEVEL_6_2, + .step_or_mask = BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_1) | + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_2) | + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_2_1) | + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_3) | + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_3_1) | + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_4) | + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_4_1) | + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_5) | + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_5_1) | + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_5_2) | + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_6) | + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_6_1) | + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_6_2), + .value = V4L2_MPEG_VIDEO_HEVC_LEVEL_5, + .hfi_id = HFI_PROP_LEVEL, + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU, + }, + { + .cap_id = STAGE, + .min = STAGE_1, + .max = STAGE_2, + .step_or_mask = 1, + .value = STAGE_2, + .hfi_id = HFI_PROP_STAGE, + }, + { + .cap_id = HEADER_MODE, + .min = V4L2_MPEG_VIDEO_HEADER_MODE_SEPARATE, + .max = V4L2_MPEG_VIDEO_HEADER_MODE_JOINED_WITH_1ST_FRAME, + .step_or_mask = BIT(V4L2_MPEG_VIDEO_HEADER_MODE_SEPARATE) | + BIT(V4L2_MPEG_VIDEO_HEADER_MODE_JOINED_WITH_1ST_FRAME), + .value = V4L2_MPEG_VIDEO_HEADER_MODE_JOINED_WITH_1ST_FRAME, + .hfi_id = HFI_PROP_SEQ_HEADER_MODE, + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU, + }, + { + .cap_id = PREPEND_SPSPPS_TO_IDR, + .min = 0, + .max = 1, + .step_or_mask = 1, + .value = 0, + }, + { + .cap_id = BITRATE, + .min = 1, + .max = BITRATE_MAX, + .step_or_mask = 1, + .value = BITRATE_DEFAULT, + .hfi_id = HFI_PROP_TOTAL_BITRATE, + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT | + CAP_FLAG_DYNAMIC_ALLOWED, + }, + { + .cap_id = BITRATE_PEAK, + .min = 1, + .max = BITRATE_MAX, + .step_or_mask = 1, + .value = BITRATE_DEFAULT, + .hfi_id = HFI_PROP_TOTAL_PEAK_BITRATE, + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT | + CAP_FLAG_DYNAMIC_ALLOWED, + }, + { + .cap_id = BITRATE_MODE, + .min = V4L2_MPEG_VIDEO_BITRATE_MODE_VBR, + .max = V4L2_MPEG_VIDEO_BITRATE_MODE_CBR, + .step_or_mask = BIT(V4L2_MPEG_VIDEO_BITRATE_MODE_VBR) | + BIT(V4L2_MPEG_VIDEO_BITRATE_MODE_CBR), + .value = V4L2_MPEG_VIDEO_BITRATE_MODE_VBR, + .hfi_id = HFI_PROP_RATE_CONTROL, + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU, + }, + { + .cap_id = FRAME_SKIP_MODE, + .min = V4L2_MPEG_VIDEO_FRAME_SKIP_MODE_DISABLED, + .max = V4L2_MPEG_VIDEO_FRAME_SKIP_MODE_BUF_LIMIT, + .step_or_mask = BIT(V4L2_MPEG_VIDEO_FRAME_SKIP_MODE_DISABLED) | + BIT(V4L2_MPEG_VIDEO_FRAME_SKIP_MODE_LEVEL_LIMIT) | + BIT(V4L2_MPEG_VIDEO_FRAME_SKIP_MODE_BUF_LIMIT), + .value = V4L2_MPEG_VIDEO_FRAME_SKIP_MODE_DISABLED, + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU, + }, + { + .cap_id = FRAME_RC_ENABLE, + .min = 0, + .max = 1, + .step_or_mask = 1, + .value = 1, + }, + { + .cap_id = GOP_SIZE, + .min = 0, + .max = INT_MAX, + .step_or_mask = 1, + .value = 2 * DEFAULT_FPS - 1, + .hfi_id = HFI_PROP_MAX_GOP_FRAMES, + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT | + CAP_FLAG_DYNAMIC_ALLOWED, + }, + { + .cap_id = ENTROPY_MODE, + .min = V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CAVLC, + .max = V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CABAC, + .step_or_mask = BIT(V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CAVLC) | + BIT(V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CABAC), + .value = V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CABAC, + .hfi_id = HFI_PROP_CABAC_SESSION, + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU, + }, + { + .cap_id = MIN_FRAME_QP_H264, + .min = MIN_QP_8BIT, + .max = MAX_QP, + .step_or_mask = 1, + .value = MIN_QP_8BIT, + .hfi_id = HFI_PROP_MIN_QP_PACKED, + .flags = CAP_FLAG_OUTPUT_PORT, + }, + { + .cap_id = MIN_FRAME_QP_HEVC, + .min = MIN_QP_8BIT, + .max = MAX_QP, + .step_or_mask = 1, + .value = MIN_QP_8BIT, + .hfi_id = HFI_PROP_MIN_QP_PACKED, + .flags = CAP_FLAG_OUTPUT_PORT, + }, + { + .cap_id = MAX_FRAME_QP_H264, + .min = MIN_QP_8BIT, + .max = MAX_QP, + .step_or_mask = 1, + .value = MAX_QP, + .hfi_id = HFI_PROP_MAX_QP_PACKED, + .flags = CAP_FLAG_OUTPUT_PORT, + }, + { + .cap_id = MAX_FRAME_QP_HEVC, + .min = MIN_QP_8BIT, + .max = MAX_QP, + .step_or_mask = 1, + .value = MAX_QP, + .hfi_id = HFI_PROP_MAX_QP_PACKED, + .flags = CAP_FLAG_OUTPUT_PORT, + }, + { + .cap_id = I_FRAME_MIN_QP_H264, + .min = MIN_QP_8BIT, + .max = MAX_QP, + .step_or_mask = 1, + .value = MIN_QP_8BIT, + }, + { + .cap_id = I_FRAME_MIN_QP_HEVC, + .min = MIN_QP_8BIT, + .max = MAX_QP, + .step_or_mask = 1, + .value = MIN_QP_8BIT, + }, + { + .cap_id = P_FRAME_MIN_QP_H264, + .min = MIN_QP_8BIT, + .max = MAX_QP, + .step_or_mask = 1, + .value = MIN_QP_8BIT, + }, + { + .cap_id = P_FRAME_MIN_QP_HEVC, + .min = MIN_QP_8BIT, + .max = MAX_QP, + .step_or_mask = 1, + .value = MIN_QP_8BIT, + }, + { + .cap_id = B_FRAME_MIN_QP_H264, + .min = MIN_QP_8BIT, + .max = MAX_QP, + .step_or_mask = 1, + .value = MIN_QP_8BIT, + }, + { + .cap_id = B_FRAME_MIN_QP_HEVC, + .min = MIN_QP_8BIT, + .max = MAX_QP, + .step_or_mask = 1, + .value = MIN_QP_8BIT, + }, + { + .cap_id = I_FRAME_MAX_QP_H264, + .min = MIN_QP_8BIT, + .max = MAX_QP, + .step_or_mask = 1, + .value = MAX_QP, + }, + { + .cap_id = I_FRAME_MAX_QP_HEVC, + .min = MIN_QP_8BIT, + .max = MAX_QP, + .step_or_mask = 1, + .value = MAX_QP, + }, + { + .cap_id = P_FRAME_MAX_QP_H264, + .min = MIN_QP_8BIT, + .max = MAX_QP, + .step_or_mask = 1, + .value = MAX_QP, + }, + { + .cap_id = P_FRAME_MAX_QP_HEVC, + .min = MIN_QP_8BIT, + .max = MAX_QP, + .step_or_mask = 1, + .value = MAX_QP, + }, + { + .cap_id = B_FRAME_MAX_QP_H264, + .min = MIN_QP_8BIT, + .max = MAX_QP, + .step_or_mask = 1, + .value = MAX_QP, + }, + { + .cap_id = B_FRAME_MAX_QP_HEVC, + .min = MIN_QP_8BIT, + .max = MAX_QP, + .step_or_mask = 1, + .value = MAX_QP, + }, + { + .cap_id = I_FRAME_QP_H264, + .min = MIN_QP_8BIT, + .max = MAX_QP, + .step_or_mask = 1, + .value = DEFAULT_QP, + .hfi_id = HFI_PROP_QP_PACKED, + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT | + CAP_FLAG_DYNAMIC_ALLOWED, + }, + { + .cap_id = I_FRAME_QP_HEVC, + .min = MIN_QP_8BIT, + .max = MAX_QP, + .step_or_mask = 1, + .value = DEFAULT_QP, + .hfi_id = HFI_PROP_QP_PACKED, + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT | + CAP_FLAG_DYNAMIC_ALLOWED, + }, + { + .cap_id = P_FRAME_QP_H264, + .min = MIN_QP_8BIT, + .max = MAX_QP, + .step_or_mask = 1, + .value = DEFAULT_QP, + .hfi_id = HFI_PROP_QP_PACKED, + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT | + CAP_FLAG_DYNAMIC_ALLOWED, + }, + { + .cap_id = P_FRAME_QP_HEVC, + .min = MIN_QP_8BIT, + .max = MAX_QP, + .step_or_mask = 1, + .value = DEFAULT_QP, + .hfi_id = HFI_PROP_QP_PACKED, + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT | + CAP_FLAG_DYNAMIC_ALLOWED, + }, + { + .cap_id = B_FRAME_QP_H264, + .min = MIN_QP_8BIT, + .max = MAX_QP, + .step_or_mask = 1, + .value = DEFAULT_QP, + .hfi_id = HFI_PROP_QP_PACKED, + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT | + CAP_FLAG_DYNAMIC_ALLOWED, + }, + { + .cap_id = B_FRAME_QP_HEVC, + .min = MIN_QP_8BIT, + .max = MAX_QP, + .step_or_mask = 1, + .value = DEFAULT_QP, + .hfi_id = HFI_PROP_QP_PACKED, + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT | + CAP_FLAG_DYNAMIC_ALLOWED, + }, +}; + static struct platform_inst_caps platform_inst_cap_qcs8300 = { .min_frame_width = 96, .max_frame_width = 4096, @@ -197,4 +545,6 @@ static struct platform_inst_caps platform_inst_cap_qcs8300 = { .mb_cycles_fw = 326389, .mb_cycles_fw_vpp = 44156, .num_comv = 0, + .max_frame_rate = MAXIMUM_FPS, + .max_operating_rate = MAXIMUM_FPS, }; diff --git a/drivers/media/platform/qcom/iris/iris_platform_sm8250.c b/drivers/media/platform/qcom/iris/iris_platform_sm8250.c index 8d0816a67ae0..16486284f8ac 100644 --- a/drivers/media/platform/qcom/iris/iris_platform_sm8250.c +++ b/drivers/media/platform/qcom/iris/iris_platform_sm8250.c @@ -9,9 +9,15 @@ #include "iris_resources.h" #include "iris_hfi_gen1.h" #include "iris_hfi_gen1_defines.h" +#include "iris_vpu_buffer.h" #include "iris_vpu_common.h" -static struct platform_inst_fw_cap inst_fw_cap_sm8250[] = { +#define BITRATE_MIN 32000 +#define BITRATE_MAX 160000000 +#define BITRATE_PEAK_DEFAULT (BITRATE_DEFAULT * 2) +#define BITRATE_STEP 100 + +static struct platform_inst_fw_cap inst_fw_cap_sm8250_dec[] = { { .cap_id = PIPE, .min = PIPE_1, @@ -32,6 +38,200 @@ static struct platform_inst_fw_cap inst_fw_cap_sm8250[] = { }, }; +static struct platform_inst_fw_cap inst_fw_cap_sm8250_enc[] = { + { + .cap_id = STAGE, + .min = STAGE_1, + .max = STAGE_2, + .step_or_mask = 1, + .value = STAGE_2, + .hfi_id = HFI_PROPERTY_PARAM_WORK_MODE, + .set = iris_set_stage, + }, + { + .cap_id = PROFILE_H264, + .min = V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE, + .max = V4L2_MPEG_VIDEO_H264_PROFILE_MULTIVIEW_HIGH, + .step_or_mask = BIT(V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE) | + BIT(V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_BASELINE) | + BIT(V4L2_MPEG_VIDEO_H264_PROFILE_MAIN) | + BIT(V4L2_MPEG_VIDEO_H264_PROFILE_HIGH) | + BIT(V4L2_MPEG_VIDEO_H264_PROFILE_STEREO_HIGH) | + BIT(V4L2_MPEG_VIDEO_H264_PROFILE_MULTIVIEW_HIGH), + .value = V4L2_MPEG_VIDEO_H264_PROFILE_HIGH, + .hfi_id = HFI_PROPERTY_PARAM_PROFILE_LEVEL_CURRENT, + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU, + .set = iris_set_profile_level_gen1, + }, + { + .cap_id = PROFILE_HEVC, + .min = V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN, + .max = V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN_10, + .step_or_mask = BIT(V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN) | + BIT(V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN_STILL_PICTURE) | + BIT(V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN_10), + .value = V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN, + .hfi_id = HFI_PROPERTY_PARAM_PROFILE_LEVEL_CURRENT, + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU, + .set = iris_set_profile_level_gen1, + }, + { + .cap_id = LEVEL_H264, + .min = V4L2_MPEG_VIDEO_H264_LEVEL_1_0, + .max = V4L2_MPEG_VIDEO_H264_LEVEL_5_1, + .step_or_mask = BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1_0) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1B) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1_1) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1_2) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1_3) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_2_0) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_2_1) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_2_2) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_3_0) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_3_1) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_3_2) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_4_0) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_4_1) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_4_2) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_5_0) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_5_1), + .value = V4L2_MPEG_VIDEO_H264_LEVEL_1_0, + .hfi_id = HFI_PROPERTY_PARAM_PROFILE_LEVEL_CURRENT, + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU, + .set = iris_set_profile_level_gen1, + }, + { + .cap_id = LEVEL_HEVC, + .min = V4L2_MPEG_VIDEO_HEVC_LEVEL_1, + .max = V4L2_MPEG_VIDEO_HEVC_LEVEL_6_2, + .step_or_mask = BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_1) | + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_2) | + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_2_1) | + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_3) | + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_3_1) | + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_4) | + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_4_1) | + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_5) | + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_5_1) | + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_5_2) | + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_6) | + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_6_1) | + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_6_2), + .value = V4L2_MPEG_VIDEO_HEVC_LEVEL_1, + .hfi_id = HFI_PROPERTY_PARAM_PROFILE_LEVEL_CURRENT, + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU, + .set = iris_set_profile_level_gen1, + }, + { + .cap_id = HEADER_MODE, + .min = V4L2_MPEG_VIDEO_HEADER_MODE_SEPARATE, + .max = V4L2_MPEG_VIDEO_HEADER_MODE_JOINED_WITH_1ST_FRAME, + .step_or_mask = BIT(V4L2_MPEG_VIDEO_HEADER_MODE_SEPARATE) | + BIT(V4L2_MPEG_VIDEO_HEADER_MODE_JOINED_WITH_1ST_FRAME), + .value = V4L2_MPEG_VIDEO_HEADER_MODE_JOINED_WITH_1ST_FRAME, + .hfi_id = HFI_PROPERTY_CONFIG_VENC_SYNC_FRAME_SEQUENCE_HEADER, + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU, + .set = iris_set_header_mode_gen1, + }, + { + .cap_id = BITRATE, + .min = BITRATE_MIN, + .max = BITRATE_MAX, + .step_or_mask = BITRATE_STEP, + .value = BITRATE_DEFAULT, + .hfi_id = HFI_PROPERTY_CONFIG_VENC_TARGET_BITRATE, + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT | + CAP_FLAG_DYNAMIC_ALLOWED, + .set = iris_set_bitrate, + }, + { + .cap_id = BITRATE_MODE, + .min = V4L2_MPEG_VIDEO_BITRATE_MODE_VBR, + .max = V4L2_MPEG_VIDEO_BITRATE_MODE_CBR, + .step_or_mask = BIT(V4L2_MPEG_VIDEO_BITRATE_MODE_VBR) | + BIT(V4L2_MPEG_VIDEO_BITRATE_MODE_CBR), + .value = V4L2_MPEG_VIDEO_BITRATE_MODE_VBR, + .hfi_id = HFI_PROPERTY_PARAM_VENC_RATE_CONTROL, + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU, + .set = iris_set_bitrate_mode_gen1, + }, + { + .cap_id = FRAME_SKIP_MODE, + .min = V4L2_MPEG_VIDEO_FRAME_SKIP_MODE_DISABLED, + .max = V4L2_MPEG_VIDEO_FRAME_SKIP_MODE_BUF_LIMIT, + .step_or_mask = BIT(V4L2_MPEG_VIDEO_FRAME_SKIP_MODE_DISABLED) | + BIT(V4L2_MPEG_VIDEO_FRAME_SKIP_MODE_BUF_LIMIT), + .value = V4L2_MPEG_VIDEO_FRAME_SKIP_MODE_DISABLED, + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU, + }, + { + .cap_id = FRAME_RC_ENABLE, + .min = 0, + .max = 1, + .step_or_mask = 1, + .value = 1, + }, + { + .cap_id = GOP_SIZE, + .min = 0, + .max = (1 << 16) - 1, + .step_or_mask = 1, + .value = 30, + .set = iris_set_u32 + }, + { + .cap_id = ENTROPY_MODE, + .min = V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CAVLC, + .max = V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CABAC, + .step_or_mask = BIT(V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CAVLC) | + BIT(V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CABAC), + .value = V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CAVLC, + .hfi_id = HFI_PROPERTY_PARAM_VENC_H264_ENTROPY_CONTROL, + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU, + .set = iris_set_entropy_mode_gen1, + }, + { + .cap_id = MIN_FRAME_QP_H264, + .min = MIN_QP_8BIT, + .max = MAX_QP, + .step_or_mask = 1, + .value = MIN_QP_8BIT, + .hfi_id = HFI_PROPERTY_PARAM_VENC_SESSION_QP_RANGE_V2, + .flags = CAP_FLAG_OUTPUT_PORT, + .set = iris_set_qp_range, + }, + { + .cap_id = MIN_FRAME_QP_HEVC, + .min = MIN_QP_8BIT, + .max = MAX_QP_HEVC, + .step_or_mask = 1, + .value = MIN_QP_8BIT, + .hfi_id = HFI_PROPERTY_PARAM_VENC_SESSION_QP_RANGE_V2, + .flags = CAP_FLAG_OUTPUT_PORT, + .set = iris_set_qp_range, + }, + { + .cap_id = MAX_FRAME_QP_H264, + .min = MIN_QP_8BIT, + .max = MAX_QP, + .step_or_mask = 1, + .value = MAX_QP, + .hfi_id = HFI_PROPERTY_PARAM_VENC_SESSION_QP_RANGE_V2, + .flags = CAP_FLAG_OUTPUT_PORT, + .set = iris_set_qp_range, + }, + { + .cap_id = MAX_FRAME_QP_HEVC, + .min = MIN_QP_8BIT, + .max = MAX_QP_HEVC, + .step_or_mask = 1, + .value = MAX_QP_HEVC, + .hfi_id = HFI_PROPERTY_PARAM_VENC_SESSION_QP_RANGE_V2, + .flags = CAP_FLAG_OUTPUT_PORT, + .set = iris_set_qp_range, + }, +}; + static struct platform_inst_caps platform_inst_cap_sm8250 = { .min_frame_width = 128, .max_frame_width = 8192, @@ -40,6 +240,8 @@ static struct platform_inst_caps platform_inst_cap_sm8250 = { .max_mbpf = 138240, .mb_cycles_vsp = 25, .mb_cycles_vpp = 200, + .max_frame_rate = MAXIMUM_FPS, + .max_operating_rate = MAXIMUM_FPS, }; static void iris_set_sm8250_preset_registers(struct iris_core *core) @@ -89,6 +291,14 @@ static const u32 sm8250_vdec_input_config_param_default[] = { HFI_PROPERTY_PARAM_BUFFER_ALLOC_MODE, }; +static const u32 sm8250_venc_input_config_param[] = { + HFI_PROPERTY_CONFIG_FRAME_RATE, + HFI_PROPERTY_PARAM_UNCOMPRESSED_PLANE_ACTUAL_INFO, + HFI_PROPERTY_PARAM_FRAME_SIZE, + HFI_PROPERTY_PARAM_UNCOMPRESSED_FORMAT_SELECT, + HFI_PROPERTY_PARAM_BUFFER_COUNT_ACTUAL, +}; + static const u32 sm8250_dec_ip_int_buf_tbl[] = { BUF_BIN, BUF_SCRATCH_1, @@ -98,10 +308,17 @@ static const u32 sm8250_dec_op_int_buf_tbl[] = { BUF_DPB, }; +static const u32 sm8250_enc_ip_int_buf_tbl[] = { + BUF_BIN, + BUF_SCRATCH_1, + BUF_SCRATCH_2, +}; + struct iris_platform_data sm8250_data = { .get_instance = iris_hfi_gen1_get_instance, .init_hfi_command_ops = &iris_hfi_gen1_command_ops_init, .init_hfi_response_ops = iris_hfi_gen1_response_ops_init, + .get_vpu_buffer_size = iris_vpu_buf_size, .vpu_ops = &iris_vpu2_ops, .set_preset_registers = iris_set_sm8250_preset_registers, .icc_tbl = sm8250_icc_table, @@ -121,20 +338,29 @@ struct iris_platform_data sm8250_data = { .fwname = "qcom/vpu-1.0/venus.mbn", .pas_id = IRIS_PAS_ID, .inst_caps = &platform_inst_cap_sm8250, - .inst_fw_caps = inst_fw_cap_sm8250, - .inst_fw_caps_size = ARRAY_SIZE(inst_fw_cap_sm8250), + .inst_fw_caps_dec = inst_fw_cap_sm8250_dec, + .inst_fw_caps_dec_size = ARRAY_SIZE(inst_fw_cap_sm8250_dec), + .inst_fw_caps_enc = inst_fw_cap_sm8250_enc, + .inst_fw_caps_enc_size = ARRAY_SIZE(inst_fw_cap_sm8250_enc), .tz_cp_config_data = &tz_cp_config_sm8250, .hw_response_timeout = HW_RESPONSE_TIMEOUT_VALUE, .num_vpp_pipe = 4, .max_session_count = 16, .max_core_mbpf = NUM_MBS_8K, - .input_config_params_default = + .max_core_mbps = ((7680 * 4320) / 256) * 60, + .dec_input_config_params_default = sm8250_vdec_input_config_param_default, - .input_config_params_default_size = + .dec_input_config_params_default_size = ARRAY_SIZE(sm8250_vdec_input_config_param_default), + .enc_input_config_params = sm8250_venc_input_config_param, + .enc_input_config_params_size = + ARRAY_SIZE(sm8250_venc_input_config_param), .dec_ip_int_buf_tbl = sm8250_dec_ip_int_buf_tbl, .dec_ip_int_buf_tbl_size = ARRAY_SIZE(sm8250_dec_ip_int_buf_tbl), .dec_op_int_buf_tbl = sm8250_dec_op_int_buf_tbl, .dec_op_int_buf_tbl_size = ARRAY_SIZE(sm8250_dec_op_int_buf_tbl), + + .enc_ip_int_buf_tbl = sm8250_enc_ip_int_buf_tbl, + .enc_ip_int_buf_tbl_size = ARRAY_SIZE(sm8250_enc_ip_int_buf_tbl), }; diff --git a/drivers/media/platform/qcom/iris/iris_platform_sm8750.h b/drivers/media/platform/qcom/iris/iris_platform_sm8750.h new file mode 100644 index 000000000000..719056656a5b --- /dev/null +++ b/drivers/media/platform/qcom/iris/iris_platform_sm8750.h @@ -0,0 +1,22 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2025 Linaro Ltd + */ + +#ifndef __MEDIA_IRIS_PLATFORM_SM8750_H__ +#define __MEDIA_IRIS_PLATFORM_SM8750_H__ + +static const char * const sm8750_clk_reset_table[] = { + "bus0", "bus1", "core", "vcodec0_core" +}; + +static const struct platform_clk_data sm8750_clk_table[] = { + {IRIS_AXI_CLK, "iface" }, + {IRIS_CTRL_CLK, "core" }, + {IRIS_HW_CLK, "vcodec0_core" }, + {IRIS_AXI1_CLK, "iface1" }, + {IRIS_CTRL_FREERUN_CLK, "core_freerun" }, + {IRIS_HW_FREERUN_CLK, "vcodec0_core_freerun" }, +}; + +#endif diff --git a/drivers/media/platform/qcom/iris/iris_probe.c b/drivers/media/platform/qcom/iris/iris_probe.c index 4e6e92357968..00e99be16e08 100644 --- a/drivers/media/platform/qcom/iris/iris_probe.c +++ b/drivers/media/platform/qcom/iris/iris_probe.c @@ -146,7 +146,7 @@ static int iris_init_resources(struct iris_core *core) return iris_init_resets(core); } -static int iris_register_video_device(struct iris_core *core) +static int iris_register_video_device(struct iris_core *core, enum domain_type type) { struct video_device *vdev; int ret; @@ -155,19 +155,29 @@ static int iris_register_video_device(struct iris_core *core) if (!vdev) return -ENOMEM; - strscpy(vdev->name, "qcom-iris-decoder", sizeof(vdev->name)); vdev->release = video_device_release; vdev->fops = core->iris_v4l2_file_ops; - vdev->ioctl_ops = core->iris_v4l2_ioctl_ops; vdev->vfl_dir = VFL_DIR_M2M; vdev->v4l2_dev = &core->v4l2_dev; vdev->device_caps = V4L2_CAP_VIDEO_M2M_MPLANE | V4L2_CAP_STREAMING; + if (type == DECODER) { + strscpy(vdev->name, "qcom-iris-decoder", sizeof(vdev->name)); + vdev->ioctl_ops = core->iris_v4l2_ioctl_ops_dec; + core->vdev_dec = vdev; + } else if (type == ENCODER) { + strscpy(vdev->name, "qcom-iris-encoder", sizeof(vdev->name)); + vdev->ioctl_ops = core->iris_v4l2_ioctl_ops_enc; + core->vdev_enc = vdev; + } else { + ret = -EINVAL; + goto err_vdev_release; + } + ret = video_register_device(vdev, VFL_TYPE_VIDEO, -1); if (ret) goto err_vdev_release; - core->vdev_dec = vdev; video_set_drvdata(vdev, core); return 0; @@ -189,6 +199,7 @@ static void iris_remove(struct platform_device *pdev) iris_core_deinit(core); video_unregister_device(core->vdev_dec); + video_unregister_device(core->vdev_enc); v4l2_device_unregister(&core->v4l2_dev); @@ -258,17 +269,21 @@ static int iris_probe(struct platform_device *pdev) if (ret) return ret; - ret = iris_register_video_device(core); + ret = iris_register_video_device(core, DECODER); if (ret) goto err_v4l2_unreg; + ret = iris_register_video_device(core, ENCODER); + if (ret) + goto err_vdev_unreg_dec; + platform_set_drvdata(pdev, core); dma_mask = core->iris_platform_data->dma_mask; ret = dma_set_mask_and_coherent(dev, dma_mask); if (ret) - goto err_vdev_unreg; + goto err_vdev_unreg_enc; dma_set_max_seg_size(&pdev->dev, DMA_BIT_MASK(32)); dma_set_seg_boundary(&pdev->dev, DMA_BIT_MASK(32)); @@ -277,11 +292,13 @@ static int iris_probe(struct platform_device *pdev) pm_runtime_use_autosuspend(core->dev); ret = devm_pm_runtime_enable(core->dev); if (ret) - goto err_vdev_unreg; + goto err_vdev_unreg_enc; return 0; -err_vdev_unreg: +err_vdev_unreg_enc: + video_unregister_device(core->vdev_enc); +err_vdev_unreg_dec: video_unregister_device(core->vdev_dec); err_v4l2_unreg: v4l2_device_unregister(&core->v4l2_dev); @@ -353,6 +370,10 @@ static const struct of_device_id iris_dt_match[] = { .compatible = "qcom,sm8650-iris", .data = &sm8650_data, }, + { + .compatible = "qcom,sm8750-iris", + .data = &sm8750_data, + }, { }, }; MODULE_DEVICE_TABLE(of, iris_dt_match); diff --git a/drivers/media/platform/qcom/iris/iris_state.c b/drivers/media/platform/qcom/iris/iris_state.c index 104e1687ad39..d14472414750 100644 --- a/drivers/media/platform/qcom/iris/iris_state.c +++ b/drivers/media/platform/qcom/iris/iris_state.c @@ -122,7 +122,8 @@ static bool iris_inst_allow_sub_state(struct iris_inst *inst, enum iris_inst_sub return false; case IRIS_INST_OUTPUT_STREAMING: if (sub_state & (IRIS_INST_SUB_DRC_LAST | - IRIS_INST_SUB_DRAIN_LAST | IRIS_INST_SUB_OUTPUT_PAUSE)) + IRIS_INST_SUB_DRAIN_LAST | IRIS_INST_SUB_OUTPUT_PAUSE | + IRIS_INST_SUB_LOAD_RESOURCES)) return true; return false; case IRIS_INST_STREAMING: @@ -251,7 +252,7 @@ bool iris_drc_pending(struct iris_inst *inst) inst->sub_state & IRIS_INST_SUB_DRC_LAST; } -static inline bool iris_drain_pending(struct iris_inst *inst) +bool iris_drain_pending(struct iris_inst *inst) { return inst->sub_state & IRIS_INST_SUB_DRAIN && inst->sub_state & IRIS_INST_SUB_DRAIN_LAST; @@ -262,11 +263,11 @@ bool iris_allow_cmd(struct iris_inst *inst, u32 cmd) struct vb2_queue *src_q = v4l2_m2m_get_src_vq(inst->m2m_ctx); struct vb2_queue *dst_q = v4l2_m2m_get_dst_vq(inst->m2m_ctx); - if (cmd == V4L2_DEC_CMD_START) { + if (cmd == V4L2_DEC_CMD_START || cmd == V4L2_ENC_CMD_START) { if (vb2_is_streaming(src_q) || vb2_is_streaming(dst_q)) if (iris_drc_pending(inst) || iris_drain_pending(inst)) return true; - } else if (cmd == V4L2_DEC_CMD_STOP) { + } else if (cmd == V4L2_DEC_CMD_STOP || cmd == V4L2_ENC_CMD_STOP) { if (vb2_is_streaming(src_q)) if (inst->sub_state != IRIS_INST_SUB_DRAIN) return true; diff --git a/drivers/media/platform/qcom/iris/iris_state.h b/drivers/media/platform/qcom/iris/iris_state.h index e718386dbe04..b09fa54cf17e 100644 --- a/drivers/media/platform/qcom/iris/iris_state.h +++ b/drivers/media/platform/qcom/iris/iris_state.h @@ -141,5 +141,6 @@ int iris_inst_sub_state_change_drc_last(struct iris_inst *inst); int iris_inst_sub_state_change_pause(struct iris_inst *inst, u32 plane); bool iris_allow_cmd(struct iris_inst *inst, u32 cmd); bool iris_drc_pending(struct iris_inst *inst); +bool iris_drain_pending(struct iris_inst *inst); #endif diff --git a/drivers/media/platform/qcom/iris/iris_utils.c b/drivers/media/platform/qcom/iris/iris_utils.c index 83c70d6a2d90..85c70a62b1fd 100644 --- a/drivers/media/platform/qcom/iris/iris_utils.c +++ b/drivers/media/platform/qcom/iris/iris_utils.c @@ -88,3 +88,39 @@ struct iris_inst *iris_get_instance(struct iris_core *core, u32 session_id) mutex_unlock(&core->lock); return NULL; } + +int iris_check_core_mbpf(struct iris_inst *inst) +{ + struct iris_core *core = inst->core; + struct iris_inst *instance; + u32 total_mbpf = 0; + + mutex_lock(&core->lock); + list_for_each_entry(instance, &core->instances, list) + total_mbpf += iris_get_mbpf(instance); + mutex_unlock(&core->lock); + + if (total_mbpf > core->iris_platform_data->max_core_mbpf) + return -ENOMEM; + + return 0; +} + +int iris_check_core_mbps(struct iris_inst *inst) +{ + struct iris_core *core = inst->core; + struct iris_inst *instance; + u32 total_mbps = 0, fps = 0; + + mutex_lock(&core->lock); + list_for_each_entry(instance, &core->instances, list) { + fps = max(instance->frame_rate, instance->operating_rate); + total_mbps += iris_get_mbpf(instance) * fps; + } + mutex_unlock(&core->lock); + + if (total_mbps > core->iris_platform_data->max_core_mbps) + return -ENOMEM; + + return 0; +} diff --git a/drivers/media/platform/qcom/iris/iris_utils.h b/drivers/media/platform/qcom/iris/iris_utils.h index 49869cf7a376..75740181122f 100644 --- a/drivers/media/platform/qcom/iris/iris_utils.h +++ b/drivers/media/platform/qcom/iris/iris_utils.h @@ -49,5 +49,7 @@ struct iris_inst *iris_get_instance(struct iris_core *core, u32 session_id); void iris_helper_buffers_done(struct iris_inst *inst, unsigned int type, enum vb2_buffer_state state); int iris_wait_for_session_response(struct iris_inst *inst, bool is_flush); +int iris_check_core_mbpf(struct iris_inst *inst); +int iris_check_core_mbps(struct iris_inst *inst); #endif diff --git a/drivers/media/platform/qcom/iris/iris_vb2.c b/drivers/media/platform/qcom/iris/iris_vb2.c index 8b17c7c39487..139b821f7952 100644 --- a/drivers/media/platform/qcom/iris/iris_vb2.c +++ b/drivers/media/platform/qcom/iris/iris_vb2.c @@ -7,28 +7,13 @@ #include <media/v4l2-event.h> #include <media/v4l2-mem2mem.h> +#include "iris_common.h" #include "iris_instance.h" #include "iris_vb2.h" #include "iris_vdec.h" +#include "iris_venc.h" #include "iris_power.h" -static int iris_check_core_mbpf(struct iris_inst *inst) -{ - struct iris_core *core = inst->core; - struct iris_inst *instance; - u32 total_mbpf = 0; - - mutex_lock(&core->lock); - list_for_each_entry(instance, &core->instances, list) - total_mbpf += iris_get_mbpf(instance); - mutex_unlock(&core->lock); - - if (total_mbpf > core->iris_platform_data->max_core_mbpf) - return -ENOMEM; - - return 0; -} - static int iris_check_inst_mbpf(struct iris_inst *inst) { struct platform_inst_caps *caps; @@ -173,9 +158,6 @@ int iris_vb2_start_streaming(struct vb2_queue *q, unsigned int count) inst = vb2_get_drv_priv(q); - if (V4L2_TYPE_IS_CAPTURE(q->type) && inst->state == IRIS_INST_INIT) - return 0; - mutex_lock(&inst->lock); if (inst->state == IRIS_INST_ERROR) { ret = -EBUSY; @@ -194,16 +176,35 @@ int iris_vb2_start_streaming(struct vb2_queue *q, unsigned int count) if (ret) goto error; - if (V4L2_TYPE_IS_OUTPUT(q->type)) - ret = iris_vdec_streamon_input(inst); - else if (V4L2_TYPE_IS_CAPTURE(q->type)) - ret = iris_vdec_streamon_output(inst); + if (V4L2_TYPE_IS_OUTPUT(q->type)) { + if (inst->domain == DECODER) + ret = iris_vdec_streamon_input(inst); + else + ret = iris_venc_streamon_input(inst); + } else if (V4L2_TYPE_IS_CAPTURE(q->type)) { + if (inst->domain == DECODER) + ret = iris_vdec_streamon_output(inst); + else + ret = iris_venc_streamon_output(inst); + } if (ret) goto error; buf_type = iris_v4l2_type_to_driver(q->type); - ret = iris_queue_deferred_buffers(inst, buf_type); + if (inst->domain == DECODER) { + if (inst->state == IRIS_INST_STREAMING) + ret = iris_queue_internal_deferred_buffers(inst, BUF_DPB); + if (!ret) + ret = iris_queue_deferred_buffers(inst, buf_type); + } else { + if (inst->state == IRIS_INST_STREAMING) { + ret = iris_queue_deferred_buffers(inst, BUF_INPUT); + if (!ret) + ret = iris_queue_deferred_buffers(inst, BUF_OUTPUT); + } + } + if (ret) goto error; @@ -235,7 +236,7 @@ void iris_vb2_stop_streaming(struct vb2_queue *q) !V4L2_TYPE_IS_CAPTURE(q->type)) goto exit; - ret = iris_vdec_session_streamoff(inst, q->type); + ret = iris_session_streamoff(inst, q->type); if (ret) goto exit; @@ -326,7 +327,10 @@ void iris_vb2_buf_queue(struct vb2_buffer *vb2) v4l2_m2m_buf_queue(m2m_ctx, vbuf); - ret = iris_vdec_qbuf(inst, vbuf); + if (inst->domain == DECODER) + ret = iris_vdec_qbuf(inst, vbuf); + else + ret = iris_venc_qbuf(inst, vbuf); exit: if (ret) { diff --git a/drivers/media/platform/qcom/iris/iris_vdec.c b/drivers/media/platform/qcom/iris/iris_vdec.c index d670b51c5839..ae13c3e1b426 100644 --- a/drivers/media/platform/qcom/iris/iris_vdec.c +++ b/drivers/media/platform/qcom/iris/iris_vdec.c @@ -7,14 +7,13 @@ #include <media/v4l2-mem2mem.h> #include "iris_buffer.h" +#include "iris_common.h" #include "iris_ctrls.h" #include "iris_instance.h" #include "iris_power.h" #include "iris_vdec.h" #include "iris_vpu_buffer.h" -#define DEFAULT_WIDTH 320 -#define DEFAULT_HEIGHT 240 #define DEFAULT_CODEC_ALIGNMENT 16 int iris_vdec_inst_init(struct iris_inst *inst) @@ -56,7 +55,7 @@ int iris_vdec_inst_init(struct iris_inst *inst) inst->buffers[BUF_OUTPUT].min_count = iris_vpu_buf_count(inst, BUF_OUTPUT); inst->buffers[BUF_OUTPUT].size = f->fmt.pix_mp.plane_fmt[0].sizeimage; - memcpy(&inst->fw_caps[0], &core->inst_fw_caps[0], + memcpy(&inst->fw_caps[0], &core->inst_fw_caps_dec[0], INST_FW_CAP_MAX * sizeof(struct platform_inst_fw_cap)); return iris_ctrls_init(inst); @@ -158,7 +157,7 @@ int iris_vdec_try_fmt(struct iris_inst *inst, struct v4l2_format *f) } break; case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: - if (!fmt) { + if (f->fmt.pix_mp.pixelformat != V4L2_PIX_FMT_NV12) { f_inst = inst->fmt_dst; f->fmt.pix_mp.pixelformat = f_inst->fmt.pix_mp.pixelformat; f->fmt.pix_mp.width = f_inst->fmt.pix_mp.width; @@ -265,6 +264,19 @@ int iris_vdec_s_fmt(struct iris_inst *inst, struct v4l2_format *f) return 0; } +int iris_vdec_validate_format(struct iris_inst *inst, u32 pixelformat) +{ + const struct iris_fmt *fmt = NULL; + + if (pixelformat != V4L2_PIX_FMT_NV12) { + fmt = find_format(inst, pixelformat, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); + if (!fmt) + return -EINVAL; + } + + return 0; +} + int iris_vdec_subscribe_event(struct iris_inst *inst, const struct v4l2_event_subscription *sub) { int ret = 0; @@ -301,125 +313,6 @@ void iris_vdec_src_change(struct iris_inst *inst) v4l2_event_queue_fh(&inst->fh, &event); } - -static void iris_vdec_flush_deferred_buffers(struct iris_inst *inst, - enum iris_buffer_type type) -{ - struct v4l2_m2m_ctx *m2m_ctx = inst->m2m_ctx; - struct v4l2_m2m_buffer *buffer, *n; - struct iris_buffer *buf; - - if (type == BUF_INPUT) { - v4l2_m2m_for_each_src_buf_safe(m2m_ctx, buffer, n) { - buf = to_iris_buffer(&buffer->vb); - if (buf->attr & BUF_ATTR_DEFERRED) { - if (!(buf->attr & BUF_ATTR_BUFFER_DONE)) { - buf->attr |= BUF_ATTR_BUFFER_DONE; - buf->data_size = 0; - iris_vb2_buffer_done(inst, buf); - } - } - } - } else { - v4l2_m2m_for_each_dst_buf_safe(m2m_ctx, buffer, n) { - buf = to_iris_buffer(&buffer->vb); - if (buf->attr & BUF_ATTR_DEFERRED) { - if (!(buf->attr & BUF_ATTR_BUFFER_DONE)) { - buf->attr |= BUF_ATTR_BUFFER_DONE; - buf->data_size = 0; - iris_vb2_buffer_done(inst, buf); - } - } - } - } -} - -static void iris_vdec_kill_session(struct iris_inst *inst) -{ - const struct iris_hfi_command_ops *hfi_ops = inst->core->hfi_ops; - - if (!inst->session_id) - return; - - hfi_ops->session_close(inst); - iris_inst_change_state(inst, IRIS_INST_ERROR); -} - -int iris_vdec_session_streamoff(struct iris_inst *inst, u32 plane) -{ - const struct iris_hfi_command_ops *hfi_ops = inst->core->hfi_ops; - enum iris_buffer_type buffer_type; - int ret; - - switch (plane) { - case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: - buffer_type = BUF_INPUT; - break; - case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: - buffer_type = BUF_OUTPUT; - break; - default: - return -EINVAL; - } - - ret = hfi_ops->session_stop(inst, plane); - if (ret) - goto error; - - ret = iris_inst_state_change_streamoff(inst, plane); - if (ret) - goto error; - - iris_vdec_flush_deferred_buffers(inst, buffer_type); - - return 0; - -error: - iris_vdec_kill_session(inst); - iris_vdec_flush_deferred_buffers(inst, buffer_type); - - return ret; -} - -static int iris_vdec_process_streamon_input(struct iris_inst *inst) -{ - const struct iris_hfi_command_ops *hfi_ops = inst->core->hfi_ops; - enum iris_inst_sub_state set_sub_state = 0; - int ret; - - iris_scale_power(inst); - - ret = hfi_ops->session_start(inst, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); - if (ret) - return ret; - - if (inst->sub_state & IRIS_INST_SUB_INPUT_PAUSE) { - ret = iris_inst_change_sub_state(inst, IRIS_INST_SUB_INPUT_PAUSE, 0); - if (ret) - return ret; - } - - if (inst->sub_state & IRIS_INST_SUB_DRC || - inst->sub_state & IRIS_INST_SUB_DRAIN || - inst->sub_state & IRIS_INST_SUB_FIRST_IPSC) { - if (!(inst->sub_state & IRIS_INST_SUB_INPUT_PAUSE)) { - if (hfi_ops->session_pause) { - ret = hfi_ops->session_pause(inst, - V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); - if (ret) - return ret; - } - set_sub_state = IRIS_INST_SUB_INPUT_PAUSE; - } - } - - ret = iris_inst_state_change_streamon(inst, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); - if (ret) - return ret; - - return iris_inst_change_sub_state(inst, 0, set_sub_state); -} - int iris_vdec_streamon_input(struct iris_inst *inst) { int ret; @@ -428,7 +321,7 @@ int iris_vdec_streamon_input(struct iris_inst *inst) if (ret) return ret; - ret = iris_alloc_and_queue_persist_bufs(inst); + ret = iris_alloc_and_queue_persist_bufs(inst, BUF_PERSIST); if (ret) return ret; @@ -446,71 +339,7 @@ int iris_vdec_streamon_input(struct iris_inst *inst) if (ret) return ret; - return iris_vdec_process_streamon_input(inst); -} - -static int iris_vdec_process_streamon_output(struct iris_inst *inst) -{ - const struct iris_hfi_command_ops *hfi_ops = inst->core->hfi_ops; - bool drain_active = false, drc_active = false; - enum iris_inst_sub_state clear_sub_state = 0; - int ret = 0; - - iris_scale_power(inst); - - drain_active = inst->sub_state & IRIS_INST_SUB_DRAIN && - inst->sub_state & IRIS_INST_SUB_DRAIN_LAST; - - drc_active = inst->sub_state & IRIS_INST_SUB_DRC && - inst->sub_state & IRIS_INST_SUB_DRC_LAST; - - if (drc_active) - clear_sub_state = IRIS_INST_SUB_DRC | IRIS_INST_SUB_DRC_LAST; - else if (drain_active) - clear_sub_state = IRIS_INST_SUB_DRAIN | IRIS_INST_SUB_DRAIN_LAST; - - if (inst->sub_state & IRIS_INST_SUB_INPUT_PAUSE) { - ret = iris_alloc_and_queue_input_int_bufs(inst); - if (ret) - return ret; - ret = iris_set_stage(inst, STAGE); - if (ret) - return ret; - ret = iris_set_pipe(inst, PIPE); - if (ret) - return ret; - } - - if (inst->state == IRIS_INST_INPUT_STREAMING && - inst->sub_state & IRIS_INST_SUB_INPUT_PAUSE) { - if (!drain_active) - ret = hfi_ops->session_resume_drc(inst, - V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); - else if (hfi_ops->session_resume_drain) - ret = hfi_ops->session_resume_drain(inst, - V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); - if (ret) - return ret; - clear_sub_state |= IRIS_INST_SUB_INPUT_PAUSE; - } - - if (inst->sub_state & IRIS_INST_SUB_FIRST_IPSC) - clear_sub_state |= IRIS_INST_SUB_FIRST_IPSC; - - ret = hfi_ops->session_start(inst, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE); - if (ret) - return ret; - - if (inst->sub_state & IRIS_INST_SUB_OUTPUT_PAUSE) - clear_sub_state |= IRIS_INST_SUB_OUTPUT_PAUSE; - - ret = iris_inst_state_change_streamon(inst, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE); - if (ret) - return ret; - - inst->last_buffer_dequeued = false; - - return iris_inst_change_sub_state(inst, clear_sub_state, 0); + return iris_process_streamon_input(inst); } int iris_vdec_streamon_output(struct iris_inst *inst) @@ -532,7 +361,7 @@ int iris_vdec_streamon_output(struct iris_inst *inst) if (ret) return ret; - ret = iris_vdec_process_streamon_output(inst); + ret = iris_process_streamon_output(inst); if (ret) goto error; @@ -543,49 +372,11 @@ int iris_vdec_streamon_output(struct iris_inst *inst) return ret; error: - iris_vdec_session_streamoff(inst, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE); + iris_session_streamoff(inst, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE); return ret; } -static int -iris_vdec_vb2_buffer_to_driver(struct vb2_buffer *vb2, struct iris_buffer *buf) -{ - struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb2); - - buf->type = iris_v4l2_type_to_driver(vb2->type); - buf->index = vb2->index; - buf->fd = vb2->planes[0].m.fd; - buf->buffer_size = vb2->planes[0].length; - buf->data_offset = vb2->planes[0].data_offset; - buf->data_size = vb2->planes[0].bytesused - vb2->planes[0].data_offset; - buf->flags = vbuf->flags; - buf->timestamp = vb2->timestamp; - buf->attr = 0; - - return 0; -} - -static void -iris_set_ts_metadata(struct iris_inst *inst, struct vb2_v4l2_buffer *vbuf) -{ - u32 mask = V4L2_BUF_FLAG_TIMECODE | V4L2_BUF_FLAG_TSTAMP_SRC_MASK; - struct vb2_buffer *vb = &vbuf->vb2_buf; - u64 ts_us = vb->timestamp; - - if (inst->metadata_idx >= ARRAY_SIZE(inst->tss)) - inst->metadata_idx = 0; - - do_div(ts_us, NSEC_PER_USEC); - - inst->tss[inst->metadata_idx].flags = vbuf->flags & mask; - inst->tss[inst->metadata_idx].tc = vbuf->timecode; - inst->tss[inst->metadata_idx].ts_us = ts_us; - inst->tss[inst->metadata_idx].ts_ns = vb->timestamp; - - inst->metadata_idx++; -} - int iris_vdec_qbuf(struct iris_inst *inst, struct vb2_v4l2_buffer *vbuf) { struct iris_buffer *buf = to_iris_buffer(vbuf); @@ -593,7 +384,7 @@ int iris_vdec_qbuf(struct iris_inst *inst, struct vb2_v4l2_buffer *vbuf) struct vb2_queue *q; int ret; - ret = iris_vdec_vb2_buffer_to_driver(vb2, buf); + ret = iris_vb2_buffer_to_driver(vb2, buf); if (ret) return ret; diff --git a/drivers/media/platform/qcom/iris/iris_vdec.h b/drivers/media/platform/qcom/iris/iris_vdec.h index cd7aab66dc7c..ec1ce55d1375 100644 --- a/drivers/media/platform/qcom/iris/iris_vdec.h +++ b/drivers/media/platform/qcom/iris/iris_vdec.h @@ -8,22 +8,12 @@ struct iris_inst; -enum iris_fmt_type { - IRIS_FMT_H264, - IRIS_FMT_HEVC, - IRIS_FMT_VP9, -}; - -struct iris_fmt { - u32 pixfmt; - u32 type; -}; - int iris_vdec_inst_init(struct iris_inst *inst); void iris_vdec_inst_deinit(struct iris_inst *inst); int iris_vdec_enum_fmt(struct iris_inst *inst, struct v4l2_fmtdesc *f); int iris_vdec_try_fmt(struct iris_inst *inst, struct v4l2_format *f); int iris_vdec_s_fmt(struct iris_inst *inst, struct v4l2_format *f); +int iris_vdec_validate_format(struct iris_inst *inst, u32 pixelformat); int iris_vdec_subscribe_event(struct iris_inst *inst, const struct v4l2_event_subscription *sub); void iris_vdec_src_change(struct iris_inst *inst); int iris_vdec_streamon_input(struct iris_inst *inst); @@ -31,6 +21,5 @@ int iris_vdec_streamon_output(struct iris_inst *inst); int iris_vdec_qbuf(struct iris_inst *inst, struct vb2_v4l2_buffer *vbuf); int iris_vdec_start_cmd(struct iris_inst *inst); int iris_vdec_stop_cmd(struct iris_inst *inst); -int iris_vdec_session_streamoff(struct iris_inst *inst, u32 plane); #endif diff --git a/drivers/media/platform/qcom/iris/iris_venc.c b/drivers/media/platform/qcom/iris/iris_venc.c new file mode 100644 index 000000000000..099bd5ed4ae0 --- /dev/null +++ b/drivers/media/platform/qcom/iris/iris_venc.c @@ -0,0 +1,579 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2022-2025 Qualcomm Innovation Center, Inc. All rights reserved. + */ + +#include <media/v4l2-event.h> +#include <media/v4l2-mem2mem.h> + +#include "iris_buffer.h" +#include "iris_common.h" +#include "iris_ctrls.h" +#include "iris_instance.h" +#include "iris_power.h" +#include "iris_venc.h" +#include "iris_vpu_buffer.h" + +int iris_venc_inst_init(struct iris_inst *inst) +{ + struct iris_core *core = inst->core; + struct v4l2_format *f; + + inst->fmt_src = kzalloc(sizeof(*inst->fmt_src), GFP_KERNEL); + inst->fmt_dst = kzalloc(sizeof(*inst->fmt_dst), GFP_KERNEL); + if (!inst->fmt_src || !inst->fmt_dst) { + kfree(inst->fmt_src); + kfree(inst->fmt_dst); + return -ENOMEM; + } + + f = inst->fmt_dst; + f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; + f->fmt.pix_mp.width = DEFAULT_WIDTH; + f->fmt.pix_mp.height = DEFAULT_HEIGHT; + f->fmt.pix_mp.pixelformat = V4L2_PIX_FMT_H264; + inst->codec = f->fmt.pix_mp.pixelformat; + f->fmt.pix_mp.num_planes = 1; + f->fmt.pix_mp.plane_fmt[0].bytesperline = 0; + f->fmt.pix_mp.plane_fmt[0].sizeimage = iris_get_buffer_size(inst, BUF_OUTPUT); + f->fmt.pix_mp.field = V4L2_FIELD_NONE; + f->fmt.pix_mp.colorspace = V4L2_COLORSPACE_DEFAULT; + f->fmt.pix_mp.xfer_func = V4L2_XFER_FUNC_DEFAULT; + f->fmt.pix_mp.ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT; + f->fmt.pix_mp.quantization = V4L2_QUANTIZATION_DEFAULT; + inst->buffers[BUF_OUTPUT].min_count = iris_vpu_buf_count(inst, BUF_OUTPUT); + inst->buffers[BUF_OUTPUT].size = f->fmt.pix_mp.plane_fmt[0].sizeimage; + + f = inst->fmt_src; + f->type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; + f->fmt.pix_mp.pixelformat = V4L2_PIX_FMT_NV12; + f->fmt.pix_mp.width = ALIGN(DEFAULT_WIDTH, 128); + f->fmt.pix_mp.height = ALIGN(DEFAULT_HEIGHT, 32); + f->fmt.pix_mp.num_planes = 1; + f->fmt.pix_mp.plane_fmt[0].bytesperline = ALIGN(DEFAULT_WIDTH, 128); + f->fmt.pix_mp.plane_fmt[0].sizeimage = iris_get_buffer_size(inst, BUF_INPUT); + f->fmt.pix_mp.field = V4L2_FIELD_NONE; + f->fmt.pix_mp.colorspace = V4L2_COLORSPACE_DEFAULT; + f->fmt.pix_mp.xfer_func = V4L2_XFER_FUNC_DEFAULT; + f->fmt.pix_mp.ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT; + f->fmt.pix_mp.quantization = V4L2_QUANTIZATION_DEFAULT; + inst->buffers[BUF_INPUT].min_count = iris_vpu_buf_count(inst, BUF_INPUT); + inst->buffers[BUF_INPUT].size = f->fmt.pix_mp.plane_fmt[0].sizeimage; + + inst->crop.left = 0; + inst->crop.top = 0; + inst->crop.width = f->fmt.pix_mp.width; + inst->crop.height = f->fmt.pix_mp.height; + + inst->operating_rate = DEFAULT_FPS; + inst->frame_rate = DEFAULT_FPS; + + memcpy(&inst->fw_caps[0], &core->inst_fw_caps_enc[0], + INST_FW_CAP_MAX * sizeof(struct platform_inst_fw_cap)); + + return iris_ctrls_init(inst); +} + +void iris_venc_inst_deinit(struct iris_inst *inst) +{ + kfree(inst->fmt_dst); + kfree(inst->fmt_src); +} + +static const struct iris_fmt iris_venc_formats[] = { + [IRIS_FMT_H264] = { + .pixfmt = V4L2_PIX_FMT_H264, + .type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE, + }, + [IRIS_FMT_HEVC] = { + .pixfmt = V4L2_PIX_FMT_HEVC, + .type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE, + }, +}; + +static const struct iris_fmt * +find_format(struct iris_inst *inst, u32 pixfmt, u32 type) +{ + const struct iris_fmt *fmt = iris_venc_formats; + unsigned int size = ARRAY_SIZE(iris_venc_formats); + unsigned int i; + + for (i = 0; i < size; i++) { + if (fmt[i].pixfmt == pixfmt) + break; + } + + if (i == size || fmt[i].type != type) + return NULL; + + return &fmt[i]; +} + +static const struct iris_fmt * +find_format_by_index(struct iris_inst *inst, u32 index, u32 type) +{ + const struct iris_fmt *fmt = iris_venc_formats; + unsigned int size = ARRAY_SIZE(iris_venc_formats); + + if (index >= size || fmt[index].type != type) + return NULL; + + return &fmt[index]; +} + +int iris_venc_enum_fmt(struct iris_inst *inst, struct v4l2_fmtdesc *f) +{ + const struct iris_fmt *fmt; + + switch (f->type) { + case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: + if (f->index) + return -EINVAL; + f->pixelformat = V4L2_PIX_FMT_NV12; + break; + case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: + fmt = find_format_by_index(inst, f->index, f->type); + if (!fmt) + return -EINVAL; + + f->pixelformat = fmt->pixfmt; + f->flags = V4L2_FMT_FLAG_COMPRESSED | V4L2_FMT_FLAG_ENC_CAP_FRAME_INTERVAL; + break; + default: + return -EINVAL; + } + + return 0; +} + +int iris_venc_try_fmt(struct iris_inst *inst, struct v4l2_format *f) +{ + struct v4l2_pix_format_mplane *pixmp = &f->fmt.pix_mp; + const struct iris_fmt *fmt; + struct v4l2_format *f_inst; + + memset(pixmp->reserved, 0, sizeof(pixmp->reserved)); + fmt = find_format(inst, pixmp->pixelformat, f->type); + switch (f->type) { + case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: + if (f->fmt.pix_mp.pixelformat != V4L2_PIX_FMT_NV12) { + f_inst = inst->fmt_src; + f->fmt.pix_mp.width = f_inst->fmt.pix_mp.width; + f->fmt.pix_mp.height = f_inst->fmt.pix_mp.height; + f->fmt.pix_mp.pixelformat = f_inst->fmt.pix_mp.pixelformat; + } + break; + case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: + if (!fmt) { + f_inst = inst->fmt_dst; + f->fmt.pix_mp.width = f_inst->fmt.pix_mp.width; + f->fmt.pix_mp.height = f_inst->fmt.pix_mp.height; + f->fmt.pix_mp.pixelformat = f_inst->fmt.pix_mp.pixelformat; + } + break; + default: + return -EINVAL; + } + + if (pixmp->field == V4L2_FIELD_ANY) + pixmp->field = V4L2_FIELD_NONE; + + pixmp->num_planes = 1; + + return 0; +} + +static int iris_venc_s_fmt_output(struct iris_inst *inst, struct v4l2_format *f) +{ + struct v4l2_format *fmt; + + iris_venc_try_fmt(inst, f); + + if (!(find_format(inst, f->fmt.pix_mp.pixelformat, f->type))) + return -EINVAL; + + fmt = inst->fmt_dst; + fmt->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; + fmt->fmt.pix_mp.num_planes = 1; + fmt->fmt.pix_mp.plane_fmt[0].bytesperline = 0; + fmt->fmt.pix_mp.plane_fmt[0].sizeimage = iris_get_buffer_size(inst, BUF_OUTPUT); + + if (f->fmt.pix_mp.colorspace != V4L2_COLORSPACE_DEFAULT && + f->fmt.pix_mp.colorspace != V4L2_COLORSPACE_REC709) + f->fmt.pix_mp.colorspace = V4L2_COLORSPACE_DEFAULT; + fmt->fmt.pix_mp.colorspace = f->fmt.pix_mp.colorspace; + fmt->fmt.pix_mp.xfer_func = f->fmt.pix_mp.xfer_func; + fmt->fmt.pix_mp.ycbcr_enc = f->fmt.pix_mp.ycbcr_enc; + fmt->fmt.pix_mp.quantization = f->fmt.pix_mp.quantization; + + inst->buffers[BUF_OUTPUT].min_count = iris_vpu_buf_count(inst, BUF_OUTPUT); + inst->buffers[BUF_OUTPUT].size = fmt->fmt.pix_mp.plane_fmt[0].sizeimage; + fmt->fmt.pix_mp.pixelformat = f->fmt.pix_mp.pixelformat; + inst->codec = f->fmt.pix_mp.pixelformat; + memcpy(f, fmt, sizeof(struct v4l2_format)); + + return 0; +} + +static int iris_venc_s_fmt_input(struct iris_inst *inst, struct v4l2_format *f) +{ + struct v4l2_format *fmt, *output_fmt; + + iris_venc_try_fmt(inst, f); + + if (f->fmt.pix_mp.pixelformat != V4L2_PIX_FMT_NV12) + return -EINVAL; + + fmt = inst->fmt_src; + fmt->type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; + fmt->fmt.pix_mp.width = ALIGN(f->fmt.pix_mp.width, 128); + fmt->fmt.pix_mp.height = ALIGN(f->fmt.pix_mp.height, 32); + fmt->fmt.pix_mp.num_planes = 1; + fmt->fmt.pix_mp.pixelformat = f->fmt.pix_mp.pixelformat; + fmt->fmt.pix_mp.plane_fmt[0].bytesperline = ALIGN(f->fmt.pix_mp.width, 128); + fmt->fmt.pix_mp.plane_fmt[0].sizeimage = iris_get_buffer_size(inst, BUF_INPUT); + + fmt->fmt.pix_mp.colorspace = f->fmt.pix_mp.colorspace; + fmt->fmt.pix_mp.xfer_func = f->fmt.pix_mp.xfer_func; + fmt->fmt.pix_mp.ycbcr_enc = f->fmt.pix_mp.ycbcr_enc; + fmt->fmt.pix_mp.quantization = f->fmt.pix_mp.quantization; + + output_fmt = inst->fmt_dst; + output_fmt->fmt.pix_mp.width = fmt->fmt.pix_mp.width; + output_fmt->fmt.pix_mp.height = fmt->fmt.pix_mp.height; + output_fmt->fmt.pix_mp.colorspace = fmt->fmt.pix_mp.colorspace; + output_fmt->fmt.pix_mp.xfer_func = fmt->fmt.pix_mp.xfer_func; + output_fmt->fmt.pix_mp.ycbcr_enc = fmt->fmt.pix_mp.ycbcr_enc; + output_fmt->fmt.pix_mp.quantization = fmt->fmt.pix_mp.quantization; + + inst->buffers[BUF_INPUT].min_count = iris_vpu_buf_count(inst, BUF_INPUT); + inst->buffers[BUF_INPUT].size = fmt->fmt.pix_mp.plane_fmt[0].sizeimage; + + if (f->fmt.pix_mp.width != inst->crop.width || + f->fmt.pix_mp.height != inst->crop.height) { + inst->crop.top = 0; + inst->crop.left = 0; + inst->crop.width = fmt->fmt.pix_mp.width; + inst->crop.height = fmt->fmt.pix_mp.height; + + iris_venc_s_fmt_output(inst, output_fmt); + } + + memcpy(f, fmt, sizeof(struct v4l2_format)); + + return 0; +} + +int iris_venc_s_fmt(struct iris_inst *inst, struct v4l2_format *f) +{ + struct vb2_queue *q; + + q = v4l2_m2m_get_vq(inst->m2m_ctx, f->type); + if (!q) + return -EINVAL; + + if (vb2_is_busy(q)) + return -EBUSY; + + switch (f->type) { + case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: + return iris_venc_s_fmt_input(inst, f); + case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: + return iris_venc_s_fmt_output(inst, f); + default: + return -EINVAL; + } +} + +int iris_venc_validate_format(struct iris_inst *inst, u32 pixelformat) +{ + const struct iris_fmt *fmt = NULL; + + if (pixelformat != V4L2_PIX_FMT_NV12) { + fmt = find_format(inst, pixelformat, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE); + if (!fmt) + return -EINVAL; + } + + return 0; +} + +int iris_venc_subscribe_event(struct iris_inst *inst, + const struct v4l2_event_subscription *sub) +{ + switch (sub->type) { + case V4L2_EVENT_EOS: + return v4l2_event_subscribe(&inst->fh, sub, 0, NULL); + case V4L2_EVENT_CTRL: + return v4l2_ctrl_subscribe_event(&inst->fh, sub); + default: + return -EINVAL; + } +} + +int iris_venc_s_selection(struct iris_inst *inst, struct v4l2_selection *s) +{ + if (s->type != V4L2_BUF_TYPE_VIDEO_OUTPUT) + return -EINVAL; + + switch (s->target) { + case V4L2_SEL_TGT_CROP: + s->r.left = 0; + s->r.top = 0; + + if (s->r.width > inst->fmt_src->fmt.pix_mp.width || + s->r.height > inst->fmt_src->fmt.pix_mp.height) + return -EINVAL; + + inst->crop.left = s->r.left; + inst->crop.top = s->r.top; + inst->crop.width = s->r.width; + inst->crop.height = s->r.height; + inst->fmt_dst->fmt.pix_mp.width = inst->crop.width; + inst->fmt_dst->fmt.pix_mp.height = inst->crop.height; + return iris_venc_s_fmt_output(inst, inst->fmt_dst); + default: + return -EINVAL; + } +} + +int iris_venc_s_param(struct iris_inst *inst, struct v4l2_streamparm *s_parm) +{ + struct platform_inst_caps *caps = inst->core->iris_platform_data->inst_caps; + struct vb2_queue *src_q = v4l2_m2m_get_src_vq(inst->m2m_ctx); + struct vb2_queue *dst_q = v4l2_m2m_get_dst_vq(inst->m2m_ctx); + struct v4l2_fract *timeperframe = NULL; + u32 default_rate = DEFAULT_FPS; + bool is_frame_rate = false; + u64 us_per_frame, fps; + u32 max_rate; + + int ret = 0; + + if (s_parm->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { + timeperframe = &s_parm->parm.output.timeperframe; + max_rate = caps->max_operating_rate; + s_parm->parm.output.capability = V4L2_CAP_TIMEPERFRAME; + } else { + timeperframe = &s_parm->parm.capture.timeperframe; + is_frame_rate = true; + max_rate = caps->max_frame_rate; + s_parm->parm.capture.capability = V4L2_CAP_TIMEPERFRAME; + } + + if (!timeperframe->denominator || !timeperframe->numerator) { + if (!timeperframe->numerator) + timeperframe->numerator = 1; + if (!timeperframe->denominator) + timeperframe->denominator = default_rate; + } + + us_per_frame = timeperframe->numerator * (u64)USEC_PER_SEC; + do_div(us_per_frame, timeperframe->denominator); + + if (!us_per_frame) + return -EINVAL; + + fps = (u64)USEC_PER_SEC; + do_div(fps, us_per_frame); + if (fps > max_rate) { + ret = -ENOMEM; + goto reset_rate; + } + + if (is_frame_rate) + inst->frame_rate = (u32)fps; + else + inst->operating_rate = (u32)fps; + + if ((s_parm->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE && vb2_is_streaming(src_q)) || + (s_parm->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE && vb2_is_streaming(dst_q))) { + ret = iris_check_core_mbpf(inst); + if (ret) + goto reset_rate; + ret = iris_check_core_mbps(inst); + if (ret) + goto reset_rate; + } + + return 0; + +reset_rate: + if (ret) { + if (is_frame_rate) + inst->frame_rate = default_rate; + else + inst->operating_rate = default_rate; + } + + return ret; +} + +int iris_venc_g_param(struct iris_inst *inst, struct v4l2_streamparm *s_parm) +{ + struct v4l2_fract *timeperframe = NULL; + + if (s_parm->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { + timeperframe = &s_parm->parm.output.timeperframe; + timeperframe->numerator = 1; + timeperframe->denominator = inst->operating_rate; + s_parm->parm.output.capability = V4L2_CAP_TIMEPERFRAME; + } else { + timeperframe = &s_parm->parm.capture.timeperframe; + timeperframe->numerator = 1; + timeperframe->denominator = inst->frame_rate; + s_parm->parm.capture.capability = V4L2_CAP_TIMEPERFRAME; + } + + return 0; +} + +int iris_venc_streamon_input(struct iris_inst *inst) +{ + int ret; + + ret = iris_set_properties(inst, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); + if (ret) + return ret; + + ret = iris_alloc_and_queue_persist_bufs(inst, BUF_ARP); + if (ret) + return ret; + + iris_get_internal_buffers(inst, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); + + ret = iris_destroy_dequeued_internal_buffers(inst, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); + if (ret) + return ret; + + ret = iris_create_internal_buffers(inst, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); + if (ret) + return ret; + + ret = iris_queue_internal_buffers(inst, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); + if (ret) + return ret; + + return iris_process_streamon_input(inst); +} + +int iris_venc_streamon_output(struct iris_inst *inst) +{ + int ret; + + ret = iris_set_properties(inst, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE); + if (ret) + goto error; + + ret = iris_alloc_and_queue_persist_bufs(inst, BUF_ARP); + if (ret) + return ret; + + iris_get_internal_buffers(inst, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE); + + ret = iris_destroy_dequeued_internal_buffers(inst, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE); + if (ret) + goto error; + + ret = iris_create_internal_buffers(inst, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE); + if (ret) + goto error; + + ret = iris_queue_internal_buffers(inst, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE); + if (ret) + goto error; + + ret = iris_process_streamon_output(inst); + if (ret) + goto error; + + return ret; + +error: + iris_session_streamoff(inst, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE); + + return ret; +} + +int iris_venc_qbuf(struct iris_inst *inst, struct vb2_v4l2_buffer *vbuf) +{ + struct iris_buffer *buf = to_iris_buffer(vbuf); + struct vb2_buffer *vb2 = &vbuf->vb2_buf; + struct vb2_queue *q; + int ret; + + ret = iris_vb2_buffer_to_driver(vb2, buf); + if (ret) + return ret; + + if (buf->type == BUF_INPUT) + iris_set_ts_metadata(inst, vbuf); + + q = v4l2_m2m_get_vq(inst->m2m_ctx, vb2->type); + if (!vb2_is_streaming(q)) { + buf->attr |= BUF_ATTR_DEFERRED; + return 0; + } + + iris_scale_power(inst); + + return iris_queue_buffer(inst, buf); +} + +int iris_venc_start_cmd(struct iris_inst *inst) +{ + const struct iris_hfi_command_ops *hfi_ops = inst->core->hfi_ops; + enum iris_inst_sub_state clear_sub_state = 0; + struct vb2_queue *dst_vq; + int ret; + + dst_vq = v4l2_m2m_get_dst_vq(inst->m2m_ctx); + + if (inst->sub_state & IRIS_INST_SUB_DRAIN && + inst->sub_state & IRIS_INST_SUB_DRAIN_LAST) { + vb2_clear_last_buffer_dequeued(dst_vq); + clear_sub_state = IRIS_INST_SUB_DRAIN | IRIS_INST_SUB_DRAIN_LAST; + if (inst->sub_state & IRIS_INST_SUB_INPUT_PAUSE) { + if (hfi_ops->session_resume_drain) { + ret = hfi_ops->session_resume_drain(inst, + V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); + if (ret) + return ret; + } + clear_sub_state |= IRIS_INST_SUB_INPUT_PAUSE; + } + if (inst->sub_state & IRIS_INST_SUB_OUTPUT_PAUSE) { + if (hfi_ops->session_resume_drain) { + ret = hfi_ops->session_resume_drain(inst, + V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE); + if (ret) + return ret; + } + clear_sub_state |= IRIS_INST_SUB_OUTPUT_PAUSE; + } + } else { + dev_err(inst->core->dev, "start called before receiving last_flag\n"); + iris_inst_change_state(inst, IRIS_INST_ERROR); + return -EBUSY; + } + + inst->last_buffer_dequeued = false; + + return iris_inst_change_sub_state(inst, clear_sub_state, 0); +} + +int iris_venc_stop_cmd(struct iris_inst *inst) +{ + const struct iris_hfi_command_ops *hfi_ops = inst->core->hfi_ops; + int ret; + + ret = hfi_ops->session_drain(inst, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); + if (ret) + return ret; + + ret = iris_inst_change_sub_state(inst, 0, IRIS_INST_SUB_DRAIN); + + iris_scale_power(inst); + + return ret; +} diff --git a/drivers/media/platform/qcom/iris/iris_venc.h b/drivers/media/platform/qcom/iris/iris_venc.h new file mode 100644 index 000000000000..c4db7433da53 --- /dev/null +++ b/drivers/media/platform/qcom/iris/iris_venc.h @@ -0,0 +1,27 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2022-2025 Qualcomm Innovation Center, Inc. All rights reserved. + */ + +#ifndef _IRIS_VENC_H_ +#define _IRIS_VENC_H_ + +struct iris_inst; + +int iris_venc_inst_init(struct iris_inst *inst); +void iris_venc_inst_deinit(struct iris_inst *inst); +int iris_venc_enum_fmt(struct iris_inst *inst, struct v4l2_fmtdesc *f); +int iris_venc_try_fmt(struct iris_inst *inst, struct v4l2_format *f); +int iris_venc_s_fmt(struct iris_inst *inst, struct v4l2_format *f); +int iris_venc_validate_format(struct iris_inst *inst, u32 pixelformat); +int iris_venc_subscribe_event(struct iris_inst *inst, const struct v4l2_event_subscription *sub); +int iris_venc_s_selection(struct iris_inst *inst, struct v4l2_selection *s); +int iris_venc_g_param(struct iris_inst *inst, struct v4l2_streamparm *s_parm); +int iris_venc_s_param(struct iris_inst *inst, struct v4l2_streamparm *s_parm); +int iris_venc_streamon_input(struct iris_inst *inst); +int iris_venc_streamon_output(struct iris_inst *inst); +int iris_venc_qbuf(struct iris_inst *inst, struct vb2_v4l2_buffer *vbuf); +int iris_venc_start_cmd(struct iris_inst *inst); +int iris_venc_stop_cmd(struct iris_inst *inst); + +#endif diff --git a/drivers/media/platform/qcom/iris/iris_vidc.c b/drivers/media/platform/qcom/iris/iris_vidc.c index c417e8c31f80..d38d0f6961cd 100644 --- a/drivers/media/platform/qcom/iris/iris_vidc.c +++ b/drivers/media/platform/qcom/iris/iris_vidc.c @@ -12,6 +12,7 @@ #include "iris_vidc.h" #include "iris_instance.h" #include "iris_vdec.h" +#include "iris_venc.h" #include "iris_vb2.h" #include "iris_vpu_buffer.h" #include "iris_platform_common.h" @@ -21,16 +22,19 @@ #define STEP_WIDTH 1 #define STEP_HEIGHT 1 -static void iris_v4l2_fh_init(struct iris_inst *inst) +static void iris_v4l2_fh_init(struct iris_inst *inst, struct file *filp) { - v4l2_fh_init(&inst->fh, inst->core->vdev_dec); + if (inst->domain == ENCODER) + v4l2_fh_init(&inst->fh, inst->core->vdev_enc); + else if (inst->domain == DECODER) + v4l2_fh_init(&inst->fh, inst->core->vdev_dec); inst->fh.ctrl_handler = &inst->ctrl_handler; - v4l2_fh_add(&inst->fh); + v4l2_fh_add(&inst->fh, filp); } -static void iris_v4l2_fh_deinit(struct iris_inst *inst) +static void iris_v4l2_fh_deinit(struct iris_inst *inst, struct file *filp) { - v4l2_fh_del(&inst->fh); + v4l2_fh_del(&inst->fh, filp); inst->fh.ctrl_handler = NULL; v4l2_fh_exit(&inst->fh); } @@ -67,9 +71,9 @@ static void iris_remove_session(struct iris_inst *inst) mutex_unlock(&core->lock); } -static inline struct iris_inst *iris_get_inst(struct file *filp, void *fh) +static inline struct iris_inst *iris_get_inst(struct file *filp) { - return container_of(filp->private_data, struct iris_inst, fh); + return container_of(file_to_v4l2_fh(filp), struct iris_inst, fh); } static void iris_m2m_device_run(void *priv) @@ -126,9 +130,19 @@ iris_m2m_queue_init(void *priv, struct vb2_queue *src_vq, struct vb2_queue *dst_ int iris_open(struct file *filp) { struct iris_core *core = video_drvdata(filp); + struct video_device *vdev; struct iris_inst *inst; + u32 session_type; int ret; + vdev = video_devdata(filp); + if (strcmp(vdev->name, "qcom-iris-decoder") == 0) + session_type = DECODER; + else if (strcmp(vdev->name, "qcom-iris-encoder") == 0) + session_type = ENCODER; + else + return -EINVAL; + ret = pm_runtime_resume_and_get(core->dev); if (ret < 0) return ret; @@ -147,6 +161,7 @@ int iris_open(struct file *filp) return -ENOMEM; inst->core = core; + inst->domain = session_type; inst->session_id = hash32_ptr(inst); inst->state = IRIS_INST_DEINIT; @@ -161,10 +176,12 @@ int iris_open(struct file *filp) INIT_LIST_HEAD(&inst->buffers[BUF_DPB].list); INIT_LIST_HEAD(&inst->buffers[BUF_PERSIST].list); INIT_LIST_HEAD(&inst->buffers[BUF_SCRATCH_1].list); + INIT_LIST_HEAD(&inst->buffers[BUF_SCRATCH_2].list); + INIT_LIST_HEAD(&inst->buffers[BUF_VPSS].list); init_completion(&inst->completion); init_completion(&inst->flush_completion); - iris_v4l2_fh_init(inst); + iris_v4l2_fh_init(inst, filp); inst->m2m_dev = v4l2_m2m_init(&iris_m2m_ops); if (IS_ERR_OR_NULL(inst->m2m_dev)) { @@ -178,14 +195,16 @@ int iris_open(struct file *filp) goto fail_m2m_release; } - ret = iris_vdec_inst_init(inst); + if (inst->domain == DECODER) + ret = iris_vdec_inst_init(inst); + else if (inst->domain == ENCODER) + ret = iris_venc_inst_init(inst); if (ret) goto fail_m2m_ctx_release; iris_add_session(inst); inst->fh.m2m_ctx = inst->m2m_ctx; - filp->private_data = &inst->fh; return 0; @@ -194,7 +213,7 @@ fail_m2m_ctx_release: fail_m2m_release: v4l2_m2m_release(inst->m2m_dev); fail_v4l2_fh_deinit: - iris_v4l2_fh_deinit(inst); + iris_v4l2_fh_deinit(inst, filp); mutex_destroy(&inst->ctx_q_lock); mutex_destroy(&inst->lock); kfree(inst); @@ -240,26 +259,42 @@ static void iris_check_num_queued_internal_buffers(struct iris_inst *inst, u32 p for (i = 0; i < internal_buffer_count; i++) { buffers = &inst->buffers[internal_buf_type[i]]; + count = 0; list_for_each_entry_safe(buf, next, &buffers->list, list) count++; if (count) dev_err(inst->core->dev, "%d buffer of type %d not released", count, internal_buf_type[i]); } + + if (inst->domain == DECODER) + buffers = &inst->buffers[BUF_PERSIST]; + else + buffers = &inst->buffers[BUF_ARP]; + + count = 0; + list_for_each_entry_safe(buf, next, &buffers->list, list) + count++; + if (count) + dev_err(inst->core->dev, "%d buffer of type %d not released", + count, inst->domain == DECODER ? BUF_PERSIST : BUF_ARP); } int iris_close(struct file *filp) { - struct iris_inst *inst = iris_get_inst(filp, NULL); + struct iris_inst *inst = iris_get_inst(filp); v4l2_ctrl_handler_free(&inst->ctrl_handler); v4l2_m2m_ctx_release(inst->m2m_ctx); v4l2_m2m_release(inst->m2m_dev); mutex_lock(&inst->lock); - iris_vdec_inst_deinit(inst); + if (inst->domain == DECODER) + iris_vdec_inst_deinit(inst); + else if (inst->domain == ENCODER) + iris_venc_inst_deinit(inst); iris_session_close(inst); iris_inst_change_state(inst, IRIS_INST_DEINIT); - iris_v4l2_fh_deinit(inst); + iris_v4l2_fh_deinit(inst, filp); iris_destroy_all_internal_buffers(inst, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); iris_destroy_all_internal_buffers(inst, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE); iris_check_num_queued_internal_buffers(inst, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); @@ -269,25 +304,34 @@ int iris_close(struct file *filp) mutex_destroy(&inst->ctx_q_lock); mutex_destroy(&inst->lock); kfree(inst); - filp->private_data = NULL; return 0; } static int iris_enum_fmt(struct file *filp, void *fh, struct v4l2_fmtdesc *f) { - struct iris_inst *inst = iris_get_inst(filp, NULL); + struct iris_inst *inst = iris_get_inst(filp); - return iris_vdec_enum_fmt(inst, f); + if (inst->domain == DECODER) + return iris_vdec_enum_fmt(inst, f); + else if (inst->domain == ENCODER) + return iris_venc_enum_fmt(inst, f); + else + return -EINVAL; } static int iris_try_fmt_vid_mplane(struct file *filp, void *fh, struct v4l2_format *f) { - struct iris_inst *inst = iris_get_inst(filp, NULL); - int ret; + struct iris_inst *inst = iris_get_inst(filp); + int ret = 0; mutex_lock(&inst->lock); - ret = iris_vdec_try_fmt(inst, f); + + if (inst->domain == DECODER) + ret = iris_vdec_try_fmt(inst, f); + else if (inst->domain == ENCODER) + ret = iris_venc_try_fmt(inst, f); + mutex_unlock(&inst->lock); return ret; @@ -295,11 +339,16 @@ static int iris_try_fmt_vid_mplane(struct file *filp, void *fh, struct v4l2_form static int iris_s_fmt_vid_mplane(struct file *filp, void *fh, struct v4l2_format *f) { - struct iris_inst *inst = iris_get_inst(filp, NULL); - int ret; + struct iris_inst *inst = iris_get_inst(filp); + int ret = 0; mutex_lock(&inst->lock); - ret = iris_vdec_s_fmt(inst, f); + + if (inst->domain == DECODER) + ret = iris_vdec_s_fmt(inst, f); + else if (inst->domain == ENCODER) + ret = iris_venc_s_fmt(inst, f); + mutex_unlock(&inst->lock); return ret; @@ -307,7 +356,7 @@ static int iris_s_fmt_vid_mplane(struct file *filp, void *fh, struct v4l2_format static int iris_g_fmt_vid_mplane(struct file *filp, void *fh, struct v4l2_format *f) { - struct iris_inst *inst = iris_get_inst(filp, NULL); + struct iris_inst *inst = iris_get_inst(filp); int ret = 0; mutex_lock(&inst->lock); @@ -326,15 +375,20 @@ static int iris_g_fmt_vid_mplane(struct file *filp, void *fh, struct v4l2_format static int iris_enum_framesizes(struct file *filp, void *fh, struct v4l2_frmsizeenum *fsize) { - struct iris_inst *inst = iris_get_inst(filp, NULL); + struct iris_inst *inst = iris_get_inst(filp); struct platform_inst_caps *caps; + int ret = 0; if (fsize->index) return -EINVAL; - if (fsize->pixel_format != V4L2_PIX_FMT_H264 && - fsize->pixel_format != V4L2_PIX_FMT_NV12) - return -EINVAL; + if (inst->domain == DECODER) + ret = iris_vdec_validate_format(inst, fsize->pixel_format); + else + ret = iris_venc_validate_format(inst, fsize->pixel_format); + + if (ret) + return ret; caps = inst->core->iris_platform_data->inst_caps; @@ -346,55 +400,174 @@ static int iris_enum_framesizes(struct file *filp, void *fh, fsize->stepwise.max_height = caps->max_frame_height; fsize->stepwise.step_height = STEP_HEIGHT; + return ret; +} + +static int iris_enum_frameintervals(struct file *filp, void *fh, + struct v4l2_frmivalenum *fival) + +{ + struct iris_inst *inst = iris_get_inst(filp); + struct iris_core *core = inst->core; + struct platform_inst_caps *caps; + u32 fps, mbpf; + int ret = 0; + + if (inst->domain == DECODER) + return -ENOTTY; + + if (fival->index) + return -EINVAL; + + ret = iris_venc_validate_format(inst, fival->pixel_format); + if (ret) + return ret; + + if (!fival->width || !fival->height) + return -EINVAL; + + caps = inst->core->iris_platform_data->inst_caps; + if (fival->width > caps->max_frame_width || + fival->width < caps->min_frame_width || + fival->height > caps->max_frame_height || + fival->height < caps->min_frame_height) + return -EINVAL; + + mbpf = NUM_MBS_PER_FRAME(fival->height, fival->width); + fps = DIV_ROUND_UP(core->iris_platform_data->max_core_mbps, mbpf); + + fival->type = V4L2_FRMIVAL_TYPE_STEPWISE; + fival->stepwise.min.numerator = 1; + fival->stepwise.min.denominator = + min_t(u32, fps, MAXIMUM_FPS); + fival->stepwise.max.numerator = 1; + fival->stepwise.max.denominator = 1; + fival->stepwise.step.numerator = 1; + fival->stepwise.step.denominator = MAXIMUM_FPS; + return 0; } static int iris_querycap(struct file *filp, void *fh, struct v4l2_capability *cap) { + struct iris_inst *inst = iris_get_inst(filp); + strscpy(cap->driver, IRIS_DRV_NAME, sizeof(cap->driver)); - strscpy(cap->card, "Iris Decoder", sizeof(cap->card)); + + if (inst->domain == DECODER) + strscpy(cap->card, "Iris Decoder", sizeof(cap->card)); + else + strscpy(cap->card, "Iris Encoder", sizeof(cap->card)); return 0; } static int iris_g_selection(struct file *filp, void *fh, struct v4l2_selection *s) { - struct iris_inst *inst = iris_get_inst(filp, NULL); + struct iris_inst *inst = iris_get_inst(filp); - if (s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + if (s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE && + inst->domain == DECODER) return -EINVAL; - switch (s->target) { - case V4L2_SEL_TGT_CROP_BOUNDS: - case V4L2_SEL_TGT_CROP_DEFAULT: - case V4L2_SEL_TGT_CROP: - case V4L2_SEL_TGT_COMPOSE_BOUNDS: - case V4L2_SEL_TGT_COMPOSE_PADDED: - case V4L2_SEL_TGT_COMPOSE_DEFAULT: - case V4L2_SEL_TGT_COMPOSE: + if (s->type != V4L2_BUF_TYPE_VIDEO_OUTPUT && + inst->domain == ENCODER) + return -EINVAL; + + if (inst->domain == DECODER) { + switch (s->target) { + case V4L2_SEL_TGT_CROP_BOUNDS: + case V4L2_SEL_TGT_CROP_DEFAULT: + case V4L2_SEL_TGT_CROP: + case V4L2_SEL_TGT_COMPOSE_BOUNDS: + case V4L2_SEL_TGT_COMPOSE_PADDED: + case V4L2_SEL_TGT_COMPOSE_DEFAULT: + case V4L2_SEL_TGT_COMPOSE: + s->r.left = inst->crop.left; + s->r.top = inst->crop.top; + s->r.width = inst->crop.width; + s->r.height = inst->crop.height; + break; + default: + return -EINVAL; + } + } else if (inst->domain == ENCODER) { + switch (s->target) { + case V4L2_SEL_TGT_CROP_BOUNDS: + case V4L2_SEL_TGT_CROP_DEFAULT: + s->r.width = inst->fmt_src->fmt.pix_mp.width; + s->r.height = inst->fmt_src->fmt.pix_mp.height; + break; + case V4L2_SEL_TGT_CROP: + s->r.width = inst->crop.width; + s->r.height = inst->crop.height; + break; + default: + return -EINVAL; + } s->r.left = inst->crop.left; s->r.top = inst->crop.top; - s->r.width = inst->crop.width; - s->r.height = inst->crop.height; - break; - default: - return -EINVAL; } return 0; } +static int iris_s_selection(struct file *filp, void *fh, struct v4l2_selection *s) +{ + struct iris_inst *inst = iris_get_inst(filp); + + if (inst->domain == DECODER) + return -EINVAL; + else if (inst->domain == ENCODER) + return iris_venc_s_selection(inst, s); + + return -EINVAL; +} + static int iris_subscribe_event(struct v4l2_fh *fh, const struct v4l2_event_subscription *sub) { struct iris_inst *inst = container_of(fh, struct iris_inst, fh); - return iris_vdec_subscribe_event(inst, sub); + if (inst->domain == DECODER) + return iris_vdec_subscribe_event(inst, sub); + else if (inst->domain == ENCODER) + return iris_venc_subscribe_event(inst, sub); + + return -EINVAL; +} + +static int iris_s_parm(struct file *filp, void *fh, struct v4l2_streamparm *a) +{ + struct iris_inst *inst = iris_get_inst(filp); + + if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE && + a->type != V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) + return -EINVAL; + + if (inst->domain == ENCODER) + return iris_venc_s_param(inst, a); + else + return -EINVAL; +} + +static int iris_g_parm(struct file *filp, void *fh, struct v4l2_streamparm *a) +{ + struct iris_inst *inst = iris_get_inst(filp); + + if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE && + a->type != V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) + return -EINVAL; + + if (inst->domain == ENCODER) + return iris_venc_g_param(inst, a); + else + return -EINVAL; } static int iris_dec_cmd(struct file *filp, void *fh, struct v4l2_decoder_cmd *dec) { - struct iris_inst *inst = iris_get_inst(filp, NULL); + struct iris_inst *inst = iris_get_inst(filp); int ret = 0; mutex_lock(&inst->lock); @@ -424,6 +597,39 @@ unlock: return ret; } +static int iris_enc_cmd(struct file *filp, void *fh, + struct v4l2_encoder_cmd *enc) +{ + struct iris_inst *inst = iris_get_inst(filp); + int ret = 0; + + mutex_lock(&inst->lock); + + ret = v4l2_m2m_ioctl_encoder_cmd(filp, fh, enc); + if (ret) + goto unlock; + + if (inst->state == IRIS_INST_DEINIT) + goto unlock; + + if (!iris_allow_cmd(inst, enc->cmd)) { + ret = -EBUSY; + goto unlock; + } + + if (enc->cmd == V4L2_ENC_CMD_START) + ret = iris_venc_start_cmd(inst); + else if (enc->cmd == V4L2_ENC_CMD_STOP) + ret = iris_venc_stop_cmd(inst); + else + ret = -EINVAL; + +unlock: + mutex_unlock(&inst->lock); + + return ret; +} + static struct v4l2_file_operations iris_v4l2_file_ops = { .owner = THIS_MODULE, .open = iris_open, @@ -443,7 +649,7 @@ static const struct vb2_ops iris_vb2_ops = { .buf_queue = iris_vb2_buf_queue, }; -static const struct v4l2_ioctl_ops iris_v4l2_ioctl_ops = { +static const struct v4l2_ioctl_ops iris_v4l2_ioctl_ops_dec = { .vidioc_enum_fmt_vid_cap = iris_enum_fmt, .vidioc_enum_fmt_vid_out = iris_enum_fmt, .vidioc_try_fmt_vid_cap_mplane = iris_try_fmt_vid_mplane, @@ -471,9 +677,42 @@ static const struct v4l2_ioctl_ops iris_v4l2_ioctl_ops = { .vidioc_decoder_cmd = iris_dec_cmd, }; +static const struct v4l2_ioctl_ops iris_v4l2_ioctl_ops_enc = { + .vidioc_enum_fmt_vid_cap = iris_enum_fmt, + .vidioc_enum_fmt_vid_out = iris_enum_fmt, + .vidioc_try_fmt_vid_cap_mplane = iris_try_fmt_vid_mplane, + .vidioc_try_fmt_vid_out_mplane = iris_try_fmt_vid_mplane, + .vidioc_s_fmt_vid_cap_mplane = iris_s_fmt_vid_mplane, + .vidioc_s_fmt_vid_out_mplane = iris_s_fmt_vid_mplane, + .vidioc_g_fmt_vid_cap_mplane = iris_g_fmt_vid_mplane, + .vidioc_g_fmt_vid_out_mplane = iris_g_fmt_vid_mplane, + .vidioc_enum_framesizes = iris_enum_framesizes, + .vidioc_enum_frameintervals = iris_enum_frameintervals, + .vidioc_querycap = iris_querycap, + .vidioc_subscribe_event = iris_subscribe_event, + .vidioc_unsubscribe_event = v4l2_event_unsubscribe, + .vidioc_g_selection = iris_g_selection, + .vidioc_s_selection = iris_s_selection, + .vidioc_s_parm = iris_s_parm, + .vidioc_g_parm = iris_g_parm, + .vidioc_streamon = v4l2_m2m_ioctl_streamon, + .vidioc_streamoff = v4l2_m2m_ioctl_streamoff, + .vidioc_reqbufs = v4l2_m2m_ioctl_reqbufs, + .vidioc_querybuf = v4l2_m2m_ioctl_querybuf, + .vidioc_create_bufs = v4l2_m2m_ioctl_create_bufs, + .vidioc_prepare_buf = v4l2_m2m_ioctl_prepare_buf, + .vidioc_expbuf = v4l2_m2m_ioctl_expbuf, + .vidioc_qbuf = v4l2_m2m_ioctl_qbuf, + .vidioc_dqbuf = v4l2_m2m_ioctl_dqbuf, + .vidioc_remove_bufs = v4l2_m2m_ioctl_remove_bufs, + .vidioc_try_encoder_cmd = v4l2_m2m_ioctl_try_encoder_cmd, + .vidioc_encoder_cmd = iris_enc_cmd, +}; + void iris_init_ops(struct iris_core *core) { core->iris_v4l2_file_ops = &iris_v4l2_file_ops; core->iris_vb2_ops = &iris_vb2_ops; - core->iris_v4l2_ioctl_ops = &iris_v4l2_ioctl_ops; + core->iris_v4l2_ioctl_ops_dec = &iris_v4l2_ioctl_ops_dec; + core->iris_v4l2_ioctl_ops_enc = &iris_v4l2_ioctl_ops_enc; } diff --git a/drivers/media/platform/qcom/iris/iris_vpu2.c b/drivers/media/platform/qcom/iris/iris_vpu2.c index 7cf1bfc352d3..de7d142316d2 100644 --- a/drivers/media/platform/qcom/iris/iris_vpu2.c +++ b/drivers/media/platform/qcom/iris/iris_vpu2.c @@ -34,6 +34,8 @@ static u64 iris_vpu2_calc_freq(struct iris_inst *inst, size_t data_size) const struct vpu_ops iris_vpu2_ops = { .power_off_hw = iris_vpu_power_off_hw, + .power_on_hw = iris_vpu_power_on_hw, .power_off_controller = iris_vpu_power_off_controller, + .power_on_controller = iris_vpu_power_on_controller, .calc_freq = iris_vpu2_calc_freq, }; diff --git a/drivers/media/platform/qcom/iris/iris_vpu3x.c b/drivers/media/platform/qcom/iris/iris_vpu3x.c index 9b7c9a1495ee..339776a0b467 100644 --- a/drivers/media/platform/qcom/iris/iris_vpu3x.c +++ b/drivers/media/platform/qcom/iris/iris_vpu3x.c @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) 2025 Linaro Ltd */ #include <linux/iopoll.h> @@ -19,8 +20,13 @@ #define WRAPPER_IRIS_CPU_NOC_LPI_CONTROL (WRAPPER_BASE_OFFS + 0x5C) #define REQ_POWER_DOWN_PREP BIT(0) #define WRAPPER_IRIS_CPU_NOC_LPI_STATUS (WRAPPER_BASE_OFFS + 0x60) +#define NOC_LPI_STATUS_DONE BIT(0) /* Indicates the NOC handshake is complete */ +#define NOC_LPI_STATUS_DENY BIT(1) /* Indicates the NOC handshake is denied */ +#define NOC_LPI_STATUS_ACTIVE BIT(2) /* Indicates the NOC is active */ #define WRAPPER_CORE_CLOCK_CONFIG (WRAPPER_BASE_OFFS + 0x88) #define CORE_CLK_RUN 0x0 +/* VPU v3.5 */ +#define WRAPPER_IRIS_VCODEC_VPU_WRAPPER_SPARE_0 (WRAPPER_BASE_OFFS + 0x78) #define WRAPPER_TZ_CTL_AXI_CLOCK_CONFIG (WRAPPER_TZ_BASE_OFFS + 0x14) #define CTL_AXI_CLK_HALT BIT(0) @@ -52,6 +58,8 @@ #define AON_WRAPPER_MVP_NOC_CORE_CLK_CONTROL (AON_BASE_OFFS + 0x20) #define NOC_HALT BIT(0) #define AON_WRAPPER_SPARE (AON_BASE_OFFS + 0x28) +#define AON_WRAPPER_MVP_VIDEO_CTL_NOC_LPI_CONTROL (AON_BASE_OFFS + 0x2C) +#define AON_WRAPPER_MVP_VIDEO_CTL_NOC_LPI_STATUS (AON_BASE_OFFS + 0x30) static bool iris_vpu3x_hw_power_collapsed(struct iris_core *core) { @@ -109,7 +117,9 @@ disable_power: static void iris_vpu33_power_off_hardware(struct iris_core *core) { + bool handshake_done = false, handshake_busy = false; u32 reg_val = 0, value, i; + u32 count = 0; int ret; if (iris_vpu3x_hw_power_collapsed(core)) @@ -128,13 +138,36 @@ static void iris_vpu33_power_off_hardware(struct iris_core *core) goto disable_power; } + /* Retry up to 1000 times as recommended by hardware documentation */ + do { + /* set MNoC to low power */ + writel(REQ_POWER_DOWN_PREP, core->reg_base + AON_WRAPPER_MVP_NOC_LPI_CONTROL); + + udelay(15); + + value = readl(core->reg_base + AON_WRAPPER_MVP_NOC_LPI_STATUS); + + handshake_done = value & NOC_LPI_STATUS_DONE; + handshake_busy = value & (NOC_LPI_STATUS_DENY | NOC_LPI_STATUS_ACTIVE); + + if (handshake_done || !handshake_busy) + break; + + writel(0, core->reg_base + AON_WRAPPER_MVP_NOC_LPI_CONTROL); + + udelay(15); + + } while (++count < 1000); + + if (!handshake_done && handshake_busy) + dev_err(core->dev, "LPI handshake timeout\n"); + ret = readl_poll_timeout(core->reg_base + AON_WRAPPER_MVP_NOC_LPI_STATUS, reg_val, reg_val & BIT(0), 200, 2000); if (ret) goto disable_power; - /* set MNoC to low power, set PD_NOC_QREQ (bit 0) */ - writel(BIT(0), core->reg_base + AON_WRAPPER_MVP_NOC_LPI_CONTROL); + writel(0, core->reg_base + AON_WRAPPER_MVP_NOC_LPI_CONTROL); writel(CORE_BRIDGE_SW_RESET | CORE_BRIDGE_HW_RESET_DISABLE, core->reg_base + CPU_CS_AHB_BRIDGE_SYNC_RESET); @@ -225,6 +258,158 @@ disable_power: return 0; } +static int iris_vpu35_power_on_hw(struct iris_core *core) +{ + int ret; + + ret = iris_enable_power_domains(core, core->pmdomain_tbl->pd_devs[IRIS_HW_POWER_DOMAIN]); + if (ret) + return ret; + + ret = iris_prepare_enable_clock(core, IRIS_AXI_CLK); + if (ret) + goto err_disable_power; + + ret = iris_prepare_enable_clock(core, IRIS_HW_FREERUN_CLK); + if (ret) + goto err_disable_axi_clk; + + ret = iris_prepare_enable_clock(core, IRIS_HW_CLK); + if (ret) + goto err_disable_hw_free_clk; + + ret = dev_pm_genpd_set_hwmode(core->pmdomain_tbl->pd_devs[IRIS_HW_POWER_DOMAIN], true); + if (ret) + goto err_disable_hw_clk; + + return 0; + +err_disable_hw_clk: + iris_disable_unprepare_clock(core, IRIS_HW_CLK); +err_disable_hw_free_clk: + iris_disable_unprepare_clock(core, IRIS_HW_FREERUN_CLK); +err_disable_axi_clk: + iris_disable_unprepare_clock(core, IRIS_AXI_CLK); +err_disable_power: + iris_disable_power_domains(core, core->pmdomain_tbl->pd_devs[IRIS_HW_POWER_DOMAIN]); + + return ret; +} + +static void iris_vpu35_power_off_hw(struct iris_core *core) +{ + iris_vpu33_power_off_hardware(core); + + iris_disable_unprepare_clock(core, IRIS_HW_FREERUN_CLK); + iris_disable_unprepare_clock(core, IRIS_AXI_CLK); +} + +static int iris_vpu35_power_off_controller(struct iris_core *core) +{ + u32 clk_rst_tbl_size = core->iris_platform_data->clk_rst_tbl_size; + unsigned int count = 0; + u32 val = 0; + bool handshake_done, handshake_busy; + int ret; + + writel(MSK_SIGNAL_FROM_TENSILICA | MSK_CORE_POWER_ON, core->reg_base + CPU_CS_X2RPMH); + + writel(REQ_POWER_DOWN_PREP, core->reg_base + WRAPPER_IRIS_CPU_NOC_LPI_CONTROL); + + ret = readl_poll_timeout(core->reg_base + WRAPPER_IRIS_CPU_NOC_LPI_STATUS, + val, val & BIT(0), 200, 2000); + if (ret) + goto disable_power; + + writel(0, core->reg_base + WRAPPER_IRIS_CPU_NOC_LPI_CONTROL); + + /* Retry up to 1000 times as recommended by hardware documentation */ + do { + /* set MNoC to low power */ + writel(REQ_POWER_DOWN_PREP, core->reg_base + AON_WRAPPER_MVP_VIDEO_CTL_NOC_LPI_CONTROL); + + udelay(15); + + val = readl(core->reg_base + AON_WRAPPER_MVP_VIDEO_CTL_NOC_LPI_STATUS); + + handshake_done = val & NOC_LPI_STATUS_DONE; + handshake_busy = val & (NOC_LPI_STATUS_DENY | NOC_LPI_STATUS_ACTIVE); + + if (handshake_done || !handshake_busy) + break; + + writel(0, core->reg_base + AON_WRAPPER_MVP_VIDEO_CTL_NOC_LPI_CONTROL); + + udelay(15); + + } while (++count < 1000); + + if (!handshake_done && handshake_busy) + dev_err(core->dev, "LPI handshake timeout\n"); + + ret = readl_poll_timeout(core->reg_base + AON_WRAPPER_MVP_VIDEO_CTL_NOC_LPI_STATUS, + val, val & BIT(0), 200, 2000); + if (ret) + goto disable_power; + + writel(0, core->reg_base + AON_WRAPPER_MVP_VIDEO_CTL_NOC_LPI_CONTROL); + + writel(0, core->reg_base + WRAPPER_DEBUG_BRIDGE_LPI_CONTROL); + + ret = readl_poll_timeout(core->reg_base + WRAPPER_DEBUG_BRIDGE_LPI_STATUS, + val, val == 0, 200, 2000); + if (ret) + goto disable_power; + +disable_power: + iris_disable_unprepare_clock(core, IRIS_CTRL_CLK); + iris_disable_unprepare_clock(core, IRIS_CTRL_FREERUN_CLK); + iris_disable_unprepare_clock(core, IRIS_AXI1_CLK); + + iris_disable_power_domains(core, core->pmdomain_tbl->pd_devs[IRIS_CTRL_POWER_DOMAIN]); + + reset_control_bulk_reset(clk_rst_tbl_size, core->resets); + + return 0; +} + +static int iris_vpu35_power_on_controller(struct iris_core *core) +{ + int ret; + + ret = iris_enable_power_domains(core, core->pmdomain_tbl->pd_devs[IRIS_CTRL_POWER_DOMAIN]); + if (ret) + return ret; + + ret = iris_prepare_enable_clock(core, IRIS_AXI1_CLK); + if (ret) + goto err_disable_power; + + ret = iris_prepare_enable_clock(core, IRIS_CTRL_FREERUN_CLK); + if (ret) + goto err_disable_axi1_clk; + + ret = iris_prepare_enable_clock(core, IRIS_CTRL_CLK); + if (ret) + goto err_disable_ctrl_free_clk; + + return 0; + +err_disable_ctrl_free_clk: + iris_disable_unprepare_clock(core, IRIS_CTRL_FREERUN_CLK); +err_disable_axi1_clk: + iris_disable_unprepare_clock(core, IRIS_AXI1_CLK); +err_disable_power: + iris_disable_power_domains(core, core->pmdomain_tbl->pd_devs[IRIS_CTRL_POWER_DOMAIN]); + + return ret; +} + +static void iris_vpu35_program_bootup_registers(struct iris_core *core) +{ + writel(0x1, core->reg_base + WRAPPER_IRIS_VCODEC_VPU_WRAPPER_SPARE_0); +} + static u64 iris_vpu3x_calculate_frequency(struct iris_inst *inst, size_t data_size) { struct platform_inst_caps *caps = inst->core->iris_platform_data->inst_caps; @@ -264,12 +449,25 @@ static u64 iris_vpu3x_calculate_frequency(struct iris_inst *inst, size_t data_si const struct vpu_ops iris_vpu3_ops = { .power_off_hw = iris_vpu3_power_off_hardware, + .power_on_hw = iris_vpu_power_on_hw, .power_off_controller = iris_vpu_power_off_controller, + .power_on_controller = iris_vpu_power_on_controller, .calc_freq = iris_vpu3x_calculate_frequency, }; const struct vpu_ops iris_vpu33_ops = { .power_off_hw = iris_vpu33_power_off_hardware, + .power_on_hw = iris_vpu_power_on_hw, .power_off_controller = iris_vpu33_power_off_controller, + .power_on_controller = iris_vpu_power_on_controller, + .calc_freq = iris_vpu3x_calculate_frequency, +}; + +const struct vpu_ops iris_vpu35_ops = { + .power_off_hw = iris_vpu35_power_off_hw, + .power_on_hw = iris_vpu35_power_on_hw, + .power_off_controller = iris_vpu35_power_off_controller, + .power_on_controller = iris_vpu35_power_on_controller, + .program_bootup_registers = iris_vpu35_program_bootup_registers, .calc_freq = iris_vpu3x_calculate_frequency, }; diff --git a/drivers/media/platform/qcom/iris/iris_vpu_buffer.c b/drivers/media/platform/qcom/iris/iris_vpu_buffer.c index f92fd39fe310..4463be05ce16 100644 --- a/drivers/media/platform/qcom/iris/iris_vpu_buffer.c +++ b/drivers/media/platform/qcom/iris/iris_vpu_buffer.c @@ -5,6 +5,14 @@ #include "iris_instance.h" #include "iris_vpu_buffer.h" +#include "iris_hfi_gen1_defines.h" +#include "iris_hfi_gen2_defines.h" + +#define HFI_MAX_COL_FRAME 6 + +#ifndef SYSTEM_LAL_TILE10 +#define SYSTEM_LAL_TILE10 192 +#endif static u32 size_h264d_hw_bin_buffer(u32 frame_width, u32 frame_height, u32 num_vpp_pipes) { @@ -548,6 +556,858 @@ static u32 iris_vpu_dec_scratch1_size(struct iris_inst *inst) iris_vpu_dec_line_size(inst); } +static inline u32 size_bin_bitstream_enc(u32 width, u32 height, + u32 rc_type) +{ + u32 aligned_height = ALIGN(height, 32); + u32 aligned_width = ALIGN(width, 32); + u32 frame_size = width * height * 3; + u32 mbs_per_frame; + + /* + * Encoder output size calculation: 32 Align width/height + * For resolution < 720p : YUVsize * 4 + * For resolution > 720p & <= 4K : YUVsize / 2 + * For resolution > 4k : YUVsize / 4 + * Initially frame_size = YUVsize * 2; + */ + + mbs_per_frame = (ALIGN(aligned_height, 16) * ALIGN(aligned_width, 16)) / 256; + + if (mbs_per_frame < NUM_MBS_720P) + frame_size = frame_size << 1; + else if (mbs_per_frame <= NUM_MBS_4K) + frame_size = frame_size >> 2; + else + frame_size = frame_size >> 3; + + if (rc_type == HFI_RATE_CONTROL_OFF || rc_type == HFI_RATE_CONTROL_CQ || + rc_type == HFI_RC_OFF || rc_type == HFI_RC_CQ) + frame_size = frame_size << 1; + + /* + * In case of opaque color format bitdepth will be known + * with first ETB, buffers allocated already with 8 bit + * won't be sufficient for 10 bit + * calculate size considering 10-bit by default + * For 10-bit cases size = size * 1.25 + */ + frame_size *= 5; + frame_size /= 4; + + return ALIGN(frame_size, SZ_4K); +} + +static inline u32 hfi_buffer_bin_enc(u32 width, u32 height, + u32 work_mode, u32 lcu_size, + u32 num_vpp_pipes, u32 rc_type) +{ + u32 sao_bin_buffer_size, padded_bin_size, bitstream_size; + u32 total_bitbin_buffers, size_single_pipe, bitbin_size; + u32 aligned_height = ALIGN(height, lcu_size); + u32 aligned_width = ALIGN(width, lcu_size); + + bitstream_size = size_bin_bitstream_enc(width, height, rc_type); + bitstream_size = ALIGN(bitstream_size, 256); + + if (work_mode == STAGE_2) { + total_bitbin_buffers = 3; + bitbin_size = bitstream_size * 17 / 10; + bitbin_size = ALIGN(bitbin_size, 256); + } else { + total_bitbin_buffers = 1; + bitstream_size = aligned_width * aligned_height * 3; + bitbin_size = ALIGN(bitstream_size, 256); + } + + if (num_vpp_pipes > 2) + size_single_pipe = bitbin_size / 2; + else + size_single_pipe = bitbin_size; + + size_single_pipe = ALIGN(size_single_pipe, 256); + sao_bin_buffer_size = (64 * (((width + 32) * (height + 32)) >> 10)) + 384; + padded_bin_size = ALIGN(size_single_pipe, 256); + size_single_pipe = sao_bin_buffer_size + padded_bin_size; + size_single_pipe = ALIGN(size_single_pipe, 256); + bitbin_size = size_single_pipe * num_vpp_pipes; + + return ALIGN(bitbin_size, 256) * total_bitbin_buffers + 512; +} + +static u32 iris_vpu_enc_bin_size(struct iris_inst *inst) +{ + u32 num_vpp_pipes = inst->core->iris_platform_data->num_vpp_pipe; + u32 stage = inst->fw_caps[STAGE].value; + struct v4l2_format *f = inst->fmt_dst; + u32 height = f->fmt.pix_mp.height; + u32 width = f->fmt.pix_mp.width; + u32 lcu_size; + + if (inst->codec == V4L2_PIX_FMT_HEVC) + lcu_size = 32; + else + lcu_size = 16; + + return hfi_buffer_bin_enc(width, height, stage, lcu_size, + num_vpp_pipes, inst->hfi_rc_type); +} + +static inline +u32 hfi_buffer_comv_enc(u32 frame_width, u32 frame_height, u32 lcu_size, + u32 num_recon, u32 standard) +{ + u32 height_in_lcus = ((frame_height) + (lcu_size) - 1) / (lcu_size); + u32 width_in_lcus = ((frame_width) + (lcu_size) - 1) / (lcu_size); + u32 num_lcu_in_frame = width_in_lcus * height_in_lcus; + u32 mb_height = ((frame_height) + 15) >> 4; + u32 mb_width = ((frame_width) + 15) >> 4; + u32 size_colloc_mv, size_colloc_rc; + + size_colloc_mv = (standard == HFI_CODEC_ENCODE_HEVC) ? + (16 * ((num_lcu_in_frame << 2) + 32)) : + (3 * 16 * (width_in_lcus * height_in_lcus + 32)); + size_colloc_mv = ALIGN(size_colloc_mv, 256) * num_recon; + size_colloc_rc = (((mb_width + 7) >> 3) * 16 * 2 * mb_height); + size_colloc_rc = ALIGN(size_colloc_rc, 256) * HFI_MAX_COL_FRAME; + + return size_colloc_mv + size_colloc_rc; +} + +static u32 iris_vpu_enc_comv_size(struct iris_inst *inst) +{ + struct v4l2_format *f = inst->fmt_dst; + u32 height = f->fmt.pix_mp.height; + u32 width = f->fmt.pix_mp.width; + u32 num_recon = 1; + u32 lcu_size = 16; + + if (inst->codec == V4L2_PIX_FMT_HEVC) { + lcu_size = 32; + return hfi_buffer_comv_enc(width, height, lcu_size, + num_recon + 1, HFI_CODEC_ENCODE_HEVC); + } + + return hfi_buffer_comv_enc(width, height, lcu_size, + num_recon + 1, HFI_CODEC_ENCODE_AVC); +} + +static inline +u32 size_frame_rc_buf_size(u32 standard, u32 frame_height_coded, + u32 num_vpp_pipes_enc) +{ + u32 size = 0; + + size = (standard == HFI_CODEC_ENCODE_HEVC) ? + (256 + 16 * (14 + ((((frame_height_coded) >> 5) + 7) >> 3))) : + (256 + 16 * (14 + ((((frame_height_coded) >> 4) + 7) >> 3))); + size *= 11; + + if (num_vpp_pipes_enc > 1) + size = ALIGN(size, 256) * num_vpp_pipes_enc; + + return ALIGN(size, 512) * HFI_MAX_COL_FRAME; +} + +static inline +u32 size_enc_slice_info_buf(u32 num_lcu_in_frame) +{ + return ALIGN((256 + (num_lcu_in_frame << 4)), 256); +} + +static inline u32 enc_bitcnt_buf_size(u32 num_lcu_in_frame) +{ + return ALIGN((256 + (4 * (num_lcu_in_frame))), 256); +} + +static inline u32 enc_bitmap_buf_size(u32 num_lcu_in_frame) +{ + return ALIGN((256 + ((num_lcu_in_frame) >> 3)), 256); +} + +static inline u32 size_override_buf(u32 num_lcumb) +{ + return ALIGN(((16 * (((num_lcumb) + 7) >> 3))), 256) * 2; +} + +static inline u32 size_ir_buf(u32 num_lcu_in_frame) +{ + return ALIGN((((((num_lcu_in_frame) << 1) + 7) & (~7)) * 3), 256); +} + +static inline +u32 size_linebuff_data(bool is_ten_bit, u32 frame_width_coded) +{ + return is_ten_bit ? + (((((10 * (frame_width_coded) + 1024) + (256 - 1)) & + (~(256 - 1))) * 1) + + (((((10 * (frame_width_coded) + 1024) >> 1) + (256 - 1)) & + (~(256 - 1))) * 2)) : + (((((8 * (frame_width_coded) + 1024) + (256 - 1)) & + (~(256 - 1))) * 1) + + (((((8 * (frame_width_coded) + 1024) >> 1) + (256 - 1)) & + (~(256 - 1))) * 2)); +} + +static inline +u32 size_left_linebuff_ctrl(u32 standard, u32 frame_height_coded, + u32 num_vpp_pipes_enc) +{ + u32 size = 0; + + size = standard == HFI_CODEC_ENCODE_HEVC ? + (((frame_height_coded) + + (32)) / 32 * 4 * 16) : + (((frame_height_coded) + 15) / 16 * 5 * 16); + + if ((num_vpp_pipes_enc) > 1) { + size += 512; + size = ALIGN(size, 512) * + num_vpp_pipes_enc; + } + + return ALIGN(size, 256); +} + +static inline +u32 size_left_linebuff_recon_pix(bool is_ten_bit, u32 frame_height_coded, + u32 num_vpp_pipes_enc) +{ + return (((is_ten_bit + 1) * 2 * (frame_height_coded) + 256) + + (256 << (num_vpp_pipes_enc - 1)) - 1) & + (~((256 << (num_vpp_pipes_enc - 1)) - 1)) * 1; +} + +static inline +u32 size_top_linebuff_ctrl_fe(u32 frame_width_coded, u32 standard) +{ + return standard == HFI_CODEC_ENCODE_HEVC ? + ALIGN((64 * ((frame_width_coded) >> 5)), 256) : + ALIGN((256 + 16 * ((frame_width_coded) >> 4)), 256); +} + +static inline +u32 size_left_linebuff_ctrl_fe(u32 frame_height_coded, u32 num_vpp_pipes_enc) +{ + return (((256 + 64 * ((frame_height_coded) >> 4)) + + (256 << (num_vpp_pipes_enc - 1)) - 1) & + (~((256 << (num_vpp_pipes_enc - 1)) - 1)) * 1) * + num_vpp_pipes_enc; +} + +static inline +u32 size_left_linebuff_metadata_recon_y(u32 frame_height_coded, + bool is_ten_bit, + u32 num_vpp_pipes_enc) +{ + return ALIGN(((256 + 64 * ((frame_height_coded) / + (8 * (is_ten_bit ? 4 : 8))))), 256) * num_vpp_pipes_enc; +} + +static inline +u32 size_left_linebuff_metadata_recon_uv(u32 frame_height_coded, + bool is_ten_bit, + u32 num_vpp_pipes_enc) +{ + return ALIGN(((256 + 64 * ((frame_height_coded) / + (4 * (is_ten_bit ? 4 : 8))))), 256) * num_vpp_pipes_enc; +} + +static inline +u32 size_linebuff_recon_pix(bool is_ten_bit, u32 frame_width_coded) +{ + return ALIGN(((is_ten_bit ? 3 : 2) * (frame_width_coded)), 256); +} + +static inline +u32 size_line_buf_ctrl(u32 frame_width_coded) +{ + return ALIGN(frame_width_coded, 256); +} + +static inline +u32 size_line_buf_ctrl_id2(u32 frame_width_coded) +{ + return ALIGN(frame_width_coded, 256); +} + +static inline u32 size_line_buf_sde(u32 frame_width_coded) +{ + return ALIGN((256 + (16 * ((frame_width_coded) >> 4))), 256); +} + +static inline +u32 size_vpss_line_buf(u32 num_vpp_pipes_enc, u32 frame_height_coded, + u32 frame_width_coded) +{ + return ALIGN(((((((8192) >> 2) << 5) * (num_vpp_pipes_enc)) + 64) + + (((((max_t(u32, (frame_width_coded), + (frame_height_coded)) + 3) >> 2) << 5) + 256) * 16)), 256); +} +static inline +u32 size_vpss_line_buf_vpu33(u32 num_vpp_pipes_enc, u32 frame_height_coded, + u32 frame_width_coded) +{ + u32 vpss_4tap_top, vpss_4tap_left, vpss_div2_top; + u32 vpss_div2_left, vpss_top_lb, vpss_left_lb; + u32 size_left, size_top; + u32 max_width_height; + + max_width_height = max_t(u32, frame_width_coded, frame_height_coded); + vpss_4tap_top = ((((max_width_height * 2) + 3) >> 2) << 4) + 256; + vpss_4tap_left = (((8192 + 3) >> 2) << 5) + 64; + vpss_div2_top = (((max_width_height + 3) >> 2) << 4) + 256; + vpss_div2_left = ((((max_width_height * 2) + 3) >> 2) << 5) + 64; + vpss_top_lb = (frame_width_coded + 1) << 3; + vpss_left_lb = (frame_height_coded << 3) * num_vpp_pipes_enc; + size_left = (vpss_4tap_left + vpss_div2_left) * 2 * num_vpp_pipes_enc; + size_top = (vpss_4tap_top + vpss_div2_top) * 2; + + return ALIGN(size_left + size_top + vpss_top_lb + vpss_left_lb, DMA_ALIGNMENT); +} + +static inline +u32 size_top_line_buf_first_stg_sao(u32 frame_width_coded) +{ + return ALIGN((16 * ((frame_width_coded) >> 5)), 256); +} + +static inline +u32 size_enc_ref_buffer(u32 frame_width, u32 frame_height) +{ + u32 u_chroma_buffer_height = ALIGN(frame_height >> 1, 32); + u32 u_buffer_height = ALIGN(frame_height, 32); + u32 u_buffer_width = ALIGN(frame_width, 32); + + return (u_buffer_height + u_chroma_buffer_height) * u_buffer_width; +} + +static inline +u32 size_enc_ten_bit_ref_buffer(u32 frame_width, u32 frame_height) +{ + u32 ref_luma_stride_in_bytes = ((frame_width + SYSTEM_LAL_TILE10 - 1) / SYSTEM_LAL_TILE10) * + SYSTEM_LAL_TILE10; + u32 ref_buf_height = (frame_height + (32 - 1)) & (~(32 - 1)); + u32 u_ref_stride, luma_size; + u32 ref_chrm_height_in_bytes; + u32 chroma_size; + + u_ref_stride = 4 * (ref_luma_stride_in_bytes / 3); + u_ref_stride = (u_ref_stride + (128 - 1)) & (~(128 - 1)); + luma_size = ref_buf_height * u_ref_stride; + luma_size = (luma_size + (4096 - 1)) & (~(4096 - 1)); + + ref_chrm_height_in_bytes = (((frame_height + 1) >> 1) + (32 - 1)) & (~(32 - 1)); + chroma_size = u_ref_stride * ref_chrm_height_in_bytes; + chroma_size = (chroma_size + (4096 - 1)) & (~(4096 - 1)); + + return luma_size + chroma_size; +} + +static inline +u32 hfi_ubwc_calc_metadata_plane_stride(u32 frame_width, + u32 metadata_stride_multiple, + u32 tile_width_in_pels) +{ + return ALIGN(((frame_width + (tile_width_in_pels - 1)) / tile_width_in_pels), + metadata_stride_multiple); +} + +static inline +u32 hfi_ubwc_metadata_plane_bufheight(u32 frame_height, + u32 metadata_height_multiple, + u32 tile_height_in_pels) +{ + return ALIGN(((frame_height + (tile_height_in_pels - 1)) / tile_height_in_pels), + metadata_height_multiple); +} + +static inline +u32 hfi_ubwc_metadata_plane_buffer_size(u32 _metadata_tride, u32 _metadata_buf_height) +{ + return ALIGN(_metadata_tride * _metadata_buf_height, 4096); +} + +static inline +u32 hfi_buffer_non_comv_enc(u32 frame_width, u32 frame_height, + u32 num_vpp_pipes_enc, u32 lcu_size, u32 standard) +{ + u32 height_in_lcus = ((frame_height) + (lcu_size) - 1) / (lcu_size); + u32 width_in_lcus = ((frame_width) + (lcu_size) - 1) / (lcu_size); + u32 num_lcu_in_frame = width_in_lcus * height_in_lcus; + u32 frame_height_coded = height_in_lcus * (lcu_size); + u32 frame_width_coded = width_in_lcus * (lcu_size); + u32 num_lcumb, frame_rc_buf_size; + + num_lcumb = (frame_height_coded / lcu_size) * + ((frame_width_coded + lcu_size * 8) / lcu_size); + frame_rc_buf_size = size_frame_rc_buf_size(standard, frame_height_coded, + num_vpp_pipes_enc); + return size_enc_slice_info_buf(num_lcu_in_frame) + + SIZE_SLICE_CMD_BUFFER + + SIZE_SPS_PPS_SLICE_HDR + + frame_rc_buf_size + + enc_bitcnt_buf_size(num_lcu_in_frame) + + enc_bitmap_buf_size(num_lcu_in_frame) + + SIZE_BSE_SLICE_CMD_BUF + + SIZE_LAMBDA_LUT + + size_override_buf(num_lcumb) + + size_ir_buf(num_lcu_in_frame); +} + +static u32 iris_vpu_enc_non_comv_size(struct iris_inst *inst) +{ + u32 num_vpp_pipes = inst->core->iris_platform_data->num_vpp_pipe; + struct v4l2_format *f = inst->fmt_dst; + u32 height = f->fmt.pix_mp.height; + u32 width = f->fmt.pix_mp.width; + u32 lcu_size = 16; + + if (inst->codec == V4L2_PIX_FMT_HEVC) { + lcu_size = 32; + return hfi_buffer_non_comv_enc(width, height, num_vpp_pipes, + lcu_size, HFI_CODEC_ENCODE_HEVC) + + SIZE_ONE_SLICE_BUF; + } + + return hfi_buffer_non_comv_enc(width, height, num_vpp_pipes, + lcu_size, HFI_CODEC_ENCODE_AVC); +} + +static inline +u32 hfi_buffer_line_enc_base(u32 frame_width, u32 frame_height, bool is_ten_bit, + u32 num_vpp_pipes_enc, u32 lcu_size, u32 standard) +{ + u32 width_in_lcus = ((frame_width) + (lcu_size) - 1) / (lcu_size); + u32 height_in_lcus = ((frame_height) + (lcu_size) - 1) / (lcu_size); + u32 frame_height_coded = height_in_lcus * (lcu_size); + u32 frame_width_coded = width_in_lcus * (lcu_size); + u32 line_buff_data_size, left_line_buff_ctrl_size; + u32 left_line_buff_metadata_recon__uv__size; + u32 left_line_buff_metadata_recon__y__size; + u32 left_line_buff_recon_pix_size; + u32 top_line_buff_ctrl_fe_size; + u32 line_buff_recon_pix_size; + + line_buff_data_size = size_linebuff_data(is_ten_bit, frame_width_coded); + left_line_buff_ctrl_size = + size_left_linebuff_ctrl(standard, frame_height_coded, num_vpp_pipes_enc); + left_line_buff_recon_pix_size = + size_left_linebuff_recon_pix(is_ten_bit, frame_height_coded, + num_vpp_pipes_enc); + top_line_buff_ctrl_fe_size = + size_top_linebuff_ctrl_fe(frame_width_coded, standard); + left_line_buff_metadata_recon__y__size = + size_left_linebuff_metadata_recon_y(frame_height_coded, is_ten_bit, + num_vpp_pipes_enc); + left_line_buff_metadata_recon__uv__size = + size_left_linebuff_metadata_recon_uv(frame_height_coded, is_ten_bit, + num_vpp_pipes_enc); + line_buff_recon_pix_size = size_linebuff_recon_pix(is_ten_bit, frame_width_coded); + + return size_line_buf_ctrl(frame_width_coded) + + size_line_buf_ctrl_id2(frame_width_coded) + + line_buff_data_size + + left_line_buff_ctrl_size + + left_line_buff_recon_pix_size + + top_line_buff_ctrl_fe_size + + left_line_buff_metadata_recon__y__size + + left_line_buff_metadata_recon__uv__size + + line_buff_recon_pix_size + + size_left_linebuff_ctrl_fe(frame_height_coded, num_vpp_pipes_enc) + + size_line_buf_sde(frame_width_coded) + + size_top_line_buf_first_stg_sao(frame_width_coded); +} + +static inline +u32 hfi_buffer_line_enc(u32 frame_width, u32 frame_height, bool is_ten_bit, + u32 num_vpp_pipes_enc, u32 lcu_size, u32 standard) +{ + u32 width_in_lcus = ((frame_width) + (lcu_size) - 1) / (lcu_size); + u32 height_in_lcus = ((frame_height) + (lcu_size) - 1) / (lcu_size); + u32 frame_height_coded = height_in_lcus * (lcu_size); + u32 frame_width_coded = width_in_lcus * (lcu_size); + + return hfi_buffer_line_enc_base(frame_width, frame_height, is_ten_bit, + num_vpp_pipes_enc, lcu_size, standard) + + size_vpss_line_buf(num_vpp_pipes_enc, frame_height_coded, frame_width_coded); +} + +static inline +u32 hfi_buffer_line_enc_vpu33(u32 frame_width, u32 frame_height, bool is_ten_bit, + u32 num_vpp_pipes_enc, u32 lcu_size, u32 standard) +{ + u32 width_in_lcus = ((frame_width) + (lcu_size) - 1) / (lcu_size); + u32 height_in_lcus = ((frame_height) + (lcu_size) - 1) / (lcu_size); + u32 frame_height_coded = height_in_lcus * (lcu_size); + u32 frame_width_coded = width_in_lcus * (lcu_size); + + return hfi_buffer_line_enc_base(frame_width, frame_height, is_ten_bit, + num_vpp_pipes_enc, lcu_size, standard) + + size_vpss_line_buf_vpu33(num_vpp_pipes_enc, frame_height_coded, + frame_width_coded); +} + +static u32 iris_vpu_enc_line_size(struct iris_inst *inst) +{ + u32 num_vpp_pipes = inst->core->iris_platform_data->num_vpp_pipe; + struct v4l2_format *f = inst->fmt_dst; + u32 height = f->fmt.pix_mp.height; + u32 width = f->fmt.pix_mp.width; + u32 lcu_size = 16; + + if (inst->codec == V4L2_PIX_FMT_HEVC) { + lcu_size = 32; + return hfi_buffer_line_enc(width, height, 0, num_vpp_pipes, + lcu_size, HFI_CODEC_ENCODE_HEVC); + } + + return hfi_buffer_line_enc(width, height, 0, num_vpp_pipes, + lcu_size, HFI_CODEC_ENCODE_AVC); +} + +static u32 iris_vpu33_enc_line_size(struct iris_inst *inst) +{ + u32 num_vpp_pipes = inst->core->iris_platform_data->num_vpp_pipe; + struct v4l2_format *f = inst->fmt_dst; + u32 height = f->fmt.pix_mp.height; + u32 width = f->fmt.pix_mp.width; + u32 lcu_size = 16; + + if (inst->codec == V4L2_PIX_FMT_HEVC) { + lcu_size = 32; + return hfi_buffer_line_enc_vpu33(width, height, 0, num_vpp_pipes, + lcu_size, HFI_CODEC_ENCODE_HEVC); + } + + return hfi_buffer_line_enc_vpu33(width, height, 0, num_vpp_pipes, + lcu_size, HFI_CODEC_ENCODE_AVC); +} + +static inline +u32 hfi_buffer_dpb_enc(u32 frame_width, u32 frame_height, bool is_ten_bit) +{ + u32 metadata_stride, metadata_buf_height, meta_size_y, meta_size_c; + u32 ten_bit_ref_buf_size = 0, ref_buf_size = 0; + u32 size; + + if (!is_ten_bit) { + ref_buf_size = size_enc_ref_buffer(frame_width, frame_height); + metadata_stride = + hfi_ubwc_calc_metadata_plane_stride(frame_width, 64, + HFI_COL_FMT_NV12C_Y_TILE_WIDTH); + metadata_buf_height = + hfi_ubwc_metadata_plane_bufheight(frame_height, 16, + HFI_COL_FMT_NV12C_Y_TILE_HEIGHT); + meta_size_y = + hfi_ubwc_metadata_plane_buffer_size(metadata_stride, metadata_buf_height); + meta_size_c = + hfi_ubwc_metadata_plane_buffer_size(metadata_stride, metadata_buf_height); + size = ref_buf_size + meta_size_y + meta_size_c; + } else { + ten_bit_ref_buf_size = size_enc_ten_bit_ref_buffer(frame_width, frame_height); + metadata_stride = + hfi_ubwc_calc_metadata_plane_stride(frame_width, + IRIS_METADATA_STRIDE_MULTIPLE, + HFI_COL_FMT_TP10C_Y_TILE_WIDTH); + metadata_buf_height = + hfi_ubwc_metadata_plane_bufheight(frame_height, + IRIS_METADATA_HEIGHT_MULTIPLE, + HFI_COL_FMT_TP10C_Y_TILE_HEIGHT); + meta_size_y = + hfi_ubwc_metadata_plane_buffer_size(metadata_stride, metadata_buf_height); + meta_size_c = + hfi_ubwc_metadata_plane_buffer_size(metadata_stride, metadata_buf_height); + size = ten_bit_ref_buf_size + meta_size_y + meta_size_c; + } + + return size; +} + +static u32 iris_vpu_enc_arp_size(struct iris_inst *inst) +{ + return HFI_BUFFER_ARP_ENC; +} + +inline bool is_scaling_enabled(struct iris_inst *inst) +{ + return inst->crop.left != inst->compose.left || + inst->crop.top != inst->compose.top || + inst->crop.width != inst->compose.width || + inst->crop.height != inst->compose.height; +} + +static inline +u32 hfi_buffer_vpss_enc(u32 dswidth, u32 dsheight, bool ds_enable, + u32 blur, bool is_ten_bit) +{ + if (ds_enable || blur) + return hfi_buffer_dpb_enc(dswidth, dsheight, is_ten_bit); + + return 0; +} + +static inline u32 hfi_buffer_scratch1_enc(u32 frame_width, u32 frame_height, + u32 lcu_size, u32 num_ref, + bool ten_bit, u32 num_vpp_pipes, + bool is_h265) +{ + u32 line_buf_ctrl_size, line_buf_data_size, leftline_buf_ctrl_size; + u32 line_buf_sde_size, sps_pps_slice_hdr, topline_buf_ctrl_size_FE; + u32 leftline_buf_ctrl_size_FE, line_buf_recon_pix_size; + u32 leftline_buf_recon_pix_size, lambda_lut_size, override_buffer_size; + u32 col_mv_buf_size, vpp_reg_buffer_size, ir_buffer_size; + u32 vpss_line_buf, leftline_buf_meta_recony, h265e_colrcbuf_size; + u32 h265e_framerc_bufsize, h265e_lcubitcnt_bufsize; + u32 h265e_lcubitmap_bufsize, se_stats_bufsize; + u32 bse_reg_buffer_size, bse_slice_cmd_buffer_size, slice_info_bufsize; + u32 line_buf_ctrl_size_buffid2, slice_cmd_buffer_size; + u32 width_lcu_num, height_lcu_num, width_coded, height_coded; + u32 frame_num_lcu, linebuf_meta_recon_uv, topline_bufsize_fe_1stg_sao; + u32 vpss_line_buffer_size_1; + u32 bit_depth, num_lcu_mb; + + width_lcu_num = (frame_width + lcu_size - 1) / lcu_size; + height_lcu_num = (frame_height + lcu_size - 1) / lcu_size; + frame_num_lcu = width_lcu_num * height_lcu_num; + width_coded = width_lcu_num * lcu_size; + height_coded = height_lcu_num * lcu_size; + num_lcu_mb = (height_coded / lcu_size) * + ((width_coded + lcu_size * 8) / lcu_size); + slice_info_bufsize = 256 + (frame_num_lcu << 4); + slice_info_bufsize = ALIGN(slice_info_bufsize, 256); + line_buf_ctrl_size = ALIGN(width_coded, 256); + line_buf_ctrl_size_buffid2 = ALIGN(width_coded, 256); + + bit_depth = ten_bit ? 10 : 8; + line_buf_data_size = + (((((bit_depth * width_coded + 1024) + (256 - 1)) & + (~(256 - 1))) * 1) + + (((((bit_depth * width_coded + 1024) >> 1) + (256 - 1)) & + (~(256 - 1))) * 2)); + + leftline_buf_ctrl_size = is_h265 ? ((height_coded + 32) / 32 * 4 * 16) : + ((height_coded + 15) / 16 * 5 * 16); + + if (num_vpp_pipes > 1) { + leftline_buf_ctrl_size += 512; + leftline_buf_ctrl_size = + ALIGN(leftline_buf_ctrl_size, 512) * num_vpp_pipes; + } + + leftline_buf_ctrl_size = ALIGN(leftline_buf_ctrl_size, 256); + leftline_buf_recon_pix_size = + (((ten_bit + 1) * 2 * (height_coded) + 256) + + (256 << (num_vpp_pipes - 1)) - 1) & + (~((256 << (num_vpp_pipes - 1)) - 1)) * 1; + + topline_buf_ctrl_size_FE = is_h265 ? (64 * (width_coded >> 5)) : + (256 + 16 * (width_coded >> 4)); + topline_buf_ctrl_size_FE = ALIGN(topline_buf_ctrl_size_FE, 256); + leftline_buf_ctrl_size_FE = + (((256 + 64 * (height_coded >> 4)) + + (256 << (num_vpp_pipes - 1)) - 1) & + (~((256 << (num_vpp_pipes - 1)) - 1)) * 1) * + num_vpp_pipes; + leftline_buf_meta_recony = + (256 + 64 * ((height_coded) / (8 * (ten_bit ? 4 : 8)))); + leftline_buf_meta_recony = ALIGN(leftline_buf_meta_recony, 256); + leftline_buf_meta_recony = leftline_buf_meta_recony * num_vpp_pipes; + linebuf_meta_recon_uv = + (256 + 64 * ((height_coded) / (4 * (ten_bit ? 4 : 8)))); + linebuf_meta_recon_uv = ALIGN(linebuf_meta_recon_uv, 256); + linebuf_meta_recon_uv = linebuf_meta_recon_uv * num_vpp_pipes; + line_buf_recon_pix_size = ((ten_bit ? 3 : 2) * width_coded); + line_buf_recon_pix_size = ALIGN(line_buf_recon_pix_size, 256); + slice_cmd_buffer_size = ALIGN(20480, 256); + sps_pps_slice_hdr = 2048 + 4096; + col_mv_buf_size = + is_h265 ? (16 * ((frame_num_lcu << 2) + 32)) : + (3 * 16 * (width_lcu_num * height_lcu_num + 32)); + col_mv_buf_size = ALIGN(col_mv_buf_size, 256) * (num_ref + 1); + h265e_colrcbuf_size = + (((width_lcu_num + 7) >> 3) * 16 * 2 * height_lcu_num); + if (num_vpp_pipes > 1) + h265e_colrcbuf_size = + ALIGN(h265e_colrcbuf_size, 256) * num_vpp_pipes; + + h265e_colrcbuf_size = + ALIGN(h265e_colrcbuf_size, 256) * HFI_MAX_COL_FRAME; + h265e_framerc_bufsize = + (is_h265) ? + (256 + 16 * (14 + (((height_coded >> 5) + 7) >> 3))) : + (256 + 16 * (14 + (((height_coded >> 4) + 7) >> 3))); + h265e_framerc_bufsize *= 6; + if (num_vpp_pipes > 1) + h265e_framerc_bufsize = + ALIGN(h265e_framerc_bufsize, 256) * num_vpp_pipes; + + h265e_framerc_bufsize = + ALIGN(h265e_framerc_bufsize, 512) * HFI_MAX_COL_FRAME; + h265e_lcubitcnt_bufsize = 256 + 4 * frame_num_lcu; + h265e_lcubitcnt_bufsize = ALIGN(h265e_lcubitcnt_bufsize, 256); + h265e_lcubitmap_bufsize = 256 + (frame_num_lcu >> 3); + h265e_lcubitmap_bufsize = ALIGN(h265e_lcubitmap_bufsize, 256); + line_buf_sde_size = 256 + 16 * (width_coded >> 4); + line_buf_sde_size = ALIGN(line_buf_sde_size, 256); + if ((width_coded * height_coded) > (4096 * 2160)) + se_stats_bufsize = 0; + else if ((width_coded * height_coded) > (1920 * 1088)) + se_stats_bufsize = (40 * 4 * frame_num_lcu + 256 + 256); + else + se_stats_bufsize = (1024 * frame_num_lcu + 256 + 256); + + se_stats_bufsize = ALIGN(se_stats_bufsize, 256) * 2; + bse_slice_cmd_buffer_size = (((8192 << 2) + 7) & (~7)) * 6; + bse_reg_buffer_size = (((512 << 3) + 7) & (~7)) * 4; + vpp_reg_buffer_size = (((2048 << 3) + 31) & (~31)) * 10; + lambda_lut_size = 256 * 11; + override_buffer_size = 16 * ((num_lcu_mb + 7) >> 3); + override_buffer_size = ALIGN(override_buffer_size, 256) * 2; + ir_buffer_size = (((frame_num_lcu << 1) + 7) & (~7)) * 3; + vpss_line_buffer_size_1 = (((8192 >> 2) << 5) * num_vpp_pipes) + 64; + vpss_line_buf = + (((((max(width_coded, height_coded) + 3) >> 2) << 5) + 256) * + 16) + + vpss_line_buffer_size_1; + topline_bufsize_fe_1stg_sao = 16 * (width_coded >> 5); + topline_bufsize_fe_1stg_sao = ALIGN(topline_bufsize_fe_1stg_sao, 256); + + return line_buf_ctrl_size + line_buf_data_size + + line_buf_ctrl_size_buffid2 + leftline_buf_ctrl_size + + vpss_line_buf + col_mv_buf_size + topline_buf_ctrl_size_FE + + leftline_buf_ctrl_size_FE + line_buf_recon_pix_size + + leftline_buf_recon_pix_size + leftline_buf_meta_recony + + linebuf_meta_recon_uv + h265e_colrcbuf_size + + h265e_framerc_bufsize + h265e_lcubitcnt_bufsize + + h265e_lcubitmap_bufsize + line_buf_sde_size + + topline_bufsize_fe_1stg_sao + override_buffer_size + + bse_reg_buffer_size + vpp_reg_buffer_size + sps_pps_slice_hdr + + slice_cmd_buffer_size + bse_slice_cmd_buffer_size + + ir_buffer_size + slice_info_bufsize + lambda_lut_size + + se_stats_bufsize + 1024; +} + +static u32 iris_vpu_enc_scratch1_size(struct iris_inst *inst) +{ + u32 num_vpp_pipes = inst->core->iris_platform_data->num_vpp_pipe; + struct v4l2_format *f = inst->fmt_dst; + u32 frame_height = f->fmt.pix_mp.height; + u32 frame_width = f->fmt.pix_mp.width; + u32 num_ref = 1; + u32 lcu_size; + bool is_h265; + + if (inst->codec == V4L2_PIX_FMT_H264) { + lcu_size = 16; + is_h265 = false; + } else if (inst->codec == V4L2_PIX_FMT_HEVC) { + lcu_size = 32; + is_h265 = true; + } else { + return 0; + } + + return hfi_buffer_scratch1_enc(frame_width, frame_height, lcu_size, + num_ref, false, num_vpp_pipes, is_h265); +} + +static inline u32 ubwc_metadata_plane_stride(u32 width, + u32 metadata_stride_multi, + u32 tile_width_pels) +{ + return ALIGN(((width + (tile_width_pels - 1)) / tile_width_pels), + metadata_stride_multi); +} + +static inline u32 ubwc_metadata_plane_bufheight(u32 height, + u32 metadata_height_multi, + u32 tile_height_pels) +{ + return ALIGN(((height + (tile_height_pels - 1)) / tile_height_pels), + metadata_height_multi); +} + +static inline u32 ubwc_metadata_plane_buffer_size(u32 metadata_stride, + u32 metadata_buf_height) +{ + return ALIGN(metadata_stride * metadata_buf_height, SZ_4K); +} + +static inline u32 hfi_buffer_scratch2_enc(u32 frame_width, u32 frame_height, + u32 num_ref, bool ten_bit) +{ + u32 aligned_width, aligned_height, chroma_height, ref_buf_height; + u32 metadata_stride, meta_buf_height, meta_size_y, meta_size_c; + u32 ref_luma_stride_bytes, ref_chroma_height_bytes; + u32 ref_buf_size, ref_stride; + u32 luma_size, chroma_size; + u32 size; + + if (!ten_bit) { + aligned_height = ALIGN(frame_height, 32); + chroma_height = frame_height >> 1; + chroma_height = ALIGN(chroma_height, 32); + aligned_width = ALIGN(frame_width, 128); + metadata_stride = + ubwc_metadata_plane_stride(frame_width, 64, 32); + meta_buf_height = + ubwc_metadata_plane_bufheight(frame_height, 16, 8); + meta_size_y = ubwc_metadata_plane_buffer_size(metadata_stride, + meta_buf_height); + meta_size_c = ubwc_metadata_plane_buffer_size(metadata_stride, + meta_buf_height); + size = (aligned_height + chroma_height) * aligned_width + + meta_size_y + meta_size_c; + size = (size * (num_ref + 3)) + 4096; + } else { + ref_buf_height = (frame_height + (32 - 1)) & (~(32 - 1)); + ref_luma_stride_bytes = ((frame_width + 192 - 1) / 192) * 192; + ref_stride = 4 * (ref_luma_stride_bytes / 3); + ref_stride = (ref_stride + (128 - 1)) & (~(128 - 1)); + luma_size = ref_buf_height * ref_stride; + ref_chroma_height_bytes = + (((frame_height + 1) >> 1) + (32 - 1)) & (~(32 - 1)); + chroma_size = ref_stride * ref_chroma_height_bytes; + luma_size = (luma_size + (SZ_4K - 1)) & (~(SZ_4K - 1)); + chroma_size = (chroma_size + (SZ_4K - 1)) & (~(SZ_4K - 1)); + ref_buf_size = luma_size + chroma_size; + metadata_stride = + ubwc_metadata_plane_stride(frame_width, 64, 48); + meta_buf_height = + ubwc_metadata_plane_bufheight(frame_height, 16, 4); + meta_size_y = ubwc_metadata_plane_buffer_size(metadata_stride, + meta_buf_height); + meta_size_c = ubwc_metadata_plane_buffer_size(metadata_stride, + meta_buf_height); + size = ref_buf_size + meta_size_y + meta_size_c; + size = (size * (num_ref + 3)) + 4096; + } + + return size; +} + +static u32 iris_vpu_enc_scratch2_size(struct iris_inst *inst) +{ + struct v4l2_format *f = inst->fmt_dst; + u32 frame_width = f->fmt.pix_mp.width; + u32 frame_height = f->fmt.pix_mp.height; + u32 num_ref = 1; + + return hfi_buffer_scratch2_enc(frame_width, frame_height, num_ref, + false); +} + +static u32 iris_vpu_enc_vpss_size(struct iris_inst *inst) +{ + u32 ds_enable = is_scaling_enabled(inst); + struct v4l2_format *f = inst->fmt_dst; + u32 height = f->fmt.pix_mp.height; + u32 width = f->fmt.pix_mp.width; + + return hfi_buffer_vpss_enc(width, height, ds_enable, 0, 0); +} + static int output_min_count(struct iris_inst *inst) { int output_min_count = 4; @@ -571,10 +1431,10 @@ struct iris_vpu_buf_type_handle { u32 (*handle)(struct iris_inst *inst); }; -int iris_vpu_buf_size(struct iris_inst *inst, enum iris_buffer_type buffer_type) +u32 iris_vpu_buf_size(struct iris_inst *inst, enum iris_buffer_type buffer_type) { - const struct iris_vpu_buf_type_handle *buf_type_handle_arr; - u32 size = 0, buf_type_handle_size, i; + const struct iris_vpu_buf_type_handle *buf_type_handle_arr = NULL; + u32 size = 0, buf_type_handle_size = 0, i; static const struct iris_vpu_buf_type_handle dec_internal_buf_type_handle[] = { {BUF_BIN, iris_vpu_dec_bin_size }, @@ -586,8 +1446,24 @@ int iris_vpu_buf_size(struct iris_inst *inst, enum iris_buffer_type buffer_type) {BUF_SCRATCH_1, iris_vpu_dec_scratch1_size }, }; - buf_type_handle_size = ARRAY_SIZE(dec_internal_buf_type_handle); - buf_type_handle_arr = dec_internal_buf_type_handle; + static const struct iris_vpu_buf_type_handle enc_internal_buf_type_handle[] = { + {BUF_BIN, iris_vpu_enc_bin_size }, + {BUF_COMV, iris_vpu_enc_comv_size }, + {BUF_NON_COMV, iris_vpu_enc_non_comv_size }, + {BUF_LINE, iris_vpu_enc_line_size }, + {BUF_ARP, iris_vpu_enc_arp_size }, + {BUF_VPSS, iris_vpu_enc_vpss_size }, + {BUF_SCRATCH_1, iris_vpu_enc_scratch1_size }, + {BUF_SCRATCH_2, iris_vpu_enc_scratch2_size }, + }; + + if (inst->domain == DECODER) { + buf_type_handle_size = ARRAY_SIZE(dec_internal_buf_type_handle); + buf_type_handle_arr = dec_internal_buf_type_handle; + } else if (inst->domain == ENCODER) { + buf_type_handle_size = ARRAY_SIZE(enc_internal_buf_type_handle); + buf_type_handle_arr = enc_internal_buf_type_handle; + } for (i = 0; i < buf_type_handle_size; i++) { if (buf_type_handle_arr[i].type == buffer_type) { @@ -599,6 +1475,34 @@ int iris_vpu_buf_size(struct iris_inst *inst, enum iris_buffer_type buffer_type) return size; } +u32 iris_vpu33_buf_size(struct iris_inst *inst, enum iris_buffer_type buffer_type) +{ + u32 size = 0, i; + + static const struct iris_vpu_buf_type_handle enc_internal_buf_type_handle[] = { + {BUF_BIN, iris_vpu_enc_bin_size }, + {BUF_COMV, iris_vpu_enc_comv_size }, + {BUF_NON_COMV, iris_vpu_enc_non_comv_size }, + {BUF_LINE, iris_vpu33_enc_line_size }, + {BUF_ARP, iris_vpu_enc_arp_size }, + {BUF_VPSS, iris_vpu_enc_vpss_size }, + {BUF_SCRATCH_1, iris_vpu_enc_scratch1_size }, + {BUF_SCRATCH_2, iris_vpu_enc_scratch2_size }, + }; + + if (inst->domain == DECODER) + return iris_vpu_buf_size(inst, buffer_type); + + for (i = 0; i < ARRAY_SIZE(enc_internal_buf_type_handle); i++) { + if (enc_internal_buf_type_handle[i].type == buffer_type) { + size = enc_internal_buf_type_handle[i].handle(inst); + break; + } + } + + return size; +} + static u32 internal_buffer_count(struct iris_inst *inst, enum iris_buffer_type buffer_type) { @@ -628,7 +1532,10 @@ int iris_vpu_buf_count(struct iris_inst *inst, enum iris_buffer_type buffer_type case BUF_INPUT: return MIN_BUFFERS; case BUF_OUTPUT: - return output_min_count(inst); + if (inst->domain == ENCODER) + return MIN_BUFFERS; + else + return output_min_count(inst); case BUF_BIN: case BUF_COMV: case BUF_NON_COMV: @@ -636,6 +1543,9 @@ int iris_vpu_buf_count(struct iris_inst *inst, enum iris_buffer_type buffer_type case BUF_PERSIST: return internal_buffer_count(inst, buffer_type); case BUF_SCRATCH_1: + case BUF_SCRATCH_2: + case BUF_VPSS: + case BUF_ARP: return 1; /* internal buffer count needed by firmware is 1 */ case BUF_DPB: return iris_vpu_dpb_count(inst); diff --git a/drivers/media/platform/qcom/iris/iris_vpu_buffer.h b/drivers/media/platform/qcom/iris/iris_vpu_buffer.h index ee95fd20b794..04f0b7400a1e 100644 --- a/drivers/media/platform/qcom/iris/iris_vpu_buffer.h +++ b/drivers/media/platform/qcom/iris/iris_vpu_buffer.h @@ -41,6 +41,7 @@ struct iris_inst; #define SIZE_SLIST_BUF_H265 (BIT(10)) #define H265_DISPLAY_BUF_SIZE (3072) #define H265_NUM_FRM_INFO (48) +#define SIZE_ONE_SLICE_BUF 256 #define VP9_NUM_FRAME_INFO_BUF 32 #define VP9_NUM_PROBABILITY_TABLE_BUF (VP9_NUM_FRAME_INFO_BUF + 4) @@ -80,6 +81,26 @@ struct iris_inst; #define MAX_PE_NBR_DATA_LCU64_LINE_BUFFER_SIZE 384 #define MAX_FE_NBR_DATA_LUMA_LINE_BUFFER_SIZE 640 +#define SIZE_SLICE_CMD_BUFFER (ALIGN(20480, 256)) +#define SIZE_SPS_PPS_SLICE_HDR (2048 + 4096) +#define SIZE_BSE_SLICE_CMD_BUF ((((8192 << 2) + 7) & (~7)) * 3) +#define SIZE_LAMBDA_LUT (256 * 11) + +#define HFI_COL_FMT_NV12C_Y_TILE_HEIGHT (8) +#define HFI_COL_FMT_NV12C_Y_TILE_WIDTH (32) +#define HFI_COL_FMT_TP10C_Y_TILE_HEIGHT (4) +#define HFI_COL_FMT_TP10C_Y_TILE_WIDTH (48) + +#define IRIS_METADATA_STRIDE_MULTIPLE 64 +#define IRIS_METADATA_HEIGHT_MULTIPLE 16 + +#define HFI_BUFFER_ARP_ENC 204800 + +#define MAX_WIDTH 4096 +#define MAX_HEIGHT 2304 +#define NUM_MBS_4K (DIV_ROUND_UP(MAX_WIDTH, 16) * DIV_ROUND_UP(MAX_HEIGHT, 16)) +#define NUM_MBS_720P (((ALIGN(1280, 16)) >> 4) * ((ALIGN(736, 16)) >> 4)) + static inline u32 size_h264d_lb_fe_top_data(u32 frame_width) { return MAX_FE_NBR_DATA_LUMA_LINE_BUFFER_SIZE * ALIGN(frame_width, 16) * 3; @@ -125,7 +146,8 @@ static inline u32 size_h264d_qp(u32 frame_width, u32 frame_height) return DIV_ROUND_UP(frame_width, 64) * DIV_ROUND_UP(frame_height, 64) * 128; } -int iris_vpu_buf_size(struct iris_inst *inst, enum iris_buffer_type buffer_type); +u32 iris_vpu_buf_size(struct iris_inst *inst, enum iris_buffer_type buffer_type); +u32 iris_vpu33_buf_size(struct iris_inst *inst, enum iris_buffer_type buffer_type); int iris_vpu_buf_count(struct iris_inst *inst, enum iris_buffer_type buffer_type); #endif diff --git a/drivers/media/platform/qcom/iris/iris_vpu_common.c b/drivers/media/platform/qcom/iris/iris_vpu_common.c index 268e45acaa7c..bb98950e018f 100644 --- a/drivers/media/platform/qcom/iris/iris_vpu_common.c +++ b/drivers/media/platform/qcom/iris/iris_vpu_common.c @@ -84,6 +84,7 @@ static void iris_vpu_interrupt_init(struct iris_core *core) static void iris_vpu_setup_ucregion_memory_map(struct iris_core *core) { u32 queue_size, value; + const struct vpu_ops *vpu_ops = core->iris_platform_data->vpu_ops; /* Iris hardware requires 4K queue alignment */ queue_size = ALIGN(sizeof(struct iris_hfi_queue_table_header) + @@ -105,6 +106,9 @@ static void iris_vpu_setup_ucregion_memory_map(struct iris_core *core) value = (u32)core->sfr_daddr + core->iris_platform_data->core_arch; writel(value, core->reg_base + SFR_ADDR); } + + if (vpu_ops->program_bootup_registers) + vpu_ops->program_bootup_registers(core); } int iris_vpu_boot_firmware(struct iris_core *core) @@ -271,7 +275,7 @@ void iris_vpu_power_off(struct iris_core *core) disable_irq_nosync(core->irq); } -static int iris_vpu_power_on_controller(struct iris_core *core) +int iris_vpu_power_on_controller(struct iris_core *core) { u32 rst_tbl_size = core->iris_platform_data->clk_rst_tbl_size; int ret; @@ -302,7 +306,7 @@ err_disable_power: return ret; } -static int iris_vpu_power_on_hw(struct iris_core *core) +int iris_vpu_power_on_hw(struct iris_core *core) { int ret; @@ -337,11 +341,11 @@ int iris_vpu_power_on(struct iris_core *core) if (ret) goto err; - ret = iris_vpu_power_on_controller(core); + ret = core->iris_platform_data->vpu_ops->power_on_controller(core); if (ret) goto err_unvote_icc; - ret = iris_vpu_power_on_hw(core); + ret = core->iris_platform_data->vpu_ops->power_on_hw(core); if (ret) goto err_power_off_ctrl; @@ -359,7 +363,7 @@ int iris_vpu_power_on(struct iris_core *core) return 0; err_power_off_ctrl: - iris_vpu_power_off_controller(core); + core->iris_platform_data->vpu_ops->power_off_controller(core); err_unvote_icc: iris_unset_icc_bw(core); err: diff --git a/drivers/media/platform/qcom/iris/iris_vpu_common.h b/drivers/media/platform/qcom/iris/iris_vpu_common.h index 93b7fa27be3b..d636e287457a 100644 --- a/drivers/media/platform/qcom/iris/iris_vpu_common.h +++ b/drivers/media/platform/qcom/iris/iris_vpu_common.h @@ -11,10 +11,14 @@ struct iris_core; extern const struct vpu_ops iris_vpu2_ops; extern const struct vpu_ops iris_vpu3_ops; extern const struct vpu_ops iris_vpu33_ops; +extern const struct vpu_ops iris_vpu35_ops; struct vpu_ops { void (*power_off_hw)(struct iris_core *core); + int (*power_on_hw)(struct iris_core *core); int (*power_off_controller)(struct iris_core *core); + int (*power_on_controller)(struct iris_core *core); + void (*program_bootup_registers)(struct iris_core *core); u64 (*calc_freq)(struct iris_inst *inst, size_t data_size); }; @@ -23,6 +27,8 @@ void iris_vpu_raise_interrupt(struct iris_core *core); void iris_vpu_clear_interrupt(struct iris_core *core); int iris_vpu_watchdog(struct iris_core *core, u32 intr_status); int iris_vpu_prepare_pc(struct iris_core *core); +int iris_vpu_power_on_controller(struct iris_core *core); +int iris_vpu_power_on_hw(struct iris_core *core); int iris_vpu_power_on(struct iris_core *core); int iris_vpu_power_off_controller(struct iris_core *core); void iris_vpu_power_off_hw(struct iris_core *core); diff --git a/drivers/media/platform/qcom/venus/core.c b/drivers/media/platform/qcom/venus/core.c index 4c049c694d9c..abf959b8f3a6 100644 --- a/drivers/media/platform/qcom/venus/core.c +++ b/drivers/media/platform/qcom/venus/core.c @@ -254,14 +254,19 @@ err: static void venus_assign_register_offsets(struct venus_core *core) { - if (IS_IRIS2(core) || IS_IRIS2_1(core)) { - core->vbif_base = core->base + VBIF_BASE; + if (IS_IRIS2(core) || IS_IRIS2_1(core) || IS_AR50_LITE(core)) { core->cpu_base = core->base + CPU_BASE_V6; core->cpu_cs_base = core->base + CPU_CS_BASE_V6; core->cpu_ic_base = core->base + CPU_IC_BASE_V6; core->wrapper_base = core->base + WRAPPER_BASE_V6; core->wrapper_tz_base = core->base + WRAPPER_TZ_BASE_V6; - core->aon_base = core->base + AON_BASE_V6; + if (IS_AR50_LITE(core)) { + core->vbif_base = NULL; + core->aon_base = NULL; + } else { + core->vbif_base = core->base + VBIF_BASE; + core->aon_base = core->base + AON_BASE_V6; + } } else { core->vbif_base = core->base + VBIF_BASE; core->cpu_base = core->base + CPU_BASE; @@ -448,24 +453,18 @@ static int venus_probe(struct platform_device *pdev) if (ret < 0) goto err_runtime_disable; - if (core->res->dec_nodename || core->res->enc_nodename) { - ret = venus_add_dynamic_nodes(core); - if (ret) - goto err_runtime_disable; - } - - ret = of_platform_populate(dev->of_node, NULL, NULL, dev); - if (ret) - goto err_remove_dynamic_nodes; - ret = venus_firmware_init(core); if (ret) - goto err_of_depopulate; + goto err_runtime_disable; ret = venus_boot(core); if (ret) goto err_firmware_deinit; + ret = venus_firmware_cfg(core); + if (ret) + goto err_venus_shutdown; + ret = hfi_core_resume(core, true); if (ret) goto err_venus_shutdown; @@ -474,34 +473,48 @@ static int venus_probe(struct platform_device *pdev) if (ret) goto err_venus_shutdown; - ret = venus_enumerate_codecs(core, VIDC_SESSION_TYPE_DEC); + ret = venus_firmware_check(core); if (ret) goto err_core_deinit; + if (core->res->dec_nodename || core->res->enc_nodename) { + ret = venus_add_dynamic_nodes(core); + if (ret) + goto err_core_deinit; + } + + ret = of_platform_populate(dev->of_node, NULL, NULL, dev); + if (ret) + goto err_remove_dynamic_nodes; + + ret = venus_enumerate_codecs(core, VIDC_SESSION_TYPE_DEC); + if (ret) + goto err_of_depopulate; + ret = venus_enumerate_codecs(core, VIDC_SESSION_TYPE_ENC); if (ret) - goto err_core_deinit; + goto err_of_depopulate; ret = pm_runtime_put_sync(dev); if (ret) { pm_runtime_get_noresume(dev); - goto err_core_deinit; + goto err_of_depopulate; } venus_dbgfs_init(core); return 0; +err_of_depopulate: + of_platform_depopulate(dev); +err_remove_dynamic_nodes: + venus_remove_dynamic_nodes(core); err_core_deinit: hfi_core_deinit(core, false); err_venus_shutdown: venus_shutdown(core); err_firmware_deinit: venus_firmware_deinit(core); -err_of_depopulate: - of_platform_depopulate(dev); -err_remove_dynamic_nodes: - venus_remove_dynamic_nodes(core); err_runtime_disable: pm_runtime_put_noidle(dev); pm_runtime_disable(dev); @@ -596,7 +609,7 @@ err_cpucfg_path: return ret; } -void venus_close_common(struct venus_inst *inst) +void venus_close_common(struct venus_inst *inst, struct file *filp) { /* * Make sure we don't have IRQ/IRQ-thread currently running @@ -607,7 +620,7 @@ void venus_close_common(struct venus_inst *inst) v4l2_m2m_ctx_release(inst->m2m_ctx); v4l2_m2m_release(inst->m2m_dev); hfi_session_destroy(inst); - v4l2_fh_del(&inst->fh); + v4l2_fh_del(&inst->fh, filp); v4l2_fh_exit(&inst->fh); v4l2_ctrl_handler_free(&inst->ctrl_handler); @@ -1057,15 +1070,65 @@ static const struct venus_resources sc7280_res = { .enc_nodename = "video-encoder", }; +static const struct bw_tbl qcm2290_bw_table_dec[] = { + { 352800, 597000, 0, 746000, 0 }, /* 1080p@30 + 720p@30 */ + { 244800, 413000, 0, 516000, 0 }, /* 1080p@30 */ + { 216000, 364000, 0, 454000, 0 }, /* 720p@60 */ + { 108000, 182000, 0, 227000, 0 }, /* 720p@30 */ +}; + +static const struct bw_tbl qcm2290_bw_table_enc[] = { + { 352800, 396000, 0, 0, 0 }, /* 1080p@30 + 720p@30 */ + { 244800, 275000, 0, 0, 0 }, /* 1080p@30 */ + { 216000, 242000, 0, 0, 0 }, /* 720p@60 */ + { 108000, 121000, 0, 0, 0 }, /* 720p@30 */ +}; + +static const struct firmware_version min_fw = { + .major = 6, .minor = 0, .rev = 55, +}; + +static const struct venus_resources qcm2290_res = { + .bw_tbl_dec = qcm2290_bw_table_dec, + .bw_tbl_dec_size = ARRAY_SIZE(qcm2290_bw_table_dec), + .bw_tbl_enc = qcm2290_bw_table_enc, + .bw_tbl_enc_size = ARRAY_SIZE(qcm2290_bw_table_enc), + .clks = { "core", "iface", "bus", "throttle" }, + .clks_num = 4, + .vcodec0_clks = { "vcodec0_core", "vcodec0_bus" }, + .vcodec_clks_num = 2, + .vcodec_pmdomains = (const char *[]) { "venus", "vcodec0" }, + .vcodec_pmdomains_num = 2, + .opp_pmdomain = (const char *[]) { "cx" }, + .vcodec_num = 1, + .hfi_version = HFI_VERSION_4XX, + .vpu_version = VPU_VERSION_AR50_LITE, + .max_load = 352800, + .num_vpp_pipes = 1, + .vmem_id = VIDC_RESOURCE_NONE, + .vmem_size = 0, + .vmem_addr = 0, + .cp_start = 0, + .cp_size = 0x70800000, + .cp_nonpixel_start = 0x1000000, + .cp_nonpixel_size = 0x24800000, + .dma_mask = 0xe0000000 - 1, + .fwname = "qcom/venus-6.0/venus.mbn", + .dec_nodename = "video-decoder", + .enc_nodename = "video-encoder", + .min_fw = &min_fw, +}; + static const struct of_device_id venus_dt_match[] = { { .compatible = "qcom,msm8916-venus", .data = &msm8916_res, }, { .compatible = "qcom,msm8996-venus", .data = &msm8996_res, }, { .compatible = "qcom,msm8998-venus", .data = &msm8998_res, }, + { .compatible = "qcom,qcm2290-venus", .data = &qcm2290_res, }, + { .compatible = "qcom,sc7180-venus", .data = &sc7180_res, }, + { .compatible = "qcom,sc7280-venus", .data = &sc7280_res, }, { .compatible = "qcom,sdm660-venus", .data = &sdm660_res, }, { .compatible = "qcom,sdm845-venus", .data = &sdm845_res, }, { .compatible = "qcom,sdm845-venus-v2", .data = &sdm845_res_v2, }, - { .compatible = "qcom,sc7180-venus", .data = &sc7180_res, }, - { .compatible = "qcom,sc7280-venus", .data = &sc7280_res, }, { .compatible = "qcom,sm8250-venus", .data = &sm8250_res, }, { } }; diff --git a/drivers/media/platform/qcom/venus/core.h b/drivers/media/platform/qcom/venus/core.h index 5b1ba1c69adb..7506f5d0f609 100644 --- a/drivers/media/platform/qcom/venus/core.h +++ b/drivers/media/platform/qcom/venus/core.h @@ -58,6 +58,12 @@ enum vpu_version { VPU_VERSION_IRIS2_1, }; +struct firmware_version { + u32 major; + u32 minor; + u32 rev; +}; + struct venus_resources { u64 dma_mask; const struct freq_tbl *freq_tbl; @@ -94,6 +100,7 @@ struct venus_resources { const char *fwname; const char *enc_nodename; const char *dec_nodename; + const struct firmware_version *min_fw; }; enum venus_fmt { @@ -231,11 +238,7 @@ struct venus_core { unsigned int core0_usage_count; unsigned int core1_usage_count; struct dentry *root; - struct venus_img_version { - u32 major; - u32 minor; - u32 rev; - } venus_ver; + struct firmware_version venus_ver; unsigned long dump_core; struct of_changeset *ocs; bool hwmode_dev; @@ -530,12 +533,17 @@ struct venus_inst { #define IS_IRIS2(core) ((core)->res->vpu_version == VPU_VERSION_IRIS2) #define IS_IRIS2_1(core) ((core)->res->vpu_version == VPU_VERSION_IRIS2_1) +static inline bool is_lite(struct venus_core *core) +{ + return IS_AR50_LITE(core); +} + #define ctrl_to_inst(ctrl) \ container_of((ctrl)->handler, struct venus_inst, ctrl_handler) static inline struct venus_inst *to_inst(struct file *filp) { - return container_of(filp->private_data, struct venus_inst, fh); + return container_of(file_to_v4l2_fh(filp), struct venus_inst, fh); } static inline void *to_hfi_priv(struct venus_core *core) @@ -573,5 +581,5 @@ is_fw_rev_or_older(struct venus_core *core, u32 vmajor, u32 vminor, u32 vrev) (core)->venus_ver.rev <= vrev); } -void venus_close_common(struct venus_inst *inst); +void venus_close_common(struct venus_inst *inst, struct file *filp); #endif diff --git a/drivers/media/platform/qcom/venus/firmware.c b/drivers/media/platform/qcom/venus/firmware.c index 862d0718f694..af0ac40bec9b 100644 --- a/drivers/media/platform/qcom/venus/firmware.c +++ b/drivers/media/platform/qcom/venus/firmware.c @@ -30,7 +30,7 @@ static void venus_reset_cpu(struct venus_core *core) u32 fw_size = core->fw.mapped_mem_size; void __iomem *wrapper_base; - if (IS_IRIS2_1(core)) + if (IS_IRIS2(core) || IS_IRIS2_1(core)) wrapper_base = core->wrapper_tz_base; else wrapper_base = core->wrapper_base; @@ -42,7 +42,7 @@ static void venus_reset_cpu(struct venus_core *core) writel(fw_size, wrapper_base + WRAPPER_NONPIX_START_ADDR); writel(fw_size, wrapper_base + WRAPPER_NONPIX_END_ADDR); - if (IS_IRIS2_1(core)) { + if (IS_IRIS2(core) || IS_IRIS2_1(core)) { /* Bring XTSS out of reset */ writel(0, wrapper_base + WRAPPER_TZ_XTSS_SW_RESET); } else { @@ -68,7 +68,7 @@ int venus_set_hw_state(struct venus_core *core, bool resume) if (resume) { venus_reset_cpu(core); } else { - if (IS_IRIS2_1(core)) + if (IS_IRIS2(core) || IS_IRIS2_1(core)) writel(WRAPPER_XTSS_SW_RESET_BIT, core->wrapper_tz_base + WRAPPER_TZ_XTSS_SW_RESET); else @@ -181,7 +181,7 @@ static int venus_shutdown_no_tz(struct venus_core *core) void __iomem *wrapper_base = core->wrapper_base; void __iomem *wrapper_tz_base = core->wrapper_tz_base; - if (IS_IRIS2_1(core)) { + if (IS_IRIS2(core) || IS_IRIS2_1(core)) { /* Assert the reset to XTSS */ reg = readl(wrapper_tz_base + WRAPPER_TZ_XTSS_SW_RESET); reg |= WRAPPER_XTSS_SW_RESET_BIT; @@ -207,6 +207,16 @@ static int venus_shutdown_no_tz(struct venus_core *core) return 0; } +int venus_firmware_cfg(struct venus_core *core) +{ + void __iomem *cpu_cs_base = core->cpu_cs_base; + + if (IS_AR50_LITE(core)) + writel(CPU_CS_VCICMD_ARP_OFF, cpu_cs_base + CPU_CS_VCICMD); + + return 0; +} + int venus_boot(struct venus_core *core) { struct device *dev = core->dev; @@ -280,6 +290,26 @@ int venus_shutdown(struct venus_core *core) return ret; } +int venus_firmware_check(struct venus_core *core) +{ + const struct firmware_version *req = core->res->min_fw; + const struct firmware_version *run = &core->venus_ver; + + if (!req) + return 0; + + if (!is_fw_rev_or_newer(core, req->major, req->minor, req->rev)) + goto error; + + return 0; +error: + dev_err(core->dev, "Firmware v%d.%d.%d < v%d.%d.%d\n", + run->major, run->minor, run->rev, + req->major, req->minor, req->rev); + + return -EINVAL; +} + int venus_firmware_init(struct venus_core *core) { struct platform_device_info info; diff --git a/drivers/media/platform/qcom/venus/firmware.h b/drivers/media/platform/qcom/venus/firmware.h index aaccd847fa30..87e1d922b369 100644 --- a/drivers/media/platform/qcom/venus/firmware.h +++ b/drivers/media/platform/qcom/venus/firmware.h @@ -9,6 +9,8 @@ struct device; int venus_firmware_init(struct venus_core *core); void venus_firmware_deinit(struct venus_core *core); +int venus_firmware_check(struct venus_core *core); +int venus_firmware_cfg(struct venus_core *core); int venus_boot(struct venus_core *core); int venus_shutdown(struct venus_core *core); int venus_set_hw_state(struct venus_core *core, bool suspend); diff --git a/drivers/media/platform/qcom/venus/helpers.c b/drivers/media/platform/qcom/venus/helpers.c index 8295542e1a7c..2e4363f82231 100644 --- a/drivers/media/platform/qcom/venus/helpers.c +++ b/drivers/media/platform/qcom/venus/helpers.c @@ -1715,11 +1715,17 @@ int venus_helper_session_init(struct venus_inst *inst) if (ret) return ret; - inst->clk_data.vpp_freq = hfi_platform_get_codec_vpp_freq(version, codec, + inst->clk_data.vpp_freq = hfi_platform_get_codec_vpp_freq(inst->core, + version, + codec, session_type); - inst->clk_data.vsp_freq = hfi_platform_get_codec_vsp_freq(version, codec, + inst->clk_data.vsp_freq = hfi_platform_get_codec_vsp_freq(inst->core, + version, + codec, session_type); - inst->clk_data.low_power_freq = hfi_platform_get_codec_lp_freq(version, codec, + inst->clk_data.low_power_freq = hfi_platform_get_codec_lp_freq(inst->core, + version, + codec, session_type); return 0; diff --git a/drivers/media/platform/qcom/venus/hfi_msgs.c b/drivers/media/platform/qcom/venus/hfi_msgs.c index cf0d97cbc463..47b99d5b5af7 100644 --- a/drivers/media/platform/qcom/venus/hfi_msgs.c +++ b/drivers/media/platform/qcom/venus/hfi_msgs.c @@ -277,7 +277,12 @@ static void hfi_sys_init_done(struct venus_core *core, struct venus_inst *inst, done: core->error = error; - complete(&core->done); + /* + * Since core_init could ask for the firmware version to be validated, + * completion might have to wait until the version is retrieved. + */ + if (!core->res->min_fw) + complete(&core->done); } static void @@ -328,6 +333,10 @@ done: 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); + + /* core_init could have had to wait for a version check */ + if (core->res->min_fw) + complete(&core->done); } static void hfi_sys_property_info(struct venus_core *core, diff --git a/drivers/media/platform/qcom/venus/hfi_parser.c b/drivers/media/platform/qcom/venus/hfi_parser.c index 1b3db2caa99f..92765f9c8873 100644 --- a/drivers/media/platform/qcom/venus/hfi_parser.c +++ b/drivers/media/platform/qcom/venus/hfi_parser.c @@ -282,7 +282,7 @@ static int hfi_platform_parser(struct venus_core *core, struct venus_inst *inst) return ret; if (plat->capabilities) - caps = plat->capabilities(&entries); + caps = plat->capabilities(core, &entries); if (!caps || !entries || !count) return -EINVAL; diff --git a/drivers/media/platform/qcom/venus/hfi_platform.c b/drivers/media/platform/qcom/venus/hfi_platform.c index 643e5aa138f5..cde7f93045ac 100644 --- a/drivers/media/platform/qcom/venus/hfi_platform.c +++ b/drivers/media/platform/qcom/venus/hfi_platform.c @@ -21,7 +21,9 @@ const struct hfi_platform *hfi_platform_get(enum hfi_version version) } unsigned long -hfi_platform_get_codec_vpp_freq(enum hfi_version version, u32 codec, u32 session_type) +hfi_platform_get_codec_vpp_freq(struct venus_core *core, + enum hfi_version version, u32 codec, + u32 session_type) { const struct hfi_platform *plat; unsigned long freq = 0; @@ -31,13 +33,15 @@ hfi_platform_get_codec_vpp_freq(enum hfi_version version, u32 codec, u32 session return 0; if (plat->codec_vpp_freq) - freq = plat->codec_vpp_freq(session_type, codec); + freq = plat->codec_vpp_freq(core, session_type, codec); return freq; } unsigned long -hfi_platform_get_codec_vsp_freq(enum hfi_version version, u32 codec, u32 session_type) +hfi_platform_get_codec_vsp_freq(struct venus_core *core, + enum hfi_version version, u32 codec, + u32 session_type) { const struct hfi_platform *plat; unsigned long freq = 0; @@ -47,13 +51,15 @@ hfi_platform_get_codec_vsp_freq(enum hfi_version version, u32 codec, u32 session return 0; if (plat->codec_vpp_freq) - freq = plat->codec_vsp_freq(session_type, codec); + freq = plat->codec_vsp_freq(core, session_type, codec); return freq; } unsigned long -hfi_platform_get_codec_lp_freq(enum hfi_version version, u32 codec, u32 session_type) +hfi_platform_get_codec_lp_freq(struct venus_core *core, + enum hfi_version version, u32 codec, + u32 session_type) { const struct hfi_platform *plat; unsigned long freq = 0; @@ -63,13 +69,14 @@ hfi_platform_get_codec_lp_freq(enum hfi_version version, u32 codec, u32 session_ return 0; if (plat->codec_lp_freq) - freq = plat->codec_lp_freq(session_type, codec); + freq = plat->codec_lp_freq(core, session_type, codec); return freq; } int -hfi_platform_get_codecs(struct venus_core *core, u32 *enc_codecs, u32 *dec_codecs, u32 *count) +hfi_platform_get_codecs(struct venus_core *core, u32 *enc_codecs, + u32 *dec_codecs, u32 *count) { const struct hfi_platform *plat; @@ -78,7 +85,7 @@ hfi_platform_get_codecs(struct venus_core *core, u32 *enc_codecs, u32 *dec_codec return -EINVAL; if (plat->codecs) - plat->codecs(enc_codecs, dec_codecs, count); + plat->codecs(core, enc_codecs, dec_codecs, count); if (IS_IRIS2_1(core)) { *enc_codecs &= ~HFI_VIDEO_CODEC_VP8; diff --git a/drivers/media/platform/qcom/venus/hfi_platform.h b/drivers/media/platform/qcom/venus/hfi_platform.h index ec89a90a8129..5e4f8013a6b1 100644 --- a/drivers/media/platform/qcom/venus/hfi_platform.h +++ b/drivers/media/platform/qcom/venus/hfi_platform.h @@ -47,11 +47,16 @@ struct hfi_platform_codec_freq_data { }; struct hfi_platform { - unsigned long (*codec_vpp_freq)(u32 session_type, u32 codec); - unsigned long (*codec_vsp_freq)(u32 session_type, u32 codec); - unsigned long (*codec_lp_freq)(u32 session_type, u32 codec); - void (*codecs)(u32 *enc_codecs, u32 *dec_codecs, u32 *count); - const struct hfi_plat_caps *(*capabilities)(unsigned int *entries); + unsigned long (*codec_vpp_freq)(struct venus_core *core, + u32 session_type, u32 codec); + unsigned long (*codec_vsp_freq)(struct venus_core *core, + u32 session_type, u32 codec); + unsigned long (*codec_lp_freq)(struct venus_core *core, + u32 session_type, u32 codec); + void (*codecs)(struct venus_core *core, u32 *enc_codecs, + u32 *dec_codecs, u32 *count); + const struct hfi_plat_caps *(*capabilities)(struct venus_core *core, + unsigned int *entries); int (*bufreq)(struct hfi_plat_buffers_params *params, u32 session_type, u32 buftype, struct hfi_buffer_requirements *bufreq); }; @@ -60,12 +65,15 @@ extern const struct hfi_platform hfi_plat_v4; extern const struct hfi_platform hfi_plat_v6; const struct hfi_platform *hfi_platform_get(enum hfi_version version); -unsigned long hfi_platform_get_codec_vpp_freq(enum hfi_version version, u32 codec, - u32 session_type); -unsigned long hfi_platform_get_codec_vsp_freq(enum hfi_version version, u32 codec, - u32 session_type); -unsigned long hfi_platform_get_codec_lp_freq(enum hfi_version version, u32 codec, - u32 session_type); -int hfi_platform_get_codecs(struct venus_core *core, u32 *enc_codecs, u32 *dec_codecs, - u32 *count); +unsigned long hfi_platform_get_codec_vpp_freq(struct venus_core *core, + enum hfi_version version, + u32 codec, u32 session_type); +unsigned long hfi_platform_get_codec_vsp_freq(struct venus_core *core, + enum hfi_version version, + u32 codec, u32 session_type); +unsigned long hfi_platform_get_codec_lp_freq(struct venus_core *core, + enum hfi_version version, + u32 codec, u32 session_type); +int hfi_platform_get_codecs(struct venus_core *core, u32 *enc_codecs, + u32 *dec_codecs, u32 *count); #endif diff --git a/drivers/media/platform/qcom/venus/hfi_platform_v4.c b/drivers/media/platform/qcom/venus/hfi_platform_v4.c index e3f0a90a567b..cda888b56b5d 100644 --- a/drivers/media/platform/qcom/venus/hfi_platform_v4.c +++ b/drivers/media/platform/qcom/venus/hfi_platform_v4.c @@ -2,6 +2,7 @@ /* * Copyright (c) 2020, The Linux Foundation. All rights reserved. */ +#include "core.h" #include "hfi_platform.h" static const struct hfi_plat_caps caps[] = { @@ -245,20 +246,150 @@ static const struct hfi_plat_caps caps[] = { .num_fmts = 4, } }; -static const struct hfi_plat_caps *get_capabilities(unsigned int *entries) +static const struct hfi_plat_caps caps_lite[] = { { - *entries = ARRAY_SIZE(caps); - return caps; + .codec = HFI_VIDEO_CODEC_H264, + .domain = VIDC_SESSION_TYPE_DEC, + .caps[0] = {HFI_CAPABILITY_FRAME_WIDTH, 128, 1920, 1}, + .caps[1] = {HFI_CAPABILITY_FRAME_HEIGHT, 128, 1920, 1}, + .caps[2] = {HFI_CAPABILITY_MBS_PER_FRAME, 64, 8160, 1}, + .caps[3] = {HFI_CAPABILITY_BITRATE, 1, 60000000, 1 }, + .caps[4] = {HFI_CAPABILITY_MBS_PER_SECOND, 64, 244800, 1}, + .caps[5] = {HFI_CAPABILITY_FRAMERATE, 1, 120, 1}, + .caps[6] = {HFI_CAPABILITY_MAX_VIDEOCORES, 0, 1, 1}, + .num_caps = 7, + .pl[0] = { HFI_H264_PROFILE_BASELINE, HFI_H264_LEVEL_5}, + .pl[1] = {HFI_H264_PROFILE_MAIN, HFI_H264_LEVEL_5}, + .pl[2] = {HFI_H264_PROFILE_HIGH, HFI_H264_LEVEL_5}, + .pl[3] = {HFI_H264_PROFILE_CONSTRAINED_BASE, HFI_H264_LEVEL_5}, + .pl[4] = {HFI_H264_PROFILE_CONSTRAINED_HIGH, HFI_H264_LEVEL_5}, + .num_pl = 5, + .fmts[0] = {HFI_BUFFER_OUTPUT, HFI_COLOR_FORMAT_NV12_UBWC}, + .fmts[1] = {HFI_BUFFER_OUTPUT2, HFI_COLOR_FORMAT_NV12_UBWC}, + .fmts[2] = {HFI_BUFFER_OUTPUT2, HFI_COLOR_FORMAT_NV12}, + .fmts[3] = {HFI_BUFFER_OUTPUT2, HFI_COLOR_FORMAT_NV21}, + .num_fmts = 4, +}, { + .codec = HFI_VIDEO_CODEC_HEVC, + .domain = VIDC_SESSION_TYPE_DEC, + .caps[0] = {HFI_CAPABILITY_FRAME_WIDTH, 128, 1920, 1}, + .caps[1] = {HFI_CAPABILITY_FRAME_HEIGHT, 128, 1920, 1}, + .caps[2] = {HFI_CAPABILITY_MBS_PER_FRAME, 64, 8160, 1}, + .caps[3] = {HFI_CAPABILITY_BITRATE, 1, 60000000, 1 }, + .caps[4] = {HFI_CAPABILITY_MBS_PER_SECOND, 64, 244800, 1}, + .caps[5] = {HFI_CAPABILITY_FRAMERATE, 1, 120, 1}, + .caps[6] = {HFI_CAPABILITY_MAX_VIDEOCORES, 0, 1, 1}, + .num_caps = 7, + .pl[0] = {HFI_HEVC_PROFILE_MAIN, HFI_HEVC_LEVEL_5 | HFI_HEVC_TIER_HIGH0 << 28 }, + .pl[1] = {HFI_HEVC_PROFILE_MAIN10, HFI_HEVC_LEVEL_5 | HFI_HEVC_TIER_HIGH0 << 28 }, + .num_pl = 2, + .fmts[0] = {HFI_BUFFER_OUTPUT, HFI_COLOR_FORMAT_NV12_UBWC}, + .fmts[1] = {HFI_BUFFER_OUTPUT2, HFI_COLOR_FORMAT_NV12_UBWC}, + .fmts[2] = {HFI_BUFFER_OUTPUT2, HFI_COLOR_FORMAT_NV12}, + .fmts[3] = {HFI_BUFFER_OUTPUT2, HFI_COLOR_FORMAT_NV21}, + .num_fmts = 4, +}, { + .codec = HFI_VIDEO_CODEC_VP9, + .domain = VIDC_SESSION_TYPE_DEC, + .caps[0] = {HFI_CAPABILITY_FRAME_WIDTH, 128, 1920, 1}, + .caps[1] = {HFI_CAPABILITY_FRAME_HEIGHT, 128, 1920, 1}, + .caps[2] = {HFI_CAPABILITY_MBS_PER_FRAME, 64, 8160, 1}, + .caps[3] = {HFI_CAPABILITY_BITRATE, 1, 60000000, 1 }, + .caps[4] = {HFI_CAPABILITY_MBS_PER_SECOND, 64, 244800, 1}, + .caps[5] = {HFI_CAPABILITY_FRAMERATE, 1, 120, 1}, + .caps[6] = {HFI_CAPABILITY_MAX_VIDEOCORES, 0, 1, 1}, + .num_caps = 7, + .pl[0] = {HFI_VP9_PROFILE_P0, 200}, + .pl[1] = {HFI_VP9_PROFILE_P2_10B, 200}, + .num_pl = 2, + .fmts[0] = {HFI_BUFFER_OUTPUT, HFI_COLOR_FORMAT_NV12_UBWC}, + .fmts[1] = {HFI_BUFFER_OUTPUT2, HFI_COLOR_FORMAT_NV12_UBWC}, + .fmts[2] = {HFI_BUFFER_OUTPUT2, HFI_COLOR_FORMAT_NV12}, + .fmts[3] = {HFI_BUFFER_OUTPUT2, HFI_COLOR_FORMAT_NV21}, + .num_fmts = 4, +}, { + .codec = HFI_VIDEO_CODEC_H264, + .domain = VIDC_SESSION_TYPE_ENC, + .caps[0] = {HFI_CAPABILITY_FRAME_WIDTH, 128, 1920, 1}, + .caps[1] = {HFI_CAPABILITY_FRAME_HEIGHT, 128, 1920, 1}, + .caps[2] = {HFI_CAPABILITY_MBS_PER_FRAME, 64, 8160, 1}, + .caps[3] = {HFI_CAPABILITY_BITRATE, 1, 60000000, 1 }, + .caps[4] = {HFI_CAPABILITY_MBS_PER_SECOND, 64, 244800, 1}, + .caps[5] = {HFI_CAPABILITY_FRAMERATE, 1, 120, 1}, + .caps[6] = {HFI_CAPABILITY_MAX_VIDEOCORES, 0, 1, 1}, + .caps[7] = {HFI_CAPABILITY_HIER_P_NUM_ENH_LAYERS, 0, 6, 1}, + .caps[8] = {HFI_CAPABILITY_ENC_LTR_COUNT, 0, 4, 1}, + .caps[9] = {HFI_CAPABILITY_MBS_PER_SECOND_POWERSAVE, 0, 244800, 1}, + .caps[10] = {HFI_CAPABILITY_I_FRAME_QP, 0, 51, 1}, + .caps[11] = {HFI_CAPABILITY_P_FRAME_QP, 0, 51, 1}, + .caps[12] = {HFI_CAPABILITY_B_FRAME_QP, 0, 51, 1}, + .caps[13] = {HFI_CAPABILITY_SLICE_BYTE, 1, 10, 1}, + .caps[14] = {HFI_CAPABILITY_SLICE_MB, 1, 10, 1}, + .num_caps = 15, + .pl[0] = {HFI_H264_PROFILE_BASELINE, HFI_H264_LEVEL_5}, + .pl[1] = {HFI_H264_PROFILE_MAIN, HFI_H264_LEVEL_5}, + .pl[2] = {HFI_H264_PROFILE_HIGH, HFI_H264_LEVEL_5}, + .pl[3] = {HFI_H264_PROFILE_CONSTRAINED_BASE, HFI_H264_LEVEL_5}, + .pl[4] = {HFI_H264_PROFILE_CONSTRAINED_HIGH, HFI_H264_LEVEL_5}, + .num_pl = 5, + .fmts[0] = {HFI_BUFFER_INPUT, HFI_COLOR_FORMAT_NV12}, + .fmts[1] = {HFI_BUFFER_INPUT, HFI_COLOR_FORMAT_NV12_UBWC}, + .num_fmts = 2, +}, { + .codec = HFI_VIDEO_CODEC_HEVC, + .domain = VIDC_SESSION_TYPE_ENC, + .caps[0] = {HFI_CAPABILITY_FRAME_WIDTH, 128, 1920, 1}, + .caps[1] = {HFI_CAPABILITY_FRAME_HEIGHT, 128, 1920, 1}, + .caps[2] = {HFI_CAPABILITY_MBS_PER_FRAME, 64, 8160, 1}, + .caps[3] = {HFI_CAPABILITY_BITRATE, 1, 60000000, 1 }, + .caps[4] = {HFI_CAPABILITY_MBS_PER_SECOND, 64, 244800, 1}, + .caps[5] = {HFI_CAPABILITY_FRAMERATE, 1, 120, 1}, + .caps[6] = {HFI_CAPABILITY_MAX_VIDEOCORES, 0, 1, 1}, + .caps[7] = {HFI_CAPABILITY_HIER_P_NUM_ENH_LAYERS, 0, 6, 1}, + .caps[8] = {HFI_CAPABILITY_ENC_LTR_COUNT, 0, 4, 1}, + .caps[9] = {HFI_CAPABILITY_MBS_PER_SECOND_POWERSAVE, 0, 244800, 1}, + .caps[10] = {HFI_CAPABILITY_I_FRAME_QP, 0, 51, 1}, + .caps[11] = {HFI_CAPABILITY_P_FRAME_QP, 0, 51, 1}, + .caps[12] = {HFI_CAPABILITY_B_FRAME_QP, 0, 51, 1}, + .caps[13] = {HFI_CAPABILITY_SLICE_BYTE, 1, 10, 1}, + .caps[14] = {HFI_CAPABILITY_SLICE_MB, 1, 10, 1}, + .num_caps = 15, + .pl[0] = {HFI_HEVC_PROFILE_MAIN, HFI_HEVC_LEVEL_5 | HFI_HEVC_TIER_HIGH0}, + .pl[1] = {HFI_HEVC_PROFILE_MAIN10, HFI_HEVC_LEVEL_5 | HFI_HEVC_TIER_HIGH0}, + .num_pl = 2, + .fmts[0] = {HFI_BUFFER_INPUT, HFI_COLOR_FORMAT_NV12}, + .fmts[1] = {HFI_BUFFER_INPUT, HFI_COLOR_FORMAT_NV12_UBWC}, + .num_fmts = 2, +} }; + +static const struct hfi_plat_caps *get_capabilities(struct venus_core *core, + unsigned int *entries) +{ + *entries = is_lite(core) ? ARRAY_SIZE(caps_lite) : ARRAY_SIZE(caps); + + return is_lite(core) ? caps_lite : caps; } -static void get_codecs(u32 *enc_codecs, u32 *dec_codecs, u32 *count) +static void get_codecs(struct venus_core *core, + u32 *enc_codecs, u32 *dec_codecs, u32 *count) { - *enc_codecs = HFI_VIDEO_CODEC_H264 | HFI_VIDEO_CODEC_HEVC | - HFI_VIDEO_CODEC_VP8; - *dec_codecs = HFI_VIDEO_CODEC_H264 | HFI_VIDEO_CODEC_HEVC | - HFI_VIDEO_CODEC_VP8 | HFI_VIDEO_CODEC_VP9 | - HFI_VIDEO_CODEC_MPEG2; - *count = 8; + const struct hfi_plat_caps *caps; + unsigned int num; + size_t i; + + *enc_codecs = 0; + *dec_codecs = 0; + + caps = get_capabilities(core, &num); + + for (i = 0; i < num; caps++, i++) { + if (caps->domain == VIDC_SESSION_TYPE_ENC) + *enc_codecs |= caps->codec; + else + *dec_codecs |= caps->codec; + } + + *count = num; } static const struct hfi_platform_codec_freq_data codec_freq_data[] = { @@ -272,13 +403,29 @@ static const struct hfi_platform_codec_freq_data codec_freq_data[] = { { V4L2_PIX_FMT_VP9, VIDC_SESSION_TYPE_DEC, 200, 10, 200 }, }; +static const struct hfi_platform_codec_freq_data codec_freq_data_lite[] = { + { V4L2_PIX_FMT_H264, VIDC_SESSION_TYPE_DEC, 440, 0, 440 }, + { V4L2_PIX_FMT_HEVC, VIDC_SESSION_TYPE_DEC, 440, 0, 440 }, + { V4L2_PIX_FMT_VP9, VIDC_SESSION_TYPE_DEC, 440, 0, 440 }, + { V4L2_PIX_FMT_H264, VIDC_SESSION_TYPE_ENC, 675, 0, 675 }, + { V4L2_PIX_FMT_HEVC, VIDC_SESSION_TYPE_ENC, 675, 0, 675 }, +}; + static const struct hfi_platform_codec_freq_data * -get_codec_freq_data(u32 session_type, u32 pixfmt) +get_codec_freq_data(struct venus_core *core, u32 session_type, u32 pixfmt) { - const struct hfi_platform_codec_freq_data *data = codec_freq_data; - unsigned int i, data_size = ARRAY_SIZE(codec_freq_data); + const struct hfi_platform_codec_freq_data *data; + unsigned int i, data_size; const struct hfi_platform_codec_freq_data *found = NULL; + if (is_lite(core)) { + data = codec_freq_data_lite; + data_size = ARRAY_SIZE(codec_freq_data_lite); + } else { + data = codec_freq_data; + data_size = ARRAY_SIZE(codec_freq_data); + } + for (i = 0; i < data_size; i++) { if (data[i].pixfmt == pixfmt && data[i].session_type == session_type) { found = &data[i]; @@ -289,33 +436,36 @@ get_codec_freq_data(u32 session_type, u32 pixfmt) return found; } -static unsigned long codec_vpp_freq(u32 session_type, u32 codec) +static unsigned long codec_vpp_freq(struct venus_core *core, + u32 session_type, u32 codec) { const struct hfi_platform_codec_freq_data *data; - data = get_codec_freq_data(session_type, codec); + data = get_codec_freq_data(core, session_type, codec); if (data) return data->vpp_freq; return 0; } -static unsigned long codec_vsp_freq(u32 session_type, u32 codec) +static unsigned long codec_vsp_freq(struct venus_core *core, + u32 session_type, u32 codec) { const struct hfi_platform_codec_freq_data *data; - data = get_codec_freq_data(session_type, codec); + data = get_codec_freq_data(core, session_type, codec); if (data) return data->vsp_freq; return 0; } -static unsigned long codec_lp_freq(u32 session_type, u32 codec) +static unsigned long codec_lp_freq(struct venus_core *core, + u32 session_type, u32 codec) { const struct hfi_platform_codec_freq_data *data; - data = get_codec_freq_data(session_type, codec); + data = get_codec_freq_data(core, session_type, codec); if (data) return data->low_power_freq; diff --git a/drivers/media/platform/qcom/venus/hfi_platform_v6.c b/drivers/media/platform/qcom/venus/hfi_platform_v6.c index 4e8af645f8b9..d8568c08cc36 100644 --- a/drivers/media/platform/qcom/venus/hfi_platform_v6.c +++ b/drivers/media/platform/qcom/venus/hfi_platform_v6.c @@ -2,6 +2,7 @@ /* * Copyright (c) 2020, The Linux Foundation. All rights reserved. */ +#include "core.h" #include "hfi_platform.h" static const struct hfi_plat_caps caps[] = { @@ -245,14 +246,22 @@ static const struct hfi_plat_caps caps[] = { .num_fmts = 4, } }; -static const struct hfi_plat_caps *get_capabilities(unsigned int *entries) +static const struct hfi_plat_caps *get_capabilities(struct venus_core *core, + unsigned int *entries) { + if (is_lite(core)) + return NULL; + *entries = ARRAY_SIZE(caps); return caps; } -static void get_codecs(u32 *enc_codecs, u32 *dec_codecs, u32 *count) +static void get_codecs(struct venus_core *core, u32 *enc_codecs, + u32 *dec_codecs, u32 *count) { + if (is_lite(core)) + return; + *enc_codecs = HFI_VIDEO_CODEC_H264 | HFI_VIDEO_CODEC_HEVC | HFI_VIDEO_CODEC_VP8; *dec_codecs = HFI_VIDEO_CODEC_H264 | HFI_VIDEO_CODEC_HEVC | @@ -273,12 +282,15 @@ static const struct hfi_platform_codec_freq_data codec_freq_data[] = { }; static const struct hfi_platform_codec_freq_data * -get_codec_freq_data(u32 session_type, u32 pixfmt) +get_codec_freq_data(struct venus_core *core, u32 session_type, u32 pixfmt) { const struct hfi_platform_codec_freq_data *data = codec_freq_data; unsigned int i, data_size = ARRAY_SIZE(codec_freq_data); const struct hfi_platform_codec_freq_data *found = NULL; + if (is_lite(core)) + return NULL; + for (i = 0; i < data_size; i++) { if (data[i].pixfmt == pixfmt && data[i].session_type == session_type) { found = &data[i]; @@ -289,33 +301,36 @@ get_codec_freq_data(u32 session_type, u32 pixfmt) return found; } -static unsigned long codec_vpp_freq(u32 session_type, u32 codec) +static unsigned long codec_vpp_freq(struct venus_core *core, u32 session_type, + u32 codec) { const struct hfi_platform_codec_freq_data *data; - data = get_codec_freq_data(session_type, codec); + data = get_codec_freq_data(core, session_type, codec); if (data) return data->vpp_freq; return 0; } -static unsigned long codec_vsp_freq(u32 session_type, u32 codec) +static unsigned long codec_vsp_freq(struct venus_core *core, u32 session_type, + u32 codec) { const struct hfi_platform_codec_freq_data *data; - data = get_codec_freq_data(session_type, codec); + data = get_codec_freq_data(core, session_type, codec); if (data) return data->vsp_freq; return 0; } -static unsigned long codec_lp_freq(u32 session_type, u32 codec) +static unsigned long codec_lp_freq(struct venus_core *core, u32 session_type, + u32 codec) { const struct hfi_platform_codec_freq_data *data; - data = get_codec_freq_data(session_type, codec); + data = get_codec_freq_data(core, session_type, codec); if (data) return data->low_power_freq; diff --git a/drivers/media/platform/qcom/venus/hfi_venus.c b/drivers/media/platform/qcom/venus/hfi_venus.c index cec7f5964d3d..d3da35f67fd5 100644 --- a/drivers/media/platform/qcom/venus/hfi_venus.c +++ b/drivers/media/platform/qcom/venus/hfi_venus.c @@ -380,7 +380,7 @@ static void venus_soft_int(struct venus_hfi_device *hdev) void __iomem *cpu_ic_base = hdev->core->cpu_ic_base; u32 clear_bit; - if (IS_V6(hdev->core)) + if (IS_V6(hdev->core) || (IS_V4(hdev->core) && is_lite(hdev->core))) clear_bit = BIT(CPU_IC_SOFTINT_H2A_SHIFT_V6); else clear_bit = BIT(CPU_IC_SOFTINT_H2A_SHIFT); @@ -501,9 +501,11 @@ static int venus_boot_core(struct venus_hfi_device *hdev) if (count >= max_tries) ret = -ETIMEDOUT; - if (IS_IRIS2(hdev->core) || IS_IRIS2_1(hdev->core)) { + if (IS_IRIS2(hdev->core) || IS_IRIS2_1(hdev->core) || IS_AR50_LITE(hdev->core)) { writel(0x1, cpu_cs_base + CPU_CS_H2XSOFTINTEN_V6); - writel(0x0, cpu_cs_base + CPU_CS_X2RPMH_V6); + + if (!IS_AR50_LITE(hdev->core)) + writel(0x0, cpu_cs_base + CPU_CS_X2RPMH_V6); } return ret; @@ -569,6 +571,9 @@ static int venus_halt_axi(struct venus_hfi_device *hdev) u32 mask_val; int ret; + if (IS_AR50_LITE(hdev->core)) + return 0; + if (IS_IRIS2(hdev->core) || IS_IRIS2_1(hdev->core)) { writel(0x3, cpu_cs_base + CPU_CS_X2RPMH_V6); @@ -1138,7 +1143,13 @@ static irqreturn_t venus_isr(struct venus_core *core) wrapper_base = hdev->core->wrapper_base; status = readl(wrapper_base + WRAPPER_INTR_STATUS); - if (IS_IRIS2(core) || IS_IRIS2_1(core)) { + + if (IS_AR50_LITE(core)) { + if (status & WRAPPER_INTR_STATUS_A2H_MASK || + status & WRAPPER_INTR_STATUS_A2HWD_MASK_V4_LITE || + status & CPU_CS_SCIACMDARG0_INIT_IDLE_MSG_MASK) + hdev->irq_status = status; + } else if (IS_IRIS2(core) || IS_IRIS2_1(core)) { if (status & WRAPPER_INTR_STATUS_A2H_MASK || status & WRAPPER_INTR_STATUS_A2HWD_MASK_V6 || status & CPU_CS_SCIACMDARG0_INIT_IDLE_MSG_MASK) @@ -1150,7 +1161,7 @@ static irqreturn_t venus_isr(struct venus_core *core) hdev->irq_status = status; } writel(1, cpu_cs_base + CPU_CS_A2HSOFTINTCLR); - if (!(IS_IRIS2(core) || IS_IRIS2_1(core))) + if (!(IS_IRIS2(core) || IS_IRIS2_1(core) || IS_AR50_LITE(core))) writel(status, wrapper_base + WRAPPER_INTR_CLEAR); return IRQ_WAKE_THREAD; @@ -1535,7 +1546,7 @@ static bool venus_cpu_and_video_core_idle(struct venus_hfi_device *hdev) void __iomem *cpu_cs_base = hdev->core->cpu_cs_base; u32 ctrl_status, cpu_status; - if (IS_IRIS2(hdev->core) || IS_IRIS2_1(hdev->core)) + if (IS_IRIS2(hdev->core) || IS_IRIS2_1(hdev->core) || IS_AR50_LITE(hdev->core)) cpu_status = readl(wrapper_tz_base + WRAPPER_TZ_CPU_STATUS_V6); else cpu_status = readl(wrapper_base + WRAPPER_CPU_STATUS); @@ -1555,7 +1566,7 @@ static bool venus_cpu_idle_and_pc_ready(struct venus_hfi_device *hdev) void __iomem *cpu_cs_base = hdev->core->cpu_cs_base; u32 ctrl_status, cpu_status; - if (IS_IRIS2(hdev->core) || IS_IRIS2_1(hdev->core)) + if (IS_IRIS2(hdev->core) || IS_IRIS2_1(hdev->core) || IS_AR50_LITE(hdev->core)) cpu_status = readl(wrapper_tz_base + WRAPPER_TZ_CPU_STATUS_V6); else cpu_status = readl(wrapper_base + WRAPPER_CPU_STATUS); diff --git a/drivers/media/platform/qcom/venus/hfi_venus_io.h b/drivers/media/platform/qcom/venus/hfi_venus_io.h index 9735a246ce36..f2c3064c44ae 100644 --- a/drivers/media/platform/qcom/venus/hfi_venus_io.h +++ b/drivers/media/platform/qcom/venus/hfi_venus_io.h @@ -51,6 +51,9 @@ /* Venus cpu */ #define CPU_CS_SCIACMDARG3 0x58 +#define CPU_CS_VCICMD 0x20 +#define CPU_CS_VCICMD_ARP_OFF BIT(0) + #define SFR_ADDR 0x5c #define MMAP_ADDR 0x60 #define UC_REGION_ADDR 0x64 @@ -100,6 +103,7 @@ #define WRAPPER_INTR_MASK_A2HCPU_MASK 0x4 #define WRAPPER_INTR_MASK_A2HCPU_SHIFT 0x2 +#define WRAPPER_INTR_STATUS_A2HWD_MASK_V4_LITE 0x10 #define WRAPPER_INTR_STATUS_A2HWD_MASK_V6 0x8 #define WRAPPER_INTR_MASK_A2HWD_BASK_V6 0x8 diff --git a/drivers/media/platform/qcom/venus/pm_helpers.c b/drivers/media/platform/qcom/venus/pm_helpers.c index e32f8862a9f9..f0269524ac70 100644 --- a/drivers/media/platform/qcom/venus/pm_helpers.c +++ b/drivers/media/platform/qcom/venus/pm_helpers.c @@ -40,6 +40,8 @@ static int core_clks_get(struct venus_core *core) static int core_clks_enable(struct venus_core *core) { + const struct freq_tbl *freq_tbl = core->res->freq_tbl; + unsigned int freq_tbl_size = core->res->freq_tbl_size; const struct venus_resources *res = core->res; struct device *dev = core->dev; unsigned long freq = 0; @@ -48,11 +50,16 @@ static int core_clks_enable(struct venus_core *core) int ret; opp = dev_pm_opp_find_freq_ceil(dev, &freq); - if (!IS_ERR(opp)) + if (IS_ERR(opp)) { + if (!freq_tbl) + return -ENODEV; + freq = freq_tbl[freq_tbl_size - 1].freq; + } else { dev_pm_opp_put(opp); + } for (i = 0; i < res->clks_num; i++) { - if (IS_V6(core)) { + if (IS_V6(core) || (IS_V4(core) && is_lite(core))) { ret = clk_set_rate(core->clks[i], freq); if (ret) goto err; diff --git a/drivers/media/platform/qcom/venus/vdec.c b/drivers/media/platform/qcom/venus/vdec.c index 29b0d6a5303d..55c27345b7d8 100644 --- a/drivers/media/platform/qcom/venus/vdec.c +++ b/drivers/media/platform/qcom/venus/vdec.c @@ -1732,9 +1732,8 @@ static int vdec_open(struct file *file) v4l2_fh_init(&inst->fh, core->vdev_dec); inst->fh.ctrl_handler = &inst->ctrl_handler; - v4l2_fh_add(&inst->fh); + v4l2_fh_add(&inst->fh, file); inst->fh.m2m_ctx = inst->m2m_ctx; - file->private_data = &inst->fh; return 0; @@ -1755,7 +1754,7 @@ static int vdec_close(struct file *file) vdec_pm_get(inst); cancel_work_sync(&inst->delayed_process_work); - venus_close_common(inst); + venus_close_common(inst, file); ida_destroy(&inst->dpb_ids); vdec_pm_put(inst, false); diff --git a/drivers/media/platform/qcom/venus/venc.c b/drivers/media/platform/qcom/venus/venc.c index c0a0ccdded80..fba07557a399 100644 --- a/drivers/media/platform/qcom/venus/venc.c +++ b/drivers/media/platform/qcom/venus/venc.c @@ -1515,9 +1515,8 @@ static int venc_open(struct file *file) v4l2_fh_init(&inst->fh, core->vdev_enc); inst->fh.ctrl_handler = &inst->ctrl_handler; - v4l2_fh_add(&inst->fh); + v4l2_fh_add(&inst->fh, file); inst->fh.m2m_ctx = inst->m2m_ctx; - file->private_data = &inst->fh; return 0; @@ -1537,7 +1536,7 @@ static int venc_close(struct file *file) struct venus_inst *inst = to_inst(file); venc_pm_get(inst); - venus_close_common(inst); + venus_close_common(inst, file); inst->enc_state = VENUS_ENC_STATE_DEINIT; venc_pm_put(inst, false); diff --git a/drivers/media/platform/raspberrypi/rp1-cfe/csi2.c b/drivers/media/platform/raspberrypi/rp1-cfe/csi2.c index 35c2ab1e2cd4..2c5b4d24b4e6 100644 --- a/drivers/media/platform/raspberrypi/rp1-cfe/csi2.c +++ b/drivers/media/platform/raspberrypi/rp1-cfe/csi2.c @@ -525,7 +525,7 @@ static const struct v4l2_subdev_internal_ops csi2_internal_ops = { int csi2_init(struct csi2_device *csi2, struct dentry *debugfs) { - unsigned int ret; + int ret; spin_lock_init(&csi2->errors_lock); diff --git a/drivers/media/platform/renesas/rcar-vin/rcar-core.c b/drivers/media/platform/renesas/rcar-vin/rcar-core.c index f73729f59671..100105b620e3 100644 --- a/drivers/media/platform/renesas/rcar-vin/rcar-core.c +++ b/drivers/media/platform/renesas/rcar-vin/rcar-core.c @@ -849,7 +849,7 @@ static int rvin_isp_init(struct rvin_dev *vin) * Suspend / Resume */ -static int __maybe_unused rvin_suspend(struct device *dev) +static int rvin_suspend(struct device *dev) { struct rvin_dev *vin = dev_get_drvdata(dev); @@ -861,7 +861,7 @@ static int __maybe_unused rvin_suspend(struct device *dev) return 0; } -static int __maybe_unused rvin_resume(struct device *dev) +static int rvin_resume(struct device *dev) { struct rvin_dev *vin = dev_get_drvdata(dev); @@ -1276,13 +1276,13 @@ static void rcar_vin_remove(struct platform_device *pdev) rvin_dma_unregister(vin); } -static SIMPLE_DEV_PM_OPS(rvin_pm_ops, rvin_suspend, rvin_resume); +static DEFINE_SIMPLE_DEV_PM_OPS(rvin_pm_ops, rvin_suspend, rvin_resume); static struct platform_driver rcar_vin_driver = { .driver = { .name = "rcar-vin", .suppress_bind_attrs = true, - .pm = &rvin_pm_ops, + .pm = pm_sleep_ptr(&rvin_pm_ops), .of_match_table = rvin_of_id_table, }, .probe = rcar_vin_probe, diff --git a/drivers/media/platform/renesas/rcar-vin/rcar-v4l2.c b/drivers/media/platform/renesas/rcar-vin/rcar-v4l2.c index 62eddf3a35fc..079dbaf016c2 100644 --- a/drivers/media/platform/renesas/rcar-vin/rcar-v4l2.c +++ b/drivers/media/platform/renesas/rcar-vin/rcar-v4l2.c @@ -588,8 +588,6 @@ static int rvin_open(struct file *file) if (ret) goto err_pm; - file->private_data = vin; - ret = v4l2_fh_open(file); if (ret) goto err_unlock; diff --git a/drivers/media/platform/renesas/rcar_drif.c b/drivers/media/platform/renesas/rcar_drif.c index fc8b6bbef793..11bf47fb8266 100644 --- a/drivers/media/platform/renesas/rcar_drif.c +++ b/drivers/media/platform/renesas/rcar_drif.c @@ -1446,18 +1446,18 @@ static void rcar_drif_remove(struct platform_device *pdev) } /* FIXME: Implement suspend/resume support */ -static int __maybe_unused rcar_drif_suspend(struct device *dev) +static int rcar_drif_suspend(struct device *dev) { return 0; } -static int __maybe_unused rcar_drif_resume(struct device *dev) +static int rcar_drif_resume(struct device *dev) { return 0; } -static SIMPLE_DEV_PM_OPS(rcar_drif_pm_ops, rcar_drif_suspend, - rcar_drif_resume); +static DEFINE_SIMPLE_DEV_PM_OPS(rcar_drif_pm_ops, rcar_drif_suspend, + rcar_drif_resume); static const struct of_device_id rcar_drif_of_table[] = { { .compatible = "renesas,rcar-gen3-drif" }, @@ -1470,8 +1470,8 @@ static struct platform_driver rcar_drif_driver = { .driver = { .name = RCAR_DRIF_DRV_NAME, .of_match_table = rcar_drif_of_table, - .pm = &rcar_drif_pm_ops, - }, + .pm = pm_sleep_ptr(&rcar_drif_pm_ops), + }, .probe = rcar_drif_probe, .remove = rcar_drif_remove, }; diff --git a/drivers/media/platform/renesas/rcar_fdp1.c b/drivers/media/platform/renesas/rcar_fdp1.c index 5d453a7a8988..e615c56083f1 100644 --- a/drivers/media/platform/renesas/rcar_fdp1.c +++ b/drivers/media/platform/renesas/rcar_fdp1.c @@ -630,9 +630,9 @@ struct fdp1_ctx { struct fdp1_field_buffer *previous; }; -static inline struct fdp1_ctx *fh_to_ctx(struct v4l2_fh *fh) +static inline struct fdp1_ctx *file_to_ctx(struct file *filp) { - return container_of(fh, struct fdp1_ctx, fh); + return container_of(file_to_v4l2_fh(filp), struct fdp1_ctx, fh); } static struct fdp1_q_data *get_q_data(struct fdp1_ctx *ctx, @@ -1406,8 +1406,8 @@ static int fdp1_enum_fmt_vid_out(struct file *file, void *priv, static int fdp1_g_fmt(struct file *file, void *priv, struct v4l2_format *f) { + struct fdp1_ctx *ctx = file_to_ctx(file); struct fdp1_q_data *q_data; - struct fdp1_ctx *ctx = fh_to_ctx(priv); if (!v4l2_m2m_get_vq(ctx->fh.m2m_ctx, f->type)) return -EINVAL; @@ -1584,7 +1584,7 @@ static void fdp1_try_fmt_capture(struct fdp1_ctx *ctx, static int fdp1_try_fmt(struct file *file, void *priv, struct v4l2_format *f) { - struct fdp1_ctx *ctx = fh_to_ctx(priv); + struct fdp1_ctx *ctx = file_to_ctx(file); if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) fdp1_try_fmt_output(ctx, NULL, &f->fmt.pix_mp); @@ -1655,7 +1655,7 @@ static void fdp1_set_format(struct fdp1_ctx *ctx, static int fdp1_s_fmt(struct file *file, void *priv, struct v4l2_format *f) { - struct fdp1_ctx *ctx = fh_to_ctx(priv); + struct fdp1_ctx *ctx = file_to_ctx(file); struct v4l2_m2m_ctx *m2m_ctx = ctx->fh.m2m_ctx; struct vb2_queue *vq = v4l2_m2m_get_vq(m2m_ctx, f->type); @@ -2088,7 +2088,6 @@ static int fdp1_open(struct file *file) } v4l2_fh_init(&ctx->fh, video_devdata(file)); - file->private_data = &ctx->fh; ctx->fdp1 = fdp1; /* Initialise Queues */ @@ -2137,7 +2136,7 @@ static int fdp1_open(struct file *file) if (ret < 0) goto error_pm; - v4l2_fh_add(&ctx->fh); + v4l2_fh_add(&ctx->fh, file); dprintk(fdp1, "Created instance: %p, m2m_ctx: %p\n", ctx, ctx->fh.m2m_ctx); @@ -2158,11 +2157,11 @@ done: static int fdp1_release(struct file *file) { struct fdp1_dev *fdp1 = video_drvdata(file); - struct fdp1_ctx *ctx = fh_to_ctx(file->private_data); + struct fdp1_ctx *ctx = file_to_ctx(file); dprintk(fdp1, "Releasing instance %p\n", ctx); - v4l2_fh_del(&ctx->fh); + v4l2_fh_del(&ctx->fh, file); v4l2_fh_exit(&ctx->fh); v4l2_ctrl_handler_free(&ctx->hdl); mutex_lock(&fdp1->dev_mutex); @@ -2409,7 +2408,7 @@ static void fdp1_remove(struct platform_device *pdev) rcar_fcp_put(fdp1->fcp); } -static int __maybe_unused fdp1_pm_runtime_suspend(struct device *dev) +static int fdp1_pm_runtime_suspend(struct device *dev) { struct fdp1_dev *fdp1 = dev_get_drvdata(dev); @@ -2418,7 +2417,7 @@ static int __maybe_unused fdp1_pm_runtime_suspend(struct device *dev) return 0; } -static int __maybe_unused fdp1_pm_runtime_resume(struct device *dev) +static int fdp1_pm_runtime_resume(struct device *dev) { struct fdp1_dev *fdp1 = dev_get_drvdata(dev); @@ -2429,9 +2428,7 @@ static int __maybe_unused fdp1_pm_runtime_resume(struct device *dev) } static const struct dev_pm_ops fdp1_pm_ops = { - SET_RUNTIME_PM_OPS(fdp1_pm_runtime_suspend, - fdp1_pm_runtime_resume, - NULL) + RUNTIME_PM_OPS(fdp1_pm_runtime_suspend, fdp1_pm_runtime_resume, NULL) }; static const struct of_device_id fdp1_dt_ids[] = { @@ -2446,7 +2443,7 @@ static struct platform_driver fdp1_pdrv = { .driver = { .name = DRIVER_NAME, .of_match_table = fdp1_dt_ids, - .pm = &fdp1_pm_ops, + .pm = pm_ptr(&fdp1_pm_ops), }, }; diff --git a/drivers/media/platform/renesas/rcar_jpu.c b/drivers/media/platform/renesas/rcar_jpu.c index 81038df71bb5..46ea259a2bb9 100644 --- a/drivers/media/platform/renesas/rcar_jpu.c +++ b/drivers/media/platform/renesas/rcar_jpu.c @@ -480,9 +480,9 @@ static struct jpu_ctx *ctrl_to_ctx(struct v4l2_ctrl *c) return container_of(c->handler, struct jpu_ctx, ctrl_handler); } -static struct jpu_ctx *fh_to_ctx(struct v4l2_fh *fh) +static struct jpu_ctx *file_to_ctx(struct file *filp) { - return container_of(fh, struct jpu_ctx, fh); + return container_of(file_to_v4l2_fh(filp), struct jpu_ctx, fh); } static void jpu_set_tbl(struct jpu *jpu, u32 reg, const unsigned int *tbl, @@ -656,7 +656,7 @@ static u8 jpu_parse_hdr(void *buffer, unsigned long size, unsigned int *width, static int jpu_querycap(struct file *file, void *priv, struct v4l2_capability *cap) { - struct jpu_ctx *ctx = fh_to_ctx(priv); + struct jpu_ctx *ctx = file_to_ctx(file); if (ctx->encoder) strscpy(cap->card, DRV_NAME " encoder", sizeof(cap->card)); @@ -714,7 +714,7 @@ static int jpu_enum_fmt(struct v4l2_fmtdesc *f, u32 type) static int jpu_enum_fmt_cap(struct file *file, void *priv, struct v4l2_fmtdesc *f) { - struct jpu_ctx *ctx = fh_to_ctx(priv); + struct jpu_ctx *ctx = file_to_ctx(file); return jpu_enum_fmt(f, ctx->encoder ? JPU_ENC_CAPTURE : JPU_DEC_CAPTURE); @@ -723,7 +723,7 @@ static int jpu_enum_fmt_cap(struct file *file, void *priv, static int jpu_enum_fmt_out(struct file *file, void *priv, struct v4l2_fmtdesc *f) { - struct jpu_ctx *ctx = fh_to_ctx(priv); + struct jpu_ctx *ctx = file_to_ctx(file); return jpu_enum_fmt(f, ctx->encoder ? JPU_ENC_OUTPUT : JPU_DEC_OUTPUT); } @@ -823,7 +823,7 @@ static int __jpu_try_fmt(struct jpu_ctx *ctx, struct jpu_fmt **fmtinfo, static int jpu_try_fmt(struct file *file, void *priv, struct v4l2_format *f) { - struct jpu_ctx *ctx = fh_to_ctx(priv); + struct jpu_ctx *ctx = file_to_ctx(file); if (!v4l2_m2m_get_vq(ctx->fh.m2m_ctx, f->type)) return -EINVAL; @@ -834,7 +834,7 @@ static int jpu_try_fmt(struct file *file, void *priv, struct v4l2_format *f) static int jpu_s_fmt(struct file *file, void *priv, struct v4l2_format *f) { struct vb2_queue *vq; - struct jpu_ctx *ctx = fh_to_ctx(priv); + struct jpu_ctx *ctx = file_to_ctx(file); struct v4l2_m2m_ctx *m2m_ctx = ctx->fh.m2m_ctx; struct jpu_fmt *fmtinfo; struct jpu_q_data *q_data; @@ -863,8 +863,8 @@ static int jpu_s_fmt(struct file *file, void *priv, struct v4l2_format *f) static int jpu_g_fmt(struct file *file, void *priv, struct v4l2_format *f) { + struct jpu_ctx *ctx = file_to_ctx(file); struct jpu_q_data *q_data; - struct jpu_ctx *ctx = fh_to_ctx(priv); if (!v4l2_m2m_get_vq(ctx->fh.m2m_ctx, f->type)) return -EINVAL; @@ -897,8 +897,8 @@ static const struct v4l2_ctrl_ops jpu_ctrl_ops = { static int jpu_streamon(struct file *file, void *priv, enum v4l2_buf_type type) { - struct jpu_ctx *ctx = fh_to_ctx(priv); struct jpu_q_data *src_q_data, *dst_q_data, *orig, adj, *ref; + struct jpu_ctx *ctx = file_to_ctx(file); enum v4l2_buf_type adj_type; src_q_data = jpu_get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); @@ -1226,8 +1226,7 @@ static int jpu_open(struct file *file) v4l2_fh_init(&ctx->fh, vfd); ctx->fh.ctrl_handler = &ctx->ctrl_handler; - file->private_data = &ctx->fh; - v4l2_fh_add(&ctx->fh); + v4l2_fh_add(&ctx->fh, file); ctx->jpu = jpu; ctx->encoder = vfd == &jpu->vfd_encoder; @@ -1272,7 +1271,7 @@ jpu_reset_rollback: device_prepare_rollback: mutex_unlock(&jpu->mutex); v4l_prepare_rollback: - v4l2_fh_del(&ctx->fh); + v4l2_fh_del(&ctx->fh, file); v4l2_fh_exit(&ctx->fh); kfree(ctx); return ret; @@ -1280,12 +1279,12 @@ v4l_prepare_rollback: static int jpu_release(struct file *file) { + struct jpu_ctx *ctx = file_to_ctx(file); struct jpu *jpu = video_drvdata(file); - struct jpu_ctx *ctx = fh_to_ctx(file->private_data); v4l2_m2m_ctx_release(ctx->fh.m2m_ctx); v4l2_ctrl_handler_free(&ctx->ctrl_handler); - v4l2_fh_del(&ctx->fh); + v4l2_fh_del(&ctx->fh, file); v4l2_fh_exit(&ctx->fh); kfree(ctx); @@ -1745,6 +1744,6 @@ static struct platform_driver jpu_driver = { module_platform_driver(jpu_driver); MODULE_ALIAS("platform:" DRV_NAME); -MODULE_AUTHOR("Mikhail Ulianov <mikhail.ulyanov@cogentembedded.com>"); +MODULE_AUTHOR("Mikhail Ulianov"); MODULE_DESCRIPTION("Renesas R-Car JPEG processing unit driver"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/media/platform/renesas/renesas-ceu.c b/drivers/media/platform/renesas/renesas-ceu.c index 8cceafe491b1..deed49d0fb10 100644 --- a/drivers/media/platform/renesas/renesas-ceu.c +++ b/drivers/media/platform/renesas/renesas-ceu.c @@ -1048,7 +1048,7 @@ static int ceu_init_mbus_fmt(struct ceu_device *ceudev) /* * ceu_runtime_resume() - soft-reset the interface and turn sensor power on. */ -static int __maybe_unused ceu_runtime_resume(struct device *dev) +static int ceu_runtime_resume(struct device *dev) { struct ceu_device *ceudev = dev_get_drvdata(dev); struct v4l2_subdev *v4l2_sd = ceudev->sd->v4l2_sd; @@ -1064,7 +1064,7 @@ static int __maybe_unused ceu_runtime_resume(struct device *dev) * ceu_runtime_suspend() - disable capture and interrupts and soft-reset. * Turn sensor power off. */ -static int __maybe_unused ceu_runtime_suspend(struct device *dev) +static int ceu_runtime_suspend(struct device *dev) { struct ceu_device *ceudev = dev_get_drvdata(dev); struct v4l2_subdev *v4l2_sd = ceudev->sd->v4l2_sd; @@ -1709,15 +1709,13 @@ static void ceu_remove(struct platform_device *pdev) } static const struct dev_pm_ops ceu_pm_ops = { - SET_RUNTIME_PM_OPS(ceu_runtime_suspend, - ceu_runtime_resume, - NULL) + RUNTIME_PM_OPS(ceu_runtime_suspend, ceu_runtime_resume, NULL) }; static struct platform_driver ceu_driver = { .driver = { .name = DRIVER_NAME, - .pm = &ceu_pm_ops, + .pm = pm_ptr(&ceu_pm_ops), .of_match_table = of_match_ptr(ceu_of_match), }, .probe = ceu_probe, diff --git a/drivers/media/platform/renesas/rzg2l-cru/rzg2l-core.c b/drivers/media/platform/renesas/rzg2l-cru/rzg2l-core.c index 806acc8f9728..3c5fbd857371 100644 --- a/drivers/media/platform/renesas/rzg2l-cru/rzg2l-core.c +++ b/drivers/media/platform/renesas/rzg2l-cru/rzg2l-core.c @@ -367,7 +367,6 @@ static const struct rzg2l_cru_info rzg3e_cru_info = { .enable_interrupts = rzg3e_cru_enable_interrupts, .disable_interrupts = rzg3e_cru_disable_interrupts, .fifo_empty = rzg3e_fifo_empty, - .csi_setup = rzg3e_cru_csi2_setup, }; static const u16 rzg2l_cru_regs[] = { @@ -412,7 +411,6 @@ static const struct rzg2l_cru_info rzg2l_cru_info = { .enable_interrupts = rzg2l_cru_enable_interrupts, .disable_interrupts = rzg2l_cru_disable_interrupts, .fifo_empty = rzg2l_fifo_empty, - .csi_setup = rzg2l_cru_csi2_setup, }; static const struct of_device_id rzg2l_cru_of_id_table[] = { diff --git a/drivers/media/platform/renesas/rzg2l-cru/rzg2l-cru.h b/drivers/media/platform/renesas/rzg2l-cru/rzg2l-cru.h index be95b41c37df..3a200db15730 100644 --- a/drivers/media/platform/renesas/rzg2l-cru/rzg2l-cru.h +++ b/drivers/media/platform/renesas/rzg2l-cru/rzg2l-cru.h @@ -92,9 +92,6 @@ struct rzg2l_cru_info { void (*enable_interrupts)(struct rzg2l_cru_dev *cru); void (*disable_interrupts)(struct rzg2l_cru_dev *cru); bool (*fifo_empty)(struct rzg2l_cru_dev *cru); - void (*csi_setup)(struct rzg2l_cru_dev *cru, - const struct rzg2l_cru_ip_format *ip_fmt, - u8 csi_vc); }; /** @@ -204,11 +201,5 @@ void rzg3e_cru_disable_interrupts(struct rzg2l_cru_dev *cru); bool rzg2l_fifo_empty(struct rzg2l_cru_dev *cru); bool rzg3e_fifo_empty(struct rzg2l_cru_dev *cru); -void rzg2l_cru_csi2_setup(struct rzg2l_cru_dev *cru, - const struct rzg2l_cru_ip_format *ip_fmt, - u8 csi_vc); -void rzg3e_cru_csi2_setup(struct rzg2l_cru_dev *cru, - const struct rzg2l_cru_ip_format *ip_fmt, - u8 csi_vc); #endif diff --git a/drivers/media/platform/renesas/rzg2l-cru/rzg2l-video.c b/drivers/media/platform/renesas/rzg2l-cru/rzg2l-video.c index a8817a7066b2..162e2ace6931 100644 --- a/drivers/media/platform/renesas/rzg2l-cru/rzg2l-video.c +++ b/drivers/media/platform/renesas/rzg2l-cru/rzg2l-video.c @@ -257,30 +257,18 @@ static void rzg2l_cru_initialize_axi(struct rzg2l_cru_dev *cru) rzg2l_cru_write(cru, AMnAXIATTR, amnaxiattr); } -void rzg3e_cru_csi2_setup(struct rzg2l_cru_dev *cru, - const struct rzg2l_cru_ip_format *ip_fmt, - u8 csi_vc) +static void rzg2l_cru_csi2_setup(struct rzg2l_cru_dev *cru, + const struct rzg2l_cru_ip_format *ip_fmt, + u8 csi_vc) { const struct rzg2l_cru_info *info = cru->info; u32 icnmc = ICnMC_INF(ip_fmt->datatype); - icnmc |= rzg2l_cru_read(cru, info->image_conv) & ~ICnMC_INF_MASK; - - /* Set virtual channel CSI2 */ - icnmc |= ICnMC_VCSEL(csi_vc); - - rzg2l_cru_write(cru, ICnSVCNUM, csi_vc); - rzg2l_cru_write(cru, ICnSVC, ICnSVC_SVC0(0) | ICnSVC_SVC1(1) | - ICnSVC_SVC2(2) | ICnSVC_SVC3(3)); - rzg2l_cru_write(cru, info->image_conv, icnmc); -} - -void rzg2l_cru_csi2_setup(struct rzg2l_cru_dev *cru, - const struct rzg2l_cru_ip_format *ip_fmt, - u8 csi_vc) -{ - const struct rzg2l_cru_info *info = cru->info; - u32 icnmc = ICnMC_INF(ip_fmt->datatype); + if (cru->info->regs[ICnSVC]) { + rzg2l_cru_write(cru, ICnSVCNUM, csi_vc); + rzg2l_cru_write(cru, ICnSVC, ICnSVC_SVC0(0) | ICnSVC_SVC1(1) | + ICnSVC_SVC2(2) | ICnSVC_SVC3(3)); + } icnmc |= rzg2l_cru_read(cru, info->image_conv) & ~ICnMC_INF_MASK; @@ -299,7 +287,7 @@ static int rzg2l_cru_initialize_image_conv(struct rzg2l_cru_dev *cru, const struct rzg2l_cru_ip_format *cru_ip_fmt; cru_ip_fmt = rzg2l_cru_ip_code_to_fmt(ip_sd_fmt->code); - info->csi_setup(cru, cru_ip_fmt, csi_vc); + rzg2l_cru_csi2_setup(cru, cru_ip_fmt, csi_vc); /* Output format */ cru_video_fmt = rzg2l_cru_ip_format_to_fmt(cru->format.pixelformat); @@ -1078,7 +1066,6 @@ static int rzg2l_cru_open(struct file *file) if (ret) return ret; - file->private_data = cru; ret = v4l2_fh_open(file); if (ret) goto err_unlock; diff --git a/drivers/media/platform/renesas/vsp1/vsp1_drv.c b/drivers/media/platform/renesas/vsp1/vsp1_drv.c index b8d06e88c475..6c64657fc4f3 100644 --- a/drivers/media/platform/renesas/vsp1/vsp1_drv.c +++ b/drivers/media/platform/renesas/vsp1/vsp1_drv.c @@ -618,7 +618,7 @@ void vsp1_device_put(struct vsp1_device *vsp1) * Power Management */ -static int __maybe_unused vsp1_pm_suspend(struct device *dev) +static int vsp1_pm_suspend(struct device *dev) { struct vsp1_device *vsp1 = dev_get_drvdata(dev); @@ -634,7 +634,7 @@ static int __maybe_unused vsp1_pm_suspend(struct device *dev) return 0; } -static int __maybe_unused vsp1_pm_resume(struct device *dev) +static int vsp1_pm_resume(struct device *dev) { struct vsp1_device *vsp1 = dev_get_drvdata(dev); @@ -650,7 +650,7 @@ static int __maybe_unused vsp1_pm_resume(struct device *dev) return 0; } -static int __maybe_unused vsp1_pm_runtime_suspend(struct device *dev) +static int vsp1_pm_runtime_suspend(struct device *dev) { struct vsp1_device *vsp1 = dev_get_drvdata(dev); @@ -660,7 +660,7 @@ static int __maybe_unused vsp1_pm_runtime_suspend(struct device *dev) return 0; } -static int __maybe_unused vsp1_pm_runtime_resume(struct device *dev) +static int vsp1_pm_runtime_resume(struct device *dev) { struct vsp1_device *vsp1 = dev_get_drvdata(dev); int ret; @@ -693,8 +693,8 @@ done: } static const struct dev_pm_ops vsp1_pm_ops = { - SET_SYSTEM_SLEEP_PM_OPS(vsp1_pm_suspend, vsp1_pm_resume) - SET_RUNTIME_PM_OPS(vsp1_pm_runtime_suspend, vsp1_pm_runtime_resume, NULL) + SYSTEM_SLEEP_PM_OPS(vsp1_pm_suspend, vsp1_pm_resume) + RUNTIME_PM_OPS(vsp1_pm_runtime_suspend, vsp1_pm_runtime_resume, NULL) }; /* ----------------------------------------------------------------------------- @@ -1042,7 +1042,7 @@ static struct platform_driver vsp1_platform_driver = { .remove = vsp1_remove, .driver = { .name = "vsp1", - .pm = &vsp1_pm_ops, + .pm = pm_ptr(&vsp1_pm_ops), .of_match_table = vsp1_of_match, }, }; diff --git a/drivers/media/platform/renesas/vsp1/vsp1_histo.c b/drivers/media/platform/renesas/vsp1/vsp1_histo.c index c762202877ba..390ea50f1595 100644 --- a/drivers/media/platform/renesas/vsp1/vsp1_histo.c +++ b/drivers/media/platform/renesas/vsp1/vsp1_histo.c @@ -392,7 +392,7 @@ static const struct v4l2_subdev_ops histo_ops = { static int histo_v4l2_querycap(struct file *file, void *fh, struct v4l2_capability *cap) { - struct v4l2_fh *vfh = file->private_data; + struct v4l2_fh *vfh = file_to_v4l2_fh(file); struct vsp1_histogram *histo = vdev_to_histo(vfh->vdev); cap->capabilities = V4L2_CAP_DEVICE_CAPS | V4L2_CAP_STREAMING @@ -409,7 +409,7 @@ static int histo_v4l2_querycap(struct file *file, void *fh, static int histo_v4l2_enum_format(struct file *file, void *fh, struct v4l2_fmtdesc *f) { - struct v4l2_fh *vfh = file->private_data; + struct v4l2_fh *vfh = file_to_v4l2_fh(file); struct vsp1_histogram *histo = vdev_to_histo(vfh->vdev); if (f->index > 0 || f->type != histo->queue.type) @@ -423,7 +423,7 @@ static int histo_v4l2_enum_format(struct file *file, void *fh, static int histo_v4l2_get_format(struct file *file, void *fh, struct v4l2_format *format) { - struct v4l2_fh *vfh = file->private_data; + struct v4l2_fh *vfh = file_to_v4l2_fh(file); struct vsp1_histogram *histo = vdev_to_histo(vfh->vdev); struct v4l2_meta_format *meta = &format->fmt.meta; diff --git a/drivers/media/platform/renesas/vsp1/vsp1_video.c b/drivers/media/platform/renesas/vsp1/vsp1_video.c index bc66fbdde3cc..75f9a1a85d55 100644 --- a/drivers/media/platform/renesas/vsp1/vsp1_video.c +++ b/drivers/media/platform/renesas/vsp1/vsp1_video.c @@ -896,7 +896,7 @@ static const struct vb2_ops vsp1_video_queue_qops = { static int vsp1_video_querycap(struct file *file, void *fh, struct v4l2_capability *cap) { - struct v4l2_fh *vfh = file->private_data; + struct v4l2_fh *vfh = file_to_v4l2_fh(file); struct vsp1_video *video = to_vsp1_video(vfh->vdev); cap->capabilities = V4L2_CAP_DEVICE_CAPS | V4L2_CAP_STREAMING @@ -912,7 +912,7 @@ vsp1_video_querycap(struct file *file, void *fh, struct v4l2_capability *cap) static int vsp1_video_enum_format(struct file *file, void *fh, struct v4l2_fmtdesc *f) { - struct v4l2_fh *vfh = file->private_data; + struct v4l2_fh *vfh = file_to_v4l2_fh(file); struct vsp1_video *video = to_vsp1_video(vfh->vdev); const struct vsp1_format_info *info; @@ -933,7 +933,7 @@ static int vsp1_video_enum_format(struct file *file, void *fh, static int vsp1_video_get_format(struct file *file, void *fh, struct v4l2_format *format) { - struct v4l2_fh *vfh = file->private_data; + struct v4l2_fh *vfh = file_to_v4l2_fh(file); struct vsp1_video *video = to_vsp1_video(vfh->vdev); if (format->type != video->queue.type) @@ -949,7 +949,7 @@ vsp1_video_get_format(struct file *file, void *fh, struct v4l2_format *format) static int vsp1_video_try_format(struct file *file, void *fh, struct v4l2_format *format) { - struct v4l2_fh *vfh = file->private_data; + struct v4l2_fh *vfh = file_to_v4l2_fh(file); struct vsp1_video *video = to_vsp1_video(vfh->vdev); if (format->type != video->queue.type) @@ -961,7 +961,7 @@ vsp1_video_try_format(struct file *file, void *fh, struct v4l2_format *format) static int vsp1_video_set_format(struct file *file, void *fh, struct v4l2_format *format) { - struct v4l2_fh *vfh = file->private_data; + struct v4l2_fh *vfh = file_to_v4l2_fh(file); struct vsp1_video *video = to_vsp1_video(vfh->vdev); const struct vsp1_format_info *info; int ret; @@ -991,7 +991,7 @@ done: static int vsp1_video_streamon(struct file *file, void *fh, enum v4l2_buf_type type) { - struct v4l2_fh *vfh = file->private_data; + struct v4l2_fh *vfh = file_to_v4l2_fh(file); struct vsp1_video *video = to_vsp1_video(vfh->vdev); struct media_device *mdev = &video->vsp1->media_dev; struct vsp1_pipeline *pipe; @@ -1079,13 +1079,11 @@ static int vsp1_video_open(struct file *file) return -ENOMEM; v4l2_fh_init(vfh, &video->video); - v4l2_fh_add(vfh); - - file->private_data = vfh; + v4l2_fh_add(vfh, file); ret = vsp1_device_get(video->vsp1); if (ret < 0) { - v4l2_fh_del(vfh); + v4l2_fh_del(vfh, file); v4l2_fh_exit(vfh); kfree(vfh); } diff --git a/drivers/media/platform/renesas/vsp1/vsp1_vspx.c b/drivers/media/platform/renesas/vsp1/vsp1_vspx.c index a754b92232bd..1673479be0ff 100644 --- a/drivers/media/platform/renesas/vsp1/vsp1_vspx.c +++ b/drivers/media/platform/renesas/vsp1/vsp1_vspx.c @@ -286,6 +286,7 @@ void vsp1_isp_free_buffer(struct device *dev, dma_free_coherent(bus_master, buffer_desc->size, buffer_desc->cpu_addr, buffer_desc->dma_addr); } +EXPORT_SYMBOL_GPL(vsp1_isp_free_buffer); /** * vsp1_isp_start_streaming - Start processing VSPX jobs diff --git a/drivers/media/platform/rockchip/rga/rga.c b/drivers/media/platform/rockchip/rga/rga.c index 3dccab5fa4a1..776046de979a 100644 --- a/drivers/media/platform/rockchip/rga/rga.c +++ b/drivers/media/platform/rockchip/rga/rga.c @@ -395,8 +395,7 @@ static int rga_open(struct file *file) return ret; } v4l2_fh_init(&ctx->fh, video_devdata(file)); - file->private_data = &ctx->fh; - v4l2_fh_add(&ctx->fh); + v4l2_fh_add(&ctx->fh, file); rga_setup_ctrls(ctx); @@ -411,8 +410,7 @@ static int rga_open(struct file *file) static int rga_release(struct file *file) { - struct rga_ctx *ctx = - container_of(file->private_data, struct rga_ctx, fh); + struct rga_ctx *ctx = file_to_rga_ctx(file); struct rockchip_rga *rga = ctx->rga; mutex_lock(&rga->mutex); @@ -420,7 +418,7 @@ static int rga_release(struct file *file) v4l2_m2m_ctx_release(ctx->fh.m2m_ctx); v4l2_ctrl_handler_free(&ctx->ctrl_handler); - v4l2_fh_del(&ctx->fh); + v4l2_fh_del(&ctx->fh, file); v4l2_fh_exit(&ctx->fh); kfree(ctx); @@ -448,7 +446,7 @@ vidioc_querycap(struct file *file, void *priv, struct v4l2_capability *cap) return 0; } -static int vidioc_enum_fmt(struct file *file, void *prv, struct v4l2_fmtdesc *f) +static int vidioc_enum_fmt(struct file *file, void *priv, struct v4l2_fmtdesc *f) { struct rga_fmt *fmt; @@ -461,10 +459,10 @@ static int vidioc_enum_fmt(struct file *file, void *prv, struct v4l2_fmtdesc *f) return 0; } -static int vidioc_g_fmt(struct file *file, void *prv, struct v4l2_format *f) +static int vidioc_g_fmt(struct file *file, void *priv, struct v4l2_format *f) { struct v4l2_pix_format_mplane *pix_fmt = &f->fmt.pix_mp; - struct rga_ctx *ctx = prv; + struct rga_ctx *ctx = file_to_rga_ctx(file); struct vb2_queue *vq; struct rga_frame *frm; @@ -483,7 +481,7 @@ static int vidioc_g_fmt(struct file *file, void *prv, struct v4l2_format *f) return 0; } -static int vidioc_try_fmt(struct file *file, void *prv, struct v4l2_format *f) +static int vidioc_try_fmt(struct file *file, void *priv, struct v4l2_format *f) { struct v4l2_pix_format_mplane *pix_fmt = &f->fmt.pix_mp; struct rga_fmt *fmt; @@ -503,10 +501,10 @@ static int vidioc_try_fmt(struct file *file, void *prv, struct v4l2_format *f) return 0; } -static int vidioc_s_fmt(struct file *file, void *prv, struct v4l2_format *f) +static int vidioc_s_fmt(struct file *file, void *priv, struct v4l2_format *f) { struct v4l2_pix_format_mplane *pix_fmt = &f->fmt.pix_mp; - struct rga_ctx *ctx = prv; + struct rga_ctx *ctx = file_to_rga_ctx(file); struct rockchip_rga *rga = ctx->rga; struct vb2_queue *vq; struct rga_frame *frm; @@ -516,7 +514,7 @@ static int vidioc_s_fmt(struct file *file, void *prv, struct v4l2_format *f) /* Adjust all values accordingly to the hardware capabilities * and chosen format. */ - ret = vidioc_try_fmt(file, prv, f); + ret = vidioc_try_fmt(file, priv, f); if (ret) return ret; vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, f->type); @@ -560,10 +558,10 @@ static int vidioc_s_fmt(struct file *file, void *prv, struct v4l2_format *f) return 0; } -static int vidioc_g_selection(struct file *file, void *prv, +static int vidioc_g_selection(struct file *file, void *priv, struct v4l2_selection *s) { - struct rga_ctx *ctx = prv; + struct rga_ctx *ctx = file_to_rga_ctx(file); struct rga_frame *f; bool use_frame = false; @@ -608,10 +606,10 @@ static int vidioc_g_selection(struct file *file, void *prv, return 0; } -static int vidioc_s_selection(struct file *file, void *prv, +static int vidioc_s_selection(struct file *file, void *priv, struct v4l2_selection *s) { - struct rga_ctx *ctx = prv; + struct rga_ctx *ctx = file_to_rga_ctx(file); struct rockchip_rga *rga = ctx->rga; struct rga_frame *f; int ret = 0; diff --git a/drivers/media/platform/rockchip/rga/rga.h b/drivers/media/platform/rockchip/rga/rga.h index 530e12de73c4..72a28b120fab 100644 --- a/drivers/media/platform/rockchip/rga/rga.h +++ b/drivers/media/platform/rockchip/rga/rga.h @@ -68,6 +68,11 @@ struct rga_ctx { u32 fill_color; }; +static inline struct rga_ctx *file_to_rga_ctx(struct file *filp) +{ + return container_of(file_to_v4l2_fh(filp), struct rga_ctx, fh); +} + struct rockchip_rga { struct v4l2_device v4l2_dev; struct v4l2_m2m_dev *m2m_dev; diff --git a/drivers/media/platform/rockchip/rkisp1/rkisp1-common.h b/drivers/media/platform/rockchip/rkisp1/rkisp1-common.h index 5f187f9efc7b..6028ecdd23de 100644 --- a/drivers/media/platform/rockchip/rkisp1/rkisp1-common.h +++ b/drivers/media/platform/rockchip/rkisp1/rkisp1-common.h @@ -24,6 +24,7 @@ #include "rkisp1-regs.h" struct dentry; +struct dev_pm_domain_list; struct regmap; /* @@ -55,7 +56,7 @@ struct regmap; #define RKISP1_BUS_INFO "platform:" RKISP1_DRIVER_NAME /* maximum number of clocks */ -#define RKISP1_MAX_BUS_CLK 8 +#define RKISP1_MAX_BUS_CLK 4 /* a bitmask of the ready stats */ #define RKISP1_STATS_MEAS_MASK (RKISP1_CIF_ISP_AWB_DONE | \ @@ -139,27 +140,31 @@ enum rkisp1_feature { /* * struct rkisp1_info - Model-specific ISP Information * - * @clks: array of ISP clock names - * @clk_size: number of entries in the @clks array + * @num_clocks: number of clocks * @isrs: array of ISP interrupt descriptors * @isr_size: number of entries in the @isrs array * @isp_ver: ISP version * @features: bitmask of rkisp1_feature features implemented by the ISP * @max_width: maximum input frame width * @max_height: maximum input frame height + * @pm_domains.names: name of the power domains + * @pm_domains.count: number of power domains * * This structure contains information about the ISP specific to a particular * ISP model, version, or integration in a particular SoC. */ struct rkisp1_info { - const char * const *clks; - unsigned int clk_size; + unsigned int num_clocks; const struct rkisp1_isr_data *isrs; unsigned int isr_size; enum rkisp1_cif_isp_version isp_ver; unsigned int features; unsigned int max_width; unsigned int max_height; + struct { + const char * const *names; + unsigned int count; + } pm_domains; }; /* @@ -483,6 +488,7 @@ struct rkisp1_debug { * @dev: a pointer to the struct device * @clk_size: number of clocks * @clks: array of clocks + * @pm_domains: power domains * @gasket: the gasket - i.MX8MP only * @gasket_id: the gasket ID (0 or 1) - i.MX8MP only * @v4l2_dev: v4l2_device variable @@ -507,6 +513,7 @@ struct rkisp1_device { struct device *dev; unsigned int clk_size; struct clk_bulk_data clks[RKISP1_MAX_BUS_CLK]; + struct dev_pm_domain_list *pm_domains; struct regmap *gasket; unsigned int gasket_id; struct v4l2_device v4l2_dev; diff --git a/drivers/media/platform/rockchip/rkisp1/rkisp1-dev.c b/drivers/media/platform/rockchip/rkisp1/rkisp1-dev.c index dc65a7924f8a..1791c02a40ae 100644 --- a/drivers/media/platform/rockchip/rkisp1/rkisp1-dev.c +++ b/drivers/media/platform/rockchip/rkisp1/rkisp1-dev.c @@ -8,6 +8,7 @@ * Copyright (C) 2017 Rockchip Electronics Co., Ltd. */ +#include <linux/build_bug.h> #include <linux/clk.h> #include <linux/interrupt.h> #include <linux/mfd/syscon.h> @@ -16,6 +17,7 @@ #include <linux/of_graph.h> #include <linux/platform_device.h> #include <linux/pinctrl/consumer.h> +#include <linux/pm_domain.h> #include <linux/pm_runtime.h> #include <media/v4l2-fwnode.h> #include <media/v4l2-mc.h> @@ -491,13 +493,6 @@ static irqreturn_t rkisp1_isr(int irq, void *ctx) return ret; } -static const char * const px30_isp_clks[] = { - "isp", - "aclk", - "hclk", - "pclk", -}; - static const struct rkisp1_isr_data px30_isp_isrs[] = { { "isp", rkisp1_isp_isr, BIT(RKISP1_IRQ_ISP) }, { "mi", rkisp1_capture_isr, BIT(RKISP1_IRQ_MI) }, @@ -505,8 +500,7 @@ static const struct rkisp1_isr_data px30_isp_isrs[] = { }; static const struct rkisp1_info px30_isp_info = { - .clks = px30_isp_clks, - .clk_size = ARRAY_SIZE(px30_isp_clks), + .num_clocks = 4, .isrs = px30_isp_isrs, .isr_size = ARRAY_SIZE(px30_isp_isrs), .isp_ver = RKISP1_V12, @@ -518,19 +512,12 @@ static const struct rkisp1_info px30_isp_info = { .max_height = 2448, }; -static const char * const rk3399_isp_clks[] = { - "isp", - "aclk", - "hclk", -}; - static const struct rkisp1_isr_data rk3399_isp_isrs[] = { { NULL, rkisp1_isr, BIT(RKISP1_IRQ_ISP) | BIT(RKISP1_IRQ_MI) | BIT(RKISP1_IRQ_MIPI) }, }; static const struct rkisp1_info rk3399_isp_info = { - .clks = rk3399_isp_clks, - .clk_size = ARRAY_SIZE(rk3399_isp_clks), + .num_clocks = 3, .isrs = rk3399_isp_isrs, .isr_size = ARRAY_SIZE(rk3399_isp_isrs), .isp_ver = RKISP1_V10, @@ -542,19 +529,17 @@ static const struct rkisp1_info rk3399_isp_info = { .max_height = 3312, }; -static const char * const imx8mp_isp_clks[] = { - "isp", - "hclk", - "aclk", -}; - static const struct rkisp1_isr_data imx8mp_isp_isrs[] = { { NULL, rkisp1_isr, BIT(RKISP1_IRQ_ISP) | BIT(RKISP1_IRQ_MI) }, }; +static const char * const imx8mp_isp_pm_domains[] = { + "isp", + "csi2", +}; + static const struct rkisp1_info imx8mp_isp_info = { - .clks = imx8mp_isp_clks, - .clk_size = ARRAY_SIZE(imx8mp_isp_clks), + .num_clocks = 3, .isrs = imx8mp_isp_isrs, .isr_size = ARRAY_SIZE(imx8mp_isp_isrs), .isp_ver = RKISP1_V_IMX8MP, @@ -563,6 +548,10 @@ static const struct rkisp1_info imx8mp_isp_info = { | RKISP1_FEATURE_COMPAND, .max_width = 4096, .max_height = 3072, + .pm_domains = { + .names = imx8mp_isp_pm_domains, + .count = ARRAY_SIZE(imx8mp_isp_pm_domains), + }, }; static const struct of_device_id rkisp1_of_match[] = { @@ -582,6 +571,81 @@ static const struct of_device_id rkisp1_of_match[] = { }; MODULE_DEVICE_TABLE(of, rkisp1_of_match); +static const char * const rkisp1_clk_names[] = { + "isp", + "aclk", + "hclk", + "pclk", +}; + +static int rkisp1_init_clocks(struct rkisp1_device *rkisp1) +{ + const struct rkisp1_info *info = rkisp1->info; + unsigned int i; + int ret; + + static_assert(ARRAY_SIZE(rkisp1_clk_names) == ARRAY_SIZE(rkisp1->clks)); + + for (i = 0; i < info->num_clocks; i++) + rkisp1->clks[i].id = rkisp1_clk_names[i]; + + ret = devm_clk_bulk_get(rkisp1->dev, info->num_clocks, rkisp1->clks); + if (ret) + return ret; + + rkisp1->clk_size = info->num_clocks; + + /* + * On i.MX8MP the pclk clock is needed to access the HDR stitching + * registers, but wasn't required by DT bindings. Try to acquire it as + * an optional clock to avoid breaking backward compatibility. + */ + if (info->isp_ver == RKISP1_V_IMX8MP) { + struct clk *clk; + + clk = devm_clk_get_optional(rkisp1->dev, "pclk"); + if (IS_ERR(clk)) + return dev_err_probe(rkisp1->dev, PTR_ERR(clk), + "Failed to acquire pclk clock\n"); + + if (clk) + rkisp1->clks[rkisp1->clk_size++].clk = clk; + } + + return 0; +} + +static int rkisp1_init_pm_domains(struct rkisp1_device *rkisp1) +{ + const struct rkisp1_info *info = rkisp1->info; + struct dev_pm_domain_attach_data pm_domain_data = { + .pd_names = info->pm_domains.names, + .num_pd_names = info->pm_domains.count, + }; + int ret; + + /* + * Most platforms have a single power domain, which the PM domain core + * automatically attaches at probe time. When that's the case there's + * nothing to do here. + */ + if (rkisp1->dev->pm_domain) + return 0; + + if (!pm_domain_data.num_pd_names) + return 0; + + ret = devm_pm_domain_attach_list(rkisp1->dev, &pm_domain_data, + &rkisp1->pm_domains); + if (ret < 0) { + dev_err_probe(rkisp1->dev, ret, + "Failed to attach power domains\n"); + return ret; + } + + return 0; +} + static int rkisp1_probe(struct platform_device *pdev) { const struct rkisp1_info *info; @@ -639,12 +703,13 @@ static int rkisp1_probe(struct platform_device *pdev) } } - for (i = 0; i < info->clk_size; i++) - rkisp1->clks[i].id = info->clks[i]; - ret = devm_clk_bulk_get(dev, info->clk_size, rkisp1->clks); + ret = rkisp1_init_clocks(rkisp1); + if (ret) + return ret; + + ret = rkisp1_init_pm_domains(rkisp1); if (ret) return ret; - rkisp1->clk_size = info->clk_size; if (info->isp_ver == RKISP1_V_IMX8MP) { unsigned int id; diff --git a/drivers/media/platform/rockchip/rkvdec/rkvdec.c b/drivers/media/platform/rockchip/rkvdec/rkvdec.c index d3b31f461194..6e606d73ff51 100644 --- a/drivers/media/platform/rockchip/rkvdec/rkvdec.c +++ b/drivers/media/platform/rockchip/rkvdec/rkvdec.c @@ -354,7 +354,7 @@ static int rkvdec_try_capture_fmt(struct file *file, void *priv, struct v4l2_format *f) { struct v4l2_pix_format_mplane *pix_mp = &f->fmt.pix_mp; - struct rkvdec_ctx *ctx = fh_to_rkvdec_ctx(priv); + struct rkvdec_ctx *ctx = file_to_rkvdec_ctx(file); const struct rkvdec_coded_fmt_desc *coded_desc; /* @@ -387,7 +387,7 @@ static int rkvdec_try_output_fmt(struct file *file, void *priv, struct v4l2_format *f) { struct v4l2_pix_format_mplane *pix_mp = &f->fmt.pix_mp; - struct rkvdec_ctx *ctx = fh_to_rkvdec_ctx(priv); + struct rkvdec_ctx *ctx = file_to_rkvdec_ctx(file); const struct rkvdec_coded_fmt_desc *desc; desc = rkvdec_find_coded_fmt_desc(pix_mp->pixelformat); @@ -418,7 +418,7 @@ static int rkvdec_try_output_fmt(struct file *file, void *priv, static int rkvdec_s_capture_fmt(struct file *file, void *priv, struct v4l2_format *f) { - struct rkvdec_ctx *ctx = fh_to_rkvdec_ctx(priv); + struct rkvdec_ctx *ctx = file_to_rkvdec_ctx(file); struct vb2_queue *vq; int ret; @@ -439,7 +439,7 @@ static int rkvdec_s_capture_fmt(struct file *file, void *priv, static int rkvdec_s_output_fmt(struct file *file, void *priv, struct v4l2_format *f) { - struct rkvdec_ctx *ctx = fh_to_rkvdec_ctx(priv); + struct rkvdec_ctx *ctx = file_to_rkvdec_ctx(file); struct v4l2_m2m_ctx *m2m_ctx = ctx->fh.m2m_ctx; const struct rkvdec_coded_fmt_desc *desc; struct v4l2_format *cap_fmt; @@ -504,7 +504,7 @@ static int rkvdec_s_output_fmt(struct file *file, void *priv, static int rkvdec_g_output_fmt(struct file *file, void *priv, struct v4l2_format *f) { - struct rkvdec_ctx *ctx = fh_to_rkvdec_ctx(priv); + struct rkvdec_ctx *ctx = file_to_rkvdec_ctx(file); *f = ctx->coded_fmt; return 0; @@ -513,7 +513,7 @@ static int rkvdec_g_output_fmt(struct file *file, void *priv, static int rkvdec_g_capture_fmt(struct file *file, void *priv, struct v4l2_format *f) { - struct rkvdec_ctx *ctx = fh_to_rkvdec_ctx(priv); + struct rkvdec_ctx *ctx = file_to_rkvdec_ctx(file); *f = ctx->decoded_fmt; return 0; @@ -532,7 +532,7 @@ static int rkvdec_enum_output_fmt(struct file *file, void *priv, static int rkvdec_enum_capture_fmt(struct file *file, void *priv, struct v4l2_fmtdesc *f) { - struct rkvdec_ctx *ctx = fh_to_rkvdec_ctx(priv); + struct rkvdec_ctx *ctx = file_to_rkvdec_ctx(file); u32 fourcc; fourcc = rkvdec_enum_decoded_fmt(ctx, f->index, ctx->image_fmt); @@ -937,8 +937,7 @@ static int rkvdec_open(struct file *filp) if (ret) goto err_cleanup_m2m_ctx; - filp->private_data = &ctx->fh; - v4l2_fh_add(&ctx->fh); + v4l2_fh_add(&ctx->fh, filp); return 0; @@ -952,9 +951,9 @@ err_free_ctx: static int rkvdec_release(struct file *filp) { - struct rkvdec_ctx *ctx = fh_to_rkvdec_ctx(filp->private_data); + struct rkvdec_ctx *ctx = file_to_rkvdec_ctx(filp); - v4l2_fh_del(&ctx->fh); + v4l2_fh_del(&ctx->fh, filp); v4l2_m2m_ctx_release(ctx->fh.m2m_ctx); v4l2_ctrl_handler_free(&ctx->ctrl_hdl); v4l2_fh_exit(&ctx->fh); diff --git a/drivers/media/platform/rockchip/rkvdec/rkvdec.h b/drivers/media/platform/rockchip/rkvdec/rkvdec.h index f6e8bf38add3..481aaa4bffe9 100644 --- a/drivers/media/platform/rockchip/rkvdec/rkvdec.h +++ b/drivers/media/platform/rockchip/rkvdec/rkvdec.h @@ -124,9 +124,9 @@ struct rkvdec_ctx { void *priv; }; -static inline struct rkvdec_ctx *fh_to_rkvdec_ctx(struct v4l2_fh *fh) +static inline struct rkvdec_ctx *file_to_rkvdec_ctx(struct file *filp) { - return container_of(fh, struct rkvdec_ctx, fh); + return container_of(file_to_v4l2_fh(filp), struct rkvdec_ctx, fh); } struct rkvdec_aux_buf { diff --git a/drivers/media/platform/samsung/exynos-gsc/gsc-core.h b/drivers/media/platform/samsung/exynos-gsc/gsc-core.h index b9777e07fb6d..265221abf4dc 100644 --- a/drivers/media/platform/samsung/exynos-gsc/gsc-core.h +++ b/drivers/media/platform/samsung/exynos-gsc/gsc-core.h @@ -85,7 +85,6 @@ enum gsc_yuv_fmt { GSC_CRCB, }; -#define fh_to_ctx(__fh) container_of(__fh, struct gsc_ctx, fh) #define is_rgb(x) (!!((x) & 0x1)) #define is_yuv420(x) (!!((x) & 0x2)) #define is_yuv422(x) (!!((x) & 0x4)) @@ -381,6 +380,11 @@ struct gsc_ctx { enum v4l2_colorspace out_colorspace; }; +static inline struct gsc_ctx *file_to_ctx(struct file *filp) +{ + return container_of(file_to_v4l2_fh(filp), struct gsc_ctx, fh); +} + void gsc_set_prefbuf(struct gsc_dev *gsc, struct gsc_frame *frm); int gsc_register_m2m_device(struct gsc_dev *gsc); void gsc_unregister_m2m_device(struct gsc_dev *gsc); diff --git a/drivers/media/platform/samsung/exynos-gsc/gsc-m2m.c b/drivers/media/platform/samsung/exynos-gsc/gsc-m2m.c index 4bda1c369c44..722e2531e23f 100644 --- a/drivers/media/platform/samsung/exynos-gsc/gsc-m2m.c +++ b/drivers/media/platform/samsung/exynos-gsc/gsc-m2m.c @@ -297,7 +297,7 @@ static int gsc_m2m_enum_fmt(struct file *file, void *priv, static int gsc_m2m_g_fmt_mplane(struct file *file, void *fh, struct v4l2_format *f) { - struct gsc_ctx *ctx = fh_to_ctx(fh); + struct gsc_ctx *ctx = file_to_ctx(file); return gsc_g_fmt_mplane(ctx, f); } @@ -305,7 +305,7 @@ static int gsc_m2m_g_fmt_mplane(struct file *file, void *fh, static int gsc_m2m_try_fmt_mplane(struct file *file, void *fh, struct v4l2_format *f) { - struct gsc_ctx *ctx = fh_to_ctx(fh); + struct gsc_ctx *ctx = file_to_ctx(file); return gsc_try_fmt_mplane(ctx, f); } @@ -313,7 +313,7 @@ static int gsc_m2m_try_fmt_mplane(struct file *file, void *fh, static int gsc_m2m_s_fmt_mplane(struct file *file, void *fh, struct v4l2_format *f) { - struct gsc_ctx *ctx = fh_to_ctx(fh); + struct gsc_ctx *ctx = file_to_ctx(file); struct vb2_queue *vq; struct gsc_frame *frame; struct v4l2_pix_format_mplane *pix; @@ -359,7 +359,7 @@ static int gsc_m2m_s_fmt_mplane(struct file *file, void *fh, static int gsc_m2m_reqbufs(struct file *file, void *fh, struct v4l2_requestbuffers *reqbufs) { - struct gsc_ctx *ctx = fh_to_ctx(fh); + struct gsc_ctx *ctx = file_to_ctx(file); struct gsc_dev *gsc = ctx->gsc_dev; u32 max_cnt; @@ -374,35 +374,35 @@ static int gsc_m2m_reqbufs(struct file *file, void *fh, static int gsc_m2m_expbuf(struct file *file, void *fh, struct v4l2_exportbuffer *eb) { - struct gsc_ctx *ctx = fh_to_ctx(fh); + struct gsc_ctx *ctx = file_to_ctx(file); return v4l2_m2m_expbuf(file, ctx->m2m_ctx, eb); } static int gsc_m2m_querybuf(struct file *file, void *fh, struct v4l2_buffer *buf) { - struct gsc_ctx *ctx = fh_to_ctx(fh); + struct gsc_ctx *ctx = file_to_ctx(file); return v4l2_m2m_querybuf(file, ctx->m2m_ctx, buf); } static int gsc_m2m_qbuf(struct file *file, void *fh, struct v4l2_buffer *buf) { - struct gsc_ctx *ctx = fh_to_ctx(fh); + struct gsc_ctx *ctx = file_to_ctx(file); return v4l2_m2m_qbuf(file, ctx->m2m_ctx, buf); } static int gsc_m2m_dqbuf(struct file *file, void *fh, struct v4l2_buffer *buf) { - struct gsc_ctx *ctx = fh_to_ctx(fh); + struct gsc_ctx *ctx = file_to_ctx(file); return v4l2_m2m_dqbuf(file, ctx->m2m_ctx, buf); } static int gsc_m2m_streamon(struct file *file, void *fh, enum v4l2_buf_type type) { - struct gsc_ctx *ctx = fh_to_ctx(fh); + struct gsc_ctx *ctx = file_to_ctx(file); /* The source and target color format need to be set */ if (V4L2_TYPE_IS_OUTPUT(type)) { @@ -418,7 +418,7 @@ static int gsc_m2m_streamon(struct file *file, void *fh, static int gsc_m2m_streamoff(struct file *file, void *fh, enum v4l2_buf_type type) { - struct gsc_ctx *ctx = fh_to_ctx(fh); + struct gsc_ctx *ctx = file_to_ctx(file); return v4l2_m2m_streamoff(file, ctx->m2m_ctx, type); } @@ -440,8 +440,8 @@ static int is_rectangle_enclosed(struct v4l2_rect *a, struct v4l2_rect *b) static int gsc_m2m_g_selection(struct file *file, void *fh, struct v4l2_selection *s) { + struct gsc_ctx *ctx = file_to_ctx(file); struct gsc_frame *frame; - struct gsc_ctx *ctx = fh_to_ctx(fh); if ((s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) && (s->type != V4L2_BUF_TYPE_VIDEO_OUTPUT)) @@ -478,7 +478,7 @@ static int gsc_m2m_s_selection(struct file *file, void *fh, struct v4l2_selection *s) { struct gsc_frame *frame; - struct gsc_ctx *ctx = fh_to_ctx(fh); + struct gsc_ctx *ctx = file_to_ctx(file); struct gsc_variant *variant = ctx->gsc_dev->variant; struct v4l2_selection sel = *s; int ret; @@ -625,8 +625,7 @@ static int gsc_m2m_open(struct file *file) /* Use separate control handler per file handle */ ctx->fh.ctrl_handler = &ctx->ctrl_handler; - file->private_data = &ctx->fh; - v4l2_fh_add(&ctx->fh); + v4l2_fh_add(&ctx->fh, file); ctx->gsc_dev = gsc; /* Default color format */ @@ -655,7 +654,7 @@ static int gsc_m2m_open(struct file *file) error_ctrls: gsc_ctrls_delete(ctx); - v4l2_fh_del(&ctx->fh); + v4l2_fh_del(&ctx->fh, file); error_fh: v4l2_fh_exit(&ctx->fh); kfree(ctx); @@ -666,7 +665,7 @@ unlock: static int gsc_m2m_release(struct file *file) { - struct gsc_ctx *ctx = fh_to_ctx(file->private_data); + struct gsc_ctx *ctx = file_to_ctx(file); struct gsc_dev *gsc = ctx->gsc_dev; pr_debug("pid: %d, state: 0x%lx, refcnt= %d", @@ -676,7 +675,7 @@ static int gsc_m2m_release(struct file *file) v4l2_m2m_ctx_release(ctx->m2m_ctx); gsc_ctrls_delete(ctx); - v4l2_fh_del(&ctx->fh); + v4l2_fh_del(&ctx->fh, file); v4l2_fh_exit(&ctx->fh); if (--gsc->m2m.refcnt <= 0) @@ -690,7 +689,7 @@ static int gsc_m2m_release(struct file *file) static __poll_t gsc_m2m_poll(struct file *file, struct poll_table_struct *wait) { - struct gsc_ctx *ctx = fh_to_ctx(file->private_data); + struct gsc_ctx *ctx = file_to_ctx(file); struct gsc_dev *gsc = ctx->gsc_dev; __poll_t ret; @@ -705,7 +704,7 @@ static __poll_t gsc_m2m_poll(struct file *file, static int gsc_m2m_mmap(struct file *file, struct vm_area_struct *vma) { - struct gsc_ctx *ctx = fh_to_ctx(file->private_data); + struct gsc_ctx *ctx = file_to_ctx(file); struct gsc_dev *gsc = ctx->gsc_dev; int ret; diff --git a/drivers/media/platform/samsung/exynos4-is/fimc-core.h b/drivers/media/platform/samsung/exynos4-is/fimc-core.h index 63385152a2ff..c23cbdee7afc 100644 --- a/drivers/media/platform/samsung/exynos4-is/fimc-core.h +++ b/drivers/media/platform/samsung/exynos4-is/fimc-core.h @@ -496,7 +496,10 @@ struct fimc_ctx { struct fimc_ctrls ctrls; }; -#define fh_to_ctx(__fh) container_of(__fh, struct fimc_ctx, fh) +static inline struct fimc_ctx *file_to_ctx(struct file *filp) +{ + return container_of(file_to_v4l2_fh(filp), struct fimc_ctx, fh); +} static inline void set_frame_bounds(struct fimc_frame *f, u32 width, u32 height) { diff --git a/drivers/media/platform/samsung/exynos4-is/fimc-m2m.c b/drivers/media/platform/samsung/exynos4-is/fimc-m2m.c index 951433c8e92a..562c57f186c6 100644 --- a/drivers/media/platform/samsung/exynos4-is/fimc-m2m.c +++ b/drivers/media/platform/samsung/exynos4-is/fimc-m2m.c @@ -249,7 +249,7 @@ static int fimc_m2m_enum_fmt(struct file *file, void *priv, static int fimc_m2m_g_fmt_mplane(struct file *file, void *fh, struct v4l2_format *f) { - struct fimc_ctx *ctx = fh_to_ctx(fh); + struct fimc_ctx *ctx = file_to_ctx(file); const struct fimc_frame *frame = ctx_get_frame(ctx, f->type); if (IS_ERR(frame)) @@ -308,7 +308,7 @@ static int fimc_try_fmt_mplane(struct fimc_ctx *ctx, struct v4l2_format *f) static int fimc_m2m_try_fmt_mplane(struct file *file, void *fh, struct v4l2_format *f) { - struct fimc_ctx *ctx = fh_to_ctx(fh); + struct fimc_ctx *ctx = file_to_ctx(file); return fimc_try_fmt_mplane(ctx, f); } @@ -337,7 +337,7 @@ static void __set_frame_format(struct fimc_frame *frame, static int fimc_m2m_s_fmt_mplane(struct file *file, void *fh, struct v4l2_format *f) { - struct fimc_ctx *ctx = fh_to_ctx(fh); + struct fimc_ctx *ctx = file_to_ctx(file); struct fimc_dev *fimc = ctx->fimc_dev; const struct fimc_fmt *fmt; struct vb2_queue *vq; @@ -376,7 +376,7 @@ static int fimc_m2m_s_fmt_mplane(struct file *file, void *fh, static int fimc_m2m_g_selection(struct file *file, void *fh, struct v4l2_selection *s) { - struct fimc_ctx *ctx = fh_to_ctx(fh); + struct fimc_ctx *ctx = file_to_ctx(file); const struct fimc_frame *frame; frame = ctx_get_frame(ctx, s->type); @@ -484,7 +484,7 @@ static int fimc_m2m_try_selection(struct fimc_ctx *ctx, static int fimc_m2m_s_selection(struct file *file, void *fh, struct v4l2_selection *s) { - struct fimc_ctx *ctx = fh_to_ctx(fh); + struct fimc_ctx *ctx = file_to_ctx(file); struct fimc_dev *fimc = ctx->fimc_dev; struct fimc_frame *f; int ret; @@ -634,8 +634,7 @@ static int fimc_m2m_open(struct file *file) /* Use separate control handler per file handle */ ctx->fh.ctrl_handler = &ctx->ctrls.handler; - file->private_data = &ctx->fh; - v4l2_fh_add(&ctx->fh); + v4l2_fh_add(&ctx->fh, file); /* Setup the device context for memory-to-memory mode */ ctx->state = FIMC_CTX_M2M; @@ -664,7 +663,7 @@ error_m2m_ctx: v4l2_m2m_ctx_release(ctx->fh.m2m_ctx); error_c: fimc_ctrls_delete(ctx); - v4l2_fh_del(&ctx->fh); + v4l2_fh_del(&ctx->fh, file); error_fh: v4l2_fh_exit(&ctx->fh); kfree(ctx); @@ -675,7 +674,7 @@ unlock: static int fimc_m2m_release(struct file *file) { - struct fimc_ctx *ctx = fh_to_ctx(file->private_data); + struct fimc_ctx *ctx = file_to_ctx(file); struct fimc_dev *fimc = ctx->fimc_dev; dbg("pid: %d, state: 0x%lx, refcnt= %d", @@ -685,7 +684,7 @@ static int fimc_m2m_release(struct file *file) v4l2_m2m_ctx_release(ctx->fh.m2m_ctx); fimc_ctrls_delete(ctx); - v4l2_fh_del(&ctx->fh); + v4l2_fh_del(&ctx->fh, file); v4l2_fh_exit(&ctx->fh); if (--fimc->m2m.refcnt <= 0) diff --git a/drivers/media/platform/samsung/s3c-camif/camif-capture.c b/drivers/media/platform/samsung/s3c-camif/camif-capture.c index 3e566b65f417..ed1a1d693293 100644 --- a/drivers/media/platform/samsung/s3c-camif/camif-capture.c +++ b/drivers/media/platform/samsung/s3c-camif/camif-capture.c @@ -572,7 +572,7 @@ static int s3c_camif_close(struct file *file) mutex_lock(&camif->lock); - if (vp->owner == file->private_data) { + if (vp->owner == file_to_v4l2_fh(file)) { camif_stop_capture(vp); vb2_queue_release(&vp->vb_queue); vp->owner = NULL; @@ -595,7 +595,7 @@ static __poll_t s3c_camif_poll(struct file *file, __poll_t ret; mutex_lock(&camif->lock); - if (vp->owner && vp->owner != file->private_data) + if (vp->owner && vp->owner != file_to_v4l2_fh(file)) ret = EPOLLERR; else ret = vb2_poll(&vp->vb_queue, file, wait); @@ -609,7 +609,7 @@ static int s3c_camif_mmap(struct file *file, struct vm_area_struct *vma) struct camif_vp *vp = video_drvdata(file); int ret; - if (vp->owner && vp->owner != file->private_data) + if (vp->owner && vp->owner != file_to_v4l2_fh(file)) ret = -EBUSY; else ret = vb2_mmap(&vp->vb_queue, vma); @@ -791,7 +791,7 @@ static int s3c_camif_vidioc_s_fmt(struct file *file, void *priv, out_frame->rect.top = 0; if (vp->owner == NULL) - vp->owner = priv; + vp->owner = file_to_v4l2_fh(file); pr_debug("%ux%u. payload: %u. fmt: 0x%08x. %d %d. sizeimage: %d. bpl: %d\n", out_frame->f_width, out_frame->f_height, vp->payload, @@ -841,7 +841,7 @@ static int s3c_camif_streamon(struct file *file, void *priv, if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE) return -EINVAL; - if (vp->owner && vp->owner != priv) + if (vp->owner && vp->owner != file_to_v4l2_fh(file)) return -EBUSY; if (s3c_vp_active(vp)) @@ -872,7 +872,7 @@ static int s3c_camif_streamoff(struct file *file, void *priv, if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE) return -EINVAL; - if (vp->owner && vp->owner != priv) + if (vp->owner && vp->owner != file_to_v4l2_fh(file)) return -EBUSY; ret = vb2_streamoff(&vp->vb_queue, type); @@ -888,9 +888,9 @@ static int s3c_camif_reqbufs(struct file *file, void *priv, int ret; pr_debug("[vp%d] rb count: %d, owner: %p, priv: %p\n", - vp->id, rb->count, vp->owner, priv); + vp->id, rb->count, vp->owner, file_to_v4l2_fh(file)); - if (vp->owner && vp->owner != priv) + if (vp->owner && vp->owner != file_to_v4l2_fh(file)) return -EBUSY; if (rb->count) @@ -910,7 +910,7 @@ static int s3c_camif_reqbufs(struct file *file, void *priv, vp->reqbufs_count = rb->count; if (vp->owner == NULL && rb->count > 0) - vp->owner = priv; + vp->owner = file_to_v4l2_fh(file); return ret; } @@ -929,7 +929,7 @@ static int s3c_camif_qbuf(struct file *file, void *priv, pr_debug("[vp%d]\n", vp->id); - if (vp->owner && vp->owner != priv) + if (vp->owner && vp->owner != file_to_v4l2_fh(file)) return -EBUSY; return vb2_qbuf(&vp->vb_queue, vp->vdev.v4l2_dev->mdev, buf); @@ -942,7 +942,7 @@ static int s3c_camif_dqbuf(struct file *file, void *priv, pr_debug("[vp%d] sequence: %d\n", vp->id, vp->frame_sequence); - if (vp->owner && vp->owner != priv) + if (vp->owner && vp->owner != file_to_v4l2_fh(file)) return -EBUSY; return vb2_dqbuf(&vp->vb_queue, buf, file->f_flags & O_NONBLOCK); @@ -954,14 +954,14 @@ static int s3c_camif_create_bufs(struct file *file, void *priv, struct camif_vp *vp = video_drvdata(file); int ret; - if (vp->owner && vp->owner != priv) + if (vp->owner && vp->owner != file_to_v4l2_fh(file)) return -EBUSY; create->count = max_t(u32, 1, create->count); ret = vb2_create_bufs(&vp->vb_queue, create); if (!ret && vp->owner == NULL) - vp->owner = priv; + vp->owner = file_to_v4l2_fh(file); return ret; } diff --git a/drivers/media/platform/samsung/s5p-g2d/g2d.c b/drivers/media/platform/samsung/s5p-g2d/g2d.c index ffed16a34493..ffb9bee6cb9d 100644 --- a/drivers/media/platform/samsung/s5p-g2d/g2d.c +++ b/drivers/media/platform/samsung/s5p-g2d/g2d.c @@ -25,7 +25,10 @@ #include "g2d.h" #include "g2d-regs.h" -#define fh2ctx(__fh) container_of(__fh, struct g2d_ctx, fh) +static inline struct g2d_ctx *file2ctx(struct file *filp) +{ + return container_of(file_to_v4l2_fh(filp), struct g2d_ctx, fh); +} static struct g2d_fmt formats[] = { { @@ -254,8 +257,7 @@ static int g2d_open(struct file *file) return ret; } v4l2_fh_init(&ctx->fh, video_devdata(file)); - file->private_data = &ctx->fh; - v4l2_fh_add(&ctx->fh); + v4l2_fh_add(&ctx->fh, file); g2d_setup_ctrls(ctx); @@ -272,13 +274,13 @@ static int g2d_open(struct file *file) static int g2d_release(struct file *file) { struct g2d_dev *dev = video_drvdata(file); - struct g2d_ctx *ctx = fh2ctx(file->private_data); + struct g2d_ctx *ctx = file2ctx(file); mutex_lock(&dev->mutex); v4l2_m2m_ctx_release(ctx->fh.m2m_ctx); mutex_unlock(&dev->mutex); v4l2_ctrl_handler_free(&ctx->ctrl_handler); - v4l2_fh_del(&ctx->fh); + v4l2_fh_del(&ctx->fh, file); v4l2_fh_exit(&ctx->fh); kfree(ctx); v4l2_info(&dev->v4l2_dev, "instance closed\n"); @@ -295,7 +297,7 @@ static int vidioc_querycap(struct file *file, void *priv, return 0; } -static int vidioc_enum_fmt(struct file *file, void *prv, struct v4l2_fmtdesc *f) +static int vidioc_enum_fmt(struct file *file, void *priv, struct v4l2_fmtdesc *f) { if (f->index >= NUM_FORMATS) return -EINVAL; @@ -303,9 +305,9 @@ static int vidioc_enum_fmt(struct file *file, void *prv, struct v4l2_fmtdesc *f) return 0; } -static int vidioc_g_fmt(struct file *file, void *prv, struct v4l2_format *f) +static int vidioc_g_fmt(struct file *file, void *priv, struct v4l2_format *f) { - struct g2d_ctx *ctx = prv; + struct g2d_ctx *ctx = file2ctx(file); struct vb2_queue *vq; struct g2d_frame *frm; @@ -325,7 +327,7 @@ static int vidioc_g_fmt(struct file *file, void *prv, struct v4l2_format *f) return 0; } -static int vidioc_try_fmt(struct file *file, void *prv, struct v4l2_format *f) +static int vidioc_try_fmt(struct file *file, void *priv, struct v4l2_format *f) { struct g2d_fmt *fmt; enum v4l2_field *field; @@ -355,9 +357,9 @@ static int vidioc_try_fmt(struct file *file, void *prv, struct v4l2_format *f) return 0; } -static int vidioc_s_fmt(struct file *file, void *prv, struct v4l2_format *f) +static int vidioc_s_fmt(struct file *file, void *priv, struct v4l2_format *f) { - struct g2d_ctx *ctx = prv; + struct g2d_ctx *ctx = file2ctx(file); struct g2d_dev *dev = ctx->dev; struct vb2_queue *vq; struct g2d_frame *frm; @@ -366,7 +368,7 @@ static int vidioc_s_fmt(struct file *file, void *prv, struct v4l2_format *f) /* Adjust all values accordingly to the hardware capabilities * and chosen format. */ - ret = vidioc_try_fmt(file, prv, f); + ret = vidioc_try_fmt(file, priv, f); if (ret) return ret; vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, f->type); @@ -395,10 +397,10 @@ static int vidioc_s_fmt(struct file *file, void *prv, struct v4l2_format *f) return 0; } -static int vidioc_g_selection(struct file *file, void *prv, +static int vidioc_g_selection(struct file *file, void *priv, struct v4l2_selection *s) { - struct g2d_ctx *ctx = prv; + struct g2d_ctx *ctx = file2ctx(file); struct g2d_frame *f; f = get_frame(ctx, s->type); @@ -445,10 +447,10 @@ static int vidioc_g_selection(struct file *file, void *prv, return 0; } -static int vidioc_try_selection(struct file *file, void *prv, +static int vidioc_try_selection(struct file *file, void *priv, const struct v4l2_selection *s) { - struct g2d_ctx *ctx = prv; + struct g2d_ctx *ctx = file2ctx(file); struct g2d_dev *dev = ctx->dev; struct g2d_frame *f; @@ -473,14 +475,14 @@ static int vidioc_try_selection(struct file *file, void *prv, return 0; } -static int vidioc_s_selection(struct file *file, void *prv, +static int vidioc_s_selection(struct file *file, void *priv, struct v4l2_selection *s) { - struct g2d_ctx *ctx = prv; + struct g2d_ctx *ctx = file2ctx(file); struct g2d_frame *f; int ret; - ret = vidioc_try_selection(file, prv, s); + ret = vidioc_try_selection(file, priv, s); if (ret) return ret; f = get_frame(ctx, s->type); diff --git a/drivers/media/platform/samsung/s5p-jpeg/jpeg-core.c b/drivers/media/platform/samsung/s5p-jpeg/jpeg-core.c index ac4cf269456a..81792f7f8b16 100644 --- a/drivers/media/platform/samsung/s5p-jpeg/jpeg-core.c +++ b/drivers/media/platform/samsung/s5p-jpeg/jpeg-core.c @@ -580,9 +580,9 @@ static inline struct s5p_jpeg_ctx *ctrl_to_ctx(struct v4l2_ctrl *c) return container_of(c->handler, struct s5p_jpeg_ctx, ctrl_handler); } -static inline struct s5p_jpeg_ctx *fh_to_ctx(struct v4l2_fh *fh) +static inline struct s5p_jpeg_ctx *file_to_ctx(struct file *filp) { - return container_of(fh, struct s5p_jpeg_ctx, fh); + return container_of(file_to_v4l2_fh(filp), struct s5p_jpeg_ctx, fh); } static int s5p_jpeg_to_user_subsampling(struct s5p_jpeg_ctx *ctx) @@ -965,8 +965,7 @@ static int s5p_jpeg_open(struct file *file) v4l2_fh_init(&ctx->fh, vfd); /* Use separate control handler per file handle */ ctx->fh.ctrl_handler = &ctx->ctrl_handler; - file->private_data = &ctx->fh; - v4l2_fh_add(&ctx->fh); + v4l2_fh_add(&ctx->fh, file); ctx->jpeg = jpeg; if (vfd == jpeg->vfd_encoder) { @@ -1001,7 +1000,7 @@ static int s5p_jpeg_open(struct file *file) return 0; error: - v4l2_fh_del(&ctx->fh); + v4l2_fh_del(&ctx->fh, file); v4l2_fh_exit(&ctx->fh); mutex_unlock(&jpeg->lock); free: @@ -1011,13 +1010,13 @@ free: static int s5p_jpeg_release(struct file *file) { + struct s5p_jpeg_ctx *ctx = file_to_ctx(file); struct s5p_jpeg *jpeg = video_drvdata(file); - struct s5p_jpeg_ctx *ctx = fh_to_ctx(file->private_data); mutex_lock(&jpeg->lock); v4l2_m2m_ctx_release(ctx->fh.m2m_ctx); v4l2_ctrl_handler_free(&ctx->ctrl_handler); - v4l2_fh_del(&ctx->fh); + v4l2_fh_del(&ctx->fh, file); v4l2_fh_exit(&ctx->fh); kfree(ctx); mutex_unlock(&jpeg->lock); @@ -1249,7 +1248,7 @@ static bool s5p_jpeg_parse_hdr(struct s5p_jpeg_q_data *result, static int s5p_jpeg_querycap(struct file *file, void *priv, struct v4l2_capability *cap) { - struct s5p_jpeg_ctx *ctx = fh_to_ctx(priv); + struct s5p_jpeg_ctx *ctx = file_to_ctx(file); if (ctx->mode == S5P_JPEG_ENCODE) { strscpy(cap->driver, S5P_JPEG_M2M_NAME, @@ -1297,7 +1296,7 @@ static int enum_fmt(struct s5p_jpeg_ctx *ctx, static int s5p_jpeg_enum_fmt_vid_cap(struct file *file, void *priv, struct v4l2_fmtdesc *f) { - struct s5p_jpeg_ctx *ctx = fh_to_ctx(priv); + struct s5p_jpeg_ctx *ctx = file_to_ctx(file); if (ctx->mode == S5P_JPEG_ENCODE) return enum_fmt(ctx, sjpeg_formats, SJPEG_NUM_FORMATS, f, @@ -1310,7 +1309,7 @@ static int s5p_jpeg_enum_fmt_vid_cap(struct file *file, void *priv, static int s5p_jpeg_enum_fmt_vid_out(struct file *file, void *priv, struct v4l2_fmtdesc *f) { - struct s5p_jpeg_ctx *ctx = fh_to_ctx(priv); + struct s5p_jpeg_ctx *ctx = file_to_ctx(file); if (ctx->mode == S5P_JPEG_ENCODE) return enum_fmt(ctx, sjpeg_formats, SJPEG_NUM_FORMATS, f, @@ -1336,7 +1335,7 @@ static int s5p_jpeg_g_fmt(struct file *file, void *priv, struct v4l2_format *f) struct vb2_queue *vq; struct s5p_jpeg_q_data *q_data = NULL; struct v4l2_pix_format *pix = &f->fmt.pix; - struct s5p_jpeg_ctx *ct = fh_to_ctx(priv); + struct s5p_jpeg_ctx *ct = file_to_ctx(file); vq = v4l2_m2m_get_vq(ct->fh.m2m_ctx, f->type); if (!vq) @@ -1476,7 +1475,7 @@ static int vidioc_try_fmt(struct v4l2_format *f, struct s5p_jpeg_fmt *fmt, static int s5p_jpeg_try_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *f) { - struct s5p_jpeg_ctx *ctx = fh_to_ctx(priv); + struct s5p_jpeg_ctx *ctx = file_to_ctx(file); struct v4l2_pix_format *pix = &f->fmt.pix; struct s5p_jpeg_fmt *fmt; int ret; @@ -1535,7 +1534,7 @@ exit: static int s5p_jpeg_try_fmt_vid_out(struct file *file, void *priv, struct v4l2_format *f) { - struct s5p_jpeg_ctx *ctx = fh_to_ctx(priv); + struct s5p_jpeg_ctx *ctx = file_to_ctx(file); struct s5p_jpeg_fmt *fmt; fmt = s5p_jpeg_find_format(ctx, f->fmt.pix.pixelformat, @@ -1682,7 +1681,7 @@ static int s5p_jpeg_s_fmt_vid_cap(struct file *file, void *priv, if (ret) return ret; - return s5p_jpeg_s_fmt(fh_to_ctx(priv), f); + return s5p_jpeg_s_fmt(file_to_ctx(file), f); } static int s5p_jpeg_s_fmt_vid_out(struct file *file, void *priv, @@ -1694,7 +1693,7 @@ static int s5p_jpeg_s_fmt_vid_out(struct file *file, void *priv, if (ret) return ret; - return s5p_jpeg_s_fmt(fh_to_ctx(priv), f); + return s5p_jpeg_s_fmt(file_to_ctx(file), f); } static int s5p_jpeg_subscribe_event(struct v4l2_fh *fh, @@ -1791,7 +1790,7 @@ static int exynos3250_jpeg_try_crop(struct s5p_jpeg_ctx *ctx, static int s5p_jpeg_g_selection(struct file *file, void *priv, struct v4l2_selection *s) { - struct s5p_jpeg_ctx *ctx = fh_to_ctx(priv); + struct s5p_jpeg_ctx *ctx = file_to_ctx(file); if (s->type != V4L2_BUF_TYPE_VIDEO_OUTPUT && s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) @@ -1828,7 +1827,7 @@ static int s5p_jpeg_g_selection(struct file *file, void *priv, static int s5p_jpeg_s_selection(struct file *file, void *fh, struct v4l2_selection *s) { - struct s5p_jpeg_ctx *ctx = fh_to_ctx(file->private_data); + struct s5p_jpeg_ctx *ctx = file_to_ctx(file); struct v4l2_rect *rect = &s->r; int ret = -EINVAL; diff --git a/drivers/media/platform/samsung/s5p-mfc/s5p_mfc.c b/drivers/media/platform/samsung/s5p-mfc/s5p_mfc.c index 73fdcd362265..4948d734eb02 100644 --- a/drivers/media/platform/samsung/s5p-mfc/s5p_mfc.c +++ b/drivers/media/platform/samsung/s5p-mfc/s5p_mfc.c @@ -801,8 +801,7 @@ static int s5p_mfc_open(struct file *file) } init_waitqueue_head(&ctx->queue); v4l2_fh_init(&ctx->fh, vdev); - file->private_data = &ctx->fh; - v4l2_fh_add(&ctx->fh); + v4l2_fh_add(&ctx->fh, file); ctx->dev = dev; INIT_LIST_HEAD(&ctx->src_queue); INIT_LIST_HEAD(&ctx->dst_queue); @@ -877,7 +876,7 @@ static int s5p_mfc_open(struct file *file) /* Init videobuf2 queue for CAPTURE */ q = &ctx->vq_dst; q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; - q->drv_priv = &ctx->fh; + q->drv_priv = ctx; q->lock = &dev->mfc_mutex; if (vdev == dev->vfd_dec) { q->io_modes = VB2_MMAP; @@ -904,7 +903,7 @@ static int s5p_mfc_open(struct file *file) /* Init videobuf2 queue for OUTPUT */ q = &ctx->vq_src; q->type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; - q->drv_priv = &ctx->fh; + q->drv_priv = ctx; q->lock = &dev->mfc_mutex; if (vdev == dev->vfd_dec) { q->io_modes = VB2_MMAP; @@ -956,7 +955,7 @@ err_ctrls_setup: err_bad_node: dev->ctx[ctx->num] = NULL; err_no_ctx: - v4l2_fh_del(&ctx->fh); + v4l2_fh_del(&ctx->fh, file); v4l2_fh_exit(&ctx->fh); kfree(ctx); err_alloc: @@ -970,7 +969,7 @@ err_enter: /* Release MFC context */ static int s5p_mfc_release(struct file *file) { - struct s5p_mfc_ctx *ctx = fh_to_ctx(file->private_data); + struct s5p_mfc_ctx *ctx = file_to_ctx(file); struct s5p_mfc_dev *dev = ctx->dev; /* if dev is null, do cleanup that doesn't need dev */ @@ -1011,7 +1010,7 @@ static int s5p_mfc_release(struct file *file) if (dev) dev->ctx[ctx->num] = NULL; s5p_mfc_dec_ctrls_delete(ctx); - v4l2_fh_del(&ctx->fh); + v4l2_fh_del(&ctx->fh, file); /* vdev is gone if dev is null */ if (dev) v4l2_fh_exit(&ctx->fh); @@ -1027,7 +1026,7 @@ static int s5p_mfc_release(struct file *file) static __poll_t s5p_mfc_poll(struct file *file, struct poll_table_struct *wait) { - struct s5p_mfc_ctx *ctx = fh_to_ctx(file->private_data); + struct s5p_mfc_ctx *ctx = file_to_ctx(file); struct s5p_mfc_dev *dev = ctx->dev; struct vb2_queue *src_q, *dst_q; struct vb2_buffer *src_vb = NULL, *dst_vb = NULL; @@ -1078,7 +1077,7 @@ end: /* Mmap */ static int s5p_mfc_mmap(struct file *file, struct vm_area_struct *vma) { - struct s5p_mfc_ctx *ctx = fh_to_ctx(file->private_data); + struct s5p_mfc_ctx *ctx = file_to_ctx(file); unsigned long offset = vma->vm_pgoff << PAGE_SHIFT; int ret; diff --git a/drivers/media/platform/samsung/s5p-mfc/s5p_mfc_cmd_v6.c b/drivers/media/platform/samsung/s5p-mfc/s5p_mfc_cmd_v6.c index 47bc3014b5d8..f7c682fca645 100644 --- a/drivers/media/platform/samsung/s5p-mfc/s5p_mfc_cmd_v6.c +++ b/drivers/media/platform/samsung/s5p-mfc/s5p_mfc_cmd_v6.c @@ -14,8 +14,7 @@ #include "s5p_mfc_opr.h" #include "s5p_mfc_cmd_v6.h" -static int s5p_mfc_cmd_host2risc_v6(struct s5p_mfc_dev *dev, int cmd, - const struct s5p_mfc_cmd_args *args) +static int s5p_mfc_cmd_host2risc_v6(struct s5p_mfc_dev *dev, int cmd) { mfc_debug(2, "Issue the command: %d\n", cmd); @@ -31,7 +30,6 @@ static int s5p_mfc_cmd_host2risc_v6(struct s5p_mfc_dev *dev, int cmd, static int s5p_mfc_sys_init_cmd_v6(struct s5p_mfc_dev *dev) { - struct s5p_mfc_cmd_args h2r_args; const struct s5p_mfc_buf_size_v6 *buf_size = dev->variant->buf_size->priv; int ret; @@ -41,33 +39,23 @@ static int s5p_mfc_sys_init_cmd_v6(struct s5p_mfc_dev *dev) mfc_write(dev, dev->ctx_buf.dma, S5P_FIMV_CONTEXT_MEM_ADDR_V6); mfc_write(dev, buf_size->dev_ctx, S5P_FIMV_CONTEXT_MEM_SIZE_V6); - return s5p_mfc_cmd_host2risc_v6(dev, S5P_FIMV_H2R_CMD_SYS_INIT_V6, - &h2r_args); + return s5p_mfc_cmd_host2risc_v6(dev, S5P_FIMV_H2R_CMD_SYS_INIT_V6); } static int s5p_mfc_sleep_cmd_v6(struct s5p_mfc_dev *dev) { - struct s5p_mfc_cmd_args h2r_args; - - memset(&h2r_args, 0, sizeof(struct s5p_mfc_cmd_args)); - return s5p_mfc_cmd_host2risc_v6(dev, S5P_FIMV_H2R_CMD_SLEEP_V6, - &h2r_args); + return s5p_mfc_cmd_host2risc_v6(dev, S5P_FIMV_H2R_CMD_SLEEP_V6); } static int s5p_mfc_wakeup_cmd_v6(struct s5p_mfc_dev *dev) { - struct s5p_mfc_cmd_args h2r_args; - - memset(&h2r_args, 0, sizeof(struct s5p_mfc_cmd_args)); - return s5p_mfc_cmd_host2risc_v6(dev, S5P_FIMV_H2R_CMD_WAKEUP_V6, - &h2r_args); + return s5p_mfc_cmd_host2risc_v6(dev, S5P_FIMV_H2R_CMD_WAKEUP_V6); } /* Open a new instance and get its number */ static int s5p_mfc_open_inst_cmd_v6(struct s5p_mfc_ctx *ctx) { struct s5p_mfc_dev *dev = ctx->dev; - struct s5p_mfc_cmd_args h2r_args; int codec_type; mfc_debug(2, "Requested codec mode: %d\n", ctx->codec_mode); @@ -129,23 +117,20 @@ static int s5p_mfc_open_inst_cmd_v6(struct s5p_mfc_ctx *ctx) mfc_write(dev, ctx->ctx.size, S5P_FIMV_CONTEXT_MEM_SIZE_V6); mfc_write(dev, 0, S5P_FIMV_D_CRC_CTRL_V6); /* no crc */ - return s5p_mfc_cmd_host2risc_v6(dev, S5P_FIMV_H2R_CMD_OPEN_INSTANCE_V6, - &h2r_args); + return s5p_mfc_cmd_host2risc_v6(dev, S5P_FIMV_H2R_CMD_OPEN_INSTANCE_V6); } /* Close instance */ static int s5p_mfc_close_inst_cmd_v6(struct s5p_mfc_ctx *ctx) { struct s5p_mfc_dev *dev = ctx->dev; - struct s5p_mfc_cmd_args h2r_args; int ret = 0; dev->curr_ctx = ctx->num; if (ctx->state != MFCINST_FREE) { mfc_write(dev, ctx->inst_no, S5P_FIMV_INSTANCE_ID_V6); ret = s5p_mfc_cmd_host2risc_v6(dev, - S5P_FIMV_H2R_CMD_CLOSE_INSTANCE_V6, - &h2r_args); + S5P_FIMV_H2R_CMD_CLOSE_INSTANCE_V6); } else { ret = -EINVAL; } @@ -153,9 +138,15 @@ static int s5p_mfc_close_inst_cmd_v6(struct s5p_mfc_ctx *ctx) return ret; } +static int s5p_mfc_cmd_host2risc_v6_args(struct s5p_mfc_dev *dev, int cmd, + const struct s5p_mfc_cmd_args *ignored) +{ + return s5p_mfc_cmd_host2risc_v6(dev, cmd); +} + /* Initialize cmd function pointers for MFC v6 */ static const struct s5p_mfc_hw_cmds s5p_mfc_cmds_v6 = { - .cmd_host2risc = s5p_mfc_cmd_host2risc_v6, + .cmd_host2risc = s5p_mfc_cmd_host2risc_v6_args, .sys_init_cmd = s5p_mfc_sys_init_cmd_v6, .sleep_cmd = s5p_mfc_sleep_cmd_v6, .wakeup_cmd = s5p_mfc_wakeup_cmd_v6, diff --git a/drivers/media/platform/samsung/s5p-mfc/s5p_mfc_common.h b/drivers/media/platform/samsung/s5p-mfc/s5p_mfc_common.h index 86c316c1ff8f..58dc1768082c 100644 --- a/drivers/media/platform/samsung/s5p-mfc/s5p_mfc_common.h +++ b/drivers/media/platform/samsung/s5p-mfc/s5p_mfc_common.h @@ -767,7 +767,11 @@ struct mfc_control { #define s5p_mfc_hw_call(f, op, args...) \ ((f && f->op) ? f->op(args) : (typeof(f->op(args)))(-ENODEV)) -#define fh_to_ctx(__fh) container_of(__fh, struct s5p_mfc_ctx, fh) +static inline struct s5p_mfc_ctx *file_to_ctx(struct file *filp) +{ + return container_of(file_to_v4l2_fh(filp), struct s5p_mfc_ctx, fh); +} + #define ctrl_to_ctx(__ctrl) \ container_of((__ctrl)->handler, struct s5p_mfc_ctx, ctrl_handler) diff --git a/drivers/media/platform/samsung/s5p-mfc/s5p_mfc_dec.c b/drivers/media/platform/samsung/s5p-mfc/s5p_mfc_dec.c index 3efbc3367906..afd28beabfde 100644 --- a/drivers/media/platform/samsung/s5p-mfc/s5p_mfc_dec.c +++ b/drivers/media/platform/samsung/s5p-mfc/s5p_mfc_dec.c @@ -330,7 +330,7 @@ static int vidioc_enum_fmt(struct file *file, struct v4l2_fmtdesc *f, return 0; } -static int vidioc_enum_fmt_vid_cap(struct file *file, void *pirv, +static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv, struct v4l2_fmtdesc *f) { return vidioc_enum_fmt(file, f, false); @@ -345,7 +345,7 @@ static int vidioc_enum_fmt_vid_out(struct file *file, void *priv, /* Get format */ static int vidioc_g_fmt(struct file *file, void *priv, struct v4l2_format *f) { - struct s5p_mfc_ctx *ctx = fh_to_ctx(priv); + struct s5p_mfc_ctx *ctx = file_to_ctx(file); struct v4l2_pix_format_mplane *pix_mp; mfc_debug_enter(); @@ -442,7 +442,7 @@ static int vidioc_try_fmt(struct file *file, void *priv, struct v4l2_format *f) static int vidioc_s_fmt(struct file *file, void *priv, struct v4l2_format *f) { struct s5p_mfc_dev *dev = video_drvdata(file); - struct s5p_mfc_ctx *ctx = fh_to_ctx(priv); + struct s5p_mfc_ctx *ctx = file_to_ctx(file); int ret = 0; struct v4l2_pix_format_mplane *pix_mp; const struct s5p_mfc_buf_size *buf_size = dev->variant->buf_size; @@ -598,7 +598,7 @@ static int vidioc_reqbufs(struct file *file, void *priv, struct v4l2_requestbuffers *reqbufs) { struct s5p_mfc_dev *dev = video_drvdata(file); - struct s5p_mfc_ctx *ctx = fh_to_ctx(priv); + struct s5p_mfc_ctx *ctx = file_to_ctx(file); if (reqbufs->memory != V4L2_MEMORY_MMAP) { mfc_debug(2, "Only V4L2_MEMORY_MMAP is supported\n"); @@ -619,7 +619,7 @@ static int vidioc_reqbufs(struct file *file, void *priv, static int vidioc_querybuf(struct file *file, void *priv, struct v4l2_buffer *buf) { - struct s5p_mfc_ctx *ctx = fh_to_ctx(priv); + struct s5p_mfc_ctx *ctx = file_to_ctx(file); int ret; int i; @@ -647,7 +647,7 @@ static int vidioc_querybuf(struct file *file, void *priv, /* Queue a buffer */ static int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *buf) { - struct s5p_mfc_ctx *ctx = fh_to_ctx(priv); + struct s5p_mfc_ctx *ctx = file_to_ctx(file); if (ctx->state == MFCINST_ERROR) { mfc_err("Call on QBUF after unrecoverable error\n"); @@ -666,7 +666,7 @@ static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *buf) const struct v4l2_event ev = { .type = V4L2_EVENT_EOS }; - struct s5p_mfc_ctx *ctx = fh_to_ctx(priv); + struct s5p_mfc_ctx *ctx = file_to_ctx(file); int ret; if (ctx->state == MFCINST_ERROR) { @@ -695,7 +695,7 @@ static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *buf) static int vidioc_expbuf(struct file *file, void *priv, struct v4l2_exportbuffer *eb) { - struct s5p_mfc_ctx *ctx = fh_to_ctx(priv); + struct s5p_mfc_ctx *ctx = file_to_ctx(file); if (eb->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) return vb2_expbuf(&ctx->vq_src, eb); @@ -708,7 +708,7 @@ static int vidioc_expbuf(struct file *file, void *priv, static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type type) { - struct s5p_mfc_ctx *ctx = fh_to_ctx(priv); + struct s5p_mfc_ctx *ctx = file_to_ctx(file); int ret = -EINVAL; mfc_debug_enter(); @@ -724,7 +724,7 @@ static int vidioc_streamon(struct file *file, void *priv, static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type type) { - struct s5p_mfc_ctx *ctx = fh_to_ctx(priv); + struct s5p_mfc_ctx *ctx = file_to_ctx(file); if (type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) return vb2_streamoff(&ctx->vq_src, type); @@ -801,7 +801,7 @@ static const struct v4l2_ctrl_ops s5p_mfc_dec_ctrl_ops = { static int vidioc_g_selection(struct file *file, void *priv, struct v4l2_selection *s) { - struct s5p_mfc_ctx *ctx = fh_to_ctx(priv); + struct s5p_mfc_ctx *ctx = file_to_ctx(file); struct s5p_mfc_dev *dev = ctx->dev; u32 left, right, top, bottom; u32 width, height; @@ -856,7 +856,7 @@ static int vidioc_g_selection(struct file *file, void *priv, static int vidioc_decoder_cmd(struct file *file, void *priv, struct v4l2_decoder_cmd *cmd) { - struct s5p_mfc_ctx *ctx = fh_to_ctx(priv); + struct s5p_mfc_ctx *ctx = file_to_ctx(file); struct s5p_mfc_dev *dev = ctx->dev; struct s5p_mfc_buf *buf; unsigned long flags; @@ -937,7 +937,7 @@ static int s5p_mfc_queue_setup(struct vb2_queue *vq, unsigned int *plane_count, unsigned int psize[], struct device *alloc_devs[]) { - struct s5p_mfc_ctx *ctx = fh_to_ctx(vq->drv_priv); + struct s5p_mfc_ctx *ctx = vb2_get_drv_priv(vq); struct s5p_mfc_dev *dev = ctx->dev; const struct v4l2_format_info *format; @@ -1006,7 +1006,7 @@ static int s5p_mfc_buf_init(struct vb2_buffer *vb) { struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); struct vb2_queue *vq = vb->vb2_queue; - struct s5p_mfc_ctx *ctx = fh_to_ctx(vq->drv_priv); + struct s5p_mfc_ctx *ctx = vb2_get_drv_priv(vq); unsigned int i; if (vq->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) { @@ -1068,7 +1068,7 @@ static int s5p_mfc_buf_init(struct vb2_buffer *vb) static int s5p_mfc_start_streaming(struct vb2_queue *q, unsigned int count) { - struct s5p_mfc_ctx *ctx = fh_to_ctx(q->drv_priv); + struct s5p_mfc_ctx *ctx = vb2_get_drv_priv(q); struct s5p_mfc_dev *dev = ctx->dev; v4l2_ctrl_handler_setup(&ctx->ctrl_handler); @@ -1085,7 +1085,7 @@ static int s5p_mfc_start_streaming(struct vb2_queue *q, unsigned int count) static void s5p_mfc_stop_streaming(struct vb2_queue *q) { unsigned long flags; - struct s5p_mfc_ctx *ctx = fh_to_ctx(q->drv_priv); + struct s5p_mfc_ctx *ctx = vb2_get_drv_priv(q); struct s5p_mfc_dev *dev = ctx->dev; int aborted = 0; @@ -1130,7 +1130,7 @@ static void s5p_mfc_stop_streaming(struct vb2_queue *q) static void s5p_mfc_buf_queue(struct vb2_buffer *vb) { struct vb2_queue *vq = vb->vb2_queue; - struct s5p_mfc_ctx *ctx = fh_to_ctx(vq->drv_priv); + struct s5p_mfc_ctx *ctx = vb2_get_drv_priv(vq); struct s5p_mfc_dev *dev = ctx->dev; unsigned long flags; struct s5p_mfc_buf *mfc_buf; diff --git a/drivers/media/platform/samsung/s5p-mfc/s5p_mfc_enc.c b/drivers/media/platform/samsung/s5p-mfc/s5p_mfc_enc.c index 6c603dcd5664..3f8701e5614f 100644 --- a/drivers/media/platform/samsung/s5p-mfc/s5p_mfc_enc.c +++ b/drivers/media/platform/samsung/s5p-mfc/s5p_mfc_enc.c @@ -1375,7 +1375,7 @@ static int vidioc_enum_fmt(struct file *file, struct v4l2_fmtdesc *f, return -EINVAL; } -static int vidioc_enum_fmt_vid_cap(struct file *file, void *pirv, +static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv, struct v4l2_fmtdesc *f) { return vidioc_enum_fmt(file, f, false); @@ -1389,8 +1389,8 @@ static int vidioc_enum_fmt_vid_out(struct file *file, void *priv, static int vidioc_g_fmt(struct file *file, void *priv, struct v4l2_format *f) { - struct s5p_mfc_ctx *ctx = fh_to_ctx(priv); struct v4l2_pix_format_mplane *pix_fmt_mp = &f->fmt.pix_mp; + struct s5p_mfc_ctx *ctx = file_to_ctx(file); mfc_debug(2, "f->type = %d ctx->state = %d\n", f->type, ctx->state); if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) { @@ -1472,8 +1472,8 @@ static int vidioc_try_fmt(struct file *file, void *priv, struct v4l2_format *f) static int vidioc_s_fmt(struct file *file, void *priv, struct v4l2_format *f) { + struct s5p_mfc_ctx *ctx = file_to_ctx(file); struct s5p_mfc_dev *dev = video_drvdata(file); - struct s5p_mfc_ctx *ctx = fh_to_ctx(priv); struct v4l2_pix_format_mplane *pix_fmt_mp = &f->fmt.pix_mp; int ret = 0; @@ -1531,7 +1531,7 @@ static int vidioc_reqbufs(struct file *file, void *priv, struct v4l2_requestbuffers *reqbufs) { struct s5p_mfc_dev *dev = video_drvdata(file); - struct s5p_mfc_ctx *ctx = fh_to_ctx(priv); + struct s5p_mfc_ctx *ctx = file_to_ctx(file); int ret = 0; /* if memory is not mmp or userptr or dmabuf return error */ @@ -1601,7 +1601,7 @@ static int vidioc_reqbufs(struct file *file, void *priv, static int vidioc_querybuf(struct file *file, void *priv, struct v4l2_buffer *buf) { - struct s5p_mfc_ctx *ctx = fh_to_ctx(priv); + struct s5p_mfc_ctx *ctx = file_to_ctx(file); int ret = 0; /* if memory is not mmp or userptr or dmabuf return error */ @@ -1636,7 +1636,7 @@ static int vidioc_querybuf(struct file *file, void *priv, /* Queue a buffer */ static int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *buf) { - struct s5p_mfc_ctx *ctx = fh_to_ctx(priv); + struct s5p_mfc_ctx *ctx = file_to_ctx(file); if (ctx->state == MFCINST_ERROR) { mfc_err("Call on QBUF after unrecoverable error\n"); @@ -1657,10 +1657,10 @@ static int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *buf) /* Dequeue a buffer */ static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *buf) { + struct s5p_mfc_ctx *ctx = file_to_ctx(file); const struct v4l2_event ev = { .type = V4L2_EVENT_EOS }; - struct s5p_mfc_ctx *ctx = fh_to_ctx(priv); int ret; if (ctx->state == MFCINST_ERROR) { @@ -1685,7 +1685,7 @@ static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *buf) static int vidioc_expbuf(struct file *file, void *priv, struct v4l2_exportbuffer *eb) { - struct s5p_mfc_ctx *ctx = fh_to_ctx(priv); + struct s5p_mfc_ctx *ctx = file_to_ctx(file); if (eb->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) return vb2_expbuf(&ctx->vq_src, eb); @@ -1698,7 +1698,7 @@ static int vidioc_expbuf(struct file *file, void *priv, static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type type) { - struct s5p_mfc_ctx *ctx = fh_to_ctx(priv); + struct s5p_mfc_ctx *ctx = file_to_ctx(file); if (type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) return vb2_streamon(&ctx->vq_src, type); @@ -1711,7 +1711,7 @@ static int vidioc_streamon(struct file *file, void *priv, static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type type) { - struct s5p_mfc_ctx *ctx = fh_to_ctx(priv); + struct s5p_mfc_ctx *ctx = file_to_ctx(file); if (type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) return vb2_streamoff(&ctx->vq_src, type); @@ -2284,7 +2284,7 @@ static const struct v4l2_ctrl_ops s5p_mfc_enc_ctrl_ops = { static int vidioc_s_parm(struct file *file, void *priv, struct v4l2_streamparm *a) { - struct s5p_mfc_ctx *ctx = fh_to_ctx(priv); + struct s5p_mfc_ctx *ctx = file_to_ctx(file); if (a->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { ctx->enc_params.rc_framerate_num = @@ -2301,7 +2301,7 @@ static int vidioc_s_parm(struct file *file, void *priv, static int vidioc_g_parm(struct file *file, void *priv, struct v4l2_streamparm *a) { - struct s5p_mfc_ctx *ctx = fh_to_ctx(priv); + struct s5p_mfc_ctx *ctx = file_to_ctx(file); if (a->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) { a->parm.output.timeperframe.denominator = @@ -2318,7 +2318,7 @@ static int vidioc_g_parm(struct file *file, void *priv, static int vidioc_encoder_cmd(struct file *file, void *priv, struct v4l2_encoder_cmd *cmd) { - struct s5p_mfc_ctx *ctx = fh_to_ctx(priv); + struct s5p_mfc_ctx *ctx = file_to_ctx(file); struct s5p_mfc_dev *dev = ctx->dev; struct s5p_mfc_buf *buf; unsigned long flags; @@ -2418,7 +2418,7 @@ static int s5p_mfc_queue_setup(struct vb2_queue *vq, unsigned int *buf_count, unsigned int *plane_count, unsigned int psize[], struct device *alloc_devs[]) { - struct s5p_mfc_ctx *ctx = fh_to_ctx(vq->drv_priv); + struct s5p_mfc_ctx *ctx = vb2_get_drv_priv(vq); struct s5p_mfc_dev *dev = ctx->dev; if (vq->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) { @@ -2477,7 +2477,7 @@ static int s5p_mfc_buf_init(struct vb2_buffer *vb) { struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); struct vb2_queue *vq = vb->vb2_queue; - struct s5p_mfc_ctx *ctx = fh_to_ctx(vq->drv_priv); + struct s5p_mfc_ctx *ctx = vb2_get_drv_priv(vq); unsigned int i; int ret; @@ -2516,7 +2516,7 @@ static int s5p_mfc_buf_init(struct vb2_buffer *vb) static int s5p_mfc_buf_prepare(struct vb2_buffer *vb) { struct vb2_queue *vq = vb->vb2_queue; - struct s5p_mfc_ctx *ctx = fh_to_ctx(vq->drv_priv); + struct s5p_mfc_ctx *ctx = vb2_get_drv_priv(vq); int ret; if (vq->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) { @@ -2557,7 +2557,7 @@ static int s5p_mfc_buf_prepare(struct vb2_buffer *vb) static int s5p_mfc_start_streaming(struct vb2_queue *q, unsigned int count) { - struct s5p_mfc_ctx *ctx = fh_to_ctx(q->drv_priv); + struct s5p_mfc_ctx *ctx = vb2_get_drv_priv(q); struct s5p_mfc_dev *dev = ctx->dev; if (IS_MFCV6_PLUS(dev) && @@ -2588,7 +2588,7 @@ static int s5p_mfc_start_streaming(struct vb2_queue *q, unsigned int count) static void s5p_mfc_stop_streaming(struct vb2_queue *q) { unsigned long flags; - struct s5p_mfc_ctx *ctx = fh_to_ctx(q->drv_priv); + struct s5p_mfc_ctx *ctx = vb2_get_drv_priv(q); struct s5p_mfc_dev *dev = ctx->dev; if ((ctx->state == MFCINST_FINISHING || @@ -2617,7 +2617,7 @@ static void s5p_mfc_stop_streaming(struct vb2_queue *q) static void s5p_mfc_buf_queue(struct vb2_buffer *vb) { struct vb2_queue *vq = vb->vb2_queue; - struct s5p_mfc_ctx *ctx = fh_to_ctx(vq->drv_priv); + struct s5p_mfc_ctx *ctx = vb2_get_drv_priv(vq); struct s5p_mfc_dev *dev = ctx->dev; unsigned long flags; struct s5p_mfc_buf *mfc_buf; diff --git a/drivers/media/platform/st/sti/bdisp/bdisp-v4l2.c b/drivers/media/platform/st/sti/bdisp/bdisp-v4l2.c index 1eb934490c0b..56169b70652d 100644 --- a/drivers/media/platform/st/sti/bdisp/bdisp-v4l2.c +++ b/drivers/media/platform/st/sti/bdisp/bdisp-v4l2.c @@ -33,7 +33,10 @@ #define BDISP_MIN_H 1 #define BDISP_MAX_H 8191 -#define fh_to_ctx(__fh) container_of(__fh, struct bdisp_ctx, fh) +static inline struct bdisp_ctx *file_to_ctx(struct file *filp) +{ + return container_of(file_to_v4l2_fh(filp), struct bdisp_ctx, fh); +} enum bdisp_dev_flags { ST_M2M_OPEN, /* Driver opened */ @@ -603,8 +606,7 @@ static int bdisp_open(struct file *file) /* Use separate control handler per file handle */ ctx->fh.ctrl_handler = &ctx->ctrl_handler; - file->private_data = &ctx->fh; - v4l2_fh_add(&ctx->fh); + v4l2_fh_add(&ctx->fh, file); /* Default format */ ctx->src = bdisp_dflt_fmt; @@ -630,7 +632,7 @@ static int bdisp_open(struct file *file) error_ctrls: bdisp_ctrls_delete(ctx); - v4l2_fh_del(&ctx->fh); + v4l2_fh_del(&ctx->fh, file); error_fh: v4l2_fh_exit(&ctx->fh); bdisp_hw_free_nodes(ctx); @@ -644,7 +646,7 @@ unlock: static int bdisp_release(struct file *file) { - struct bdisp_ctx *ctx = fh_to_ctx(file->private_data); + struct bdisp_ctx *ctx = file_to_ctx(file); struct bdisp_dev *bdisp = ctx->bdisp_dev; dev_dbg(bdisp->dev, "%s\n", __func__); @@ -655,7 +657,7 @@ static int bdisp_release(struct file *file) bdisp_ctrls_delete(ctx); - v4l2_fh_del(&ctx->fh); + v4l2_fh_del(&ctx->fh, file); v4l2_fh_exit(&ctx->fh); if (--bdisp->m2m.refcnt <= 0) @@ -682,7 +684,7 @@ static const struct v4l2_file_operations bdisp_fops = { static int bdisp_querycap(struct file *file, void *fh, struct v4l2_capability *cap) { - struct bdisp_ctx *ctx = fh_to_ctx(fh); + struct bdisp_ctx *ctx = file_to_ctx(file); struct bdisp_dev *bdisp = ctx->bdisp_dev; strscpy(cap->driver, bdisp->pdev->name, sizeof(cap->driver)); @@ -694,7 +696,7 @@ static int bdisp_querycap(struct file *file, void *fh, static int bdisp_enum_fmt(struct file *file, void *fh, struct v4l2_fmtdesc *f) { - struct bdisp_ctx *ctx = fh_to_ctx(fh); + struct bdisp_ctx *ctx = file_to_ctx(file); const struct bdisp_fmt *fmt; if (f->index >= ARRAY_SIZE(bdisp_formats)) @@ -714,7 +716,7 @@ static int bdisp_enum_fmt(struct file *file, void *fh, struct v4l2_fmtdesc *f) static int bdisp_g_fmt(struct file *file, void *fh, struct v4l2_format *f) { - struct bdisp_ctx *ctx = fh_to_ctx(fh); + struct bdisp_ctx *ctx = file_to_ctx(file); struct v4l2_pix_format *pix; struct bdisp_frame *frame = ctx_get_frame(ctx, f->type); @@ -738,7 +740,7 @@ static int bdisp_g_fmt(struct file *file, void *fh, struct v4l2_format *f) static int bdisp_try_fmt(struct file *file, void *fh, struct v4l2_format *f) { - struct bdisp_ctx *ctx = fh_to_ctx(fh); + struct bdisp_ctx *ctx = file_to_ctx(file); struct v4l2_pix_format *pix = &f->fmt.pix; const struct bdisp_fmt *format; u32 in_w, in_h; @@ -788,7 +790,7 @@ static int bdisp_try_fmt(struct file *file, void *fh, struct v4l2_format *f) static int bdisp_s_fmt(struct file *file, void *fh, struct v4l2_format *f) { - struct bdisp_ctx *ctx = fh_to_ctx(fh); + struct bdisp_ctx *ctx = file_to_ctx(file); struct vb2_queue *vq; struct bdisp_frame *frame; struct v4l2_pix_format *pix; @@ -841,8 +843,8 @@ static int bdisp_s_fmt(struct file *file, void *fh, struct v4l2_format *f) static int bdisp_g_selection(struct file *file, void *fh, struct v4l2_selection *s) { + struct bdisp_ctx *ctx = file_to_ctx(file); struct bdisp_frame *frame; - struct bdisp_ctx *ctx = fh_to_ctx(fh); frame = ctx_get_frame(ctx, s->type); if (IS_ERR(frame)) { @@ -919,8 +921,8 @@ static int is_rect_enclosed(struct v4l2_rect *a, struct v4l2_rect *b) static int bdisp_s_selection(struct file *file, void *fh, struct v4l2_selection *s) { + struct bdisp_ctx *ctx = file_to_ctx(file); struct bdisp_frame *frame; - struct bdisp_ctx *ctx = fh_to_ctx(fh); struct v4l2_rect *in, out; bool valid = false; @@ -997,7 +999,7 @@ static int bdisp_s_selection(struct file *file, void *fh, static int bdisp_streamon(struct file *file, void *fh, enum v4l2_buf_type type) { - struct bdisp_ctx *ctx = fh_to_ctx(fh); + struct bdisp_ctx *ctx = file_to_ctx(file); if ((type == V4L2_BUF_TYPE_VIDEO_OUTPUT) && !bdisp_ctx_state_is_set(BDISP_SRC_FMT, ctx)) { diff --git a/drivers/media/platform/st/sti/delta/delta-mjpeg-dec.c b/drivers/media/platform/st/sti/delta/delta-mjpeg-dec.c index 0533d4a083d2..a078f1107300 100644 --- a/drivers/media/platform/st/sti/delta/delta-mjpeg-dec.c +++ b/drivers/media/platform/st/sti/delta/delta-mjpeg-dec.c @@ -239,7 +239,7 @@ static int delta_mjpeg_ipc_open(struct delta_ctx *pctx) return 0; } -static int delta_mjpeg_ipc_decode(struct delta_ctx *pctx, struct delta_au *au) +static int delta_mjpeg_ipc_decode(struct delta_ctx *pctx, dma_addr_t pstart, dma_addr_t pend) { struct delta_dev *delta = pctx->dev; struct delta_mjpeg_ctx *ctx = to_ctx(pctx); @@ -256,8 +256,8 @@ static int delta_mjpeg_ipc_decode(struct delta_ctx *pctx, struct delta_au *au) memset(params, 0, sizeof(*params)); - params->picture_start_addr_p = (u32)(au->paddr); - params->picture_end_addr_p = (u32)(au->paddr + au->size - 1); + params->picture_start_addr_p = pstart; + params->picture_end_addr_p = pend; /* * !WARNING! @@ -374,12 +374,14 @@ static int delta_mjpeg_decode(struct delta_ctx *pctx, struct delta_au *pau) struct delta_dev *delta = pctx->dev; struct delta_mjpeg_ctx *ctx = to_ctx(pctx); int ret; - struct delta_au au = *pau; + void *au_vaddr = pau->vaddr; + dma_addr_t au_dma = pau->paddr; + size_t au_size = pau->size; unsigned int data_offset = 0; struct mjpeg_header *header = &ctx->header_struct; if (!ctx->header) { - ret = delta_mjpeg_read_header(pctx, au.vaddr, au.size, + ret = delta_mjpeg_read_header(pctx, au_vaddr, au_size, header, &data_offset); if (ret) { pctx->stream_errors++; @@ -405,17 +407,17 @@ static int delta_mjpeg_decode(struct delta_ctx *pctx, struct delta_au *pau) goto err; } - ret = delta_mjpeg_read_header(pctx, au.vaddr, au.size, + ret = delta_mjpeg_read_header(pctx, au_vaddr, au_size, ctx->header, &data_offset); if (ret) { pctx->stream_errors++; goto err; } - au.paddr += data_offset; - au.vaddr += data_offset; + au_dma += data_offset; + au_vaddr += data_offset; - ret = delta_mjpeg_ipc_decode(pctx, &au); + ret = delta_mjpeg_ipc_decode(pctx, au_dma, au_dma + au_size - 1); if (ret) goto err; diff --git a/drivers/media/platform/st/sti/delta/delta-v4l2.c b/drivers/media/platform/st/sti/delta/delta-v4l2.c index 196e6a40335d..6c1a53c771f7 100644 --- a/drivers/media/platform/st/sti/delta/delta-v4l2.c +++ b/drivers/media/platform/st/sti/delta/delta-v4l2.c @@ -24,7 +24,11 @@ #define DELTA_PREFIX "[---:----]" -#define to_ctx(__fh) container_of(__fh, struct delta_ctx, fh) +static inline struct delta_ctx *file_to_ctx(struct file *filp) +{ + return container_of(file_to_v4l2_fh(filp), struct delta_ctx, fh); +} + #define to_au(__vbuf) container_of(__vbuf, struct delta_au, vbuf) #define to_frame(__vbuf) container_of(__vbuf, struct delta_frame, vbuf) @@ -382,7 +386,7 @@ static int delta_open_decoder(struct delta_ctx *ctx, u32 streamformat, static int delta_querycap(struct file *file, void *priv, struct v4l2_capability *cap) { - struct delta_ctx *ctx = to_ctx(file->private_data); + struct delta_ctx *ctx = file_to_ctx(file); struct delta_dev *delta = ctx->dev; strscpy(cap->driver, DELTA_NAME, sizeof(cap->driver)); @@ -396,7 +400,7 @@ static int delta_querycap(struct file *file, void *priv, static int delta_enum_fmt_stream(struct file *file, void *priv, struct v4l2_fmtdesc *f) { - struct delta_ctx *ctx = to_ctx(file->private_data); + struct delta_ctx *ctx = file_to_ctx(file); struct delta_dev *delta = ctx->dev; if (unlikely(f->index >= delta->nb_of_streamformats)) @@ -410,7 +414,7 @@ static int delta_enum_fmt_stream(struct file *file, void *priv, static int delta_enum_fmt_frame(struct file *file, void *priv, struct v4l2_fmtdesc *f) { - struct delta_ctx *ctx = to_ctx(file->private_data); + struct delta_ctx *ctx = file_to_ctx(file); struct delta_dev *delta = ctx->dev; if (unlikely(f->index >= delta->nb_of_pixelformats)) @@ -424,7 +428,7 @@ static int delta_enum_fmt_frame(struct file *file, void *priv, static int delta_g_fmt_stream(struct file *file, void *fh, struct v4l2_format *f) { - struct delta_ctx *ctx = to_ctx(file->private_data); + struct delta_ctx *ctx = file_to_ctx(file); struct delta_dev *delta = ctx->dev; struct v4l2_pix_format *pix = &f->fmt.pix; struct delta_streaminfo *streaminfo = &ctx->streaminfo; @@ -452,7 +456,7 @@ static int delta_g_fmt_stream(struct file *file, void *fh, static int delta_g_fmt_frame(struct file *file, void *fh, struct v4l2_format *f) { - struct delta_ctx *ctx = to_ctx(file->private_data); + struct delta_ctx *ctx = file_to_ctx(file); struct delta_dev *delta = ctx->dev; struct v4l2_pix_format *pix = &f->fmt.pix; struct delta_frameinfo *frameinfo = &ctx->frameinfo; @@ -491,7 +495,7 @@ static int delta_g_fmt_frame(struct file *file, void *fh, struct v4l2_format *f) static int delta_try_fmt_stream(struct file *file, void *priv, struct v4l2_format *f) { - struct delta_ctx *ctx = to_ctx(file->private_data); + struct delta_ctx *ctx = file_to_ctx(file); struct delta_dev *delta = ctx->dev; struct v4l2_pix_format *pix = &f->fmt.pix; u32 streamformat = pix->pixelformat; @@ -545,7 +549,7 @@ static int delta_try_fmt_stream(struct file *file, void *priv, static int delta_try_fmt_frame(struct file *file, void *priv, struct v4l2_format *f) { - struct delta_ctx *ctx = to_ctx(file->private_data); + struct delta_ctx *ctx = file_to_ctx(file); struct delta_dev *delta = ctx->dev; struct v4l2_pix_format *pix = &f->fmt.pix; u32 pixelformat = pix->pixelformat; @@ -605,7 +609,7 @@ static int delta_try_fmt_frame(struct file *file, void *priv, static int delta_s_fmt_stream(struct file *file, void *fh, struct v4l2_format *f) { - struct delta_ctx *ctx = to_ctx(file->private_data); + struct delta_ctx *ctx = file_to_ctx(file); struct delta_dev *delta = ctx->dev; struct vb2_queue *vq; struct v4l2_pix_format *pix = &f->fmt.pix; @@ -641,7 +645,7 @@ static int delta_s_fmt_stream(struct file *file, void *fh, static int delta_s_fmt_frame(struct file *file, void *fh, struct v4l2_format *f) { - struct delta_ctx *ctx = to_ctx(file->private_data); + struct delta_ctx *ctx = file_to_ctx(file); struct delta_dev *delta = ctx->dev; const struct delta_dec *dec = ctx->dec; struct v4l2_pix_format *pix = &f->fmt.pix; @@ -721,7 +725,7 @@ static int delta_s_fmt_frame(struct file *file, void *fh, struct v4l2_format *f) static int delta_g_selection(struct file *file, void *fh, struct v4l2_selection *s) { - struct delta_ctx *ctx = to_ctx(fh); + struct delta_ctx *ctx = file_to_ctx(file); struct delta_frameinfo *frameinfo = &ctx->frameinfo; struct v4l2_rect crop; @@ -803,7 +807,7 @@ static int delta_try_decoder_cmd(struct file *file, void *fh, return 0; } -static int delta_decoder_stop_cmd(struct delta_ctx *ctx, void *fh) +static int delta_decoder_stop_cmd(struct delta_ctx *ctx) { const struct delta_dec *dec = ctx->dec; struct delta_dev *delta = ctx->dev; @@ -866,14 +870,14 @@ delay_eos: static int delta_decoder_cmd(struct file *file, void *fh, struct v4l2_decoder_cmd *cmd) { - struct delta_ctx *ctx = to_ctx(fh); + struct delta_ctx *ctx = file_to_ctx(file); int ret = 0; ret = delta_try_decoder_cmd(file, fh, cmd); if (ret) return ret; - return delta_decoder_stop_cmd(ctx, fh); + return delta_decoder_stop_cmd(ctx); } static int delta_subscribe_event(struct v4l2_fh *fh, @@ -1633,8 +1637,7 @@ static int delta_open(struct file *file) ctx->dev = delta; v4l2_fh_init(&ctx->fh, video_devdata(file)); - file->private_data = &ctx->fh; - v4l2_fh_add(&ctx->fh); + v4l2_fh_add(&ctx->fh, file); INIT_WORK(&ctx->run_work, delta_run_work); mutex_init(&ctx->lock); @@ -1679,7 +1682,7 @@ static int delta_open(struct file *file) return 0; err_fh_del: - v4l2_fh_del(&ctx->fh); + v4l2_fh_del(&ctx->fh, file); v4l2_fh_exit(&ctx->fh); kfree(ctx); err: @@ -1690,7 +1693,7 @@ err: static int delta_release(struct file *file) { - struct delta_ctx *ctx = to_ctx(file->private_data); + struct delta_ctx *ctx = file_to_ctx(file); struct delta_dev *delta = ctx->dev; const struct delta_dec *dec = ctx->dec; @@ -1707,7 +1710,7 @@ static int delta_release(struct file *file) v4l2_m2m_ctx_release(ctx->fh.m2m_ctx); - v4l2_fh_del(&ctx->fh); + v4l2_fh_del(&ctx->fh, file); v4l2_fh_exit(&ctx->fh); /* disable ST231 clocks */ diff --git a/drivers/media/platform/st/sti/hva/hva-v4l2.c b/drivers/media/platform/st/sti/hva/hva-v4l2.c index 5366c0f92549..3581b73a99b8 100644 --- a/drivers/media/platform/st/sti/hva/hva-v4l2.c +++ b/drivers/media/platform/st/sti/hva/hva-v4l2.c @@ -36,7 +36,10 @@ #define to_type_str(type) (type == V4L2_BUF_TYPE_VIDEO_OUTPUT ? \ "frame" : "stream") -#define fh_to_ctx(f) (container_of(f, struct hva_ctx, fh)) +static inline struct hva_ctx *file_to_ctx(struct file *filp) +{ + return container_of(file_to_v4l2_fh(filp), struct hva_ctx, fh); +} /* registry of available encoders */ static const struct hva_enc *hva_encoders[] = { @@ -254,7 +257,7 @@ static void hva_dbg_summary(struct hva_ctx *ctx) static int hva_querycap(struct file *file, void *priv, struct v4l2_capability *cap) { - struct hva_ctx *ctx = fh_to_ctx(file->private_data); + struct hva_ctx *ctx = file_to_ctx(file); struct hva_dev *hva = ctx_to_hdev(ctx); strscpy(cap->driver, HVA_NAME, sizeof(cap->driver)); @@ -268,7 +271,7 @@ static int hva_querycap(struct file *file, void *priv, static int hva_enum_fmt_stream(struct file *file, void *priv, struct v4l2_fmtdesc *f) { - struct hva_ctx *ctx = fh_to_ctx(file->private_data); + struct hva_ctx *ctx = file_to_ctx(file); struct hva_dev *hva = ctx_to_hdev(ctx); if (unlikely(f->index >= hva->nb_of_streamformats)) @@ -282,7 +285,7 @@ static int hva_enum_fmt_stream(struct file *file, void *priv, static int hva_enum_fmt_frame(struct file *file, void *priv, struct v4l2_fmtdesc *f) { - struct hva_ctx *ctx = fh_to_ctx(file->private_data); + struct hva_ctx *ctx = file_to_ctx(file); struct hva_dev *hva = ctx_to_hdev(ctx); if (unlikely(f->index >= hva->nb_of_pixelformats)) @@ -295,7 +298,7 @@ static int hva_enum_fmt_frame(struct file *file, void *priv, static int hva_g_fmt_stream(struct file *file, void *fh, struct v4l2_format *f) { - struct hva_ctx *ctx = fh_to_ctx(file->private_data); + struct hva_ctx *ctx = file_to_ctx(file); struct hva_streaminfo *streaminfo = &ctx->streaminfo; f->fmt.pix.width = streaminfo->width; @@ -314,7 +317,7 @@ static int hva_g_fmt_stream(struct file *file, void *fh, struct v4l2_format *f) static int hva_g_fmt_frame(struct file *file, void *fh, struct v4l2_format *f) { - struct hva_ctx *ctx = fh_to_ctx(file->private_data); + struct hva_ctx *ctx = file_to_ctx(file); struct hva_frameinfo *frameinfo = &ctx->frameinfo; f->fmt.pix.width = frameinfo->width; @@ -335,7 +338,7 @@ static int hva_g_fmt_frame(struct file *file, void *fh, struct v4l2_format *f) static int hva_try_fmt_stream(struct file *file, void *priv, struct v4l2_format *f) { - struct hva_ctx *ctx = fh_to_ctx(file->private_data); + struct hva_ctx *ctx = file_to_ctx(file); struct device *dev = ctx_to_dev(ctx); struct v4l2_pix_format *pix = &f->fmt.pix; u32 streamformat = pix->pixelformat; @@ -399,7 +402,7 @@ static int hva_try_fmt_stream(struct file *file, void *priv, static int hva_try_fmt_frame(struct file *file, void *priv, struct v4l2_format *f) { - struct hva_ctx *ctx = fh_to_ctx(file->private_data); + struct hva_ctx *ctx = file_to_ctx(file); struct device *dev = ctx_to_dev(ctx); struct v4l2_pix_format *pix = &f->fmt.pix; u32 pixelformat = pix->pixelformat; @@ -449,7 +452,7 @@ static int hva_try_fmt_frame(struct file *file, void *priv, static int hva_s_fmt_stream(struct file *file, void *fh, struct v4l2_format *f) { - struct hva_ctx *ctx = fh_to_ctx(file->private_data); + struct hva_ctx *ctx = file_to_ctx(file); struct device *dev = ctx_to_dev(ctx); struct vb2_queue *vq; int ret; @@ -479,7 +482,7 @@ static int hva_s_fmt_stream(struct file *file, void *fh, struct v4l2_format *f) static int hva_s_fmt_frame(struct file *file, void *fh, struct v4l2_format *f) { - struct hva_ctx *ctx = fh_to_ctx(file->private_data); + struct hva_ctx *ctx = file_to_ctx(file); struct device *dev = ctx_to_dev(ctx); struct v4l2_pix_format *pix = &f->fmt.pix; struct vb2_queue *vq; @@ -517,7 +520,7 @@ static int hva_s_fmt_frame(struct file *file, void *fh, struct v4l2_format *f) static int hva_g_parm(struct file *file, void *fh, struct v4l2_streamparm *sp) { - struct hva_ctx *ctx = fh_to_ctx(file->private_data); + struct hva_ctx *ctx = file_to_ctx(file); struct v4l2_fract *time_per_frame = &ctx->ctrls.time_per_frame; if (sp->type != V4L2_BUF_TYPE_VIDEO_OUTPUT) @@ -533,7 +536,7 @@ static int hva_g_parm(struct file *file, void *fh, struct v4l2_streamparm *sp) static int hva_s_parm(struct file *file, void *fh, struct v4l2_streamparm *sp) { - struct hva_ctx *ctx = fh_to_ctx(file->private_data); + struct hva_ctx *ctx = file_to_ctx(file); struct v4l2_fract *time_per_frame = &ctx->ctrls.time_per_frame; if (sp->type != V4L2_BUF_TYPE_VIDEO_OUTPUT) @@ -553,7 +556,7 @@ static int hva_s_parm(struct file *file, void *fh, struct v4l2_streamparm *sp) static int hva_qbuf(struct file *file, void *priv, struct v4l2_buffer *buf) { - struct hva_ctx *ctx = fh_to_ctx(file->private_data); + struct hva_ctx *ctx = file_to_ctx(file); struct device *dev = ctx_to_dev(ctx); if (buf->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) { @@ -1171,8 +1174,7 @@ static int hva_open(struct file *file) INIT_WORK(&ctx->run_work, hva_run_work); v4l2_fh_init(&ctx->fh, video_devdata(file)); - file->private_data = &ctx->fh; - v4l2_fh_add(&ctx->fh); + v4l2_fh_add(&ctx->fh, file); ret = hva_ctrls_setup(ctx); if (ret) { @@ -1216,7 +1218,7 @@ static int hva_open(struct file *file) err_ctrls: v4l2_ctrl_handler_free(&ctx->ctrl_handler); err_fh: - v4l2_fh_del(&ctx->fh); + v4l2_fh_del(&ctx->fh, file); v4l2_fh_exit(&ctx->fh); kfree(ctx); out: @@ -1225,7 +1227,7 @@ out: static int hva_release(struct file *file) { - struct hva_ctx *ctx = fh_to_ctx(file->private_data); + struct hva_ctx *ctx = file_to_ctx(file); struct hva_dev *hva = ctx_to_hdev(ctx); struct device *dev = ctx_to_dev(ctx); const struct hva_enc *enc = ctx->enc; @@ -1247,7 +1249,7 @@ static int hva_release(struct file *file) v4l2_ctrl_handler_free(&ctx->ctrl_handler); - v4l2_fh_del(&ctx->fh); + v4l2_fh_del(&ctx->fh, file); v4l2_fh_exit(&ctx->fh); #ifdef CONFIG_VIDEO_STI_HVA_DEBUGFS diff --git a/drivers/media/platform/st/sti/hva/hva.h b/drivers/media/platform/st/sti/hva/hva.h index ba6b893416ec..1fe561082a74 100644 --- a/drivers/media/platform/st/sti/hva/hva.h +++ b/drivers/media/platform/st/sti/hva/hva.h @@ -13,8 +13,6 @@ #include <media/videobuf2-v4l2.h> #include <media/v4l2-mem2mem.h> -#define fh_to_ctx(f) (container_of(f, struct hva_ctx, fh)) - #define hva_to_dev(h) (h->dev) #define ctx_to_dev(c) (c->hva_dev->dev) diff --git a/drivers/media/platform/st/stm32/dma2d/dma2d.c b/drivers/media/platform/st/stm32/dma2d/dma2d.c index 48fa781aab06..468c247ba328 100644 --- a/drivers/media/platform/st/stm32/dma2d/dma2d.c +++ b/drivers/media/platform/st/stm32/dma2d/dma2d.c @@ -45,7 +45,10 @@ * whole of a destination image with a pixel format conversion. */ -#define fh2ctx(__fh) container_of(__fh, struct dma2d_ctx, fh) +static inline struct dma2d_ctx *file2ctx(struct file *filp) +{ + return container_of(file_to_v4l2_fh(filp), struct dma2d_ctx, fh); +} static const struct dma2d_fmt formats[] = { { @@ -301,8 +304,7 @@ static int dma2d_open(struct file *file) } v4l2_fh_init(&ctx->fh, video_devdata(file)); - file->private_data = &ctx->fh; - v4l2_fh_add(&ctx->fh); + v4l2_fh_add(&ctx->fh, file); dma2d_setup_ctrls(ctx); @@ -318,13 +320,13 @@ static int dma2d_open(struct file *file) static int dma2d_release(struct file *file) { struct dma2d_dev *dev = video_drvdata(file); - struct dma2d_ctx *ctx = fh2ctx(file->private_data); + struct dma2d_ctx *ctx = file2ctx(file); mutex_lock(&dev->mutex); v4l2_m2m_ctx_release(ctx->fh.m2m_ctx); mutex_unlock(&dev->mutex); v4l2_ctrl_handler_free(&ctx->ctrl_handler); - v4l2_fh_del(&ctx->fh); + v4l2_fh_del(&ctx->fh, file); v4l2_fh_exit(&ctx->fh); kfree(ctx); @@ -341,7 +343,7 @@ static int vidioc_querycap(struct file *file, void *priv, return 0; } -static int vidioc_enum_fmt(struct file *file, void *prv, struct v4l2_fmtdesc *f) +static int vidioc_enum_fmt(struct file *file, void *priv, struct v4l2_fmtdesc *f) { if (f->index >= NUM_FORMATS) return -EINVAL; @@ -350,9 +352,9 @@ static int vidioc_enum_fmt(struct file *file, void *prv, struct v4l2_fmtdesc *f) return 0; } -static int vidioc_g_fmt(struct file *file, void *prv, struct v4l2_format *f) +static int vidioc_g_fmt(struct file *file, void *priv, struct v4l2_format *f) { - struct dma2d_ctx *ctx = prv; + struct dma2d_ctx *ctx = file2ctx(file); struct vb2_queue *vq; struct dma2d_frame *frm; @@ -375,9 +377,9 @@ static int vidioc_g_fmt(struct file *file, void *prv, struct v4l2_format *f) return 0; } -static int vidioc_try_fmt(struct file *file, void *prv, struct v4l2_format *f) +static int vidioc_try_fmt(struct file *file, void *priv, struct v4l2_format *f) { - struct dma2d_ctx *ctx = prv; + struct dma2d_ctx *ctx = file2ctx(file); struct dma2d_fmt *fmt; enum v4l2_field *field; u32 fourcc = f->fmt.pix.pixelformat; @@ -418,9 +420,9 @@ static int vidioc_try_fmt(struct file *file, void *prv, struct v4l2_format *f) return 0; } -static int vidioc_s_fmt(struct file *file, void *prv, struct v4l2_format *f) +static int vidioc_s_fmt(struct file *file, void *priv, struct v4l2_format *f) { - struct dma2d_ctx *ctx = prv; + struct dma2d_ctx *ctx = file2ctx(file); struct vb2_queue *vq; struct dma2d_frame *frm; struct dma2d_fmt *fmt; @@ -429,7 +431,7 @@ static int vidioc_s_fmt(struct file *file, void *prv, struct v4l2_format *f) /* Adjust all values accordingly to the hardware capabilities * and chosen format. */ - ret = vidioc_try_fmt(file, prv, f); + ret = vidioc_try_fmt(file, priv, f); if (ret) return ret; diff --git a/drivers/media/platform/st/stm32/stm32-csi.c b/drivers/media/platform/st/stm32/stm32-csi.c index b69048144cc1..fd2b6dfbd44c 100644 --- a/drivers/media/platform/st/stm32/stm32-csi.c +++ b/drivers/media/platform/st/stm32/stm32-csi.c @@ -443,8 +443,7 @@ static void stm32_csi_phy_reg_write(struct stm32_csi_dev *csidev, static int stm32_csi_start(struct stm32_csi_dev *csidev, struct v4l2_subdev_state *state) { - struct media_pad *src_pad = - &csidev->s_subdev->entity.pads[csidev->s_subdev_pad_nb]; + struct media_pad *src_pad; const struct stm32_csi_mbps_phy_reg *phy_regs = NULL; struct v4l2_mbus_framefmt *sink_fmt; const struct stm32_csi_fmts *fmt; @@ -466,6 +465,7 @@ static int stm32_csi_start(struct stm32_csi_dev *csidev, if (!csidev->s_subdev) return -EIO; + src_pad = &csidev->s_subdev->entity.pads[csidev->s_subdev_pad_nb]; link_freq = v4l2_get_link_freq(src_pad, fmt->bpp, 2 * csidev->num_lanes); if (link_freq < 0) diff --git a/drivers/media/platform/st/stm32/stm32-dcmi.c b/drivers/media/platform/st/stm32/stm32-dcmi.c index d94c61b8569d..13762861b769 100644 --- a/drivers/media/platform/st/stm32/stm32-dcmi.c +++ b/drivers/media/platform/st/stm32/stm32-dcmi.c @@ -1701,8 +1701,8 @@ static int dcmi_framesizes_init(struct stm32_dcmi *dcmi) .which = V4L2_SUBDEV_FORMAT_ACTIVE, .code = dcmi->sd_format->mbus_code, }; - unsigned int ret; unsigned int i; + int ret; /* Allocate discrete framesizes array */ while (!v4l2_subdev_call(subdev, pad, enum_frame_size, @@ -1808,8 +1808,8 @@ static int dcmi_graph_notify_bound(struct v4l2_async_notifier *notifier, struct v4l2_async_connection *asd) { struct stm32_dcmi *dcmi = notifier_to_dcmi(notifier); - unsigned int ret; int src_pad; + int ret; dev_dbg(dcmi->dev, "Subdev \"%s\" bound\n", subdev->name); diff --git a/drivers/media/platform/sunxi/sun6i-csi/sun6i_csi_capture.c b/drivers/media/platform/sunxi/sun6i-csi/sun6i_csi_capture.c index 76356bc7f10e..65879f4802c0 100644 --- a/drivers/media/platform/sunxi/sun6i-csi/sun6i_csi_capture.c +++ b/drivers/media/platform/sunxi/sun6i-csi/sun6i_csi_capture.c @@ -711,7 +711,7 @@ static void sun6i_csi_capture_format_prepare(struct v4l2_format *format) pix_format->xfer_func = V4L2_XFER_FUNC_DEFAULT; } -static int sun6i_csi_capture_querycap(struct file *file, void *private, +static int sun6i_csi_capture_querycap(struct file *file, void *priv, struct v4l2_capability *capability) { struct sun6i_csi_device *csi_dev = video_drvdata(file); @@ -725,7 +725,7 @@ static int sun6i_csi_capture_querycap(struct file *file, void *private, return 0; } -static int sun6i_csi_capture_enum_fmt(struct file *file, void *private, +static int sun6i_csi_capture_enum_fmt(struct file *file, void *priv, struct v4l2_fmtdesc *fmtdesc) { u32 index = fmtdesc->index; @@ -738,7 +738,7 @@ static int sun6i_csi_capture_enum_fmt(struct file *file, void *private, return 0; } -static int sun6i_csi_capture_g_fmt(struct file *file, void *private, +static int sun6i_csi_capture_g_fmt(struct file *file, void *priv, struct v4l2_format *format) { struct sun6i_csi_device *csi_dev = video_drvdata(file); @@ -748,7 +748,7 @@ static int sun6i_csi_capture_g_fmt(struct file *file, void *private, return 0; } -static int sun6i_csi_capture_s_fmt(struct file *file, void *private, +static int sun6i_csi_capture_s_fmt(struct file *file, void *priv, struct v4l2_format *format) { struct sun6i_csi_device *csi_dev = video_drvdata(file); @@ -764,7 +764,7 @@ static int sun6i_csi_capture_s_fmt(struct file *file, void *private, return 0; } -static int sun6i_csi_capture_try_fmt(struct file *file, void *private, +static int sun6i_csi_capture_try_fmt(struct file *file, void *priv, struct v4l2_format *format) { sun6i_csi_capture_format_prepare(format); @@ -772,7 +772,7 @@ static int sun6i_csi_capture_try_fmt(struct file *file, void *private, return 0; } -static int sun6i_csi_capture_enum_input(struct file *file, void *private, +static int sun6i_csi_capture_enum_input(struct file *file, void *priv, struct v4l2_input *input) { if (input->index != 0) @@ -784,7 +784,7 @@ static int sun6i_csi_capture_enum_input(struct file *file, void *private, return 0; } -static int sun6i_csi_capture_g_input(struct file *file, void *private, +static int sun6i_csi_capture_g_input(struct file *file, void *priv, unsigned int *index) { *index = 0; @@ -792,7 +792,7 @@ static int sun6i_csi_capture_g_input(struct file *file, void *private, return 0; } -static int sun6i_csi_capture_s_input(struct file *file, void *private, +static int sun6i_csi_capture_s_input(struct file *file, void *priv, unsigned int index) { if (index != 0) diff --git a/drivers/media/platform/sunxi/sun8i-di/sun8i-di.c b/drivers/media/platform/sunxi/sun8i-di/sun8i-di.c index 3e7f2df70408..eb519afb30ca 100644 --- a/drivers/media/platform/sunxi/sun8i-di/sun8i-di.c +++ b/drivers/media/platform/sunxi/sun8i-di/sun8i-di.c @@ -309,7 +309,7 @@ static void deinterlace_init(struct deinterlace_dev *dev) static inline struct deinterlace_ctx *deinterlace_file2ctx(struct file *file) { - return container_of(file->private_data, struct deinterlace_ctx, fh); + return container_of(file_to_v4l2_fh(file), struct deinterlace_ctx, fh); } static bool deinterlace_check_format(u32 pixelformat) @@ -730,7 +730,6 @@ static int deinterlace_open(struct file *file) deinterlace_prepare_format(&ctx->dst_fmt); v4l2_fh_init(&ctx->fh, video_devdata(file)); - file->private_data = &ctx->fh; ctx->dev = dev; ctx->fh.m2m_ctx = v4l2_m2m_ctx_init(dev->m2m_dev, ctx, @@ -740,7 +739,7 @@ static int deinterlace_open(struct file *file) goto err_free; } - v4l2_fh_add(&ctx->fh); + v4l2_fh_add(&ctx->fh, file); mutex_unlock(&dev->dev_mutex); @@ -756,12 +755,11 @@ err_free: static int deinterlace_release(struct file *file) { struct deinterlace_dev *dev = video_drvdata(file); - struct deinterlace_ctx *ctx = container_of(file->private_data, - struct deinterlace_ctx, fh); + struct deinterlace_ctx *ctx = deinterlace_file2ctx(file); mutex_lock(&dev->dev_mutex); - v4l2_fh_del(&ctx->fh); + v4l2_fh_del(&ctx->fh, file); v4l2_fh_exit(&ctx->fh); v4l2_m2m_ctx_release(ctx->fh.m2m_ctx); diff --git a/drivers/media/platform/sunxi/sun8i-rotate/sun8i_rotate.c b/drivers/media/platform/sunxi/sun8i-rotate/sun8i_rotate.c index abd10b218aa1..89992feaab60 100644 --- a/drivers/media/platform/sunxi/sun8i-rotate/sun8i_rotate.c +++ b/drivers/media/platform/sunxi/sun8i-rotate/sun8i_rotate.c @@ -170,7 +170,7 @@ static irqreturn_t rotate_irq(int irq, void *data) static inline struct rotate_ctx *rotate_file2ctx(struct file *file) { - return container_of(file->private_data, struct rotate_ctx, fh); + return container_of(file_to_v4l2_fh(file), struct rotate_ctx, fh); } static void rotate_prepare_format(struct v4l2_pix_format *pix_fmt) @@ -659,7 +659,6 @@ static int rotate_open(struct file *file) rotate_set_cap_format(ctx, &ctx->dst_fmt, ctx->rotate); v4l2_fh_init(&ctx->fh, video_devdata(file)); - file->private_data = &ctx->fh; ctx->dev = dev; ctx->fh.m2m_ctx = v4l2_m2m_ctx_init(dev->m2m_dev, ctx, @@ -669,7 +668,7 @@ static int rotate_open(struct file *file) goto err_free; } - v4l2_fh_add(&ctx->fh); + v4l2_fh_add(&ctx->fh, file); ret = rotate_setup_ctrls(ctx); if (ret) @@ -691,13 +690,12 @@ err_free: static int rotate_release(struct file *file) { struct rotate_dev *dev = video_drvdata(file); - struct rotate_ctx *ctx = container_of(file->private_data, - struct rotate_ctx, fh); + struct rotate_ctx *ctx = rotate_file2ctx(file); mutex_lock(&dev->dev_mutex); v4l2_ctrl_handler_free(&ctx->ctrl_handler); - v4l2_fh_del(&ctx->fh); + v4l2_fh_del(&ctx->fh, file); v4l2_fh_exit(&ctx->fh); v4l2_m2m_ctx_release(ctx->fh.m2m_ctx); diff --git a/drivers/media/platform/synopsys/hdmirx/snps_hdmirx.c b/drivers/media/platform/synopsys/hdmirx/snps_hdmirx.c index 7af6765532e3..b7d278b3889f 100644 --- a/drivers/media/platform/synopsys/hdmirx/snps_hdmirx.c +++ b/drivers/media/platform/synopsys/hdmirx/snps_hdmirx.c @@ -459,7 +459,7 @@ static bool port_no_link(struct snps_hdmirx_dev *hdmirx_dev) return !tx_5v_power_present(hdmirx_dev); } -static int hdmirx_query_dv_timings(struct file *file, void *_fh, +static int hdmirx_query_dv_timings(struct file *file, void *priv, struct v4l2_dv_timings *timings) { struct hdmirx_stream *stream = video_drvdata(file); @@ -751,7 +751,7 @@ static int hdmirx_dv_timings_cap(struct file *file, void *fh, return 0; } -static int hdmirx_enum_dv_timings(struct file *file, void *_fh, +static int hdmirx_enum_dv_timings(struct file *file, void *priv, struct v4l2_enum_dv_timings *timings) { return v4l2_enum_dv_timings_cap(timings, &hdmirx_timings_cap, NULL, NULL); @@ -1323,7 +1323,7 @@ static int hdmirx_g_fmt_vid_cap_mplane(struct file *file, void *fh, return 0; } -static int hdmirx_g_dv_timings(struct file *file, void *_fh, +static int hdmirx_g_dv_timings(struct file *file, void *priv, struct v4l2_dv_timings *timings) { struct hdmirx_stream *stream = video_drvdata(file); @@ -1339,7 +1339,7 @@ static int hdmirx_g_dv_timings(struct file *file, void *_fh, return 0; } -static int hdmirx_s_dv_timings(struct file *file, void *_fh, +static int hdmirx_s_dv_timings(struct file *file, void *priv, struct v4l2_dv_timings *timings) { struct hdmirx_stream *stream = video_drvdata(file); diff --git a/drivers/media/platform/ti/Kconfig b/drivers/media/platform/ti/Kconfig index bab998c4179a..3bc4aa35887e 100644 --- a/drivers/media/platform/ti/Kconfig +++ b/drivers/media/platform/ti/Kconfig @@ -67,7 +67,8 @@ config VIDEO_TI_J721E_CSI2RX tristate "TI J721E CSI2RX wrapper layer driver" depends on VIDEO_DEV && VIDEO_V4L2_SUBDEV_API depends on MEDIA_SUPPORT && MEDIA_CONTROLLER - depends on (PHY_CADENCE_DPHY_RX && VIDEO_CADENCE_CSI2RX) || COMPILE_TEST + depends on VIDEO_CADENCE_CSI2RX + depends on PHY_CADENCE_DPHY_RX || COMPILE_TEST depends on ARCH_K3 || COMPILE_TEST select VIDEOBUF2_DMA_CONTIG select V4L2_FWNODE diff --git a/drivers/media/platform/ti/j721e-csi2rx/j721e-csi2rx.c b/drivers/media/platform/ti/j721e-csi2rx/j721e-csi2rx.c index b628d6e081db..b75aa363d1bf 100644 --- a/drivers/media/platform/ti/j721e-csi2rx/j721e-csi2rx.c +++ b/drivers/media/platform/ti/j721e-csi2rx/j721e-csi2rx.c @@ -13,7 +13,9 @@ #include <linux/module.h> #include <linux/of_platform.h> #include <linux/platform_device.h> +#include <linux/property.h> +#include <media/cadence/cdns-csi2rx.h> #include <media/mipi-csi2.h> #include <media/v4l2-device.h> #include <media/v4l2-ioctl.h> @@ -28,6 +30,7 @@ #define SHIM_DMACNTX 0x20 #define SHIM_DMACNTX_EN BIT(31) #define SHIM_DMACNTX_YUV422 GENMASK(27, 26) +#define SHIM_DMACNTX_DUAL_PCK_CFG BIT(24) #define SHIM_DMACNTX_SIZE GENMASK(21, 20) #define SHIM_DMACNTX_FMT GENMASK(5, 0) #define SHIM_DMACNTX_YUV422_MODE_11 3 @@ -39,6 +42,7 @@ #define SHIM_PSI_CFG0_SRC_TAG GENMASK(15, 0) #define SHIM_PSI_CFG0_DST_TAG GENMASK(31, 16) +#define TI_CSI2RX_MAX_PIX_PER_CLK 4 #define PSIL_WORD_SIZE_BYTES 16 /* * There are no hard limits on the width or height. The DMA engine can handle @@ -52,6 +56,8 @@ #define DRAIN_TIMEOUT_MS 50 #define DRAIN_BUFFER_SIZE SZ_32K +#define CSI2RX_BRIDGE_SOURCE_PAD 1 + struct ti_csi2rx_fmt { u32 fourcc; /* Four character code. */ u32 code; /* Mbus code. */ @@ -107,6 +113,7 @@ struct ti_csi2rx_dev { struct v4l2_format v_fmt; struct ti_csi2rx_dma dma; u32 sequence; + u8 pix_per_clk; }; static const struct ti_csi2rx_fmt ti_csi2rx_formats[] = { @@ -299,7 +306,7 @@ static int ti_csi2rx_enum_fmt_vid_cap(struct file *file, void *priv, return 0; } -static int ti_csi2rx_g_fmt_vid_cap(struct file *file, void *prov, +static int ti_csi2rx_g_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *f) { struct ti_csi2rx_dev *csi = video_drvdata(file); @@ -426,8 +433,9 @@ static int csi_async_notifier_complete(struct v4l2_async_notifier *notifier) if (ret) return ret; - ret = v4l2_create_fwnode_links_to_pad(csi->source, &csi->pad, - MEDIA_LNK_FL_IMMUTABLE | MEDIA_LNK_FL_ENABLED); + ret = media_create_pad_link(&csi->source->entity, CSI2RX_BRIDGE_SOURCE_PAD, + &vdev->entity, csi->pad.index, + MEDIA_LNK_FL_IMMUTABLE | MEDIA_LNK_FL_ENABLED); if (ret) { video_unregister_device(vdev); @@ -450,25 +458,23 @@ static int ti_csi2rx_notifier_register(struct ti_csi2rx_dev *csi) { struct fwnode_handle *fwnode; struct v4l2_async_connection *asc; - struct device_node *node; int ret; - node = of_get_child_by_name(csi->dev->of_node, "csi-bridge"); - if (!node) + fwnode = fwnode_get_named_child_node(csi->dev->fwnode, "csi-bridge"); + if (!fwnode) return -EINVAL; - fwnode = of_fwnode_handle(node); - if (!fwnode) { - of_node_put(node); - return -EINVAL; - } - v4l2_async_nf_init(&csi->notifier, &csi->v4l2_dev); csi->notifier.ops = &csi_async_notifier_ops; asc = v4l2_async_nf_add_fwnode(&csi->notifier, fwnode, struct v4l2_async_connection); - of_node_put(node); + /* + * Calling v4l2_async_nf_add_fwnode grabs a refcount, + * so drop the one we got in fwnode_get_named_child_node + */ + fwnode_handle_put(fwnode); + if (IS_ERR(asc)) { v4l2_async_nf_cleanup(&csi->notifier); return PTR_ERR(asc); @@ -483,6 +489,26 @@ static int ti_csi2rx_notifier_register(struct ti_csi2rx_dev *csi) return 0; } +/* Request maximum possible pixels per clock from the bridge */ +static void ti_csi2rx_request_max_ppc(struct ti_csi2rx_dev *csi) +{ + u8 ppc = TI_CSI2RX_MAX_PIX_PER_CLK; + struct media_pad *pad; + int ret; + + pad = media_entity_remote_source_pad_unique(&csi->vdev.entity); + if (IS_ERR(pad)) + return; + + ret = cdns_csi2rx_negotiate_ppc(csi->source, pad->index, &ppc); + if (ret) { + dev_warn(csi->dev, "NUM_PIXELS negotiation failed: %d\n", ret); + csi->pix_per_clk = 1; + } else { + csi->pix_per_clk = ppc; + } +} + static void ti_csi2rx_setup_shim(struct ti_csi2rx_dev *csi) { const struct ti_csi2rx_fmt *fmt; @@ -494,6 +520,9 @@ static void ti_csi2rx_setup_shim(struct ti_csi2rx_dev *csi) reg = SHIM_CNTL_PIX_RST; writel(reg, csi->shim + SHIM_CNTL); + /* Negotiate pixel count from the source */ + ti_csi2rx_request_max_ppc(csi); + reg = SHIM_DMACNTX_EN; reg |= FIELD_PREP(SHIM_DMACNTX_FMT, fmt->csi_dt); @@ -522,14 +551,18 @@ static void ti_csi2rx_setup_shim(struct ti_csi2rx_dev *csi) case V4L2_PIX_FMT_YVYU: reg |= FIELD_PREP(SHIM_DMACNTX_YUV422, SHIM_DMACNTX_YUV422_MODE_11); + /* Multiple pixels are handled differently for packed YUV */ + if (csi->pix_per_clk == 2) + reg |= SHIM_DMACNTX_DUAL_PCK_CFG; + reg |= FIELD_PREP(SHIM_DMACNTX_SIZE, fmt->size); break; default: - /* Ignore if not YUV 4:2:2 */ + /* By default we change the shift size for multiple pixels */ + reg |= FIELD_PREP(SHIM_DMACNTX_SIZE, + fmt->size + (csi->pix_per_clk >> 1)); break; } - reg |= FIELD_PREP(SHIM_DMACNTX_SIZE, fmt->size); - writel(reg, csi->shim + SHIM_DMACNTX); reg = FIELD_PREP(SHIM_PSI_CFG0_SRC_TAG, 0) | @@ -1120,7 +1153,7 @@ static int ti_csi2rx_probe(struct platform_device *pdev) if (ret) goto err_vb2q; - ret = of_platform_populate(csi->dev->of_node, NULL, NULL, csi->dev); + ret = devm_of_platform_populate(csi->dev); if (ret) { dev_err(csi->dev, "Failed to create children: %d\n", ret); goto err_subdev; diff --git a/drivers/media/platform/ti/omap/omap_vout.c b/drivers/media/platform/ti/omap/omap_vout.c index a87d5030ac35..22782e9f1f4e 100644 --- a/drivers/media/platform/ti/omap/omap_vout.c +++ b/drivers/media/platform/ti/omap/omap_vout.c @@ -1236,7 +1236,7 @@ static int vidioc_g_fbuf(struct file *file, void *fh, return 0; } -static int vidioc_enum_output(struct file *file, void *priv_fh, +static int vidioc_enum_output(struct file *file, void *priv, struct v4l2_output *out) { if (out->index) @@ -1246,13 +1246,13 @@ static int vidioc_enum_output(struct file *file, void *priv_fh, return 0; } -static int vidioc_g_output(struct file *file, void *priv_fh, unsigned int *i) +static int vidioc_g_output(struct file *file, void *priv, unsigned int *i) { *i = 0; return 0; } -static int vidioc_s_output(struct file *file, void *priv_fh, unsigned int i) +static int vidioc_s_output(struct file *file, void *priv, unsigned int i) { return i ? -EINVAL : 0; } diff --git a/drivers/media/platform/ti/omap3isp/ispccdc.c b/drivers/media/platform/ti/omap3isp/ispccdc.c index 7d0c723dcd11..55ee14e8b449 100644 --- a/drivers/media/platform/ti/omap3isp/ispccdc.c +++ b/drivers/media/platform/ti/omap3isp/ispccdc.c @@ -1873,12 +1873,6 @@ static int ccdc_subscribe_event(struct v4l2_subdev *sd, struct v4l2_fh *fh, return v4l2_event_subscribe(fh, sub, OMAP3ISP_CCDC_NEVENTS, NULL); } -static int ccdc_unsubscribe_event(struct v4l2_subdev *sd, struct v4l2_fh *fh, - struct v4l2_event_subscription *sub) -{ - return v4l2_event_unsubscribe(fh, sub); -} - /* * ccdc_set_stream - Enable/Disable streaming on the CCDC module * @sd: ISP CCDC V4L2 subdevice @@ -2487,7 +2481,7 @@ static int ccdc_init_formats(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) static const struct v4l2_subdev_core_ops ccdc_v4l2_core_ops = { .ioctl = ccdc_ioctl, .subscribe_event = ccdc_subscribe_event, - .unsubscribe_event = ccdc_unsubscribe_event, + .unsubscribe_event = v4l2_event_subdev_unsubscribe, }; /* V4L2 subdev video operations */ diff --git a/drivers/media/platform/ti/omap3isp/isph3a_aewb.c b/drivers/media/platform/ti/omap3isp/isph3a_aewb.c index e6c54c4bbfca..ae93da9c4542 100644 --- a/drivers/media/platform/ti/omap3isp/isph3a_aewb.c +++ b/drivers/media/platform/ti/omap3isp/isph3a_aewb.c @@ -269,7 +269,7 @@ static const struct ispstat_ops h3a_aewb_ops = { static const struct v4l2_subdev_core_ops h3a_aewb_subdev_core_ops = { .ioctl = h3a_aewb_ioctl, .subscribe_event = omap3isp_stat_subscribe_event, - .unsubscribe_event = omap3isp_stat_unsubscribe_event, + .unsubscribe_event = v4l2_event_subdev_unsubscribe, }; static const struct v4l2_subdev_video_ops h3a_aewb_subdev_video_ops = { diff --git a/drivers/media/platform/ti/omap3isp/isph3a_af.c b/drivers/media/platform/ti/omap3isp/isph3a_af.c index de7b116d0122..ca478da4ad34 100644 --- a/drivers/media/platform/ti/omap3isp/isph3a_af.c +++ b/drivers/media/platform/ti/omap3isp/isph3a_af.c @@ -334,7 +334,7 @@ static const struct ispstat_ops h3a_af_ops = { static const struct v4l2_subdev_core_ops h3a_af_subdev_core_ops = { .ioctl = h3a_af_ioctl, .subscribe_event = omap3isp_stat_subscribe_event, - .unsubscribe_event = omap3isp_stat_unsubscribe_event, + .unsubscribe_event = v4l2_event_subdev_unsubscribe, }; static const struct v4l2_subdev_video_ops h3a_af_subdev_video_ops = { diff --git a/drivers/media/platform/ti/omap3isp/isphist.c b/drivers/media/platform/ti/omap3isp/isphist.c index 0ef78aace6da..7851ad13d84f 100644 --- a/drivers/media/platform/ti/omap3isp/isphist.c +++ b/drivers/media/platform/ti/omap3isp/isphist.c @@ -456,7 +456,7 @@ static const struct ispstat_ops hist_ops = { static const struct v4l2_subdev_core_ops hist_subdev_core_ops = { .ioctl = hist_ioctl, .subscribe_event = omap3isp_stat_subscribe_event, - .unsubscribe_event = omap3isp_stat_unsubscribe_event, + .unsubscribe_event = v4l2_event_subdev_unsubscribe, }; static const struct v4l2_subdev_video_ops hist_subdev_video_ops = { diff --git a/drivers/media/platform/ti/omap3isp/ispstat.c b/drivers/media/platform/ti/omap3isp/ispstat.c index d3da68408ecb..07bd62a93d99 100644 --- a/drivers/media/platform/ti/omap3isp/ispstat.c +++ b/drivers/media/platform/ti/omap3isp/ispstat.c @@ -1010,13 +1010,6 @@ int omap3isp_stat_subscribe_event(struct v4l2_subdev *subdev, return v4l2_event_subscribe(fh, sub, STAT_NEVENTS, NULL); } -int omap3isp_stat_unsubscribe_event(struct v4l2_subdev *subdev, - struct v4l2_fh *fh, - struct v4l2_event_subscription *sub) -{ - return v4l2_event_unsubscribe(fh, sub); -} - void omap3isp_stat_unregister_entities(struct ispstat *stat) { v4l2_device_unregister_subdev(&stat->subdev); diff --git a/drivers/media/platform/ti/omap3isp/ispstat.h b/drivers/media/platform/ti/omap3isp/ispstat.h index b548e617cf62..59842c4a9c33 100644 --- a/drivers/media/platform/ti/omap3isp/ispstat.h +++ b/drivers/media/platform/ti/omap3isp/ispstat.h @@ -135,9 +135,6 @@ void omap3isp_stat_cleanup(struct ispstat *stat); int omap3isp_stat_subscribe_event(struct v4l2_subdev *subdev, struct v4l2_fh *fh, struct v4l2_event_subscription *sub); -int omap3isp_stat_unsubscribe_event(struct v4l2_subdev *subdev, - struct v4l2_fh *fh, - struct v4l2_event_subscription *sub); int omap3isp_stat_s_stream(struct v4l2_subdev *subdev, int enable); int omap3isp_stat_busy(struct ispstat *stat); diff --git a/drivers/media/platform/ti/omap3isp/ispvideo.c b/drivers/media/platform/ti/omap3isp/ispvideo.c index 78e30298c7ad..0e7f0bf2b346 100644 --- a/drivers/media/platform/ti/omap3isp/ispvideo.c +++ b/drivers/media/platform/ti/omap3isp/ispvideo.c @@ -657,7 +657,7 @@ isp_video_querycap(struct file *file, void *fh, struct v4l2_capability *cap) static int isp_video_get_format(struct file *file, void *fh, struct v4l2_format *format) { - struct isp_video_fh *vfh = to_isp_video_fh(fh); + struct isp_video_fh *vfh = file_to_isp_video_fh(file); struct isp_video *video = video_drvdata(file); if (format->type != video->type) @@ -673,7 +673,7 @@ isp_video_get_format(struct file *file, void *fh, struct v4l2_format *format) static int isp_video_set_format(struct file *file, void *fh, struct v4l2_format *format) { - struct isp_video_fh *vfh = to_isp_video_fh(fh); + struct isp_video_fh *vfh = file_to_isp_video_fh(file); struct isp_video *video = video_drvdata(file); struct v4l2_mbus_framefmt fmt; @@ -858,7 +858,7 @@ isp_video_set_selection(struct file *file, void *fh, struct v4l2_selection *sel) static int isp_video_get_param(struct file *file, void *fh, struct v4l2_streamparm *a) { - struct isp_video_fh *vfh = to_isp_video_fh(fh); + struct isp_video_fh *vfh = file_to_isp_video_fh(file); struct isp_video *video = video_drvdata(file); if (video->type != V4L2_BUF_TYPE_VIDEO_OUTPUT || @@ -876,7 +876,7 @@ isp_video_get_param(struct file *file, void *fh, struct v4l2_streamparm *a) static int isp_video_set_param(struct file *file, void *fh, struct v4l2_streamparm *a) { - struct isp_video_fh *vfh = to_isp_video_fh(fh); + struct isp_video_fh *vfh = file_to_isp_video_fh(file); struct isp_video *video = video_drvdata(file); if (video->type != V4L2_BUF_TYPE_VIDEO_OUTPUT || @@ -894,7 +894,7 @@ isp_video_set_param(struct file *file, void *fh, struct v4l2_streamparm *a) static int isp_video_reqbufs(struct file *file, void *fh, struct v4l2_requestbuffers *rb) { - struct isp_video_fh *vfh = to_isp_video_fh(fh); + struct isp_video_fh *vfh = file_to_isp_video_fh(file); struct isp_video *video = video_drvdata(file); int ret; @@ -908,7 +908,7 @@ isp_video_reqbufs(struct file *file, void *fh, struct v4l2_requestbuffers *rb) static int isp_video_querybuf(struct file *file, void *fh, struct v4l2_buffer *b) { - struct isp_video_fh *vfh = to_isp_video_fh(fh); + struct isp_video_fh *vfh = file_to_isp_video_fh(file); struct isp_video *video = video_drvdata(file); int ret; @@ -922,7 +922,7 @@ isp_video_querybuf(struct file *file, void *fh, struct v4l2_buffer *b) static int isp_video_qbuf(struct file *file, void *fh, struct v4l2_buffer *b) { - struct isp_video_fh *vfh = to_isp_video_fh(fh); + struct isp_video_fh *vfh = file_to_isp_video_fh(file); struct isp_video *video = video_drvdata(file); int ret; @@ -936,7 +936,7 @@ isp_video_qbuf(struct file *file, void *fh, struct v4l2_buffer *b) static int isp_video_dqbuf(struct file *file, void *fh, struct v4l2_buffer *b) { - struct isp_video_fh *vfh = to_isp_video_fh(fh); + struct isp_video_fh *vfh = file_to_isp_video_fh(file); struct isp_video *video = video_drvdata(file); int ret; @@ -1074,7 +1074,7 @@ static int isp_video_check_external_subdevs(struct isp_video *video, static int isp_video_streamon(struct file *file, void *fh, enum v4l2_buf_type type) { - struct isp_video_fh *vfh = to_isp_video_fh(fh); + struct isp_video_fh *vfh = file_to_isp_video_fh(file); struct isp_video *video = video_drvdata(file); enum isp_pipeline_state state; struct isp_pipeline *pipe; @@ -1180,7 +1180,7 @@ err_enum_init: static int isp_video_streamoff(struct file *file, void *fh, enum v4l2_buf_type type) { - struct isp_video_fh *vfh = to_isp_video_fh(fh); + struct isp_video_fh *vfh = file_to_isp_video_fh(file); struct isp_video *video = video_drvdata(file); struct isp_pipeline *pipe = to_isp_pipeline(&video->video.entity); enum isp_pipeline_state state; @@ -1297,7 +1297,7 @@ static int isp_video_open(struct file *file) return -ENOMEM; v4l2_fh_init(&handle->vfh, &video->video); - v4l2_fh_add(&handle->vfh); + v4l2_fh_add(&handle->vfh, file); /* If this is the first user, initialise the pipeline. */ if (omap3isp_get(video->isp) == NULL) { @@ -1333,11 +1333,10 @@ static int isp_video_open(struct file *file) handle->timeperframe.denominator = 1; handle->video = video; - file->private_data = &handle->vfh; done: if (ret < 0) { - v4l2_fh_del(&handle->vfh); + v4l2_fh_del(&handle->vfh, file); v4l2_fh_exit(&handle->vfh); kfree(handle); } @@ -1348,8 +1347,8 @@ done: static int isp_video_release(struct file *file) { struct isp_video *video = video_drvdata(file); - struct v4l2_fh *vfh = file->private_data; - struct isp_video_fh *handle = to_isp_video_fh(vfh); + struct v4l2_fh *vfh = file_to_v4l2_fh(file); + struct isp_video_fh *handle = file_to_isp_video_fh(file); /* Disable streaming and free the buffers queue resources. */ isp_video_streamoff(file, vfh, video->type); @@ -1361,10 +1360,9 @@ static int isp_video_release(struct file *file) v4l2_pipeline_pm_put(&video->video.entity); /* Release the file handle. */ - v4l2_fh_del(vfh); + v4l2_fh_del(vfh, file); v4l2_fh_exit(vfh); kfree(handle); - file->private_data = NULL; omap3isp_put(video->isp); @@ -1373,7 +1371,7 @@ static int isp_video_release(struct file *file) static __poll_t isp_video_poll(struct file *file, poll_table *wait) { - struct isp_video_fh *vfh = to_isp_video_fh(file->private_data); + struct isp_video_fh *vfh = file_to_isp_video_fh(file); struct isp_video *video = video_drvdata(file); __poll_t ret; @@ -1386,7 +1384,7 @@ static __poll_t isp_video_poll(struct file *file, poll_table *wait) static int isp_video_mmap(struct file *file, struct vm_area_struct *vma) { - struct isp_video_fh *vfh = to_isp_video_fh(file->private_data); + struct isp_video_fh *vfh = file_to_isp_video_fh(file); return vb2_mmap(&vfh->queue, vma); } diff --git a/drivers/media/platform/ti/omap3isp/ispvideo.h b/drivers/media/platform/ti/omap3isp/ispvideo.h index 1d23df576e6b..537da59cff62 100644 --- a/drivers/media/platform/ti/omap3isp/ispvideo.h +++ b/drivers/media/platform/ti/omap3isp/ispvideo.h @@ -194,7 +194,11 @@ struct isp_video_fh { struct v4l2_fract timeperframe; }; -#define to_isp_video_fh(fh) container_of(fh, struct isp_video_fh, vfh) +static inline struct isp_video_fh *file_to_isp_video_fh(struct file *filp) +{ + return container_of(file_to_v4l2_fh(filp), struct isp_video_fh, vfh); +} + #define isp_video_queue_to_isp_video_fh(q) \ container_of(q, struct isp_video_fh, queue) diff --git a/drivers/media/platform/ti/vpe/vpe.c b/drivers/media/platform/ti/vpe/vpe.c index 636d76ecebcd..6029d4e8e0bd 100644 --- a/drivers/media/platform/ti/vpe/vpe.c +++ b/drivers/media/platform/ti/vpe/vpe.c @@ -422,6 +422,10 @@ struct vpe_ctx { unsigned int src_mv_buf_selector; }; +static inline struct vpe_ctx *to_vpe_ctx(struct file *filp) +{ + return container_of(file_to_v4l2_fh(filp), struct vpe_ctx, fh); +} /* * M2M devices get 2 queues. @@ -1562,7 +1566,7 @@ static int vpe_enum_fmt(struct file *file, void *priv, static int vpe_g_fmt(struct file *file, void *priv, struct v4l2_format *f) { struct v4l2_pix_format_mplane *pix = &f->fmt.pix_mp; - struct vpe_ctx *ctx = file->private_data; + struct vpe_ctx *ctx = to_vpe_ctx(file); struct vb2_queue *vq; struct vpe_q_data *q_data; @@ -1719,7 +1723,7 @@ static int __vpe_try_fmt(struct vpe_ctx *ctx, struct v4l2_format *f, static int vpe_try_fmt(struct file *file, void *priv, struct v4l2_format *f) { - struct vpe_ctx *ctx = file->private_data; + struct vpe_ctx *ctx = to_vpe_ctx(file); struct vpe_fmt *fmt = find_format(f); if (V4L2_TYPE_IS_OUTPUT(f->type)) @@ -1783,7 +1787,7 @@ static int __vpe_s_fmt(struct vpe_ctx *ctx, struct v4l2_format *f) static int vpe_s_fmt(struct file *file, void *priv, struct v4l2_format *f) { int ret; - struct vpe_ctx *ctx = file->private_data; + struct vpe_ctx *ctx = to_vpe_ctx(file); ret = vpe_try_fmt(file, priv, f); if (ret) @@ -1871,7 +1875,7 @@ static int __vpe_try_selection(struct vpe_ctx *ctx, struct v4l2_selection *s) static int vpe_g_selection(struct file *file, void *fh, struct v4l2_selection *s) { - struct vpe_ctx *ctx = file->private_data; + struct vpe_ctx *ctx = to_vpe_ctx(file); struct vpe_q_data *q_data; struct v4l2_pix_format_mplane *pix; bool use_c_rect = false; @@ -1935,7 +1939,7 @@ static int vpe_g_selection(struct file *file, void *fh, static int vpe_s_selection(struct file *file, void *fh, struct v4l2_selection *s) { - struct vpe_ctx *ctx = file->private_data; + struct vpe_ctx *ctx = to_vpe_ctx(file); struct vpe_q_data *q_data; struct v4l2_selection sel = *s; int ret; @@ -2306,7 +2310,6 @@ static int vpe_open(struct file *file) init_adb_hdrs(ctx); v4l2_fh_init(&ctx->fh, video_devdata(file)); - file->private_data = ctx; hdl = &ctx->hdl; v4l2_ctrl_handler_init(hdl, 1); @@ -2360,7 +2363,7 @@ static int vpe_open(struct file *file) goto exit_fh; } - v4l2_fh_add(&ctx->fh); + v4l2_fh_add(&ctx->fh, file); /* * for now, just report the creation of the first instance, we can later @@ -2400,7 +2403,7 @@ free_ctx: static int vpe_release(struct file *file) { struct vpe_dev *dev = video_drvdata(file); - struct vpe_ctx *ctx = file->private_data; + struct vpe_ctx *ctx = to_vpe_ctx(file); vpe_dbg(dev, "releasing instance %p\n", ctx); @@ -2418,7 +2421,7 @@ static int vpe_release(struct file *file) vpdma_free_desc_buf(&ctx->sc_coeff_v); vpdma_free_desc_buf(&ctx->sc_coeff_h); - v4l2_fh_del(&ctx->fh); + v4l2_fh_del(&ctx->fh, file); v4l2_fh_exit(&ctx->fh); v4l2_ctrl_handler_free(&ctx->hdl); v4l2_m2m_ctx_release(ctx->fh.m2m_ctx); diff --git a/drivers/media/platform/verisilicon/hantro.h b/drivers/media/platform/verisilicon/hantro.h index 81328c63b796..e0fdc4535b2d 100644 --- a/drivers/media/platform/verisilicon/hantro.h +++ b/drivers/media/platform/verisilicon/hantro.h @@ -382,9 +382,9 @@ extern int hantro_debug; pr_err("%s:%d: " fmt, __func__, __LINE__, ##args) /* Structure access helpers. */ -static __always_inline struct hantro_ctx *fh_to_ctx(struct v4l2_fh *fh) +static __always_inline struct hantro_ctx *file_to_ctx(struct file *filp) { - return container_of(fh, struct hantro_ctx, fh); + return container_of(file_to_v4l2_fh(filp), struct hantro_ctx, fh); } /* Register accessors. */ diff --git a/drivers/media/platform/verisilicon/hantro_drv.c b/drivers/media/platform/verisilicon/hantro_drv.c index fa972effd4a2..e0c11fe8b55c 100644 --- a/drivers/media/platform/verisilicon/hantro_drv.c +++ b/drivers/media/platform/verisilicon/hantro_drv.c @@ -662,8 +662,7 @@ static int hantro_open(struct file *filp) } v4l2_fh_init(&ctx->fh, vdev); - filp->private_data = &ctx->fh; - v4l2_fh_add(&ctx->fh); + v4l2_fh_add(&ctx->fh, filp); hantro_reset_fmts(ctx); @@ -677,7 +676,7 @@ static int hantro_open(struct file *filp) return 0; err_fh_free: - v4l2_fh_del(&ctx->fh); + v4l2_fh_del(&ctx->fh, filp); v4l2_fh_exit(&ctx->fh); err_ctx_free: kfree(ctx); @@ -686,15 +685,14 @@ err_ctx_free: static int hantro_release(struct file *filp) { - struct hantro_ctx *ctx = - container_of(filp->private_data, struct hantro_ctx, fh); + struct hantro_ctx *ctx = file_to_ctx(filp); /* * No need for extra locking because this was the last reference * to this file. */ v4l2_m2m_ctx_release(ctx->fh.m2m_ctx); - v4l2_fh_del(&ctx->fh); + v4l2_fh_del(&ctx->fh, filp); v4l2_fh_exit(&ctx->fh); v4l2_ctrl_handler_free(&ctx->ctrl_handler); kfree(ctx); @@ -917,6 +915,8 @@ static int hantro_add_func(struct hantro_dev *vpu, unsigned int funcid) vpu->decoder = func; v4l2_disable_ioctl(vfd, VIDIOC_TRY_ENCODER_CMD); v4l2_disable_ioctl(vfd, VIDIOC_ENCODER_CMD); + v4l2_disable_ioctl(vfd, VIDIOC_G_SELECTION); + v4l2_disable_ioctl(vfd, VIDIOC_S_SELECTION); } video_set_drvdata(vfd, vpu); diff --git a/drivers/media/platform/verisilicon/hantro_v4l2.c b/drivers/media/platform/verisilicon/hantro_v4l2.c index 7c3515cf7d64..fcf3bd9bcda2 100644 --- a/drivers/media/platform/verisilicon/hantro_v4l2.c +++ b/drivers/media/platform/verisilicon/hantro_v4l2.c @@ -185,7 +185,7 @@ static int vidioc_querycap(struct file *file, void *priv, static int vidioc_enum_framesizes(struct file *file, void *priv, struct v4l2_frmsizeenum *fsize) { - struct hantro_ctx *ctx = fh_to_ctx(priv); + struct hantro_ctx *ctx = file_to_ctx(file); const struct hantro_fmt *fmt; fmt = hantro_find_format(ctx, fsize->pixel_format); @@ -217,7 +217,7 @@ static int vidioc_enum_fmt(struct file *file, void *priv, struct v4l2_fmtdesc *f, bool capture) { - struct hantro_ctx *ctx = fh_to_ctx(priv); + struct hantro_ctx *ctx = file_to_ctx(file); const struct hantro_fmt *fmt, *formats; unsigned int num_fmts, i, j = 0; bool skip_mode_none, enum_all_formats; @@ -297,7 +297,7 @@ static int vidioc_g_fmt_out_mplane(struct file *file, void *priv, struct v4l2_format *f) { struct v4l2_pix_format_mplane *pix_mp = &f->fmt.pix_mp; - struct hantro_ctx *ctx = fh_to_ctx(priv); + struct hantro_ctx *ctx = file_to_ctx(file); vpu_debug(4, "f->type = %d\n", f->type); @@ -310,7 +310,7 @@ static int vidioc_g_fmt_cap_mplane(struct file *file, void *priv, struct v4l2_format *f) { struct v4l2_pix_format_mplane *pix_mp = &f->fmt.pix_mp; - struct hantro_ctx *ctx = fh_to_ctx(priv); + struct hantro_ctx *ctx = file_to_ctx(file); vpu_debug(4, "f->type = %d\n", f->type); @@ -398,13 +398,13 @@ static int hantro_try_fmt(const struct hantro_ctx *ctx, static int vidioc_try_fmt_cap_mplane(struct file *file, void *priv, struct v4l2_format *f) { - return hantro_try_fmt(fh_to_ctx(priv), &f->fmt.pix_mp, f->type); + return hantro_try_fmt(file_to_ctx(file), &f->fmt.pix_mp, f->type); } static int vidioc_try_fmt_out_mplane(struct file *file, void *priv, struct v4l2_format *f) { - return hantro_try_fmt(fh_to_ctx(priv), &f->fmt.pix_mp, f->type); + return hantro_try_fmt(file_to_ctx(file), &f->fmt.pix_mp, f->type); } static void @@ -648,23 +648,22 @@ static int hantro_set_fmt_cap(struct hantro_ctx *ctx, static int vidioc_s_fmt_out_mplane(struct file *file, void *priv, struct v4l2_format *f) { - return hantro_set_fmt_out(fh_to_ctx(priv), &f->fmt.pix_mp, HANTRO_AUTO_POSTPROC); + return hantro_set_fmt_out(file_to_ctx(file), &f->fmt.pix_mp, HANTRO_AUTO_POSTPROC); } static int vidioc_s_fmt_cap_mplane(struct file *file, void *priv, struct v4l2_format *f) { - return hantro_set_fmt_cap(fh_to_ctx(priv), &f->fmt.pix_mp); + return hantro_set_fmt_cap(file_to_ctx(file), &f->fmt.pix_mp); } static int vidioc_g_selection(struct file *file, void *priv, struct v4l2_selection *sel) { - struct hantro_ctx *ctx = fh_to_ctx(priv); + struct hantro_ctx *ctx = file_to_ctx(file); /* Crop only supported on source. */ - if (!ctx->is_encoder || - sel->type != V4L2_BUF_TYPE_VIDEO_OUTPUT) + if (sel->type != V4L2_BUF_TYPE_VIDEO_OUTPUT) return -EINVAL; switch (sel->target) { @@ -691,13 +690,12 @@ static int vidioc_g_selection(struct file *file, void *priv, static int vidioc_s_selection(struct file *file, void *priv, struct v4l2_selection *sel) { - struct hantro_ctx *ctx = fh_to_ctx(priv); + struct hantro_ctx *ctx = file_to_ctx(file); struct v4l2_rect *rect = &sel->r; struct vb2_queue *vq; /* Crop only supported on source. */ - if (!ctx->is_encoder || - sel->type != V4L2_BUF_TYPE_VIDEO_OUTPUT) + if (sel->type != V4L2_BUF_TYPE_VIDEO_OUTPUT) return -EINVAL; /* Change not allowed if the queue is streaming. */ @@ -738,7 +736,7 @@ static const struct v4l2_event hantro_eos_event = { static int vidioc_encoder_cmd(struct file *file, void *priv, struct v4l2_encoder_cmd *ec) { - struct hantro_ctx *ctx = fh_to_ctx(priv); + struct hantro_ctx *ctx = file_to_ctx(file); int ret; ret = v4l2_m2m_ioctl_try_encoder_cmd(file, priv, ec); diff --git a/drivers/media/platform/verisilicon/imx8m_vpu_hw.c b/drivers/media/platform/verisilicon/imx8m_vpu_hw.c index 35799da534ed..f9f276385c11 100644 --- a/drivers/media/platform/verisilicon/imx8m_vpu_hw.c +++ b/drivers/media/platform/verisilicon/imx8m_vpu_hw.c @@ -234,24 +234,6 @@ static const struct hantro_fmt imx8m_vpu_g2_dec_fmts[] = { }, }; -static irqreturn_t imx8m_vpu_g1_irq(int irq, void *dev_id) -{ - struct hantro_dev *vpu = dev_id; - enum vb2_buffer_state state; - u32 status; - - status = vdpu_read(vpu, G1_REG_INTERRUPT); - state = (status & G1_REG_INTERRUPT_DEC_RDY_INT) ? - VB2_BUF_STATE_DONE : VB2_BUF_STATE_ERROR; - - vdpu_write(vpu, 0, G1_REG_INTERRUPT); - vdpu_write(vpu, G1_REG_CONFIG_DEC_CLK_GATE_E, G1_REG_CONFIG); - - hantro_irq_done(vpu, state); - - return IRQ_HANDLED; -} - static int imx8mq_vpu_hw_init(struct hantro_dev *vpu) { vpu->ctrl_base = vpu->reg_bases[vpu->variant->num_regs - 1]; @@ -328,7 +310,7 @@ static const struct hantro_codec_ops imx8mq_vpu_g2_codec_ops[] = { */ static const struct hantro_irq imx8mq_irqs[] = { - { "g1", imx8m_vpu_g1_irq }, + { "g1", hantro_g1_irq }, }; static const struct hantro_irq imx8mq_g2_irqs[] = { diff --git a/drivers/media/platform/xilinx/xilinx-dma.c b/drivers/media/platform/xilinx/xilinx-dma.c index 18bfa6001909..fcfe0883aba5 100644 --- a/drivers/media/platform/xilinx/xilinx-dma.c +++ b/drivers/media/platform/xilinx/xilinx-dma.c @@ -469,7 +469,7 @@ static const struct vb2_ops xvip_dma_queue_qops = { static int xvip_dma_querycap(struct file *file, void *fh, struct v4l2_capability *cap) { - struct v4l2_fh *vfh = file->private_data; + struct v4l2_fh *vfh = file_to_v4l2_fh(file); struct xvip_dma *dma = to_xvip_dma(vfh->vdev); cap->capabilities = dma->xdev->v4l2_caps | V4L2_CAP_STREAMING | @@ -491,7 +491,7 @@ xvip_dma_querycap(struct file *file, void *fh, struct v4l2_capability *cap) static int xvip_dma_enum_format(struct file *file, void *fh, struct v4l2_fmtdesc *f) { - struct v4l2_fh *vfh = file->private_data; + struct v4l2_fh *vfh = file_to_v4l2_fh(file); struct xvip_dma *dma = to_xvip_dma(vfh->vdev); if (f->index > 0) @@ -505,7 +505,7 @@ xvip_dma_enum_format(struct file *file, void *fh, struct v4l2_fmtdesc *f) static int xvip_dma_get_format(struct file *file, void *fh, struct v4l2_format *format) { - struct v4l2_fh *vfh = file->private_data; + struct v4l2_fh *vfh = file_to_v4l2_fh(file); struct xvip_dma *dma = to_xvip_dma(vfh->vdev); format->fmt.pix = dma->format; @@ -565,7 +565,7 @@ __xvip_dma_try_format(struct xvip_dma *dma, struct v4l2_pix_format *pix, static int xvip_dma_try_format(struct file *file, void *fh, struct v4l2_format *format) { - struct v4l2_fh *vfh = file->private_data; + struct v4l2_fh *vfh = file_to_v4l2_fh(file); struct xvip_dma *dma = to_xvip_dma(vfh->vdev); __xvip_dma_try_format(dma, &format->fmt.pix, NULL); @@ -575,7 +575,7 @@ xvip_dma_try_format(struct file *file, void *fh, struct v4l2_format *format) static int xvip_dma_set_format(struct file *file, void *fh, struct v4l2_format *format) { - struct v4l2_fh *vfh = file->private_data; + struct v4l2_fh *vfh = file_to_v4l2_fh(file); struct xvip_dma *dma = to_xvip_dma(vfh->vdev); const struct xvip_video_format *info; diff --git a/drivers/media/radio/Kconfig b/drivers/media/radio/Kconfig index 72776d08046a..bbbdd054ba64 100644 --- a/drivers/media/radio/Kconfig +++ b/drivers/media/radio/Kconfig @@ -141,23 +141,6 @@ config RADIO_TIMBERDALE found behind the Timberdale FPGA on the Russellville board. Enabling this driver will automatically select the DSP and tuner. -config RADIO_WL1273 - tristate "Texas Instruments WL1273 I2C FM Radio" - depends on I2C - select MFD_CORE - select MFD_WL1273_CORE - select FW_LOADER - help - Choose Y here if you have this FM radio chip. - - In order to control your radio card, you will need to use programs - that are compatible with the Video For Linux 2 API. Information on - this API and pointers to "v4l2" programs may be found at - <file:Documentation/userspace-api/media/index.rst>. - - To compile this driver as a module, choose M here: the - module will be called radio-wl1273. - config USB_DSBR tristate "D-Link/GemTek USB FM radio support" depends on USB diff --git a/drivers/media/radio/Makefile b/drivers/media/radio/Makefile index 1ff46f3a6ed3..f54693ebdb30 100644 --- a/drivers/media/radio/Makefile +++ b/drivers/media/radio/Makefile @@ -30,7 +30,6 @@ obj-$(CONFIG_RADIO_TERRATEC) += radio-terratec.o obj-$(CONFIG_RADIO_TIMBERDALE) += radio-timb.o obj-$(CONFIG_RADIO_TRUST) += radio-trust.o obj-$(CONFIG_RADIO_TYPHOON) += radio-typhoon.o -obj-$(CONFIG_RADIO_WL1273) += radio-wl1273.o obj-$(CONFIG_RADIO_ZOLTRIX) += radio-zoltrix.o obj-$(CONFIG_USB_DSBR) += dsbr100.o diff --git a/drivers/media/radio/radio-aimslab.c b/drivers/media/radio/radio-aimslab.c index 3c8c17d64821..2c1d413e8636 100644 --- a/drivers/media/radio/radio-aimslab.c +++ b/drivers/media/radio/radio-aimslab.c @@ -4,7 +4,7 @@ * * Copyright 1997 M. Kirkwood * - * Converted to the radio-isa framework by Hans Verkuil <hansverk@cisco.com> + * Converted to the radio-isa framework by Hans Verkuil <hverkuil@kernel.org> * Converted to V4L2 API by Mauro Carvalho Chehab <mchehab@kernel.org> * Converted to new API by Alan Cox <alan@lxorguk.ukuu.org.uk> * Various bugfixes and enhancements by Russell Kroll <rkroll@exploits.org> diff --git a/drivers/media/radio/radio-aztech.c b/drivers/media/radio/radio-aztech.c index d989c0b3966f..0a4667bb7034 100644 --- a/drivers/media/radio/radio-aztech.c +++ b/drivers/media/radio/radio-aztech.c @@ -2,7 +2,7 @@ /* * radio-aztech.c - Aztech radio card driver * - * Converted to the radio-isa framework by Hans Verkuil <hverkuil@xs4all.nl> + * Converted to the radio-isa framework by Hans Verkuil <hverkuil@kernel.org> * Converted to V4L2 API by Mauro Carvalho Chehab <mchehab@kernel.org> * Adapted to support the Video for Linux API by * Russell Kroll <rkroll@exploits.org>. Based on original tuner code by: diff --git a/drivers/media/radio/radio-gemtek.c b/drivers/media/radio/radio-gemtek.c index 5ca6274c45bd..a3265f1dd189 100644 --- a/drivers/media/radio/radio-gemtek.c +++ b/drivers/media/radio/radio-gemtek.c @@ -15,7 +15,7 @@ * Converted to new API by Alan Cox <alan@lxorguk.ukuu.org.uk> * Various bugfixes and enhancements by Russell Kroll <rkroll@exploits.org> * - * Converted to the radio-isa framework by Hans Verkuil <hansverk@cisco.com> + * Converted to the radio-isa framework by Hans Verkuil <hverkuil@kernel.org> * Converted to V4L2 API by Mauro Carvalho Chehab <mchehab@kernel.org> * * Note: this card seems to swap the left and right audio channels! diff --git a/drivers/media/radio/radio-isa.c b/drivers/media/radio/radio-isa.c index 4f87c76a2a96..1a144536ffa7 100644 --- a/drivers/media/radio/radio-isa.c +++ b/drivers/media/radio/radio-isa.c @@ -4,7 +4,7 @@ * This takes care of all the V4L2 scaffolding, allowing the ISA drivers * to concentrate on the actual hardware operation. * - * Copyright (C) 2012 Hans Verkuil <hansverk@cisco.com> + * Copyright (C) 2012 Hans Verkuil <hverkuil@kernel.org> */ #include <linux/module.h> diff --git a/drivers/media/radio/radio-isa.h b/drivers/media/radio/radio-isa.h index 0f3db473da5e..62ff5c3fb5d5 100644 --- a/drivers/media/radio/radio-isa.h +++ b/drivers/media/radio/radio-isa.h @@ -4,7 +4,7 @@ * This takes care of all the V4L2 scaffolding, allowing the ISA drivers * to concentrate on the actual hardware operation. * - * Copyright (C) 2012 Hans Verkuil <hansverk@cisco.com> + * Copyright (C) 2012 Hans Verkuil <hverkuil@kernel.org> */ #ifndef _RADIO_ISA_H_ diff --git a/drivers/media/radio/radio-keene.c b/drivers/media/radio/radio-keene.c index a35648316aa8..f3b57f0cb1ec 100644 --- a/drivers/media/radio/radio-keene.c +++ b/drivers/media/radio/radio-keene.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later /* - * Copyright (c) 2012 Hans Verkuil <hverkuil@xs4all.nl> + * Copyright (c) 2012 Hans Verkuil <hverkuil@kernel.org> */ /* kernel includes */ @@ -18,7 +18,7 @@ #include <linux/mutex.h> /* driver and module definitions */ -MODULE_AUTHOR("Hans Verkuil <hverkuil@xs4all.nl>"); +MODULE_AUTHOR("Hans Verkuil <hverkuil@kernel.org>"); MODULE_DESCRIPTION("Keene FM Transmitter driver"); MODULE_LICENSE("GPL"); diff --git a/drivers/media/radio/radio-miropcm20.c b/drivers/media/radio/radio-miropcm20.c index 27f058c5e677..67712ab3d564 100644 --- a/drivers/media/radio/radio-miropcm20.c +++ b/drivers/media/radio/radio-miropcm20.c @@ -23,7 +23,7 @@ * This code has been reintroduced and converted to use * the new V4L2 RDS API by: * - * Hans Verkuil <hansverk@cisco.com> + * Hans Verkuil <hverkuil@kernel.org> */ #include <linux/module.h> diff --git a/drivers/media/radio/radio-raremono.c b/drivers/media/radio/radio-raremono.c index 64c7452c05b5..f60775b005e1 100644 --- a/drivers/media/radio/radio-raremono.c +++ b/drivers/media/radio/radio-raremono.c @@ -25,14 +25,14 @@ * * The USB protocol has been reversed engineered using wireshark, initially * by Dinesh Ram <dinesh.ram@cern.ch> and finished by Hans Verkuil - * <hverkuil@xs4all.nl>. + * <hverkuil@kernel.org>. * * Sadly the firmware used in this product hides lots of goodies since the * si4734 has more features than are supported by the firmware. Oh well... */ /* driver and module definitions */ -MODULE_AUTHOR("Hans Verkuil <hverkuil@xs4all.nl>"); +MODULE_AUTHOR("Hans Verkuil <hverkuil@kernel.org>"); MODULE_DESCRIPTION("Thanko's Raremono AM/FM/SW Receiver USB driver"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/media/radio/radio-rtrack2.c b/drivers/media/radio/radio-rtrack2.c index 16b13a63bfed..efc02069bf9d 100644 --- a/drivers/media/radio/radio-rtrack2.c +++ b/drivers/media/radio/radio-rtrack2.c @@ -7,7 +7,7 @@ * Converted to new API by Alan Cox <alan@lxorguk.ukuu.org.uk> * Various bugfixes and enhancements by Russell Kroll <rkroll@exploits.org> * - * Converted to the radio-isa framework by Hans Verkuil <hansverk@cisco.com> + * Converted to the radio-isa framework by Hans Verkuil <hverkuil@kernel.org> * Converted to V4L2 API by Mauro Carvalho Chehab <mchehab@kernel.org> * * Fully tested with actual hardware and the v4l2-compliance tool. diff --git a/drivers/media/radio/radio-terratec.c b/drivers/media/radio/radio-terratec.c index 720080634454..43817dd0a0fe 100644 --- a/drivers/media/radio/radio-terratec.c +++ b/drivers/media/radio/radio-terratec.c @@ -17,7 +17,7 @@ * Frequency control is done digitally -- ie out(port,encodefreq(95.8)); * Volume Control is done digitally * - * Converted to the radio-isa framework by Hans Verkuil <hansverk@cisco.com> + * Converted to the radio-isa framework by Hans Verkuil <hverkuil@kernel.org> * Converted to V4L2 API by Mauro Carvalho Chehab <mchehab@kernel.org> */ diff --git a/drivers/media/radio/radio-wl1273.c b/drivers/media/radio/radio-wl1273.c deleted file mode 100644 index f55217ccf2b8..000000000000 --- a/drivers/media/radio/radio-wl1273.c +++ /dev/null @@ -1,2159 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Driver for the Texas Instruments WL1273 FM radio. - * - * Copyright (C) 2011 Nokia Corporation - * Author: Matti J. Aaltonen <matti.j.aaltonen@nokia.com> - */ - -#include <linux/delay.h> -#include <linux/firmware.h> -#include <linux/interrupt.h> -#include <linux/mfd/wl1273-core.h> -#include <linux/slab.h> -#include <linux/module.h> -#include <media/v4l2-common.h> -#include <media/v4l2-ctrls.h> -#include <media/v4l2-device.h> -#include <media/v4l2-ioctl.h> - -#define DRIVER_DESC "Wl1273 FM Radio" - -#define WL1273_POWER_SET_OFF 0 -#define WL1273_POWER_SET_FM BIT(0) -#define WL1273_POWER_SET_RDS BIT(1) -#define WL1273_POWER_SET_RETENTION BIT(4) - -#define WL1273_PUPD_SET_OFF 0x00 -#define WL1273_PUPD_SET_ON 0x01 -#define WL1273_PUPD_SET_RETENTION 0x10 - -#define WL1273_FREQ(x) (x * 10000 / 625) -#define WL1273_INV_FREQ(x) (x * 625 / 10000) - -/* - * static int radio_nr - The number of the radio device - * - * The default is 0. - */ -static int radio_nr; -module_param(radio_nr, int, 0); -MODULE_PARM_DESC(radio_nr, "The number of the radio device. Default = 0"); - -struct wl1273_device { - char *bus_type; - - u8 forbidden; - unsigned int preemphasis; - unsigned int spacing; - unsigned int tx_power; - unsigned int rx_frequency; - unsigned int tx_frequency; - unsigned int rangelow; - unsigned int rangehigh; - unsigned int band; - bool stereo; - - /* RDS */ - unsigned int rds_on; - - wait_queue_head_t read_queue; - struct mutex lock; /* for serializing fm radio operations */ - struct completion busy; - - unsigned char *buffer; - unsigned int buf_size; - unsigned int rd_index; - unsigned int wr_index; - - /* Selected interrupts */ - u16 irq_flags; - u16 irq_received; - - struct v4l2_ctrl_handler ctrl_handler; - struct v4l2_device v4l2dev; - struct video_device videodev; - struct device *dev; - struct wl1273_core *core; - struct file *owner; - char *write_buf; - unsigned int rds_users; -}; - -#define WL1273_IRQ_MASK (WL1273_FR_EVENT | \ - WL1273_POW_ENB_EVENT) - -/* - * static unsigned int rds_buf - the number of RDS buffer blocks used. - * - * The default number is 100. - */ -static unsigned int rds_buf = 100; -module_param(rds_buf, uint, 0); -MODULE_PARM_DESC(rds_buf, "Number of RDS buffer entries. Default = 100"); - -static int wl1273_fm_write_fw(struct wl1273_core *core, - __u8 *fw, int len) -{ - struct i2c_client *client = core->client; - struct i2c_msg msg; - int i, r = 0; - - msg.addr = client->addr; - msg.flags = 0; - - for (i = 0; i <= len; i++) { - msg.len = fw[0]; - msg.buf = fw + 1; - - fw += msg.len + 1; - dev_dbg(&client->dev, "%s:len[%d]: %d\n", __func__, i, msg.len); - - r = i2c_transfer(client->adapter, &msg, 1); - if (r < 0 && i < len + 1) - break; - } - - dev_dbg(&client->dev, "%s: i: %d\n", __func__, i); - dev_dbg(&client->dev, "%s: len + 1: %d\n", __func__, len + 1); - - /* Last transfer always fails. */ - if (i == len || r == 1) - r = 0; - - return r; -} - -#define WL1273_FIFO_HAS_DATA(status) (1 << 5 & status) -#define WL1273_RDS_CORRECTABLE_ERROR (1 << 3) -#define WL1273_RDS_UNCORRECTABLE_ERROR (1 << 4) - -static int wl1273_fm_rds(struct wl1273_device *radio) -{ - struct wl1273_core *core = radio->core; - struct i2c_client *client = core->client; - u16 val; - u8 b0 = WL1273_RDS_DATA_GET, status; - struct v4l2_rds_data rds = { 0, 0, 0 }; - struct i2c_msg msg[] = { - { - .addr = client->addr, - .flags = 0, - .buf = &b0, - .len = 1, - }, - { - .addr = client->addr, - .flags = I2C_M_RD, - .buf = (u8 *) &rds, - .len = sizeof(rds), - } - }; - int r; - - if (core->mode != WL1273_MODE_RX) - return 0; - - r = core->read(core, WL1273_RDS_SYNC_GET, &val); - if (r) - return r; - - if ((val & 0x01) == 0) { - /* RDS decoder not synchronized */ - return -EAGAIN; - } - - /* copy all four RDS blocks to internal buffer */ - do { - r = i2c_transfer(client->adapter, msg, ARRAY_SIZE(msg)); - if (r != ARRAY_SIZE(msg)) { - dev_err(radio->dev, WL1273_FM_DRIVER_NAME - ": %s: read_rds error r == %i)\n", - __func__, r); - } - - status = rds.block; - - if (!WL1273_FIFO_HAS_DATA(status)) - break; - - /* copy bits 0-2 (the block ID) to bits 3-5 */ - rds.block = V4L2_RDS_BLOCK_MSK & status; - rds.block |= rds.block << 3; - - /* copy the error bits to standard positions */ - if (WL1273_RDS_UNCORRECTABLE_ERROR & status) { - rds.block |= V4L2_RDS_BLOCK_ERROR; - rds.block &= ~V4L2_RDS_BLOCK_CORRECTED; - } else if (WL1273_RDS_CORRECTABLE_ERROR & status) { - rds.block &= ~V4L2_RDS_BLOCK_ERROR; - rds.block |= V4L2_RDS_BLOCK_CORRECTED; - } - - /* copy RDS block to internal buffer */ - memcpy(&radio->buffer[radio->wr_index], &rds, RDS_BLOCK_SIZE); - radio->wr_index += 3; - - /* wrap write pointer */ - if (radio->wr_index >= radio->buf_size) - radio->wr_index = 0; - - /* check for overflow & start over */ - if (radio->wr_index == radio->rd_index) { - dev_dbg(radio->dev, "RDS OVERFLOW"); - - radio->rd_index = 0; - radio->wr_index = 0; - break; - } - } while (WL1273_FIFO_HAS_DATA(status)); - - /* wake up read queue */ - if (radio->wr_index != radio->rd_index) - wake_up_interruptible(&radio->read_queue); - - return 0; -} - -static irqreturn_t wl1273_fm_irq_thread_handler(int irq, void *dev_id) -{ - struct wl1273_device *radio = dev_id; - struct wl1273_core *core = radio->core; - u16 flags; - int r; - - r = core->read(core, WL1273_FLAG_GET, &flags); - if (r) - goto out; - - if (flags & WL1273_BL_EVENT) { - radio->irq_received = flags; - dev_dbg(radio->dev, "IRQ: BL\n"); - } - - if (flags & WL1273_RDS_EVENT) { - msleep(200); - - wl1273_fm_rds(radio); - } - - if (flags & WL1273_BBLK_EVENT) - dev_dbg(radio->dev, "IRQ: BBLK\n"); - - if (flags & WL1273_LSYNC_EVENT) - dev_dbg(radio->dev, "IRQ: LSYNC\n"); - - if (flags & WL1273_LEV_EVENT) { - u16 level; - - r = core->read(core, WL1273_RSSI_LVL_GET, &level); - if (r) - goto out; - - if (level > 14) - dev_dbg(radio->dev, "IRQ: LEV: 0x%x04\n", level); - } - - if (flags & WL1273_IFFR_EVENT) - dev_dbg(radio->dev, "IRQ: IFFR\n"); - - if (flags & WL1273_PI_EVENT) - dev_dbg(radio->dev, "IRQ: PI\n"); - - if (flags & WL1273_PD_EVENT) - dev_dbg(radio->dev, "IRQ: PD\n"); - - if (flags & WL1273_STIC_EVENT) - dev_dbg(radio->dev, "IRQ: STIC\n"); - - if (flags & WL1273_MAL_EVENT) - dev_dbg(radio->dev, "IRQ: MAL\n"); - - if (flags & WL1273_POW_ENB_EVENT) { - complete(&radio->busy); - dev_dbg(radio->dev, "NOT BUSY\n"); - dev_dbg(radio->dev, "IRQ: POW_ENB\n"); - } - - if (flags & WL1273_SCAN_OVER_EVENT) - dev_dbg(radio->dev, "IRQ: SCAN_OVER\n"); - - if (flags & WL1273_ERROR_EVENT) - dev_dbg(radio->dev, "IRQ: ERROR\n"); - - if (flags & WL1273_FR_EVENT) { - u16 freq; - - dev_dbg(radio->dev, "IRQ: FR:\n"); - - if (core->mode == WL1273_MODE_RX) { - r = core->write(core, WL1273_TUNER_MODE_SET, - TUNER_MODE_STOP_SEARCH); - if (r) { - dev_err(radio->dev, - "%s: TUNER_MODE_SET fails: %d\n", - __func__, r); - goto out; - } - - r = core->read(core, WL1273_FREQ_SET, &freq); - if (r) - goto out; - - if (radio->band == WL1273_BAND_JAPAN) - radio->rx_frequency = WL1273_BAND_JAPAN_LOW + - freq * 50; - else - radio->rx_frequency = WL1273_BAND_OTHER_LOW + - freq * 50; - /* - * The driver works better with this msleep, - * the documentation doesn't mention it. - */ - usleep_range(10000, 15000); - - dev_dbg(radio->dev, "%dkHz\n", radio->rx_frequency); - - } else { - r = core->read(core, WL1273_CHANL_SET, &freq); - if (r) - goto out; - - dev_dbg(radio->dev, "%dkHz\n", freq); - } - dev_dbg(radio->dev, "%s: NOT BUSY\n", __func__); - } - -out: - core->write(core, WL1273_INT_MASK_SET, radio->irq_flags); - complete(&radio->busy); - - return IRQ_HANDLED; -} - -static int wl1273_fm_set_tx_freq(struct wl1273_device *radio, unsigned int freq) -{ - struct wl1273_core *core = radio->core; - int r = 0; - unsigned long t; - - if (freq < WL1273_BAND_TX_LOW) { - dev_err(radio->dev, - "Frequency out of range: %d < %d\n", freq, - WL1273_BAND_TX_LOW); - return -ERANGE; - } - - if (freq > WL1273_BAND_TX_HIGH) { - dev_err(radio->dev, - "Frequency out of range: %d > %d\n", freq, - WL1273_BAND_TX_HIGH); - return -ERANGE; - } - - /* - * The driver works better with this sleep, - * the documentation doesn't mention it. - */ - usleep_range(5000, 10000); - - dev_dbg(radio->dev, "%s: freq: %d kHz\n", __func__, freq); - - /* Set the current tx channel */ - r = core->write(core, WL1273_CHANL_SET, freq / 10); - if (r) - return r; - - reinit_completion(&radio->busy); - - /* wait for the FR IRQ */ - t = wait_for_completion_timeout(&radio->busy, msecs_to_jiffies(2000)); - if (!t) - return -ETIMEDOUT; - - dev_dbg(radio->dev, "WL1273_CHANL_SET: %lu\n", t); - - /* Enable the output power */ - r = core->write(core, WL1273_POWER_ENB_SET, 1); - if (r) - return r; - - reinit_completion(&radio->busy); - - /* wait for the POWER_ENB IRQ */ - t = wait_for_completion_timeout(&radio->busy, msecs_to_jiffies(1000)); - if (!t) - return -ETIMEDOUT; - - radio->tx_frequency = freq; - dev_dbg(radio->dev, "WL1273_POWER_ENB_SET: %lu\n", t); - - return 0; -} - -static int wl1273_fm_set_rx_freq(struct wl1273_device *radio, unsigned int freq) -{ - struct wl1273_core *core = radio->core; - int r, f; - unsigned long t; - - if (freq < radio->rangelow) { - dev_err(radio->dev, - "Frequency out of range: %d < %d\n", freq, - radio->rangelow); - r = -ERANGE; - goto err; - } - - if (freq > radio->rangehigh) { - dev_err(radio->dev, - "Frequency out of range: %d > %d\n", freq, - radio->rangehigh); - r = -ERANGE; - goto err; - } - - dev_dbg(radio->dev, "%s: %dkHz\n", __func__, freq); - - core->write(core, WL1273_INT_MASK_SET, radio->irq_flags); - - if (radio->band == WL1273_BAND_JAPAN) - f = (freq - WL1273_BAND_JAPAN_LOW) / 50; - else - f = (freq - WL1273_BAND_OTHER_LOW) / 50; - - r = core->write(core, WL1273_FREQ_SET, f); - if (r) { - dev_err(radio->dev, "FREQ_SET fails\n"); - goto err; - } - - r = core->write(core, WL1273_TUNER_MODE_SET, TUNER_MODE_PRESET); - if (r) { - dev_err(radio->dev, "TUNER_MODE_SET fails\n"); - goto err; - } - - reinit_completion(&radio->busy); - - t = wait_for_completion_timeout(&radio->busy, msecs_to_jiffies(2000)); - if (!t) { - dev_err(radio->dev, "%s: TIMEOUT\n", __func__); - return -ETIMEDOUT; - } - - radio->rd_index = 0; - radio->wr_index = 0; - radio->rx_frequency = freq; - return 0; -err: - return r; -} - -static int wl1273_fm_get_freq(struct wl1273_device *radio) -{ - struct wl1273_core *core = radio->core; - unsigned int freq; - u16 f; - int r; - - if (core->mode == WL1273_MODE_RX) { - r = core->read(core, WL1273_FREQ_SET, &f); - if (r) - return r; - - dev_dbg(radio->dev, "Freq get: 0x%04x\n", f); - if (radio->band == WL1273_BAND_JAPAN) - freq = WL1273_BAND_JAPAN_LOW + 50 * f; - else - freq = WL1273_BAND_OTHER_LOW + 50 * f; - } else { - r = core->read(core, WL1273_CHANL_SET, &f); - if (r) - return r; - - freq = f * 10; - } - - return freq; -} - -/** - * wl1273_fm_upload_firmware_patch() - Upload the firmware. - * @radio: A pointer to the device struct. - * - * The firmware file consists of arrays of bytes where the first byte - * gives the array length. The first byte in the file gives the - * number of these arrays. - */ -static int wl1273_fm_upload_firmware_patch(struct wl1273_device *radio) -{ - struct wl1273_core *core = radio->core; - unsigned int packet_num; - const struct firmware *fw_p; - const char *fw_name = "radio-wl1273-fw.bin"; - struct device *dev = radio->dev; - __u8 *ptr; - int r; - - dev_dbg(dev, "%s:\n", __func__); - - /* - * Uploading the firmware patch is not always necessary, - * so we only print an info message. - */ - if (request_firmware(&fw_p, fw_name, dev)) { - dev_info(dev, "%s - %s not found\n", __func__, fw_name); - - return 0; - } - - ptr = (__u8 *) fw_p->data; - packet_num = ptr[0]; - dev_dbg(dev, "%s: packets: %d\n", __func__, packet_num); - - r = wl1273_fm_write_fw(core, ptr + 1, packet_num); - if (r) { - dev_err(dev, "FW upload error: %d\n", r); - goto out; - } - - /* ignore possible error here */ - core->write(core, WL1273_RESET, 0); - - dev_dbg(dev, "%s - download OK, r: %d\n", __func__, r); -out: - release_firmware(fw_p); - return r; -} - -static int wl1273_fm_stop(struct wl1273_device *radio) -{ - struct wl1273_core *core = radio->core; - - if (core->mode == WL1273_MODE_RX) { - int r = core->write(core, WL1273_POWER_SET, - WL1273_POWER_SET_OFF); - if (r) - dev_err(radio->dev, "%s: POWER_SET fails: %d\n", - __func__, r); - } else if (core->mode == WL1273_MODE_TX) { - int r = core->write(core, WL1273_PUPD_SET, - WL1273_PUPD_SET_OFF); - if (r) - dev_err(radio->dev, - "%s: PUPD_SET fails: %d\n", __func__, r); - } - - if (core->pdata->disable) { - core->pdata->disable(); - dev_dbg(radio->dev, "Back to reset\n"); - } - - return 0; -} - -static int wl1273_fm_start(struct wl1273_device *radio, int new_mode) -{ - struct wl1273_core *core = radio->core; - struct wl1273_fm_platform_data *pdata = core->pdata; - struct device *dev = radio->dev; - int r = -EINVAL; - - if (pdata->enable && core->mode == WL1273_MODE_OFF) { - dev_dbg(radio->dev, "Out of reset\n"); - - pdata->enable(); - msleep(250); - } - - if (new_mode == WL1273_MODE_RX) { - u16 val = WL1273_POWER_SET_FM; - - if (radio->rds_on) - val |= WL1273_POWER_SET_RDS; - - /* If this fails try again */ - r = core->write(core, WL1273_POWER_SET, val); - if (r) { - msleep(100); - - r = core->write(core, WL1273_POWER_SET, val); - if (r) { - dev_err(dev, "%s: POWER_SET fails\n", __func__); - goto fail; - } - } - - /* rds buffer configuration */ - radio->wr_index = 0; - radio->rd_index = 0; - - } else if (new_mode == WL1273_MODE_TX) { - /* If this fails try again once */ - r = core->write(core, WL1273_PUPD_SET, WL1273_PUPD_SET_ON); - if (r) { - msleep(100); - r = core->write(core, WL1273_PUPD_SET, - WL1273_PUPD_SET_ON); - if (r) { - dev_err(dev, "%s: PUPD_SET fails\n", __func__); - goto fail; - } - } - - if (radio->rds_on) { - r = core->write(core, WL1273_RDS_DATA_ENB, 1); - if (r) { - dev_err(dev, "%s: RDS_DATA_ENB ON fails\n", - __func__); - goto fail; - } - } else { - r = core->write(core, WL1273_RDS_DATA_ENB, 0); - if (r) { - dev_err(dev, "%s: RDS_DATA_ENB OFF fails\n", - __func__); - goto fail; - } - } - } else { - dev_warn(dev, "%s: Illegal mode.\n", __func__); - } - - if (core->mode == WL1273_MODE_OFF) { - r = wl1273_fm_upload_firmware_patch(radio); - if (r) - dev_warn(dev, "Firmware upload failed.\n"); - - /* - * Sometimes the chip is in a wrong power state at this point. - * So we set the power once again. - */ - if (new_mode == WL1273_MODE_RX) { - u16 val = WL1273_POWER_SET_FM; - - if (radio->rds_on) - val |= WL1273_POWER_SET_RDS; - - r = core->write(core, WL1273_POWER_SET, val); - if (r) { - dev_err(dev, "%s: POWER_SET fails\n", __func__); - goto fail; - } - } else if (new_mode == WL1273_MODE_TX) { - r = core->write(core, WL1273_PUPD_SET, - WL1273_PUPD_SET_ON); - if (r) { - dev_err(dev, "%s: PUPD_SET fails\n", __func__); - goto fail; - } - } - } - - return 0; -fail: - if (pdata->disable) - pdata->disable(); - - dev_dbg(dev, "%s: return: %d\n", __func__, r); - return r; -} - -static int wl1273_fm_suspend(struct wl1273_device *radio) -{ - struct wl1273_core *core = radio->core; - int r; - - /* Cannot go from OFF to SUSPENDED */ - if (core->mode == WL1273_MODE_RX) - r = core->write(core, WL1273_POWER_SET, - WL1273_POWER_SET_RETENTION); - else if (core->mode == WL1273_MODE_TX) - r = core->write(core, WL1273_PUPD_SET, - WL1273_PUPD_SET_RETENTION); - else - r = -EINVAL; - - if (r) { - dev_err(radio->dev, "%s: POWER_SET fails: %d\n", __func__, r); - goto out; - } - -out: - return r; -} - -static int wl1273_fm_set_mode(struct wl1273_device *radio, int mode) -{ - struct wl1273_core *core = radio->core; - struct device *dev = radio->dev; - int old_mode; - int r; - - dev_dbg(dev, "%s\n", __func__); - dev_dbg(dev, "Forbidden modes: 0x%02x\n", radio->forbidden); - - old_mode = core->mode; - if (mode & radio->forbidden) { - r = -EPERM; - goto out; - } - - switch (mode) { - case WL1273_MODE_RX: - case WL1273_MODE_TX: - r = wl1273_fm_start(radio, mode); - if (r) { - dev_err(dev, "%s: Cannot start.\n", __func__); - wl1273_fm_stop(radio); - goto out; - } - - core->mode = mode; - r = core->write(core, WL1273_INT_MASK_SET, radio->irq_flags); - if (r) { - dev_err(dev, "INT_MASK_SET fails.\n"); - goto out; - } - - /* remember previous settings */ - if (mode == WL1273_MODE_RX) { - r = wl1273_fm_set_rx_freq(radio, radio->rx_frequency); - if (r) { - dev_err(dev, "set freq fails: %d.\n", r); - goto out; - } - - r = core->set_volume(core, core->volume); - if (r) { - dev_err(dev, "set volume fails: %d.\n", r); - goto out; - } - - dev_dbg(dev, "%s: Set vol: %d.\n", __func__, - core->volume); - } else { - r = wl1273_fm_set_tx_freq(radio, radio->tx_frequency); - if (r) { - dev_err(dev, "set freq fails: %d.\n", r); - goto out; - } - } - - dev_dbg(radio->dev, "%s: Set audio mode.\n", __func__); - - r = core->set_audio(core, core->audio_mode); - if (r) - dev_err(dev, "Cannot set audio mode.\n"); - break; - - case WL1273_MODE_OFF: - r = wl1273_fm_stop(radio); - if (r) - dev_err(dev, "%s: Off fails: %d\n", __func__, r); - else - core->mode = WL1273_MODE_OFF; - - break; - - case WL1273_MODE_SUSPENDED: - r = wl1273_fm_suspend(radio); - if (r) - dev_err(dev, "%s: Suspend fails: %d\n", __func__, r); - else - core->mode = WL1273_MODE_SUSPENDED; - - break; - - default: - dev_err(dev, "%s: Unknown mode: %d\n", __func__, mode); - r = -EINVAL; - break; - } -out: - if (r) - core->mode = old_mode; - - return r; -} - -static int wl1273_fm_set_seek(struct wl1273_device *radio, - unsigned int wrap_around, - unsigned int seek_upward, - int level) -{ - struct wl1273_core *core = radio->core; - int r = 0; - unsigned int dir = (seek_upward == 0) ? 0 : 1; - unsigned int f; - - f = radio->rx_frequency; - dev_dbg(radio->dev, "rx_frequency: %d\n", f); - - if (dir && f + radio->spacing <= radio->rangehigh) - r = wl1273_fm_set_rx_freq(radio, f + radio->spacing); - else if (dir && wrap_around) - r = wl1273_fm_set_rx_freq(radio, radio->rangelow); - else if (f - radio->spacing >= radio->rangelow) - r = wl1273_fm_set_rx_freq(radio, f - radio->spacing); - else if (wrap_around) - r = wl1273_fm_set_rx_freq(radio, radio->rangehigh); - - if (r) - goto out; - - if (level < SCHAR_MIN || level > SCHAR_MAX) - return -EINVAL; - - reinit_completion(&radio->busy); - dev_dbg(radio->dev, "%s: BUSY\n", __func__); - - r = core->write(core, WL1273_INT_MASK_SET, radio->irq_flags); - if (r) - goto out; - - dev_dbg(radio->dev, "%s\n", __func__); - - r = core->write(core, WL1273_SEARCH_LVL_SET, level); - if (r) - goto out; - - r = core->write(core, WL1273_SEARCH_DIR_SET, dir); - if (r) - goto out; - - r = core->write(core, WL1273_TUNER_MODE_SET, TUNER_MODE_AUTO_SEEK); - if (r) - goto out; - - /* wait for the FR IRQ */ - wait_for_completion_timeout(&radio->busy, msecs_to_jiffies(1000)); - if (!(radio->irq_received & WL1273_BL_EVENT)) { - r = -ETIMEDOUT; - goto out; - } - - radio->irq_received &= ~WL1273_BL_EVENT; - - if (!wrap_around) - goto out; - - /* Wrap around */ - dev_dbg(radio->dev, "Wrap around in HW seek.\n"); - - if (seek_upward) - f = radio->rangelow; - else - f = radio->rangehigh; - - r = wl1273_fm_set_rx_freq(radio, f); - if (r) - goto out; - - reinit_completion(&radio->busy); - dev_dbg(radio->dev, "%s: BUSY\n", __func__); - - r = core->write(core, WL1273_TUNER_MODE_SET, TUNER_MODE_AUTO_SEEK); - if (r) - goto out; - - /* wait for the FR IRQ */ - if (!wait_for_completion_timeout(&radio->busy, msecs_to_jiffies(1000))) - r = -ETIMEDOUT; -out: - dev_dbg(radio->dev, "%s: Err: %d\n", __func__, r); - return r; -} - -/** - * wl1273_fm_get_tx_ctune() - Get the TX tuning capacitor value. - * @radio: A pointer to the device struct. - */ -static unsigned int wl1273_fm_get_tx_ctune(struct wl1273_device *radio) -{ - struct wl1273_core *core = radio->core; - struct device *dev = radio->dev; - u16 val; - int r; - - if (core->mode == WL1273_MODE_OFF || - core->mode == WL1273_MODE_SUSPENDED) - return -EPERM; - - r = core->read(core, WL1273_READ_FMANT_TUNE_VALUE, &val); - if (r) { - dev_err(dev, "%s: read error: %d\n", __func__, r); - goto out; - } - -out: - return val; -} - -/** - * wl1273_fm_set_preemphasis() - Set the TX pre-emphasis value. - * @radio: A pointer to the device struct. - * @preemphasis: The new pre-amphasis value. - * - * Possible pre-emphasis values are: V4L2_PREEMPHASIS_DISABLED, - * V4L2_PREEMPHASIS_50_uS and V4L2_PREEMPHASIS_75_uS. - */ -static int wl1273_fm_set_preemphasis(struct wl1273_device *radio, - unsigned int preemphasis) -{ - struct wl1273_core *core = radio->core; - int r; - u16 em; - - if (core->mode == WL1273_MODE_OFF || - core->mode == WL1273_MODE_SUSPENDED) - return -EPERM; - - mutex_lock(&core->lock); - - switch (preemphasis) { - case V4L2_PREEMPHASIS_DISABLED: - em = 1; - break; - case V4L2_PREEMPHASIS_50_uS: - em = 0; - break; - case V4L2_PREEMPHASIS_75_uS: - em = 2; - break; - default: - r = -EINVAL; - goto out; - } - - r = core->write(core, WL1273_PREMPH_SET, em); - if (r) - goto out; - - radio->preemphasis = preemphasis; - -out: - mutex_unlock(&core->lock); - return r; -} - -static int wl1273_fm_rds_on(struct wl1273_device *radio) -{ - struct wl1273_core *core = radio->core; - int r; - - dev_dbg(radio->dev, "%s\n", __func__); - if (radio->rds_on) - return 0; - - r = core->write(core, WL1273_POWER_SET, - WL1273_POWER_SET_FM | WL1273_POWER_SET_RDS); - if (r) - goto out; - - r = wl1273_fm_set_rx_freq(radio, radio->rx_frequency); - if (r) - dev_err(radio->dev, "set freq fails: %d.\n", r); -out: - return r; -} - -static int wl1273_fm_rds_off(struct wl1273_device *radio) -{ - struct wl1273_core *core = radio->core; - int r; - - if (!radio->rds_on) - return 0; - - radio->irq_flags &= ~WL1273_RDS_EVENT; - - r = core->write(core, WL1273_INT_MASK_SET, radio->irq_flags); - if (r) - goto out; - - /* Service pending read */ - wake_up_interruptible(&radio->read_queue); - - dev_dbg(radio->dev, "%s\n", __func__); - - r = core->write(core, WL1273_POWER_SET, WL1273_POWER_SET_FM); - if (r) - goto out; - - r = wl1273_fm_set_rx_freq(radio, radio->rx_frequency); - if (r) - dev_err(radio->dev, "set freq fails: %d.\n", r); -out: - dev_dbg(radio->dev, "%s: exiting...\n", __func__); - - return r; -} - -static int wl1273_fm_set_rds(struct wl1273_device *radio, unsigned int new_mode) -{ - int r = 0; - struct wl1273_core *core = radio->core; - - if (core->mode == WL1273_MODE_OFF || - core->mode == WL1273_MODE_SUSPENDED) - return -EPERM; - - if (new_mode == WL1273_RDS_RESET) { - r = core->write(core, WL1273_RDS_CNTRL_SET, 1); - return r; - } - - if (core->mode == WL1273_MODE_TX && new_mode == WL1273_RDS_OFF) { - r = core->write(core, WL1273_RDS_DATA_ENB, 0); - } else if (core->mode == WL1273_MODE_TX && new_mode == WL1273_RDS_ON) { - r = core->write(core, WL1273_RDS_DATA_ENB, 1); - } else if (core->mode == WL1273_MODE_RX && new_mode == WL1273_RDS_OFF) { - r = wl1273_fm_rds_off(radio); - } else if (core->mode == WL1273_MODE_RX && new_mode == WL1273_RDS_ON) { - r = wl1273_fm_rds_on(radio); - } else { - dev_err(radio->dev, "%s: Unknown mode: %d\n", - __func__, new_mode); - r = -EINVAL; - } - - if (!r) - radio->rds_on = new_mode == WL1273_RDS_ON; - - return r; -} - -static ssize_t wl1273_fm_fops_write(struct file *file, const char __user *buf, - size_t count, loff_t *ppos) -{ - struct wl1273_device *radio = video_get_drvdata(video_devdata(file)); - struct wl1273_core *core = radio->core; - u16 val; - int r; - - dev_dbg(radio->dev, "%s\n", __func__); - - if (core->mode != WL1273_MODE_TX) - return count; - - if (radio->rds_users == 0) { - dev_warn(radio->dev, "%s: RDS not on.\n", __func__); - return 0; - } - - if (mutex_lock_interruptible(&core->lock)) - return -EINTR; - /* - * Multiple processes can open the device, but only - * one gets to write to it. - */ - if (radio->owner && radio->owner != file) { - r = -EBUSY; - goto out; - } - radio->owner = file; - - /* Manual Mode */ - if (count > 255) - val = 255; - else - val = count; - - core->write(core, WL1273_RDS_CONFIG_DATA_SET, val); - - if (copy_from_user(radio->write_buf + 1, buf, val)) { - r = -EFAULT; - goto out; - } - - dev_dbg(radio->dev, "Count: %d\n", val); - dev_dbg(radio->dev, "From user: \"%s\"\n", radio->write_buf); - - radio->write_buf[0] = WL1273_RDS_DATA_SET; - core->write_data(core, radio->write_buf, val + 1); - - r = val; -out: - mutex_unlock(&core->lock); - - return r; -} - -static __poll_t wl1273_fm_fops_poll(struct file *file, - struct poll_table_struct *pts) -{ - struct wl1273_device *radio = video_get_drvdata(video_devdata(file)); - struct wl1273_core *core = radio->core; - - if (radio->owner && radio->owner != file) - return EPOLLERR; - - radio->owner = file; - - if (core->mode == WL1273_MODE_RX) { - poll_wait(file, &radio->read_queue, pts); - - if (radio->rd_index != radio->wr_index) - return EPOLLIN | EPOLLRDNORM; - - } else if (core->mode == WL1273_MODE_TX) { - return EPOLLOUT | EPOLLWRNORM; - } - - return 0; -} - -static int wl1273_fm_fops_open(struct file *file) -{ - struct wl1273_device *radio = video_get_drvdata(video_devdata(file)); - struct wl1273_core *core = radio->core; - int r = 0; - - dev_dbg(radio->dev, "%s\n", __func__); - - if (core->mode == WL1273_MODE_RX && radio->rds_on && - !radio->rds_users) { - dev_dbg(radio->dev, "%s: Mode: %d\n", __func__, core->mode); - - if (mutex_lock_interruptible(&core->lock)) - return -EINTR; - - radio->irq_flags |= WL1273_RDS_EVENT; - - r = core->write(core, WL1273_INT_MASK_SET, - radio->irq_flags); - if (r) { - mutex_unlock(&core->lock); - goto out; - } - - radio->rds_users++; - - mutex_unlock(&core->lock); - } -out: - return r; -} - -static int wl1273_fm_fops_release(struct file *file) -{ - struct wl1273_device *radio = video_get_drvdata(video_devdata(file)); - struct wl1273_core *core = radio->core; - int r = 0; - - dev_dbg(radio->dev, "%s\n", __func__); - - if (radio->rds_users > 0) { - radio->rds_users--; - if (radio->rds_users == 0) { - mutex_lock(&core->lock); - - radio->irq_flags &= ~WL1273_RDS_EVENT; - - if (core->mode == WL1273_MODE_RX) { - r = core->write(core, - WL1273_INT_MASK_SET, - radio->irq_flags); - if (r) { - mutex_unlock(&core->lock); - goto out; - } - } - mutex_unlock(&core->lock); - } - } - - if (file == radio->owner) - radio->owner = NULL; -out: - return r; -} - -static ssize_t wl1273_fm_fops_read(struct file *file, char __user *buf, - size_t count, loff_t *ppos) -{ - int r = 0; - struct wl1273_device *radio = video_get_drvdata(video_devdata(file)); - struct wl1273_core *core = radio->core; - unsigned int block_count = 0; - u16 val; - - dev_dbg(radio->dev, "%s\n", __func__); - - if (core->mode != WL1273_MODE_RX) - return 0; - - if (radio->rds_users == 0) { - dev_warn(radio->dev, "%s: RDS not on.\n", __func__); - return 0; - } - - if (mutex_lock_interruptible(&core->lock)) - return -EINTR; - - /* - * Multiple processes can open the device, but only - * one at a time gets read access. - */ - if (radio->owner && radio->owner != file) { - r = -EBUSY; - goto out; - } - radio->owner = file; - - r = core->read(core, WL1273_RDS_SYNC_GET, &val); - if (r) { - dev_err(radio->dev, "%s: Get RDS_SYNC fails.\n", __func__); - goto out; - } else if (val == 0) { - dev_info(radio->dev, "RDS_SYNC: Not synchronized\n"); - r = -ENODATA; - goto out; - } - - /* block if no new data available */ - while (radio->wr_index == radio->rd_index) { - if (file->f_flags & O_NONBLOCK) { - r = -EWOULDBLOCK; - goto out; - } - - dev_dbg(radio->dev, "%s: Wait for RDS data.\n", __func__); - if (wait_event_interruptible(radio->read_queue, - radio->wr_index != - radio->rd_index) < 0) { - r = -EINTR; - goto out; - } - } - - /* calculate block count from byte count */ - count /= RDS_BLOCK_SIZE; - - /* copy RDS blocks from the internal buffer and to user buffer */ - while (block_count < count) { - if (radio->rd_index == radio->wr_index) - break; - - /* always transfer complete RDS blocks */ - if (copy_to_user(buf, &radio->buffer[radio->rd_index], - RDS_BLOCK_SIZE)) - break; - - /* increment and wrap the read pointer */ - radio->rd_index += RDS_BLOCK_SIZE; - if (radio->rd_index >= radio->buf_size) - radio->rd_index = 0; - - /* increment counters */ - block_count++; - buf += RDS_BLOCK_SIZE; - r += RDS_BLOCK_SIZE; - } - -out: - dev_dbg(radio->dev, "%s: exit\n", __func__); - mutex_unlock(&core->lock); - - return r; -} - -static const struct v4l2_file_operations wl1273_fops = { - .owner = THIS_MODULE, - .read = wl1273_fm_fops_read, - .write = wl1273_fm_fops_write, - .poll = wl1273_fm_fops_poll, - .unlocked_ioctl = video_ioctl2, - .open = wl1273_fm_fops_open, - .release = wl1273_fm_fops_release, -}; - -static int wl1273_fm_vidioc_querycap(struct file *file, void *priv, - struct v4l2_capability *capability) -{ - struct wl1273_device *radio = video_get_drvdata(video_devdata(file)); - - dev_dbg(radio->dev, "%s\n", __func__); - - strscpy(capability->driver, WL1273_FM_DRIVER_NAME, - sizeof(capability->driver)); - strscpy(capability->card, "TI Wl1273 FM Radio", - sizeof(capability->card)); - strscpy(capability->bus_info, radio->bus_type, - sizeof(capability->bus_info)); - return 0; -} - -static int wl1273_fm_vidioc_g_input(struct file *file, void *priv, - unsigned int *i) -{ - struct wl1273_device *radio = video_get_drvdata(video_devdata(file)); - - dev_dbg(radio->dev, "%s\n", __func__); - - *i = 0; - - return 0; -} - -static int wl1273_fm_vidioc_s_input(struct file *file, void *priv, - unsigned int i) -{ - struct wl1273_device *radio = video_get_drvdata(video_devdata(file)); - - dev_dbg(radio->dev, "%s\n", __func__); - - if (i != 0) - return -EINVAL; - - return 0; -} - -/** - * wl1273_fm_set_tx_power() - Set the transmission power value. - * @radio: A pointer to the device struct. - * @power: The new power value. - */ -static int wl1273_fm_set_tx_power(struct wl1273_device *radio, u16 power) -{ - struct wl1273_core *core = radio->core; - int r; - - if (core->mode == WL1273_MODE_OFF || - core->mode == WL1273_MODE_SUSPENDED) - return -EPERM; - - mutex_lock(&core->lock); - - /* Convert the dBuV value to chip presentation */ - r = core->write(core, WL1273_POWER_LEV_SET, 122 - power); - if (r) - goto out; - - radio->tx_power = power; - -out: - mutex_unlock(&core->lock); - return r; -} - -#define WL1273_SPACING_50kHz 1 -#define WL1273_SPACING_100kHz 2 -#define WL1273_SPACING_200kHz 4 - -static int wl1273_fm_tx_set_spacing(struct wl1273_device *radio, - unsigned int spacing) -{ - struct wl1273_core *core = radio->core; - int r; - - if (spacing == 0) { - r = core->write(core, WL1273_SCAN_SPACING_SET, - WL1273_SPACING_100kHz); - radio->spacing = 100; - } else if (spacing - 50000 < 25000) { - r = core->write(core, WL1273_SCAN_SPACING_SET, - WL1273_SPACING_50kHz); - radio->spacing = 50; - } else if (spacing - 100000 < 50000) { - r = core->write(core, WL1273_SCAN_SPACING_SET, - WL1273_SPACING_100kHz); - radio->spacing = 100; - } else { - r = core->write(core, WL1273_SCAN_SPACING_SET, - WL1273_SPACING_200kHz); - radio->spacing = 200; - } - - return r; -} - -static int wl1273_fm_g_volatile_ctrl(struct v4l2_ctrl *ctrl) -{ - struct wl1273_device *radio = ctrl->priv; - struct wl1273_core *core = radio->core; - - dev_dbg(radio->dev, "%s\n", __func__); - - if (mutex_lock_interruptible(&core->lock)) - return -EINTR; - - switch (ctrl->id) { - case V4L2_CID_TUNE_ANTENNA_CAPACITOR: - ctrl->val = wl1273_fm_get_tx_ctune(radio); - break; - - default: - dev_warn(radio->dev, "%s: Unknown IOCTL: %d\n", - __func__, ctrl->id); - break; - } - - mutex_unlock(&core->lock); - - return 0; -} - -#define WL1273_MUTE_SOFT_ENABLE (1 << 0) -#define WL1273_MUTE_AC (1 << 1) -#define WL1273_MUTE_HARD_LEFT (1 << 2) -#define WL1273_MUTE_HARD_RIGHT (1 << 3) -#define WL1273_MUTE_SOFT_FORCE (1 << 4) - -static inline struct wl1273_device *to_radio(struct v4l2_ctrl *ctrl) -{ - return container_of(ctrl->handler, struct wl1273_device, ctrl_handler); -} - -static int wl1273_fm_s_ctrl(struct v4l2_ctrl *ctrl) -{ - struct wl1273_device *radio = to_radio(ctrl); - struct wl1273_core *core = radio->core; - int r = 0; - - dev_dbg(radio->dev, "%s\n", __func__); - - switch (ctrl->id) { - case V4L2_CID_AUDIO_MUTE: - if (mutex_lock_interruptible(&core->lock)) - return -EINTR; - - if (core->mode == WL1273_MODE_RX && ctrl->val) - r = core->write(core, - WL1273_MUTE_STATUS_SET, - WL1273_MUTE_HARD_LEFT | - WL1273_MUTE_HARD_RIGHT); - else if (core->mode == WL1273_MODE_RX) - r = core->write(core, - WL1273_MUTE_STATUS_SET, 0x0); - else if (core->mode == WL1273_MODE_TX && ctrl->val) - r = core->write(core, WL1273_MUTE, 1); - else if (core->mode == WL1273_MODE_TX) - r = core->write(core, WL1273_MUTE, 0); - - mutex_unlock(&core->lock); - break; - - case V4L2_CID_AUDIO_VOLUME: - if (ctrl->val == 0) - r = wl1273_fm_set_mode(radio, WL1273_MODE_OFF); - else - r = core->set_volume(core, core->volume); - break; - - case V4L2_CID_TUNE_PREEMPHASIS: - r = wl1273_fm_set_preemphasis(radio, ctrl->val); - break; - - case V4L2_CID_TUNE_POWER_LEVEL: - r = wl1273_fm_set_tx_power(radio, ctrl->val); - break; - - default: - dev_warn(radio->dev, "%s: Unknown IOCTL: %d\n", - __func__, ctrl->id); - break; - } - - dev_dbg(radio->dev, "%s\n", __func__); - return r; -} - -static int wl1273_fm_vidioc_g_audio(struct file *file, void *priv, - struct v4l2_audio *audio) -{ - struct wl1273_device *radio = video_get_drvdata(video_devdata(file)); - - dev_dbg(radio->dev, "%s\n", __func__); - - if (audio->index > 1) - return -EINVAL; - - strscpy(audio->name, "Radio", sizeof(audio->name)); - audio->capability = V4L2_AUDCAP_STEREO; - - return 0; -} - -static int wl1273_fm_vidioc_s_audio(struct file *file, void *priv, - const struct v4l2_audio *audio) -{ - struct wl1273_device *radio = video_get_drvdata(video_devdata(file)); - - dev_dbg(radio->dev, "%s\n", __func__); - - if (audio->index != 0) - return -EINVAL; - - return 0; -} - -#define WL1273_RDS_NOT_SYNCHRONIZED 0 -#define WL1273_RDS_SYNCHRONIZED 1 - -static int wl1273_fm_vidioc_g_tuner(struct file *file, void *priv, - struct v4l2_tuner *tuner) -{ - struct wl1273_device *radio = video_get_drvdata(video_devdata(file)); - struct wl1273_core *core = radio->core; - u16 val; - int r; - - dev_dbg(radio->dev, "%s\n", __func__); - - if (tuner->index > 0) - return -EINVAL; - - strscpy(tuner->name, WL1273_FM_DRIVER_NAME, sizeof(tuner->name)); - tuner->type = V4L2_TUNER_RADIO; - - tuner->rangelow = WL1273_FREQ(WL1273_BAND_JAPAN_LOW); - tuner->rangehigh = WL1273_FREQ(WL1273_BAND_OTHER_HIGH); - - tuner->capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_RDS | - V4L2_TUNER_CAP_STEREO | V4L2_TUNER_CAP_RDS_BLOCK_IO | - V4L2_TUNER_CAP_HWSEEK_BOUNDED | V4L2_TUNER_CAP_HWSEEK_WRAP; - - if (radio->stereo) - tuner->audmode = V4L2_TUNER_MODE_STEREO; - else - tuner->audmode = V4L2_TUNER_MODE_MONO; - - if (core->mode != WL1273_MODE_RX) - return 0; - - if (mutex_lock_interruptible(&core->lock)) - return -EINTR; - - r = core->read(core, WL1273_STEREO_GET, &val); - if (r) - goto out; - - if (val == 1) - tuner->rxsubchans = V4L2_TUNER_SUB_STEREO; - else - tuner->rxsubchans = V4L2_TUNER_SUB_MONO; - - r = core->read(core, WL1273_RSSI_LVL_GET, &val); - if (r) - goto out; - - tuner->signal = (s16) val; - dev_dbg(radio->dev, "Signal: %d\n", tuner->signal); - - tuner->afc = 0; - - r = core->read(core, WL1273_RDS_SYNC_GET, &val); - if (r) - goto out; - - if (val == WL1273_RDS_SYNCHRONIZED) - tuner->rxsubchans |= V4L2_TUNER_SUB_RDS; -out: - mutex_unlock(&core->lock); - - return r; -} - -static int wl1273_fm_vidioc_s_tuner(struct file *file, void *priv, - const struct v4l2_tuner *tuner) -{ - struct wl1273_device *radio = video_get_drvdata(video_devdata(file)); - struct wl1273_core *core = radio->core; - int r = 0; - - dev_dbg(radio->dev, "%s\n", __func__); - dev_dbg(radio->dev, "tuner->index: %d\n", tuner->index); - dev_dbg(radio->dev, "tuner->name: %s\n", tuner->name); - dev_dbg(radio->dev, "tuner->capability: 0x%04x\n", tuner->capability); - dev_dbg(radio->dev, "tuner->rxsubchans: 0x%04x\n", tuner->rxsubchans); - dev_dbg(radio->dev, "tuner->rangelow: %d\n", tuner->rangelow); - dev_dbg(radio->dev, "tuner->rangehigh: %d\n", tuner->rangehigh); - - if (tuner->index > 0) - return -EINVAL; - - if (mutex_lock_interruptible(&core->lock)) - return -EINTR; - - r = wl1273_fm_set_mode(radio, WL1273_MODE_RX); - if (r) - goto out; - - if (tuner->rxsubchans & V4L2_TUNER_SUB_RDS) - r = wl1273_fm_set_rds(radio, WL1273_RDS_ON); - else - r = wl1273_fm_set_rds(radio, WL1273_RDS_OFF); - - if (r) - dev_warn(radio->dev, "%s: RDS fails: %d\n", __func__, r); - - if (tuner->audmode == V4L2_TUNER_MODE_MONO) { - r = core->write(core, WL1273_MOST_MODE_SET, WL1273_RX_MONO); - if (r < 0) { - dev_warn(radio->dev, "%s: MOST_MODE fails: %d\n", - __func__, r); - goto out; - } - radio->stereo = false; - } else if (tuner->audmode == V4L2_TUNER_MODE_STEREO) { - r = core->write(core, WL1273_MOST_MODE_SET, WL1273_RX_STEREO); - if (r < 0) { - dev_warn(radio->dev, "%s: MOST_MODE fails: %d\n", - __func__, r); - goto out; - } - radio->stereo = true; - } else { - dev_err(radio->dev, "%s: tuner->audmode: %d\n", - __func__, tuner->audmode); - r = -EINVAL; - goto out; - } - -out: - mutex_unlock(&core->lock); - - return r; -} - -static int wl1273_fm_vidioc_g_frequency(struct file *file, void *priv, - struct v4l2_frequency *freq) -{ - struct wl1273_device *radio = video_get_drvdata(video_devdata(file)); - struct wl1273_core *core = radio->core; - - dev_dbg(radio->dev, "%s\n", __func__); - - if (mutex_lock_interruptible(&core->lock)) - return -EINTR; - - freq->type = V4L2_TUNER_RADIO; - freq->frequency = WL1273_FREQ(wl1273_fm_get_freq(radio)); - - mutex_unlock(&core->lock); - - return 0; -} - -static int wl1273_fm_vidioc_s_frequency(struct file *file, void *priv, - const struct v4l2_frequency *freq) -{ - struct wl1273_device *radio = video_get_drvdata(video_devdata(file)); - struct wl1273_core *core = radio->core; - int r; - - dev_dbg(radio->dev, "%s: %d\n", __func__, freq->frequency); - - if (freq->type != V4L2_TUNER_RADIO) { - dev_dbg(radio->dev, - "freq->type != V4L2_TUNER_RADIO: %d\n", freq->type); - return -EINVAL; - } - - if (mutex_lock_interruptible(&core->lock)) - return -EINTR; - - if (core->mode == WL1273_MODE_RX) { - dev_dbg(radio->dev, "freq: %d\n", freq->frequency); - - r = wl1273_fm_set_rx_freq(radio, - WL1273_INV_FREQ(freq->frequency)); - if (r) - dev_warn(radio->dev, WL1273_FM_DRIVER_NAME - ": set frequency failed with %d\n", r); - } else { - r = wl1273_fm_set_tx_freq(radio, - WL1273_INV_FREQ(freq->frequency)); - if (r) - dev_warn(radio->dev, WL1273_FM_DRIVER_NAME - ": set frequency failed with %d\n", r); - } - - mutex_unlock(&core->lock); - - dev_dbg(radio->dev, "wl1273_vidioc_s_frequency: DONE\n"); - return r; -} - -#define WL1273_DEFAULT_SEEK_LEVEL 7 - -static int wl1273_fm_vidioc_s_hw_freq_seek(struct file *file, void *priv, - const struct v4l2_hw_freq_seek *seek) -{ - struct wl1273_device *radio = video_get_drvdata(video_devdata(file)); - struct wl1273_core *core = radio->core; - int r; - - dev_dbg(radio->dev, "%s\n", __func__); - - if (seek->tuner != 0 || seek->type != V4L2_TUNER_RADIO) - return -EINVAL; - - if (file->f_flags & O_NONBLOCK) - return -EWOULDBLOCK; - - if (mutex_lock_interruptible(&core->lock)) - return -EINTR; - - r = wl1273_fm_set_mode(radio, WL1273_MODE_RX); - if (r) - goto out; - - r = wl1273_fm_tx_set_spacing(radio, seek->spacing); - if (r) - dev_warn(radio->dev, "HW seek failed: %d\n", r); - - r = wl1273_fm_set_seek(radio, seek->wrap_around, seek->seek_upward, - WL1273_DEFAULT_SEEK_LEVEL); - if (r) - dev_warn(radio->dev, "HW seek failed: %d\n", r); - -out: - mutex_unlock(&core->lock); - return r; -} - -static int wl1273_fm_vidioc_s_modulator(struct file *file, void *priv, - const struct v4l2_modulator *modulator) -{ - struct wl1273_device *radio = video_get_drvdata(video_devdata(file)); - struct wl1273_core *core = radio->core; - int r = 0; - - dev_dbg(radio->dev, "%s\n", __func__); - - if (modulator->index > 0) - return -EINVAL; - - if (mutex_lock_interruptible(&core->lock)) - return -EINTR; - - r = wl1273_fm_set_mode(radio, WL1273_MODE_TX); - if (r) - goto out; - - if (modulator->txsubchans & V4L2_TUNER_SUB_RDS) - r = wl1273_fm_set_rds(radio, WL1273_RDS_ON); - else - r = wl1273_fm_set_rds(radio, WL1273_RDS_OFF); - - if (modulator->txsubchans & V4L2_TUNER_SUB_MONO) - r = core->write(core, WL1273_MONO_SET, WL1273_TX_MONO); - else - r = core->write(core, WL1273_MONO_SET, - WL1273_RX_STEREO); - if (r < 0) - dev_warn(radio->dev, WL1273_FM_DRIVER_NAME - "MONO_SET fails: %d\n", r); -out: - mutex_unlock(&core->lock); - - return r; -} - -static int wl1273_fm_vidioc_g_modulator(struct file *file, void *priv, - struct v4l2_modulator *modulator) -{ - struct wl1273_device *radio = video_get_drvdata(video_devdata(file)); - struct wl1273_core *core = radio->core; - u16 val; - int r; - - dev_dbg(radio->dev, "%s\n", __func__); - - strscpy(modulator->name, WL1273_FM_DRIVER_NAME, - sizeof(modulator->name)); - - modulator->rangelow = WL1273_FREQ(WL1273_BAND_JAPAN_LOW); - modulator->rangehigh = WL1273_FREQ(WL1273_BAND_OTHER_HIGH); - - modulator->capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_RDS | - V4L2_TUNER_CAP_STEREO | V4L2_TUNER_CAP_RDS_BLOCK_IO; - - if (core->mode != WL1273_MODE_TX) - return 0; - - if (mutex_lock_interruptible(&core->lock)) - return -EINTR; - - r = core->read(core, WL1273_MONO_SET, &val); - if (r) - goto out; - - if (val == WL1273_TX_STEREO) - modulator->txsubchans = V4L2_TUNER_SUB_STEREO; - else - modulator->txsubchans = V4L2_TUNER_SUB_MONO; - - if (radio->rds_on) - modulator->txsubchans |= V4L2_TUNER_SUB_RDS; -out: - mutex_unlock(&core->lock); - - return 0; -} - -static int wl1273_fm_vidioc_log_status(struct file *file, void *priv) -{ - struct wl1273_device *radio = video_get_drvdata(video_devdata(file)); - struct wl1273_core *core = radio->core; - struct device *dev = radio->dev; - u16 val; - int r; - - dev_info(dev, DRIVER_DESC); - - if (core->mode == WL1273_MODE_OFF) { - dev_info(dev, "Mode: Off\n"); - return 0; - } - - if (core->mode == WL1273_MODE_SUSPENDED) { - dev_info(dev, "Mode: Suspended\n"); - return 0; - } - - r = core->read(core, WL1273_ASIC_ID_GET, &val); - if (r) - dev_err(dev, "%s: Get ASIC_ID fails.\n", __func__); - else - dev_info(dev, "ASIC_ID: 0x%04x\n", val); - - r = core->read(core, WL1273_ASIC_VER_GET, &val); - if (r) - dev_err(dev, "%s: Get ASIC_VER fails.\n", __func__); - else - dev_info(dev, "ASIC Version: 0x%04x\n", val); - - r = core->read(core, WL1273_FIRM_VER_GET, &val); - if (r) - dev_err(dev, "%s: Get FIRM_VER fails.\n", __func__); - else - dev_info(dev, "FW version: %d(0x%04x)\n", val, val); - - r = core->read(core, WL1273_BAND_SET, &val); - if (r) - dev_err(dev, "%s: Get BAND fails.\n", __func__); - else - dev_info(dev, "BAND: %d\n", val); - - if (core->mode == WL1273_MODE_TX) { - r = core->read(core, WL1273_PUPD_SET, &val); - if (r) - dev_err(dev, "%s: Get PUPD fails.\n", __func__); - else - dev_info(dev, "PUPD: 0x%04x\n", val); - - r = core->read(core, WL1273_CHANL_SET, &val); - if (r) - dev_err(dev, "%s: Get CHANL fails.\n", __func__); - else - dev_info(dev, "Tx frequency: %dkHz\n", val*10); - } else if (core->mode == WL1273_MODE_RX) { - int bf = radio->rangelow; - - r = core->read(core, WL1273_FREQ_SET, &val); - if (r) - dev_err(dev, "%s: Get FREQ fails.\n", __func__); - else - dev_info(dev, "RX Frequency: %dkHz\n", bf + val*50); - - r = core->read(core, WL1273_MOST_MODE_SET, &val); - if (r) - dev_err(dev, "%s: Get MOST_MODE fails.\n", - __func__); - else if (val == 0) - dev_info(dev, "MOST_MODE: Stereo according to blend\n"); - else if (val == 1) - dev_info(dev, "MOST_MODE: Force mono output\n"); - else - dev_info(dev, "MOST_MODE: Unexpected value: %d\n", val); - - r = core->read(core, WL1273_MOST_BLEND_SET, &val); - if (r) - dev_err(dev, "%s: Get MOST_BLEND fails.\n", __func__); - else if (val == 0) - dev_info(dev, - "MOST_BLEND: Switched blend & hysteresis.\n"); - else if (val == 1) - dev_info(dev, "MOST_BLEND: Soft blend.\n"); - else - dev_info(dev, "MOST_BLEND: Unexpected val: %d\n", val); - - r = core->read(core, WL1273_STEREO_GET, &val); - if (r) - dev_err(dev, "%s: Get STEREO fails.\n", __func__); - else if (val == 0) - dev_info(dev, "STEREO: Not detected\n"); - else if (val == 1) - dev_info(dev, "STEREO: Detected\n"); - else - dev_info(dev, "STEREO: Unexpected value: %d\n", val); - - r = core->read(core, WL1273_RSSI_LVL_GET, &val); - if (r) - dev_err(dev, "%s: Get RSSI_LVL fails.\n", __func__); - else - dev_info(dev, "RX signal strength: %d\n", (s16) val); - - r = core->read(core, WL1273_POWER_SET, &val); - if (r) - dev_err(dev, "%s: Get POWER fails.\n", __func__); - else - dev_info(dev, "POWER: 0x%04x\n", val); - - r = core->read(core, WL1273_INT_MASK_SET, &val); - if (r) - dev_err(dev, "%s: Get INT_MASK fails.\n", __func__); - else - dev_info(dev, "INT_MASK: 0x%04x\n", val); - - r = core->read(core, WL1273_RDS_SYNC_GET, &val); - if (r) - dev_err(dev, "%s: Get RDS_SYNC fails.\n", - __func__); - else if (val == 0) - dev_info(dev, "RDS_SYNC: Not synchronized\n"); - - else if (val == 1) - dev_info(dev, "RDS_SYNC: Synchronized\n"); - else - dev_info(dev, "RDS_SYNC: Unexpected value: %d\n", val); - - r = core->read(core, WL1273_I2S_MODE_CONFIG_SET, &val); - if (r) - dev_err(dev, "%s: Get I2S_MODE_CONFIG fails.\n", - __func__); - else - dev_info(dev, "I2S_MODE_CONFIG: 0x%04x\n", val); - - r = core->read(core, WL1273_VOLUME_SET, &val); - if (r) - dev_err(dev, "%s: Get VOLUME fails.\n", __func__); - else - dev_info(dev, "VOLUME: 0x%04x\n", val); - } - - return 0; -} - -static void wl1273_vdev_release(struct video_device *dev) -{ -} - -static const struct v4l2_ctrl_ops wl1273_ctrl_ops = { - .s_ctrl = wl1273_fm_s_ctrl, - .g_volatile_ctrl = wl1273_fm_g_volatile_ctrl, -}; - -static const struct v4l2_ioctl_ops wl1273_ioctl_ops = { - .vidioc_querycap = wl1273_fm_vidioc_querycap, - .vidioc_g_input = wl1273_fm_vidioc_g_input, - .vidioc_s_input = wl1273_fm_vidioc_s_input, - .vidioc_g_audio = wl1273_fm_vidioc_g_audio, - .vidioc_s_audio = wl1273_fm_vidioc_s_audio, - .vidioc_g_tuner = wl1273_fm_vidioc_g_tuner, - .vidioc_s_tuner = wl1273_fm_vidioc_s_tuner, - .vidioc_g_frequency = wl1273_fm_vidioc_g_frequency, - .vidioc_s_frequency = wl1273_fm_vidioc_s_frequency, - .vidioc_s_hw_freq_seek = wl1273_fm_vidioc_s_hw_freq_seek, - .vidioc_g_modulator = wl1273_fm_vidioc_g_modulator, - .vidioc_s_modulator = wl1273_fm_vidioc_s_modulator, - .vidioc_log_status = wl1273_fm_vidioc_log_status, -}; - -static const struct video_device wl1273_viddev_template = { - .fops = &wl1273_fops, - .ioctl_ops = &wl1273_ioctl_ops, - .name = WL1273_FM_DRIVER_NAME, - .release = wl1273_vdev_release, - .vfl_dir = VFL_DIR_TX, - .device_caps = V4L2_CAP_HW_FREQ_SEEK | V4L2_CAP_TUNER | - V4L2_CAP_RADIO | V4L2_CAP_AUDIO | - V4L2_CAP_RDS_CAPTURE | V4L2_CAP_MODULATOR | - V4L2_CAP_RDS_OUTPUT, -}; - -static void wl1273_fm_radio_remove(struct platform_device *pdev) -{ - struct wl1273_device *radio = platform_get_drvdata(pdev); - struct wl1273_core *core = radio->core; - - dev_info(&pdev->dev, "%s.\n", __func__); - - free_irq(core->client->irq, radio); - core->pdata->free_resources(); - - v4l2_ctrl_handler_free(&radio->ctrl_handler); - video_unregister_device(&radio->videodev); - v4l2_device_unregister(&radio->v4l2dev); -} - -static int wl1273_fm_radio_probe(struct platform_device *pdev) -{ - struct wl1273_core **core = pdev->dev.platform_data; - struct wl1273_device *radio; - struct v4l2_ctrl *ctrl; - int r = 0; - - pr_debug("%s\n", __func__); - - if (!core) { - dev_err(&pdev->dev, "No platform data.\n"); - r = -EINVAL; - goto pdata_err; - } - - radio = devm_kzalloc(&pdev->dev, sizeof(*radio), GFP_KERNEL); - if (!radio) { - r = -ENOMEM; - goto pdata_err; - } - - /* RDS buffer allocation */ - radio->buf_size = rds_buf * RDS_BLOCK_SIZE; - radio->buffer = devm_kzalloc(&pdev->dev, radio->buf_size, GFP_KERNEL); - if (!radio->buffer) { - pr_err("Cannot allocate memory for RDS buffer.\n"); - r = -ENOMEM; - goto pdata_err; - } - - radio->core = *core; - radio->irq_flags = WL1273_IRQ_MASK; - radio->dev = &radio->core->client->dev; - radio->rds_on = false; - radio->core->mode = WL1273_MODE_OFF; - radio->tx_power = 118; - radio->core->audio_mode = WL1273_AUDIO_ANALOG; - radio->band = WL1273_BAND_OTHER; - radio->core->i2s_mode = WL1273_I2S_DEF_MODE; - radio->core->channel_number = 2; - radio->core->volume = WL1273_DEFAULT_VOLUME; - radio->rx_frequency = WL1273_BAND_OTHER_LOW; - radio->tx_frequency = WL1273_BAND_OTHER_HIGH; - radio->rangelow = WL1273_BAND_OTHER_LOW; - radio->rangehigh = WL1273_BAND_OTHER_HIGH; - radio->stereo = true; - radio->bus_type = "I2C"; - - if (radio->core->pdata->request_resources) { - r = radio->core->pdata->request_resources(radio->core->client); - if (r) { - dev_err(radio->dev, WL1273_FM_DRIVER_NAME - ": Cannot get platform data\n"); - goto pdata_err; - } - - dev_dbg(radio->dev, "irq: %d\n", radio->core->client->irq); - - r = request_threaded_irq(radio->core->client->irq, NULL, - wl1273_fm_irq_thread_handler, - IRQF_ONESHOT | IRQF_TRIGGER_FALLING, - "wl1273-fm", radio); - if (r < 0) { - dev_err(radio->dev, WL1273_FM_DRIVER_NAME - ": Unable to register IRQ handler: %d\n", r); - goto err_request_irq; - } - } else { - dev_err(radio->dev, WL1273_FM_DRIVER_NAME ": Core WL1273 IRQ not configured"); - r = -EINVAL; - goto pdata_err; - } - - init_completion(&radio->busy); - init_waitqueue_head(&radio->read_queue); - - radio->write_buf = devm_kzalloc(&pdev->dev, 256, GFP_KERNEL); - if (!radio->write_buf) { - r = -ENOMEM; - goto write_buf_err; - } - - radio->dev = &pdev->dev; - radio->v4l2dev.ctrl_handler = &radio->ctrl_handler; - radio->rds_users = 0; - - r = v4l2_device_register(&pdev->dev, &radio->v4l2dev); - if (r) { - dev_err(&pdev->dev, "Cannot register v4l2_device.\n"); - goto write_buf_err; - } - - /* V4L2 configuration */ - radio->videodev = wl1273_viddev_template; - - radio->videodev.v4l2_dev = &radio->v4l2dev; - - v4l2_ctrl_handler_init(&radio->ctrl_handler, 6); - - /* add in ascending ID order */ - v4l2_ctrl_new_std(&radio->ctrl_handler, &wl1273_ctrl_ops, - V4L2_CID_AUDIO_VOLUME, 0, WL1273_MAX_VOLUME, 1, - WL1273_DEFAULT_VOLUME); - - v4l2_ctrl_new_std(&radio->ctrl_handler, &wl1273_ctrl_ops, - V4L2_CID_AUDIO_MUTE, 0, 1, 1, 1); - - v4l2_ctrl_new_std_menu(&radio->ctrl_handler, &wl1273_ctrl_ops, - V4L2_CID_TUNE_PREEMPHASIS, - V4L2_PREEMPHASIS_75_uS, 0x03, - V4L2_PREEMPHASIS_50_uS); - - v4l2_ctrl_new_std(&radio->ctrl_handler, &wl1273_ctrl_ops, - V4L2_CID_TUNE_POWER_LEVEL, 91, 122, 1, 118); - - ctrl = v4l2_ctrl_new_std(&radio->ctrl_handler, &wl1273_ctrl_ops, - V4L2_CID_TUNE_ANTENNA_CAPACITOR, - 0, 255, 1, 255); - if (ctrl) - ctrl->flags |= V4L2_CTRL_FLAG_VOLATILE; - - if (radio->ctrl_handler.error) { - r = radio->ctrl_handler.error; - dev_err(&pdev->dev, "Ctrl handler error: %d\n", r); - goto handler_init_err; - } - - video_set_drvdata(&radio->videodev, radio); - platform_set_drvdata(pdev, radio); - - /* register video device */ - r = video_register_device(&radio->videodev, VFL_TYPE_RADIO, radio_nr); - if (r) { - dev_err(&pdev->dev, WL1273_FM_DRIVER_NAME - ": Could not register video device\n"); - goto handler_init_err; - } - - return 0; - -handler_init_err: - v4l2_ctrl_handler_free(&radio->ctrl_handler); - v4l2_device_unregister(&radio->v4l2dev); -write_buf_err: - free_irq(radio->core->client->irq, radio); -err_request_irq: - radio->core->pdata->free_resources(); -pdata_err: - return r; -} - -static struct platform_driver wl1273_fm_radio_driver = { - .probe = wl1273_fm_radio_probe, - .remove = wl1273_fm_radio_remove, - .driver = { - .name = "wl1273_fm_radio", - }, -}; - -module_platform_driver(wl1273_fm_radio_driver); - -MODULE_AUTHOR("Matti Aaltonen <matti.j.aaltonen@nokia.com>"); -MODULE_DESCRIPTION(DRIVER_DESC); -MODULE_LICENSE("GPL"); -MODULE_ALIAS("platform:wl1273_fm_radio"); diff --git a/drivers/media/radio/radio-zoltrix.c b/drivers/media/radio/radio-zoltrix.c index 099b7af6a410..e043bee52384 100644 --- a/drivers/media/radio/radio-zoltrix.c +++ b/drivers/media/radio/radio-zoltrix.c @@ -30,7 +30,7 @@ * 2006-07-24 - Converted to V4L2 API * by Mauro Carvalho Chehab <mchehab@kernel.org> * - * Converted to the radio-isa framework by Hans Verkuil <hansverk@cisco.com> + * Converted to the radio-isa framework by Hans Verkuil <hverkuil@kernel.org> * * Note that this is the driver for the Zoltrix Radio Plus. * This driver does not work for the Zoltrix Radio Plus 108 or the diff --git a/drivers/media/radio/si4713/radio-platform-si4713.c b/drivers/media/radio/si4713/radio-platform-si4713.c index 67b4afadc95a..4132968110e3 100644 --- a/drivers/media/radio/si4713/radio-platform-si4713.c +++ b/drivers/media/radio/si4713/radio-platform-si4713.c @@ -75,35 +75,35 @@ static inline struct v4l2_device *get_v4l2_dev(struct file *file) return &((struct radio_si4713_device *)video_drvdata(file))->v4l2_dev; } -static int radio_si4713_g_modulator(struct file *file, void *p, +static int radio_si4713_g_modulator(struct file *file, void *priv, struct v4l2_modulator *vm) { return v4l2_device_call_until_err(get_v4l2_dev(file), 0, tuner, g_modulator, vm); } -static int radio_si4713_s_modulator(struct file *file, void *p, +static int radio_si4713_s_modulator(struct file *file, void *priv, const struct v4l2_modulator *vm) { return v4l2_device_call_until_err(get_v4l2_dev(file), 0, tuner, s_modulator, vm); } -static int radio_si4713_g_frequency(struct file *file, void *p, +static int radio_si4713_g_frequency(struct file *file, void *priv, struct v4l2_frequency *vf) { return v4l2_device_call_until_err(get_v4l2_dev(file), 0, tuner, g_frequency, vf); } -static int radio_si4713_s_frequency(struct file *file, void *p, +static int radio_si4713_s_frequency(struct file *file, void *priv, const struct v4l2_frequency *vf) { return v4l2_device_call_until_err(get_v4l2_dev(file), 0, tuner, s_frequency, vf); } -static long radio_si4713_default(struct file *file, void *p, +static long radio_si4713_default(struct file *file, void *priv, bool valid_prio, unsigned int cmd, void *arg) { return v4l2_device_call_until_err(get_v4l2_dev(file), 0, core, diff --git a/drivers/media/rc/imon.c b/drivers/media/rc/imon.c index f5221b018808..35b9e07003d8 100644 --- a/drivers/media/rc/imon.c +++ b/drivers/media/rc/imon.c @@ -39,11 +39,6 @@ #define DISPLAY_MINOR_BASE 144 #define DEVICE_NAME "lcd%d" -#define BUF_CHUNK_SIZE 8 -#define BUF_SIZE 128 - -#define BIT_DURATION 250 /* each bit received is 250us */ - #define IMON_CLOCK_ENABLE_PACKETS 2 /*** P R O T O T Y P E S ***/ @@ -536,7 +531,9 @@ static int display_open(struct inode *inode, struct file *file) mutex_lock(&ictx->lock); - if (!ictx->display_supported) { + if (ictx->disconnected) { + retval = -ENODEV; + } else if (!ictx->display_supported) { pr_err("display not supported by device\n"); retval = -ENODEV; } else if (ictx->display_isopen) { @@ -598,6 +595,11 @@ static int send_packet(struct imon_context *ictx) int retval = 0; struct usb_ctrlrequest *control_req = NULL; + lockdep_assert_held(&ictx->lock); + + if (ictx->disconnected) + return -ENODEV; + /* Check if we need to use control or interrupt urb */ if (!ictx->tx_control) { pipe = usb_sndintpipe(ictx->usbdev_intf0, @@ -645,12 +647,15 @@ static int send_packet(struct imon_context *ictx) smp_rmb(); /* ensure later readers know we're not busy */ pr_err_ratelimited("error submitting urb(%d)\n", retval); } else { - /* Wait for transmission to complete (or abort) */ - retval = wait_for_completion_interruptible( - &ictx->tx.finished); - if (retval) { + /* Wait for transmission to complete (or abort or timeout) */ + retval = wait_for_completion_interruptible_timeout(&ictx->tx.finished, 10 * HZ); + if (retval <= 0) { usb_kill_urb(ictx->tx_urb); pr_err_ratelimited("task interrupted\n"); + if (retval < 0) + ictx->tx.status = retval; + else + ictx->tx.status = -ETIMEDOUT; } ictx->tx.busy = false; @@ -949,12 +954,14 @@ static ssize_t vfd_write(struct file *file, const char __user *buf, static const unsigned char vfd_packet6[] = { 0x01, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF }; - if (ictx->disconnected) - return -ENODEV; - if (mutex_lock_interruptible(&ictx->lock)) return -ERESTARTSYS; + if (ictx->disconnected) { + retval = -ENODEV; + goto exit; + } + if (!ictx->dev_present_intf0) { pr_err_ratelimited("no iMON device present\n"); retval = -ENODEV; @@ -1029,11 +1036,13 @@ static ssize_t lcd_write(struct file *file, const char __user *buf, int retval = 0; struct imon_context *ictx = file->private_data; - if (ictx->disconnected) - return -ENODEV; - mutex_lock(&ictx->lock); + if (ictx->disconnected) { + retval = -ENODEV; + goto exit; + } + if (!ictx->display_supported) { pr_err_ratelimited("no iMON display present\n"); retval = -ENODEV; @@ -1121,7 +1130,7 @@ static int imon_ir_change_protocol(struct rc_dev *rc, u64 *rc_proto) int retval; struct imon_context *ictx = rc->priv; struct device *dev = ictx->dev; - bool unlock = false; + const bool unlock = mutex_trylock(&ictx->lock); unsigned char ir_proto_packet[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x86 }; @@ -1148,8 +1157,6 @@ static int imon_ir_change_protocol(struct rc_dev *rc, u64 *rc_proto) memcpy(ictx->usb_tx_buf, &ir_proto_packet, sizeof(ir_proto_packet)); - unlock = mutex_trylock(&ictx->lock); - retval = send_packet(ictx); if (retval) goto out; @@ -1745,14 +1752,6 @@ static void usb_rx_callback_intf0(struct urb *urb) if (!ictx) return; - /* - * if we get a callback before we're done configuring the hardware, we - * can't yet process the data, as there's nowhere to send it, but we - * still need to submit a new rx URB to avoid wedging the hardware - */ - if (!ictx->dev_present_intf0) - goto out; - switch (urb->status) { case -ENOENT: /* usbcore unlink successful! */ return; @@ -1761,16 +1760,29 @@ static void usb_rx_callback_intf0(struct urb *urb) break; case 0: - imon_incoming_packet(ictx, urb, intfnum); + /* + * if we get a callback before we're done configuring the hardware, we + * can't yet process the data, as there's nowhere to send it, but we + * still need to submit a new rx URB to avoid wedging the hardware + */ + if (ictx->dev_present_intf0) + imon_incoming_packet(ictx, urb, intfnum); break; + case -ECONNRESET: + case -EILSEQ: + case -EPROTO: + case -EPIPE: + dev_warn(ictx->dev, "imon %s: status(%d)\n", + __func__, urb->status); + return; + default: dev_warn(ictx->dev, "imon %s: status(%d): ignored\n", __func__, urb->status); break; } -out: usb_submit_urb(ictx->rx_urb_intf0, GFP_ATOMIC); } @@ -1786,14 +1798,6 @@ static void usb_rx_callback_intf1(struct urb *urb) if (!ictx) return; - /* - * if we get a callback before we're done configuring the hardware, we - * can't yet process the data, as there's nowhere to send it, but we - * still need to submit a new rx URB to avoid wedging the hardware - */ - if (!ictx->dev_present_intf1) - goto out; - switch (urb->status) { case -ENOENT: /* usbcore unlink successful! */ return; @@ -1802,16 +1806,29 @@ static void usb_rx_callback_intf1(struct urb *urb) break; case 0: - imon_incoming_packet(ictx, urb, intfnum); + /* + * if we get a callback before we're done configuring the hardware, we + * can't yet process the data, as there's nowhere to send it, but we + * still need to submit a new rx URB to avoid wedging the hardware + */ + if (ictx->dev_present_intf1) + imon_incoming_packet(ictx, urb, intfnum); break; + case -ECONNRESET: + case -EILSEQ: + case -EPROTO: + case -EPIPE: + dev_warn(ictx->dev, "imon %s: status(%d)\n", + __func__, urb->status); + return; + default: dev_warn(ictx->dev, "imon %s: status(%d): ignored\n", __func__, urb->status); break; } -out: usb_submit_urb(ictx->rx_urb_intf1, GFP_ATOMIC); } @@ -2499,7 +2516,11 @@ static void imon_disconnect(struct usb_interface *interface) int ifnum; ictx = usb_get_intfdata(interface); + + mutex_lock(&ictx->lock); ictx->disconnected = true; + mutex_unlock(&ictx->lock); + dev = ictx->dev; ifnum = interface->cur_altsetting->desc.bInterfaceNumber; diff --git a/drivers/media/rc/lirc_dev.c b/drivers/media/rc/lirc_dev.c index a2257dc2f25d..7d4942925993 100644 --- a/drivers/media/rc/lirc_dev.c +++ b/drivers/media/rc/lirc_dev.c @@ -736,11 +736,11 @@ int lirc_register(struct rc_dev *dev) cdev_init(&dev->lirc_cdev, &lirc_fops); + get_device(&dev->dev); + err = cdev_device_add(&dev->lirc_cdev, &dev->lirc_dev); if (err) - goto out_ida; - - get_device(&dev->dev); + goto out_put_device; switch (dev->driver_type) { case RC_DRIVER_SCANCODE: @@ -764,7 +764,8 @@ int lirc_register(struct rc_dev *dev) return 0; -out_ida: +out_put_device: + put_device(&dev->lirc_dev); ida_free(&lirc_ida, minor); return err; } diff --git a/drivers/media/rc/redrat3.c b/drivers/media/rc/redrat3.c index d89a4cfe3c89..a49173f54a4d 100644 --- a/drivers/media/rc/redrat3.c +++ b/drivers/media/rc/redrat3.c @@ -422,7 +422,7 @@ static int redrat3_send_cmd(int cmd, struct redrat3_dev *rr3) static int redrat3_enable_detector(struct redrat3_dev *rr3) { struct device *dev = rr3->dev; - u8 ret; + int ret; ret = redrat3_send_cmd(RR3_RC_DET_ENABLE, rr3); if (ret != 0) diff --git a/drivers/media/test-drivers/vicodec/vicodec-core.c b/drivers/media/test-drivers/vicodec/vicodec-core.c index c45f5cf12ded..a3df3a33237e 100644 --- a/drivers/media/test-drivers/vicodec/vicodec-core.c +++ b/drivers/media/test-drivers/vicodec/vicodec-core.c @@ -26,7 +26,7 @@ #include "codec-v4l2-fwht.h" MODULE_DESCRIPTION("Virtual codec device"); -MODULE_AUTHOR("Hans Verkuil <hansverk@cisco.com>"); +MODULE_AUTHOR("Hans Verkuil <hverkuil@kernel.org>"); MODULE_LICENSE("GPL v2"); static bool multiplanar; @@ -144,7 +144,7 @@ static const struct v4l2_event vicodec_eos_event = { static inline struct vicodec_ctx *file2ctx(struct file *file) { - return container_of(file->private_data, struct vicodec_ctx, fh); + return container_of(file_to_v4l2_fh(file), struct vicodec_ctx, fh); } static struct vicodec_q_data *get_q_data(struct vicodec_ctx *ctx, @@ -1207,20 +1207,20 @@ static int vidioc_s_selection(struct file *file, void *priv, return 0; } -static int vicodec_encoder_cmd(struct file *file, void *fh, +static int vicodec_encoder_cmd(struct file *file, void *priv, struct v4l2_encoder_cmd *ec) { struct vicodec_ctx *ctx = file2ctx(file); int ret; - ret = v4l2_m2m_ioctl_try_encoder_cmd(file, fh, ec); + ret = v4l2_m2m_ioctl_try_encoder_cmd(file, priv, ec); if (ret < 0) return ret; if (!vb2_is_streaming(&ctx->fh.m2m_ctx->out_q_ctx.q)) return 0; - ret = v4l2_m2m_ioctl_encoder_cmd(file, fh, ec); + ret = v4l2_m2m_ioctl_encoder_cmd(file, priv, ec); if (ret < 0) return ret; @@ -1235,7 +1235,7 @@ static int vicodec_encoder_cmd(struct file *file, void *fh, return 0; } -static int vicodec_decoder_cmd(struct file *file, void *fh, +static int vicodec_decoder_cmd(struct file *file, void *priv, struct v4l2_decoder_cmd *dc) { struct vicodec_ctx *ctx = file2ctx(file); @@ -1247,14 +1247,14 @@ static int vicodec_decoder_cmd(struct file *file, void *fh, */ WARN_ON(ctx->is_stateless); - ret = v4l2_m2m_ioctl_try_decoder_cmd(file, fh, dc); + ret = v4l2_m2m_ioctl_try_decoder_cmd(file, priv, dc); if (ret < 0) return ret; if (!vb2_is_streaming(&ctx->fh.m2m_ctx->out_q_ctx.q)) return 0; - ret = v4l2_m2m_ioctl_decoder_cmd(file, fh, dc); + ret = v4l2_m2m_ioctl_decoder_cmd(file, priv, dc); if (ret < 0) return ret; @@ -1269,7 +1269,7 @@ static int vicodec_decoder_cmd(struct file *file, void *fh, return 0; } -static int vicodec_enum_framesizes(struct file *file, void *fh, +static int vicodec_enum_framesizes(struct file *file, void *priv, struct v4l2_frmsizeenum *fsize) { switch (fsize->pixel_format) { @@ -1848,7 +1848,6 @@ static int vicodec_open(struct file *file) ctx->is_stateless = true; v4l2_fh_init(&ctx->fh, video_devdata(file)); - file->private_data = &ctx->fh; ctx->dev = dev; hdl = &ctx->hdl; v4l2_ctrl_handler_init(hdl, 5); @@ -1932,7 +1931,7 @@ static int vicodec_open(struct file *file) goto open_unlock; } - v4l2_fh_add(&ctx->fh); + v4l2_fh_add(&ctx->fh, file); open_unlock: mutex_unlock(vfd->lock); @@ -1947,7 +1946,7 @@ static int vicodec_release(struct file *file) mutex_lock(vfd->lock); v4l2_m2m_ctx_release(ctx->fh.m2m_ctx); mutex_unlock(vfd->lock); - v4l2_fh_del(&ctx->fh); + v4l2_fh_del(&ctx->fh, file); v4l2_fh_exit(&ctx->fh); v4l2_ctrl_handler_free(&ctx->hdl); kvfree(ctx->state.compressed_frame); diff --git a/drivers/media/test-drivers/vim2m.c b/drivers/media/test-drivers/vim2m.c index 1d1a9e768505..86c32699111a 100644 --- a/drivers/media/test-drivers/vim2m.c +++ b/drivers/media/test-drivers/vim2m.c @@ -191,9 +191,7 @@ static void get_alignment(u32 fourcc, struct vim2m_dev { struct v4l2_device v4l2_dev; struct video_device vfd; -#ifdef CONFIG_MEDIA_CONTROLLER struct media_device mdev; -#endif atomic_t num_inst; struct mutex dev_mutex; @@ -236,7 +234,7 @@ struct vim2m_ctx { static inline struct vim2m_ctx *file2ctx(struct file *file) { - return container_of(file->private_data, struct vim2m_ctx, fh); + return container_of(file_to_v4l2_fh(file), struct vim2m_ctx, fh); } static struct vim2m_q_data *get_q_data(struct vim2m_ctx *ctx, @@ -268,9 +266,6 @@ static const char *type_name(enum v4l2_buf_type type) } } -#define CLIP(__color) \ - (u8)(((__color) > 0xff) ? 0xff : (((__color) < 0) ? 0 : (__color))) - static void copy_line(struct vim2m_q_data *q_data_out, u8 *src, u8 *dst, bool reverse) { @@ -1389,7 +1384,6 @@ static int vim2m_open(struct file *file) } v4l2_fh_init(&ctx->fh, video_devdata(file)); - file->private_data = &ctx->fh; ctx->dev = dev; hdl = &ctx->hdl; v4l2_ctrl_handler_init(hdl, 4); @@ -1433,7 +1427,7 @@ static int vim2m_open(struct file *file) goto open_unlock; } - v4l2_fh_add(&ctx->fh); + v4l2_fh_add(&ctx->fh, file); atomic_inc(&dev->num_inst); dprintk(dev, 1, "Created instance: %p, m2m_ctx: %p\n", @@ -1451,7 +1445,7 @@ static int vim2m_release(struct file *file) dprintk(dev, 1, "Releasing instance %p\n", ctx); - v4l2_fh_del(&ctx->fh); + v4l2_fh_del(&ctx->fh, file); v4l2_fh_exit(&ctx->fh); v4l2_ctrl_handler_free(&ctx->hdl); mutex_lock(&dev->dev_mutex); @@ -1470,9 +1464,7 @@ static void vim2m_device_release(struct video_device *vdev) v4l2_device_unregister(&dev->v4l2_dev); v4l2_m2m_release(dev->m2m_dev); -#ifdef CONFIG_MEDIA_CONTROLLER media_device_cleanup(&dev->mdev); -#endif kfree(dev); } @@ -1543,7 +1535,6 @@ static int vim2m_probe(struct platform_device *pdev) goto error_dev; } -#ifdef CONFIG_MEDIA_CONTROLLER dev->mdev.dev = &pdev->dev; strscpy(dev->mdev.model, "vim2m", sizeof(dev->mdev.model)); strscpy(dev->mdev.bus_info, "platform:vim2m", @@ -1551,7 +1542,6 @@ static int vim2m_probe(struct platform_device *pdev) media_device_init(&dev->mdev); dev->mdev.ops = &m2m_media_ops; dev->v4l2_dev.mdev = &dev->mdev; -#endif ret = video_register_device(vfd, VFL_TYPE_VIDEO, 0); if (ret) { @@ -1562,7 +1552,6 @@ static int vim2m_probe(struct platform_device *pdev) v4l2_info(&dev->v4l2_dev, "Device registered as /dev/video%d\n", vfd->num); -#ifdef CONFIG_MEDIA_CONTROLLER ret = v4l2_m2m_register_media_controller(dev->m2m_dev, vfd, MEDIA_ENT_F_PROC_VIDEO_SCALER); if (ret) { @@ -1575,13 +1564,11 @@ static int vim2m_probe(struct platform_device *pdev) v4l2_err(&dev->v4l2_dev, "Failed to register mem2mem media device\n"); goto error_m2m_mc; } -#endif + return 0; -#ifdef CONFIG_MEDIA_CONTROLLER error_m2m_mc: v4l2_m2m_unregister_media_controller(dev->m2m_dev); -#endif error_v4l2: video_unregister_device(&dev->vfd); /* vim2m_device_release called by video_unregister_device to release various objects */ @@ -1602,10 +1589,8 @@ static void vim2m_remove(struct platform_device *pdev) v4l2_info(&dev->v4l2_dev, "Removing " MEM2MEM_NAME); -#ifdef CONFIG_MEDIA_CONTROLLER media_device_unregister(&dev->mdev); v4l2_m2m_unregister_media_controller(dev->m2m_dev); -#endif video_unregister_device(&dev->vfd); } diff --git a/drivers/media/test-drivers/vimc/vimc-capture.c b/drivers/media/test-drivers/vimc/vimc-capture.c index 10df039278e7..7f6124025fc9 100644 --- a/drivers/media/test-drivers/vimc/vimc-capture.c +++ b/drivers/media/test-drivers/vimc/vimc-capture.c @@ -57,8 +57,6 @@ static int vimc_capture_querycap(struct file *file, void *priv, { strscpy(cap->driver, VIMC_PDEV_NAME, sizeof(cap->driver)); strscpy(cap->card, KBUILD_MODNAME, sizeof(cap->card)); - snprintf(cap->bus_info, sizeof(cap->bus_info), - "platform:%s", VIMC_PDEV_NAME); return 0; } @@ -169,7 +167,7 @@ static int vimc_capture_enum_fmt_vid_cap(struct file *file, void *priv, return 0; } -static int vimc_capture_enum_framesizes(struct file *file, void *fh, +static int vimc_capture_enum_framesizes(struct file *file, void *priv, struct v4l2_frmsizeenum *fsize) { const struct vimc_pix_map *vpix; diff --git a/drivers/media/test-drivers/vimc/vimc-core.c b/drivers/media/test-drivers/vimc/vimc-core.c index c812fa9f0650..f632c77e52f5 100644 --- a/drivers/media/test-drivers/vimc/vimc-core.c +++ b/drivers/media/test-drivers/vimc/vimc-core.c @@ -366,8 +366,6 @@ static int vimc_probe(struct platform_device *pdev) /* Initialize media device */ strscpy(vimc->mdev.model, VIMC_MDEV_MODEL_NAME, sizeof(vimc->mdev.model)); - snprintf(vimc->mdev.bus_info, sizeof(vimc->mdev.bus_info), - "platform:%s", VIMC_PDEV_NAME); vimc->mdev.dev = &pdev->dev; media_device_init(&vimc->mdev); diff --git a/drivers/media/test-drivers/visl/visl-core.c b/drivers/media/test-drivers/visl/visl-core.c index 5bf3136b36eb..26c6c6835f79 100644 --- a/drivers/media/test-drivers/visl/visl-core.c +++ b/drivers/media/test-drivers/visl/visl-core.c @@ -341,7 +341,6 @@ static int visl_open(struct file *file) ctx->tpg_str_buf = kzalloc(TPG_STR_BUF_SZ, GFP_KERNEL); v4l2_fh_init(&ctx->fh, video_devdata(file)); - file->private_data = &ctx->fh; ctx->dev = dev; rc = visl_init_ctrls(ctx); @@ -361,7 +360,7 @@ static int visl_open(struct file *file) if (rc) goto free_m2m_ctx; - v4l2_fh_add(&ctx->fh); + v4l2_fh_add(&ctx->fh, file); dprintk(dev, "Created instance: %p, m2m_ctx: %p\n", ctx, ctx->fh.m2m_ctx); @@ -390,7 +389,7 @@ static int visl_release(struct file *file) dprintk(dev, "Releasing instance %p\n", ctx); tpg_free(&ctx->tpg); - v4l2_fh_del(&ctx->fh); + v4l2_fh_del(&ctx->fh, file); v4l2_fh_exit(&ctx->fh); v4l2_ctrl_handler_free(&ctx->hdl); mutex_lock(&dev->dev_mutex); diff --git a/drivers/media/test-drivers/visl/visl.h b/drivers/media/test-drivers/visl/visl.h index 434e9efbf9b2..2971e8b37ff6 100644 --- a/drivers/media/test-drivers/visl/visl.h +++ b/drivers/media/test-drivers/visl/visl.h @@ -163,12 +163,7 @@ struct visl_ctrl_desc { static inline struct visl_ctx *visl_file_to_ctx(struct file *file) { - return container_of(file->private_data, struct visl_ctx, fh); -} - -static inline struct visl_ctx *visl_v4l2fh_to_ctx(struct v4l2_fh *v4l2_fh) -{ - return container_of(v4l2_fh, struct visl_ctx, fh); + return container_of(file_to_v4l2_fh(file), struct visl_ctx, fh); } void *visl_find_control_data(struct visl_ctx *ctx, u32 id); diff --git a/drivers/media/test-drivers/vivid/vivid-cec.c b/drivers/media/test-drivers/vivid/vivid-cec.c index 356a988dd6a1..2d15fdd5d999 100644 --- a/drivers/media/test-drivers/vivid/vivid-cec.c +++ b/drivers/media/test-drivers/vivid/vivid-cec.c @@ -327,7 +327,7 @@ static int vivid_received(struct cec_adapter *adap, struct cec_msg *msg) char osd[14]; if (!cec_is_sink(adap)) - return -ENOMSG; + break; cec_ops_set_osd_string(msg, &disp_ctl, osd); switch (disp_ctl) { case CEC_OP_DISP_CTL_DEFAULT: @@ -348,7 +348,7 @@ static int vivid_received(struct cec_adapter *adap, struct cec_msg *msg) cec_transmit_msg(adap, &reply, false); break; } - break; + return 0; } case CEC_MSG_VENDOR_COMMAND_WITH_ID: { u32 vendor_id; @@ -379,7 +379,7 @@ static int vivid_received(struct cec_adapter *adap, struct cec_msg *msg) if (size == 1) { // Ignore even op values if (!(vendor_cmd[0] & 1)) - break; + return 0; reply.len = msg->len; memcpy(reply.msg + 1, msg->msg + 1, msg->len - 1); reply.msg[msg->len - 1]++; @@ -388,12 +388,10 @@ static int vivid_received(struct cec_adapter *adap, struct cec_msg *msg) CEC_OP_ABORT_INVALID_OP); } cec_transmit_msg(adap, &reply, false); - break; + return 0; } - default: - return -ENOMSG; } - return 0; + return -ENOMSG; } static const struct cec_adap_ops vivid_cec_adap_ops = { diff --git a/drivers/media/test-drivers/vivid/vivid-core.c b/drivers/media/test-drivers/vivid/vivid-core.c index 8d56168c72aa..86506be36acb 100644 --- a/drivers/media/test-drivers/vivid/vivid-core.c +++ b/drivers/media/test-drivers/vivid/vivid-core.c @@ -277,49 +277,49 @@ static int vidioc_querycap(struct file *file, void *priv, return 0; } -static int vidioc_s_hw_freq_seek(struct file *file, void *fh, const struct v4l2_hw_freq_seek *a) +static int vidioc_s_hw_freq_seek(struct file *file, void *priv, const struct v4l2_hw_freq_seek *a) { struct video_device *vdev = video_devdata(file); if (vdev->vfl_type == VFL_TYPE_RADIO) - return vivid_radio_rx_s_hw_freq_seek(file, fh, a); + return vivid_radio_rx_s_hw_freq_seek(file, priv, a); return -ENOTTY; } -static int vidioc_enum_freq_bands(struct file *file, void *fh, struct v4l2_frequency_band *band) +static int vidioc_enum_freq_bands(struct file *file, void *priv, struct v4l2_frequency_band *band) { struct video_device *vdev = video_devdata(file); if (vdev->vfl_type == VFL_TYPE_RADIO) - return vivid_radio_rx_enum_freq_bands(file, fh, band); + return vivid_radio_rx_enum_freq_bands(file, priv, band); if (vdev->vfl_type == VFL_TYPE_SDR) - return vivid_sdr_enum_freq_bands(file, fh, band); + return vivid_sdr_enum_freq_bands(file, priv, band); return -ENOTTY; } -static int vidioc_g_tuner(struct file *file, void *fh, struct v4l2_tuner *vt) +static int vidioc_g_tuner(struct file *file, void *priv, struct v4l2_tuner *vt) { struct video_device *vdev = video_devdata(file); if (vdev->vfl_type == VFL_TYPE_RADIO) - return vivid_radio_rx_g_tuner(file, fh, vt); + return vivid_radio_rx_g_tuner(file, priv, vt); if (vdev->vfl_type == VFL_TYPE_SDR) - return vivid_sdr_g_tuner(file, fh, vt); - return vivid_video_g_tuner(file, fh, vt); + return vivid_sdr_g_tuner(file, priv, vt); + return vivid_video_g_tuner(file, priv, vt); } -static int vidioc_s_tuner(struct file *file, void *fh, const struct v4l2_tuner *vt) +static int vidioc_s_tuner(struct file *file, void *priv, const struct v4l2_tuner *vt) { struct video_device *vdev = video_devdata(file); if (vdev->vfl_type == VFL_TYPE_RADIO) - return vivid_radio_rx_s_tuner(file, fh, vt); + return vivid_radio_rx_s_tuner(file, priv, vt); if (vdev->vfl_type == VFL_TYPE_SDR) - return vivid_sdr_s_tuner(file, fh, vt); - return vivid_video_s_tuner(file, fh, vt); + return vivid_sdr_s_tuner(file, priv, vt); + return vivid_video_s_tuner(file, priv, vt); } -static int vidioc_g_frequency(struct file *file, void *fh, struct v4l2_frequency *vf) +static int vidioc_g_frequency(struct file *file, void *priv, struct v4l2_frequency *vf) { struct vivid_dev *dev = video_drvdata(file); struct video_device *vdev = video_devdata(file); @@ -329,11 +329,11 @@ static int vidioc_g_frequency(struct file *file, void *fh, struct v4l2_frequency vdev->vfl_dir == VFL_DIR_RX ? &dev->radio_rx_freq : &dev->radio_tx_freq, vf); if (vdev->vfl_type == VFL_TYPE_SDR) - return vivid_sdr_g_frequency(file, fh, vf); - return vivid_video_g_frequency(file, fh, vf); + return vivid_sdr_g_frequency(file, priv, vf); + return vivid_video_g_frequency(file, priv, vf); } -static int vidioc_s_frequency(struct file *file, void *fh, const struct v4l2_frequency *vf) +static int vidioc_s_frequency(struct file *file, void *priv, const struct v4l2_frequency *vf) { struct vivid_dev *dev = video_drvdata(file); struct video_device *vdev = video_devdata(file); @@ -343,113 +343,113 @@ static int vidioc_s_frequency(struct file *file, void *fh, const struct v4l2_fre vdev->vfl_dir == VFL_DIR_RX ? &dev->radio_rx_freq : &dev->radio_tx_freq, vf); if (vdev->vfl_type == VFL_TYPE_SDR) - return vivid_sdr_s_frequency(file, fh, vf); - return vivid_video_s_frequency(file, fh, vf); + return vivid_sdr_s_frequency(file, priv, vf); + return vivid_video_s_frequency(file, priv, vf); } -static int vidioc_overlay(struct file *file, void *fh, unsigned i) +static int vidioc_overlay(struct file *file, void *priv, unsigned i) { struct video_device *vdev = video_devdata(file); if (vdev->vfl_dir == VFL_DIR_RX) return -ENOTTY; - return vivid_vid_out_overlay(file, fh, i); + return vivid_vid_out_overlay(file, priv, i); } -static int vidioc_g_fbuf(struct file *file, void *fh, struct v4l2_framebuffer *a) +static int vidioc_g_fbuf(struct file *file, void *priv, struct v4l2_framebuffer *a) { struct video_device *vdev = video_devdata(file); if (vdev->vfl_dir == VFL_DIR_RX) return -ENOTTY; - return vivid_vid_out_g_fbuf(file, fh, a); + return vivid_vid_out_g_fbuf(file, priv, a); } -static int vidioc_s_fbuf(struct file *file, void *fh, const struct v4l2_framebuffer *a) +static int vidioc_s_fbuf(struct file *file, void *priv, const struct v4l2_framebuffer *a) { struct video_device *vdev = video_devdata(file); if (vdev->vfl_dir == VFL_DIR_RX) return -ENOTTY; - return vivid_vid_out_s_fbuf(file, fh, a); + return vivid_vid_out_s_fbuf(file, priv, a); } -static int vidioc_s_std(struct file *file, void *fh, v4l2_std_id id) +static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id id) { struct video_device *vdev = video_devdata(file); if (vdev->vfl_dir == VFL_DIR_RX) - return vivid_vid_cap_s_std(file, fh, id); - return vivid_vid_out_s_std(file, fh, id); + return vivid_vid_cap_s_std(file, priv, id); + return vivid_vid_out_s_std(file, priv, id); } -static int vidioc_s_dv_timings(struct file *file, void *fh, struct v4l2_dv_timings *timings) +static int vidioc_s_dv_timings(struct file *file, void *priv, struct v4l2_dv_timings *timings) { struct video_device *vdev = video_devdata(file); if (vdev->vfl_dir == VFL_DIR_RX) - return vivid_vid_cap_s_dv_timings(file, fh, timings); - return vivid_vid_out_s_dv_timings(file, fh, timings); + return vivid_vid_cap_s_dv_timings(file, priv, timings); + return vivid_vid_out_s_dv_timings(file, priv, timings); } -static int vidioc_g_pixelaspect(struct file *file, void *fh, +static int vidioc_g_pixelaspect(struct file *file, void *priv, int type, struct v4l2_fract *f) { struct video_device *vdev = video_devdata(file); if (vdev->vfl_dir == VFL_DIR_RX) - return vivid_vid_cap_g_pixelaspect(file, fh, type, f); - return vivid_vid_out_g_pixelaspect(file, fh, type, f); + return vivid_vid_cap_g_pixelaspect(file, priv, type, f); + return vivid_vid_out_g_pixelaspect(file, priv, type, f); } -static int vidioc_g_selection(struct file *file, void *fh, +static int vidioc_g_selection(struct file *file, void *priv, struct v4l2_selection *sel) { struct video_device *vdev = video_devdata(file); if (vdev->vfl_dir == VFL_DIR_RX) - return vivid_vid_cap_g_selection(file, fh, sel); - return vivid_vid_out_g_selection(file, fh, sel); + return vivid_vid_cap_g_selection(file, priv, sel); + return vivid_vid_out_g_selection(file, priv, sel); } -static int vidioc_s_selection(struct file *file, void *fh, +static int vidioc_s_selection(struct file *file, void *priv, struct v4l2_selection *sel) { struct video_device *vdev = video_devdata(file); if (vdev->vfl_dir == VFL_DIR_RX) - return vivid_vid_cap_s_selection(file, fh, sel); - return vivid_vid_out_s_selection(file, fh, sel); + return vivid_vid_cap_s_selection(file, priv, sel); + return vivid_vid_out_s_selection(file, priv, sel); } -static int vidioc_g_parm(struct file *file, void *fh, +static int vidioc_g_parm(struct file *file, void *priv, struct v4l2_streamparm *parm) { struct video_device *vdev = video_devdata(file); if (vdev->vfl_type == VFL_TYPE_TOUCH) - return vivid_g_parm_tch(file, fh, parm); + return vivid_g_parm_tch(file, priv, parm); if (vdev->vfl_dir == VFL_DIR_RX) - return vivid_vid_cap_g_parm(file, fh, parm); - return vivid_vid_out_g_parm(file, fh, parm); + return vivid_vid_cap_g_parm(file, priv, parm); + return vivid_vid_out_g_parm(file, priv, parm); } -static int vidioc_s_parm(struct file *file, void *fh, +static int vidioc_s_parm(struct file *file, void *priv, struct v4l2_streamparm *parm) { struct video_device *vdev = video_devdata(file); if (vdev->vfl_dir == VFL_DIR_RX) - return vivid_vid_cap_s_parm(file, fh, parm); + return vivid_vid_cap_s_parm(file, priv, parm); return -ENOTTY; } -static int vidioc_log_status(struct file *file, void *fh) +static int vidioc_log_status(struct file *file, void *priv) { struct vivid_dev *dev = video_drvdata(file); struct video_device *vdev = video_devdata(file); - v4l2_ctrl_log_status(file, fh); + v4l2_ctrl_log_status(file, priv); if (vdev->vfl_dir == VFL_DIR_RX && vdev->vfl_type == VFL_TYPE_VIDEO) tpg_log_status(&dev->tpg); return 0; @@ -654,11 +654,11 @@ static int vivid_fop_release(struct file *file) v4l2_info(&dev->v4l2_dev, "reconnect\n"); vivid_reconnect(dev); } - if (file->private_data == dev->radio_rx_rds_owner) { + if (file_to_v4l2_fh(file) == dev->radio_rx_rds_owner) { dev->radio_rx_rds_last_block = 0; dev->radio_rx_rds_owner = NULL; } - if (file->private_data == dev->radio_tx_rds_owner) { + if (file_to_v4l2_fh(file) == dev->radio_tx_rds_owner) { dev->radio_tx_rds_last_block = 0; dev->radio_tx_rds_owner = NULL; } diff --git a/drivers/media/test-drivers/vivid/vivid-radio-rx.c b/drivers/media/test-drivers/vivid/vivid-radio-rx.c index 79c1723bd84c..b5e3026f883e 100644 --- a/drivers/media/test-drivers/vivid/vivid-radio-rx.c +++ b/drivers/media/test-drivers/vivid/vivid-radio-rx.c @@ -42,13 +42,13 @@ ssize_t vivid_radio_rx_read(struct file *file, char __user *buf, if (mutex_lock_interruptible(&dev->mutex)) return -ERESTARTSYS; if (dev->radio_rx_rds_owner && - file->private_data != dev->radio_rx_rds_owner) { + file_to_v4l2_fh(file) != dev->radio_rx_rds_owner) { mutex_unlock(&dev->mutex); return -EBUSY; } if (dev->radio_rx_rds_owner == NULL) { vivid_radio_rds_init(dev); - dev->radio_rx_rds_owner = file->private_data; + dev->radio_rx_rds_owner = file_to_v4l2_fh(file); } retry: @@ -133,7 +133,7 @@ __poll_t vivid_radio_rx_poll(struct file *file, struct poll_table_struct *wait) return EPOLLIN | EPOLLRDNORM | v4l2_ctrl_poll(file, wait); } -int vivid_radio_rx_enum_freq_bands(struct file *file, void *fh, struct v4l2_frequency_band *band) +int vivid_radio_rx_enum_freq_bands(struct file *file, void *priv, struct v4l2_frequency_band *band) { if (band->tuner != 0) return -EINVAL; @@ -145,7 +145,7 @@ int vivid_radio_rx_enum_freq_bands(struct file *file, void *fh, struct v4l2_freq return 0; } -int vivid_radio_rx_s_hw_freq_seek(struct file *file, void *fh, const struct v4l2_hw_freq_seek *a) +int vivid_radio_rx_s_hw_freq_seek(struct file *file, void *priv, const struct v4l2_hw_freq_seek *a) { struct vivid_dev *dev = video_drvdata(file); unsigned low, high; @@ -214,7 +214,7 @@ int vivid_radio_rx_s_hw_freq_seek(struct file *file, void *fh, const struct v4l2 return 0; } -int vivid_radio_rx_g_tuner(struct file *file, void *fh, struct v4l2_tuner *vt) +int vivid_radio_rx_g_tuner(struct file *file, void *priv, struct v4l2_tuner *vt) { struct vivid_dev *dev = video_drvdata(file); int delta = 800; @@ -267,7 +267,7 @@ int vivid_radio_rx_g_tuner(struct file *file, void *fh, struct v4l2_tuner *vt) return 0; } -int vivid_radio_rx_s_tuner(struct file *file, void *fh, const struct v4l2_tuner *vt) +int vivid_radio_rx_s_tuner(struct file *file, void *priv, const struct v4l2_tuner *vt) { struct vivid_dev *dev = video_drvdata(file); diff --git a/drivers/media/test-drivers/vivid/vivid-radio-rx.h b/drivers/media/test-drivers/vivid/vivid-radio-rx.h index c9c7849f6f99..a2ae17c78ece 100644 --- a/drivers/media/test-drivers/vivid/vivid-radio-rx.h +++ b/drivers/media/test-drivers/vivid/vivid-radio-rx.h @@ -11,9 +11,9 @@ ssize_t vivid_radio_rx_read(struct file *, char __user *, size_t, loff_t *); __poll_t vivid_radio_rx_poll(struct file *file, struct poll_table_struct *wait); -int vivid_radio_rx_enum_freq_bands(struct file *file, void *fh, struct v4l2_frequency_band *band); -int vivid_radio_rx_s_hw_freq_seek(struct file *file, void *fh, const struct v4l2_hw_freq_seek *a); -int vivid_radio_rx_g_tuner(struct file *file, void *fh, struct v4l2_tuner *vt); -int vivid_radio_rx_s_tuner(struct file *file, void *fh, const struct v4l2_tuner *vt); +int vivid_radio_rx_enum_freq_bands(struct file *file, void *priv, struct v4l2_frequency_band *band); +int vivid_radio_rx_s_hw_freq_seek(struct file *file, void *priv, const struct v4l2_hw_freq_seek *a); +int vivid_radio_rx_g_tuner(struct file *file, void *priv, struct v4l2_tuner *vt); +int vivid_radio_rx_s_tuner(struct file *file, void *priv, const struct v4l2_tuner *vt); #endif diff --git a/drivers/media/test-drivers/vivid/vivid-radio-tx.c b/drivers/media/test-drivers/vivid/vivid-radio-tx.c index 049d40b948bb..ada60722066e 100644 --- a/drivers/media/test-drivers/vivid/vivid-radio-tx.c +++ b/drivers/media/test-drivers/vivid/vivid-radio-tx.c @@ -39,11 +39,11 @@ ssize_t vivid_radio_tx_write(struct file *file, const char __user *buf, if (mutex_lock_interruptible(&dev->mutex)) return -ERESTARTSYS; if (dev->radio_tx_rds_owner && - file->private_data != dev->radio_tx_rds_owner) { + file_to_v4l2_fh(file) != dev->radio_tx_rds_owner) { mutex_unlock(&dev->mutex); return -EBUSY; } - dev->radio_tx_rds_owner = file->private_data; + dev->radio_tx_rds_owner = file_to_v4l2_fh(file); retry: timestamp = ktime_sub(ktime_get(), dev->radio_rds_init_time); @@ -96,7 +96,7 @@ __poll_t vivid_radio_tx_poll(struct file *file, struct poll_table_struct *wait) return EPOLLOUT | EPOLLWRNORM | v4l2_ctrl_poll(file, wait); } -int vidioc_g_modulator(struct file *file, void *fh, struct v4l2_modulator *a) +int vidioc_g_modulator(struct file *file, void *priv, struct v4l2_modulator *a) { struct vivid_dev *dev = video_drvdata(file); @@ -115,7 +115,7 @@ int vidioc_g_modulator(struct file *file, void *fh, struct v4l2_modulator *a) return 0; } -int vidioc_s_modulator(struct file *file, void *fh, const struct v4l2_modulator *a) +int vidioc_s_modulator(struct file *file, void *priv, const struct v4l2_modulator *a) { struct vivid_dev *dev = video_drvdata(file); diff --git a/drivers/media/test-drivers/vivid/vivid-radio-tx.h b/drivers/media/test-drivers/vivid/vivid-radio-tx.h index c2bf1e7e634a..20cb6f1363ff 100644 --- a/drivers/media/test-drivers/vivid/vivid-radio-tx.h +++ b/drivers/media/test-drivers/vivid/vivid-radio-tx.h @@ -11,7 +11,7 @@ ssize_t vivid_radio_tx_write(struct file *, const char __user *, size_t, loff_t *); __poll_t vivid_radio_tx_poll(struct file *file, struct poll_table_struct *wait); -int vidioc_g_modulator(struct file *file, void *fh, struct v4l2_modulator *a); -int vidioc_s_modulator(struct file *file, void *fh, const struct v4l2_modulator *a); +int vidioc_g_modulator(struct file *file, void *priv, struct v4l2_modulator *a); +int vidioc_s_modulator(struct file *file, void *priv, const struct v4l2_modulator *a); #endif diff --git a/drivers/media/test-drivers/vivid/vivid-sdr-cap.c b/drivers/media/test-drivers/vivid/vivid-sdr-cap.c index c633fc2ed664..2664a593e8e1 100644 --- a/drivers/media/test-drivers/vivid/vivid-sdr-cap.c +++ b/drivers/media/test-drivers/vivid/vivid-sdr-cap.c @@ -344,7 +344,7 @@ const struct vb2_ops vivid_sdr_cap_qops = { .buf_request_complete = sdr_cap_buf_request_complete, }; -int vivid_sdr_enum_freq_bands(struct file *file, void *fh, +int vivid_sdr_enum_freq_bands(struct file *file, void *priv, struct v4l2_frequency_band *band) { switch (band->tuner) { @@ -363,7 +363,7 @@ int vivid_sdr_enum_freq_bands(struct file *file, void *fh, } } -int vivid_sdr_g_frequency(struct file *file, void *fh, +int vivid_sdr_g_frequency(struct file *file, void *priv, struct v4l2_frequency *vf) { struct vivid_dev *dev = video_drvdata(file); @@ -382,7 +382,7 @@ int vivid_sdr_g_frequency(struct file *file, void *fh, } } -int vivid_sdr_s_frequency(struct file *file, void *fh, +int vivid_sdr_s_frequency(struct file *file, void *priv, const struct v4l2_frequency *vf) { struct vivid_dev *dev = video_drvdata(file); @@ -423,7 +423,7 @@ int vivid_sdr_s_frequency(struct file *file, void *fh, } } -int vivid_sdr_g_tuner(struct file *file, void *fh, struct v4l2_tuner *vt) +int vivid_sdr_g_tuner(struct file *file, void *priv, struct v4l2_tuner *vt) { switch (vt->index) { case 0: @@ -447,14 +447,14 @@ int vivid_sdr_g_tuner(struct file *file, void *fh, struct v4l2_tuner *vt) } } -int vivid_sdr_s_tuner(struct file *file, void *fh, const struct v4l2_tuner *vt) +int vivid_sdr_s_tuner(struct file *file, void *priv, const struct v4l2_tuner *vt) { if (vt->index > 1) return -EINVAL; return 0; } -int vidioc_enum_fmt_sdr_cap(struct file *file, void *fh, struct v4l2_fmtdesc *f) +int vidioc_enum_fmt_sdr_cap(struct file *file, void *priv, struct v4l2_fmtdesc *f) { if (f->index >= ARRAY_SIZE(formats)) return -EINVAL; @@ -462,7 +462,7 @@ int vidioc_enum_fmt_sdr_cap(struct file *file, void *fh, struct v4l2_fmtdesc *f) return 0; } -int vidioc_g_fmt_sdr_cap(struct file *file, void *fh, struct v4l2_format *f) +int vidioc_g_fmt_sdr_cap(struct file *file, void *priv, struct v4l2_format *f) { struct vivid_dev *dev = video_drvdata(file); @@ -471,7 +471,7 @@ int vidioc_g_fmt_sdr_cap(struct file *file, void *fh, struct v4l2_format *f) return 0; } -int vidioc_s_fmt_sdr_cap(struct file *file, void *fh, struct v4l2_format *f) +int vidioc_s_fmt_sdr_cap(struct file *file, void *priv, struct v4l2_format *f) { struct vivid_dev *dev = video_drvdata(file); struct vb2_queue *q = &dev->vb_sdr_cap_q; @@ -495,7 +495,7 @@ int vidioc_s_fmt_sdr_cap(struct file *file, void *fh, struct v4l2_format *f) return 0; } -int vidioc_try_fmt_sdr_cap(struct file *file, void *fh, struct v4l2_format *f) +int vidioc_try_fmt_sdr_cap(struct file *file, void *priv, struct v4l2_format *f) { int i; diff --git a/drivers/media/test-drivers/vivid/vivid-sdr-cap.h b/drivers/media/test-drivers/vivid/vivid-sdr-cap.h index 813c9248e5a7..3d8eeabbfc10 100644 --- a/drivers/media/test-drivers/vivid/vivid-sdr-cap.h +++ b/drivers/media/test-drivers/vivid/vivid-sdr-cap.h @@ -8,15 +8,15 @@ #ifndef _VIVID_SDR_CAP_H_ #define _VIVID_SDR_CAP_H_ -int vivid_sdr_enum_freq_bands(struct file *file, void *fh, struct v4l2_frequency_band *band); -int vivid_sdr_g_frequency(struct file *file, void *fh, struct v4l2_frequency *vf); -int vivid_sdr_s_frequency(struct file *file, void *fh, const struct v4l2_frequency *vf); -int vivid_sdr_g_tuner(struct file *file, void *fh, struct v4l2_tuner *vt); -int vivid_sdr_s_tuner(struct file *file, void *fh, const struct v4l2_tuner *vt); -int vidioc_enum_fmt_sdr_cap(struct file *file, void *fh, struct v4l2_fmtdesc *f); -int vidioc_g_fmt_sdr_cap(struct file *file, void *fh, struct v4l2_format *f); -int vidioc_s_fmt_sdr_cap(struct file *file, void *fh, struct v4l2_format *f); -int vidioc_try_fmt_sdr_cap(struct file *file, void *fh, struct v4l2_format *f); +int vivid_sdr_enum_freq_bands(struct file *file, void *priv, struct v4l2_frequency_band *band); +int vivid_sdr_g_frequency(struct file *file, void *priv, struct v4l2_frequency *vf); +int vivid_sdr_s_frequency(struct file *file, void *priv, const struct v4l2_frequency *vf); +int vivid_sdr_g_tuner(struct file *file, void *priv, struct v4l2_tuner *vt); +int vivid_sdr_s_tuner(struct file *file, void *priv, const struct v4l2_tuner *vt); +int vidioc_enum_fmt_sdr_cap(struct file *file, void *priv, struct v4l2_fmtdesc *f); +int vidioc_g_fmt_sdr_cap(struct file *file, void *priv, struct v4l2_format *f); +int vidioc_s_fmt_sdr_cap(struct file *file, void *priv, struct v4l2_format *f); +int vidioc_try_fmt_sdr_cap(struct file *file, void *priv, struct v4l2_format *f); void vivid_sdr_cap_process(struct vivid_dev *dev, struct vivid_buffer *buf); extern const struct vb2_ops vivid_sdr_cap_qops; diff --git a/drivers/media/test-drivers/vivid/vivid-vbi-cap.c b/drivers/media/test-drivers/vivid/vivid-vbi-cap.c index a09f62c66c33..791382a54b4f 100644 --- a/drivers/media/test-drivers/vivid/vivid-vbi-cap.c +++ b/drivers/media/test-drivers/vivid/vivid-vbi-cap.c @@ -282,7 +282,7 @@ void vivid_fill_service_lines(struct v4l2_sliced_vbi_format *vbi, u32 service_se } } -int vidioc_g_fmt_sliced_vbi_cap(struct file *file, void *fh, struct v4l2_format *fmt) +int vidioc_g_fmt_sliced_vbi_cap(struct file *file, void *priv, struct v4l2_format *fmt) { struct vivid_dev *dev = video_drvdata(file); struct v4l2_sliced_vbi_format *vbi = &fmt->fmt.sliced; @@ -294,7 +294,7 @@ int vidioc_g_fmt_sliced_vbi_cap(struct file *file, void *fh, struct v4l2_format return 0; } -int vidioc_try_fmt_sliced_vbi_cap(struct file *file, void *fh, struct v4l2_format *fmt) +int vidioc_try_fmt_sliced_vbi_cap(struct file *file, void *priv, struct v4l2_format *fmt) { struct vivid_dev *dev = video_drvdata(file); struct v4l2_sliced_vbi_format *vbi = &fmt->fmt.sliced; @@ -310,11 +310,11 @@ int vidioc_try_fmt_sliced_vbi_cap(struct file *file, void *fh, struct v4l2_forma return 0; } -int vidioc_s_fmt_sliced_vbi_cap(struct file *file, void *fh, struct v4l2_format *fmt) +int vidioc_s_fmt_sliced_vbi_cap(struct file *file, void *priv, struct v4l2_format *fmt) { struct vivid_dev *dev = video_drvdata(file); struct v4l2_sliced_vbi_format *vbi = &fmt->fmt.sliced; - int ret = vidioc_try_fmt_sliced_vbi_cap(file, fh, fmt); + int ret = vidioc_try_fmt_sliced_vbi_cap(file, priv, fmt); if (ret) return ret; @@ -324,7 +324,7 @@ int vidioc_s_fmt_sliced_vbi_cap(struct file *file, void *fh, struct v4l2_format return 0; } -int vidioc_g_sliced_vbi_cap(struct file *file, void *fh, struct v4l2_sliced_vbi_cap *cap) +int vidioc_g_sliced_vbi_cap(struct file *file, void *priv, struct v4l2_sliced_vbi_cap *cap) { struct vivid_dev *dev = video_drvdata(file); struct video_device *vdev = video_devdata(file); diff --git a/drivers/media/test-drivers/vivid/vivid-vbi-cap.h b/drivers/media/test-drivers/vivid/vivid-vbi-cap.h index 91d2de01381c..ec2d200c9e0d 100644 --- a/drivers/media/test-drivers/vivid/vivid-vbi-cap.h +++ b/drivers/media/test-drivers/vivid/vivid-vbi-cap.h @@ -16,10 +16,10 @@ int vidioc_g_fmt_vbi_cap(struct file *file, void *priv, struct v4l2_format *f); int vidioc_s_fmt_vbi_cap(struct file *file, void *priv, struct v4l2_format *f); -int vidioc_g_fmt_sliced_vbi_cap(struct file *file, void *fh, struct v4l2_format *fmt); -int vidioc_try_fmt_sliced_vbi_cap(struct file *file, void *fh, struct v4l2_format *fmt); -int vidioc_s_fmt_sliced_vbi_cap(struct file *file, void *fh, struct v4l2_format *fmt); -int vidioc_g_sliced_vbi_cap(struct file *file, void *fh, struct v4l2_sliced_vbi_cap *cap); +int vidioc_g_fmt_sliced_vbi_cap(struct file *file, void *priv, struct v4l2_format *fmt); +int vidioc_try_fmt_sliced_vbi_cap(struct file *file, void *priv, struct v4l2_format *fmt); +int vidioc_s_fmt_sliced_vbi_cap(struct file *file, void *priv, struct v4l2_format *fmt); +int vidioc_g_sliced_vbi_cap(struct file *file, void *priv, struct v4l2_sliced_vbi_cap *cap); void vivid_fill_service_lines(struct v4l2_sliced_vbi_format *vbi, u32 service_set); diff --git a/drivers/media/test-drivers/vivid/vivid-vbi-out.c b/drivers/media/test-drivers/vivid/vivid-vbi-out.c index b7a09d2f394e..7b3ea96744bb 100644 --- a/drivers/media/test-drivers/vivid/vivid-vbi-out.c +++ b/drivers/media/test-drivers/vivid/vivid-vbi-out.c @@ -168,7 +168,7 @@ int vidioc_s_fmt_vbi_out(struct file *file, void *priv, return 0; } -int vidioc_g_fmt_sliced_vbi_out(struct file *file, void *fh, struct v4l2_format *fmt) +int vidioc_g_fmt_sliced_vbi_out(struct file *file, void *priv, struct v4l2_format *fmt) { struct vivid_dev *dev = video_drvdata(file); struct v4l2_sliced_vbi_format *vbi = &fmt->fmt.sliced; @@ -180,7 +180,7 @@ int vidioc_g_fmt_sliced_vbi_out(struct file *file, void *fh, struct v4l2_format return 0; } -int vidioc_try_fmt_sliced_vbi_out(struct file *file, void *fh, struct v4l2_format *fmt) +int vidioc_try_fmt_sliced_vbi_out(struct file *file, void *priv, struct v4l2_format *fmt) { struct vivid_dev *dev = video_drvdata(file); struct v4l2_sliced_vbi_format *vbi = &fmt->fmt.sliced; @@ -196,12 +196,12 @@ int vidioc_try_fmt_sliced_vbi_out(struct file *file, void *fh, struct v4l2_forma return 0; } -int vidioc_s_fmt_sliced_vbi_out(struct file *file, void *fh, +int vidioc_s_fmt_sliced_vbi_out(struct file *file, void *priv, struct v4l2_format *fmt) { struct vivid_dev *dev = video_drvdata(file); struct v4l2_sliced_vbi_format *vbi = &fmt->fmt.sliced; - int ret = vidioc_try_fmt_sliced_vbi_out(file, fh, fmt); + int ret = vidioc_try_fmt_sliced_vbi_out(file, priv, fmt); if (ret) return ret; diff --git a/drivers/media/test-drivers/vivid/vivid-vbi-out.h b/drivers/media/test-drivers/vivid/vivid-vbi-out.h index 76584940cdaf..a28e55519ade 100644 --- a/drivers/media/test-drivers/vivid/vivid-vbi-out.h +++ b/drivers/media/test-drivers/vivid/vivid-vbi-out.h @@ -13,9 +13,9 @@ int vidioc_g_fmt_vbi_out(struct file *file, void *priv, struct v4l2_format *f); int vidioc_s_fmt_vbi_out(struct file *file, void *priv, struct v4l2_format *f); -int vidioc_g_fmt_sliced_vbi_out(struct file *file, void *fh, struct v4l2_format *fmt); -int vidioc_try_fmt_sliced_vbi_out(struct file *file, void *fh, struct v4l2_format *fmt); -int vidioc_s_fmt_sliced_vbi_out(struct file *file, void *fh, struct v4l2_format *fmt); +int vidioc_g_fmt_sliced_vbi_out(struct file *file, void *priv, struct v4l2_format *fmt); +int vidioc_try_fmt_sliced_vbi_out(struct file *file, void *priv, struct v4l2_format *fmt); +int vidioc_s_fmt_sliced_vbi_out(struct file *file, void *priv, struct v4l2_format *fmt); extern const struct vb2_ops vivid_vbi_out_qops; diff --git a/drivers/media/test-drivers/vivid/vivid-vid-cap.c b/drivers/media/test-drivers/vivid/vivid-vid-cap.c index 2e4c1ed37cd2..8b3162e82032 100644 --- a/drivers/media/test-drivers/vivid/vivid-vid-cap.c +++ b/drivers/media/test-drivers/vivid/vivid-vid-cap.c @@ -899,7 +899,7 @@ int vivid_vid_cap_g_selection(struct file *file, void *priv, return 0; } -int vivid_vid_cap_s_selection(struct file *file, void *fh, struct v4l2_selection *s) +int vivid_vid_cap_s_selection(struct file *file, void *priv, struct v4l2_selection *s) { struct vivid_dev *dev = video_drvdata(file); struct v4l2_rect *crop = &dev->crop_cap; @@ -1222,7 +1222,7 @@ int vidioc_s_input(struct file *file, void *priv, unsigned i) return 0; } -int vidioc_enumaudio(struct file *file, void *fh, struct v4l2_audio *vin) +int vidioc_enumaudio(struct file *file, void *priv, struct v4l2_audio *vin) { if (vin->index >= ARRAY_SIZE(vivid_audio_inputs)) return -EINVAL; @@ -1230,7 +1230,7 @@ int vidioc_enumaudio(struct file *file, void *fh, struct v4l2_audio *vin) return 0; } -int vidioc_g_audio(struct file *file, void *fh, struct v4l2_audio *vin) +int vidioc_g_audio(struct file *file, void *priv, struct v4l2_audio *vin) { struct vivid_dev *dev = video_drvdata(file); @@ -1240,7 +1240,7 @@ int vidioc_g_audio(struct file *file, void *fh, struct v4l2_audio *vin) return 0; } -int vidioc_s_audio(struct file *file, void *fh, const struct v4l2_audio *vin) +int vidioc_s_audio(struct file *file, void *priv, const struct v4l2_audio *vin) { struct vivid_dev *dev = video_drvdata(file); @@ -1252,7 +1252,7 @@ int vidioc_s_audio(struct file *file, void *fh, const struct v4l2_audio *vin) return 0; } -int vivid_video_g_frequency(struct file *file, void *fh, struct v4l2_frequency *vf) +int vivid_video_g_frequency(struct file *file, void *priv, struct v4l2_frequency *vf) { struct vivid_dev *dev = video_drvdata(file); @@ -1262,7 +1262,7 @@ int vivid_video_g_frequency(struct file *file, void *fh, struct v4l2_frequency * return 0; } -int vivid_video_s_frequency(struct file *file, void *fh, const struct v4l2_frequency *vf) +int vivid_video_s_frequency(struct file *file, void *priv, const struct v4l2_frequency *vf) { struct vivid_dev *dev = video_drvdata(file); @@ -1274,7 +1274,7 @@ int vivid_video_s_frequency(struct file *file, void *fh, const struct v4l2_frequ return 0; } -int vivid_video_s_tuner(struct file *file, void *fh, const struct v4l2_tuner *vt) +int vivid_video_s_tuner(struct file *file, void *priv, const struct v4l2_tuner *vt) { struct vivid_dev *dev = video_drvdata(file); @@ -1286,7 +1286,7 @@ int vivid_video_s_tuner(struct file *file, void *fh, const struct v4l2_tuner *vt return 0; } -int vivid_video_g_tuner(struct file *file, void *fh, struct v4l2_tuner *vt) +int vivid_video_g_tuner(struct file *file, void *priv, struct v4l2_tuner *vt) { struct vivid_dev *dev = video_drvdata(file); enum tpg_quality qual; @@ -1490,7 +1490,7 @@ static bool valid_cvt_gtf_timings(struct v4l2_dv_timings *timings) return false; } -int vivid_vid_cap_s_dv_timings(struct file *file, void *_fh, +int vivid_vid_cap_s_dv_timings(struct file *file, void *priv, struct v4l2_dv_timings *timings) { struct vivid_dev *dev = video_drvdata(file); @@ -1513,7 +1513,7 @@ int vivid_vid_cap_s_dv_timings(struct file *file, void *_fh, return 0; } -int vidioc_query_dv_timings(struct file *file, void *_fh, +int vidioc_query_dv_timings(struct file *file, void *priv, struct v4l2_dv_timings *timings) { struct vivid_dev *dev = video_drvdata(file); @@ -1600,7 +1600,7 @@ void vivid_update_connected_outputs(struct vivid_dev *dev) } } -int vidioc_s_edid(struct file *file, void *_fh, +int vidioc_s_edid(struct file *file, void *priv, struct v4l2_edid *edid) { struct vivid_dev *dev = video_drvdata(file); @@ -1638,7 +1638,7 @@ int vidioc_s_edid(struct file *file, void *_fh, return 0; } -int vidioc_enum_framesizes(struct file *file, void *fh, +int vidioc_enum_framesizes(struct file *file, void *priv, struct v4l2_frmsizeenum *fsize) { struct vivid_dev *dev = video_drvdata(file); diff --git a/drivers/media/test-drivers/vivid/vivid-vid-cap.h b/drivers/media/test-drivers/vivid/vivid-vid-cap.h index 7a8daf0af2ca..38a99f7e038e 100644 --- a/drivers/media/test-drivers/vivid/vivid-vid-cap.h +++ b/drivers/media/test-drivers/vivid/vivid-vid-cap.h @@ -29,7 +29,7 @@ int vidioc_g_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *f); int vidioc_try_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *f); int vidioc_s_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *f); int vivid_vid_cap_g_selection(struct file *file, void *priv, struct v4l2_selection *sel); -int vivid_vid_cap_s_selection(struct file *file, void *fh, struct v4l2_selection *s); +int vivid_vid_cap_s_selection(struct file *file, void *priv, struct v4l2_selection *s); int vivid_vid_cap_g_pixelaspect(struct file *file, void *priv, int type, struct v4l2_fract *f); int vidioc_enum_fmt_vid_overlay(struct file *file, void *priv, struct v4l2_fmtdesc *f); int vidioc_g_fmt_vid_overlay(struct file *file, void *priv, struct v4l2_format *f); @@ -38,19 +38,19 @@ int vidioc_s_fmt_vid_overlay(struct file *file, void *priv, struct v4l2_format * int vidioc_enum_input(struct file *file, void *priv, struct v4l2_input *inp); int vidioc_g_input(struct file *file, void *priv, unsigned *i); int vidioc_s_input(struct file *file, void *priv, unsigned i); -int vidioc_enumaudio(struct file *file, void *fh, struct v4l2_audio *vin); -int vidioc_g_audio(struct file *file, void *fh, struct v4l2_audio *vin); -int vidioc_s_audio(struct file *file, void *fh, const struct v4l2_audio *vin); -int vivid_video_g_frequency(struct file *file, void *fh, struct v4l2_frequency *vf); -int vivid_video_s_frequency(struct file *file, void *fh, const struct v4l2_frequency *vf); -int vivid_video_s_tuner(struct file *file, void *fh, const struct v4l2_tuner *vt); -int vivid_video_g_tuner(struct file *file, void *fh, struct v4l2_tuner *vt); +int vidioc_enumaudio(struct file *file, void *priv, struct v4l2_audio *vin); +int vidioc_g_audio(struct file *file, void *priv, struct v4l2_audio *vin); +int vidioc_s_audio(struct file *file, void *priv, const struct v4l2_audio *vin); +int vivid_video_g_frequency(struct file *file, void *priv, struct v4l2_frequency *vf); +int vivid_video_s_frequency(struct file *file, void *priv, const struct v4l2_frequency *vf); +int vivid_video_s_tuner(struct file *file, void *priv, const struct v4l2_tuner *vt); +int vivid_video_g_tuner(struct file *file, void *priv, struct v4l2_tuner *vt); int vidioc_querystd(struct file *file, void *priv, v4l2_std_id *id); int vivid_vid_cap_s_std(struct file *file, void *priv, v4l2_std_id id); -int vivid_vid_cap_s_dv_timings(struct file *file, void *_fh, struct v4l2_dv_timings *timings); -int vidioc_query_dv_timings(struct file *file, void *_fh, struct v4l2_dv_timings *timings); -int vidioc_s_edid(struct file *file, void *_fh, struct v4l2_edid *edid); -int vidioc_enum_framesizes(struct file *file, void *fh, struct v4l2_frmsizeenum *fsize); +int vivid_vid_cap_s_dv_timings(struct file *file, void *priv, struct v4l2_dv_timings *timings); +int vidioc_query_dv_timings(struct file *file, void *priv, struct v4l2_dv_timings *timings); +int vidioc_s_edid(struct file *file, void *priv, struct v4l2_edid *edid); +int vidioc_enum_framesizes(struct file *file, void *priv, struct v4l2_frmsizeenum *fsize); int vidioc_enum_frameintervals(struct file *file, void *priv, struct v4l2_frmivalenum *fival); int vivid_vid_cap_g_parm(struct file *file, void *priv, struct v4l2_streamparm *parm); int vivid_vid_cap_s_parm(struct file *file, void *priv, struct v4l2_streamparm *parm); diff --git a/drivers/media/test-drivers/vivid/vivid-vid-common.c b/drivers/media/test-drivers/vivid/vivid-vid-common.c index df7678db67fb..786a1aa3b26b 100644 --- a/drivers/media/test-drivers/vivid/vivid-vid-common.c +++ b/drivers/media/test-drivers/vivid/vivid-vid-common.c @@ -1021,7 +1021,7 @@ int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *id) return 0; } -int vidioc_g_dv_timings(struct file *file, void *_fh, +int vidioc_g_dv_timings(struct file *file, void *priv, struct v4l2_dv_timings *timings) { struct vivid_dev *dev = video_drvdata(file); @@ -1039,7 +1039,7 @@ int vidioc_g_dv_timings(struct file *file, void *_fh, return 0; } -int vidioc_enum_dv_timings(struct file *file, void *_fh, +int vidioc_enum_dv_timings(struct file *file, void *priv, struct v4l2_enum_dv_timings *timings) { struct vivid_dev *dev = video_drvdata(file); @@ -1056,7 +1056,7 @@ int vidioc_enum_dv_timings(struct file *file, void *_fh, NULL, NULL); } -int vidioc_dv_timings_cap(struct file *file, void *_fh, +int vidioc_dv_timings_cap(struct file *file, void *priv, struct v4l2_dv_timings_cap *cap) { struct vivid_dev *dev = video_drvdata(file); @@ -1073,7 +1073,7 @@ int vidioc_dv_timings_cap(struct file *file, void *_fh, return 0; } -int vidioc_g_edid(struct file *file, void *_fh, +int vidioc_g_edid(struct file *file, void *priv, struct v4l2_edid *edid) { struct vivid_dev *dev = video_drvdata(file); diff --git a/drivers/media/test-drivers/vivid/vivid-vid-common.h b/drivers/media/test-drivers/vivid/vivid-vid-common.h index c49ac85abaed..fb5878174dba 100644 --- a/drivers/media/test-drivers/vivid/vivid-vid-common.h +++ b/drivers/media/test-drivers/vivid/vivid-vid-common.h @@ -32,10 +32,10 @@ int vivid_vid_adjust_sel(unsigned flags, struct v4l2_rect *r); int vivid_enum_fmt_vid(struct file *file, void *priv, struct v4l2_fmtdesc *f); int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *id); -int vidioc_g_dv_timings(struct file *file, void *_fh, struct v4l2_dv_timings *timings); -int vidioc_enum_dv_timings(struct file *file, void *_fh, struct v4l2_enum_dv_timings *timings); -int vidioc_dv_timings_cap(struct file *file, void *_fh, struct v4l2_dv_timings_cap *cap); -int vidioc_g_edid(struct file *file, void *_fh, struct v4l2_edid *edid); +int vidioc_g_dv_timings(struct file *file, void *priv, struct v4l2_dv_timings *timings); +int vidioc_enum_dv_timings(struct file *file, void *priv, struct v4l2_enum_dv_timings *timings); +int vidioc_dv_timings_cap(struct file *file, void *priv, struct v4l2_dv_timings_cap *cap); +int vidioc_g_edid(struct file *file, void *priv, struct v4l2_edid *edid); int vidioc_subscribe_event(struct v4l2_fh *fh, const struct v4l2_event_subscription *sub); #endif diff --git a/drivers/media/test-drivers/vivid/vivid-vid-out.c b/drivers/media/test-drivers/vivid/vivid-vid-out.c index c3398bce6c15..8c037b90833e 100644 --- a/drivers/media/test-drivers/vivid/vivid-vid-out.c +++ b/drivers/media/test-drivers/vivid/vivid-vid-out.c @@ -672,7 +672,7 @@ int vivid_vid_out_g_selection(struct file *file, void *priv, return 0; } -int vivid_vid_out_s_selection(struct file *file, void *fh, struct v4l2_selection *s) +int vivid_vid_out_s_selection(struct file *file, void *priv, struct v4l2_selection *s) { struct vivid_dev *dev = video_drvdata(file); struct v4l2_rect *crop = &dev->crop_out; @@ -880,7 +880,7 @@ int vidioc_s_fmt_vid_out_overlay(struct file *file, void *priv, return ret; } -int vivid_vid_out_overlay(struct file *file, void *fh, unsigned i) +int vivid_vid_out_overlay(struct file *file, void *priv, unsigned i) { struct vivid_dev *dev = video_drvdata(file); @@ -893,7 +893,7 @@ int vivid_vid_out_overlay(struct file *file, void *fh, unsigned i) return 0; } -int vivid_vid_out_g_fbuf(struct file *file, void *fh, +int vivid_vid_out_g_fbuf(struct file *file, void *priv, struct v4l2_framebuffer *a) { struct vivid_dev *dev = video_drvdata(file); @@ -920,7 +920,7 @@ int vivid_vid_out_g_fbuf(struct file *file, void *fh, return 0; } -int vivid_vid_out_s_fbuf(struct file *file, void *fh, +int vivid_vid_out_s_fbuf(struct file *file, void *priv, const struct v4l2_framebuffer *a) { struct vivid_dev *dev = video_drvdata(file); @@ -1016,7 +1016,7 @@ int vidioc_s_output(struct file *file, void *priv, unsigned o) return 0; } -int vidioc_enumaudout(struct file *file, void *fh, struct v4l2_audioout *vout) +int vidioc_enumaudout(struct file *file, void *priv, struct v4l2_audioout *vout) { if (vout->index >= ARRAY_SIZE(vivid_audio_outputs)) return -EINVAL; @@ -1024,7 +1024,7 @@ int vidioc_enumaudout(struct file *file, void *fh, struct v4l2_audioout *vout) return 0; } -int vidioc_g_audout(struct file *file, void *fh, struct v4l2_audioout *vout) +int vidioc_g_audout(struct file *file, void *priv, struct v4l2_audioout *vout) { struct vivid_dev *dev = video_drvdata(file); @@ -1034,7 +1034,7 @@ int vidioc_g_audout(struct file *file, void *fh, struct v4l2_audioout *vout) return 0; } -int vidioc_s_audout(struct file *file, void *fh, const struct v4l2_audioout *vout) +int vidioc_s_audout(struct file *file, void *priv, const struct v4l2_audioout *vout) { struct vivid_dev *dev = video_drvdata(file); @@ -1072,7 +1072,7 @@ static bool valid_cvt_gtf_timings(struct v4l2_dv_timings *timings) return false; } -int vivid_vid_out_s_dv_timings(struct file *file, void *_fh, +int vivid_vid_out_s_dv_timings(struct file *file, void *priv, struct v4l2_dv_timings *timings) { struct vivid_dev *dev = video_drvdata(file); diff --git a/drivers/media/test-drivers/vivid/vivid-vid-out.h b/drivers/media/test-drivers/vivid/vivid-vid-out.h index 8d56314f4ea1..1d03891a5de5 100644 --- a/drivers/media/test-drivers/vivid/vivid-vid-out.h +++ b/drivers/media/test-drivers/vivid/vivid-vid-out.h @@ -22,23 +22,23 @@ int vidioc_g_fmt_vid_out(struct file *file, void *priv, struct v4l2_format *f); int vidioc_try_fmt_vid_out(struct file *file, void *priv, struct v4l2_format *f); int vidioc_s_fmt_vid_out(struct file *file, void *priv, struct v4l2_format *f); int vivid_vid_out_g_selection(struct file *file, void *priv, struct v4l2_selection *sel); -int vivid_vid_out_s_selection(struct file *file, void *fh, struct v4l2_selection *s); +int vivid_vid_out_s_selection(struct file *file, void *priv, struct v4l2_selection *s); int vivid_vid_out_g_pixelaspect(struct file *file, void *priv, int type, struct v4l2_fract *f); int vidioc_enum_fmt_vid_out_overlay(struct file *file, void *priv, struct v4l2_fmtdesc *f); int vidioc_g_fmt_vid_out_overlay(struct file *file, void *priv, struct v4l2_format *f); int vidioc_try_fmt_vid_out_overlay(struct file *file, void *priv, struct v4l2_format *f); int vidioc_s_fmt_vid_out_overlay(struct file *file, void *priv, struct v4l2_format *f); -int vivid_vid_out_overlay(struct file *file, void *fh, unsigned i); -int vivid_vid_out_g_fbuf(struct file *file, void *fh, struct v4l2_framebuffer *a); -int vivid_vid_out_s_fbuf(struct file *file, void *fh, const struct v4l2_framebuffer *a); +int vivid_vid_out_overlay(struct file *file, void *priv, unsigned i); +int vivid_vid_out_g_fbuf(struct file *file, void *priv, struct v4l2_framebuffer *a); +int vivid_vid_out_s_fbuf(struct file *file, void *priv, const struct v4l2_framebuffer *a); int vidioc_enum_output(struct file *file, void *priv, struct v4l2_output *out); int vidioc_g_output(struct file *file, void *priv, unsigned *i); int vidioc_s_output(struct file *file, void *priv, unsigned i); -int vidioc_enumaudout(struct file *file, void *fh, struct v4l2_audioout *vout); -int vidioc_g_audout(struct file *file, void *fh, struct v4l2_audioout *vout); -int vidioc_s_audout(struct file *file, void *fh, const struct v4l2_audioout *vout); +int vidioc_enumaudout(struct file *file, void *priv, struct v4l2_audioout *vout); +int vidioc_g_audout(struct file *file, void *priv, struct v4l2_audioout *vout); +int vidioc_s_audout(struct file *file, void *priv, const struct v4l2_audioout *vout); int vivid_vid_out_s_std(struct file *file, void *priv, v4l2_std_id id); -int vivid_vid_out_s_dv_timings(struct file *file, void *_fh, struct v4l2_dv_timings *timings); +int vivid_vid_out_s_dv_timings(struct file *file, void *priv, struct v4l2_dv_timings *timings); int vivid_vid_out_g_parm(struct file *file, void *priv, struct v4l2_streamparm *parm); #endif diff --git a/drivers/media/tuners/xc4000.c b/drivers/media/tuners/xc4000.c index 3cf54d776d36..b44c97e4e5ec 100644 --- a/drivers/media/tuners/xc4000.c +++ b/drivers/media/tuners/xc4000.c @@ -1087,12 +1087,12 @@ fail: static void xc_debug_dump(struct xc4000_priv *priv) { - u16 adc_envelope; + u16 adc_envelope = 0; u32 freq_error_hz = 0; - u16 lock_status; + u16 lock_status = 0; u32 hsync_freq_hz = 0; - u16 frame_lines; - u16 quality; + u16 frame_lines = 0; + u16 quality = 0; u16 signal = 0; u16 noise = 0; u8 hw_majorversion = 0, hw_minorversion = 0; diff --git a/drivers/media/tuners/xc5000.c b/drivers/media/tuners/xc5000.c index 30aa4ee958bd..a28481edd22e 100644 --- a/drivers/media/tuners/xc5000.c +++ b/drivers/media/tuners/xc5000.c @@ -622,14 +622,14 @@ static int xc5000_fwupload(struct dvb_frontend *fe, static void xc_debug_dump(struct xc5000_priv *priv) { - u16 adc_envelope; + u16 adc_envelope = 0; u32 freq_error_hz = 0; - u16 lock_status; + u16 lock_status = 0; u32 hsync_freq_hz = 0; - u16 frame_lines; - u16 quality; - u16 snr; - u16 totalgain; + u16 frame_lines = 0; + u16 quality = 0; + u16 snr = 0; + u16 totalgain = 0; u8 hw_majorversion = 0, hw_minorversion = 0; u8 fw_majorversion = 0, fw_minorversion = 0; u16 fw_buildversion = 0; @@ -1304,7 +1304,7 @@ static void xc5000_release(struct dvb_frontend *fe) mutex_lock(&xc5000_list_mutex); if (priv) { - cancel_delayed_work(&priv->timer_sleep); + cancel_delayed_work_sync(&priv->timer_sleep); hybrid_tuner_release_state(priv); } diff --git a/drivers/media/usb/au0828/au0828-video.c b/drivers/media/usb/au0828/au0828-video.c index e5dff969ed57..fbaa542c8259 100644 --- a/drivers/media/usb/au0828/au0828-video.c +++ b/drivers/media/usb/au0828/au0828-video.c @@ -1921,9 +1921,8 @@ int au0828_analog_register(struct au0828_dev *dev, iface_desc = interface->cur_altsetting; for (i = 0; i < iface_desc->desc.bNumEndpoints; i++) { endpoint = &iface_desc->endpoint[i].desc; - if (((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK) - == USB_DIR_IN) && - ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) + if (usb_endpoint_dir_in(endpoint) && + (usb_endpoint_type(endpoint) == USB_ENDPOINT_XFER_ISOC)) { /* we find our isoc in endpoint */ diff --git a/drivers/media/usb/cx231xx/cx231xx-417.c b/drivers/media/usb/cx231xx/cx231xx-417.c index e585c8f6e4c5..c695a97e202b 100644 --- a/drivers/media/usb/cx231xx/cx231xx-417.c +++ b/drivers/media/usb/cx231xx/cx231xx-417.c @@ -1499,7 +1499,7 @@ static int vidioc_g_selection(struct file *file, void *priv, return 0; } -static int vidioc_g_std(struct file *file, void *fh0, v4l2_std_id *norm) +static int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *norm) { struct cx231xx *dev = video_drvdata(file); diff --git a/drivers/media/usb/em28xx/Kconfig b/drivers/media/usb/em28xx/Kconfig index cb61fd6cc6c6..3122d4bdfc59 100644 --- a/drivers/media/usb/em28xx/Kconfig +++ b/drivers/media/usb/em28xx/Kconfig @@ -68,6 +68,7 @@ config VIDEO_EM28XX_DVB select MEDIA_TUNER_XC5000 if MEDIA_SUBDRV_AUTOSELECT select MEDIA_TUNER_MT2060 if MEDIA_SUBDRV_AUTOSELECT select DVB_MXL692 if MEDIA_SUBDRV_AUTOSELECT + select GPIOLIB_LEGACY if GPIOLIB && DVB_CXD2820R help This adds support for DVB cards based on the Empiatech em28xx chips. diff --git a/drivers/media/usb/em28xx/em28xx-dvb.c b/drivers/media/usb/em28xx/em28xx-dvb.c index 9fce59979e3b..b94f5c70ab75 100644 --- a/drivers/media/usb/em28xx/em28xx-dvb.c +++ b/drivers/media/usb/em28xx/em28xx-dvb.c @@ -727,7 +727,7 @@ static int em28xx_pctv_290e_set_lna(struct dvb_frontend *fe) struct dtv_frontend_properties *c = &fe->dtv_property_cache; struct em28xx_i2c_bus *i2c_bus = fe->dvb->priv; struct em28xx *dev = i2c_bus->dev; -#ifdef CONFIG_GPIOLIB +#ifdef CONFIG_GPIOLIB_LEGACY struct em28xx_dvb *dvb = dev->dvb; int ret; unsigned long flags; @@ -1705,7 +1705,7 @@ static int em28xx_dvb_init(struct em28xx *dev) goto out_free; } -#ifdef CONFIG_GPIOLIB +#ifdef CONFIG_GPIOLIB_LEGACY /* enable LNA for DVB-T, DVB-T2 and DVB-C */ result = gpio_request_one(dvb->lna_gpio, GPIOF_OUT_INIT_LOW, NULL); diff --git a/drivers/media/usb/gspca/gspca.c b/drivers/media/usb/gspca/gspca.c index 25edd2189654..3fc15d16df8e 100644 --- a/drivers/media/usb/gspca/gspca.c +++ b/drivers/media/usb/gspca/gspca.c @@ -1029,15 +1029,15 @@ static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv, return 0; } -static int vidioc_g_fmt_vid_cap(struct file *file, void *_priv, +static int vidioc_g_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *fmt) { struct gspca_dev *gspca_dev = video_drvdata(file); - u32 priv = fmt->fmt.pix.priv; + u32 fmt_priv = fmt->fmt.pix.priv; fmt->fmt.pix = gspca_dev->pixfmt; /* some drivers use priv internally, so keep the original value */ - fmt->fmt.pix.priv = priv; + fmt->fmt.pix.priv = fmt_priv; return 0; } @@ -1075,24 +1075,24 @@ static int try_fmt_vid_cap(struct gspca_dev *gspca_dev, return mode; /* used when s_fmt */ } -static int vidioc_try_fmt_vid_cap(struct file *file, void *_priv, +static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *fmt) { struct gspca_dev *gspca_dev = video_drvdata(file); - u32 priv = fmt->fmt.pix.priv; + u32 fmt_priv = fmt->fmt.pix.priv; if (try_fmt_vid_cap(gspca_dev, fmt) < 0) return -EINVAL; /* some drivers use priv internally, so keep the original value */ - fmt->fmt.pix.priv = priv; + fmt->fmt.pix.priv = fmt_priv; return 0; } -static int vidioc_s_fmt_vid_cap(struct file *file, void *_priv, +static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *fmt) { struct gspca_dev *gspca_dev = video_drvdata(file); - u32 priv = fmt->fmt.pix.priv; + u32 fmt_priv = fmt->fmt.pix.priv; int mode; if (vb2_is_busy(&gspca_dev->queue)) @@ -1109,7 +1109,7 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *_priv, else gspca_dev->pixfmt = gspca_dev->cam.cam_mode[mode]; /* some drivers use priv internally, so keep the original value */ - fmt->fmt.pix.priv = priv; + fmt->fmt.pix.priv = fmt_priv; return 0; } diff --git a/drivers/media/usb/hdpvr/hdpvr-video.c b/drivers/media/usb/hdpvr/hdpvr-video.c index fd7d2a9d0449..8c7ae362d992 100644 --- a/drivers/media/usb/hdpvr/hdpvr-video.c +++ b/drivers/media/usb/hdpvr/hdpvr-video.c @@ -52,6 +52,11 @@ struct hdpvr_fh { bool legacy_mode; }; +static inline struct hdpvr_fh *file_to_hdpvr_fh(struct file *file) +{ + return container_of(file_to_v4l2_fh(file), struct hdpvr_fh, fh); +} + static uint list_size(struct list_head *list) { struct list_head *tmp; @@ -380,8 +385,7 @@ static int hdpvr_open(struct file *file) return -ENOMEM; fh->legacy_mode = true; v4l2_fh_init(&fh->fh, video_devdata(file)); - v4l2_fh_add(&fh->fh); - file->private_data = fh; + v4l2_fh_add(&fh->fh, file); return 0; } @@ -390,7 +394,7 @@ static int hdpvr_release(struct file *file) struct hdpvr_device *dev = video_drvdata(file); mutex_lock(&dev->io_mutex); - if (file->private_data == dev->owner) { + if (file_to_v4l2_fh(file) == dev->owner) { hdpvr_stop_streaming(dev); dev->owner = NULL; } @@ -426,7 +430,7 @@ static ssize_t hdpvr_read(struct file *file, char __user *buffer, size_t count, mutex_unlock(&dev->io_mutex); goto err; } - dev->owner = file->private_data; + dev->owner = file_to_v4l2_fh(file); print_buffer_status(); } mutex_unlock(&dev->io_mutex); @@ -541,7 +545,7 @@ static __poll_t hdpvr_poll(struct file *filp, poll_table *wait) "start_streaming failed\n"); dev->status = STATUS_IDLE; } else { - dev->owner = filp->private_data; + dev->owner = file_to_v4l2_fh(filp); } print_buffer_status(); @@ -586,11 +590,11 @@ static int vidioc_querycap(struct file *file, void *priv, return 0; } -static int vidioc_s_std(struct file *file, void *_fh, +static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id std) { struct hdpvr_device *dev = video_drvdata(file); - struct hdpvr_fh *fh = _fh; + struct hdpvr_fh *fh = file_to_hdpvr_fh(file); u8 std_type = 1; if (!fh->legacy_mode && dev->options.video_input == HDPVR_COMPONENT) @@ -606,11 +610,12 @@ static int vidioc_s_std(struct file *file, void *_fh, return hdpvr_config_call(dev, CTRL_VIDEO_STD_TYPE, std_type); } -static int vidioc_g_std(struct file *file, void *_fh, +static int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *std) { struct hdpvr_device *dev = video_drvdata(file); - struct hdpvr_fh *fh = _fh; + struct hdpvr_fh *fh = file_to_hdpvr_fh(file); + if (!fh->legacy_mode && dev->options.video_input == HDPVR_COMPONENT) return -ENODATA; @@ -618,11 +623,11 @@ static int vidioc_g_std(struct file *file, void *_fh, return 0; } -static int vidioc_querystd(struct file *file, void *_fh, v4l2_std_id *a) +static int vidioc_querystd(struct file *file, void *priv, v4l2_std_id *a) { struct hdpvr_device *dev = video_drvdata(file); + struct hdpvr_fh *fh = file_to_hdpvr_fh(file); struct hdpvr_video_info vid_info; - struct hdpvr_fh *fh = _fh; int ret; *a = V4L2_STD_UNKNOWN; @@ -637,11 +642,11 @@ static int vidioc_querystd(struct file *file, void *_fh, v4l2_std_id *a) return ret; } -static int vidioc_s_dv_timings(struct file *file, void *_fh, +static int vidioc_s_dv_timings(struct file *file, void *priv, struct v4l2_dv_timings *timings) { struct hdpvr_device *dev = video_drvdata(file); - struct hdpvr_fh *fh = _fh; + struct hdpvr_fh *fh = file_to_hdpvr_fh(file); int i; fh->legacy_mode = false; @@ -660,11 +665,11 @@ static int vidioc_s_dv_timings(struct file *file, void *_fh, return 0; } -static int vidioc_g_dv_timings(struct file *file, void *_fh, +static int vidioc_g_dv_timings(struct file *file, void *priv, struct v4l2_dv_timings *timings) { struct hdpvr_device *dev = video_drvdata(file); - struct hdpvr_fh *fh = _fh; + struct hdpvr_fh *fh = file_to_hdpvr_fh(file); fh->legacy_mode = false; if (dev->options.video_input) @@ -673,11 +678,11 @@ static int vidioc_g_dv_timings(struct file *file, void *_fh, return 0; } -static int vidioc_query_dv_timings(struct file *file, void *_fh, +static int vidioc_query_dv_timings(struct file *file, void *priv, struct v4l2_dv_timings *timings) { struct hdpvr_device *dev = video_drvdata(file); - struct hdpvr_fh *fh = _fh; + struct hdpvr_fh *fh = file_to_hdpvr_fh(file); struct hdpvr_video_info vid_info; bool interlaced; int ret = 0; @@ -715,11 +720,11 @@ static int vidioc_query_dv_timings(struct file *file, void *_fh, return ret; } -static int vidioc_enum_dv_timings(struct file *file, void *_fh, +static int vidioc_enum_dv_timings(struct file *file, void *priv, struct v4l2_enum_dv_timings *timings) { struct hdpvr_device *dev = video_drvdata(file); - struct hdpvr_fh *fh = _fh; + struct hdpvr_fh *fh = file_to_hdpvr_fh(file); fh->legacy_mode = false; memset(timings->reserved, 0, sizeof(timings->reserved)); @@ -731,11 +736,11 @@ static int vidioc_enum_dv_timings(struct file *file, void *_fh, return 0; } -static int vidioc_dv_timings_cap(struct file *file, void *_fh, +static int vidioc_dv_timings_cap(struct file *file, void *priv, struct v4l2_dv_timings_cap *cap) { struct hdpvr_device *dev = video_drvdata(file); - struct hdpvr_fh *fh = _fh; + struct hdpvr_fh *fh = file_to_hdpvr_fh(file); fh->legacy_mode = false; if (dev->options.video_input) @@ -758,7 +763,7 @@ static const char *iname[] = { [HDPVR_COMPOSITE] = "Composite", }; -static int vidioc_enum_input(struct file *file, void *_fh, struct v4l2_input *i) +static int vidioc_enum_input(struct file *file, void *priv, struct v4l2_input *i) { unsigned int n; @@ -778,7 +783,7 @@ static int vidioc_enum_input(struct file *file, void *_fh, struct v4l2_input *i) return 0; } -static int vidioc_s_input(struct file *file, void *_fh, +static int vidioc_s_input(struct file *file, void *priv, unsigned int index) { struct hdpvr_device *dev = video_drvdata(file); @@ -812,7 +817,7 @@ static int vidioc_s_input(struct file *file, void *_fh, return retval; } -static int vidioc_g_input(struct file *file, void *private_data, +static int vidioc_g_input(struct file *file, void *priv, unsigned int *index) { struct hdpvr_device *dev = video_drvdata(file); @@ -844,7 +849,7 @@ static int vidioc_enumaudio(struct file *file, void *priv, return 0; } -static int vidioc_s_audio(struct file *file, void *private_data, +static int vidioc_s_audio(struct file *file, void *priv, const struct v4l2_audio *audio) { struct hdpvr_device *dev = video_drvdata(file); @@ -863,7 +868,7 @@ static int vidioc_s_audio(struct file *file, void *private_data, return retval; } -static int vidioc_g_audio(struct file *file, void *private_data, +static int vidioc_g_audio(struct file *file, void *priv, struct v4l2_audio *audio) { struct hdpvr_device *dev = video_drvdata(file); @@ -980,7 +985,7 @@ static int hdpvr_s_ctrl(struct v4l2_ctrl *ctrl) return ret; } -static int vidioc_enum_fmt_vid_cap(struct file *file, void *private_data, +static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv, struct v4l2_fmtdesc *f) { if (f->index != 0) @@ -991,11 +996,11 @@ static int vidioc_enum_fmt_vid_cap(struct file *file, void *private_data, return 0; } -static int vidioc_g_fmt_vid_cap(struct file *file, void *_fh, +static int vidioc_g_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *f) { struct hdpvr_device *dev = video_drvdata(file); - struct hdpvr_fh *fh = _fh; + struct hdpvr_fh *fh = file_to_hdpvr_fh(file); int ret; /* @@ -1048,7 +1053,7 @@ static int vidioc_encoder_cmd(struct file *filp, void *priv, switch (a->cmd) { case V4L2_ENC_CMD_START: - if (dev->owner && filp->private_data != dev->owner) { + if (dev->owner && file_to_v4l2_fh(filp) != dev->owner) { res = -EBUSY; break; } @@ -1056,12 +1061,12 @@ static int vidioc_encoder_cmd(struct file *filp, void *priv, break; res = hdpvr_start_streaming(dev); if (!res) - dev->owner = filp->private_data; + dev->owner = file_to_v4l2_fh(filp); else dev->status = STATUS_IDLE; break; case V4L2_ENC_CMD_STOP: - if (dev->owner && filp->private_data != dev->owner) { + if (dev->owner && file_to_v4l2_fh(filp) != dev->owner) { res = -EBUSY; break; } diff --git a/drivers/media/usb/pvrusb2/pvrusb2-v4l2.c b/drivers/media/usb/pvrusb2/pvrusb2-v4l2.c index ad38e1240541..f9535a484738 100644 --- a/drivers/media/usb/pvrusb2/pvrusb2-v4l2.c +++ b/drivers/media/usb/pvrusb2/pvrusb2-v4l2.c @@ -21,8 +21,6 @@ #include <media/v4l2-common.h> #include <media/v4l2-ioctl.h> -struct pvr2_v4l2_dev; -struct pvr2_v4l2_fh; struct pvr2_v4l2; struct pvr2_v4l2_dev { @@ -48,6 +46,11 @@ struct pvr2_v4l2_fh { unsigned int input_cnt; }; +static inline struct pvr2_v4l2_fh *to_pvr2_v4l2_fh(struct file *filp) +{ + return container_of(file_to_v4l2_fh(filp), struct pvr2_v4l2_fh, fh); +} + struct pvr2_v4l2 { struct pvr2_channel channel; @@ -108,7 +111,7 @@ static struct v4l2_format pvr_format [] = { */ static int pvr2_querycap(struct file *file, void *priv, struct v4l2_capability *cap) { - struct pvr2_v4l2_fh *fh = file->private_data; + struct pvr2_v4l2_fh *fh = to_pvr2_v4l2_fh(file); struct pvr2_hdw *hdw = fh->channel.mc_head->hdw; strscpy(cap->driver, "pvrusb2", sizeof(cap->driver)); @@ -123,7 +126,7 @@ static int pvr2_querycap(struct file *file, void *priv, struct v4l2_capability * static int pvr2_g_std(struct file *file, void *priv, v4l2_std_id *std) { - struct pvr2_v4l2_fh *fh = file->private_data; + struct pvr2_v4l2_fh *fh = to_pvr2_v4l2_fh(file); struct pvr2_hdw *hdw = fh->channel.mc_head->hdw; int val = 0; int ret; @@ -136,7 +139,7 @@ static int pvr2_g_std(struct file *file, void *priv, v4l2_std_id *std) static int pvr2_s_std(struct file *file, void *priv, v4l2_std_id std) { - struct pvr2_v4l2_fh *fh = file->private_data; + struct pvr2_v4l2_fh *fh = to_pvr2_v4l2_fh(file); struct pvr2_hdw *hdw = fh->channel.mc_head->hdw; int ret; @@ -148,7 +151,7 @@ static int pvr2_s_std(struct file *file, void *priv, v4l2_std_id std) static int pvr2_querystd(struct file *file, void *priv, v4l2_std_id *std) { - struct pvr2_v4l2_fh *fh = file->private_data; + struct pvr2_v4l2_fh *fh = to_pvr2_v4l2_fh(file); struct pvr2_hdw *hdw = fh->channel.mc_head->hdw; int val = 0; int ret; @@ -161,7 +164,7 @@ static int pvr2_querystd(struct file *file, void *priv, v4l2_std_id *std) static int pvr2_enum_input(struct file *file, void *priv, struct v4l2_input *vi) { - struct pvr2_v4l2_fh *fh = file->private_data; + struct pvr2_v4l2_fh *fh = to_pvr2_v4l2_fh(file); struct pvr2_hdw *hdw = fh->channel.mc_head->hdw; struct pvr2_ctrl *cptr; struct v4l2_input tmp; @@ -209,7 +212,7 @@ static int pvr2_enum_input(struct file *file, void *priv, struct v4l2_input *vi) static int pvr2_g_input(struct file *file, void *priv, unsigned int *i) { - struct pvr2_v4l2_fh *fh = file->private_data; + struct pvr2_v4l2_fh *fh = to_pvr2_v4l2_fh(file); struct pvr2_hdw *hdw = fh->channel.mc_head->hdw; unsigned int idx; struct pvr2_ctrl *cptr; @@ -231,7 +234,7 @@ static int pvr2_g_input(struct file *file, void *priv, unsigned int *i) static int pvr2_s_input(struct file *file, void *priv, unsigned int inp) { - struct pvr2_v4l2_fh *fh = file->private_data; + struct pvr2_v4l2_fh *fh = to_pvr2_v4l2_fh(file); struct pvr2_hdw *hdw = fh->channel.mc_head->hdw; int ret; @@ -286,7 +289,7 @@ static int pvr2_s_audio(struct file *file, void *priv, const struct v4l2_audio * static int pvr2_g_tuner(struct file *file, void *priv, struct v4l2_tuner *vt) { - struct pvr2_v4l2_fh *fh = file->private_data; + struct pvr2_v4l2_fh *fh = to_pvr2_v4l2_fh(file); struct pvr2_hdw *hdw = fh->channel.mc_head->hdw; if (vt->index != 0) @@ -298,7 +301,7 @@ static int pvr2_g_tuner(struct file *file, void *priv, struct v4l2_tuner *vt) static int pvr2_s_tuner(struct file *file, void *priv, const struct v4l2_tuner *vt) { - struct pvr2_v4l2_fh *fh = file->private_data; + struct pvr2_v4l2_fh *fh = to_pvr2_v4l2_fh(file); struct pvr2_hdw *hdw = fh->channel.mc_head->hdw; int ret; @@ -314,7 +317,7 @@ static int pvr2_s_tuner(struct file *file, void *priv, const struct v4l2_tuner * static int pvr2_s_frequency(struct file *file, void *priv, const struct v4l2_frequency *vf) { - struct pvr2_v4l2_fh *fh = file->private_data; + struct pvr2_v4l2_fh *fh = to_pvr2_v4l2_fh(file); struct pvr2_hdw *hdw = fh->channel.mc_head->hdw; unsigned long fv; struct v4l2_tuner vt; @@ -349,7 +352,7 @@ static int pvr2_s_frequency(struct file *file, void *priv, const struct v4l2_fre static int pvr2_g_frequency(struct file *file, void *priv, struct v4l2_frequency *vf) { - struct pvr2_v4l2_fh *fh = file->private_data; + struct pvr2_v4l2_fh *fh = to_pvr2_v4l2_fh(file); struct pvr2_hdw *hdw = fh->channel.mc_head->hdw; int val = 0; int cur_input; @@ -391,7 +394,7 @@ static int pvr2_enum_fmt_vid_cap(struct file *file, void *priv, struct v4l2_fmtd static int pvr2_g_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *vf) { - struct pvr2_v4l2_fh *fh = file->private_data; + struct pvr2_v4l2_fh *fh = to_pvr2_v4l2_fh(file); struct pvr2_hdw *hdw = fh->channel.mc_head->hdw; int val; @@ -411,7 +414,7 @@ static int pvr2_g_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format static int pvr2_try_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *vf) { - struct pvr2_v4l2_fh *fh = file->private_data; + struct pvr2_v4l2_fh *fh = to_pvr2_v4l2_fh(file); struct pvr2_hdw *hdw = fh->channel.mc_head->hdw; int lmin, lmax, ldef; struct pvr2_ctrl *hcp, *vcp; @@ -449,7 +452,7 @@ static int pvr2_try_fmt_vid_cap(struct file *file, void *priv, struct v4l2_forma static int pvr2_s_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *vf) { - struct pvr2_v4l2_fh *fh = file->private_data; + struct pvr2_v4l2_fh *fh = to_pvr2_v4l2_fh(file); struct pvr2_hdw *hdw = fh->channel.mc_head->hdw; struct pvr2_ctrl *hcp, *vcp; int ret = pvr2_try_fmt_vid_cap(file, fh, vf); @@ -466,7 +469,7 @@ static int pvr2_s_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format static int pvr2_streamon(struct file *file, void *priv, enum v4l2_buf_type i) { - struct pvr2_v4l2_fh *fh = file->private_data; + struct pvr2_v4l2_fh *fh = to_pvr2_v4l2_fh(file); struct pvr2_hdw *hdw = fh->channel.mc_head->hdw; struct pvr2_v4l2_dev *pdi = fh->pdi; int ret; @@ -485,7 +488,7 @@ static int pvr2_streamon(struct file *file, void *priv, enum v4l2_buf_type i) static int pvr2_streamoff(struct file *file, void *priv, enum v4l2_buf_type i) { - struct pvr2_v4l2_fh *fh = file->private_data; + struct pvr2_v4l2_fh *fh = to_pvr2_v4l2_fh(file); struct pvr2_hdw *hdw = fh->channel.mc_head->hdw; if (!fh->pdi->stream) { @@ -500,7 +503,7 @@ static int pvr2_streamoff(struct file *file, void *priv, enum v4l2_buf_type i) static int pvr2_query_ext_ctrl(struct file *file, void *priv, struct v4l2_query_ext_ctrl *vc) { - struct pvr2_v4l2_fh *fh = file->private_data; + struct pvr2_v4l2_fh *fh = to_pvr2_v4l2_fh(file); struct pvr2_hdw *hdw = fh->channel.mc_head->hdw; struct pvr2_ctrl *cptr; int val; @@ -561,7 +564,7 @@ static int pvr2_query_ext_ctrl(struct file *file, void *priv, static int pvr2_querymenu(struct file *file, void *priv, struct v4l2_querymenu *vm) { - struct pvr2_v4l2_fh *fh = file->private_data; + struct pvr2_v4l2_fh *fh = to_pvr2_v4l2_fh(file); struct pvr2_hdw *hdw = fh->channel.mc_head->hdw; unsigned int cnt = 0; int ret; @@ -577,7 +580,7 @@ static int pvr2_querymenu(struct file *file, void *priv, struct v4l2_querymenu * static int pvr2_g_ext_ctrls(struct file *file, void *priv, struct v4l2_ext_controls *ctls) { - struct pvr2_v4l2_fh *fh = file->private_data; + struct pvr2_v4l2_fh *fh = to_pvr2_v4l2_fh(file); struct pvr2_hdw *hdw = fh->channel.mc_head->hdw; struct v4l2_ext_control *ctrl; struct pvr2_ctrl *cptr; @@ -612,7 +615,7 @@ static int pvr2_g_ext_ctrls(struct file *file, void *priv, static int pvr2_s_ext_ctrls(struct file *file, void *priv, struct v4l2_ext_controls *ctls) { - struct pvr2_v4l2_fh *fh = file->private_data; + struct pvr2_v4l2_fh *fh = to_pvr2_v4l2_fh(file); struct pvr2_hdw *hdw = fh->channel.mc_head->hdw; struct v4l2_ext_control *ctrl; unsigned int idx; @@ -637,7 +640,7 @@ commit: static int pvr2_try_ext_ctrls(struct file *file, void *priv, struct v4l2_ext_controls *ctls) { - struct pvr2_v4l2_fh *fh = file->private_data; + struct pvr2_v4l2_fh *fh = to_pvr2_v4l2_fh(file); struct pvr2_hdw *hdw = fh->channel.mc_head->hdw; struct v4l2_ext_control *ctrl; struct pvr2_ctrl *pctl; @@ -659,7 +662,7 @@ static int pvr2_try_ext_ctrls(struct file *file, void *priv, static int pvr2_g_pixelaspect(struct file *file, void *priv, int type, struct v4l2_fract *f) { - struct pvr2_v4l2_fh *fh = file->private_data; + struct pvr2_v4l2_fh *fh = to_pvr2_v4l2_fh(file); struct pvr2_hdw *hdw = fh->channel.mc_head->hdw; struct v4l2_cropcap cap = { .type = type }; int ret; @@ -675,7 +678,7 @@ static int pvr2_g_pixelaspect(struct file *file, void *priv, static int pvr2_g_selection(struct file *file, void *priv, struct v4l2_selection *sel) { - struct pvr2_v4l2_fh *fh = file->private_data; + struct pvr2_v4l2_fh *fh = to_pvr2_v4l2_fh(file); struct pvr2_hdw *hdw = fh->channel.mc_head->hdw; struct v4l2_cropcap cap; int val = 0; @@ -726,7 +729,7 @@ static int pvr2_g_selection(struct file *file, void *priv, static int pvr2_s_selection(struct file *file, void *priv, struct v4l2_selection *sel) { - struct pvr2_v4l2_fh *fh = file->private_data; + struct pvr2_v4l2_fh *fh = to_pvr2_v4l2_fh(file); struct pvr2_hdw *hdw = fh->channel.mc_head->hdw; int ret; @@ -758,7 +761,7 @@ commit: static int pvr2_log_status(struct file *file, void *priv) { - struct pvr2_v4l2_fh *fh = file->private_data; + struct pvr2_v4l2_fh *fh = to_pvr2_v4l2_fh(file); struct pvr2_hdw *hdw = fh->channel.mc_head->hdw; pvr2_hdw_trigger_module_log(hdw); @@ -882,7 +885,7 @@ static void pvr2_v4l2_internal_check(struct pvr2_channel *chp) static int pvr2_v4l2_release(struct file *file) { - struct pvr2_v4l2_fh *fhp = file->private_data; + struct pvr2_v4l2_fh *fhp = to_pvr2_v4l2_fh(file); struct pvr2_v4l2 *vp = fhp->pdi->v4lp; struct pvr2_hdw *hdw = fhp->channel.mc_head->hdw; @@ -897,9 +900,8 @@ static int pvr2_v4l2_release(struct file *file) fhp->rhp = NULL; } - v4l2_fh_del(&fhp->fh); + v4l2_fh_del(&fhp->fh, file); v4l2_fh_exit(&fhp->fh); - file->private_data = NULL; pvr2_channel_done(&fhp->channel); pvr2_trace(PVR2_TRACE_STRUCT, @@ -1000,10 +1002,9 @@ static int pvr2_v4l2_open(struct file *file) } fhp->file = file; - file->private_data = fhp; fhp->fw_mode_flag = pvr2_hdw_cpufw_get_enabled(hdw); - v4l2_fh_add(&fhp->fh); + v4l2_fh_add(&fhp->fh, file); return 0; } @@ -1055,7 +1056,7 @@ static int pvr2_v4l2_iosetup(struct pvr2_v4l2_fh *fh) static ssize_t pvr2_v4l2_read(struct file *file, char __user *buff, size_t count, loff_t *ppos) { - struct pvr2_v4l2_fh *fh = file->private_data; + struct pvr2_v4l2_fh *fh = to_pvr2_v4l2_fh(file); int ret; if (fh->fw_mode_flag) { @@ -1117,7 +1118,7 @@ static ssize_t pvr2_v4l2_read(struct file *file, static __poll_t pvr2_v4l2_poll(struct file *file, poll_table *wait) { __poll_t mask = 0; - struct pvr2_v4l2_fh *fh = file->private_data; + struct pvr2_v4l2_fh *fh = to_pvr2_v4l2_fh(file); int ret; if (fh->fw_mode_flag) { diff --git a/drivers/media/usb/stk1160/stk1160-core.c b/drivers/media/usb/stk1160/stk1160-core.c index ce717502ea4c..25d725c2ab3c 100644 --- a/drivers/media/usb/stk1160/stk1160-core.c +++ b/drivers/media/usb/stk1160/stk1160-core.c @@ -195,8 +195,7 @@ static int stk1160_scan_usb(struct usb_interface *intf, struct usb_device *udev, if (udev->speed == USB_SPEED_HIGH) size = size * hb_mult(sizedescr); - if (usb_endpoint_xfer_isoc(desc) && - usb_endpoint_dir_in(desc)) { + if (usb_endpoint_is_isoc_in(desc)) { switch (desc->bEndpointAddress) { case STK1160_EP_AUDIO: has_audio = true; diff --git a/drivers/media/usb/stk1160/stk1160-video.c b/drivers/media/usb/stk1160/stk1160-video.c index 416cb74377eb..f4baf9263286 100644 --- a/drivers/media/usb/stk1160/stk1160-video.c +++ b/drivers/media/usb/stk1160/stk1160-video.c @@ -408,8 +408,13 @@ static int stk1160_fill_urb(struct stk1160 *dev, struct stk1160_urb *stk_urb, stk_urb->transfer_buffer = usb_alloc_noncoherent(dev->udev, sb_size, GFP_KERNEL, &stk_urb->dma, DMA_FROM_DEVICE, &stk_urb->sgt); - if (!stk_urb->transfer_buffer) + if (!stk_urb->transfer_buffer) { + /* + * If the buffer allocation failed, we exit but return 0 since + * we allow the driver working with less buffers. + */ goto free_urb; + } stk_urb->dev = dev; return 0; diff --git a/drivers/media/usb/uvc/uvc_ctrl.c b/drivers/media/usb/uvc/uvc_ctrl.c index efe609d70877..2905505c240c 100644 --- a/drivers/media/usb/uvc/uvc_ctrl.c +++ b/drivers/media/usb/uvc/uvc_ctrl.c @@ -376,6 +376,15 @@ static const struct uvc_control_info uvc_ctrls[] = { | UVC_CTRL_FLAG_GET_DEF | UVC_CTRL_FLAG_AUTO_UPDATE, }, + { + .entity = UVC_GUID_CHROMEOS_XU, + .selector = UVC_CROSXU_CONTROL_IQ_PROFILE, + .index = 3, + .size = 1, + .flags = UVC_CTRL_FLAG_SET_CUR + | UVC_CTRL_FLAG_GET_RANGE + | UVC_CTRL_FLAG_RESTORE, + }, }; static const u32 uvc_control_classes[] = { @@ -384,6 +393,19 @@ static const u32 uvc_control_classes[] = { }; static const int exposure_auto_mapping[] = { 2, 1, 4, 8 }; +static const int cros_colorfx_mapping[] = { + 1, /* V4L2_COLORFX_NONE */ + -1, /* V4L2_COLORFX_BW */ + -1, /* V4L2_COLORFX_SEPIA */ + -1, /* V4L2_COLORFX_NEGATIVE */ + -1, /* V4L2_COLORFX_EMBOSS */ + -1, /* V4L2_COLORFX_SKETCH */ + -1, /* V4L2_COLORFX_SKY_BLUE */ + -1, /* V4L2_COLORFX_GRASS_GREEN */ + -1, /* V4L2_COLORFX_SKIN_WHITEN */ + 0, /* V4L2_COLORFX_VIVID */ +}; + static bool uvc_ctrl_mapping_is_compound(struct uvc_control_mapping *mapping) { @@ -975,6 +997,18 @@ static const struct uvc_control_mapping uvc_ctrl_mappings[] = { .data_type = UVC_CTRL_DATA_TYPE_BITMASK, .name = "Region of Interest Auto Ctrls", }, + { + .id = V4L2_CID_COLORFX, + .entity = UVC_GUID_CHROMEOS_XU, + .selector = UVC_CROSXU_CONTROL_IQ_PROFILE, + .size = 8, + .offset = 0, + .v4l2_type = V4L2_CTRL_TYPE_MENU, + .data_type = UVC_CTRL_DATA_TYPE_ENUM, + .menu_mapping = cros_colorfx_mapping, + .menu_mask = BIT(V4L2_COLORFX_VIVID) | + BIT(V4L2_COLORFX_NONE), + }, }; /* ------------------------------------------------------------------------ @@ -1619,7 +1653,7 @@ static int __uvc_query_v4l2_ctrl(struct uvc_video_chain *chain, } if (ret == -EIO) { - dev_warn_ratelimited(&chain->dev->udev->dev, + dev_warn_ratelimited(&chain->dev->intf->dev, "UVC non compliance: Error %d querying master control %x (%s)\n", ret, master_map->id, uvc_map_get_name(master_map)); @@ -1643,7 +1677,7 @@ static int __uvc_query_v4l2_ctrl(struct uvc_video_chain *chain, ret = __uvc_queryctrl_boundaries(chain, ctrl, mapping, v4l2_ctrl); if (ret && !mapping->disabled) { - dev_warn(&chain->dev->udev->dev, + dev_warn(&chain->dev->intf->dev, "UVC non compliance: permanently disabling control %x (%s), due to error %d\n", mapping->id, uvc_map_get_name(mapping), ret); mapping->disabled = true; @@ -1858,7 +1892,7 @@ static int uvc_ctrl_set_handle(struct uvc_control *ctrl, struct uvc_fh *handle) lockdep_assert_held(&handle->chain->ctrl_mutex); if (ctrl->handle) { - dev_warn_ratelimited(&handle->stream->dev->udev->dev, + dev_warn_ratelimited(&handle->stream->dev->intf->dev, "UVC non compliance: Setting an async control with a pending operation."); if (ctrl->handle == handle) @@ -1956,7 +1990,7 @@ static void uvc_ctrl_status_event_work(struct work_struct *work) w->urb->interval = dev->int_ep->desc.bInterval; ret = usb_submit_urb(w->urb, GFP_KERNEL); if (ret < 0) - dev_err(&dev->udev->dev, + dev_err(&dev->intf->dev, "Failed to resubmit status URB (%d).\n", ret); } @@ -2895,7 +2929,7 @@ int uvc_ctrl_restore_values(struct uvc_device *dev) if (!ctrl->initialized || !ctrl->modified || (ctrl->info.flags & UVC_CTRL_FLAG_RESTORE) == 0) continue; - dev_dbg(&dev->udev->dev, + dev_dbg(&dev->intf->dev, "restoring control %pUl/%u/%u\n", ctrl->info.entity, ctrl->info.index, ctrl->info.selector); @@ -3181,15 +3215,6 @@ static void uvc_ctrl_init_ctrl(struct uvc_video_chain *chain, { unsigned int i; - /* - * XU controls initialization requires querying the device for control - * information. As some buggy UVC devices will crash when queried - * repeatedly in a tight loop, delay XU controls initialization until - * first use. - */ - if (UVC_ENTITY_TYPE(ctrl->entity) == UVC_VC_EXTENSION_UNIT) - return; - for (i = 0; i < ARRAY_SIZE(uvc_ctrls); ++i) { const struct uvc_control_info *info = &uvc_ctrls[i]; @@ -3307,7 +3332,6 @@ int uvc_ctrl_init_device(struct uvc_device *dev) void uvc_ctrl_cleanup_fh(struct uvc_fh *handle) { struct uvc_entity *entity; - int i; guard(mutex)(&handle->chain->ctrl_mutex); @@ -3325,7 +3349,7 @@ void uvc_ctrl_cleanup_fh(struct uvc_fh *handle) if (!WARN_ON(handle->pending_async_ctrls)) return; - for (i = 0; i < handle->pending_async_ctrls; i++) + for (unsigned int i = 0; i < handle->pending_async_ctrls; i++) uvc_pm_put(handle->stream->dev); } diff --git a/drivers/media/usb/uvc/uvc_driver.c b/drivers/media/usb/uvc/uvc_driver.c index 775bede0d93d..fa61f1d0ea2c 100644 --- a/drivers/media/usb/uvc/uvc_driver.c +++ b/drivers/media/usb/uvc/uvc_driver.c @@ -137,6 +137,9 @@ struct uvc_entity *uvc_entity_by_id(struct uvc_device *dev, int id) { struct uvc_entity *entity; + if (id == UVC_INVALID_ENTITY_ID) + return NULL; + list_for_each_entry(entity, &dev->entities, list) { if (entity->id == id) return entity; @@ -183,8 +186,6 @@ static void uvc_stream_delete(struct uvc_streaming *stream) if (stream->async_wq) destroy_workqueue(stream->async_wq); - mutex_destroy(&stream->mutex); - usb_put_intf(stream->intf); kfree(stream->formats); @@ -201,8 +202,6 @@ static struct uvc_streaming *uvc_stream_new(struct uvc_device *dev, if (stream == NULL) return NULL; - mutex_init(&stream->mutex); - stream->dev = dev; stream->intf = usb_get_intf(intf); stream->intfnum = intf->cur_altsetting->desc.bInterfaceNumber; @@ -795,14 +794,27 @@ static const u8 uvc_media_transport_input_guid[16] = UVC_GUID_UVC_MEDIA_TRANSPORT_INPUT; static const u8 uvc_processing_guid[16] = UVC_GUID_UVC_PROCESSING; -static struct uvc_entity *uvc_alloc_entity(u16 type, u16 id, - unsigned int num_pads, unsigned int extra_size) +static struct uvc_entity *uvc_alloc_new_entity(struct uvc_device *dev, u16 type, + u16 id, unsigned int num_pads, + unsigned int extra_size) { struct uvc_entity *entity; unsigned int num_inputs; unsigned int size; unsigned int i; + /* Per UVC 1.1+ spec 3.7.2, the ID should be non-zero. */ + if (id == 0) { + dev_err(&dev->intf->dev, "Found Unit with invalid ID 0\n"); + id = UVC_INVALID_ENTITY_ID; + } + + /* Per UVC 1.1+ spec 3.7.2, the ID is unique. */ + if (uvc_entity_by_id(dev, id)) { + dev_err(&dev->intf->dev, "Found multiple Units with ID %u\n", id); + id = UVC_INVALID_ENTITY_ID; + } + extra_size = roundup(extra_size, sizeof(*entity->pads)); if (num_pads) num_inputs = type & UVC_TERM_OUTPUT ? num_pads : num_pads - 1; @@ -812,7 +824,7 @@ static struct uvc_entity *uvc_alloc_entity(u16 type, u16 id, + num_inputs; entity = kzalloc(size, GFP_KERNEL); if (entity == NULL) - return NULL; + return ERR_PTR(-ENOMEM); entity->id = id; entity->type = type; @@ -882,7 +894,7 @@ static int uvc_parse_vendor_control(struct uvc_device *dev, unsigned int n, p; int handled = 0; - switch (le16_to_cpu(dev->udev->descriptor.idVendor)) { + switch (le16_to_cpu(udev->descriptor.idVendor)) { case 0x046d: /* Logitech */ if (buffer[1] != 0x41 || buffer[2] != 0x01) break; @@ -924,10 +936,10 @@ static int uvc_parse_vendor_control(struct uvc_device *dev, break; } - unit = uvc_alloc_entity(UVC_VC_EXTENSION_UNIT, buffer[3], - p + 1, 2*n); - if (unit == NULL) - return -ENOMEM; + unit = uvc_alloc_new_entity(dev, UVC_VC_EXTENSION_UNIT, + buffer[3], p + 1, 2 * n); + if (IS_ERR(unit)) + return PTR_ERR(unit); memcpy(unit->guid, &buffer[4], 16); unit->extension.bNumControls = buffer[20]; @@ -1036,10 +1048,10 @@ static int uvc_parse_standard_control(struct uvc_device *dev, return -EINVAL; } - term = uvc_alloc_entity(type | UVC_TERM_INPUT, buffer[3], - 1, n + p); - if (term == NULL) - return -ENOMEM; + term = uvc_alloc_new_entity(dev, type | UVC_TERM_INPUT, + buffer[3], 1, n + p); + if (IS_ERR(term)) + return PTR_ERR(term); if (UVC_ENTITY_TYPE(term) == UVC_ITT_CAMERA) { term->camera.bControlSize = n; @@ -1095,10 +1107,10 @@ static int uvc_parse_standard_control(struct uvc_device *dev, return 0; } - term = uvc_alloc_entity(type | UVC_TERM_OUTPUT, buffer[3], - 1, 0); - if (term == NULL) - return -ENOMEM; + term = uvc_alloc_new_entity(dev, type | UVC_TERM_OUTPUT, + buffer[3], 1, 0); + if (IS_ERR(term)) + return PTR_ERR(term); memcpy(term->baSourceID, &buffer[7], 1); @@ -1117,9 +1129,10 @@ static int uvc_parse_standard_control(struct uvc_device *dev, return -EINVAL; } - unit = uvc_alloc_entity(buffer[2], buffer[3], p + 1, 0); - if (unit == NULL) - return -ENOMEM; + unit = uvc_alloc_new_entity(dev, buffer[2], buffer[3], + p + 1, 0); + if (IS_ERR(unit)) + return PTR_ERR(unit); memcpy(unit->baSourceID, &buffer[5], p); @@ -1139,9 +1152,9 @@ static int uvc_parse_standard_control(struct uvc_device *dev, return -EINVAL; } - unit = uvc_alloc_entity(buffer[2], buffer[3], 2, n); - if (unit == NULL) - return -ENOMEM; + unit = uvc_alloc_new_entity(dev, buffer[2], buffer[3], 2, n); + if (IS_ERR(unit)) + return PTR_ERR(unit); memcpy(unit->baSourceID, &buffer[4], 1); unit->processing.wMaxMultiplier = @@ -1168,9 +1181,10 @@ static int uvc_parse_standard_control(struct uvc_device *dev, return -EINVAL; } - unit = uvc_alloc_entity(buffer[2], buffer[3], p + 1, n); - if (unit == NULL) - return -ENOMEM; + unit = uvc_alloc_new_entity(dev, buffer[2], buffer[3], + p + 1, n); + if (IS_ERR(unit)) + return PTR_ERR(unit); memcpy(unit->guid, &buffer[4], 16); unit->extension.bNumControls = buffer[20]; @@ -1315,9 +1329,10 @@ static int uvc_gpio_parse(struct uvc_device *dev) return dev_err_probe(&dev->intf->dev, irq, "No IRQ for privacy GPIO\n"); - unit = uvc_alloc_entity(UVC_EXT_GPIO_UNIT, UVC_EXT_GPIO_UNIT_ID, 0, 1); - if (!unit) - return -ENOMEM; + unit = uvc_alloc_new_entity(dev, UVC_EXT_GPIO_UNIT, + UVC_EXT_GPIO_UNIT_ID, 0, 1); + if (IS_ERR(unit)) + return PTR_ERR(unit); unit->gpio.gpio_privacy = gpio_privacy; unit->gpio.irq = irq; @@ -1868,7 +1883,7 @@ static int uvc_scan_device(struct uvc_device *dev) uvc_scan_fallback(dev); if (list_empty(&dev->chains)) { - dev_info(&dev->udev->dev, "No valid video chain found.\n"); + dev_info(&dev->intf->dev, "No valid video chain found.\n"); return -ENODEV; } @@ -1958,11 +1973,11 @@ static void uvc_unregister_video(struct uvc_device *dev) list_for_each_entry(stream, &dev->streams, list) { /* Nothing to do here, continue. */ - if (!video_is_registered(&stream->vdev)) + if (!video_is_registered(&stream->queue.vdev)) continue; - vb2_video_unregister_device(&stream->vdev); - vb2_video_unregister_device(&stream->meta.vdev); + vb2_video_unregister_device(&stream->queue.vdev); + vb2_video_unregister_device(&stream->meta.queue.vdev); /* * Now both vdevs are not streaming and all the ioctls will @@ -1984,12 +1999,12 @@ static void uvc_unregister_video(struct uvc_device *dev) int uvc_register_video_device(struct uvc_device *dev, struct uvc_streaming *stream, - struct video_device *vdev, struct uvc_video_queue *queue, enum v4l2_buf_type type, const struct v4l2_file_operations *fops, const struct v4l2_ioctl_ops *ioctl_ops) { + struct video_device *vdev = &queue->vdev; int ret; /* Initialize the video buffers queue. */ @@ -2071,9 +2086,9 @@ static int uvc_register_video(struct uvc_device *dev, uvc_debugfs_init_stream(stream); /* Register the device with V4L. */ - return uvc_register_video_device(dev, stream, &stream->vdev, - &stream->queue, stream->type, - &uvc_fops, &uvc_ioctl_ops); + return uvc_register_video_device(dev, stream, &stream->queue, + stream->type, &uvc_fops, + &uvc_ioctl_ops); } /* @@ -2092,7 +2107,7 @@ static int uvc_register_terms(struct uvc_device *dev, stream = uvc_stream_by_id(dev, term->id); if (stream == NULL) { - dev_info(&dev->udev->dev, + dev_info(&dev->intf->dev, "No streaming interface found for terminal %u.", term->id); continue; @@ -2109,7 +2124,7 @@ static int uvc_register_terms(struct uvc_device *dev, */ uvc_meta_register(stream); - term->vdev = &stream->vdev; + term->vdev = &stream->queue.vdev; } return 0; @@ -2128,7 +2143,7 @@ static int uvc_register_chains(struct uvc_device *dev) #ifdef CONFIG_MEDIA_CONTROLLER ret = uvc_mc_register_entities(chain); if (ret < 0) - dev_info(&dev->udev->dev, + dev_info(&dev->intf->dev, "Failed to register entities (%d).\n", ret); #endif } @@ -2229,23 +2244,23 @@ static int uvc_probe(struct usb_interface *intf, if (ret < 0) goto error; - dev_info(&dev->udev->dev, "Found UVC %u.%02x device %s (%04x:%04x)\n", + dev_info(&dev->intf->dev, "Found UVC %u.%02x device %s (%04x:%04x)\n", dev->uvc_version >> 8, dev->uvc_version & 0xff, udev->product ? udev->product : "<unnamed>", le16_to_cpu(udev->descriptor.idVendor), le16_to_cpu(udev->descriptor.idProduct)); if (dev->quirks != dev->info->quirks) { - dev_info(&dev->udev->dev, + dev_info(&dev->intf->dev, "Forcing device quirks to 0x%x by module parameter for testing purpose.\n", dev->quirks); - dev_info(&dev->udev->dev, + dev_info(&dev->intf->dev, "Please report required quirks to the linux-media mailing list.\n"); } if (dev->info->uvc_version) { dev->uvc_version = dev->info->uvc_version; - dev_info(&dev->udev->dev, "Forcing UVC version to %u.%02x\n", + dev_info(&dev->intf->dev, "Forcing UVC version to %u.%02x\n", dev->uvc_version >> 8, dev->uvc_version & 0xff); } @@ -2281,21 +2296,21 @@ static int uvc_probe(struct usb_interface *intf, /* Initialize the interrupt URB. */ ret = uvc_status_init(dev); if (ret < 0) { - dev_info(&dev->udev->dev, + dev_info(&dev->intf->dev, "Unable to initialize the status endpoint (%d), status interrupt will not be supported.\n", ret); } ret = uvc_gpio_init_irq(dev); if (ret < 0) { - dev_err(&dev->udev->dev, + dev_err(&dev->intf->dev, "Unable to request privacy GPIO IRQ (%d)\n", ret); goto error; } ret = uvc_meta_init(dev); if (ret < 0) { - dev_err(&dev->udev->dev, + dev_err(&dev->intf->dev, "Error initializing the metadata formats (%d)\n", ret); goto error; } diff --git a/drivers/media/usb/uvc/uvc_entity.c b/drivers/media/usb/uvc/uvc_entity.c index cc68dd24eb42..3823ac9c8045 100644 --- a/drivers/media/usb/uvc/uvc_entity.c +++ b/drivers/media/usb/uvc/uvc_entity.c @@ -140,7 +140,7 @@ int uvc_mc_register_entities(struct uvc_video_chain *chain) list_for_each_entry(entity, &chain->entities, chain) { ret = uvc_mc_init_entity(chain, entity); if (ret < 0) { - dev_info(&chain->dev->udev->dev, + dev_info(&chain->dev->intf->dev, "Failed to initialize entity for entity %u\n", entity->id); return ret; @@ -150,7 +150,7 @@ int uvc_mc_register_entities(struct uvc_video_chain *chain) list_for_each_entry(entity, &chain->entities, chain) { ret = uvc_mc_create_links(chain, entity); if (ret < 0) { - dev_info(&chain->dev->udev->dev, + dev_info(&chain->dev->intf->dev, "Failed to create links for entity %u\n", entity->id); return ret; diff --git a/drivers/media/usb/uvc/uvc_metadata.c b/drivers/media/usb/uvc/uvc_metadata.c index 229e08ff323e..c23b174965c3 100644 --- a/drivers/media/usb/uvc/uvc_metadata.c +++ b/drivers/media/usb/uvc/uvc_metadata.c @@ -23,10 +23,10 @@ * V4L2 ioctls */ -static int uvc_meta_v4l2_querycap(struct file *file, void *fh, +static int uvc_meta_v4l2_querycap(struct file *file, void *priv, struct v4l2_capability *cap) { - struct v4l2_fh *vfh = file->private_data; + struct v4l2_fh *vfh = file_to_v4l2_fh(file); struct uvc_streaming *stream = video_get_drvdata(vfh->vdev); struct uvc_video_chain *chain = stream->chain; @@ -39,28 +39,26 @@ static int uvc_meta_v4l2_querycap(struct file *file, void *fh, return 0; } -static int uvc_meta_v4l2_get_format(struct file *file, void *fh, +static int uvc_meta_v4l2_get_format(struct file *file, void *priv, struct v4l2_format *format) { - struct v4l2_fh *vfh = file->private_data; + struct v4l2_fh *vfh = file_to_v4l2_fh(file); struct uvc_streaming *stream = video_get_drvdata(vfh->vdev); struct v4l2_meta_format *fmt = &format->fmt.meta; if (format->type != vfh->vdev->queue->type) return -EINVAL; - memset(fmt, 0, sizeof(*fmt)); - fmt->dataformat = stream->meta.format; fmt->buffersize = UVC_METADATA_BUF_SIZE; return 0; } -static int uvc_meta_v4l2_try_format(struct file *file, void *fh, +static int uvc_meta_v4l2_try_format(struct file *file, void *priv, struct v4l2_format *format) { - struct v4l2_fh *vfh = file->private_data; + struct v4l2_fh *vfh = file_to_v4l2_fh(file); struct uvc_streaming *stream = video_get_drvdata(vfh->vdev); struct uvc_device *dev = stream->dev; struct v4l2_meta_format *fmt = &format->fmt.meta; @@ -69,11 +67,12 @@ static int uvc_meta_v4l2_try_format(struct file *file, void *fh, if (format->type != vfh->vdev->queue->type) return -EINVAL; - for (unsigned int i = 0; i < dev->nmeta_formats; i++) + for (unsigned int i = 0; i < dev->nmeta_formats; i++) { if (dev->meta_formats[i] == fmt->dataformat) { fmeta = fmt->dataformat; break; } + } memset(fmt, 0, sizeof(*fmt)); @@ -83,15 +82,15 @@ static int uvc_meta_v4l2_try_format(struct file *file, void *fh, return 0; } -static int uvc_meta_v4l2_set_format(struct file *file, void *fh, +static int uvc_meta_v4l2_set_format(struct file *file, void *priv, struct v4l2_format *format) { - struct v4l2_fh *vfh = file->private_data; + struct v4l2_fh *vfh = file_to_v4l2_fh(file); struct uvc_streaming *stream = video_get_drvdata(vfh->vdev); struct v4l2_meta_format *fmt = &format->fmt.meta; int ret; - ret = uvc_meta_v4l2_try_format(file, fh, format); + ret = uvc_meta_v4l2_try_format(file, priv, format); if (ret < 0) return ret; @@ -100,37 +99,28 @@ static int uvc_meta_v4l2_set_format(struct file *file, void *fh, * Metadata buffers would still be perfectly parseable, but it's more * consistent and cleaner to disallow that. */ - mutex_lock(&stream->mutex); - if (vb2_is_busy(&stream->meta.queue.queue)) - ret = -EBUSY; - else - stream->meta.format = fmt->dataformat; + return -EBUSY; - mutex_unlock(&stream->mutex); + stream->meta.format = fmt->dataformat; - return ret; + return 0; } -static int uvc_meta_v4l2_enum_formats(struct file *file, void *fh, +static int uvc_meta_v4l2_enum_formats(struct file *file, void *priv, struct v4l2_fmtdesc *fdesc) { - struct v4l2_fh *vfh = file->private_data; + struct v4l2_fh *vfh = file_to_v4l2_fh(file); struct uvc_streaming *stream = video_get_drvdata(vfh->vdev); struct uvc_device *dev = stream->dev; - u32 i = fdesc->index; if (fdesc->type != vfh->vdev->queue->type) return -EINVAL; - if (i >= dev->nmeta_formats) + if (fdesc->index >= dev->nmeta_formats) return -EINVAL; - memset(fdesc, 0, sizeof(*fdesc)); - - fdesc->type = vfh->vdev->queue->type; - fdesc->index = i; - fdesc->pixelformat = dev->meta_formats[i]; + fdesc->pixelformat = dev->meta_formats[fdesc->index]; return 0; } @@ -177,7 +167,6 @@ static struct uvc_entity *uvc_meta_find_msxu(struct uvc_device *dev) return NULL; } -#define MSXU_CONTROL_METADATA 0x9 static int uvc_meta_detect_msxu(struct uvc_device *dev) { u32 *data __free(kfree) = NULL; @@ -196,9 +185,12 @@ static int uvc_meta_detect_msxu(struct uvc_device *dev) if (!data) return -ENOMEM; - /* Check if the metadata is already enabled. */ + /* + * Check if the metadata is already enabled, or if the device always + * returns metadata. + */ ret = uvc_query_ctrl(dev, UVC_GET_CUR, entity->id, dev->intfnum, - MSXU_CONTROL_METADATA, data, sizeof(*data)); + UVC_MSXU_CONTROL_METADATA, data, sizeof(*data)); if (ret) return 0; @@ -208,21 +200,23 @@ static int uvc_meta_detect_msxu(struct uvc_device *dev) } /* - * We have seen devices that require 1 to enable the metadata, others - * requiring a value != 1 and others requiring a value >1. Luckily for - * us, the value from GET_MAX seems to work all the time. + * Set the value of UVC_MSXU_CONTROL_METADATA to the value reported by + * GET_MAX to enable production of MSXU metadata. The GET_MAX request + * reports the maximum size of the metadata, if its value is 0 then MSXU + * metadata is not supported. For more information, see + * https://learn.microsoft.com/en-us/windows-hardware/drivers/stream/uvc-extensions-1-5#2229-metadata-control */ ret = uvc_query_ctrl(dev, UVC_GET_MAX, entity->id, dev->intfnum, - MSXU_CONTROL_METADATA, data, sizeof(*data)); + UVC_MSXU_CONTROL_METADATA, data, sizeof(*data)); if (ret || !*data) return 0; /* - * If we can set MSXU_CONTROL_METADATA, the device will report + * If we can set UVC_MSXU_CONTROL_METADATA, the device will report * metadata. */ ret = uvc_query_ctrl(dev, UVC_SET_CUR, entity->id, dev->intfnum, - MSXU_CONTROL_METADATA, data, sizeof(*data)); + UVC_MSXU_CONTROL_METADATA, data, sizeof(*data)); if (!ret) dev->quirks |= UVC_QUIRK_MSXU_META; @@ -232,12 +226,11 @@ static int uvc_meta_detect_msxu(struct uvc_device *dev) int uvc_meta_register(struct uvc_streaming *stream) { struct uvc_device *dev = stream->dev; - struct video_device *vdev = &stream->meta.vdev; struct uvc_video_queue *queue = &stream->meta.queue; stream->meta.format = V4L2_META_FMT_UVC; - return uvc_register_video_device(dev, stream, vdev, queue, + return uvc_register_video_device(dev, stream, queue, V4L2_BUF_TYPE_META_CAPTURE, &uvc_meta_fops, &uvc_meta_ioctl_ops); } diff --git a/drivers/media/usb/uvc/uvc_status.c b/drivers/media/usb/uvc/uvc_status.c index ee01dce4b783..231cfee8e7c2 100644 --- a/drivers/media/usb/uvc/uvc_status.c +++ b/drivers/media/usb/uvc/uvc_status.c @@ -62,7 +62,8 @@ static int uvc_input_init(struct uvc_device *dev) __set_bit(EV_KEY, input->evbit); __set_bit(KEY_CAMERA, input->keybit); - if ((ret = input_register_device(input)) < 0) + ret = input_register_device(input); + if (ret < 0) goto error; dev->input = input; @@ -215,7 +216,7 @@ static void uvc_status_complete(struct urb *urb) return; default: - dev_warn(&dev->udev->dev, + dev_warn(&dev->intf->dev, "Non-zero status (%d) in status completion handler.\n", urb->status); return; @@ -247,7 +248,7 @@ static void uvc_status_complete(struct urb *urb) urb->interval = dev->int_ep->desc.bInterval; ret = usb_submit_urb(urb, GFP_ATOMIC); if (ret < 0) - dev_err(&dev->udev->dev, + dev_err(&dev->intf->dev, "Failed to resubmit status URB (%d).\n", ret); } diff --git a/drivers/media/usb/uvc/uvc_v4l2.c b/drivers/media/usb/uvc/uvc_v4l2.c index 160f9cf6e6db..9e4a251eca88 100644 --- a/drivers/media/usb/uvc/uvc_v4l2.c +++ b/drivers/media/usb/uvc/uvc_v4l2.c @@ -329,14 +329,12 @@ static int uvc_v4l2_try_format(struct uvc_streaming *stream, * developers test their webcams with the Linux driver as well as with * the Windows driver). */ - mutex_lock(&stream->mutex); if (stream->dev->quirks & UVC_QUIRK_PROBE_EXTRAFIELDS) probe->dwMaxVideoFrameSize = stream->ctrl.dwMaxVideoFrameSize; /* Probe the device. */ ret = uvc_probe_video(stream, probe); - mutex_unlock(&stream->mutex); if (ret < 0) return ret; @@ -388,26 +386,22 @@ static int uvc_v4l2_try_format(struct uvc_streaming *stream, return ret; } -static int uvc_ioctl_g_fmt(struct file *file, void *fh, +static int uvc_ioctl_g_fmt(struct file *file, void *priv, struct v4l2_format *fmt) { - struct uvc_fh *handle = fh; + struct uvc_fh *handle = to_uvc_fh(file); struct uvc_streaming *stream = handle->stream; const struct uvc_format *format; const struct uvc_frame *frame; - int ret = 0; if (fmt->type != stream->type) return -EINVAL; - mutex_lock(&stream->mutex); format = stream->cur_format; frame = stream->cur_frame; - if (format == NULL || frame == NULL) { - ret = -EINVAL; - goto done; - } + if (!format || !frame) + return -EINVAL; fmt->fmt.pix.pixelformat = format->fcc; fmt->fmt.pix.width = frame->wWidth; @@ -419,15 +413,13 @@ static int uvc_ioctl_g_fmt(struct file *file, void *fh, fmt->fmt.pix.xfer_func = format->xfer_func; fmt->fmt.pix.ycbcr_enc = format->ycbcr_enc; -done: - mutex_unlock(&stream->mutex); - return ret; + return 0; } -static int uvc_ioctl_s_fmt(struct file *file, void *fh, +static int uvc_ioctl_s_fmt(struct file *file, void *priv, struct v4l2_format *fmt) { - struct uvc_fh *handle = fh; + struct uvc_fh *handle = to_uvc_fh(file); struct uvc_streaming *stream = handle->stream; struct uvc_streaming_control probe; const struct uvc_format *format; @@ -441,35 +433,27 @@ static int uvc_ioctl_s_fmt(struct file *file, void *fh, if (ret < 0) return ret; - mutex_lock(&stream->mutex); - if (vb2_is_busy(&stream->queue.queue)) { - ret = -EBUSY; - goto done; - } + if (vb2_is_busy(&stream->queue.queue)) + return -EBUSY; stream->ctrl = probe; stream->cur_format = format; stream->cur_frame = frame; -done: - mutex_unlock(&stream->mutex); - return ret; + return 0; } -static int uvc_ioctl_g_parm(struct file *file, void *fh, +static int uvc_ioctl_g_parm(struct file *file, void *priv, struct v4l2_streamparm *parm) { u32 numerator, denominator; - struct uvc_fh *handle = fh; + struct uvc_fh *handle = to_uvc_fh(file); struct uvc_streaming *stream = handle->stream; if (parm->type != stream->type) return -EINVAL; - mutex_lock(&stream->mutex); numerator = stream->ctrl.dwFrameInterval; - mutex_unlock(&stream->mutex); - denominator = 10000000; v4l2_simplify_fraction(&numerator, &denominator, 8, 333); @@ -493,10 +477,10 @@ static int uvc_ioctl_g_parm(struct file *file, void *fh, return 0; } -static int uvc_ioctl_s_parm(struct file *file, void *fh, +static int uvc_ioctl_s_parm(struct file *file, void *priv, struct v4l2_streamparm *parm) { - struct uvc_fh *handle = fh; + struct uvc_fh *handle = to_uvc_fh(file); struct uvc_streaming *stream = handle->stream; struct uvc_streaming_control probe; struct v4l2_fract timeperframe; @@ -519,12 +503,8 @@ static int uvc_ioctl_s_parm(struct file *file, void *fh, uvc_dbg(stream->dev, FORMAT, "Setting frame interval to %u/%u (%u)\n", timeperframe.numerator, timeperframe.denominator, interval); - mutex_lock(&stream->mutex); - - if (uvc_queue_streaming(&stream->queue)) { - mutex_unlock(&stream->mutex); + if (uvc_queue_streaming(&stream->queue)) return -EBUSY; - } format = stream->cur_format; frame = stream->cur_frame; @@ -556,14 +536,11 @@ static int uvc_ioctl_s_parm(struct file *file, void *fh, /* Probe the device with the new settings. */ ret = uvc_probe_video(stream, &probe); - if (ret < 0) { - mutex_unlock(&stream->mutex); + if (ret < 0) return ret; - } stream->ctrl = probe; stream->cur_frame = frame; - mutex_unlock(&stream->mutex); /* Return the actual frame period. */ timeperframe.numerator = probe.dwFrameInterval; @@ -599,18 +576,17 @@ static int uvc_v4l2_open(struct file *file) if (!handle) return -ENOMEM; - v4l2_fh_init(&handle->vfh, &stream->vdev); - v4l2_fh_add(&handle->vfh); + v4l2_fh_init(&handle->vfh, &stream->queue.vdev); + v4l2_fh_add(&handle->vfh, file); handle->chain = stream->chain; handle->stream = stream; - file->private_data = handle; return 0; } static int uvc_v4l2_release(struct file *file) { - struct uvc_fh *handle = file->private_data; + struct uvc_fh *handle = to_uvc_fh(file); struct uvc_streaming *stream = handle->stream; uvc_dbg(stream->dev, CALLS, "%s\n", __func__); @@ -623,10 +599,10 @@ static int uvc_v4l2_release(struct file *file) return 0; } -static int uvc_ioctl_querycap(struct file *file, void *fh, +static int uvc_ioctl_querycap(struct file *file, void *priv, struct v4l2_capability *cap) { - struct uvc_fh *handle = file->private_data; + struct uvc_fh *handle = to_uvc_fh(file); struct uvc_video_chain *chain = handle->chain; struct uvc_streaming *stream = handle->stream; @@ -639,10 +615,10 @@ static int uvc_ioctl_querycap(struct file *file, void *fh, return 0; } -static int uvc_ioctl_enum_fmt(struct file *file, void *fh, +static int uvc_ioctl_enum_fmt(struct file *file, void *priv, struct v4l2_fmtdesc *fmt) { - struct uvc_fh *handle = fh; + struct uvc_fh *handle = to_uvc_fh(file); struct uvc_streaming *stream = handle->stream; enum v4l2_buf_type type = fmt->type; const struct uvc_format *format; @@ -663,20 +639,20 @@ static int uvc_ioctl_enum_fmt(struct file *file, void *fh, return 0; } -static int uvc_ioctl_try_fmt(struct file *file, void *fh, +static int uvc_ioctl_try_fmt(struct file *file, void *priv, struct v4l2_format *fmt) { - struct uvc_fh *handle = fh; + struct uvc_fh *handle = to_uvc_fh(file); struct uvc_streaming *stream = handle->stream; struct uvc_streaming_control probe; return uvc_v4l2_try_format(stream, fmt, &probe, NULL, NULL); } -static int uvc_ioctl_enum_input(struct file *file, void *fh, +static int uvc_ioctl_enum_input(struct file *file, void *priv, struct v4l2_input *input) { - struct uvc_fh *handle = fh; + struct uvc_fh *handle = to_uvc_fh(file); struct uvc_video_chain *chain = handle->chain; const struct uvc_entity *selector = chain->selector; struct uvc_entity *iterm = NULL; @@ -716,9 +692,9 @@ static int uvc_ioctl_enum_input(struct file *file, void *fh, return 0; } -static int uvc_ioctl_g_input(struct file *file, void *fh, unsigned int *input) +static int uvc_ioctl_g_input(struct file *file, void *priv, unsigned int *input) { - struct uvc_fh *handle = fh; + struct uvc_fh *handle = to_uvc_fh(file); struct uvc_video_chain *chain = handle->chain; u8 *buf; int ret; @@ -744,9 +720,9 @@ static int uvc_ioctl_g_input(struct file *file, void *fh, unsigned int *input) return ret; } -static int uvc_ioctl_s_input(struct file *file, void *fh, unsigned int input) +static int uvc_ioctl_s_input(struct file *file, void *priv, unsigned int input) { - struct uvc_fh *handle = fh; + struct uvc_fh *handle = to_uvc_fh(file); struct uvc_streaming *stream = handle->stream; struct uvc_video_chain *chain = handle->chain; u8 *buf; @@ -778,10 +754,10 @@ static int uvc_ioctl_s_input(struct file *file, void *fh, unsigned int input) return ret; } -static int uvc_ioctl_query_ext_ctrl(struct file *file, void *fh, +static int uvc_ioctl_query_ext_ctrl(struct file *file, void *priv, struct v4l2_query_ext_ctrl *qec) { - struct uvc_fh *handle = fh; + struct uvc_fh *handle = to_uvc_fh(file); struct uvc_video_chain *chain = handle->chain; return uvc_query_v4l2_ctrl(chain, qec); @@ -806,10 +782,10 @@ static int uvc_ctrl_check_access(struct uvc_video_chain *chain, return ret; } -static int uvc_ioctl_g_ext_ctrls(struct file *file, void *fh, +static int uvc_ioctl_g_ext_ctrls(struct file *file, void *priv, struct v4l2_ext_controls *ctrls) { - struct uvc_fh *handle = fh; + struct uvc_fh *handle = to_uvc_fh(file); struct uvc_video_chain *chain = handle->chain; struct v4l2_ext_control *ctrl = ctrls->controls; unsigned int i; @@ -890,35 +866,35 @@ static int uvc_ioctl_s_try_ext_ctrls(struct uvc_fh *handle, return uvc_ctrl_rollback(handle); } -static int uvc_ioctl_s_ext_ctrls(struct file *file, void *fh, +static int uvc_ioctl_s_ext_ctrls(struct file *file, void *priv, struct v4l2_ext_controls *ctrls) { - struct uvc_fh *handle = fh; + struct uvc_fh *handle = to_uvc_fh(file); return uvc_ioctl_s_try_ext_ctrls(handle, ctrls, VIDIOC_S_EXT_CTRLS); } -static int uvc_ioctl_try_ext_ctrls(struct file *file, void *fh, +static int uvc_ioctl_try_ext_ctrls(struct file *file, void *priv, struct v4l2_ext_controls *ctrls) { - struct uvc_fh *handle = fh; + struct uvc_fh *handle = to_uvc_fh(file); return uvc_ioctl_s_try_ext_ctrls(handle, ctrls, VIDIOC_TRY_EXT_CTRLS); } -static int uvc_ioctl_querymenu(struct file *file, void *fh, +static int uvc_ioctl_querymenu(struct file *file, void *priv, struct v4l2_querymenu *qm) { - struct uvc_fh *handle = fh; + struct uvc_fh *handle = to_uvc_fh(file); struct uvc_video_chain *chain = handle->chain; return uvc_query_v4l2_menu(chain, qm); } -static int uvc_ioctl_g_selection(struct file *file, void *fh, +static int uvc_ioctl_g_selection(struct file *file, void *priv, struct v4l2_selection *sel) { - struct uvc_fh *handle = fh; + struct uvc_fh *handle = to_uvc_fh(file); struct uvc_streaming *stream = handle->stream; if (sel->type != stream->type) @@ -941,18 +917,16 @@ static int uvc_ioctl_g_selection(struct file *file, void *fh, sel->r.left = 0; sel->r.top = 0; - mutex_lock(&stream->mutex); sel->r.width = stream->cur_frame->wWidth; sel->r.height = stream->cur_frame->wHeight; - mutex_unlock(&stream->mutex); return 0; } -static int uvc_ioctl_enum_framesizes(struct file *file, void *fh, +static int uvc_ioctl_enum_framesizes(struct file *file, void *priv, struct v4l2_frmsizeenum *fsize) { - struct uvc_fh *handle = fh; + struct uvc_fh *handle = to_uvc_fh(file); struct uvc_streaming *stream = handle->stream; const struct uvc_format *format = NULL; const struct uvc_frame *frame = NULL; @@ -989,10 +963,10 @@ static int uvc_ioctl_enum_framesizes(struct file *file, void *fh, return 0; } -static int uvc_ioctl_enum_frameintervals(struct file *file, void *fh, +static int uvc_ioctl_enum_frameintervals(struct file *file, void *priv, struct v4l2_frmivalenum *fival) { - struct uvc_fh *handle = fh; + struct uvc_fh *handle = to_uvc_fh(file); struct uvc_streaming *stream = handle->stream; const struct uvc_format *format = NULL; const struct uvc_frame *frame = NULL; @@ -1061,10 +1035,10 @@ static int uvc_ioctl_subscribe_event(struct v4l2_fh *fh, } } -static long uvc_ioctl_default(struct file *file, void *fh, bool valid_prio, +static long uvc_ioctl_default(struct file *file, void *priv, bool valid_prio, unsigned int cmd, void *arg) { - struct uvc_fh *handle = fh; + struct uvc_fh *handle = to_uvc_fh(file); struct uvc_video_chain *chain = handle->chain; switch (cmd) { @@ -1170,7 +1144,7 @@ static int uvc_v4l2_put_xu_query(const struct uvc_xu_control_query *kp, static long uvc_v4l2_compat_ioctl32(struct file *file, unsigned int cmd, unsigned long arg) { - struct uvc_fh *handle = file->private_data; + struct uvc_fh *handle = to_uvc_fh(file); union { struct uvc_xu_control_mapping xmap; struct uvc_xu_control_query xqry; @@ -1221,7 +1195,7 @@ static long uvc_v4l2_compat_ioctl32(struct file *file, static long uvc_v4l2_unlocked_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { - struct uvc_fh *handle = file->private_data; + struct uvc_fh *handle = to_uvc_fh(file); unsigned int converted_cmd = v4l2_translate_cmd(cmd); int ret; diff --git a/drivers/media/usb/uvc/uvc_video.c b/drivers/media/usb/uvc/uvc_video.c index a5013a7fbca4..784be9330320 100644 --- a/drivers/media/usb/uvc/uvc_video.c +++ b/drivers/media/usb/uvc/uvc_video.c @@ -95,14 +95,14 @@ int uvc_query_ctrl(struct uvc_device *dev, u8 query, u8 unit, */ if (ret > 0 && query != UVC_GET_INFO) { memset(data + ret, 0, size - ret); - dev_warn_once(&dev->udev->dev, + dev_warn_once(&dev->intf->dev, "UVC non compliance: %s control %u on unit %u returned %d bytes when we expected %u.\n", uvc_query_name(query), cs, unit, ret, size); return 0; } if (ret != -EPIPE) { - dev_err(&dev->udev->dev, + dev_err(&dev->intf->dev, "Failed to query (%s) UVC control %u on unit %u: %d (exp. %u).\n", uvc_query_name(query), cs, unit, ret, size); return ret < 0 ? ret : -EPIPE; @@ -119,7 +119,7 @@ int uvc_query_ctrl(struct uvc_device *dev, u8 query, u8 unit, *(u8 *)data = tmp; if (ret != 1) { - dev_err_ratelimited(&dev->udev->dev, + dev_err_ratelimited(&dev->intf->dev, "Failed to query (%s) UVC error code control %u on unit %u: %d (exp. 1).\n", uvc_query_name(query), cs, unit, ret); return ret < 0 ? ret : -EPIPE; @@ -266,7 +266,7 @@ static void uvc_fixup_video_ctrl(struct uvc_streaming *stream, if (stream->intf->num_altsetting > 1 && ctrl->dwMaxPayloadTransferSize > stream->maxpsize) { dev_warn_ratelimited(&stream->intf->dev, - "UVC non compliance: the max payload transmission size (%u) exceeds the size of the ep max packet (%u). Using the max size.\n", + "UVC non compliance: Reducing max payload transfer size (%u) to fit endpoint limit (%u).\n", ctrl->dwMaxPayloadTransferSize, stream->maxpsize); ctrl->dwMaxPayloadTransferSize = stream->maxpsize; @@ -1691,7 +1691,7 @@ static void uvc_video_complete(struct urb *urb) struct uvc_streaming *stream = uvc_urb->stream; struct uvc_video_queue *queue = &stream->queue; struct uvc_video_queue *qmeta = &stream->meta.queue; - struct vb2_queue *vb2_qmeta = stream->meta.vdev.queue; + struct vb2_queue *vb2_qmeta = stream->meta.queue.vdev.queue; struct uvc_buffer *buf = NULL; struct uvc_buffer *buf_meta = NULL; unsigned long flags; diff --git a/drivers/media/usb/uvc/uvcvideo.h b/drivers/media/usb/uvc/uvcvideo.h index 757254fc4fe9..24292efbe47d 100644 --- a/drivers/media/usb/uvc/uvcvideo.h +++ b/drivers/media/usb/uvc/uvcvideo.h @@ -41,6 +41,8 @@ #define UVC_EXT_GPIO_UNIT 0x7ffe #define UVC_EXT_GPIO_UNIT_ID 0x100 +#define UVC_INVALID_ENTITY_ID 0xffff + /* ------------------------------------------------------------------------ * Driver specific constants. */ @@ -328,6 +330,7 @@ struct uvc_buffer { #define UVC_QUEUE_DISCONNECTED (1 << 0) struct uvc_video_queue { + struct video_device vdev; struct vb2_queue queue; struct mutex mutex; /* * Serializes vb2_queue and @@ -450,7 +453,6 @@ struct uvc_urb { struct uvc_streaming { struct list_head list; struct uvc_device *dev; - struct video_device vdev; struct uvc_video_chain *chain; atomic_t active; @@ -469,12 +471,6 @@ struct uvc_streaming { const struct uvc_format *cur_format; const struct uvc_frame *cur_frame; - /* - * Protect access to ctrl, cur_format, cur_frame and hardware video - * probe control. - */ - struct mutex mutex; - /* Buffers queue. */ unsigned int frozen : 1; struct uvc_video_queue queue; @@ -483,7 +479,6 @@ struct uvc_streaming { struct uvc_buffer *meta_buf); struct { - struct video_device vdev; struct uvc_video_queue queue; u32 format; } meta; @@ -637,6 +632,11 @@ struct uvc_fh { unsigned int pending_async_ctrls; }; +static inline struct uvc_fh *to_uvc_fh(struct file *filp) +{ + return container_of(file_to_v4l2_fh(filp), struct uvc_fh, vfh); +} + /* ------------------------------------------------------------------------ * Debugging, printing and logging */ @@ -667,7 +667,7 @@ extern unsigned int uvc_hw_timestamps_param; #define uvc_dbg(_dev, flag, fmt, ...) \ do { \ if (uvc_dbg_param & UVC_DBG_##flag) \ - dev_printk(KERN_DEBUG, &(_dev)->udev->dev, fmt, \ + dev_printk(KERN_DEBUG, &(_dev)->intf->dev, fmt, \ ##__VA_ARGS__); \ } while (0) @@ -680,7 +680,7 @@ do { \ #define uvc_warn_once(_dev, warn, fmt, ...) \ do { \ if (!test_and_set_bit(warn, &(_dev)->warnings)) \ - dev_info(&(_dev)->udev->dev, fmt, ##__VA_ARGS__); \ + dev_info(&(_dev)->intf->dev, fmt, ##__VA_ARGS__); \ } while (0) /* -------------------------------------------------------------------------- @@ -733,7 +733,6 @@ int uvc_meta_register(struct uvc_streaming *stream); int uvc_register_video_device(struct uvc_device *dev, struct uvc_streaming *stream, - struct video_device *vdev, struct uvc_video_queue *queue, enum v4l2_buf_type type, const struct v4l2_file_operations *fops, diff --git a/drivers/media/v4l2-core/v4l2-common.c b/drivers/media/v4l2-core/v4l2-common.c index 6e585bc76367..b367d479d6b3 100644 --- a/drivers/media/v4l2-core/v4l2-common.c +++ b/drivers/media/v4l2-core/v4l2-common.c @@ -34,6 +34,9 @@ * Added Gerd Knorrs v4l1 enhancements (Justin Schoeman) */ +#include <linux/clk.h> +#include <linux/clkdev.h> +#include <linux/clk-provider.h> #include <linux/module.h> #include <linux/types.h> #include <linux/kernel.h> @@ -509,8 +512,9 @@ int v4l2_fill_pixfmt(struct v4l2_pix_format *pixfmt, u32 pixelformat, } EXPORT_SYMBOL_GPL(v4l2_fill_pixfmt); -s64 __v4l2_get_link_freq_ctrl(struct v4l2_ctrl_handler *handler, - unsigned int mul, unsigned int div) +#ifdef CONFIG_MEDIA_CONTROLLER +static s64 v4l2_get_link_freq_ctrl(struct v4l2_ctrl_handler *handler, + unsigned int mul, unsigned int div) { struct v4l2_ctrl *ctrl; s64 freq; @@ -545,11 +549,9 @@ s64 __v4l2_get_link_freq_ctrl(struct v4l2_ctrl_handler *handler, return freq > 0 ? freq : -EINVAL; } -EXPORT_SYMBOL_GPL(__v4l2_get_link_freq_ctrl); -#ifdef CONFIG_MEDIA_CONTROLLER -s64 __v4l2_get_link_freq_pad(struct media_pad *pad, unsigned int mul, - unsigned int div) +s64 v4l2_get_link_freq(const struct media_pad *pad, unsigned int mul, + unsigned int div) { struct v4l2_mbus_config mbus_config = {}; struct v4l2_subdev *sd; @@ -568,10 +570,10 @@ s64 __v4l2_get_link_freq_pad(struct media_pad *pad, unsigned int mul, * Fall back to using the link frequency control if the media bus config * doesn't provide a link frequency. */ - return __v4l2_get_link_freq_ctrl(sd->ctrl_handler, mul, div); + return v4l2_get_link_freq_ctrl(sd->ctrl_handler, mul, div); } -EXPORT_SYMBOL_GPL(__v4l2_get_link_freq_pad); -#endif /* CONFIG_MEDIA_CONTROLLER */ +EXPORT_SYMBOL_GPL(v4l2_get_link_freq); +#endif /* * Simplify a fraction using a simple continued fraction decomposition. The @@ -705,3 +707,73 @@ int v4l2_link_freq_to_bitmap(struct device *dev, const u64 *fw_link_freqs, return 0; } EXPORT_SYMBOL_GPL(v4l2_link_freq_to_bitmap); + +struct clk *__devm_v4l2_sensor_clk_get(struct device *dev, const char *id, + bool legacy, bool fixed_rate, + unsigned long clk_rate) +{ + bool of_node = is_of_node(dev_fwnode(dev)); + const char *clk_id __free(kfree) = NULL; + struct clk_hw *clk_hw; + struct clk *clk; + u32 rate = clk_rate; + int ret = 0; + + clk = devm_clk_get_optional(dev, id); + if (IS_ERR(clk)) + return clk; + + /* + * If the caller didn't request a fixed rate, retrieve it from the + * clock-frequency property. -EINVAL indicates the property is absent, + * and is not a failure. Other errors, or success with a clock-frequency + * value of 0, are hard failures. + */ + if (!fixed_rate || !clk_rate) { + ret = device_property_read_u32(dev, "clock-frequency", &rate); + if ((ret && ret != -EINVAL) || (!ret && !rate)) + return ERR_PTR(-EINVAL); + } + + if (clk) { + /* + * On non-OF platforms, or when legacy behaviour is requested, + * set the clock rate if a rate has been specified by the caller + * or by the clock-frequency property. + */ + if (rate && (!of_node || legacy)) { + ret = clk_set_rate(clk, rate); + if (ret) { + dev_err(dev, "Failed to set clock rate: %u\n", + rate); + return ERR_PTR(ret); + } + } + return clk; + } + + /* + * Register a dummy fixed clock on non-OF platforms or when legacy + * behaviour is requested. This required the common clock framework. + */ + if (!IS_ENABLED(CONFIG_COMMON_CLK) || (of_node && !legacy)) + return ERR_PTR(-ENOENT); + + /* We need a rate to create a clock. */ + if (ret) + return ERR_PTR(ret == -EINVAL ? -EPROBE_DEFER : ret); + + if (!id) { + clk_id = kasprintf(GFP_KERNEL, "clk-%s", dev_name(dev)); + if (!clk_id) + return ERR_PTR(-ENOMEM); + id = clk_id; + } + + clk_hw = devm_clk_hw_register_fixed_rate(dev, id, NULL, 0, rate); + if (IS_ERR(clk_hw)) + return ERR_CAST(clk_hw); + + return clk_hw->clk; +} +EXPORT_SYMBOL_GPL(__devm_v4l2_sensor_clk_get); diff --git a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c index 8c07400bd280..2c88e1175a10 100644 --- a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c +++ b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c @@ -8,7 +8,7 @@ * Copyright (C) 2001,2002 Andi Kleen, SuSE Labs * Copyright (C) 2003 Pavel Machek (pavel@ucw.cz) * Copyright (C) 2005 Philippe De Muyter (phdm@macqel.be) - * Copyright (C) 2008 Hans Verkuil <hverkuil@xs4all.nl> + * Copyright (C) 2008 Hans Verkuil <hverkuil@kernel.org> * * These routines maintain argument size conversion between 32bit and 64bit * ioctls. @@ -672,15 +672,12 @@ struct v4l2_ext_control32 { static inline bool ctrl_is_pointer(struct file *file, u32 id) { struct video_device *vdev = video_devdata(file); - struct v4l2_fh *fh = NULL; + struct v4l2_fh *fh = file_to_v4l2_fh(file); struct v4l2_ctrl_handler *hdl = NULL; struct v4l2_query_ext_ctrl qec = { id }; const struct v4l2_ioctl_ops *ops = vdev->ioctl_ops; - if (test_bit(V4L2_FL_USES_V4L2_FH, &vdev->flags)) - fh = file->private_data; - - if (fh && fh->ctrl_handler) + if (fh->ctrl_handler) hdl = fh->ctrl_handler; else if (vdev->ctrl_handler) hdl = vdev->ctrl_handler; @@ -694,7 +691,7 @@ static inline bool ctrl_is_pointer(struct file *file, u32 id) if (!ops || !ops->vidioc_query_ext_ctrl) return false; - return !ops->vidioc_query_ext_ctrl(file, fh, &qec) && + return !ops->vidioc_query_ext_ctrl(file, NULL, &qec) && (qec.flags & V4L2_CTRL_FLAG_HAS_PAYLOAD); } diff --git a/drivers/media/v4l2-core/v4l2-ctrls-api.c b/drivers/media/v4l2-core/v4l2-ctrls-api.c index d49a68b36c28..0078a04c5445 100644 --- a/drivers/media/v4l2-core/v4l2-ctrls-api.c +++ b/drivers/media/v4l2-core/v4l2-ctrls-api.c @@ -2,7 +2,7 @@ /* * V4L2 controls framework uAPI implementation: * - * Copyright (C) 2010-2021 Hans Verkuil <hverkuil-cisco@xs4all.nl> + * Copyright (C) 2010-2021 Hans Verkuil <hverkuil@kernel.org> */ #define pr_fmt(fmt) "v4l2-ctrls: " fmt @@ -1250,14 +1250,17 @@ EXPORT_SYMBOL(v4l2_querymenu); * VIDIOC_LOG_STATUS helpers */ -int v4l2_ctrl_log_status(struct file *file, void *fh) +int v4l2_ctrl_log_status(struct file *file, void *priv) { struct video_device *vfd = video_devdata(file); - struct v4l2_fh *vfh = file->private_data; - if (test_bit(V4L2_FL_USES_V4L2_FH, &vfd->flags) && vfd->v4l2_dev) + if (vfd->v4l2_dev) { + struct v4l2_fh *vfh = file_to_v4l2_fh(file); + v4l2_ctrl_handler_log_status(vfh->ctrl_handler, vfd->v4l2_dev->name); + } + return 0; } EXPORT_SYMBOL(v4l2_ctrl_log_status); @@ -1348,7 +1351,7 @@ EXPORT_SYMBOL(v4l2_ctrl_subdev_subscribe_event); */ __poll_t v4l2_ctrl_poll(struct file *file, struct poll_table_struct *wait) { - struct v4l2_fh *fh = file->private_data; + struct v4l2_fh *fh = file_to_v4l2_fh(file); poll_wait(file, &fh->wait, wait); if (v4l2_event_pending(fh)) diff --git a/drivers/media/v4l2-core/v4l2-ctrls-core.c b/drivers/media/v4l2-core/v4l2-ctrls-core.c index 98b960775e87..85d07ef44f62 100644 --- a/drivers/media/v4l2-core/v4l2-ctrls-core.c +++ b/drivers/media/v4l2-core/v4l2-ctrls-core.c @@ -2,7 +2,7 @@ /* * V4L2 controls framework core implementation. * - * Copyright (C) 2010-2021 Hans Verkuil <hverkuil-cisco@xs4all.nl> + * Copyright (C) 2010-2021 Hans Verkuil <hverkuil@kernel.org> */ #include <linux/export.h> diff --git a/drivers/media/v4l2-core/v4l2-ctrls-defs.c b/drivers/media/v4l2-core/v4l2-ctrls-defs.c index 1ea52011247a..ad41f65374e2 100644 --- a/drivers/media/v4l2-core/v4l2-ctrls-defs.c +++ b/drivers/media/v4l2-core/v4l2-ctrls-defs.c @@ -2,7 +2,7 @@ /* * V4L2 controls framework control definitions. * - * Copyright (C) 2010-2021 Hans Verkuil <hverkuil-cisco@xs4all.nl> + * Copyright (C) 2010-2021 Hans Verkuil <hverkuil@kernel.org> */ #include <linux/export.h> diff --git a/drivers/media/v4l2-core/v4l2-ctrls-priv.h b/drivers/media/v4l2-core/v4l2-ctrls-priv.h index aba6176fab6c..f4cf273ecf30 100644 --- a/drivers/media/v4l2-core/v4l2-ctrls-priv.h +++ b/drivers/media/v4l2-core/v4l2-ctrls-priv.h @@ -2,7 +2,7 @@ /* * V4L2 controls framework private header. * - * Copyright (C) 2010-2021 Hans Verkuil <hverkuil-cisco@xs4all.nl> + * Copyright (C) 2010-2021 Hans Verkuil <hverkuil@kernel.org> */ #ifndef _V4L2_CTRLS_PRIV_H_ diff --git a/drivers/media/v4l2-core/v4l2-ctrls-request.c b/drivers/media/v4l2-core/v4l2-ctrls-request.c index c637049d7a2b..e77f722b36a4 100644 --- a/drivers/media/v4l2-core/v4l2-ctrls-request.c +++ b/drivers/media/v4l2-core/v4l2-ctrls-request.c @@ -2,7 +2,7 @@ /* * V4L2 controls framework Request API implementation. * - * Copyright (C) 2018-2021 Hans Verkuil <hverkuil-cisco@xs4all.nl> + * Copyright (C) 2018-2021 Hans Verkuil <hverkuil@kernel.org> */ #define pr_fmt(fmt) "v4l2-ctrls: " fmt diff --git a/drivers/media/v4l2-core/v4l2-dev.c b/drivers/media/v4l2-core/v4l2-dev.c index c369235113d9..10a126e50c1c 100644 --- a/drivers/media/v4l2-core/v4l2-dev.c +++ b/drivers/media/v4l2-core/v4l2-dev.c @@ -411,7 +411,7 @@ static int v4l2_mmap(struct file *filp, struct vm_area_struct *vm) static int v4l2_open(struct inode *inode, struct file *filp) { struct video_device *vdev; - int ret = 0; + int ret; /* Check if the video device is available */ mutex_lock(&videodev_lock); @@ -424,16 +424,27 @@ static int v4l2_open(struct inode *inode, struct file *filp) /* and increase the device refcount */ video_get(vdev); mutex_unlock(&videodev_lock); - if (vdev->fops->open) { - if (video_is_registered(vdev)) - ret = vdev->fops->open(filp); - else - ret = -ENODEV; + + if (!video_is_registered(vdev)) { + ret = -ENODEV; + goto done; + } + + ret = vdev->fops->open(filp); + if (ret) + goto done; + + /* All drivers must use v4l2_fh. */ + if (WARN_ON(!test_bit(V4L2_FL_USES_V4L2_FH, &vdev->flags))) { + vdev->fops->release(filp); + ret = -ENODEV; } +done: if (vdev->dev_debug & V4L2_DEV_DEBUG_FOP) dprintk("%s: open (%d)\n", video_device_node_name(vdev), ret); + /* decrease the refcount in case of an error */ if (ret) video_put(vdev); @@ -444,7 +455,7 @@ static int v4l2_open(struct inode *inode, struct file *filp) static int v4l2_release(struct inode *inode, struct file *filp) { struct video_device *vdev = video_devdata(filp); - int ret = 0; + int ret; /* * We need to serialize the release() with queueing new requests. @@ -452,14 +463,12 @@ static int v4l2_release(struct inode *inode, struct file *filp) * operation, and that should not be mixed with queueing a new * request at the same time. */ - if (vdev->fops->release) { - if (v4l2_device_supports_requests(vdev->v4l2_dev)) { - mutex_lock(&vdev->v4l2_dev->mdev->req_queue_mutex); - ret = vdev->fops->release(filp); - mutex_unlock(&vdev->v4l2_dev->mdev->req_queue_mutex); - } else { - ret = vdev->fops->release(filp); - } + if (v4l2_device_supports_requests(vdev->v4l2_dev)) { + mutex_lock(&vdev->v4l2_dev->mdev->req_queue_mutex); + ret = vdev->fops->release(filp); + mutex_unlock(&vdev->v4l2_dev->mdev->req_queue_mutex); + } else { + ret = vdev->fops->release(filp); } if (vdev->dev_debug & V4L2_DEV_DEBUG_FOP) @@ -922,6 +931,9 @@ int __video_register_device(struct video_device *vdev, /* the device_caps field MUST be set for all but subdevs */ if (WARN_ON(type != VFL_TYPE_SUBDEV && !vdev->device_caps)) return -EINVAL; + /* the open and release file operations are mandatory */ + if (WARN_ON(!vdev->fops || !vdev->fops->open || !vdev->fops->release)) + return -EINVAL; /* v4l2_fh support */ spin_lock_init(&vdev->fh_lock); @@ -1114,8 +1126,7 @@ void video_unregister_device(struct video_device *vdev) */ clear_bit(V4L2_FL_REGISTERED, &vdev->flags); mutex_unlock(&videodev_lock); - if (test_bit(V4L2_FL_USES_V4L2_FH, &vdev->flags)) - v4l2_event_wake_all(vdev); + v4l2_event_wake_all(vdev); device_unregister(&vdev->dev); } EXPORT_SYMBOL(video_unregister_device); diff --git a/drivers/media/v4l2-core/v4l2-device.c b/drivers/media/v4l2-core/v4l2-device.c index 5e537454f5cd..63b12ef9d4d9 100644 --- a/drivers/media/v4l2-core/v4l2-device.c +++ b/drivers/media/v4l2-core/v4l2-device.c @@ -2,7 +2,7 @@ /* V4L2 device support. - Copyright (C) 2008 Hans Verkuil <hverkuil@xs4all.nl> + Copyright (C) 2008 Hans Verkuil <hverkuil@kernel.org> */ diff --git a/drivers/media/v4l2-core/v4l2-dv-timings.c b/drivers/media/v4l2-core/v4l2-dv-timings.c index 7710cb26bea0..346d1b0e10ce 100644 --- a/drivers/media/v4l2-core/v4l2-dv-timings.c +++ b/drivers/media/v4l2-core/v4l2-dv-timings.c @@ -1226,6 +1226,7 @@ DEBUGFS_FOPS(avi, V4L2_DEBUGFS_IF_AVI); DEBUGFS_FOPS(audio, V4L2_DEBUGFS_IF_AUDIO); DEBUGFS_FOPS(spd, V4L2_DEBUGFS_IF_SPD); DEBUGFS_FOPS(hdmi, V4L2_DEBUGFS_IF_HDMI); +DEBUGFS_FOPS(drm, V4L2_DEBUGFS_IF_DRM); struct v4l2_debugfs_if *v4l2_debugfs_if_alloc(struct dentry *root, u32 if_types, void *priv, @@ -1255,6 +1256,9 @@ struct v4l2_debugfs_if *v4l2_debugfs_if_alloc(struct dentry *root, u32 if_types, if (if_types & V4L2_DEBUGFS_IF_HDMI) debugfs_create_file("hdmi", 0400, infoframes->if_dir, infoframes, &infoframe_hdmi_fops); + if (if_types & V4L2_DEBUGFS_IF_DRM) + debugfs_create_file("hdr_drm", 0400, infoframes->if_dir, + infoframes, &infoframe_drm_fops); return infoframes; } EXPORT_SYMBOL_GPL(v4l2_debugfs_if_alloc); diff --git a/drivers/media/v4l2-core/v4l2-fh.c b/drivers/media/v4l2-core/v4l2-fh.c index 90eec79ee995..df3ba9d4674b 100644 --- a/drivers/media/v4l2-core/v4l2-fh.c +++ b/drivers/media/v4l2-core/v4l2-fh.c @@ -41,10 +41,12 @@ void v4l2_fh_init(struct v4l2_fh *fh, struct video_device *vdev) } EXPORT_SYMBOL_GPL(v4l2_fh_init); -void v4l2_fh_add(struct v4l2_fh *fh) +void v4l2_fh_add(struct v4l2_fh *fh, struct file *filp) { unsigned long flags; + filp->private_data = fh; + v4l2_prio_open(fh->vdev->prio, &fh->prio); spin_lock_irqsave(&fh->vdev->fh_lock, flags); list_add(&fh->list, &fh->vdev->fh_list); @@ -57,16 +59,15 @@ int v4l2_fh_open(struct file *filp) struct video_device *vdev = video_devdata(filp); struct v4l2_fh *fh = kzalloc(sizeof(*fh), GFP_KERNEL); - filp->private_data = fh; if (fh == NULL) return -ENOMEM; v4l2_fh_init(fh, vdev); - v4l2_fh_add(fh); + v4l2_fh_add(fh, filp); return 0; } EXPORT_SYMBOL_GPL(v4l2_fh_open); -void v4l2_fh_del(struct v4l2_fh *fh) +void v4l2_fh_del(struct v4l2_fh *fh, struct file *filp) { unsigned long flags; @@ -74,6 +75,8 @@ void v4l2_fh_del(struct v4l2_fh *fh) list_del_init(&fh->list); spin_unlock_irqrestore(&fh->vdev->fh_lock, flags); v4l2_prio_close(fh->vdev->prio, fh->prio); + + filp->private_data = NULL; } EXPORT_SYMBOL_GPL(v4l2_fh_del); @@ -90,13 +93,12 @@ EXPORT_SYMBOL_GPL(v4l2_fh_exit); int v4l2_fh_release(struct file *filp) { - struct v4l2_fh *fh = filp->private_data; + struct v4l2_fh *fh = file_to_v4l2_fh(filp); if (fh) { - v4l2_fh_del(fh); + v4l2_fh_del(fh, filp); v4l2_fh_exit(fh); kfree(fh); - filp->private_data = NULL; } return 0; } diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c b/drivers/media/v4l2-core/v4l2-ioctl.c index 46da373066f4..01cf52c3ea33 100644 --- a/drivers/media/v4l2-core/v4l2-ioctl.c +++ b/drivers/media/v4l2-core/v4l2-ioctl.c @@ -1089,8 +1089,8 @@ static void v4l_sanitize_format(struct v4l2_format *fmt) } } -static int v4l_querycap(const struct v4l2_ioctl_ops *ops, - struct file *file, void *fh, void *arg) +static int v4l_querycap(const struct v4l2_ioctl_ops *ops, struct file *file, + void *arg) { struct v4l2_capability *cap = (struct v4l2_capability *)arg; struct video_device *vfd = video_devdata(file); @@ -1103,7 +1103,7 @@ static int v4l_querycap(const struct v4l2_ioctl_ops *ops, media_set_bus_info(cap->bus_info, sizeof(cap->bus_info), vfd->dev_parent); - ret = ops->vidioc_querycap(file, fh, cap); + ret = ops->vidioc_querycap(file, NULL, cap); /* * Drivers must not change device_caps, so check for this and @@ -1123,8 +1123,8 @@ static int v4l_querycap(const struct v4l2_ioctl_ops *ops, return ret; } -static int v4l_g_input(const struct v4l2_ioctl_ops *ops, - struct file *file, void *fh, void *arg) +static int v4l_g_input(const struct v4l2_ioctl_ops *ops, struct file *file, + void *arg) { struct video_device *vfd = video_devdata(file); @@ -1133,11 +1133,11 @@ static int v4l_g_input(const struct v4l2_ioctl_ops *ops, return 0; } - return ops->vidioc_g_input(file, fh, arg); + return ops->vidioc_g_input(file, NULL, arg); } -static int v4l_g_output(const struct v4l2_ioctl_ops *ops, - struct file *file, void *fh, void *arg) +static int v4l_g_output(const struct v4l2_ioctl_ops *ops, struct file *file, + void *arg) { struct video_device *vfd = video_devdata(file); @@ -1146,11 +1146,11 @@ static int v4l_g_output(const struct v4l2_ioctl_ops *ops, return 0; } - return ops->vidioc_g_output(file, fh, arg); + return ops->vidioc_g_output(file, NULL, arg); } -static int v4l_s_input(const struct v4l2_ioctl_ops *ops, - struct file *file, void *fh, void *arg) +static int v4l_s_input(const struct v4l2_ioctl_ops *ops, struct file *file, + void *arg) { struct video_device *vfd = video_devdata(file); int ret; @@ -1162,22 +1162,22 @@ static int v4l_s_input(const struct v4l2_ioctl_ops *ops, if (vfd->device_caps & V4L2_CAP_IO_MC) return *(int *)arg ? -EINVAL : 0; - return ops->vidioc_s_input(file, fh, *(unsigned int *)arg); + return ops->vidioc_s_input(file, NULL, *(unsigned int *)arg); } -static int v4l_s_output(const struct v4l2_ioctl_ops *ops, - struct file *file, void *fh, void *arg) +static int v4l_s_output(const struct v4l2_ioctl_ops *ops, struct file *file, + void *arg) { struct video_device *vfd = video_devdata(file); if (vfd->device_caps & V4L2_CAP_IO_MC) return *(int *)arg ? -EINVAL : 0; - return ops->vidioc_s_output(file, fh, *(unsigned int *)arg); + return ops->vidioc_s_output(file, NULL, *(unsigned int *)arg); } -static int v4l_g_priority(const struct v4l2_ioctl_ops *ops, - struct file *file, void *fh, void *arg) +static int v4l_g_priority(const struct v4l2_ioctl_ops *ops, struct file *file, + void *arg) { struct video_device *vfd; u32 *p = arg; @@ -1187,22 +1187,20 @@ static int v4l_g_priority(const struct v4l2_ioctl_ops *ops, return 0; } -static int v4l_s_priority(const struct v4l2_ioctl_ops *ops, - struct file *file, void *fh, void *arg) +static int v4l_s_priority(const struct v4l2_ioctl_ops *ops, struct file *file, + void *arg) { struct video_device *vfd; struct v4l2_fh *vfh; u32 *p = arg; vfd = video_devdata(file); - if (!test_bit(V4L2_FL_USES_V4L2_FH, &vfd->flags)) - return -ENOTTY; - vfh = file->private_data; + vfh = file_to_v4l2_fh(file); return v4l2_prio_change(vfd->prio, &vfh->prio, *p); } -static int v4l_enuminput(const struct v4l2_ioctl_ops *ops, - struct file *file, void *fh, void *arg) +static int v4l_enuminput(const struct v4l2_ioctl_ops *ops, struct file *file, + void *arg) { struct video_device *vfd = video_devdata(file); struct v4l2_input *p = arg; @@ -1224,11 +1222,11 @@ static int v4l_enuminput(const struct v4l2_ioctl_ops *ops, return 0; } - return ops->vidioc_enum_input(file, fh, p); + return ops->vidioc_enum_input(file, NULL, p); } -static int v4l_enumoutput(const struct v4l2_ioctl_ops *ops, - struct file *file, void *fh, void *arg) +static int v4l_enumoutput(const struct v4l2_ioctl_ops *ops, struct file *file, + void *arg) { struct video_device *vfd = video_devdata(file); struct v4l2_output *p = arg; @@ -1250,7 +1248,7 @@ static int v4l_enumoutput(const struct v4l2_ioctl_ops *ops, return 0; } - return ops->vidioc_enum_output(file, fh, p); + return ops->vidioc_enum_output(file, NULL, p); } static void v4l_fill_fmtdesc(struct v4l2_fmtdesc *fmt) @@ -1589,8 +1587,8 @@ static void v4l_fill_fmtdesc(struct v4l2_fmtdesc *fmt) fmt->flags |= flags; } -static int v4l_enum_fmt(const struct v4l2_ioctl_ops *ops, - struct file *file, void *fh, void *arg) +static int v4l_enum_fmt(const struct v4l2_ioctl_ops *ops, struct file *file, + void *arg) { struct video_device *vdev = video_devdata(file); struct v4l2_fmtdesc *p = arg; @@ -1620,12 +1618,12 @@ static int v4l_enum_fmt(const struct v4l2_ioctl_ops *ops, if (unlikely(!ops->vidioc_enum_fmt_vid_cap)) break; - ret = ops->vidioc_enum_fmt_vid_cap(file, fh, arg); + ret = ops->vidioc_enum_fmt_vid_cap(file, NULL, arg); break; case V4L2_BUF_TYPE_VIDEO_OVERLAY: if (unlikely(!ops->vidioc_enum_fmt_vid_overlay)) break; - ret = ops->vidioc_enum_fmt_vid_overlay(file, fh, arg); + ret = ops->vidioc_enum_fmt_vid_overlay(file, NULL, arg); break; case V4L2_BUF_TYPE_VIDEO_OUTPUT: case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: @@ -1637,27 +1635,27 @@ static int v4l_enum_fmt(const struct v4l2_ioctl_ops *ops, if (unlikely(!ops->vidioc_enum_fmt_vid_out)) break; - ret = ops->vidioc_enum_fmt_vid_out(file, fh, arg); + ret = ops->vidioc_enum_fmt_vid_out(file, NULL, arg); break; case V4L2_BUF_TYPE_SDR_CAPTURE: if (unlikely(!ops->vidioc_enum_fmt_sdr_cap)) break; - ret = ops->vidioc_enum_fmt_sdr_cap(file, fh, arg); + ret = ops->vidioc_enum_fmt_sdr_cap(file, NULL, arg); break; case V4L2_BUF_TYPE_SDR_OUTPUT: if (unlikely(!ops->vidioc_enum_fmt_sdr_out)) break; - ret = ops->vidioc_enum_fmt_sdr_out(file, fh, arg); + ret = ops->vidioc_enum_fmt_sdr_out(file, NULL, arg); break; case V4L2_BUF_TYPE_META_CAPTURE: if (unlikely(!ops->vidioc_enum_fmt_meta_cap)) break; - ret = ops->vidioc_enum_fmt_meta_cap(file, fh, arg); + ret = ops->vidioc_enum_fmt_meta_cap(file, NULL, arg); break; case V4L2_BUF_TYPE_META_OUTPUT: if (unlikely(!ops->vidioc_enum_fmt_meta_out)) break; - ret = ops->vidioc_enum_fmt_meta_out(file, fh, arg); + ret = ops->vidioc_enum_fmt_meta_out(file, NULL, arg); break; } if (ret == 0) @@ -1680,8 +1678,8 @@ static void v4l_pix_format_touch(struct v4l2_pix_format *p) p->xfer_func = 0; } -static int v4l_g_fmt(const struct v4l2_ioctl_ops *ops, - struct file *file, void *fh, void *arg) +static int v4l_g_fmt(const struct v4l2_ioctl_ops *ops, struct file *file, + void *arg) { struct v4l2_format *p = arg; struct video_device *vfd = video_devdata(file); @@ -1697,50 +1695,50 @@ static int v4l_g_fmt(const struct v4l2_ioctl_ops *ops, if (unlikely(!ops->vidioc_g_fmt_vid_cap)) break; p->fmt.pix.priv = V4L2_PIX_FMT_PRIV_MAGIC; - ret = ops->vidioc_g_fmt_vid_cap(file, fh, arg); + ret = ops->vidioc_g_fmt_vid_cap(file, NULL, arg); /* just in case the driver zeroed it again */ p->fmt.pix.priv = V4L2_PIX_FMT_PRIV_MAGIC; if (vfd->vfl_type == VFL_TYPE_TOUCH) v4l_pix_format_touch(&p->fmt.pix); return ret; case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: - return ops->vidioc_g_fmt_vid_cap_mplane(file, fh, arg); + return ops->vidioc_g_fmt_vid_cap_mplane(file, NULL, arg); case V4L2_BUF_TYPE_VIDEO_OVERLAY: - return ops->vidioc_g_fmt_vid_overlay(file, fh, arg); + return ops->vidioc_g_fmt_vid_overlay(file, NULL, arg); case V4L2_BUF_TYPE_VBI_CAPTURE: - return ops->vidioc_g_fmt_vbi_cap(file, fh, arg); + return ops->vidioc_g_fmt_vbi_cap(file, NULL, arg); case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE: - return ops->vidioc_g_fmt_sliced_vbi_cap(file, fh, arg); + return ops->vidioc_g_fmt_sliced_vbi_cap(file, NULL, arg); case V4L2_BUF_TYPE_VIDEO_OUTPUT: if (unlikely(!ops->vidioc_g_fmt_vid_out)) break; p->fmt.pix.priv = V4L2_PIX_FMT_PRIV_MAGIC; - ret = ops->vidioc_g_fmt_vid_out(file, fh, arg); + ret = ops->vidioc_g_fmt_vid_out(file, NULL, arg); /* just in case the driver zeroed it again */ p->fmt.pix.priv = V4L2_PIX_FMT_PRIV_MAGIC; return ret; case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: - return ops->vidioc_g_fmt_vid_out_mplane(file, fh, arg); + return ops->vidioc_g_fmt_vid_out_mplane(file, NULL, arg); case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY: - return ops->vidioc_g_fmt_vid_out_overlay(file, fh, arg); + return ops->vidioc_g_fmt_vid_out_overlay(file, NULL, arg); case V4L2_BUF_TYPE_VBI_OUTPUT: - return ops->vidioc_g_fmt_vbi_out(file, fh, arg); + return ops->vidioc_g_fmt_vbi_out(file, NULL, arg); case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT: - return ops->vidioc_g_fmt_sliced_vbi_out(file, fh, arg); + return ops->vidioc_g_fmt_sliced_vbi_out(file, NULL, arg); case V4L2_BUF_TYPE_SDR_CAPTURE: - return ops->vidioc_g_fmt_sdr_cap(file, fh, arg); + return ops->vidioc_g_fmt_sdr_cap(file, NULL, arg); case V4L2_BUF_TYPE_SDR_OUTPUT: - return ops->vidioc_g_fmt_sdr_out(file, fh, arg); + return ops->vidioc_g_fmt_sdr_out(file, NULL, arg); case V4L2_BUF_TYPE_META_CAPTURE: - return ops->vidioc_g_fmt_meta_cap(file, fh, arg); + return ops->vidioc_g_fmt_meta_cap(file, NULL, arg); case V4L2_BUF_TYPE_META_OUTPUT: - return ops->vidioc_g_fmt_meta_out(file, fh, arg); + return ops->vidioc_g_fmt_meta_out(file, NULL, arg); } return -EINVAL; } -static int v4l_s_fmt(const struct v4l2_ioctl_ops *ops, - struct file *file, void *fh, void *arg) +static int v4l_s_fmt(const struct v4l2_ioctl_ops *ops, struct file *file, + void *arg) { struct v4l2_format *p = arg; struct video_device *vfd = video_devdata(file); @@ -1760,7 +1758,7 @@ static int v4l_s_fmt(const struct v4l2_ioctl_ops *ops, if (unlikely(!ops->vidioc_s_fmt_vid_cap)) break; memset_after(p, 0, fmt.pix); - ret = ops->vidioc_s_fmt_vid_cap(file, fh, arg); + ret = ops->vidioc_s_fmt_vid_cap(file, NULL, arg); /* just in case the driver zeroed it again */ p->fmt.pix.priv = V4L2_PIX_FMT_PRIV_MAGIC; if (vfd->vfl_type == VFL_TYPE_TOUCH) @@ -1773,7 +1771,7 @@ static int v4l_s_fmt(const struct v4l2_ioctl_ops *ops, for (i = 0; i < p->fmt.pix_mp.num_planes; i++) memset_after(&p->fmt.pix_mp.plane_fmt[i], 0, bytesperline); - return ops->vidioc_s_fmt_vid_cap_mplane(file, fh, arg); + return ops->vidioc_s_fmt_vid_cap_mplane(file, NULL, arg); case V4L2_BUF_TYPE_VIDEO_OVERLAY: if (unlikely(!ops->vidioc_s_fmt_vid_overlay)) break; @@ -1781,22 +1779,22 @@ static int v4l_s_fmt(const struct v4l2_ioctl_ops *ops, p->fmt.win.clips = NULL; p->fmt.win.clipcount = 0; p->fmt.win.bitmap = NULL; - return ops->vidioc_s_fmt_vid_overlay(file, fh, arg); + return ops->vidioc_s_fmt_vid_overlay(file, NULL, arg); case V4L2_BUF_TYPE_VBI_CAPTURE: if (unlikely(!ops->vidioc_s_fmt_vbi_cap)) break; memset_after(p, 0, fmt.vbi.flags); - return ops->vidioc_s_fmt_vbi_cap(file, fh, arg); + return ops->vidioc_s_fmt_vbi_cap(file, NULL, arg); case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE: if (unlikely(!ops->vidioc_s_fmt_sliced_vbi_cap)) break; memset_after(p, 0, fmt.sliced.io_size); - return ops->vidioc_s_fmt_sliced_vbi_cap(file, fh, arg); + return ops->vidioc_s_fmt_sliced_vbi_cap(file, NULL, arg); case V4L2_BUF_TYPE_VIDEO_OUTPUT: if (unlikely(!ops->vidioc_s_fmt_vid_out)) break; memset_after(p, 0, fmt.pix); - ret = ops->vidioc_s_fmt_vid_out(file, fh, arg); + ret = ops->vidioc_s_fmt_vid_out(file, NULL, arg); /* just in case the driver zeroed it again */ p->fmt.pix.priv = V4L2_PIX_FMT_PRIV_MAGIC; return ret; @@ -1807,7 +1805,7 @@ static int v4l_s_fmt(const struct v4l2_ioctl_ops *ops, for (i = 0; i < p->fmt.pix_mp.num_planes; i++) memset_after(&p->fmt.pix_mp.plane_fmt[i], 0, bytesperline); - return ops->vidioc_s_fmt_vid_out_mplane(file, fh, arg); + return ops->vidioc_s_fmt_vid_out_mplane(file, NULL, arg); case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY: if (unlikely(!ops->vidioc_s_fmt_vid_out_overlay)) break; @@ -1815,43 +1813,43 @@ static int v4l_s_fmt(const struct v4l2_ioctl_ops *ops, p->fmt.win.clips = NULL; p->fmt.win.clipcount = 0; p->fmt.win.bitmap = NULL; - return ops->vidioc_s_fmt_vid_out_overlay(file, fh, arg); + return ops->vidioc_s_fmt_vid_out_overlay(file, NULL, arg); case V4L2_BUF_TYPE_VBI_OUTPUT: if (unlikely(!ops->vidioc_s_fmt_vbi_out)) break; memset_after(p, 0, fmt.vbi.flags); - return ops->vidioc_s_fmt_vbi_out(file, fh, arg); + return ops->vidioc_s_fmt_vbi_out(file, NULL, arg); case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT: if (unlikely(!ops->vidioc_s_fmt_sliced_vbi_out)) break; memset_after(p, 0, fmt.sliced.io_size); - return ops->vidioc_s_fmt_sliced_vbi_out(file, fh, arg); + return ops->vidioc_s_fmt_sliced_vbi_out(file, NULL, arg); case V4L2_BUF_TYPE_SDR_CAPTURE: if (unlikely(!ops->vidioc_s_fmt_sdr_cap)) break; memset_after(p, 0, fmt.sdr.buffersize); - return ops->vidioc_s_fmt_sdr_cap(file, fh, arg); + return ops->vidioc_s_fmt_sdr_cap(file, NULL, arg); case V4L2_BUF_TYPE_SDR_OUTPUT: if (unlikely(!ops->vidioc_s_fmt_sdr_out)) break; memset_after(p, 0, fmt.sdr.buffersize); - return ops->vidioc_s_fmt_sdr_out(file, fh, arg); + return ops->vidioc_s_fmt_sdr_out(file, NULL, arg); case V4L2_BUF_TYPE_META_CAPTURE: if (unlikely(!ops->vidioc_s_fmt_meta_cap)) break; memset_after(p, 0, fmt.meta); - return ops->vidioc_s_fmt_meta_cap(file, fh, arg); + return ops->vidioc_s_fmt_meta_cap(file, NULL, arg); case V4L2_BUF_TYPE_META_OUTPUT: if (unlikely(!ops->vidioc_s_fmt_meta_out)) break; memset_after(p, 0, fmt.meta); - return ops->vidioc_s_fmt_meta_out(file, fh, arg); + return ops->vidioc_s_fmt_meta_out(file, NULL, arg); } return -EINVAL; } -static int v4l_try_fmt(const struct v4l2_ioctl_ops *ops, - struct file *file, void *fh, void *arg) +static int v4l_try_fmt(const struct v4l2_ioctl_ops *ops, struct file *file, + void *arg) { struct v4l2_format *p = arg; struct video_device *vfd = video_devdata(file); @@ -1868,7 +1866,7 @@ static int v4l_try_fmt(const struct v4l2_ioctl_ops *ops, if (unlikely(!ops->vidioc_try_fmt_vid_cap)) break; memset_after(p, 0, fmt.pix); - ret = ops->vidioc_try_fmt_vid_cap(file, fh, arg); + ret = ops->vidioc_try_fmt_vid_cap(file, NULL, arg); /* just in case the driver zeroed it again */ p->fmt.pix.priv = V4L2_PIX_FMT_PRIV_MAGIC; if (vfd->vfl_type == VFL_TYPE_TOUCH) @@ -1881,7 +1879,7 @@ static int v4l_try_fmt(const struct v4l2_ioctl_ops *ops, for (i = 0; i < p->fmt.pix_mp.num_planes; i++) memset_after(&p->fmt.pix_mp.plane_fmt[i], 0, bytesperline); - return ops->vidioc_try_fmt_vid_cap_mplane(file, fh, arg); + return ops->vidioc_try_fmt_vid_cap_mplane(file, NULL, arg); case V4L2_BUF_TYPE_VIDEO_OVERLAY: if (unlikely(!ops->vidioc_try_fmt_vid_overlay)) break; @@ -1889,22 +1887,22 @@ static int v4l_try_fmt(const struct v4l2_ioctl_ops *ops, p->fmt.win.clips = NULL; p->fmt.win.clipcount = 0; p->fmt.win.bitmap = NULL; - return ops->vidioc_try_fmt_vid_overlay(file, fh, arg); + return ops->vidioc_try_fmt_vid_overlay(file, NULL, arg); case V4L2_BUF_TYPE_VBI_CAPTURE: if (unlikely(!ops->vidioc_try_fmt_vbi_cap)) break; memset_after(p, 0, fmt.vbi.flags); - return ops->vidioc_try_fmt_vbi_cap(file, fh, arg); + return ops->vidioc_try_fmt_vbi_cap(file, NULL, arg); case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE: if (unlikely(!ops->vidioc_try_fmt_sliced_vbi_cap)) break; memset_after(p, 0, fmt.sliced.io_size); - return ops->vidioc_try_fmt_sliced_vbi_cap(file, fh, arg); + return ops->vidioc_try_fmt_sliced_vbi_cap(file, NULL, arg); case V4L2_BUF_TYPE_VIDEO_OUTPUT: if (unlikely(!ops->vidioc_try_fmt_vid_out)) break; memset_after(p, 0, fmt.pix); - ret = ops->vidioc_try_fmt_vid_out(file, fh, arg); + ret = ops->vidioc_try_fmt_vid_out(file, NULL, arg); /* just in case the driver zeroed it again */ p->fmt.pix.priv = V4L2_PIX_FMT_PRIV_MAGIC; return ret; @@ -1915,7 +1913,7 @@ static int v4l_try_fmt(const struct v4l2_ioctl_ops *ops, for (i = 0; i < p->fmt.pix_mp.num_planes; i++) memset_after(&p->fmt.pix_mp.plane_fmt[i], 0, bytesperline); - return ops->vidioc_try_fmt_vid_out_mplane(file, fh, arg); + return ops->vidioc_try_fmt_vid_out_mplane(file, NULL, arg); case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY: if (unlikely(!ops->vidioc_try_fmt_vid_out_overlay)) break; @@ -1923,55 +1921,55 @@ static int v4l_try_fmt(const struct v4l2_ioctl_ops *ops, p->fmt.win.clips = NULL; p->fmt.win.clipcount = 0; p->fmt.win.bitmap = NULL; - return ops->vidioc_try_fmt_vid_out_overlay(file, fh, arg); + return ops->vidioc_try_fmt_vid_out_overlay(file, NULL, arg); case V4L2_BUF_TYPE_VBI_OUTPUT: if (unlikely(!ops->vidioc_try_fmt_vbi_out)) break; memset_after(p, 0, fmt.vbi.flags); - return ops->vidioc_try_fmt_vbi_out(file, fh, arg); + return ops->vidioc_try_fmt_vbi_out(file, NULL, arg); case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT: if (unlikely(!ops->vidioc_try_fmt_sliced_vbi_out)) break; memset_after(p, 0, fmt.sliced.io_size); - return ops->vidioc_try_fmt_sliced_vbi_out(file, fh, arg); + return ops->vidioc_try_fmt_sliced_vbi_out(file, NULL, arg); case V4L2_BUF_TYPE_SDR_CAPTURE: if (unlikely(!ops->vidioc_try_fmt_sdr_cap)) break; memset_after(p, 0, fmt.sdr.buffersize); - return ops->vidioc_try_fmt_sdr_cap(file, fh, arg); + return ops->vidioc_try_fmt_sdr_cap(file, NULL, arg); case V4L2_BUF_TYPE_SDR_OUTPUT: if (unlikely(!ops->vidioc_try_fmt_sdr_out)) break; memset_after(p, 0, fmt.sdr.buffersize); - return ops->vidioc_try_fmt_sdr_out(file, fh, arg); + return ops->vidioc_try_fmt_sdr_out(file, NULL, arg); case V4L2_BUF_TYPE_META_CAPTURE: if (unlikely(!ops->vidioc_try_fmt_meta_cap)) break; memset_after(p, 0, fmt.meta); - return ops->vidioc_try_fmt_meta_cap(file, fh, arg); + return ops->vidioc_try_fmt_meta_cap(file, NULL, arg); case V4L2_BUF_TYPE_META_OUTPUT: if (unlikely(!ops->vidioc_try_fmt_meta_out)) break; memset_after(p, 0, fmt.meta); - return ops->vidioc_try_fmt_meta_out(file, fh, arg); + return ops->vidioc_try_fmt_meta_out(file, NULL, arg); } return -EINVAL; } -static int v4l_streamon(const struct v4l2_ioctl_ops *ops, - struct file *file, void *fh, void *arg) +static int v4l_streamon(const struct v4l2_ioctl_ops *ops, struct file *file, + void *arg) { - return ops->vidioc_streamon(file, fh, *(unsigned int *)arg); + return ops->vidioc_streamon(file, NULL, *(unsigned int *)arg); } -static int v4l_streamoff(const struct v4l2_ioctl_ops *ops, - struct file *file, void *fh, void *arg) +static int v4l_streamoff(const struct v4l2_ioctl_ops *ops, struct file *file, + void *arg) { - return ops->vidioc_streamoff(file, fh, *(unsigned int *)arg); + return ops->vidioc_streamoff(file, NULL, *(unsigned int *)arg); } -static int v4l_g_tuner(const struct v4l2_ioctl_ops *ops, - struct file *file, void *fh, void *arg) +static int v4l_g_tuner(const struct v4l2_ioctl_ops *ops, struct file *file, + void *arg) { struct video_device *vfd = video_devdata(file); struct v4l2_tuner *p = arg; @@ -1979,14 +1977,14 @@ static int v4l_g_tuner(const struct v4l2_ioctl_ops *ops, p->type = (vfd->vfl_type == VFL_TYPE_RADIO) ? V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV; - err = ops->vidioc_g_tuner(file, fh, p); + err = ops->vidioc_g_tuner(file, NULL, p); if (!err) p->capability |= V4L2_TUNER_CAP_FREQ_BANDS; return err; } -static int v4l_s_tuner(const struct v4l2_ioctl_ops *ops, - struct file *file, void *fh, void *arg) +static int v4l_s_tuner(const struct v4l2_ioctl_ops *ops, struct file *file, + void *arg) { struct video_device *vfd = video_devdata(file); struct v4l2_tuner *p = arg; @@ -1997,11 +1995,11 @@ static int v4l_s_tuner(const struct v4l2_ioctl_ops *ops, return ret; p->type = (vfd->vfl_type == VFL_TYPE_RADIO) ? V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV; - return ops->vidioc_s_tuner(file, fh, p); + return ops->vidioc_s_tuner(file, NULL, p); } static int v4l_g_modulator(const struct v4l2_ioctl_ops *ops, - struct file *file, void *fh, void *arg) + struct file *file, void *arg) { struct video_device *vfd = video_devdata(file); struct v4l2_modulator *p = arg; @@ -2010,14 +2008,14 @@ static int v4l_g_modulator(const struct v4l2_ioctl_ops *ops, if (vfd->vfl_type == VFL_TYPE_RADIO) p->type = V4L2_TUNER_RADIO; - err = ops->vidioc_g_modulator(file, fh, p); + err = ops->vidioc_g_modulator(file, NULL, p); if (!err) p->capability |= V4L2_TUNER_CAP_FREQ_BANDS; return err; } static int v4l_s_modulator(const struct v4l2_ioctl_ops *ops, - struct file *file, void *fh, void *arg) + struct file *file, void *arg) { struct video_device *vfd = video_devdata(file); struct v4l2_modulator *p = arg; @@ -2025,11 +2023,11 @@ static int v4l_s_modulator(const struct v4l2_ioctl_ops *ops, if (vfd->vfl_type == VFL_TYPE_RADIO) p->type = V4L2_TUNER_RADIO; - return ops->vidioc_s_modulator(file, fh, p); + return ops->vidioc_s_modulator(file, NULL, p); } static int v4l_g_frequency(const struct v4l2_ioctl_ops *ops, - struct file *file, void *fh, void *arg) + struct file *file, void *arg) { struct video_device *vfd = video_devdata(file); struct v4l2_frequency *p = arg; @@ -2039,11 +2037,11 @@ static int v4l_g_frequency(const struct v4l2_ioctl_ops *ops, else p->type = (vfd->vfl_type == VFL_TYPE_RADIO) ? V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV; - return ops->vidioc_g_frequency(file, fh, p); + return ops->vidioc_g_frequency(file, NULL, p); } static int v4l_s_frequency(const struct v4l2_ioctl_ops *ops, - struct file *file, void *fh, void *arg) + struct file *file, void *arg) { struct video_device *vfd = video_devdata(file); const struct v4l2_frequency *p = arg; @@ -2062,11 +2060,11 @@ static int v4l_s_frequency(const struct v4l2_ioctl_ops *ops, if (type != p->type) return -EINVAL; } - return ops->vidioc_s_frequency(file, fh, p); + return ops->vidioc_s_frequency(file, NULL, p); } -static int v4l_enumstd(const struct v4l2_ioctl_ops *ops, - struct file *file, void *fh, void *arg) +static int v4l_enumstd(const struct v4l2_ioctl_ops *ops, struct file *file, + void *arg) { struct video_device *vfd = video_devdata(file); struct v4l2_standard *p = arg; @@ -2074,8 +2072,8 @@ static int v4l_enumstd(const struct v4l2_ioctl_ops *ops, return v4l_video_std_enumstd(p, vfd->tvnorms); } -static int v4l_s_std(const struct v4l2_ioctl_ops *ops, - struct file *file, void *fh, void *arg) +static int v4l_s_std(const struct v4l2_ioctl_ops *ops, struct file *file, + void *arg) { struct video_device *vfd = video_devdata(file); v4l2_std_id id = *(v4l2_std_id *)arg, norm; @@ -2089,11 +2087,11 @@ static int v4l_s_std(const struct v4l2_ioctl_ops *ops, return -EINVAL; /* Calls the specific handler */ - return ops->vidioc_s_std(file, fh, norm); + return ops->vidioc_s_std(file, NULL, norm); } -static int v4l_querystd(const struct v4l2_ioctl_ops *ops, - struct file *file, void *fh, void *arg) +static int v4l_querystd(const struct v4l2_ioctl_ops *ops, struct file *file, + void *arg) { struct video_device *vfd = video_devdata(file); v4l2_std_id *p = arg; @@ -2111,11 +2109,11 @@ static int v4l_querystd(const struct v4l2_ioctl_ops *ops, * their efforts to improve the standards detection. */ *p = vfd->tvnorms; - return ops->vidioc_querystd(file, fh, arg); + return ops->vidioc_querystd(file, NULL, arg); } static int v4l_s_hw_freq_seek(const struct v4l2_ioctl_ops *ops, - struct file *file, void *fh, void *arg) + struct file *file, void *arg) { struct video_device *vfd = video_devdata(file); struct v4l2_hw_freq_seek *p = arg; @@ -2133,26 +2131,26 @@ static int v4l_s_hw_freq_seek(const struct v4l2_ioctl_ops *ops, V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV; if (p->type != type) return -EINVAL; - return ops->vidioc_s_hw_freq_seek(file, fh, p); + return ops->vidioc_s_hw_freq_seek(file, NULL, p); } -static int v4l_s_fbuf(const struct v4l2_ioctl_ops *ops, - struct file *file, void *fh, void *arg) +static int v4l_s_fbuf(const struct v4l2_ioctl_ops *ops, struct file *file, + void *arg) { struct v4l2_framebuffer *p = arg; p->base = NULL; - return ops->vidioc_s_fbuf(file, fh, p); + return ops->vidioc_s_fbuf(file, NULL, p); } -static int v4l_overlay(const struct v4l2_ioctl_ops *ops, - struct file *file, void *fh, void *arg) +static int v4l_overlay(const struct v4l2_ioctl_ops *ops, struct file *file, + void *arg) { - return ops->vidioc_overlay(file, fh, *(unsigned int *)arg); + return ops->vidioc_overlay(file, NULL, *(unsigned int *)arg); } -static int v4l_reqbufs(const struct v4l2_ioctl_ops *ops, - struct file *file, void *fh, void *arg) +static int v4l_reqbufs(const struct v4l2_ioctl_ops *ops, struct file *file, + void *arg) { struct video_device *vfd = video_devdata(file); struct v4l2_requestbuffers *p = arg; @@ -2167,38 +2165,38 @@ static int v4l_reqbufs(const struct v4l2_ioctl_ops *ops, if (is_valid_ioctl(vfd, VIDIOC_REMOVE_BUFS)) p->capabilities = V4L2_BUF_CAP_SUPPORTS_REMOVE_BUFS; - return ops->vidioc_reqbufs(file, fh, p); + return ops->vidioc_reqbufs(file, NULL, p); } -static int v4l_querybuf(const struct v4l2_ioctl_ops *ops, - struct file *file, void *fh, void *arg) +static int v4l_querybuf(const struct v4l2_ioctl_ops *ops, struct file *file, + void *arg) { struct v4l2_buffer *p = arg; int ret = check_fmt(file, p->type); - return ret ? ret : ops->vidioc_querybuf(file, fh, p); + return ret ? ret : ops->vidioc_querybuf(file, NULL, p); } -static int v4l_qbuf(const struct v4l2_ioctl_ops *ops, - struct file *file, void *fh, void *arg) +static int v4l_qbuf(const struct v4l2_ioctl_ops *ops, struct file *file, + void *arg) { struct v4l2_buffer *p = arg; int ret = check_fmt(file, p->type); - return ret ? ret : ops->vidioc_qbuf(file, fh, p); + return ret ? ret : ops->vidioc_qbuf(file, NULL, p); } -static int v4l_dqbuf(const struct v4l2_ioctl_ops *ops, - struct file *file, void *fh, void *arg) +static int v4l_dqbuf(const struct v4l2_ioctl_ops *ops, struct file *file, + void *arg) { struct v4l2_buffer *p = arg; int ret = check_fmt(file, p->type); - return ret ? ret : ops->vidioc_dqbuf(file, fh, p); + return ret ? ret : ops->vidioc_dqbuf(file, NULL, p); } static int v4l_create_bufs(const struct v4l2_ioctl_ops *ops, - struct file *file, void *fh, void *arg) + struct file *file, void *arg) { struct video_device *vfd = video_devdata(file); struct v4l2_create_buffers *create = arg; @@ -2215,7 +2213,7 @@ static int v4l_create_bufs(const struct v4l2_ioctl_ops *ops, if (is_valid_ioctl(vfd, VIDIOC_REMOVE_BUFS)) create->capabilities = V4L2_BUF_CAP_SUPPORTS_REMOVE_BUFS; - ret = ops->vidioc_create_bufs(file, fh, create); + ret = ops->vidioc_create_bufs(file, NULL, create); if (create->format.type == V4L2_BUF_TYPE_VIDEO_CAPTURE || create->format.type == V4L2_BUF_TYPE_VIDEO_OUTPUT) @@ -2225,27 +2223,27 @@ static int v4l_create_bufs(const struct v4l2_ioctl_ops *ops, } static int v4l_prepare_buf(const struct v4l2_ioctl_ops *ops, - struct file *file, void *fh, void *arg) + struct file *file, void *arg) { struct v4l2_buffer *b = arg; int ret = check_fmt(file, b->type); - return ret ? ret : ops->vidioc_prepare_buf(file, fh, b); + return ret ? ret : ops->vidioc_prepare_buf(file, NULL, b); } static int v4l_remove_bufs(const struct v4l2_ioctl_ops *ops, - struct file *file, void *fh, void *arg) + struct file *file, void *arg) { struct v4l2_remove_buffers *remove = arg; if (ops->vidioc_remove_bufs) - return ops->vidioc_remove_bufs(file, fh, remove); + return ops->vidioc_remove_bufs(file, NULL, remove); return -ENOTTY; } -static int v4l_g_parm(const struct v4l2_ioctl_ops *ops, - struct file *file, void *fh, void *arg) +static int v4l_g_parm(const struct v4l2_ioctl_ops *ops, struct file *file, + void *arg) { struct video_device *vfd = video_devdata(file); struct v4l2_streamparm *p = arg; @@ -2255,20 +2253,20 @@ static int v4l_g_parm(const struct v4l2_ioctl_ops *ops, if (ret) return ret; if (ops->vidioc_g_parm) - return ops->vidioc_g_parm(file, fh, p); + return ops->vidioc_g_parm(file, NULL, p); if (p->type != V4L2_BUF_TYPE_VIDEO_CAPTURE && p->type != V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) return -EINVAL; if (vfd->device_caps & V4L2_CAP_READWRITE) p->parm.capture.readbuffers = 2; - ret = ops->vidioc_g_std(file, fh, &std); + ret = ops->vidioc_g_std(file, NULL, &std); if (ret == 0) v4l2_video_std_frame_period(std, &p->parm.capture.timeperframe); return ret; } -static int v4l_s_parm(const struct v4l2_ioctl_ops *ops, - struct file *file, void *fh, void *arg) +static int v4l_s_parm(const struct v4l2_ioctl_ops *ops, struct file *file, + void *arg) { struct v4l2_streamparm *p = arg; int ret = check_fmt(file, p->type); @@ -2288,17 +2286,16 @@ static int v4l_s_parm(const struct v4l2_ioctl_ops *ops, p->parm.capture.extendedmode = 0; p->parm.capture.capturemode &= V4L2_MODE_HIGHQUALITY; } - return ops->vidioc_s_parm(file, fh, p); + return ops->vidioc_s_parm(file, NULL, p); } -static int v4l_queryctrl(const struct v4l2_ioctl_ops *ops, - struct file *file, void *fh, void *arg) +static int v4l_queryctrl(const struct v4l2_ioctl_ops *ops, struct file *file, + void *arg) { struct video_device *vfd = video_devdata(file); struct v4l2_query_ext_ctrl qec = {}; struct v4l2_queryctrl *p = arg; - struct v4l2_fh *vfh = - test_bit(V4L2_FL_USES_V4L2_FH, &vfd->flags) ? fh : NULL; + struct v4l2_fh *vfh = file_to_v4l2_fh(file); int ret; if (vfh && vfh->ctrl_handler) @@ -2310,7 +2307,7 @@ static int v4l_queryctrl(const struct v4l2_ioctl_ops *ops, /* Simulate query_ext_ctr using query_ctrl. */ qec.id = p->id; - ret = ops->vidioc_query_ext_ctrl(file, fh, &qec); + ret = ops->vidioc_query_ext_ctrl(file, NULL, &qec); if (ret) return ret; v4l2_query_ext_ctrl_to_v4l2_queryctrl(p, &qec); @@ -2318,46 +2315,43 @@ static int v4l_queryctrl(const struct v4l2_ioctl_ops *ops, } static int v4l_query_ext_ctrl(const struct v4l2_ioctl_ops *ops, - struct file *file, void *fh, void *arg) + struct file *file, void *arg) { struct video_device *vfd = video_devdata(file); struct v4l2_query_ext_ctrl *p = arg; - struct v4l2_fh *vfh = - test_bit(V4L2_FL_USES_V4L2_FH, &vfd->flags) ? fh : NULL; + struct v4l2_fh *vfh = file_to_v4l2_fh(file); if (vfh && vfh->ctrl_handler) return v4l2_query_ext_ctrl(vfh->ctrl_handler, p); if (vfd->ctrl_handler) return v4l2_query_ext_ctrl(vfd->ctrl_handler, p); if (ops->vidioc_query_ext_ctrl) - return ops->vidioc_query_ext_ctrl(file, fh, p); + return ops->vidioc_query_ext_ctrl(file, NULL, p); return -ENOTTY; } -static int v4l_querymenu(const struct v4l2_ioctl_ops *ops, - struct file *file, void *fh, void *arg) +static int v4l_querymenu(const struct v4l2_ioctl_ops *ops, struct file *file, + void *arg) { struct video_device *vfd = video_devdata(file); struct v4l2_querymenu *p = arg; - struct v4l2_fh *vfh = - test_bit(V4L2_FL_USES_V4L2_FH, &vfd->flags) ? fh : NULL; + struct v4l2_fh *vfh = file_to_v4l2_fh(file); if (vfh && vfh->ctrl_handler) return v4l2_querymenu(vfh->ctrl_handler, p); if (vfd->ctrl_handler) return v4l2_querymenu(vfd->ctrl_handler, p); if (ops->vidioc_querymenu) - return ops->vidioc_querymenu(file, fh, p); + return ops->vidioc_querymenu(file, NULL, p); return -ENOTTY; } -static int v4l_g_ctrl(const struct v4l2_ioctl_ops *ops, - struct file *file, void *fh, void *arg) +static int v4l_g_ctrl(const struct v4l2_ioctl_ops *ops, struct file *file, + void *arg) { struct video_device *vfd = video_devdata(file); struct v4l2_control *p = arg; - struct v4l2_fh *vfh = - test_bit(V4L2_FL_USES_V4L2_FH, &vfd->flags) ? fh : NULL; + struct v4l2_fh *vfh = file_to_v4l2_fh(file); struct v4l2_ext_controls ctrls; struct v4l2_ext_control ctrl; @@ -2374,7 +2368,7 @@ static int v4l_g_ctrl(const struct v4l2_ioctl_ops *ops, ctrl.id = p->id; ctrl.value = p->value; if (check_ext_ctrls(&ctrls, VIDIOC_G_CTRL)) { - int ret = ops->vidioc_g_ext_ctrls(file, fh, &ctrls); + int ret = ops->vidioc_g_ext_ctrls(file, NULL, &ctrls); if (ret == 0) p->value = ctrl.value; @@ -2383,13 +2377,12 @@ static int v4l_g_ctrl(const struct v4l2_ioctl_ops *ops, return -EINVAL; } -static int v4l_s_ctrl(const struct v4l2_ioctl_ops *ops, - struct file *file, void *fh, void *arg) +static int v4l_s_ctrl(const struct v4l2_ioctl_ops *ops, struct file *file, + void *arg) { struct video_device *vfd = video_devdata(file); struct v4l2_control *p = arg; - struct v4l2_fh *vfh = - test_bit(V4L2_FL_USES_V4L2_FH, &vfd->flags) ? fh : NULL; + struct v4l2_fh *vfh = file_to_v4l2_fh(file); struct v4l2_ext_controls ctrls; struct v4l2_ext_control ctrl; int ret; @@ -2408,18 +2401,17 @@ static int v4l_s_ctrl(const struct v4l2_ioctl_ops *ops, ctrl.value = p->value; if (!check_ext_ctrls(&ctrls, VIDIOC_S_CTRL)) return -EINVAL; - ret = ops->vidioc_s_ext_ctrls(file, fh, &ctrls); + ret = ops->vidioc_s_ext_ctrls(file, NULL, &ctrls); p->value = ctrl.value; return ret; } static int v4l_g_ext_ctrls(const struct v4l2_ioctl_ops *ops, - struct file *file, void *fh, void *arg) + struct file *file, void *arg) { struct video_device *vfd = video_devdata(file); struct v4l2_ext_controls *p = arg; - struct v4l2_fh *vfh = - test_bit(V4L2_FL_USES_V4L2_FH, &vfd->flags) ? fh : NULL; + struct v4l2_fh *vfh = file_to_v4l2_fh(file); p->error_idx = p->count; if (vfh && vfh->ctrl_handler) @@ -2431,16 +2423,15 @@ static int v4l_g_ext_ctrls(const struct v4l2_ioctl_ops *ops, if (ops->vidioc_g_ext_ctrls == NULL) return -ENOTTY; return check_ext_ctrls(p, VIDIOC_G_EXT_CTRLS) ? - ops->vidioc_g_ext_ctrls(file, fh, p) : -EINVAL; + ops->vidioc_g_ext_ctrls(file, NULL, p) : -EINVAL; } static int v4l_s_ext_ctrls(const struct v4l2_ioctl_ops *ops, - struct file *file, void *fh, void *arg) + struct file *file, void *arg) { struct video_device *vfd = video_devdata(file); struct v4l2_ext_controls *p = arg; - struct v4l2_fh *vfh = - test_bit(V4L2_FL_USES_V4L2_FH, &vfd->flags) ? fh : NULL; + struct v4l2_fh *vfh = file_to_v4l2_fh(file); p->error_idx = p->count; if (vfh && vfh->ctrl_handler) @@ -2452,16 +2443,15 @@ static int v4l_s_ext_ctrls(const struct v4l2_ioctl_ops *ops, if (ops->vidioc_s_ext_ctrls == NULL) return -ENOTTY; return check_ext_ctrls(p, VIDIOC_S_EXT_CTRLS) ? - ops->vidioc_s_ext_ctrls(file, fh, p) : -EINVAL; + ops->vidioc_s_ext_ctrls(file, NULL, p) : -EINVAL; } static int v4l_try_ext_ctrls(const struct v4l2_ioctl_ops *ops, - struct file *file, void *fh, void *arg) + struct file *file, void *arg) { struct video_device *vfd = video_devdata(file); struct v4l2_ext_controls *p = arg; - struct v4l2_fh *vfh = - test_bit(V4L2_FL_USES_V4L2_FH, &vfd->flags) ? fh : NULL; + struct v4l2_fh *vfh = file_to_v4l2_fh(file); p->error_idx = p->count; if (vfh && vfh->ctrl_handler) @@ -2473,7 +2463,7 @@ static int v4l_try_ext_ctrls(const struct v4l2_ioctl_ops *ops, if (ops->vidioc_try_ext_ctrls == NULL) return -ENOTTY; return check_ext_ctrls(p, VIDIOC_TRY_EXT_CTRLS) ? - ops->vidioc_try_ext_ctrls(file, fh, p) : -EINVAL; + ops->vidioc_try_ext_ctrls(file, NULL, p) : -EINVAL; } /* @@ -2486,7 +2476,7 @@ static int v4l_try_ext_ctrls(const struct v4l2_ioctl_ops *ops, * type and drivers don't need to check for both. */ static int v4l_g_selection(const struct v4l2_ioctl_ops *ops, - struct file *file, void *fh, void *arg) + struct file *file, void *arg) { struct v4l2_selection *p = arg; u32 old_type = p->type; @@ -2496,13 +2486,13 @@ static int v4l_g_selection(const struct v4l2_ioctl_ops *ops, p->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; else if (p->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) p->type = V4L2_BUF_TYPE_VIDEO_OUTPUT; - ret = ops->vidioc_g_selection(file, fh, p); + ret = ops->vidioc_g_selection(file, NULL, p); p->type = old_type; return ret; } static int v4l_s_selection(const struct v4l2_ioctl_ops *ops, - struct file *file, void *fh, void *arg) + struct file *file, void *arg) { struct v4l2_selection *p = arg; u32 old_type = p->type; @@ -2512,13 +2502,13 @@ static int v4l_s_selection(const struct v4l2_ioctl_ops *ops, p->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; else if (p->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) p->type = V4L2_BUF_TYPE_VIDEO_OUTPUT; - ret = ops->vidioc_s_selection(file, fh, p); + ret = ops->vidioc_s_selection(file, NULL, p); p->type = old_type; return ret; } -static int v4l_g_crop(const struct v4l2_ioctl_ops *ops, - struct file *file, void *fh, void *arg) +static int v4l_g_crop(const struct v4l2_ioctl_ops *ops, struct file *file, + void *arg) { struct video_device *vfd = video_devdata(file); struct v4l2_crop *p = arg; @@ -2539,7 +2529,7 @@ static int v4l_g_crop(const struct v4l2_ioctl_ops *ops, s.target = s.target == V4L2_SEL_TGT_COMPOSE ? V4L2_SEL_TGT_CROP : V4L2_SEL_TGT_COMPOSE; - ret = v4l_g_selection(ops, file, fh, &s); + ret = v4l_g_selection(ops, file, &s); /* copying results to old structure on success */ if (!ret) @@ -2547,8 +2537,8 @@ static int v4l_g_crop(const struct v4l2_ioctl_ops *ops, return ret; } -static int v4l_s_crop(const struct v4l2_ioctl_ops *ops, - struct file *file, void *fh, void *arg) +static int v4l_s_crop(const struct v4l2_ioctl_ops *ops, struct file *file, + void *arg) { struct video_device *vfd = video_devdata(file); struct v4l2_crop *p = arg; @@ -2569,11 +2559,11 @@ static int v4l_s_crop(const struct v4l2_ioctl_ops *ops, s.target = s.target == V4L2_SEL_TGT_COMPOSE ? V4L2_SEL_TGT_CROP : V4L2_SEL_TGT_COMPOSE; - return v4l_s_selection(ops, file, fh, &s); + return v4l_s_selection(ops, file, &s); } -static int v4l_cropcap(const struct v4l2_ioctl_ops *ops, - struct file *file, void *fh, void *arg) +static int v4l_cropcap(const struct v4l2_ioctl_ops *ops, struct file *file, + void *arg) { struct video_device *vfd = video_devdata(file); struct v4l2_cropcap *p = arg; @@ -2597,7 +2587,7 @@ static int v4l_cropcap(const struct v4l2_ioctl_ops *ops, return -ENOTTY; if (ops->vidioc_g_pixelaspect) - ret = ops->vidioc_g_pixelaspect(file, fh, s.type, + ret = ops->vidioc_g_pixelaspect(file, NULL, s.type, &p->pixelaspect); /* @@ -2619,7 +2609,7 @@ static int v4l_cropcap(const struct v4l2_ioctl_ops *ops, s.target = s.target == V4L2_SEL_TGT_COMPOSE_BOUNDS ? V4L2_SEL_TGT_CROP_BOUNDS : V4L2_SEL_TGT_COMPOSE_BOUNDS; - ret = v4l_g_selection(ops, file, fh, &s); + ret = v4l_g_selection(ops, file, &s); if (ret) return ret; p->bounds = s.r; @@ -2630,7 +2620,7 @@ static int v4l_cropcap(const struct v4l2_ioctl_ops *ops, else s.target = V4L2_SEL_TGT_CROP_DEFAULT; - ret = v4l_g_selection(ops, file, fh, &s); + ret = v4l_g_selection(ops, file, &s); if (ret) return ret; p->defrect = s.r; @@ -2638,8 +2628,8 @@ static int v4l_cropcap(const struct v4l2_ioctl_ops *ops, return 0; } -static int v4l_log_status(const struct v4l2_ioctl_ops *ops, - struct file *file, void *fh, void *arg) +static int v4l_log_status(const struct v4l2_ioctl_ops *ops, struct file *file, + void *arg) { struct video_device *vfd = video_devdata(file); int ret; @@ -2647,7 +2637,7 @@ static int v4l_log_status(const struct v4l2_ioctl_ops *ops, if (vfd->v4l2_dev) pr_info("%s: ================= START STATUS =================\n", vfd->v4l2_dev->name); - ret = ops->vidioc_log_status(file, fh); + ret = ops->vidioc_log_status(file, NULL); if (vfd->v4l2_dev) pr_info("%s: ================== END STATUS ==================\n", vfd->v4l2_dev->name); @@ -2655,7 +2645,7 @@ static int v4l_log_status(const struct v4l2_ioctl_ops *ops, } static int v4l_dbg_g_register(const struct v4l2_ioctl_ops *ops, - struct file *file, void *fh, void *arg) + struct file *file, void *arg) { #ifdef CONFIG_VIDEO_ADV_DEBUG struct v4l2_dbg_register *p = arg; @@ -2675,7 +2665,7 @@ static int v4l_dbg_g_register(const struct v4l2_ioctl_ops *ops, } if (ops->vidioc_g_register && p->match.type == V4L2_CHIP_MATCH_BRIDGE && (ops->vidioc_g_chip_info || p->match.addr == 0)) - return ops->vidioc_g_register(file, fh, p); + return ops->vidioc_g_register(file, NULL, p); return -EINVAL; #else return -ENOTTY; @@ -2683,7 +2673,7 @@ static int v4l_dbg_g_register(const struct v4l2_ioctl_ops *ops, } static int v4l_dbg_s_register(const struct v4l2_ioctl_ops *ops, - struct file *file, void *fh, void *arg) + struct file *file, void *arg) { #ifdef CONFIG_VIDEO_ADV_DEBUG const struct v4l2_dbg_register *p = arg; @@ -2703,7 +2693,7 @@ static int v4l_dbg_s_register(const struct v4l2_ioctl_ops *ops, } if (ops->vidioc_s_register && p->match.type == V4L2_CHIP_MATCH_BRIDGE && (ops->vidioc_g_chip_info || p->match.addr == 0)) - return ops->vidioc_s_register(file, fh, p); + return ops->vidioc_s_register(file, NULL, p); return -EINVAL; #else return -ENOTTY; @@ -2711,7 +2701,7 @@ static int v4l_dbg_s_register(const struct v4l2_ioctl_ops *ops, } static int v4l_dbg_g_chip_info(const struct v4l2_ioctl_ops *ops, - struct file *file, void *fh, void *arg) + struct file *file, void *arg) { #ifdef CONFIG_VIDEO_ADV_DEBUG struct video_device *vfd = video_devdata(file); @@ -2727,7 +2717,7 @@ static int v4l_dbg_g_chip_info(const struct v4l2_ioctl_ops *ops, p->flags |= V4L2_CHIP_FL_READABLE; strscpy(p->name, vfd->v4l2_dev->name, sizeof(p->name)); if (ops->vidioc_g_chip_info) - return ops->vidioc_g_chip_info(file, fh, arg); + return ops->vidioc_g_chip_info(file, NULL, arg); if (p->match.addr) return -EINVAL; return 0; @@ -2753,26 +2743,32 @@ static int v4l_dbg_g_chip_info(const struct v4l2_ioctl_ops *ops, #endif } -static int v4l_dqevent(const struct v4l2_ioctl_ops *ops, - struct file *file, void *fh, void *arg) +static int v4l_dqevent(const struct v4l2_ioctl_ops *ops, struct file *file, + void *arg) { - return v4l2_event_dequeue(fh, arg, file->f_flags & O_NONBLOCK); + struct v4l2_fh *vfh = file_to_v4l2_fh(file); + + return v4l2_event_dequeue(vfh, arg, file->f_flags & O_NONBLOCK); } static int v4l_subscribe_event(const struct v4l2_ioctl_ops *ops, - struct file *file, void *fh, void *arg) + struct file *file, void *arg) { - return ops->vidioc_subscribe_event(fh, arg); + struct v4l2_fh *vfh = file_to_v4l2_fh(file); + + return ops->vidioc_subscribe_event(vfh, arg); } static int v4l_unsubscribe_event(const struct v4l2_ioctl_ops *ops, - struct file *file, void *fh, void *arg) + struct file *file, void *arg) { - return ops->vidioc_unsubscribe_event(fh, arg); + struct v4l2_fh *vfh = file_to_v4l2_fh(file); + + return ops->vidioc_unsubscribe_event(vfh, arg); } static int v4l_g_sliced_vbi_cap(const struct v4l2_ioctl_ops *ops, - struct file *file, void *fh, void *arg) + struct file *file, void *arg) { struct v4l2_sliced_vbi_cap *p = arg; int ret = check_fmt(file, p->type); @@ -2783,11 +2779,11 @@ static int v4l_g_sliced_vbi_cap(const struct v4l2_ioctl_ops *ops, /* Clear up to type, everything after type is zeroed already */ memset(p, 0, offsetof(struct v4l2_sliced_vbi_cap, type)); - return ops->vidioc_g_sliced_vbi_cap(file, fh, p); + return ops->vidioc_g_sliced_vbi_cap(file, NULL, p); } static int v4l_enum_freq_bands(const struct v4l2_ioctl_ops *ops, - struct file *file, void *fh, void *arg) + struct file *file, void *arg) { struct video_device *vfd = video_devdata(file); struct v4l2_frequency_band *p = arg; @@ -2805,7 +2801,7 @@ static int v4l_enum_freq_bands(const struct v4l2_ioctl_ops *ops, return -EINVAL; } if (ops->vidioc_enum_freq_bands) { - err = ops->vidioc_enum_freq_bands(file, fh, p); + err = ops->vidioc_enum_freq_bands(file, NULL, p); if (err != -ENOTTY) return err; } @@ -2817,7 +2813,7 @@ static int v4l_enum_freq_bands(const struct v4l2_ioctl_ops *ops, if (p->index) return -EINVAL; - err = ops->vidioc_g_tuner(file, fh, &t); + err = ops->vidioc_g_tuner(file, NULL, &t); if (err) return err; p->capability = t.capability | V4L2_TUNER_CAP_FREQ_BANDS; @@ -2836,7 +2832,7 @@ static int v4l_enum_freq_bands(const struct v4l2_ioctl_ops *ops, return -EINVAL; if (p->index) return -EINVAL; - err = ops->vidioc_g_modulator(file, fh, &m); + err = ops->vidioc_g_modulator(file, NULL, &m); if (err) return err; p->capability = m.capability | V4L2_TUNER_CAP_FREQ_BANDS; @@ -2853,7 +2849,7 @@ struct v4l2_ioctl_info { u32 flags; const char * const name; int (*func)(const struct v4l2_ioctl_ops *ops, struct file *file, - void *fh, void *p); + void *p); void (*debug)(const void *arg, bool write_only); }; @@ -2874,9 +2870,9 @@ struct v4l2_ioctl_info { #define DEFINE_V4L_STUB_FUNC(_vidioc) \ static int v4l_stub_ ## _vidioc( \ const struct v4l2_ioctl_ops *ops, \ - struct file *file, void *fh, void *p) \ + struct file *file, void *p) \ { \ - return ops->vidioc_ ## _vidioc(file, fh, p); \ + return ops->vidioc_ ## _vidioc(file, NULL, p); \ } #define IOCTL_INFO(_ioctl, _func, _debug, _flags) \ @@ -3072,8 +3068,7 @@ static long __video_do_ioctl(struct file *file, bool write_only = false; struct v4l2_ioctl_info default_info; const struct v4l2_ioctl_info *info; - void *fh = file->private_data; - struct v4l2_fh *vfh = NULL; + struct v4l2_fh *vfh = file_to_v4l2_fh(file); int dev_debug = vfd->dev_debug; long ret = -ENOTTY; @@ -3083,9 +3078,6 @@ static long __video_do_ioctl(struct file *file, return ret; } - if (test_bit(V4L2_FL_USES_V4L2_FH, &vfd->flags)) - vfh = file->private_data; - /* * We need to serialize streamon/off with queueing new requests. * These ioctls may trigger the cancellation of a streaming @@ -3117,10 +3109,10 @@ static long __video_do_ioctl(struct file *file, info = &v4l2_ioctls[_IOC_NR(cmd)]; if (!is_valid_ioctl(vfd, cmd) && - !((info->flags & INFO_FL_CTRL) && vfh && vfh->ctrl_handler)) + !((info->flags & INFO_FL_CTRL) && vfh->ctrl_handler)) goto done; - if (vfh && (info->flags & INFO_FL_PRIO)) { + if (info->flags & INFO_FL_PRIO) { ret = v4l2_prio_check(vfd->prio, vfh->prio); if (ret) goto done; @@ -3134,12 +3126,12 @@ static long __video_do_ioctl(struct file *file, write_only = _IOC_DIR(cmd) == _IOC_WRITE; if (info != &default_info) { - ret = info->func(ops, file, fh, arg); + ret = info->func(ops, file, arg); } else if (!ops->vidioc_default) { ret = -ENOTTY; } else { - ret = ops->vidioc_default(file, fh, - vfh ? v4l2_prio_check(vfd->prio, vfh->prio) >= 0 : 0, + ret = ops->vidioc_default(file, NULL, + v4l2_prio_check(vfd->prio, vfh->prio) >= 0, cmd, arg); } diff --git a/drivers/media/v4l2-core/v4l2-mem2mem.c b/drivers/media/v4l2-core/v4l2-mem2mem.c index eb22d6172462..21acd9bc8607 100644 --- a/drivers/media/v4l2-core/v4l2-mem2mem.c +++ b/drivers/media/v4l2-core/v4l2-mem2mem.c @@ -951,7 +951,7 @@ static __poll_t v4l2_m2m_poll_for_data(struct file *file, __poll_t v4l2_m2m_poll(struct file *file, struct v4l2_m2m_ctx *m2m_ctx, struct poll_table_struct *wait) { - struct video_device *vfd = video_devdata(file); + struct v4l2_fh *fh = file_to_v4l2_fh(file); struct vb2_queue *src_q = v4l2_m2m_get_src_vq(m2m_ctx); struct vb2_queue *dst_q = v4l2_m2m_get_dst_vq(m2m_ctx); __poll_t req_events = poll_requested_events(wait); @@ -970,13 +970,9 @@ __poll_t v4l2_m2m_poll(struct file *file, struct v4l2_m2m_ctx *m2m_ctx, if (req_events & (EPOLLOUT | EPOLLWRNORM | EPOLLIN | EPOLLRDNORM)) rc = v4l2_m2m_poll_for_data(file, m2m_ctx, wait); - if (test_bit(V4L2_FL_USES_V4L2_FH, &vfd->flags)) { - struct v4l2_fh *fh = file->private_data; - - poll_wait(file, &fh->wait, wait); - if (v4l2_event_pending(fh)) - rc |= EPOLLPRI; - } + poll_wait(file, &fh->wait, wait); + if (v4l2_event_pending(fh)) + rc |= EPOLLPRI; return rc; } @@ -1004,7 +1000,7 @@ unsigned long v4l2_m2m_get_unmapped_area(struct file *file, unsigned long addr, unsigned long len, unsigned long pgoff, unsigned long flags) { - struct v4l2_fh *fh = file->private_data; + struct v4l2_fh *fh = file_to_v4l2_fh(file); unsigned long offset = pgoff << PAGE_SHIFT; struct vb2_queue *vq; @@ -1371,7 +1367,7 @@ EXPORT_SYMBOL_GPL(v4l2_m2m_request_queue); int v4l2_m2m_ioctl_reqbufs(struct file *file, void *priv, struct v4l2_requestbuffers *rb) { - struct v4l2_fh *fh = file->private_data; + struct v4l2_fh *fh = file_to_v4l2_fh(file); return v4l2_m2m_reqbufs(file, fh->m2m_ctx, rb); } @@ -1380,7 +1376,7 @@ EXPORT_SYMBOL_GPL(v4l2_m2m_ioctl_reqbufs); int v4l2_m2m_ioctl_create_bufs(struct file *file, void *priv, struct v4l2_create_buffers *create) { - struct v4l2_fh *fh = file->private_data; + struct v4l2_fh *fh = file_to_v4l2_fh(file); return v4l2_m2m_create_bufs(file, fh->m2m_ctx, create); } @@ -1389,7 +1385,7 @@ EXPORT_SYMBOL_GPL(v4l2_m2m_ioctl_create_bufs); int v4l2_m2m_ioctl_remove_bufs(struct file *file, void *priv, struct v4l2_remove_buffers *remove) { - struct v4l2_fh *fh = file->private_data; + struct v4l2_fh *fh = file_to_v4l2_fh(file); struct vb2_queue *q = v4l2_m2m_get_vq(fh->m2m_ctx, remove->type); if (!q) @@ -1404,7 +1400,7 @@ EXPORT_SYMBOL_GPL(v4l2_m2m_ioctl_remove_bufs); int v4l2_m2m_ioctl_querybuf(struct file *file, void *priv, struct v4l2_buffer *buf) { - struct v4l2_fh *fh = file->private_data; + struct v4l2_fh *fh = file_to_v4l2_fh(file); return v4l2_m2m_querybuf(file, fh->m2m_ctx, buf); } @@ -1413,7 +1409,7 @@ EXPORT_SYMBOL_GPL(v4l2_m2m_ioctl_querybuf); int v4l2_m2m_ioctl_qbuf(struct file *file, void *priv, struct v4l2_buffer *buf) { - struct v4l2_fh *fh = file->private_data; + struct v4l2_fh *fh = file_to_v4l2_fh(file); return v4l2_m2m_qbuf(file, fh->m2m_ctx, buf); } @@ -1422,7 +1418,7 @@ EXPORT_SYMBOL_GPL(v4l2_m2m_ioctl_qbuf); int v4l2_m2m_ioctl_dqbuf(struct file *file, void *priv, struct v4l2_buffer *buf) { - struct v4l2_fh *fh = file->private_data; + struct v4l2_fh *fh = file_to_v4l2_fh(file); return v4l2_m2m_dqbuf(file, fh->m2m_ctx, buf); } @@ -1431,7 +1427,7 @@ EXPORT_SYMBOL_GPL(v4l2_m2m_ioctl_dqbuf); int v4l2_m2m_ioctl_prepare_buf(struct file *file, void *priv, struct v4l2_buffer *buf) { - struct v4l2_fh *fh = file->private_data; + struct v4l2_fh *fh = file_to_v4l2_fh(file); return v4l2_m2m_prepare_buf(file, fh->m2m_ctx, buf); } @@ -1440,7 +1436,7 @@ EXPORT_SYMBOL_GPL(v4l2_m2m_ioctl_prepare_buf); int v4l2_m2m_ioctl_expbuf(struct file *file, void *priv, struct v4l2_exportbuffer *eb) { - struct v4l2_fh *fh = file->private_data; + struct v4l2_fh *fh = file_to_v4l2_fh(file); return v4l2_m2m_expbuf(file, fh->m2m_ctx, eb); } @@ -1449,7 +1445,7 @@ EXPORT_SYMBOL_GPL(v4l2_m2m_ioctl_expbuf); int v4l2_m2m_ioctl_streamon(struct file *file, void *priv, enum v4l2_buf_type type) { - struct v4l2_fh *fh = file->private_data; + struct v4l2_fh *fh = file_to_v4l2_fh(file); return v4l2_m2m_streamon(file, fh->m2m_ctx, type); } @@ -1458,13 +1454,13 @@ EXPORT_SYMBOL_GPL(v4l2_m2m_ioctl_streamon); int v4l2_m2m_ioctl_streamoff(struct file *file, void *priv, enum v4l2_buf_type type) { - struct v4l2_fh *fh = file->private_data; + struct v4l2_fh *fh = file_to_v4l2_fh(file); return v4l2_m2m_streamoff(file, fh->m2m_ctx, type); } EXPORT_SYMBOL_GPL(v4l2_m2m_ioctl_streamoff); -int v4l2_m2m_ioctl_try_encoder_cmd(struct file *file, void *fh, +int v4l2_m2m_ioctl_try_encoder_cmd(struct file *file, void *priv, struct v4l2_encoder_cmd *ec) { if (ec->cmd != V4L2_ENC_CMD_STOP && ec->cmd != V4L2_ENC_CMD_START) @@ -1475,7 +1471,7 @@ int v4l2_m2m_ioctl_try_encoder_cmd(struct file *file, void *fh, } EXPORT_SYMBOL_GPL(v4l2_m2m_ioctl_try_encoder_cmd); -int v4l2_m2m_ioctl_try_decoder_cmd(struct file *file, void *fh, +int v4l2_m2m_ioctl_try_decoder_cmd(struct file *file, void *priv, struct v4l2_decoder_cmd *dc) { if (dc->cmd != V4L2_DEC_CMD_STOP && dc->cmd != V4L2_DEC_CMD_START) @@ -1542,7 +1538,7 @@ EXPORT_SYMBOL_GPL(v4l2_m2m_decoder_cmd); int v4l2_m2m_ioctl_encoder_cmd(struct file *file, void *priv, struct v4l2_encoder_cmd *ec) { - struct v4l2_fh *fh = file->private_data; + struct v4l2_fh *fh = file_to_v4l2_fh(file); return v4l2_m2m_encoder_cmd(file, fh->m2m_ctx, ec); } @@ -1551,13 +1547,13 @@ EXPORT_SYMBOL_GPL(v4l2_m2m_ioctl_encoder_cmd); int v4l2_m2m_ioctl_decoder_cmd(struct file *file, void *priv, struct v4l2_decoder_cmd *dc) { - struct v4l2_fh *fh = file->private_data; + struct v4l2_fh *fh = file_to_v4l2_fh(file); return v4l2_m2m_decoder_cmd(file, fh->m2m_ctx, dc); } EXPORT_SYMBOL_GPL(v4l2_m2m_ioctl_decoder_cmd); -int v4l2_m2m_ioctl_stateless_try_decoder_cmd(struct file *file, void *fh, +int v4l2_m2m_ioctl_stateless_try_decoder_cmd(struct file *file, void *priv, struct v4l2_decoder_cmd *dc) { if (dc->cmd != V4L2_DEC_CMD_FLUSH) @@ -1572,7 +1568,7 @@ EXPORT_SYMBOL_GPL(v4l2_m2m_ioctl_stateless_try_decoder_cmd); int v4l2_m2m_ioctl_stateless_decoder_cmd(struct file *file, void *priv, struct v4l2_decoder_cmd *dc) { - struct v4l2_fh *fh = file->private_data; + struct v4l2_fh *fh = file_to_v4l2_fh(file); struct vb2_v4l2_buffer *out_vb, *cap_vb; struct v4l2_m2m_dev *m2m_dev = fh->m2m_ctx->m2m_dev; unsigned long flags; @@ -1617,7 +1613,7 @@ EXPORT_SYMBOL_GPL(v4l2_m2m_ioctl_stateless_decoder_cmd); int v4l2_m2m_fop_mmap(struct file *file, struct vm_area_struct *vma) { - struct v4l2_fh *fh = file->private_data; + struct v4l2_fh *fh = file_to_v4l2_fh(file); return v4l2_m2m_mmap(file, fh->m2m_ctx, vma); } @@ -1625,7 +1621,7 @@ EXPORT_SYMBOL_GPL(v4l2_m2m_fop_mmap); __poll_t v4l2_m2m_fop_poll(struct file *file, poll_table *wait) { - struct v4l2_fh *fh = file->private_data; + struct v4l2_fh *fh = file_to_v4l2_fh(file); struct v4l2_m2m_ctx *m2m_ctx = fh->m2m_ctx; __poll_t ret; diff --git a/drivers/media/v4l2-core/v4l2-subdev.c b/drivers/media/v4l2-core/v4l2-subdev.c index 4fd25fea3b58..1da953629010 100644 --- a/drivers/media/v4l2-core/v4l2-subdev.c +++ b/drivers/media/v4l2-core/v4l2-subdev.c @@ -26,6 +26,30 @@ #include <media/v4l2-fh.h> #include <media/v4l2-ioctl.h> +/** + * struct v4l2_subdev_stream_config - Used for storing stream configuration. + * + * @pad: pad number + * @stream: stream number + * @enabled: has the stream been enabled with v4l2_subdev_enable_streams() + * @fmt: &struct v4l2_mbus_framefmt + * @crop: &struct v4l2_rect to be used for crop + * @compose: &struct v4l2_rect to be used for compose + * @interval: frame interval + * + * This structure stores configuration for a stream. + */ +struct v4l2_subdev_stream_config { + u32 pad; + u32 stream; + bool enabled; + + struct v4l2_mbus_framefmt fmt; + struct v4l2_rect crop; + struct v4l2_rect compose; + struct v4l2_fract interval; +}; + #if defined(CONFIG_VIDEO_V4L2_SUBDEV_API) /* * The Streams API is an experimental feature. To use the Streams API, set @@ -86,8 +110,7 @@ static int subdev_open(struct file *file) } v4l2_fh_init(&subdev_fh->vfh, vdev); - v4l2_fh_add(&subdev_fh->vfh); - file->private_data = &subdev_fh->vfh; + v4l2_fh_add(&subdev_fh->vfh, file); if (sd->v4l2_dev->mdev && sd->entity.graph_obj.mdev->dev) { struct module *owner; @@ -110,7 +133,7 @@ static int subdev_open(struct file *file) err: module_put(subdev_fh->owner); - v4l2_fh_del(&subdev_fh->vfh); + v4l2_fh_del(&subdev_fh->vfh, file); v4l2_fh_exit(&subdev_fh->vfh); subdev_fh_free(subdev_fh); kfree(subdev_fh); @@ -122,17 +145,16 @@ static int subdev_close(struct file *file) { struct video_device *vdev = video_devdata(file); struct v4l2_subdev *sd = vdev_to_v4l2_subdev(vdev); - struct v4l2_fh *vfh = file->private_data; + struct v4l2_fh *vfh = file_to_v4l2_fh(file); struct v4l2_subdev_fh *subdev_fh = to_v4l2_subdev_fh(vfh); if (sd->internal_ops && sd->internal_ops->close) sd->internal_ops->close(sd, subdev_fh); module_put(subdev_fh->owner); - v4l2_fh_del(vfh); + v4l2_fh_del(vfh, file); v4l2_fh_exit(vfh); subdev_fh_free(subdev_fh); kfree(subdev_fh); - file->private_data = NULL; return 0; } @@ -612,7 +634,7 @@ static long subdev_do_ioctl(struct file *file, unsigned int cmd, void *arg, { struct video_device *vdev = video_devdata(file); struct v4l2_subdev *sd = vdev_to_v4l2_subdev(vdev); - struct v4l2_fh *vfh = file->private_data; + struct v4l2_fh *vfh = file_to_v4l2_fh(file); struct v4l2_subdev_fh *subdev_fh = to_v4l2_subdev_fh(vfh); bool ro_subdev = test_bit(V4L2_FL_SUBDEV_RO_DEVNODE, &vdev->flags); bool streams_subdev = sd->flags & V4L2_SUBDEV_FL_STREAMS; @@ -1135,7 +1157,7 @@ static long subdev_do_ioctl_lock(struct file *file, unsigned int cmd, void *arg) if (video_is_registered(vdev)) { struct v4l2_subdev *sd = vdev_to_v4l2_subdev(vdev); - struct v4l2_fh *vfh = file->private_data; + struct v4l2_fh *vfh = file_to_v4l2_fh(file); struct v4l2_subdev_fh *subdev_fh = to_v4l2_subdev_fh(vfh); struct v4l2_subdev_state *state; @@ -1192,7 +1214,7 @@ static __poll_t subdev_poll(struct file *file, poll_table *wait) { struct video_device *vdev = video_devdata(file); struct v4l2_subdev *sd = vdev_to_v4l2_subdev(vdev); - struct v4l2_fh *fh = file->private_data; + struct v4l2_fh *fh = file_to_v4l2_fh(file); if (!(sd->flags & V4L2_SUBDEV_FL_HAS_EVENTS)) return EPOLLERR; diff --git a/drivers/staging/media/atomisp/i2c/Kconfig b/drivers/staging/media/atomisp/i2c/Kconfig index ef2094c22347..7d447ba7a7e1 100644 --- a/drivers/staging/media/atomisp/i2c/Kconfig +++ b/drivers/staging/media/atomisp/i2c/Kconfig @@ -26,12 +26,3 @@ config VIDEO_ATOMISP_GC2235 GC2235 is a 2M raw sensor. It currently only works with the atomisp driver. - -config VIDEO_ATOMISP_GC0310 - tristate "GC0310 sensor support" - depends on ACPI - depends on I2C && VIDEO_DEV - select V4L2_CCI_I2C - help - This is a Video4Linux2 sensor-level driver for the Galaxycore - GC0310 0.3MP sensor. diff --git a/drivers/staging/media/atomisp/i2c/Makefile b/drivers/staging/media/atomisp/i2c/Makefile index e1637417e5c5..161aa542ef34 100644 --- a/drivers/staging/media/atomisp/i2c/Makefile +++ b/drivers/staging/media/atomisp/i2c/Makefile @@ -5,4 +5,3 @@ obj-$(CONFIG_VIDEO_ATOMISP_GC2235) += atomisp-gc2235.o obj-$(CONFIG_VIDEO_ATOMISP_OV2722) += atomisp-ov2722.o -obj-$(CONFIG_VIDEO_ATOMISP_GC0310) += atomisp-gc0310.o diff --git a/drivers/staging/media/atomisp/pci/atomisp_subdev.c b/drivers/staging/media/atomisp/pci/atomisp_subdev.c index 22c0ae0b1b7b..3d56ca83ecb7 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_subdev.c +++ b/drivers/staging/media/atomisp/pci/atomisp_subdev.c @@ -161,13 +161,6 @@ static int isp_subdev_subscribe_event(struct v4l2_subdev *sd, return v4l2_event_subscribe(fh, sub, 16, NULL); } -static int isp_subdev_unsubscribe_event(struct v4l2_subdev *sd, - struct v4l2_fh *fh, - struct v4l2_event_subscription *sub) -{ - return v4l2_event_unsubscribe(fh, sub); -} - /* * isp_subdev_enum_mbus_code - Handle pixel format enumeration * @sd: pointer to v4l2 subdev structure @@ -575,7 +568,7 @@ static int isp_subdev_set_format(struct v4l2_subdev *sd, static const struct v4l2_subdev_core_ops isp_subdev_v4l2_core_ops = { .ioctl = isp_subdev_ioctl, .subscribe_event = isp_subdev_subscribe_event, - .unsubscribe_event = isp_subdev_unsubscribe_event, + .unsubscribe_event = v4l2_event_subdev_unsubscribe, }; /* V4L2 subdev pad operations */ diff --git a/drivers/staging/media/atomisp/pci/runtime/bufq/src/bufq.c b/drivers/staging/media/atomisp/pci/runtime/bufq/src/bufq.c index bda35614c862..0f0d16f4ce7c 100644 --- a/drivers/staging/media/atomisp/pci/runtime/bufq/src/bufq.c +++ b/drivers/staging/media/atomisp/pci/runtime/bufq/src/bufq.c @@ -497,7 +497,7 @@ void ia_css_bufq_dump_queue_info(void) for (i = 0; i < SH_CSS_MAX_SP_THREADS; i++) { for (j = 0; j < SH_CSS_MAX_NUM_QUEUES; j++) { snprintf(prefix, BUFQ_DUMP_FILE_NAME_PREFIX_SIZE, - "host2sp_buffer_queue[%u][%u]", i, j); + "host2sp_buffer_queue[%d][%d]", i, j); bufq_dump_queue_info(prefix, &css_queues.host2sp_buffer_queue_handles[i][j]); } @@ -505,7 +505,7 @@ void ia_css_bufq_dump_queue_info(void) for (i = 0; i < SH_CSS_MAX_NUM_QUEUES; i++) { snprintf(prefix, BUFQ_DUMP_FILE_NAME_PREFIX_SIZE, - "sp2host_buffer_queue[%u]", i); + "sp2host_buffer_queue[%d]", i); bufq_dump_queue_info(prefix, &css_queues.sp2host_buffer_queue_handles[i]); } diff --git a/drivers/staging/media/imx/imx-media-csc-scaler.c b/drivers/staging/media/imx/imx-media-csc-scaler.c index 19fd31cb9bb0..1869c5792ecb 100644 --- a/drivers/staging/media/imx/imx-media-csc-scaler.c +++ b/drivers/staging/media/imx/imx-media-csc-scaler.c @@ -23,8 +23,6 @@ #include "imx-media.h" -#define fh_to_ctx(__fh) container_of(__fh, struct ipu_csc_scaler_ctx, fh) - #define IMX_CSC_SCALER_NAME "imx-csc-scaler" enum { @@ -66,6 +64,11 @@ struct ipu_csc_scaler_ctx { unsigned int sequence; }; +static inline struct ipu_csc_scaler_ctx *file_to_ctx(struct file *filp) +{ + return container_of(file_to_v4l2_fh(filp), struct ipu_csc_scaler_ctx, fh); +} + static struct ipu_csc_scaler_q_data *get_q_data(struct ipu_csc_scaler_ctx *ctx, enum v4l2_buf_type type) { @@ -179,7 +182,7 @@ static int ipu_csc_scaler_enum_fmt(struct file *file, void *fh, static int ipu_csc_scaler_g_fmt(struct file *file, void *priv, struct v4l2_format *f) { - struct ipu_csc_scaler_ctx *ctx = fh_to_ctx(priv); + struct ipu_csc_scaler_ctx *ctx = file_to_ctx(file); struct ipu_csc_scaler_q_data *q_data; q_data = get_q_data(ctx, f->type); @@ -192,7 +195,7 @@ static int ipu_csc_scaler_g_fmt(struct file *file, void *priv, static int ipu_csc_scaler_try_fmt(struct file *file, void *priv, struct v4l2_format *f) { - struct ipu_csc_scaler_ctx *ctx = fh_to_ctx(priv); + struct ipu_csc_scaler_ctx *ctx = file_to_ctx(file); struct ipu_csc_scaler_q_data *q_data = get_q_data(ctx, f->type); struct ipu_image test_in, test_out; enum v4l2_field field; @@ -240,8 +243,8 @@ static int ipu_csc_scaler_try_fmt(struct file *file, void *priv, static int ipu_csc_scaler_s_fmt(struct file *file, void *priv, struct v4l2_format *f) { + struct ipu_csc_scaler_ctx *ctx = file_to_ctx(file); struct ipu_csc_scaler_q_data *q_data; - struct ipu_csc_scaler_ctx *ctx = fh_to_ctx(priv); struct vb2_queue *vq; int ret; @@ -296,7 +299,7 @@ static int ipu_csc_scaler_s_fmt(struct file *file, void *priv, static int ipu_csc_scaler_g_selection(struct file *file, void *priv, struct v4l2_selection *s) { - struct ipu_csc_scaler_ctx *ctx = fh_to_ctx(priv); + struct ipu_csc_scaler_ctx *ctx = file_to_ctx(file); struct ipu_csc_scaler_q_data *q_data; switch (s->target) { @@ -334,7 +337,7 @@ static int ipu_csc_scaler_g_selection(struct file *file, void *priv, static int ipu_csc_scaler_s_selection(struct file *file, void *priv, struct v4l2_selection *s) { - struct ipu_csc_scaler_ctx *ctx = fh_to_ctx(priv); + struct ipu_csc_scaler_ctx *ctx = file_to_ctx(file); struct ipu_csc_scaler_q_data *q_data; switch (s->target) { @@ -760,8 +763,7 @@ static int ipu_csc_scaler_open(struct file *file) ctx->rot_mode = IPU_ROTATE_NONE; v4l2_fh_init(&ctx->fh, video_devdata(file)); - file->private_data = &ctx->fh; - v4l2_fh_add(&ctx->fh); + v4l2_fh_add(&ctx->fh, file); ctx->priv = priv; ctx->fh.m2m_ctx = v4l2_m2m_ctx_init(priv->m2m_dev, ctx, @@ -788,7 +790,7 @@ static int ipu_csc_scaler_open(struct file *file) err_ctrls: v4l2_m2m_ctx_release(ctx->fh.m2m_ctx); err_ctx: - v4l2_fh_del(&ctx->fh); + v4l2_fh_del(&ctx->fh, file); v4l2_fh_exit(&ctx->fh); kfree(ctx); return ret; @@ -797,13 +799,13 @@ err_ctx: static int ipu_csc_scaler_release(struct file *file) { struct ipu_csc_scaler_priv *priv = video_drvdata(file); - struct ipu_csc_scaler_ctx *ctx = fh_to_ctx(file->private_data); + struct ipu_csc_scaler_ctx *ctx = file_to_ctx(file); dev_dbg(priv->dev, "Releasing instance %p\n", ctx); v4l2_ctrl_handler_free(&ctx->ctrl_hdlr); v4l2_m2m_ctx_release(ctx->fh.m2m_ctx); - v4l2_fh_del(&ctx->fh); + v4l2_fh_del(&ctx->fh, file); v4l2_fh_exit(&ctx->fh); kfree(ctx); diff --git a/drivers/staging/media/imx/imx-media-csi.c b/drivers/staging/media/imx/imx-media-csi.c index a7cd3ef95fc3..fd7e37d803e7 100644 --- a/drivers/staging/media/imx/imx-media-csi.c +++ b/drivers/staging/media/imx/imx-media-csi.c @@ -1751,12 +1751,6 @@ static int csi_subscribe_event(struct v4l2_subdev *sd, struct v4l2_fh *fh, return v4l2_event_subscribe(fh, sub, 0, NULL); } -static int csi_unsubscribe_event(struct v4l2_subdev *sd, struct v4l2_fh *fh, - struct v4l2_event_subscription *sub) -{ - return v4l2_event_unsubscribe(fh, sub); -} - static int csi_registered(struct v4l2_subdev *sd) { struct csi_priv *priv = v4l2_get_subdevdata(sd); @@ -1872,7 +1866,7 @@ static const struct media_entity_operations csi_entity_ops = { static const struct v4l2_subdev_core_ops csi_core_ops = { .subscribe_event = csi_subscribe_event, - .unsubscribe_event = csi_unsubscribe_event, + .unsubscribe_event = v4l2_event_subdev_unsubscribe, }; static const struct v4l2_subdev_video_ops csi_video_ops = { diff --git a/drivers/staging/media/ipu3/ipu3-css.c b/drivers/staging/media/ipu3/ipu3-css.c index 1b0a59b78949..777cac1c27bf 100644 --- a/drivers/staging/media/ipu3/ipu3-css.c +++ b/drivers/staging/media/ipu3/ipu3-css.c @@ -4,6 +4,7 @@ #include <linux/device.h> #include <linux/iopoll.h> #include <linux/slab.h> +#include <linux/string_choices.h> #include "ipu3.h" #include "ipu3-css.h" @@ -226,7 +227,7 @@ int imgu_css_set_powerup(struct device *dev, void __iomem *base, state = readl(base + IMGU_REG_STATE); dev_dbg(dev, "CSS pm_ctrl 0x%x state 0x%x (power %s)\n", - pm_ctrl, state, state & IMGU_STATE_POWER_DOWN ? "down" : "up"); + pm_ctrl, state, str_down_up(state & IMGU_STATE_POWER_DOWN)); /* Power up CSS using wrapper */ if (state & IMGU_STATE_POWER_DOWN) { diff --git a/drivers/staging/media/ipu3/ipu3-v4l2.c b/drivers/staging/media/ipu3/ipu3-v4l2.c index ad6095bf717d..2f6041d342f4 100644 --- a/drivers/staging/media/ipu3/ipu3-v4l2.c +++ b/drivers/staging/media/ipu3/ipu3-v4l2.c @@ -3,6 +3,7 @@ #include <linux/module.h> #include <linux/pm_runtime.h> +#include <linux/string_choices.h> #include <media/v4l2-event.h> #include <media/v4l2-ioctl.h> @@ -287,7 +288,7 @@ static int imgu_link_setup(struct media_entity *entity, WARN_ON(pad >= IMGU_NODE_NUM); dev_dbg(&imgu->pci_dev->dev, "pipe %u pad %u is %s", pipe, pad, - flags & MEDIA_LNK_FL_ENABLED ? "enabled" : "disabled"); + str_enabled_disabled(flags & MEDIA_LNK_FL_ENABLED)); imgu_pipe = &imgu->imgu_pipe[pipe]; imgu_pipe->nodes[pad].enabled = flags & MEDIA_LNK_FL_ENABLED; @@ -302,7 +303,7 @@ static int imgu_link_setup(struct media_entity *entity, __clear_bit(pipe, imgu->css.enabled_pipes); dev_dbg(&imgu->pci_dev->dev, "pipe %u is %s", pipe, - flags & MEDIA_LNK_FL_ENABLED ? "enabled" : "disabled"); + str_enabled_disabled(flags & MEDIA_LNK_FL_ENABLED)); return 0; } diff --git a/drivers/staging/media/ipu7/ipu7-isys-csi2.c b/drivers/staging/media/ipu7/ipu7-isys-csi2.c index 9c16ae9a0e5b..4023db4a6466 100644 --- a/drivers/staging/media/ipu7/ipu7-isys-csi2.c +++ b/drivers/staging/media/ipu7/ipu7-isys-csi2.c @@ -77,7 +77,7 @@ static int csi2_subscribe_event(struct v4l2_subdev *sd, struct v4l2_fh *fh, case V4L2_EVENT_FRAME_SYNC: return v4l2_event_subscribe(fh, sub, 10, NULL); case V4L2_EVENT_CTRL: - return v4l2_ctrl_subscribe_event(fh, sub); + return v4l2_ctrl_subdev_subscribe_event(sd, fh, sub); default: return -EINVAL; } diff --git a/drivers/staging/media/ipu7/ipu7-isys-queue.c b/drivers/staging/media/ipu7/ipu7-isys-queue.c index 7046c29141f8..434d9d9c7158 100644 --- a/drivers/staging/media/ipu7/ipu7-isys-queue.c +++ b/drivers/staging/media/ipu7/ipu7-isys-queue.c @@ -442,14 +442,13 @@ static int ipu7_isys_link_fmt_validate(struct ipu7_isys_queue *aq) media_pad_remote_pad_first(av->vdev.entity.pads); struct v4l2_mbus_framefmt format; struct v4l2_subdev *sd; - u32 r_stream, code; + u32 r_stream = 0, code; int ret; if (!remote_pad) return -ENOTCONN; sd = media_entity_to_v4l2_subdev(remote_pad->entity); - r_stream = ipu7_isys_get_src_stream_by_src_pad(sd, remote_pad->index); ret = ipu7_isys_get_stream_pad_fmt(sd, remote_pad->index, r_stream, &format); diff --git a/drivers/staging/media/ipu7/ipu7-isys-subdev.c b/drivers/staging/media/ipu7/ipu7-isys-subdev.c index 98b6ef6a2f21..67a776033d5b 100644 --- a/drivers/staging/media/ipu7/ipu7-isys-subdev.c +++ b/drivers/staging/media/ipu7/ipu7-isys-subdev.c @@ -194,13 +194,22 @@ static int subdev_set_routing(struct v4l2_subdev *sd, .code = MEDIA_BUS_FMT_SGRBG10_1X10, .field = V4L2_FIELD_NONE, }; + struct v4l2_subdev_route *route; int ret; ret = v4l2_subdev_routing_validate(sd, routing, - V4L2_SUBDEV_ROUTING_ONLY_1_TO_1); + V4L2_SUBDEV_ROUTING_ONLY_1_TO_1 | + V4L2_SUBDEV_ROUTING_NO_SOURCE_MULTIPLEXING); if (ret) return ret; + /* + * The device doesn't support source multiplexing, set all source + * streams to 0 to simplify stream handling through the driver. + */ + for_each_active_route(routing, route) + route->source_stream = 0; + return v4l2_subdev_set_routing_with_fmt(sd, state, routing, &fmt); } @@ -222,30 +231,6 @@ int ipu7_isys_get_stream_pad_fmt(struct v4l2_subdev *sd, u32 pad, u32 stream, return fmt ? 0 : -EINVAL; } -u32 ipu7_isys_get_src_stream_by_src_pad(struct v4l2_subdev *sd, u32 pad) -{ - struct v4l2_subdev_state *state; - struct v4l2_subdev_route *routes; - u32 source_stream = 0; - unsigned int i; - - state = v4l2_subdev_lock_and_get_active_state(sd); - if (!state) - return 0; - - routes = state->routing.routes; - for (i = 0; i < state->routing.num_routes; i++) { - if (routes[i].source_pad == pad) { - source_stream = routes[i].source_stream; - break; - } - } - - v4l2_subdev_unlock_state(state); - - return source_stream; -} - static int ipu7_isys_subdev_init_state(struct v4l2_subdev *sd, struct v4l2_subdev_state *state) { diff --git a/drivers/staging/media/ipu7/ipu7-isys-subdev.h b/drivers/staging/media/ipu7/ipu7-isys-subdev.h index 1057ec39ae39..faa50031cf24 100644 --- a/drivers/staging/media/ipu7/ipu7-isys-subdev.h +++ b/drivers/staging/media/ipu7/ipu7-isys-subdev.h @@ -37,7 +37,6 @@ int ipu7_isys_subdev_enum_mbus_code(struct v4l2_subdev *sd, struct v4l2_subdev_state *state, struct v4l2_subdev_mbus_code_enum *code); -u32 ipu7_isys_get_src_stream_by_src_pad(struct v4l2_subdev *sd, u32 pad); int ipu7_isys_get_stream_pad_fmt(struct v4l2_subdev *sd, u32 pad, u32 stream, struct v4l2_mbus_framefmt *format); int ipu7_isys_subdev_set_routing(struct v4l2_subdev *sd, diff --git a/drivers/staging/media/ipu7/ipu7-isys-video.c b/drivers/staging/media/ipu7/ipu7-isys-video.c index 8756da3a8fb0..1a7c8a91fffb 100644 --- a/drivers/staging/media/ipu7/ipu7-isys-video.c +++ b/drivers/staging/media/ipu7/ipu7-isys-video.c @@ -291,7 +291,7 @@ static int link_validate(struct media_link *link) struct v4l2_mbus_framefmt *s_fmt; struct v4l2_subdev *s_sd; struct media_pad *s_pad; - u32 s_stream, code; + u32 s_stream = 0, code; int ret = -EPIPE; if (!link->source->entity) @@ -307,7 +307,6 @@ static int link_validate(struct media_link *link) link->sink->entity->name); s_pad = media_pad_remote_pad_first(&av->pad); - s_stream = ipu7_isys_get_src_stream_by_src_pad(s_sd, s_pad->index); v4l2_subdev_lock_state(s_state); @@ -370,10 +369,9 @@ static int ipu7_isys_fw_pin_cfg(struct ipu7_isys_video *av, struct device *dev = &isys->adev->auxdev.dev; struct v4l2_mbus_framefmt fmt; int output_pins; - u32 src_stream; + u32 src_stream = 0; int ret; - src_stream = ipu7_isys_get_src_stream_by_src_pad(sd, src_pad->index); ret = ipu7_isys_get_stream_pad_fmt(sd, src_pad->index, src_stream, &fmt); if (ret < 0) { @@ -781,32 +779,6 @@ ipu7_isys_query_stream_by_source(struct ipu7_isys *isys, int source, u8 vc) return stream; } -static u32 get_remote_pad_stream(struct media_pad *r_pad) -{ - struct v4l2_subdev_state *state; - struct v4l2_subdev *sd; - u32 stream_id = 0; - unsigned int i; - - sd = media_entity_to_v4l2_subdev(r_pad->entity); - state = v4l2_subdev_lock_and_get_active_state(sd); - if (!state) - return 0; - - for (i = 0; i < state->stream_configs.num_configs; i++) { - struct v4l2_subdev_stream_config *cfg = - &state->stream_configs.configs[i]; - if (cfg->pad == r_pad->index) { - stream_id = cfg->stream; - break; - } - } - - v4l2_subdev_unlock_state(state); - - return stream_id; -} - int ipu7_isys_video_set_streaming(struct ipu7_isys_video *av, int state, struct ipu7_isys_buffer_list *bl) { @@ -814,7 +786,7 @@ int ipu7_isys_video_set_streaming(struct ipu7_isys_video *av, int state, struct device *dev = &av->isys->adev->auxdev.dev; struct media_pad *r_pad; struct v4l2_subdev *sd; - u32 r_stream; + u32 r_stream = 0; int ret = 0; dev_dbg(dev, "set stream: %d\n", state); @@ -824,7 +796,6 @@ int ipu7_isys_video_set_streaming(struct ipu7_isys_video *av, int state, sd = &stream->asd->sd; r_pad = media_pad_remote_pad_first(&av->pad); - r_stream = get_remote_pad_stream(r_pad); if (!state) { stop_streaming_firmware(av); @@ -946,6 +917,7 @@ void ipu7_isys_fw_close(struct ipu7_isys *isys) ipu7_fw_isys_close(isys); mutex_unlock(&isys->mutex); + pm_runtime_put(&isys->adev->auxdev.dev); } int ipu7_isys_setup_video(struct ipu7_isys_video *av, @@ -1082,7 +1054,6 @@ int ipu7_isys_video_init(struct ipu7_isys_video *av) __ipu_isys_vidioc_try_fmt_vid_cap(av, &format); av->pix_fmt = format.fmt.pix; - set_bit(V4L2_FL_USES_V4L2_FH, &av->vdev.flags); video_set_drvdata(&av->vdev, av); ret = video_register_device(&av->vdev, VFL_TYPE_VIDEO, -1); diff --git a/drivers/staging/media/ipu7/ipu7.c b/drivers/staging/media/ipu7/ipu7.c index 1b4f01db13ca..5cddc09c72bf 100644 --- a/drivers/staging/media/ipu7/ipu7.c +++ b/drivers/staging/media/ipu7/ipu7.c @@ -21,7 +21,6 @@ #include <linux/slab.h> #include <linux/types.h> #include <linux/vmalloc.h> -#include <linux/version.h> #include <media/ipu-bridge.h> @@ -2248,20 +2247,13 @@ void ipu7_dump_fw_error_log(const struct ipu7_bus_device *adev) } EXPORT_SYMBOL_NS_GPL(ipu7_dump_fw_error_log, "INTEL_IPU7"); -static int ipu7_pci_config_setup(struct pci_dev *dev) +static void ipu7_pci_config_setup(struct pci_dev *dev) { u16 pci_command; - int ret; pci_read_config_word(dev, PCI_COMMAND, &pci_command); pci_command |= PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER; pci_write_config_word(dev, PCI_COMMAND, pci_command); - - ret = pci_enable_msi(dev); - if (ret) - dev_err(&dev->dev, "Failed to enable msi (%d)\n", ret); - - return ret; } static int ipu7_map_fw_code_region(struct ipu7_bus_device *sys, @@ -2435,7 +2427,6 @@ static int ipu7_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) if (!isp) return -ENOMEM; - dev_set_name(dev, "intel-ipu7"); isp->pdev = pdev; INIT_LIST_HEAD(&isp->devices); @@ -2510,13 +2501,15 @@ static int ipu7_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) dma_set_max_seg_size(dev, UINT_MAX); - ret = ipu7_pci_config_setup(pdev); - if (ret) - return ret; + ipu7_pci_config_setup(pdev); + + ret = pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_ALL_TYPES); + if (ret < 0) + return dev_err_probe(dev, ret, "Failed to alloc irq vector\n"); ret = ipu_buttress_init(isp); if (ret) - return ret; + goto pci_irq_free; dev_info(dev, "firmware cpd file: %s\n", isp->cpd_fw_name); @@ -2632,6 +2625,8 @@ out_ipu_bus_del_devices: release_firmware(isp->cpd_fw); buttress_exit: ipu_buttress_exit(isp); +pci_irq_free: + pci_free_irq_vectors(pdev); return ret; } @@ -2648,6 +2643,9 @@ static void ipu7_pci_remove(struct pci_dev *pdev) if (!IS_ERR_OR_NULL(isp->fw_code_region)) vfree(isp->fw_code_region); + ipu7_mmu_cleanup(isp->isys->mmu); + ipu7_mmu_cleanup(isp->psys->mmu); + ipu7_bus_del_devices(pdev); pm_runtime_forbid(&pdev->dev); @@ -2656,9 +2654,6 @@ static void ipu7_pci_remove(struct pci_dev *pdev) ipu_buttress_exit(isp); release_firmware(isp->cpd_fw); - - ipu7_mmu_cleanup(isp->psys->mmu); - ipu7_mmu_cleanup(isp->isys->mmu); } static void ipu7_pci_reset_prepare(struct pci_dev *pdev) diff --git a/drivers/staging/media/meson/vdec/vdec.c b/drivers/staging/media/meson/vdec/vdec.c index 6d34a482492e..49e497a32973 100644 --- a/drivers/staging/media/meson/vdec/vdec.c +++ b/drivers/staging/media/meson/vdec/vdec.c @@ -558,8 +558,7 @@ vdec_try_fmt_common(struct amvdec_session *sess, u32 size, static int vdec_try_fmt(struct file *file, void *fh, struct v4l2_format *f) { - struct amvdec_session *sess = - container_of(file->private_data, struct amvdec_session, fh); + struct amvdec_session *sess = file_to_amvdec_session(file); vdec_try_fmt_common(sess, sess->core->platform->num_formats, f); @@ -568,8 +567,7 @@ static int vdec_try_fmt(struct file *file, void *fh, struct v4l2_format *f) static int vdec_g_fmt(struct file *file, void *fh, struct v4l2_format *f) { - struct amvdec_session *sess = - container_of(file->private_data, struct amvdec_session, fh); + struct amvdec_session *sess = file_to_amvdec_session(file); struct v4l2_pix_format_mplane *pixmp = &f->fmt.pix_mp; if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) @@ -596,8 +594,7 @@ static int vdec_g_fmt(struct file *file, void *fh, struct v4l2_format *f) static int vdec_s_fmt(struct file *file, void *fh, struct v4l2_format *f) { - struct amvdec_session *sess = - container_of(file->private_data, struct amvdec_session, fh); + struct amvdec_session *sess = file_to_amvdec_session(file); struct v4l2_pix_format_mplane *pixmp = &f->fmt.pix_mp; u32 num_formats = sess->core->platform->num_formats; const struct amvdec_format *fmt_out; @@ -658,8 +655,7 @@ static int vdec_s_fmt(struct file *file, void *fh, struct v4l2_format *f) static int vdec_enum_fmt(struct file *file, void *fh, struct v4l2_fmtdesc *f) { - struct amvdec_session *sess = - container_of(file->private_data, struct amvdec_session, fh); + struct amvdec_session *sess = file_to_amvdec_session(file); const struct vdec_platform *platform = sess->core->platform; const struct amvdec_format *fmt_out; @@ -688,8 +684,7 @@ static int vdec_enum_fmt(struct file *file, void *fh, struct v4l2_fmtdesc *f) static int vdec_enum_framesizes(struct file *file, void *fh, struct v4l2_frmsizeenum *fsize) { - struct amvdec_session *sess = - container_of(file->private_data, struct amvdec_session, fh); + struct amvdec_session *sess = file_to_amvdec_session(file); const struct amvdec_format *formats = sess->core->platform->formats; const struct amvdec_format *fmt; u32 num_formats = sess->core->platform->num_formats; @@ -713,8 +708,7 @@ static int vdec_enum_framesizes(struct file *file, void *fh, static int vdec_decoder_cmd(struct file *file, void *fh, struct v4l2_decoder_cmd *cmd) { - struct amvdec_session *sess = - container_of(file->private_data, struct amvdec_session, fh); + struct amvdec_session *sess = file_to_amvdec_session(file); struct amvdec_codec_ops *codec_ops = sess->fmt_out->codec_ops; struct device *dev = sess->core->dev; int ret; @@ -773,8 +767,7 @@ static int vdec_subscribe_event(struct v4l2_fh *fh, static int vdec_g_pixelaspect(struct file *file, void *fh, int type, struct v4l2_fract *f) { - struct amvdec_session *sess = - container_of(file->private_data, struct amvdec_session, fh); + struct amvdec_session *sess = file_to_amvdec_session(file); if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) return -EINVAL; @@ -915,9 +908,8 @@ static int vdec_open(struct file *file) v4l2_fh_init(&sess->fh, core->vdev_dec); sess->fh.ctrl_handler = &sess->ctrl_handler; - v4l2_fh_add(&sess->fh); + v4l2_fh_add(&sess->fh, file); sess->fh.m2m_ctx = sess->m2m_ctx; - file->private_data = &sess->fh; return 0; @@ -930,12 +922,11 @@ err_free_sess: static int vdec_close(struct file *file) { - struct amvdec_session *sess = - container_of(file->private_data, struct amvdec_session, fh); + struct amvdec_session *sess = file_to_amvdec_session(file); v4l2_m2m_ctx_release(sess->m2m_ctx); v4l2_m2m_release(sess->m2m_dev); - v4l2_fh_del(&sess->fh); + v4l2_fh_del(&sess->fh, file); v4l2_fh_exit(&sess->fh); mutex_destroy(&sess->lock); diff --git a/drivers/staging/media/meson/vdec/vdec.h b/drivers/staging/media/meson/vdec/vdec.h index 258685177700..7a5d8e871d70 100644 --- a/drivers/staging/media/meson/vdec/vdec.h +++ b/drivers/staging/media/meson/vdec/vdec.h @@ -282,6 +282,11 @@ struct amvdec_session { void *priv; }; +static inline struct amvdec_session *file_to_amvdec_session(struct file *filp) +{ + return container_of(file_to_v4l2_fh(filp), struct amvdec_session, fh); +} + u32 amvdec_get_output_size(struct amvdec_session *sess); #endif diff --git a/drivers/staging/media/sunxi/cedrus/cedrus.c b/drivers/staging/media/sunxi/cedrus/cedrus.c index 52a9588462ce..bff42ea1871f 100644 --- a/drivers/staging/media/sunxi/cedrus/cedrus.c +++ b/drivers/staging/media/sunxi/cedrus/cedrus.c @@ -366,7 +366,6 @@ static int cedrus_open(struct file *file) } v4l2_fh_init(&ctx->fh, video_devdata(file)); - file->private_data = &ctx->fh; ctx->dev = dev; ctx->bit_depth = 8; @@ -383,7 +382,7 @@ static int cedrus_open(struct file *file) if (ret) goto err_m2m_release; - v4l2_fh_add(&ctx->fh); + v4l2_fh_add(&ctx->fh, file); mutex_unlock(&dev->dev_mutex); @@ -401,12 +400,11 @@ err_free: static int cedrus_release(struct file *file) { struct cedrus_dev *dev = video_drvdata(file); - struct cedrus_ctx *ctx = container_of(file->private_data, - struct cedrus_ctx, fh); + struct cedrus_ctx *ctx = cedrus_file2ctx(file); mutex_lock(&dev->dev_mutex); - v4l2_fh_del(&ctx->fh); + v4l2_fh_del(&ctx->fh, file); v4l2_m2m_ctx_release(ctx->fh.m2m_ctx); v4l2_ctrl_handler_free(&ctx->hdl); diff --git a/drivers/staging/media/sunxi/cedrus/cedrus.h b/drivers/staging/media/sunxi/cedrus/cedrus.h index 522c184e2afc..c4b1217c14b6 100644 --- a/drivers/staging/media/sunxi/cedrus/cedrus.h +++ b/drivers/staging/media/sunxi/cedrus/cedrus.h @@ -155,6 +155,11 @@ struct cedrus_ctx { } codec; }; +static inline struct cedrus_ctx *cedrus_file2ctx(struct file *file) +{ + return container_of(file_to_v4l2_fh(file), struct cedrus_ctx, fh); +} + struct cedrus_dec_ops { void (*irq_clear)(struct cedrus_ctx *ctx); void (*irq_disable)(struct cedrus_ctx *ctx); diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_video.c b/drivers/staging/media/sunxi/cedrus/cedrus_video.c index 9fae2c7493d0..ad4ec3490775 100644 --- a/drivers/staging/media/sunxi/cedrus/cedrus_video.c +++ b/drivers/staging/media/sunxi/cedrus/cedrus_video.c @@ -83,11 +83,6 @@ static struct cedrus_format cedrus_formats[] = { #define CEDRUS_FORMATS_COUNT ARRAY_SIZE(cedrus_formats) -static inline struct cedrus_ctx *cedrus_file2ctx(struct file *file) -{ - return container_of(file->private_data, struct cedrus_ctx, fh); -} - static struct cedrus_format *cedrus_find_format(struct cedrus_ctx *ctx, u32 pixelformat, u32 directions) { diff --git a/drivers/staging/media/sunxi/sun6i-isp/sun6i_isp_capture.c b/drivers/staging/media/sunxi/sun6i-isp/sun6i_isp_capture.c index 24899f41dc1c..e7b99cee63d6 100644 --- a/drivers/staging/media/sunxi/sun6i-isp/sun6i_isp_capture.c +++ b/drivers/staging/media/sunxi/sun6i-isp/sun6i_isp_capture.c @@ -419,7 +419,7 @@ static void sun6i_isp_capture_format_prepare(struct v4l2_format *format) pix_format->xfer_func = V4L2_XFER_FUNC_DEFAULT; } -static int sun6i_isp_capture_querycap(struct file *file, void *private, +static int sun6i_isp_capture_querycap(struct file *file, void *priv, struct v4l2_capability *capability) { struct sun6i_isp_device *isp_dev = video_drvdata(file); @@ -433,7 +433,7 @@ static int sun6i_isp_capture_querycap(struct file *file, void *private, return 0; } -static int sun6i_isp_capture_enum_fmt(struct file *file, void *private, +static int sun6i_isp_capture_enum_fmt(struct file *file, void *priv, struct v4l2_fmtdesc *fmtdesc) { u32 index = fmtdesc->index; @@ -446,7 +446,7 @@ static int sun6i_isp_capture_enum_fmt(struct file *file, void *private, return 0; } -static int sun6i_isp_capture_g_fmt(struct file *file, void *private, +static int sun6i_isp_capture_g_fmt(struct file *file, void *priv, struct v4l2_format *format) { struct sun6i_isp_device *isp_dev = video_drvdata(file); @@ -456,7 +456,7 @@ static int sun6i_isp_capture_g_fmt(struct file *file, void *private, return 0; } -static int sun6i_isp_capture_s_fmt(struct file *file, void *private, +static int sun6i_isp_capture_s_fmt(struct file *file, void *priv, struct v4l2_format *format) { struct sun6i_isp_device *isp_dev = video_drvdata(file); @@ -471,7 +471,7 @@ static int sun6i_isp_capture_s_fmt(struct file *file, void *private, return 0; } -static int sun6i_isp_capture_try_fmt(struct file *file, void *private, +static int sun6i_isp_capture_try_fmt(struct file *file, void *priv, struct v4l2_format *format) { sun6i_isp_capture_format_prepare(format); @@ -479,7 +479,7 @@ static int sun6i_isp_capture_try_fmt(struct file *file, void *private, return 0; } -static int sun6i_isp_capture_enum_input(struct file *file, void *private, +static int sun6i_isp_capture_enum_input(struct file *file, void *priv, struct v4l2_input *input) { if (input->index != 0) @@ -491,7 +491,7 @@ static int sun6i_isp_capture_enum_input(struct file *file, void *private, return 0; } -static int sun6i_isp_capture_g_input(struct file *file, void *private, +static int sun6i_isp_capture_g_input(struct file *file, void *priv, unsigned int *index) { *index = 0; @@ -499,7 +499,7 @@ static int sun6i_isp_capture_g_input(struct file *file, void *private, return 0; } -static int sun6i_isp_capture_s_input(struct file *file, void *private, +static int sun6i_isp_capture_s_input(struct file *file, void *priv, unsigned int index) { if (index != 0) diff --git a/drivers/staging/media/sunxi/sun6i-isp/sun6i_isp_params.c b/drivers/staging/media/sunxi/sun6i-isp/sun6i_isp_params.c index 3d95ed0b023e..77c2d06c0436 100644 --- a/drivers/staging/media/sunxi/sun6i-isp/sun6i_isp_params.c +++ b/drivers/staging/media/sunxi/sun6i-isp/sun6i_isp_params.c @@ -383,7 +383,7 @@ static const struct vb2_ops sun6i_isp_params_queue_ops = { /* Video Device */ -static int sun6i_isp_params_querycap(struct file *file, void *private, +static int sun6i_isp_params_querycap(struct file *file, void *priv, struct v4l2_capability *capability) { struct sun6i_isp_device *isp_dev = video_drvdata(file); @@ -397,7 +397,7 @@ static int sun6i_isp_params_querycap(struct file *file, void *private, return 0; } -static int sun6i_isp_params_enum_fmt(struct file *file, void *private, +static int sun6i_isp_params_enum_fmt(struct file *file, void *priv, struct v4l2_fmtdesc *fmtdesc) { struct sun6i_isp_device *isp_dev = video_drvdata(file); @@ -412,7 +412,7 @@ static int sun6i_isp_params_enum_fmt(struct file *file, void *private, return 0; } -static int sun6i_isp_params_g_fmt(struct file *file, void *private, +static int sun6i_isp_params_g_fmt(struct file *file, void *priv, struct v4l2_format *format) { struct sun6i_isp_device *isp_dev = video_drvdata(file); diff --git a/drivers/staging/media/tegra-video/tegra20.c b/drivers/staging/media/tegra-video/tegra20.c index 7b8f8f810b35..1473f1b1f203 100644 --- a/drivers/staging/media/tegra-video/tegra20.c +++ b/drivers/staging/media/tegra-video/tegra20.c @@ -42,7 +42,7 @@ #define VI_INPUT_BT656 BIT(25) #define VI_INPUT_YUV_INPUT_FORMAT_SFT 8 /* bits [9:8] */ #define VI_INPUT_YUV_INPUT_FORMAT_UYVY (0 << VI_INPUT_YUV_INPUT_FORMAT_SFT) -#define VI_INPUT_YUV_INPUT_FORMAT_VYUY (1 << VI_INPUT_YUV_INPUT_FORMAT_SFT) +#define VI_INPUT_YUV_INPUT_FORMAT_VYUY BIT(VI_INPUT_YUV_INPUT_FORMAT_SFT) #define VI_INPUT_YUV_INPUT_FORMAT_YUYV (2 << VI_INPUT_YUV_INPUT_FORMAT_SFT) #define VI_INPUT_YUV_INPUT_FORMAT_YVYU (3 << VI_INPUT_YUV_INPUT_FORMAT_SFT) #define VI_INPUT_INPUT_FORMAT_SFT 2 /* bits [5:2] */ @@ -73,7 +73,7 @@ #define VI_OUTPUT_H_DIRECTION BIT(19) #define VI_OUTPUT_YUV_OUTPUT_FORMAT_SFT 17 #define VI_OUTPUT_YUV_OUTPUT_FORMAT_UYVY (0 << VI_OUTPUT_YUV_OUTPUT_FORMAT_SFT) -#define VI_OUTPUT_YUV_OUTPUT_FORMAT_VYUY (1 << VI_OUTPUT_YUV_OUTPUT_FORMAT_SFT) +#define VI_OUTPUT_YUV_OUTPUT_FORMAT_VYUY BIT(VI_OUTPUT_YUV_OUTPUT_FORMAT_SFT) #define VI_OUTPUT_YUV_OUTPUT_FORMAT_YUYV (2 << VI_OUTPUT_YUV_OUTPUT_FORMAT_SFT) #define VI_OUTPUT_YUV_OUTPUT_FORMAT_YVYU (3 << VI_OUTPUT_YUV_OUTPUT_FORMAT_SFT) #define VI_OUTPUT_OUTPUT_BYTE_SWAP BIT(16) diff --git a/drivers/staging/most/video/video.c b/drivers/staging/most/video/video.c index 2b3cdb1ce140..32f71d9a9cf7 100644 --- a/drivers/staging/most/video/video.c +++ b/drivers/staging/most/video/video.c @@ -52,6 +52,11 @@ struct comp_fh { u32 offs; }; +static inline struct comp_fh *to_comp_fh(struct file *filp) +{ + return container_of(file_to_v4l2_fh(filp), struct comp_fh, fh); +} + static LIST_HEAD(video_devices); static DEFINE_SPINLOCK(list_lock); @@ -91,9 +96,7 @@ static int comp_vdev_open(struct file *filp) fh->mdev = mdev; v4l2_fh_init(&fh->fh, vdev); - filp->private_data = fh; - - v4l2_fh_add(&fh->fh); + v4l2_fh_add(&fh->fh, filp); ret = most_start_channel(mdev->iface, mdev->ch_idx, &comp); if (ret) { @@ -104,7 +107,7 @@ static int comp_vdev_open(struct file *filp) return 0; err_rm: - v4l2_fh_del(&fh->fh); + v4l2_fh_del(&fh->fh, filp); v4l2_fh_exit(&fh->fh); err_dec: @@ -115,7 +118,7 @@ err_dec: static int comp_vdev_close(struct file *filp) { - struct comp_fh *fh = filp->private_data; + struct comp_fh *fh = to_comp_fh(filp); struct most_video_dev *mdev = fh->mdev; struct mbo *mbo, *tmp; @@ -140,7 +143,7 @@ static int comp_vdev_close(struct file *filp) most_stop_channel(mdev->iface, mdev->ch_idx, &comp); mdev->mute = false; - v4l2_fh_del(&fh->fh); + v4l2_fh_del(&fh->fh, filp); v4l2_fh_exit(&fh->fh); atomic_dec(&mdev->access_ref); @@ -151,7 +154,7 @@ static int comp_vdev_close(struct file *filp) static ssize_t comp_vdev_read(struct file *filp, char __user *buf, size_t count, loff_t *pos) { - struct comp_fh *fh = filp->private_data; + struct comp_fh *fh = to_comp_fh(filp); struct most_video_dev *mdev = fh->mdev; int ret = 0; @@ -200,7 +203,7 @@ static ssize_t comp_vdev_read(struct file *filp, char __user *buf, static __poll_t comp_vdev_poll(struct file *filp, poll_table *wait) { - struct comp_fh *fh = filp->private_data; + struct comp_fh *fh = to_comp_fh(filp); struct most_video_dev *mdev = fh->mdev; __poll_t mask = 0; diff --git a/drivers/usb/gadget/function/uvc.h b/drivers/usb/gadget/function/uvc.h index 6f44dd732315..9e79cbe50715 100644 --- a/drivers/usb/gadget/function/uvc.h +++ b/drivers/usb/gadget/function/uvc.h @@ -196,6 +196,11 @@ struct uvc_file_handle { #define to_uvc_file_handle(handle) \ container_of(handle, struct uvc_file_handle, vfh) +static inline struct uvc_file_handle *file_to_uvc_file_handle(struct file *filp) +{ + return container_of(file_to_v4l2_fh(filp), struct uvc_file_handle, vfh); +} + /* ------------------------------------------------------------------------ * Functions */ diff --git a/drivers/usb/gadget/function/uvc_v4l2.c b/drivers/usb/gadget/function/uvc_v4l2.c index fc9a8d31a1e9..fd4b998ccd16 100644 --- a/drivers/usb/gadget/function/uvc_v4l2.c +++ b/drivers/usb/gadget/function/uvc_v4l2.c @@ -672,10 +672,9 @@ uvc_v4l2_open(struct file *file) return -ENOMEM; v4l2_fh_init(&handle->vfh, vdev); - v4l2_fh_add(&handle->vfh); + v4l2_fh_add(&handle->vfh, file); handle->device = &uvc->video; - file->private_data = &handle->vfh; return 0; } @@ -685,7 +684,7 @@ uvc_v4l2_release(struct file *file) { struct video_device *vdev = video_devdata(file); struct uvc_device *uvc = video_get_drvdata(vdev); - struct uvc_file_handle *handle = to_uvc_file_handle(file->private_data); + struct uvc_file_handle *handle = file_to_uvc_file_handle(file); struct uvc_video *video = handle->device; mutex_lock(&video->mutex); @@ -693,8 +692,7 @@ uvc_v4l2_release(struct file *file) uvc_v4l2_disable(uvc); mutex_unlock(&video->mutex); - file->private_data = NULL; - v4l2_fh_del(&handle->vfh); + v4l2_fh_del(&handle->vfh, file); v4l2_fh_exit(&handle->vfh); kfree(handle); diff --git a/include/dt-bindings/media/tvp5150.h b/include/dt-bindings/media/tvp5150.h index dda00c038530..ba34c420c303 100644 --- a/include/dt-bindings/media/tvp5150.h +++ b/include/dt-bindings/media/tvp5150.h @@ -2,7 +2,7 @@ /* tvp5150.h - definition for tvp5150 inputs - Copyright (C) 2006 Hans Verkuil (hverkuil@xs4all.nl) + Copyright (C) 2006 Hans Verkuil (hverkuil@kernel.org) */ diff --git a/include/linux/usb/uvc.h b/include/linux/usb/uvc.h index ee19e9f915b8..22e0dab0809e 100644 --- a/include/linux/usb/uvc.h +++ b/include/linux/usb/uvc.h @@ -29,10 +29,32 @@ #define UVC_GUID_EXT_GPIO_CONTROLLER \ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x03} +#define UVC_GUID_CHROMEOS_XU \ + {0x24, 0xe9, 0xd7, 0x74, 0xc9, 0x49, 0x45, 0x4a, \ + 0x98, 0xa3, 0xc8, 0x07, 0x7e, 0x05, 0x1c, 0xa3} #define UVC_GUID_MSXU_1_5 \ {0xdc, 0x95, 0x3f, 0x0f, 0x32, 0x26, 0x4e, 0x4c, \ 0x92, 0xc9, 0xa0, 0x47, 0x82, 0xf4, 0x3b, 0xc8} +/* https://learn.microsoft.com/en-us/windows-hardware/drivers/stream/uvc-extensions-1-5#222-extension-unit-controls */ +#define UVC_MSXU_CONTROL_FOCUS 0x01 +#define UVC_MSXU_CONTROL_EXPOSURE 0x02 +#define UVC_MSXU_CONTROL_EVCOMPENSATION 0x03 +#define UVC_MSXU_CONTROL_WHITEBALANCE 0x04 +#define UVC_MSXU_CONTROL_FACE_AUTHENTICATION 0x06 +#define UVC_MSXU_CONTROL_CAMERA_EXTRINSICS 0x07 +#define UVC_MSXU_CONTROL_CAMERA_INTRINSICS 0x08 +#define UVC_MSXU_CONTROL_METADATA 0x09 +#define UVC_MSXU_CONTROL_IR_TORCH 0x0a +#define UVC_MSXU_CONTROL_DIGITALWINDOW 0x0b +#define UVC_MSXU_CONTROL_DIGITALWINDOW_CONFIG 0x0c +#define UVC_MSXU_CONTROL_VIDEO_HDR 0x0d +#define UVC_MSXU_CONTROL_FRAMERATE_THROTTLE 0x0e +#define UVC_MSXU_CONTROL_FIELDOFVIEW2_CONFIG 0x0f +#define UVC_MSXU_CONTROL_FIELDOFVIEW2 0x10 + +#define UVC_CROSXU_CONTROL_IQ_PROFILE 0x04 + #define UVC_GUID_FORMAT_MJPEG \ { 'M', 'J', 'P', 'G', 0x00, 0x00, 0x10, 0x00, \ 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71} diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h index 219037f4c08d..9609cf365e8e 100644 --- a/include/linux/videodev2.h +++ b/include/linux/videodev2.h @@ -50,7 +50,7 @@ * * Author: Bill Dirks <bill@thedirks.org> * Justin Schoeman - * Hans Verkuil <hverkuil@xs4all.nl> + * Hans Verkuil <hverkuil@kernel.org> * et al. */ #ifndef __LINUX_VIDEODEV2_H diff --git a/include/media/cadence/cdns-csi2rx.h b/include/media/cadence/cdns-csi2rx.h new file mode 100644 index 000000000000..782d03fc36d1 --- /dev/null +++ b/include/media/cadence/cdns-csi2rx.h @@ -0,0 +1,19 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +#ifndef _CDNS_CSI2RX_H +#define _CDNS_CSI2RX_H + +#include <media/v4l2-subdev.h> + +/** + * cdns_csi2rx_negotiate_ppc - Negotiate pixel-per-clock on output interface + * + * @subdev: point to &struct v4l2_subdev + * @pad: pad number of the source pad + * @ppc: pointer to requested pixel-per-clock value + * + * Returns 0 on success, negative error code otherwise. + */ +int cdns_csi2rx_negotiate_ppc(struct v4l2_subdev *subdev, unsigned int pad, + u8 *ppc); + +#endif diff --git a/include/media/drv-intf/cx25840.h b/include/media/drv-intf/cx25840.h index ba69bc525382..8b455d9dd5ca 100644 --- a/include/media/drv-intf/cx25840.h +++ b/include/media/drv-intf/cx25840.h @@ -3,7 +3,7 @@ /* * cx25840.h - definition for cx25840/1/2/3 inputs * - * Copyright (C) 2006 Hans Verkuil (hverkuil@xs4all.nl) + * Copyright (C) 2006 Hans Verkuil (hverkuil@kernel.org) */ #ifndef _CX25840_H_ diff --git a/include/media/drv-intf/msp3400.h b/include/media/drv-intf/msp3400.h index d6dfae104a6f..853258ee6bbd 100644 --- a/include/media/drv-intf/msp3400.h +++ b/include/media/drv-intf/msp3400.h @@ -2,7 +2,7 @@ /* msp3400.h - definition for msp3400 inputs and outputs - Copyright (C) 2006 Hans Verkuil (hverkuil@xs4all.nl) + Copyright (C) 2006 Hans Verkuil (hverkuil@kernel.org) */ diff --git a/include/media/i2c/bt819.h b/include/media/i2c/bt819.h index 70aa46bd5182..2277a7eb9548 100644 --- a/include/media/i2c/bt819.h +++ b/include/media/i2c/bt819.h @@ -2,7 +2,7 @@ /* bt819.h - bt819 notifications - Copyright (C) 2009 Hans Verkuil (hverkuil@xs4all.nl) + Copyright (C) 2009 Hans Verkuil (hverkuil@kernel.org) */ diff --git a/include/media/i2c/cs5345.h b/include/media/i2c/cs5345.h index d41e4dca3fcc..39e1cf6c1a2f 100644 --- a/include/media/i2c/cs5345.h +++ b/include/media/i2c/cs5345.h @@ -2,7 +2,7 @@ /* cs5345.h - definition for cs5345 inputs and outputs - Copyright (C) 2007 Hans Verkuil (hverkuil@xs4all.nl) + Copyright (C) 2007 Hans Verkuil (hverkuil@kernel.org) */ diff --git a/include/media/i2c/cs53l32a.h b/include/media/i2c/cs53l32a.h index 52ceb2f916d3..777f667855cb 100644 --- a/include/media/i2c/cs53l32a.h +++ b/include/media/i2c/cs53l32a.h @@ -2,7 +2,7 @@ /* cs53l32a.h - definition for cs53l32a inputs and outputs - Copyright (C) 2006 Hans Verkuil (hverkuil@xs4all.nl) + Copyright (C) 2006 Hans Verkuil (hverkuil@kernel.org) */ diff --git a/include/media/i2c/m52790.h b/include/media/i2c/m52790.h index 3f214fa9bc64..cedaaf215273 100644 --- a/include/media/i2c/m52790.h +++ b/include/media/i2c/m52790.h @@ -2,7 +2,7 @@ /* m52790.h - definition for m52790 inputs and outputs - Copyright (C) 2007 Hans Verkuil (hverkuil@xs4all.nl) + Copyright (C) 2007 Hans Verkuil (hverkuil@kernel.org) */ diff --git a/include/media/i2c/mt9v011.h b/include/media/i2c/mt9v011.h index 41c00b3e7184..552839756e64 100644 --- a/include/media/i2c/mt9v011.h +++ b/include/media/i2c/mt9v011.h @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* mt9v011 sensor * - * Copyright (C) 2011 Hans Verkuil <hverkuil@xs4all.nl> + * Copyright (C) 2011 Hans Verkuil <hverkuil@kernel.org> */ #ifndef __MT9V011_H__ diff --git a/include/media/i2c/mt9v022.h b/include/media/i2c/mt9v022.h deleted file mode 100644 index 6966eb538165..000000000000 --- a/include/media/i2c/mt9v022.h +++ /dev/null @@ -1,13 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * mt9v022 sensor - */ - -#ifndef __MT9V022_H__ -#define __MT9V022_H__ - -struct mt9v022_platform_data { - unsigned short y_skip_top; /* Lines to skip at the top */ -}; - -#endif diff --git a/include/media/i2c/mt9v032.h b/include/media/i2c/mt9v032.h deleted file mode 100644 index 83a37ccfb649..000000000000 --- a/include/media/i2c/mt9v032.h +++ /dev/null @@ -1,12 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -#ifndef _MEDIA_MT9V032_H -#define _MEDIA_MT9V032_H - -struct mt9v032_platform_data { - unsigned int clk_pol:1; - - const s64 *link_freqs; - s64 link_def_freq; -}; - -#endif diff --git a/include/media/i2c/saa7115.h b/include/media/i2c/saa7115.h index 0cd6080d7cb1..a607c91ef5f3 100644 --- a/include/media/i2c/saa7115.h +++ b/include/media/i2c/saa7115.h @@ -2,7 +2,7 @@ /* saa7115.h - definition for saa7111/3/4/5 inputs and frequency flags - Copyright (C) 2006 Hans Verkuil (hverkuil@xs4all.nl) + Copyright (C) 2006 Hans Verkuil (hverkuil@kernel.org) */ diff --git a/include/media/i2c/saa7127.h b/include/media/i2c/saa7127.h index 53ee999e6090..c81ee1743df1 100644 --- a/include/media/i2c/saa7127.h +++ b/include/media/i2c/saa7127.h @@ -2,7 +2,7 @@ /* saa7127.h - definition for saa7126/7/8/9 inputs/outputs - Copyright (C) 2006 Hans Verkuil (hverkuil@xs4all.nl) + Copyright (C) 2006 Hans Verkuil (hverkuil@kernel.org) */ diff --git a/include/media/i2c/ths7303.h b/include/media/i2c/ths7303.h index fc937025cdb4..7eda467b6725 100644 --- a/include/media/i2c/ths7303.h +++ b/include/media/i2c/ths7303.h @@ -5,7 +5,7 @@ * Copyright 2013 Cisco Systems, Inc. and/or its affiliates. * * Contributors: - * Hans Verkuil <hansverk@cisco.com> + * Hans Verkuil <hverkuil@kernel.org> * Lad, Prabhakar <prabhakar.lad@ti.com> * Martin Bugge <marbugge@cisco.com> */ diff --git a/include/media/i2c/tvaudio.h b/include/media/i2c/tvaudio.h index 42cd3206fb6c..206f42ed4e69 100644 --- a/include/media/i2c/tvaudio.h +++ b/include/media/i2c/tvaudio.h @@ -2,7 +2,7 @@ /* tvaudio.h - definition for tvaudio inputs - Copyright (C) 2006 Hans Verkuil (hverkuil@xs4all.nl) + Copyright (C) 2006 Hans Verkuil (hverkuil@kernel.org) */ diff --git a/include/media/i2c/upd64031a.h b/include/media/i2c/upd64031a.h index b6570abc84ef..d39b2b7f0cf3 100644 --- a/include/media/i2c/upd64031a.h +++ b/include/media/i2c/upd64031a.h @@ -2,7 +2,7 @@ /* * upd64031a - NEC Electronics Ghost Reduction input defines * - * 2006 by Hans Verkuil (hverkuil@xs4all.nl) + * 2006 by Hans Verkuil (hverkuil@kernel.org) */ #ifndef _UPD64031A_H_ diff --git a/include/media/i2c/upd64083.h b/include/media/i2c/upd64083.h index 17fb7b5201cc..72cf547c25fc 100644 --- a/include/media/i2c/upd64083.h +++ b/include/media/i2c/upd64083.h @@ -2,7 +2,7 @@ /* * upd6408x - NEC Electronics 3-Dimensional Y/C separation input defines * - * 2006 by Hans Verkuil (hverkuil@xs4all.nl) + * 2006 by Hans Verkuil (hverkuil@kernel.org) */ #ifndef _UPD64083_H_ diff --git a/include/media/i2c/wm8775.h b/include/media/i2c/wm8775.h index 6ccdeb3817ab..a02695ee3a58 100644 --- a/include/media/i2c/wm8775.h +++ b/include/media/i2c/wm8775.h @@ -2,7 +2,7 @@ /* wm8775.h - definition for wm8775 inputs and outputs - Copyright (C) 2006 Hans Verkuil (hverkuil@xs4all.nl) + Copyright (C) 2006 Hans Verkuil (hverkuil@kernel.org) */ diff --git a/include/media/media-request.h b/include/media/media-request.h index d4ac557678a7..bb500b2f9da4 100644 --- a/include/media/media-request.h +++ b/include/media/media-request.h @@ -5,7 +5,7 @@ * Copyright 2018 Cisco Systems, Inc. and/or its affiliates. All rights reserved. * Copyright (C) 2018 Intel Corporation * - * Author: Hans Verkuil <hansverk@cisco.com> + * Author: Hans Verkuil <hverkuil@kernel.org> * Author: Sakari Ailus <sakari.ailus@linux.intel.com> */ diff --git a/include/media/v4l2-common.h b/include/media/v4l2-common.h index 0a43f56578bc..5c0a7f6b5bb6 100644 --- a/include/media/v4l2-common.h +++ b/include/media/v4l2-common.h @@ -7,7 +7,7 @@ Each ioctl begins with VIDIOC_INT_ to clearly mark that it is an internal define, - Copyright (C) 2005 Hans Verkuil <hverkuil@xs4all.nl> + Copyright (C) 2005 Hans Verkuil <hverkuil@kernel.org> */ @@ -97,6 +97,7 @@ int v4l2_ctrl_query_fill(struct v4l2_queryctrl *qctrl, /* ------------------------------------------------------------------------- */ +struct clk; struct v4l2_device; struct v4l2_subdev; struct v4l2_subdev_ops; @@ -559,17 +560,18 @@ int v4l2_fill_pixfmt_mp(struct v4l2_pix_format_mplane *pixfmt, u32 pixelformat, /** * v4l2_get_link_freq - Get link rate from transmitter * - * @pad: The transmitter's media pad (or control handler for non-MC users or - * compatibility reasons, don't use in new code) + * @pad: The transmitter's media pad * @mul: The multiplier between pixel rate and link frequency. Bits per pixel on * D-PHY, samples per clock on parallel. 0 otherwise. * @div: The divisor between pixel rate and link frequency. Number of data lanes * times two on D-PHY, 1 on parallel. 0 otherwise. * - * This function is intended for obtaining the link frequency from the - * transmitter sub-devices. It returns the link rate, either from the - * V4L2_CID_LINK_FREQ control implemented by the transmitter, or value - * calculated based on the V4L2_CID_PIXEL_RATE implemented by the transmitter. + * This function obtains and returns the link frequency from the transmitter + * sub-device's pad. The link frequency is retrieved using the get_mbus_config + * sub-device pad operation. If this fails, the function falls back to obtaining + * the frequency either directly from the V4L2_CID_LINK_FREQ control if + * implemented by the transmitter, or by calculating it from the pixel rate + * obtained from the V4L2_CID_PIXEL_RATE control. * * Return: * * >0: Link frequency @@ -577,19 +579,9 @@ int v4l2_fill_pixfmt_mp(struct v4l2_pix_format_mplane *pixfmt, u32 pixelformat, * * %-EINVAL: Invalid link frequency value */ #ifdef CONFIG_MEDIA_CONTROLLER -#define v4l2_get_link_freq(pad, mul, div) \ - _Generic(pad, \ - struct media_pad *: __v4l2_get_link_freq_pad, \ - struct v4l2_ctrl_handler *: __v4l2_get_link_freq_ctrl) \ - (pad, mul, div) -s64 __v4l2_get_link_freq_pad(struct media_pad *pad, unsigned int mul, - unsigned int div); -#else -#define v4l2_get_link_freq(handler, mul, div) \ - __v4l2_get_link_freq_ctrl(handler, mul, div) +s64 v4l2_get_link_freq(const struct media_pad *pad, unsigned int mul, + unsigned int div); #endif -s64 __v4l2_get_link_freq_ctrl(struct v4l2_ctrl_handler *handler, - unsigned int mul, unsigned int div); void v4l2_simplify_fraction(u32 *numerator, u32 *denominator, unsigned int n_terms, unsigned int threshold); @@ -620,6 +612,79 @@ int v4l2_link_freq_to_bitmap(struct device *dev, const u64 *fw_link_freqs, unsigned int num_of_driver_link_freqs, unsigned long *bitmap); +struct clk *__devm_v4l2_sensor_clk_get(struct device *dev, const char *id, + bool legacy, bool fixed_rate, + unsigned long clk_rate); + +/** + * devm_v4l2_sensor_clk_get - lookup and obtain a reference to a clock producer + * for a camera sensor + * + * @dev: device for v4l2 sensor clock "consumer" + * @id: clock consumer ID + * + * This function behaves the same way as devm_clk_get() except where there + * is no clock producer like in ACPI-based platforms. + * + * For ACPI-based platforms, the function will read the "clock-frequency" + * ACPI _DSD property and register a fixed-clock with the frequency indicated + * in the property. + * + * This function also handles the special ACPI-based system case where: + * + * * The clock-frequency _DSD property is present. + * * A reference to the clock producer is present, where the clock is provided + * by a camera sensor PMIC driver (e.g. int3472/tps68470.c) + * + * In this case try to set the clock-frequency value to the provided clock. + * + * As the name indicates, this function may only be used on camera sensor + * devices. This is because generally only camera sensors do need a clock to + * query the frequency from, due to the requirement to configure the PLL for a + * given CSI-2 interface frequency where the sensor's external clock frequency + * is a factor. Additionally, the clock frequency tends to be available on ACPI + * firmware based systems for camera sensors specifically (if e.g. DisCo for + * Imaging compliant). + * + * Returns a pointer to a struct clk on success or an error pointer on failure. + */ +static inline struct clk * +devm_v4l2_sensor_clk_get(struct device *dev, const char *id) +{ + return __devm_v4l2_sensor_clk_get(dev, id, false, false, 0); +} + +/** + * devm_v4l2_sensor_clk_get_legacy - lookup and obtain a reference to a clock + * producer for a camera sensor. + * + * @dev: device for v4l2 sensor clock "consumer" + * @id: clock consumer ID + * @fixed_rate: interpret the @clk_rate as a fixed rate or default rate + * @clk_rate: the clock rate + * + * This function behaves the same way as devm_v4l2_sensor_clk_get() except that + * it extends the behaviour on ACPI platforms to all platforms. + * + * The function also provides the ability to set the clock rate to a fixed + * frequency by setting @fixed_rate to true and specifying the fixed frequency + * in @clk_rate, or to use a default clock rate when the "clock-frequency" + * property is absent by setting @fixed_rate to false and specifying the default + * frequency in @clk_rate. Setting @fixed_rate to true and @clk_rate to 0 is an + * error. + * + * This function is meant to support legacy behaviour in existing drivers only. + * It must not be used in any new driver. + * + * Returns a pointer to a struct clk on success or an error pointer on failure. + */ +static inline struct clk * +devm_v4l2_sensor_clk_get_legacy(struct device *dev, const char *id, + bool fixed_rate, unsigned long clk_rate) +{ + return __devm_v4l2_sensor_clk_get(dev, id, true, fixed_rate, clk_rate); +} + static inline u64 v4l2_buffer_get_timestamp(const struct v4l2_buffer *buf) { /* diff --git a/include/media/v4l2-ctrls.h b/include/media/v4l2-ctrls.h index c32c46286441..31fc1bee3797 100644 --- a/include/media/v4l2-ctrls.h +++ b/include/media/v4l2-ctrls.h @@ -2,7 +2,7 @@ /* * V4L2 controls support header. * - * Copyright (C) 2010 Hans Verkuil <hverkuil@xs4all.nl> + * Copyright (C) 2010 Hans Verkuil <hverkuil@kernel.org> */ #ifndef _V4L2_CTRLS_H @@ -1313,13 +1313,13 @@ void v4l2_ctrl_merge(const struct v4l2_event *old, struct v4l2_event *new); * v4l2_ctrl_log_status - helper function to implement %VIDIOC_LOG_STATUS ioctl * * @file: pointer to struct file - * @fh: unused. Kept just to be compatible to the arguments expected by + * @priv: unused. Kept just to be compatible to the arguments expected by * &struct v4l2_ioctl_ops.vidioc_log_status. * * Can be used as a vidioc_log_status function that just dumps all controls * associated with the filehandle. */ -int v4l2_ctrl_log_status(struct file *file, void *fh); +int v4l2_ctrl_log_status(struct file *file, void *priv); /** * v4l2_ctrl_subscribe_event - Subscribes to an event diff --git a/include/media/v4l2-dev.h b/include/media/v4l2-dev.h index a69801274800..a213c3398dcf 100644 --- a/include/media/v4l2-dev.h +++ b/include/media/v4l2-dev.h @@ -74,7 +74,7 @@ struct dentry; * @V4L2_FL_USES_V4L2_FH: * indicates that file->private_data points to &struct v4l2_fh. * This flag is set by the core when v4l2_fh_init() is called. - * All new drivers should use it. + * All drivers must use it. * @V4L2_FL_QUIRK_INVERTED_CROP: * some old M2M drivers use g/s_crop/cropcap incorrectly: crop and * compose are swapped. If this flag is set, then the selection diff --git a/include/media/v4l2-device.h b/include/media/v4l2-device.h index dd897a362f36..25f69b1b8db0 100644 --- a/include/media/v4l2-device.h +++ b/include/media/v4l2-device.h @@ -2,7 +2,7 @@ /* V4L2 device support header. - Copyright (C) 2008 Hans Verkuil <hverkuil@xs4all.nl> + Copyright (C) 2008 Hans Verkuil <hverkuil@kernel.org> */ diff --git a/include/media/v4l2-dv-timings.h b/include/media/v4l2-dv-timings.h index 714075c72f77..2b42e5d81f9e 100644 --- a/include/media/v4l2-dv-timings.h +++ b/include/media/v4l2-dv-timings.h @@ -275,6 +275,7 @@ int v4l2_phys_addr_validate(u16 phys_addr, u16 *parent, u16 *port); #define V4L2_DEBUGFS_IF_AUDIO BIT(1) #define V4L2_DEBUGFS_IF_SPD BIT(2) #define V4L2_DEBUGFS_IF_HDMI BIT(3) +#define V4L2_DEBUGFS_IF_DRM BIT(4) typedef ssize_t (*v4l2_debugfs_if_read_t)(u32 type, void *priv, struct file *filp, char __user *ubuf, diff --git a/include/media/v4l2-fh.h b/include/media/v4l2-fh.h index b5b3e00c8e6a..aad4b3689d7e 100644 --- a/include/media/v4l2-fh.h +++ b/include/media/v4l2-fh.h @@ -3,7 +3,7 @@ * v4l2-fh.h * * V4L2 file handle. Store per file handle data for the V4L2 - * framework. Using file handles is optional for the drivers. + * framework. Using file handles is mandatory for the drivers. * * Copyright (C) 2009--2010 Nokia Corporation. * @@ -57,6 +57,20 @@ struct v4l2_fh { }; /** + * file_to_v4l2_fh - Return the v4l2_fh associated with a struct file + * + * @filp: pointer to &struct file + * + * This function should be used by drivers to retrieve the &struct v4l2_fh + * instance pointer stored in the file private_data instead of accessing the + * private_data field directly. + */ +static inline struct v4l2_fh *file_to_v4l2_fh(struct file *filp) +{ + return filp->private_data; +} + +/** * v4l2_fh_init - Initialise the file handle. * * @fh: pointer to &struct v4l2_fh @@ -73,11 +87,14 @@ void v4l2_fh_init(struct v4l2_fh *fh, struct video_device *vdev); * v4l2_fh_add - Add the fh to the list of file handles on a video_device. * * @fh: pointer to &struct v4l2_fh + * @filp: pointer to &struct file associated with @fh + * + * The function sets filp->private_data to point to @fh. * * .. note:: * The @fh file handle must be initialised first. */ -void v4l2_fh_add(struct v4l2_fh *fh); +void v4l2_fh_add(struct v4l2_fh *fh, struct file *filp); /** * v4l2_fh_open - Ancillary routine that can be used as the open\(\) op @@ -87,6 +104,9 @@ void v4l2_fh_add(struct v4l2_fh *fh); * * It allocates a v4l2_fh and inits and adds it to the &struct video_device * associated with the file pointer. + * + * On error filp->private_data will be %NULL, otherwise it will point to + * the &struct v4l2_fh. */ int v4l2_fh_open(struct file *filp); @@ -94,15 +114,15 @@ int v4l2_fh_open(struct file *filp); * v4l2_fh_del - Remove file handle from the list of file handles. * * @fh: pointer to &struct v4l2_fh + * @filp: pointer to &struct file associated with @fh * - * On error filp->private_data will be %NULL, otherwise it will point to - * the &struct v4l2_fh. + * The function resets filp->private_data to NULL. * * .. note:: * Must be called in v4l2_file_operations->release\(\) handler if the driver * uses &struct v4l2_fh. */ -void v4l2_fh_del(struct v4l2_fh *fh); +void v4l2_fh_del(struct v4l2_fh *fh, struct file *filp); /** * v4l2_fh_exit - Release resources related to a file handle. diff --git a/include/media/v4l2-ioctl.h b/include/media/v4l2-ioctl.h index 82695c3a300a..6f7a58350441 100644 --- a/include/media/v4l2-ioctl.h +++ b/include/media/v4l2-ioctl.h @@ -293,144 +293,144 @@ struct v4l2_ioctl_ops { /* ioctl callbacks */ /* VIDIOC_QUERYCAP handler */ - int (*vidioc_querycap)(struct file *file, void *fh, + int (*vidioc_querycap)(struct file *file, void *priv, struct v4l2_capability *cap); /* VIDIOC_ENUM_FMT handlers */ - int (*vidioc_enum_fmt_vid_cap)(struct file *file, void *fh, + int (*vidioc_enum_fmt_vid_cap)(struct file *file, void *priv, struct v4l2_fmtdesc *f); - int (*vidioc_enum_fmt_vid_overlay)(struct file *file, void *fh, + int (*vidioc_enum_fmt_vid_overlay)(struct file *file, void *priv, struct v4l2_fmtdesc *f); - int (*vidioc_enum_fmt_vid_out)(struct file *file, void *fh, + int (*vidioc_enum_fmt_vid_out)(struct file *file, void *priv, struct v4l2_fmtdesc *f); - int (*vidioc_enum_fmt_sdr_cap)(struct file *file, void *fh, + int (*vidioc_enum_fmt_sdr_cap)(struct file *file, void *priv, struct v4l2_fmtdesc *f); - int (*vidioc_enum_fmt_sdr_out)(struct file *file, void *fh, + int (*vidioc_enum_fmt_sdr_out)(struct file *file, void *priv, struct v4l2_fmtdesc *f); - int (*vidioc_enum_fmt_meta_cap)(struct file *file, void *fh, + int (*vidioc_enum_fmt_meta_cap)(struct file *file, void *priv, struct v4l2_fmtdesc *f); - int (*vidioc_enum_fmt_meta_out)(struct file *file, void *fh, + int (*vidioc_enum_fmt_meta_out)(struct file *file, void *priv, struct v4l2_fmtdesc *f); /* VIDIOC_G_FMT handlers */ - int (*vidioc_g_fmt_vid_cap)(struct file *file, void *fh, + int (*vidioc_g_fmt_vid_cap)(struct file *file, void *priv, struct v4l2_format *f); - int (*vidioc_g_fmt_vid_overlay)(struct file *file, void *fh, + int (*vidioc_g_fmt_vid_overlay)(struct file *file, void *priv, struct v4l2_format *f); - int (*vidioc_g_fmt_vid_out)(struct file *file, void *fh, + int (*vidioc_g_fmt_vid_out)(struct file *file, void *priv, struct v4l2_format *f); - int (*vidioc_g_fmt_vid_out_overlay)(struct file *file, void *fh, + int (*vidioc_g_fmt_vid_out_overlay)(struct file *file, void *priv, struct v4l2_format *f); - int (*vidioc_g_fmt_vbi_cap)(struct file *file, void *fh, + int (*vidioc_g_fmt_vbi_cap)(struct file *file, void *priv, struct v4l2_format *f); - int (*vidioc_g_fmt_vbi_out)(struct file *file, void *fh, + int (*vidioc_g_fmt_vbi_out)(struct file *file, void *priv, struct v4l2_format *f); - int (*vidioc_g_fmt_sliced_vbi_cap)(struct file *file, void *fh, + int (*vidioc_g_fmt_sliced_vbi_cap)(struct file *file, void *priv, struct v4l2_format *f); - int (*vidioc_g_fmt_sliced_vbi_out)(struct file *file, void *fh, + int (*vidioc_g_fmt_sliced_vbi_out)(struct file *file, void *priv, struct v4l2_format *f); - int (*vidioc_g_fmt_vid_cap_mplane)(struct file *file, void *fh, + int (*vidioc_g_fmt_vid_cap_mplane)(struct file *file, void *priv, struct v4l2_format *f); - int (*vidioc_g_fmt_vid_out_mplane)(struct file *file, void *fh, + int (*vidioc_g_fmt_vid_out_mplane)(struct file *file, void *priv, struct v4l2_format *f); - int (*vidioc_g_fmt_sdr_cap)(struct file *file, void *fh, + int (*vidioc_g_fmt_sdr_cap)(struct file *file, void *priv, struct v4l2_format *f); - int (*vidioc_g_fmt_sdr_out)(struct file *file, void *fh, + int (*vidioc_g_fmt_sdr_out)(struct file *file, void *priv, struct v4l2_format *f); - int (*vidioc_g_fmt_meta_cap)(struct file *file, void *fh, + int (*vidioc_g_fmt_meta_cap)(struct file *file, void *priv, struct v4l2_format *f); - int (*vidioc_g_fmt_meta_out)(struct file *file, void *fh, + int (*vidioc_g_fmt_meta_out)(struct file *file, void *priv, struct v4l2_format *f); /* VIDIOC_S_FMT handlers */ - int (*vidioc_s_fmt_vid_cap)(struct file *file, void *fh, + int (*vidioc_s_fmt_vid_cap)(struct file *file, void *priv, struct v4l2_format *f); - int (*vidioc_s_fmt_vid_overlay)(struct file *file, void *fh, + int (*vidioc_s_fmt_vid_overlay)(struct file *file, void *priv, struct v4l2_format *f); - int (*vidioc_s_fmt_vid_out)(struct file *file, void *fh, + int (*vidioc_s_fmt_vid_out)(struct file *file, void *priv, struct v4l2_format *f); - int (*vidioc_s_fmt_vid_out_overlay)(struct file *file, void *fh, + int (*vidioc_s_fmt_vid_out_overlay)(struct file *file, void *priv, struct v4l2_format *f); - int (*vidioc_s_fmt_vbi_cap)(struct file *file, void *fh, + int (*vidioc_s_fmt_vbi_cap)(struct file *file, void *priv, struct v4l2_format *f); - int (*vidioc_s_fmt_vbi_out)(struct file *file, void *fh, + int (*vidioc_s_fmt_vbi_out)(struct file *file, void *priv, struct v4l2_format *f); - int (*vidioc_s_fmt_sliced_vbi_cap)(struct file *file, void *fh, + int (*vidioc_s_fmt_sliced_vbi_cap)(struct file *file, void *priv, struct v4l2_format *f); - int (*vidioc_s_fmt_sliced_vbi_out)(struct file *file, void *fh, + int (*vidioc_s_fmt_sliced_vbi_out)(struct file *file, void *priv, struct v4l2_format *f); - int (*vidioc_s_fmt_vid_cap_mplane)(struct file *file, void *fh, + int (*vidioc_s_fmt_vid_cap_mplane)(struct file *file, void *priv, struct v4l2_format *f); - int (*vidioc_s_fmt_vid_out_mplane)(struct file *file, void *fh, + int (*vidioc_s_fmt_vid_out_mplane)(struct file *file, void *priv, struct v4l2_format *f); - int (*vidioc_s_fmt_sdr_cap)(struct file *file, void *fh, + int (*vidioc_s_fmt_sdr_cap)(struct file *file, void *priv, struct v4l2_format *f); - int (*vidioc_s_fmt_sdr_out)(struct file *file, void *fh, + int (*vidioc_s_fmt_sdr_out)(struct file *file, void *priv, struct v4l2_format *f); - int (*vidioc_s_fmt_meta_cap)(struct file *file, void *fh, + int (*vidioc_s_fmt_meta_cap)(struct file *file, void *priv, struct v4l2_format *f); - int (*vidioc_s_fmt_meta_out)(struct file *file, void *fh, + int (*vidioc_s_fmt_meta_out)(struct file *file, void *priv, struct v4l2_format *f); /* VIDIOC_TRY_FMT handlers */ - int (*vidioc_try_fmt_vid_cap)(struct file *file, void *fh, + int (*vidioc_try_fmt_vid_cap)(struct file *file, void *priv, struct v4l2_format *f); - int (*vidioc_try_fmt_vid_overlay)(struct file *file, void *fh, + int (*vidioc_try_fmt_vid_overlay)(struct file *file, void *priv, struct v4l2_format *f); - int (*vidioc_try_fmt_vid_out)(struct file *file, void *fh, + int (*vidioc_try_fmt_vid_out)(struct file *file, void *priv, struct v4l2_format *f); - int (*vidioc_try_fmt_vid_out_overlay)(struct file *file, void *fh, - struct v4l2_format *f); - int (*vidioc_try_fmt_vbi_cap)(struct file *file, void *fh, + int (*vidioc_try_fmt_vid_out_overlay)(struct file *file, void *priv, + struct v4l2_format *f); + int (*vidioc_try_fmt_vbi_cap)(struct file *file, void *priv, struct v4l2_format *f); - int (*vidioc_try_fmt_vbi_out)(struct file *file, void *fh, + int (*vidioc_try_fmt_vbi_out)(struct file *file, void *priv, struct v4l2_format *f); - int (*vidioc_try_fmt_sliced_vbi_cap)(struct file *file, void *fh, + int (*vidioc_try_fmt_sliced_vbi_cap)(struct file *file, void *priv, struct v4l2_format *f); - int (*vidioc_try_fmt_sliced_vbi_out)(struct file *file, void *fh, + int (*vidioc_try_fmt_sliced_vbi_out)(struct file *file, void *priv, struct v4l2_format *f); - int (*vidioc_try_fmt_vid_cap_mplane)(struct file *file, void *fh, + int (*vidioc_try_fmt_vid_cap_mplane)(struct file *file, void *priv, struct v4l2_format *f); - int (*vidioc_try_fmt_vid_out_mplane)(struct file *file, void *fh, + int (*vidioc_try_fmt_vid_out_mplane)(struct file *file, void *priv, struct v4l2_format *f); - int (*vidioc_try_fmt_sdr_cap)(struct file *file, void *fh, + int (*vidioc_try_fmt_sdr_cap)(struct file *file, void *priv, struct v4l2_format *f); - int (*vidioc_try_fmt_sdr_out)(struct file *file, void *fh, + int (*vidioc_try_fmt_sdr_out)(struct file *file, void *priv, struct v4l2_format *f); - int (*vidioc_try_fmt_meta_cap)(struct file *file, void *fh, + int (*vidioc_try_fmt_meta_cap)(struct file *file, void *priv, struct v4l2_format *f); - int (*vidioc_try_fmt_meta_out)(struct file *file, void *fh, + int (*vidioc_try_fmt_meta_out)(struct file *file, void *priv, struct v4l2_format *f); /* Buffer handlers */ - int (*vidioc_reqbufs)(struct file *file, void *fh, + int (*vidioc_reqbufs)(struct file *file, void *priv, struct v4l2_requestbuffers *b); - int (*vidioc_querybuf)(struct file *file, void *fh, + int (*vidioc_querybuf)(struct file *file, void *priv, struct v4l2_buffer *b); - int (*vidioc_qbuf)(struct file *file, void *fh, + int (*vidioc_qbuf)(struct file *file, void *priv, struct v4l2_buffer *b); - int (*vidioc_expbuf)(struct file *file, void *fh, + int (*vidioc_expbuf)(struct file *file, void *priv, struct v4l2_exportbuffer *e); - int (*vidioc_dqbuf)(struct file *file, void *fh, + int (*vidioc_dqbuf)(struct file *file, void *priv, struct v4l2_buffer *b); - int (*vidioc_create_bufs)(struct file *file, void *fh, + int (*vidioc_create_bufs)(struct file *file, void *priv, struct v4l2_create_buffers *b); - int (*vidioc_prepare_buf)(struct file *file, void *fh, + int (*vidioc_prepare_buf)(struct file *file, void *priv, struct v4l2_buffer *b); - int (*vidioc_remove_bufs)(struct file *file, void *fh, + int (*vidioc_remove_bufs)(struct file *file, void *priv, struct v4l2_remove_buffers *d); - int (*vidioc_overlay)(struct file *file, void *fh, unsigned int i); - int (*vidioc_g_fbuf)(struct file *file, void *fh, + int (*vidioc_overlay)(struct file *file, void *priv, unsigned int i); + int (*vidioc_g_fbuf)(struct file *file, void *priv, struct v4l2_framebuffer *a); - int (*vidioc_s_fbuf)(struct file *file, void *fh, + int (*vidioc_s_fbuf)(struct file *file, void *priv, const struct v4l2_framebuffer *a); /* Stream on/off */ - int (*vidioc_streamon)(struct file *file, void *fh, + int (*vidioc_streamon)(struct file *file, void *priv, enum v4l2_buf_type i); - int (*vidioc_streamoff)(struct file *file, void *fh, + int (*vidioc_streamoff)(struct file *file, void *priv, enum v4l2_buf_type i); /* @@ -438,135 +438,135 @@ struct v4l2_ioctl_ops { * * Note: ENUMSTD is handled by videodev.c */ - int (*vidioc_g_std)(struct file *file, void *fh, v4l2_std_id *norm); - int (*vidioc_s_std)(struct file *file, void *fh, v4l2_std_id norm); - int (*vidioc_querystd)(struct file *file, void *fh, v4l2_std_id *a); + int (*vidioc_g_std)(struct file *file, void *priv, v4l2_std_id *norm); + int (*vidioc_s_std)(struct file *file, void *priv, v4l2_std_id norm); + int (*vidioc_querystd)(struct file *file, void *priv, v4l2_std_id *a); /* Input handling */ - int (*vidioc_enum_input)(struct file *file, void *fh, + int (*vidioc_enum_input)(struct file *file, void *priv, struct v4l2_input *inp); - int (*vidioc_g_input)(struct file *file, void *fh, unsigned int *i); - int (*vidioc_s_input)(struct file *file, void *fh, unsigned int i); + int (*vidioc_g_input)(struct file *file, void *priv, unsigned int *i); + int (*vidioc_s_input)(struct file *file, void *priv, unsigned int i); /* Output handling */ - int (*vidioc_enum_output)(struct file *file, void *fh, + int (*vidioc_enum_output)(struct file *file, void *priv, struct v4l2_output *a); - int (*vidioc_g_output)(struct file *file, void *fh, unsigned int *i); - int (*vidioc_s_output)(struct file *file, void *fh, unsigned int i); + int (*vidioc_g_output)(struct file *file, void *priv, unsigned int *i); + int (*vidioc_s_output)(struct file *file, void *priv, unsigned int i); /* Control handling */ - int (*vidioc_query_ext_ctrl)(struct file *file, void *fh, + int (*vidioc_query_ext_ctrl)(struct file *file, void *priv, struct v4l2_query_ext_ctrl *a); - int (*vidioc_g_ext_ctrls)(struct file *file, void *fh, + int (*vidioc_g_ext_ctrls)(struct file *file, void *priv, struct v4l2_ext_controls *a); - int (*vidioc_s_ext_ctrls)(struct file *file, void *fh, + int (*vidioc_s_ext_ctrls)(struct file *file, void *priv, struct v4l2_ext_controls *a); - int (*vidioc_try_ext_ctrls)(struct file *file, void *fh, + int (*vidioc_try_ext_ctrls)(struct file *file, void *priv, struct v4l2_ext_controls *a); - int (*vidioc_querymenu)(struct file *file, void *fh, + int (*vidioc_querymenu)(struct file *file, void *priv, struct v4l2_querymenu *a); /* Audio ioctls */ - int (*vidioc_enumaudio)(struct file *file, void *fh, + int (*vidioc_enumaudio)(struct file *file, void *priv, struct v4l2_audio *a); - int (*vidioc_g_audio)(struct file *file, void *fh, + int (*vidioc_g_audio)(struct file *file, void *priv, struct v4l2_audio *a); - int (*vidioc_s_audio)(struct file *file, void *fh, + int (*vidioc_s_audio)(struct file *file, void *priv, const struct v4l2_audio *a); /* Audio out ioctls */ - int (*vidioc_enumaudout)(struct file *file, void *fh, + int (*vidioc_enumaudout)(struct file *file, void *priv, struct v4l2_audioout *a); - int (*vidioc_g_audout)(struct file *file, void *fh, + int (*vidioc_g_audout)(struct file *file, void *priv, struct v4l2_audioout *a); - int (*vidioc_s_audout)(struct file *file, void *fh, + int (*vidioc_s_audout)(struct file *file, void *priv, const struct v4l2_audioout *a); - int (*vidioc_g_modulator)(struct file *file, void *fh, + int (*vidioc_g_modulator)(struct file *file, void *priv, struct v4l2_modulator *a); - int (*vidioc_s_modulator)(struct file *file, void *fh, + int (*vidioc_s_modulator)(struct file *file, void *priv, const struct v4l2_modulator *a); /* Crop ioctls */ - int (*vidioc_g_pixelaspect)(struct file *file, void *fh, + int (*vidioc_g_pixelaspect)(struct file *file, void *priv, int buf_type, struct v4l2_fract *aspect); - int (*vidioc_g_selection)(struct file *file, void *fh, + int (*vidioc_g_selection)(struct file *file, void *priv, struct v4l2_selection *s); - int (*vidioc_s_selection)(struct file *file, void *fh, + int (*vidioc_s_selection)(struct file *file, void *priv, struct v4l2_selection *s); /* Compression ioctls */ - int (*vidioc_g_jpegcomp)(struct file *file, void *fh, + int (*vidioc_g_jpegcomp)(struct file *file, void *priv, struct v4l2_jpegcompression *a); - int (*vidioc_s_jpegcomp)(struct file *file, void *fh, + int (*vidioc_s_jpegcomp)(struct file *file, void *priv, const struct v4l2_jpegcompression *a); - int (*vidioc_g_enc_index)(struct file *file, void *fh, + int (*vidioc_g_enc_index)(struct file *file, void *priv, struct v4l2_enc_idx *a); - int (*vidioc_encoder_cmd)(struct file *file, void *fh, + int (*vidioc_encoder_cmd)(struct file *file, void *priv, struct v4l2_encoder_cmd *a); - int (*vidioc_try_encoder_cmd)(struct file *file, void *fh, + int (*vidioc_try_encoder_cmd)(struct file *file, void *priv, struct v4l2_encoder_cmd *a); - int (*vidioc_decoder_cmd)(struct file *file, void *fh, + int (*vidioc_decoder_cmd)(struct file *file, void *priv, struct v4l2_decoder_cmd *a); - int (*vidioc_try_decoder_cmd)(struct file *file, void *fh, + int (*vidioc_try_decoder_cmd)(struct file *file, void *priv, struct v4l2_decoder_cmd *a); /* Stream type-dependent parameter ioctls */ - int (*vidioc_g_parm)(struct file *file, void *fh, + int (*vidioc_g_parm)(struct file *file, void *priv, struct v4l2_streamparm *a); - int (*vidioc_s_parm)(struct file *file, void *fh, + int (*vidioc_s_parm)(struct file *file, void *priv, struct v4l2_streamparm *a); /* Tuner ioctls */ - int (*vidioc_g_tuner)(struct file *file, void *fh, + int (*vidioc_g_tuner)(struct file *file, void *priv, struct v4l2_tuner *a); - int (*vidioc_s_tuner)(struct file *file, void *fh, + int (*vidioc_s_tuner)(struct file *file, void *priv, const struct v4l2_tuner *a); - int (*vidioc_g_frequency)(struct file *file, void *fh, + int (*vidioc_g_frequency)(struct file *file, void *priv, struct v4l2_frequency *a); - int (*vidioc_s_frequency)(struct file *file, void *fh, + int (*vidioc_s_frequency)(struct file *file, void *priv, const struct v4l2_frequency *a); - int (*vidioc_enum_freq_bands)(struct file *file, void *fh, + int (*vidioc_enum_freq_bands)(struct file *file, void *priv, struct v4l2_frequency_band *band); /* Sliced VBI cap */ - int (*vidioc_g_sliced_vbi_cap)(struct file *file, void *fh, + int (*vidioc_g_sliced_vbi_cap)(struct file *file, void *priv, struct v4l2_sliced_vbi_cap *a); /* Log status ioctl */ - int (*vidioc_log_status)(struct file *file, void *fh); + int (*vidioc_log_status)(struct file *file, void *priv); - int (*vidioc_s_hw_freq_seek)(struct file *file, void *fh, + int (*vidioc_s_hw_freq_seek)(struct file *file, void *priv, const struct v4l2_hw_freq_seek *a); /* Debugging ioctls */ #ifdef CONFIG_VIDEO_ADV_DEBUG - int (*vidioc_g_register)(struct file *file, void *fh, + int (*vidioc_g_register)(struct file *file, void *priv, struct v4l2_dbg_register *reg); - int (*vidioc_s_register)(struct file *file, void *fh, + int (*vidioc_s_register)(struct file *file, void *priv, const struct v4l2_dbg_register *reg); - int (*vidioc_g_chip_info)(struct file *file, void *fh, + int (*vidioc_g_chip_info)(struct file *file, void *priv, struct v4l2_dbg_chip_info *chip); #endif - int (*vidioc_enum_framesizes)(struct file *file, void *fh, + int (*vidioc_enum_framesizes)(struct file *file, void *priv, struct v4l2_frmsizeenum *fsize); - int (*vidioc_enum_frameintervals)(struct file *file, void *fh, + int (*vidioc_enum_frameintervals)(struct file *file, void *priv, struct v4l2_frmivalenum *fival); /* DV Timings IOCTLs */ - int (*vidioc_s_dv_timings)(struct file *file, void *fh, + int (*vidioc_s_dv_timings)(struct file *file, void *priv, struct v4l2_dv_timings *timings); - int (*vidioc_g_dv_timings)(struct file *file, void *fh, + int (*vidioc_g_dv_timings)(struct file *file, void *priv, struct v4l2_dv_timings *timings); - int (*vidioc_query_dv_timings)(struct file *file, void *fh, + int (*vidioc_query_dv_timings)(struct file *file, void *priv, struct v4l2_dv_timings *timings); - int (*vidioc_enum_dv_timings)(struct file *file, void *fh, + int (*vidioc_enum_dv_timings)(struct file *file, void *priv, struct v4l2_enum_dv_timings *timings); - int (*vidioc_dv_timings_cap)(struct file *file, void *fh, + int (*vidioc_dv_timings_cap)(struct file *file, void *priv, struct v4l2_dv_timings_cap *cap); - int (*vidioc_g_edid)(struct file *file, void *fh, + int (*vidioc_g_edid)(struct file *file, void *priv, struct v4l2_edid *edid); - int (*vidioc_s_edid)(struct file *file, void *fh, + int (*vidioc_s_edid)(struct file *file, void *priv, struct v4l2_edid *edid); int (*vidioc_subscribe_event)(struct v4l2_fh *fh, @@ -575,7 +575,7 @@ struct v4l2_ioctl_ops { const struct v4l2_event_subscription *sub); /* For other private ioctls */ - long (*vidioc_default)(struct file *file, void *fh, + long (*vidioc_default)(struct file *file, void *priv, bool valid_prio, unsigned int cmd, void *arg); }; diff --git a/include/media/v4l2-mem2mem.h b/include/media/v4l2-mem2mem.h index 0af330cf91c3..09c6164577cc 100644 --- a/include/media/v4l2-mem2mem.h +++ b/include/media/v4l2-mem2mem.h @@ -864,34 +864,34 @@ void v4l2_m2m_request_queue(struct media_request *req); /* v4l2 ioctl helpers */ int v4l2_m2m_ioctl_reqbufs(struct file *file, void *priv, - struct v4l2_requestbuffers *rb); -int v4l2_m2m_ioctl_create_bufs(struct file *file, void *fh, - struct v4l2_create_buffers *create); + struct v4l2_requestbuffers *rb); +int v4l2_m2m_ioctl_create_bufs(struct file *file, void *priv, + struct v4l2_create_buffers *create); int v4l2_m2m_ioctl_remove_bufs(struct file *file, void *priv, struct v4l2_remove_buffers *d); -int v4l2_m2m_ioctl_querybuf(struct file *file, void *fh, - struct v4l2_buffer *buf); -int v4l2_m2m_ioctl_expbuf(struct file *file, void *fh, - struct v4l2_exportbuffer *eb); -int v4l2_m2m_ioctl_qbuf(struct file *file, void *fh, - struct v4l2_buffer *buf); -int v4l2_m2m_ioctl_dqbuf(struct file *file, void *fh, - struct v4l2_buffer *buf); -int v4l2_m2m_ioctl_prepare_buf(struct file *file, void *fh, +int v4l2_m2m_ioctl_querybuf(struct file *file, void *priv, + struct v4l2_buffer *buf); +int v4l2_m2m_ioctl_expbuf(struct file *file, void *priv, + struct v4l2_exportbuffer *eb); +int v4l2_m2m_ioctl_qbuf(struct file *file, void *priv, + struct v4l2_buffer *buf); +int v4l2_m2m_ioctl_dqbuf(struct file *file, void *priv, + struct v4l2_buffer *buf); +int v4l2_m2m_ioctl_prepare_buf(struct file *file, void *priv, struct v4l2_buffer *buf); -int v4l2_m2m_ioctl_streamon(struct file *file, void *fh, - enum v4l2_buf_type type); -int v4l2_m2m_ioctl_streamoff(struct file *file, void *fh, - enum v4l2_buf_type type); -int v4l2_m2m_ioctl_encoder_cmd(struct file *file, void *fh, +int v4l2_m2m_ioctl_streamon(struct file *file, void *priv, + enum v4l2_buf_type type); +int v4l2_m2m_ioctl_streamoff(struct file *file, void *priv, + enum v4l2_buf_type type); +int v4l2_m2m_ioctl_encoder_cmd(struct file *file, void *priv, struct v4l2_encoder_cmd *ec); -int v4l2_m2m_ioctl_decoder_cmd(struct file *file, void *fh, +int v4l2_m2m_ioctl_decoder_cmd(struct file *file, void *priv, struct v4l2_decoder_cmd *dc); -int v4l2_m2m_ioctl_try_encoder_cmd(struct file *file, void *fh, +int v4l2_m2m_ioctl_try_encoder_cmd(struct file *file, void *priv, struct v4l2_encoder_cmd *ec); -int v4l2_m2m_ioctl_try_decoder_cmd(struct file *file, void *fh, +int v4l2_m2m_ioctl_try_decoder_cmd(struct file *file, void *priv, struct v4l2_decoder_cmd *dc); -int v4l2_m2m_ioctl_stateless_try_decoder_cmd(struct file *file, void *fh, +int v4l2_m2m_ioctl_stateless_try_decoder_cmd(struct file *file, void *priv, struct v4l2_decoder_cmd *dc); int v4l2_m2m_ioctl_stateless_decoder_cmd(struct file *file, void *priv, struct v4l2_decoder_cmd *dc); diff --git a/include/media/v4l2-subdev.h b/include/media/v4l2-subdev.h index 5dcf4065708f..e0bb58cb6d04 100644 --- a/include/media/v4l2-subdev.h +++ b/include/media/v4l2-subdev.h @@ -2,7 +2,7 @@ /* * V4L2 sub-device support header. * - * Copyright (C) 2008 Hans Verkuil <hverkuil@xs4all.nl> + * Copyright (C) 2008 Hans Verkuil <hverkuil@kernel.org> */ #ifndef _V4L2_SUBDEV_H @@ -36,6 +36,7 @@ struct v4l2_event_subscription; struct v4l2_fh; struct v4l2_subdev; struct v4l2_subdev_fh; +struct v4l2_subdev_stream_config; struct tuner_setup; struct v4l2_mbus_frame_desc; struct led_classdev; @@ -684,30 +685,6 @@ struct v4l2_subdev_pad_config { }; /** - * struct v4l2_subdev_stream_config - Used for storing stream configuration. - * - * @pad: pad number - * @stream: stream number - * @enabled: has the stream been enabled with v4l2_subdev_enable_streams() - * @fmt: &struct v4l2_mbus_framefmt - * @crop: &struct v4l2_rect to be used for crop - * @compose: &struct v4l2_rect to be used for compose - * @interval: frame interval - * - * This structure stores configuration for a stream. - */ -struct v4l2_subdev_stream_config { - u32 pad; - u32 stream; - bool enabled; - - struct v4l2_mbus_framefmt fmt; - struct v4l2_rect crop; - struct v4l2_rect compose; - struct v4l2_fract interval; -}; - -/** * struct v4l2_subdev_stream_configs - A collection of stream configs. * * @num_configs: number of entries in @config. @@ -1962,19 +1939,23 @@ extern const struct v4l2_subdev_ops v4l2_subdev_call_wrappers; * * Note: only legacy non-MC drivers may need this macro. */ -#define v4l2_subdev_call_state_try(sd, o, f, args...) \ - ({ \ - int __result; \ - static struct lock_class_key __key; \ - const char *name = KBUILD_BASENAME \ - ":" __stringify(__LINE__) ":state->lock"; \ - struct v4l2_subdev_state *state = \ - __v4l2_subdev_state_alloc(sd, name, &__key); \ - v4l2_subdev_lock_state(state); \ - __result = v4l2_subdev_call(sd, o, f, state, ##args); \ - v4l2_subdev_unlock_state(state); \ - __v4l2_subdev_state_free(state); \ - __result; \ +#define v4l2_subdev_call_state_try(sd, o, f, args...) \ + ({ \ + int __result; \ + static struct lock_class_key __key; \ + const char *name = KBUILD_BASENAME \ + ":" __stringify(__LINE__) ":state->lock"; \ + struct v4l2_subdev_state *state = \ + __v4l2_subdev_state_alloc(sd, name, &__key); \ + if (IS_ERR(state)) { \ + __result = PTR_ERR(state); \ + } else { \ + v4l2_subdev_lock_state(state); \ + __result = v4l2_subdev_call(sd, o, f, state, ##args); \ + v4l2_subdev_unlock_state(state); \ + __v4l2_subdev_state_free(state); \ + } \ + __result; \ }) /** diff --git a/include/uapi/linux/aspeed-video.h b/include/uapi/linux/aspeed-video.h index 6586a65548c4..15168e8c931e 100644 --- a/include/uapi/linux/aspeed-video.h +++ b/include/uapi/linux/aspeed-video.h @@ -8,6 +8,13 @@ #include <linux/v4l2-controls.h> +/* aspeed video's input types */ +enum aspeed_video_input { + VIDEO_INPUT_VGA = 0, + VIDEO_INPUT_GFX, + VIDEO_INPUT_MAX +}; + #define V4L2_CID_ASPEED_HQ_MODE (V4L2_CID_USER_ASPEED_BASE + 1) #define V4L2_CID_ASPEED_HQ_JPEG_QUALITY (V4L2_CID_USER_ASPEED_BASE + 2) diff --git a/include/uapi/linux/ivtv.h b/include/uapi/linux/ivtv.h index e74f18642b11..c9241f7271c4 100644 --- a/include/uapi/linux/ivtv.h +++ b/include/uapi/linux/ivtv.h @@ -2,7 +2,7 @@ /* Public ivtv API header Copyright (C) 2003-2004 Kevin Thayer <nufan_wfk at yahoo.com> - Copyright (C) 2004-2007 Hans Verkuil <hverkuil@xs4all.nl> + Copyright (C) 2004-2007 Hans Verkuil <hverkuil@kernel.org> This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/include/uapi/linux/v4l2-controls.h b/include/uapi/linux/v4l2-controls.h index f836512e9deb..2d30107e047e 100644 --- a/include/uapi/linux/v4l2-controls.h +++ b/include/uapi/linux/v4l2-controls.h @@ -1193,7 +1193,7 @@ enum v4l2_flash_strobe_source { #define V4L2_CID_JPEG_CLASS_BASE (V4L2_CTRL_CLASS_JPEG | 0x900) #define V4L2_CID_JPEG_CLASS (V4L2_CTRL_CLASS_JPEG | 1) -#define V4L2_CID_JPEG_CHROMA_SUBSAMPLING (V4L2_CID_JPEG_CLASS_BASE + 1) +#define V4L2_CID_JPEG_CHROMA_SUBSAMPLING (V4L2_CID_JPEG_CLASS_BASE + 1) enum v4l2_jpeg_chroma_subsampling { V4L2_JPEG_CHROMA_SUBSAMPLING_444 = 0, V4L2_JPEG_CHROMA_SUBSAMPLING_422 = 1, @@ -1202,15 +1202,15 @@ enum v4l2_jpeg_chroma_subsampling { V4L2_JPEG_CHROMA_SUBSAMPLING_410 = 4, V4L2_JPEG_CHROMA_SUBSAMPLING_GRAY = 5, }; -#define V4L2_CID_JPEG_RESTART_INTERVAL (V4L2_CID_JPEG_CLASS_BASE + 2) -#define V4L2_CID_JPEG_COMPRESSION_QUALITY (V4L2_CID_JPEG_CLASS_BASE + 3) +#define V4L2_CID_JPEG_RESTART_INTERVAL (V4L2_CID_JPEG_CLASS_BASE + 2) +#define V4L2_CID_JPEG_COMPRESSION_QUALITY (V4L2_CID_JPEG_CLASS_BASE + 3) -#define V4L2_CID_JPEG_ACTIVE_MARKER (V4L2_CID_JPEG_CLASS_BASE + 4) -#define V4L2_JPEG_ACTIVE_MARKER_APP0 (1 << 0) -#define V4L2_JPEG_ACTIVE_MARKER_APP1 (1 << 1) -#define V4L2_JPEG_ACTIVE_MARKER_COM (1 << 16) -#define V4L2_JPEG_ACTIVE_MARKER_DQT (1 << 17) -#define V4L2_JPEG_ACTIVE_MARKER_DHT (1 << 18) +#define V4L2_CID_JPEG_ACTIVE_MARKER (V4L2_CID_JPEG_CLASS_BASE + 4) +#define V4L2_JPEG_ACTIVE_MARKER_APP0 (1 << 0) +#define V4L2_JPEG_ACTIVE_MARKER_APP1 (1 << 1) +#define V4L2_JPEG_ACTIVE_MARKER_COM (1 << 16) +#define V4L2_JPEG_ACTIVE_MARKER_DQT (1 << 17) +#define V4L2_JPEG_ACTIVE_MARKER_DHT (1 << 18) /* Image source controls */ @@ -1243,10 +1243,10 @@ enum v4l2_jpeg_chroma_subsampling { #define V4L2_CID_DV_CLASS_BASE (V4L2_CTRL_CLASS_DV | 0x900) #define V4L2_CID_DV_CLASS (V4L2_CTRL_CLASS_DV | 1) -#define V4L2_CID_DV_TX_HOTPLUG (V4L2_CID_DV_CLASS_BASE + 1) -#define V4L2_CID_DV_TX_RXSENSE (V4L2_CID_DV_CLASS_BASE + 2) -#define V4L2_CID_DV_TX_EDID_PRESENT (V4L2_CID_DV_CLASS_BASE + 3) -#define V4L2_CID_DV_TX_MODE (V4L2_CID_DV_CLASS_BASE + 4) +#define V4L2_CID_DV_TX_HOTPLUG (V4L2_CID_DV_CLASS_BASE + 1) +#define V4L2_CID_DV_TX_RXSENSE (V4L2_CID_DV_CLASS_BASE + 2) +#define V4L2_CID_DV_TX_EDID_PRESENT (V4L2_CID_DV_CLASS_BASE + 3) +#define V4L2_CID_DV_TX_MODE (V4L2_CID_DV_CLASS_BASE + 4) enum v4l2_dv_tx_mode { V4L2_DV_TX_MODE_DVI_D = 0, V4L2_DV_TX_MODE_HDMI = 1, @@ -1267,7 +1267,7 @@ enum v4l2_dv_it_content_type { V4L2_DV_IT_CONTENT_TYPE_NO_ITC = 4, }; -#define V4L2_CID_DV_RX_POWER_PRESENT (V4L2_CID_DV_CLASS_BASE + 100) +#define V4L2_CID_DV_RX_POWER_PRESENT (V4L2_CID_DV_CLASS_BASE + 100) #define V4L2_CID_DV_RX_RGB_RANGE (V4L2_CID_DV_CLASS_BASE + 101) #define V4L2_CID_DV_RX_IT_CONTENT_TYPE (V4L2_CID_DV_CLASS_BASE + 102) @@ -1537,15 +1537,6 @@ struct v4l2_ctrl_h264_pred_weights { struct v4l2_h264_weight_factors weight_factors[2]; }; -#define V4L2_H264_SLICE_TYPE_P 0 -#define V4L2_H264_SLICE_TYPE_B 1 -#define V4L2_H264_SLICE_TYPE_I 2 -#define V4L2_H264_SLICE_TYPE_SP 3 -#define V4L2_H264_SLICE_TYPE_SI 4 - -#define V4L2_H264_SLICE_FLAG_DIRECT_SPATIAL_MV_PRED 0x01 -#define V4L2_H264_SLICE_FLAG_SP_FOR_SWITCH 0x02 - #define V4L2_H264_TOP_FIELD_REF 0x1 #define V4L2_H264_BOTTOM_FIELD_REF 0x2 #define V4L2_H264_FRAME_REF 0x3 @@ -1566,8 +1557,17 @@ struct v4l2_h264_reference { * Maximum DPB size, as specified by section 'A.3.1 Level limits * common to the Baseline, Main, and Extended profiles'. */ -#define V4L2_H264_NUM_DPB_ENTRIES 16 -#define V4L2_H264_REF_LIST_LEN (2 * V4L2_H264_NUM_DPB_ENTRIES) +#define V4L2_H264_NUM_DPB_ENTRIES 16 +#define V4L2_H264_REF_LIST_LEN (2 * V4L2_H264_NUM_DPB_ENTRIES) + +#define V4L2_H264_SLICE_TYPE_P 0 +#define V4L2_H264_SLICE_TYPE_B 1 +#define V4L2_H264_SLICE_TYPE_I 2 +#define V4L2_H264_SLICE_TYPE_SP 3 +#define V4L2_H264_SLICE_TYPE_SI 4 + +#define V4L2_H264_SLICE_FLAG_DIRECT_SPATIAL_MV_PRED 0x01 +#define V4L2_H264_SLICE_FLAG_SP_FOR_SWITCH 0x02 #define V4L2_CID_STATELESS_H264_SLICE_PARAMS (V4L2_CID_CODEC_STATELESS_BASE + 6) /** @@ -1707,7 +1707,6 @@ struct v4l2_ctrl_h264_decode_params { __u32 flags; }; - /* Stateless FWHT control, used by the vicodec driver */ /* Current FWHT version */ @@ -2549,44 +2548,10 @@ struct v4l2_ctrl_hevc_scaling_matrix { __u8 scaling_list_dc_coef_32x32[2]; }; -#define V4L2_CID_COLORIMETRY_CLASS_BASE (V4L2_CTRL_CLASS_COLORIMETRY | 0x900) -#define V4L2_CID_COLORIMETRY_CLASS (V4L2_CTRL_CLASS_COLORIMETRY | 1) - -#define V4L2_CID_COLORIMETRY_HDR10_CLL_INFO (V4L2_CID_COLORIMETRY_CLASS_BASE + 0) - -struct v4l2_ctrl_hdr10_cll_info { - __u16 max_content_light_level; - __u16 max_pic_average_light_level; -}; - -#define V4L2_CID_COLORIMETRY_HDR10_MASTERING_DISPLAY (V4L2_CID_COLORIMETRY_CLASS_BASE + 1) - -#define V4L2_HDR10_MASTERING_PRIMARIES_X_LOW 5 -#define V4L2_HDR10_MASTERING_PRIMARIES_X_HIGH 37000 -#define V4L2_HDR10_MASTERING_PRIMARIES_Y_LOW 5 -#define V4L2_HDR10_MASTERING_PRIMARIES_Y_HIGH 42000 -#define V4L2_HDR10_MASTERING_WHITE_POINT_X_LOW 5 -#define V4L2_HDR10_MASTERING_WHITE_POINT_X_HIGH 37000 -#define V4L2_HDR10_MASTERING_WHITE_POINT_Y_LOW 5 -#define V4L2_HDR10_MASTERING_WHITE_POINT_Y_HIGH 42000 -#define V4L2_HDR10_MASTERING_MAX_LUMA_LOW 50000 -#define V4L2_HDR10_MASTERING_MAX_LUMA_HIGH 100000000 -#define V4L2_HDR10_MASTERING_MIN_LUMA_LOW 1 -#define V4L2_HDR10_MASTERING_MIN_LUMA_HIGH 50000 - -struct v4l2_ctrl_hdr10_mastering_display { - __u16 display_primaries_x[3]; - __u16 display_primaries_y[3]; - __u16 white_point_x; - __u16 white_point_y; - __u32 max_display_mastering_luminance; - __u32 min_display_mastering_luminance; -}; - /* Stateless VP9 controls */ #define V4L2_VP9_LOOP_FILTER_FLAG_DELTA_ENABLED 0x1 -#define V4L2_VP9_LOOP_FILTER_FLAG_DELTA_UPDATE 0x2 +#define V4L2_VP9_LOOP_FILTER_FLAG_DELTA_UPDATE 0x2 /** * struct v4l2_vp9_loop_filter - VP9 loop filter parameters @@ -3515,4 +3480,38 @@ struct v4l2_ctrl_av1_film_grain { #define V4L2_CID_MPEG_MFC51_BASE V4L2_CID_CODEC_MFC51_BASE #endif +#define V4L2_CID_COLORIMETRY_CLASS_BASE (V4L2_CTRL_CLASS_COLORIMETRY | 0x900) +#define V4L2_CID_COLORIMETRY_CLASS (V4L2_CTRL_CLASS_COLORIMETRY | 1) + +#define V4L2_CID_COLORIMETRY_HDR10_CLL_INFO (V4L2_CID_COLORIMETRY_CLASS_BASE + 0) + +struct v4l2_ctrl_hdr10_cll_info { + __u16 max_content_light_level; + __u16 max_pic_average_light_level; +}; + +#define V4L2_CID_COLORIMETRY_HDR10_MASTERING_DISPLAY (V4L2_CID_COLORIMETRY_CLASS_BASE + 1) + +#define V4L2_HDR10_MASTERING_PRIMARIES_X_LOW 5 +#define V4L2_HDR10_MASTERING_PRIMARIES_X_HIGH 37000 +#define V4L2_HDR10_MASTERING_PRIMARIES_Y_LOW 5 +#define V4L2_HDR10_MASTERING_PRIMARIES_Y_HIGH 42000 +#define V4L2_HDR10_MASTERING_WHITE_POINT_X_LOW 5 +#define V4L2_HDR10_MASTERING_WHITE_POINT_X_HIGH 37000 +#define V4L2_HDR10_MASTERING_WHITE_POINT_Y_LOW 5 +#define V4L2_HDR10_MASTERING_WHITE_POINT_Y_HIGH 42000 +#define V4L2_HDR10_MASTERING_MAX_LUMA_LOW 50000 +#define V4L2_HDR10_MASTERING_MAX_LUMA_HIGH 100000000 +#define V4L2_HDR10_MASTERING_MIN_LUMA_LOW 1 +#define V4L2_HDR10_MASTERING_MIN_LUMA_HIGH 50000 + +struct v4l2_ctrl_hdr10_mastering_display { + __u16 display_primaries_x[3]; + __u16 display_primaries_y[3]; + __u16 white_point_x; + __u16 white_point_y; + __u32 max_display_mastering_luminance; + __u32 min_display_mastering_luminance; +}; + #endif diff --git a/include/uapi/linux/v4l2-dv-timings.h b/include/uapi/linux/v4l2-dv-timings.h index 44a16e0e5a12..58f478f98a35 100644 --- a/include/uapi/linux/v4l2-dv-timings.h +++ b/include/uapi/linux/v4l2-dv-timings.h @@ -2,7 +2,7 @@ /* * V4L2 DV timings header. * - * Copyright (C) 2012-2016 Hans Verkuil <hansverk@cisco.com> + * Copyright (C) 2012-2016 Hans Verkuil <hverkuil@kernel.org> */ #ifndef _V4L2_DV_TIMINGS_H diff --git a/include/uapi/linux/videodev2.h b/include/uapi/linux/videodev2.h index 3dd9fa45dde1..becd08fdbddb 100644 --- a/include/uapi/linux/videodev2.h +++ b/include/uapi/linux/videodev2.h @@ -51,7 +51,7 @@ * * Author: Bill Dirks <bill@thedirks.org> * Justin Schoeman - * Hans Verkuil <hverkuil@xs4all.nl> + * Hans Verkuil <hverkuil@kernel.org> * et al. */ #ifndef _UAPI__LINUX_VIDEODEV2_H @@ -1607,8 +1607,8 @@ struct v4l2_bt_timings { } __attribute__ ((packed)); /* Interlaced or progressive format */ -#define V4L2_DV_PROGRESSIVE 0 -#define V4L2_DV_INTERLACED 1 +#define V4L2_DV_PROGRESSIVE 0 +#define V4L2_DV_INTERLACED 1 /* Polarities. If bit is not set, it is assumed to be negative polarity */ #define V4L2_DV_VSYNC_POS_POL 0x00000001 @@ -2788,15 +2788,15 @@ struct v4l2_remove_buffers { * Only implemented if CONFIG_VIDEO_ADV_DEBUG is defined. * You must be root to use these ioctls. Never use these in applications! */ -#define VIDIOC_DBG_S_REGISTER _IOW('V', 79, struct v4l2_dbg_register) -#define VIDIOC_DBG_G_REGISTER _IOWR('V', 80, struct v4l2_dbg_register) +#define VIDIOC_DBG_S_REGISTER _IOW('V', 79, struct v4l2_dbg_register) +#define VIDIOC_DBG_G_REGISTER _IOWR('V', 80, struct v4l2_dbg_register) #define VIDIOC_S_HW_FREQ_SEEK _IOW('V', 82, struct v4l2_hw_freq_seek) -#define VIDIOC_S_DV_TIMINGS _IOWR('V', 87, struct v4l2_dv_timings) -#define VIDIOC_G_DV_TIMINGS _IOWR('V', 88, struct v4l2_dv_timings) -#define VIDIOC_DQEVENT _IOR('V', 89, struct v4l2_event) -#define VIDIOC_SUBSCRIBE_EVENT _IOW('V', 90, struct v4l2_event_subscription) -#define VIDIOC_UNSUBSCRIBE_EVENT _IOW('V', 91, struct v4l2_event_subscription) +#define VIDIOC_S_DV_TIMINGS _IOWR('V', 87, struct v4l2_dv_timings) +#define VIDIOC_G_DV_TIMINGS _IOWR('V', 88, struct v4l2_dv_timings) +#define VIDIOC_DQEVENT _IOR('V', 89, struct v4l2_event) +#define VIDIOC_SUBSCRIBE_EVENT _IOW('V', 90, struct v4l2_event_subscription) +#define VIDIOC_UNSUBSCRIBE_EVENT _IOW('V', 91, struct v4l2_event_subscription) #define VIDIOC_CREATE_BUFS _IOWR('V', 92, struct v4l2_create_buffers) #define VIDIOC_PREPARE_BUF _IOWR('V', 93, struct v4l2_buffer) #define VIDIOC_G_SELECTION _IOWR('V', 94, struct v4l2_selection) diff --git a/samples/v4l/v4l2-pci-skeleton.c b/samples/v4l/v4l2-pci-skeleton.c index d709d82800cd..69925d30329e 100644 --- a/samples/v4l/v4l2-pci-skeleton.c +++ b/samples/v4l/v4l2-pci-skeleton.c @@ -470,7 +470,7 @@ static int skeleton_querystd(struct file *file, void *priv, v4l2_std_id *std) return 0; } -static int skeleton_s_dv_timings(struct file *file, void *_fh, +static int skeleton_s_dv_timings(struct file *file, void *priv, struct v4l2_dv_timings *timings) { struct skeleton *skel = video_drvdata(file); @@ -509,7 +509,7 @@ static int skeleton_s_dv_timings(struct file *file, void *_fh, return 0; } -static int skeleton_g_dv_timings(struct file *file, void *_fh, +static int skeleton_g_dv_timings(struct file *file, void *priv, struct v4l2_dv_timings *timings) { struct skeleton *skel = video_drvdata(file); @@ -522,7 +522,7 @@ static int skeleton_g_dv_timings(struct file *file, void *_fh, return 0; } -static int skeleton_enum_dv_timings(struct file *file, void *_fh, +static int skeleton_enum_dv_timings(struct file *file, void *priv, struct v4l2_enum_dv_timings *timings) { struct skeleton *skel = video_drvdata(file); @@ -544,7 +544,7 @@ static int skeleton_enum_dv_timings(struct file *file, void *_fh, * can lock but that the DMA engine it is connected to cannot handle * pixelclocks above a certain frequency), then -ERANGE is returned. */ -static int skeleton_query_dv_timings(struct file *file, void *_fh, +static int skeleton_query_dv_timings(struct file *file, void *priv, struct v4l2_dv_timings *timings) { struct skeleton *skel = video_drvdata(file); @@ -573,7 +573,7 @@ static int skeleton_query_dv_timings(struct file *file, void *_fh, return 0; } -static int skeleton_dv_timings_cap(struct file *file, void *fh, +static int skeleton_dv_timings_cap(struct file *file, void *priv, struct v4l2_dv_timings_cap *cap) { struct skeleton *skel = video_drvdata(file); |