* [PATCH 00/72] media: i2c: Reduce cargo-cult
@ 2025-07-10 17:46 Laurent Pinchart
2025-07-10 17:46 ` [PATCH 01/72] dt-bindings: media: Deprecate clock-frequency property for camera sensors Laurent Pinchart
` (73 more replies)
0 siblings, 74 replies; 115+ messages in thread
From: Laurent Pinchart @ 2025-07-10 17:46 UTC (permalink / raw)
To: linux-media
Cc: Sakari Ailus, Mehdi Djait, Alim Akhtar, André Apitzsch,
Andrzej Hajda, Arec Kao, Benjamin Mugnier, Bingbu Cao,
Bjorn Andersson, Bryan O'Donoghue, Bryan O'Donoghue,
Conor Dooley, Daniel Scally, Dongcheng Yan, Dongchun Zhu,
Fabio Estevam, Geert Uytterhoeven, Hans de Goede, Hans Verkuil,
Hao Yao, Heimir Thor Sverrisson, Jacopo Mondi, Jason Chen,
Jimmy Su, Jingjing Xiong, Jonas Karlman, Konrad Dybcio,
Krzysztof Kozlowski, Lad Prabhakar, Leon Luo, Liam Girdwood,
Magnus Damm, Manivannan Sadhasivam, Mark Brown, Matthew Majewski,
Matthias Fend, Mikhail Rudenko, Nicolas Dufresne,
Niklas Söderlund, Pavel Machek, Pengutronix Kernel Team,
Ricardo Ribalda, Rob Herring, Sascha Hauer, Shawn Guo,
Shunqian Zheng, Sylvain Petinot, Sylwester Nawrocki, Tarang Raval,
Tianshu Qiu, Todor Tomov, Tomi Valkeinen, Tony Lindgren, Zhi Mao,
devicetree, imx, linux-arm-kernel, linux-arm-msm, linux-omap,
linux-renesas-soc, linux-samsung-soc
Hello,
This patch series build on top of Mehdi's introduction of the
devm_v4l2_sensor_clk_get() helper (see [1]) to drastically reduce
cargo-cult in camera sensor drivers.
A large number of camera sensor drivers directly use the
"clock-frequency" property to retrieve the effective or desired external
clock rate. This is standard behaviour on ACPI platforms that don't
implement MIPI DisCo for Imaging, but usage of the property has leaked
to OF-based platforms, due to a combination of historical reasons (using
"clock-frequency" was initially considered right until before the
introduction of "assigned-clock-rates") and plain cargo-cult.
A large number of camera sensor drivers also set the rate of the
external clock with clk_set_rate(). This behaviour is also fine on ACPI
platforms, and has also leaked to OF-based platforms for the same
reasons.
Mehdi's "[PATCH v2 00/48] media: Add a helper for obtaining the clock
producer" series improves the situation by centralizing clock handling
for camera sensor in one helper function that implements the correct
behaviour for all types of platforms (and should later allow support of
MIPI DisCo for Imaging transparently for camera sensor drivers). It
doesn't however address direct access of the "clock-frequency" property
or direct calls to clk_set_rate() in drivers.
This series builds on top of the new helper to replace manual handling
of the clock frequency in camera sensor drivers. It starts by addressing
the DT bindings and reprecating the clock-frequency property for camera
sensor drivers in all YAML bindings (01/72) and in the et8ek8 text
bindings (02/72). After that, patches 03/72 and 04/72 make the clocks
property mandatory in the two camera sensor DT bindings that specified
it as optional. Finally for the DT side, patches 05/72 to 14/72 replace
clock-frequency with assigned-clock-rates, or drops the property
altogether when the source clock has a fixed rate. This aligns the DT
bindings and device tree sources to the current recommended practice.
After that, the next 5 patches are assorted drive-by changes. Patch
15/72 drops an unused header the belonged to a long gone driver, and
patch 17/72 drops unusued support for platform data in the mt9v032
driver. Patch 18/72 is the first that addresses clock rate handling by
dropping unneeded clock rate setting in the mt9v111 driver. Patch 19/72
takes a harsher approach for the ov6650 by dropping the driver
completely as the driver hasn't been used since v5.9.
The next part of the series replaces manual clock rate handling with
usage of the devm_v4l2_sensor_clk_get() helper in a large number of
camera sensor drivers that implement clock rate handling in a standard
way. This is done in patches 20/72 to 54/72. This interleaves the clock
rate handling changes with drive-by refactoring (in separate patches) to
make the code easier to deal with.
The final part of the series addresses the remaining drivers that
implement non-standard behaviours. It starts in 55/72 by adding a new
devm_v4l2_sensor_clk_get_legacy() helper function for those drivers,
similar to devm_v4l2_sensor_clk_get() but with a few more quirks. This
function should not be used in any new driver. The remaining patches,
from 53/72 to 72/72, use the new helper in drivers, interleaved with
drive-by refactoring similarly to the previous part.
Before this series, with Mehdi's series applied, 29 drivers read the
"clock-frequency" property and 18 drivers set the external clock rate.
With these series we go down to 1 and 3 respectively, namely the ccs,
mt9p031 and mt9v032 drivers. Clock handling in the CCS driver is a bit
more convoluted so I will leave to Sakari the honour of dropping the
last direct user of "clock-frequency" :-) As for the mt9p031 and mt9v032
driver, addressing the issue there is more difficult and likely not
worth it.
[1] https://lore.kernel.org/linux-media/cover.1750942967.git.mehdi.djait@linux.intel.com
Laurent Pinchart (72):
dt-bindings: media: Deprecate clock-frequency property for camera
sensors
dt-bindings: media: et8ek8: Deprecate clock-frequency property
dt-bindings: media: imx258: Make clocks property required
dt-bindings: media: imx274: Make clocks property required
ARM: dts: nxp: imx6qdl-pico: Replace clock-frequency in camera sensor
node
ARM: dts: nxp: imx6qdl-wandboard: Replace clock-frequency in camera
sensor node
ARM: dts: samsung: exynos4210-i9100: Replace clock-frequency in camera
sensor node
ARM: dts: samsung: exynos4412-midas: Replace clock-frequency in camera
sensor node
ARM: dts: ti: omap3-n900: Replace clock-frequency in camera sensor
node
ARM: dts: ti: omap3-n950: Replace clock-frequency in camera sensor
node
ARM: dts: ti: omap3-n9: Replace clock-frequency in camera sensor node
arm64: dts: qcom: sdm845-db845c-navigation-mezzanine: Replace
clock-frequency in camera sensor node
arm64: dts: renesas: aistarvision-mipi-adapter-2.1: Drop
clock-frequency from camera sensor node
arm64: dts: renesas: rzg2l-smarc: Drop clock-frequency from camera
sensor node
media: i2c: mt9v022: Drop unused mt9v022.h header
media: i2c: mt9v032: Replace client->dev usage
media: i2c: mt9v032: Drop support for platform data
media: i2c: mt9v111: Do not set clock rate manually
media: i2c: ov6650: Drop unused driver
media: i2c: hi556: Replace client->dev usage
media: i2c: hi556: Use V4L2 sensor clock helper
media: i2c: hi847: Replace client->dev usage
media: i2c: hi847: Use V4L2 sensor clock helper
media: i2c: imx208: Replace client->dev usage
media: i2c: imx208: Use V4L2 sensor clock helper
media: i2c: imx319: Replace client->dev usage
media: i2c: imx319: Use V4L2 sensor clock helper
media: i2c: imx355: Replace client->dev usage
media: i2c: imx335: Use V4L2 sensor clock helper
media: i2c: og01a1b: Replace client->dev usage
media: i2c: og01a1b: Use V4L2 sensor clock helper
media: i2c: ov02c10: Replace client->dev usage
media: i2c: ov02c10: Use V4L2 sensor clock helper
media: i2c: ov02e10: Replace client->dev usage
media: i2c: ov02e10: Use V4L2 sensor clock helper
media: i2c: ov08d10: Replace client->dev usage
media: i2c: ov08d10: Use V4L2 sensor clock helper
media: i2c: ov08x40: Replace client->dev usage
media: i2c: ov08x40: Use V4L2 sensor clock helper
media: i2c: ov13858: Replace client->dev usage
media: i2c: ov13858: Use V4L2 sensor clock helper
media: i2c: ov13b10: Replace client->dev usage
media: i2c: ov13b10: Use V4L2 sensor clock helper
media: i2c: ov2740: Replace client->dev usage
media: i2c: ov2740: Use V4L2 sensor clock helper
media: i2c: ov4689: Use V4L2 sensor clock helper
media: i2c: ov5670: Replace client->dev usage
media: i2c: ov5670: Use V4L2 sensor clock helper
media: i2c: ov5675: Replace client->dev usage
media: i2c: ov5675: Use V4L2 sensor clock helper
media: i2c: ov5693: Use V4L2 sensor clock helper
media: i2c: ov7251: Use V4L2 sensor clock helper
media: i2c: ov9734: Replace client->dev usage
media: i2c: ov9734: Use V4L2 sensor clock helper
media: v4l2-common: Add legacy camera sensor clock helper
media: i2c: et8ek8: Drop support for per-mode external clock frequency
media: i2c: et8ek8: Use V4L2 legacy sensor clock helper
media: i2c: gc05a2: Use V4L2 legacy sensor clock helper
media: i2c: gc08a3: Use V4L2 legacy sensor clock helper
media: i2c: imx258: Replace client->dev usage
media: i2c: imx258: Use V4L2 legacy sensor clock helper
media: i2c: imx290: Use V4L2 legacy sensor clock helper
media: i2c: ov02a10: Replace client->dev usage
media: i2c: ov02a10: Use V4L2 legacy sensor clock helper
media: i2c: ov2685: Use V4L2 legacy sensor clock helper
media: i2c: ov5645: Use V4L2 legacy sensor clock helper
media: i2c: ov5695: Use V4L2 legacy sensor clock helper
media: i2c: ov8856: Replace client->dev usage
media: i2c: ov8856: Use V4L2 legacy sensor clock helper
media: i2c: s5c73m3: Use V4L2 legacy sensor clock helper
media: i2c: s5k5baf: Use V4L2 legacy sensor clock helper
media: i2c: s5k6a3: Use V4L2 legacy sensor clock helper
.../admin-guide/media/i2c-cardlist.rst | 1 -
.../bindings/media/i2c/mipi-ccs.yaml | 7 +-
.../bindings/media/i2c/ovti,ov02a10.yaml | 3 +-
.../bindings/media/i2c/ovti,ov5645.yaml | 6 +-
.../bindings/media/i2c/ovti,ov7251.yaml | 6 +-
.../bindings/media/i2c/ovti,ov8856.yaml | 3 +-
.../bindings/media/i2c/samsung,s5k5baf.yaml | 6 +-
.../bindings/media/i2c/samsung,s5k6a3.yaml | 6 +-
.../bindings/media/i2c/sony,imx258.yaml | 1 +
.../bindings/media/i2c/sony,imx274.yaml | 4 +
.../bindings/media/i2c/sony,imx290.yaml | 5 +-
.../bindings/media/i2c/toshiba,et8ek8.txt | 8 +-
MAINTAINERS | 1 -
arch/arm/boot/dts/nxp/imx/imx6qdl-pico.dtsi | 5 +-
.../boot/dts/nxp/imx/imx6qdl-wandboard.dtsi | 5 +-
.../arm/boot/dts/samsung/exynos4210-i9100.dts | 5 +-
.../boot/dts/samsung/exynos4412-midas.dtsi | 5 +-
arch/arm/boot/dts/ti/omap/omap3-n9.dts | 5 +-
arch/arm/boot/dts/ti/omap/omap3-n900.dts | 3 +-
arch/arm/boot/dts/ti/omap/omap3-n950.dts | 5 +-
.../sdm845-db845c-navigation-mezzanine.dtso | 3 +-
.../aistarvision-mipi-adapter-2.1.dtsi | 1 -
.../dts/renesas/rz-smarc-cru-csi-ov5645.dtsi | 1 -
drivers/media/i2c/Kconfig | 10 +-
drivers/media/i2c/Makefile | 1 -
drivers/media/i2c/et8ek8/et8ek8_driver.c | 27 +-
drivers/media/i2c/et8ek8/et8ek8_mode.c | 9 -
drivers/media/i2c/et8ek8/et8ek8_reg.h | 1 -
drivers/media/i2c/gc05a2.c | 8 +-
drivers/media/i2c/gc08a3.c | 8 +-
drivers/media/i2c/hi556.c | 92 +-
drivers/media/i2c/hi847.c | 84 +-
drivers/media/i2c/imx208.c | 91 +-
drivers/media/i2c/imx258.c | 105 +-
drivers/media/i2c/imx290.c | 27 +-
drivers/media/i2c/imx319.c | 92 +-
drivers/media/i2c/imx355.c | 90 +-
drivers/media/i2c/mt9v032.c | 104 +-
drivers/media/i2c/mt9v111.c | 2 -
drivers/media/i2c/og01a1b.c | 103 +-
drivers/media/i2c/ov02a10.c | 45 +-
drivers/media/i2c/ov02c10.c | 107 +-
drivers/media/i2c/ov02e10.c | 105 +-
drivers/media/i2c/ov08d10.c | 82 +-
drivers/media/i2c/ov08x40.c | 95 +-
drivers/media/i2c/ov13858.c | 69 +-
drivers/media/i2c/ov13b10.c | 110 +-
drivers/media/i2c/ov2685.c | 8 +-
drivers/media/i2c/ov2740.c | 91 +-
drivers/media/i2c/ov4689.c | 12 +-
drivers/media/i2c/ov5645.c | 13 +-
drivers/media/i2c/ov5670.c | 105 +-
drivers/media/i2c/ov5675.c | 89 +-
drivers/media/i2c/ov5693.c | 16 +-
drivers/media/i2c/ov5695.c | 8 +-
drivers/media/i2c/ov6650.c | 1147 -----------------
drivers/media/i2c/ov7251.c | 26 +-
drivers/media/i2c/ov8856.c | 93 +-
drivers/media/i2c/ov9734.c | 82 +-
drivers/media/i2c/s5c73m3/s5c73m3-core.c | 15 +-
drivers/media/i2c/s5c73m3/s5c73m3.h | 2 -
drivers/media/i2c/s5k5baf.c | 19 +-
drivers/media/i2c/s5k6a3.c | 17 +-
drivers/media/v4l2-core/v4l2-common.c | 39 +-
include/media/i2c/mt9v022.h | 13 -
include/media/i2c/mt9v032.h | 12 -
include/media/v4l2-common.h | 41 +-
67 files changed, 1031 insertions(+), 2379 deletions(-)
delete mode 100644 drivers/media/i2c/ov6650.c
delete mode 100644 include/media/i2c/mt9v022.h
delete mode 100644 include/media/i2c/mt9v032.h
base-commit: 95703a099e094c00a0714f4d6fa6d9f142ff3fda
prerequisite-patch-id: f9a80c958fab645e237a47c8e3bc19268fe699a0
prerequisite-patch-id: d058d644effe1953c742f6f0c7dd7692c61c733c
prerequisite-patch-id: 7b42fb0bc003a3857d332d404e935c01e917d73b
prerequisite-patch-id: d9b48f03a77c0fe88e60cf88256a395944b99810
prerequisite-patch-id: 9545c613887ee00591c30147553ac785703419e7
prerequisite-patch-id: 43ab82f52c5038df96167d26d63cd838a2d8eb58
prerequisite-patch-id: 182a9155342a92026b0da69532eaac966e2cd7be
prerequisite-patch-id: 2f9595bda17ce11348420cad7e446bc96b79b7e6
prerequisite-patch-id: 5e6e13044a003e00340c29539376d69e6bc1849c
prerequisite-patch-id: 32fcb56cf75ea45ff7cc556839ddbaffda509026
prerequisite-patch-id: 961a751cff6f39f6adad4e03a6dda045ccf42177
prerequisite-patch-id: 8b60d2f5b1e70480a9e6d2177f743a577db6e3ba
prerequisite-patch-id: 8ec9ba9f786d2f33e8b452bd380185351d1d97e1
prerequisite-patch-id: 24683271a88f01fef004788121ed0b0d610079e6
prerequisite-patch-id: f3bc82c9657b3bcdd81703a82efe90a39e598053
prerequisite-patch-id: 493444e38f6b82e080fec5f0e7f63fd95daca8c0
prerequisite-patch-id: 82f6ac141be65b812f142fb0e06f4501be9dc144
prerequisite-patch-id: e75c59c8eccf0248f5c8a9ba6cae398148a8d361
prerequisite-patch-id: 46aff7d253a16ebdc64dd4cb3b30f031579c3053
prerequisite-patch-id: 57e9cabf0ce8bda498fe2f16db6dd4a9d748d2fd
prerequisite-patch-id: 23781810738fe92eb26cb67ba16f554f58a6f2e4
prerequisite-patch-id: 3c82cca940d393e6ef78b79d7e065dbc62f03be9
prerequisite-patch-id: 52f23cc4ccfc514c7d24e9ac52ac537ba2256a51
prerequisite-patch-id: 2914df66fa49278e9163df769a810142652571b9
prerequisite-patch-id: a7d5dc1aa489556bdcd92d66d9ea78741a9a5d5c
prerequisite-patch-id: ac630eb405db2ea63c8ce3d037d0fa1ba635a397
prerequisite-patch-id: a4ea26b410045f28858d860bc382f6ec976be6d6
prerequisite-patch-id: 8e05fa6d4b7f0ae3feb21a8cfba71bf119d7ad8c
prerequisite-patch-id: e2db4be18a1c859947c90253b462b5d50611a4be
prerequisite-patch-id: 0fa8b8720b573929806bd35e3edc51f0544237ff
prerequisite-patch-id: 69f5743bca8d89adc28a35f3461d1c87e071e671
prerequisite-patch-id: 3076e3da660a8eef7f6f6dafb5fdd2bc2c83d754
prerequisite-patch-id: 09230d2fca61e552cc845242ed326b8eaf3514a4
prerequisite-patch-id: 63f0dc4815777b5005046c90c3fb1fe8ceb88664
prerequisite-patch-id: 012483569daea09f783c6f9a7c5c49bebb8959b0
prerequisite-patch-id: 7fe0df4335963fbf03535080ad24a4b31381c298
prerequisite-patch-id: e0b1ca15da78cb7c2acf58c6649cc26a2901ca28
prerequisite-patch-id: 8cc20810597925a8a0e52f7ed58e821c035244bf
prerequisite-patch-id: 4338a1728052ff14c029330de8f5efa65a69b3aa
prerequisite-patch-id: 198fd889e6f81ff249e56dd1a099cdf2527aef1f
prerequisite-patch-id: 9a6bef3b3dcf639f83b1255e639c99fb71f19008
prerequisite-patch-id: 57ccbadda2f33f6883289444ed7a3dbefaa9687d
prerequisite-patch-id: 9fa098d9e2757f54a616d1e7568a19f29d638d7a
prerequisite-patch-id: ef328feb7636c96629f030601b9ee950b4d62a42
prerequisite-patch-id: f9e70cc31c525d4344fc9e6e54ff2e1e3f5d80d0
prerequisite-patch-id: 9f1a026d73ac5fe39f8799915cf013843bd216aa
prerequisite-patch-id: 692b78c72fbe969fa8903982ebd6da61bd598550
prerequisite-patch-id: 2acccc54dd0fdeee252ba8eafbc16dd9a5cab0c1
--
Regards,
Laurent Pinchart
^ permalink raw reply [flat|nested] 115+ messages in thread
* [PATCH 01/72] dt-bindings: media: Deprecate clock-frequency property for camera sensors
2025-07-10 17:46 [PATCH 00/72] media: i2c: Reduce cargo-cult Laurent Pinchart
@ 2025-07-10 17:46 ` Laurent Pinchart
2025-07-10 23:10 ` Rob Herring (Arm)
2025-07-10 17:46 ` [PATCH 02/72] dt-bindings: media: et8ek8: Deprecate clock-frequency property Laurent Pinchart
` (72 subsequent siblings)
73 siblings, 1 reply; 115+ messages in thread
From: Laurent Pinchart @ 2025-07-10 17:46 UTC (permalink / raw)
To: linux-media
Cc: Sakari Ailus, Mehdi Djait, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Manivannan Sadhasivam, Dongchun Zhu, Lad Prabhakar,
Todor Tomov, devicetree
Usage of the clock-frequency property for camera sensors is discouraged
in favour of using assigned-clock-rates (and assigned-clock-parents
where needed). Mark the property as deprecated.
Update the examples accordingly. In DT examples where the sensor input
clock appears to come from a programmable clock generator, replace
clock-frequency by the assigned-clocks and assigned-clock-rates
properties. Otherwise, just drop clock-frequency.
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
Documentation/devicetree/bindings/media/i2c/mipi-ccs.yaml | 7 +++++--
.../devicetree/bindings/media/i2c/ovti,ov02a10.yaml | 3 +--
.../devicetree/bindings/media/i2c/ovti,ov5645.yaml | 6 +++++-
.../devicetree/bindings/media/i2c/ovti,ov7251.yaml | 6 +++++-
.../devicetree/bindings/media/i2c/ovti,ov8856.yaml | 3 +--
.../devicetree/bindings/media/i2c/samsung,s5k5baf.yaml | 6 +++++-
.../devicetree/bindings/media/i2c/samsung,s5k6a3.yaml | 6 +++++-
.../devicetree/bindings/media/i2c/sony,imx290.yaml | 5 +++--
8 files changed, 30 insertions(+), 12 deletions(-)
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,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,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,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,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>;
--
Regards,
Laurent Pinchart
^ permalink raw reply related [flat|nested] 115+ messages in thread
* [PATCH 02/72] dt-bindings: media: et8ek8: Deprecate clock-frequency property
2025-07-10 17:46 [PATCH 00/72] media: i2c: Reduce cargo-cult Laurent Pinchart
2025-07-10 17:46 ` [PATCH 01/72] dt-bindings: media: Deprecate clock-frequency property for camera sensors Laurent Pinchart
@ 2025-07-10 17:46 ` Laurent Pinchart
2025-07-10 23:11 ` Rob Herring (Arm)
2025-07-10 17:46 ` [PATCH 03/72] dt-bindings: media: imx258: Make clocks property required Laurent Pinchart
` (71 subsequent siblings)
73 siblings, 1 reply; 115+ messages in thread
From: Laurent Pinchart @ 2025-07-10 17:46 UTC (permalink / raw)
To: linux-media
Cc: Sakari Ailus, Mehdi Djait, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, devicetree
Usage of the clock-frequency property for camera sensors is discouraged
in favour of using assigned-clock-rates (and assigned-clock-parents
where needed). Drop the property, and update the example accordingly.
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
.../devicetree/bindings/media/i2c/toshiba,et8ek8.txt | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
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 {
--
Regards,
Laurent Pinchart
^ permalink raw reply related [flat|nested] 115+ messages in thread
* [PATCH 03/72] dt-bindings: media: imx258: Make clocks property required
2025-07-10 17:46 [PATCH 00/72] media: i2c: Reduce cargo-cult Laurent Pinchart
2025-07-10 17:46 ` [PATCH 01/72] dt-bindings: media: Deprecate clock-frequency property for camera sensors Laurent Pinchart
2025-07-10 17:46 ` [PATCH 02/72] dt-bindings: media: et8ek8: Deprecate clock-frequency property Laurent Pinchart
@ 2025-07-10 17:46 ` Laurent Pinchart
2025-07-10 23:11 ` Rob Herring (Arm)
2025-07-10 17:47 ` [PATCH 04/72] dt-bindings: media: imx274: " Laurent Pinchart
` (70 subsequent siblings)
73 siblings, 1 reply; 115+ messages in thread
From: Laurent Pinchart @ 2025-07-10 17:46 UTC (permalink / raw)
To: linux-media
Cc: Sakari Ailus, Mehdi Djait, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, devicetree
The sensor requires an external clock, and drivers need to access the
clock to retrieve its frequency in order to configure the sensor. This
makes usage of the clocks property mandatory for a system to work
properly. Mark the property as required.
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
Documentation/devicetree/bindings/media/i2c/sony,imx258.yaml | 1 +
1 file changed, 1 insertion(+)
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
--
Regards,
Laurent Pinchart
^ permalink raw reply related [flat|nested] 115+ messages in thread
* [PATCH 04/72] dt-bindings: media: imx274: Make clocks property required
2025-07-10 17:46 [PATCH 00/72] media: i2c: Reduce cargo-cult Laurent Pinchart
` (2 preceding siblings ...)
2025-07-10 17:46 ` [PATCH 03/72] dt-bindings: media: imx258: Make clocks property required Laurent Pinchart
@ 2025-07-10 17:47 ` Laurent Pinchart
2025-07-10 19:37 ` Rob Herring (Arm)
2025-07-10 17:47 ` [PATCH 05/72] ARM: dts: nxp: imx6qdl-pico: Replace clock-frequency in camera sensor node Laurent Pinchart
` (69 subsequent siblings)
73 siblings, 1 reply; 115+ messages in thread
From: Laurent Pinchart @ 2025-07-10 17:47 UTC (permalink / raw)
To: linux-media
Cc: Sakari Ailus, Mehdi Djait, Leon Luo, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, devicetree
The sensor requires an external clock, and drivers need to access the
clock to retrieve its frequency in order to configure the sensor. This
makes usage of the clocks property mandatory for a system to work
properly. Mark the clocks and clock-names properties as required, and
update the example accordingly.
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
Documentation/devicetree/bindings/media/i2c/sony,imx274.yaml | 4 ++++
1 file changed, 4 insertions(+)
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 {
--
Regards,
Laurent Pinchart
^ permalink raw reply related [flat|nested] 115+ messages in thread
* [PATCH 05/72] ARM: dts: nxp: imx6qdl-pico: Replace clock-frequency in camera sensor node
2025-07-10 17:46 [PATCH 00/72] media: i2c: Reduce cargo-cult Laurent Pinchart
` (3 preceding siblings ...)
2025-07-10 17:47 ` [PATCH 04/72] dt-bindings: media: imx274: " Laurent Pinchart
@ 2025-07-10 17:47 ` Laurent Pinchart
2025-07-10 20:19 ` Frank Li
2025-07-10 17:47 ` [PATCH 06/72] ARM: dts: nxp: imx6qdl-wandboard: " Laurent Pinchart
` (68 subsequent siblings)
73 siblings, 1 reply; 115+ messages in thread
From: Laurent Pinchart @ 2025-07-10 17:47 UTC (permalink / raw)
To: linux-media
Cc: Sakari Ailus, Mehdi Djait, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Shawn Guo, Sascha Hauer, Pengutronix Kernel Team,
Fabio Estevam, devicetree, imx, linux-arm-kernel
The clock-frequency for camera sensors has been deprecated in favour of
the assigned-clocks and assigned-clock-rates properties. Replace it in
the device tree.
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
arch/arm/boot/dts/nxp/imx/imx6qdl-pico.dtsi | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/arch/arm/boot/dts/nxp/imx/imx6qdl-pico.dtsi b/arch/arm/boot/dts/nxp/imx/imx6qdl-pico.dtsi
index c39a9ebdaba1..7821404687f4 100644
--- a/arch/arm/boot/dts/nxp/imx/imx6qdl-pico.dtsi
+++ b/arch/arm/boot/dts/nxp/imx/imx6qdl-pico.dtsi
@@ -232,8 +232,11 @@ camera@3c {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_ov5645>;
reg = <0x3c>;
+
clocks = <&clks IMX6QDL_CLK_CKO2>;
- clock-frequency = <24000000>;
+ assigned-clocks = <&clks IMX6QDL_CLK_CKO2>;
+ assigned-clock-rates = <24000000>;
+
vdddo-supply = <®_1p8v>;
vdda-supply = <®_2p8v>;
vddd-supply = <®_1p5v>;
--
Regards,
Laurent Pinchart
^ permalink raw reply related [flat|nested] 115+ messages in thread
* [PATCH 06/72] ARM: dts: nxp: imx6qdl-wandboard: Replace clock-frequency in camera sensor node
2025-07-10 17:46 [PATCH 00/72] media: i2c: Reduce cargo-cult Laurent Pinchart
` (4 preceding siblings ...)
2025-07-10 17:47 ` [PATCH 05/72] ARM: dts: nxp: imx6qdl-pico: Replace clock-frequency in camera sensor node Laurent Pinchart
@ 2025-07-10 17:47 ` Laurent Pinchart
2025-07-10 20:18 ` Frank Li
2025-07-10 17:47 ` [PATCH 07/72] ARM: dts: samsung: exynos4210-i9100: " Laurent Pinchart
` (67 subsequent siblings)
73 siblings, 1 reply; 115+ messages in thread
From: Laurent Pinchart @ 2025-07-10 17:47 UTC (permalink / raw)
To: linux-media
Cc: Sakari Ailus, Mehdi Djait, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Shawn Guo, Sascha Hauer, Pengutronix Kernel Team,
Fabio Estevam, devicetree, imx, linux-arm-kernel
The clock-frequency for camera sensors has been deprecated in favour of
the assigned-clocks and assigned-clock-rates properties. Replace it in
the device tree.
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
arch/arm/boot/dts/nxp/imx/imx6qdl-wandboard.dtsi | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/arch/arm/boot/dts/nxp/imx/imx6qdl-wandboard.dtsi b/arch/arm/boot/dts/nxp/imx/imx6qdl-wandboard.dtsi
index 26489eccd5fb..e5ac78ffb31c 100644
--- a/arch/arm/boot/dts/nxp/imx/imx6qdl-wandboard.dtsi
+++ b/arch/arm/boot/dts/nxp/imx/imx6qdl-wandboard.dtsi
@@ -136,8 +136,11 @@ camera@3c {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_ov5645>;
reg = <0x3c>;
+
clocks = <&clks IMX6QDL_CLK_CKO2>;
- clock-frequency = <24000000>;
+ assigned-clocks = <&clks IMX6QDL_CLK_CKO2>;
+ assigned-clock-rates = <24000000>;
+
vdddo-supply = <®_1p8v>;
vdda-supply = <®_2p8v>;
vddd-supply = <®_1p5v>;
--
Regards,
Laurent Pinchart
^ permalink raw reply related [flat|nested] 115+ messages in thread
* [PATCH 07/72] ARM: dts: samsung: exynos4210-i9100: Replace clock-frequency in camera sensor node
2025-07-10 17:46 [PATCH 00/72] media: i2c: Reduce cargo-cult Laurent Pinchart
` (5 preceding siblings ...)
2025-07-10 17:47 ` [PATCH 06/72] ARM: dts: nxp: imx6qdl-wandboard: " Laurent Pinchart
@ 2025-07-10 17:47 ` Laurent Pinchart
2025-07-10 17:47 ` [PATCH 08/72] ARM: dts: samsung: exynos4412-midas: " Laurent Pinchart
` (66 subsequent siblings)
73 siblings, 0 replies; 115+ messages in thread
From: Laurent Pinchart @ 2025-07-10 17:47 UTC (permalink / raw)
To: linux-media
Cc: Sakari Ailus, Mehdi Djait, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Alim Akhtar, devicetree, linux-arm-kernel,
linux-samsung-soc
The clock-frequency for camera sensors has been deprecated in favour of
the assigned-clocks and assigned-clock-rates properties. Replace it in
the device tree.
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
arch/arm/boot/dts/samsung/exynos4210-i9100.dts | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/arch/arm/boot/dts/samsung/exynos4210-i9100.dts b/arch/arm/boot/dts/samsung/exynos4210-i9100.dts
index 0d8495792a70..cdc768a87757 100644
--- a/arch/arm/boot/dts/samsung/exynos4210-i9100.dts
+++ b/arch/arm/boot/dts/samsung/exynos4210-i9100.dts
@@ -169,11 +169,14 @@ image-sensor@2d {
vdda-supply = <&cam_io_en_reg>;
vddreg-supply = <&vt_core_15v_reg>;
vddio-supply = <&vtcam_reg>;
+
clocks = <&camera 0>;
clock-names = "mclk";
+ assigned-clocks = <&camera 0>;
+ assigned-clock-rates = <24000000>;
+
stbyn-gpios = <&gpl2 0 GPIO_ACTIVE_LOW>;
rstn-gpios = <&gpl2 1 GPIO_ACTIVE_LOW>;
- clock-frequency = <24000000>;
port {
s5k5bafx_ep: endpoint {
--
Regards,
Laurent Pinchart
^ permalink raw reply related [flat|nested] 115+ messages in thread
* [PATCH 08/72] ARM: dts: samsung: exynos4412-midas: Replace clock-frequency in camera sensor node
2025-07-10 17:46 [PATCH 00/72] media: i2c: Reduce cargo-cult Laurent Pinchart
` (6 preceding siblings ...)
2025-07-10 17:47 ` [PATCH 07/72] ARM: dts: samsung: exynos4210-i9100: " Laurent Pinchart
@ 2025-07-10 17:47 ` Laurent Pinchart
2025-07-10 17:47 ` [PATCH 09/72] ARM: dts: ti: omap3-n900: " Laurent Pinchart
` (65 subsequent siblings)
73 siblings, 0 replies; 115+ messages in thread
From: Laurent Pinchart @ 2025-07-10 17:47 UTC (permalink / raw)
To: linux-media
Cc: Sakari Ailus, Mehdi Djait, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Alim Akhtar, devicetree, linux-arm-kernel,
linux-samsung-soc
The clock-frequency for camera sensors has been deprecated in favour of
the assigned-clocks and assigned-clock-rates properties. Replace it in
the device tree.
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
arch/arm/boot/dts/samsung/exynos4412-midas.dtsi | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/arch/arm/boot/dts/samsung/exynos4412-midas.dtsi b/arch/arm/boot/dts/samsung/exynos4412-midas.dtsi
index 3d5aace668dc..06eaf351fa3a 100644
--- a/arch/arm/boot/dts/samsung/exynos4412-midas.dtsi
+++ b/arch/arm/boot/dts/samsung/exynos4412-midas.dtsi
@@ -638,10 +638,13 @@ image-sensor@10 {
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 {
--
Regards,
Laurent Pinchart
^ permalink raw reply related [flat|nested] 115+ messages in thread
* [PATCH 09/72] ARM: dts: ti: omap3-n900: Replace clock-frequency in camera sensor node
2025-07-10 17:46 [PATCH 00/72] media: i2c: Reduce cargo-cult Laurent Pinchart
` (7 preceding siblings ...)
2025-07-10 17:47 ` [PATCH 08/72] ARM: dts: samsung: exynos4412-midas: " Laurent Pinchart
@ 2025-07-10 17:47 ` Laurent Pinchart
2025-07-10 17:47 ` [PATCH 10/72] ARM: dts: ti: omap3-n950: " Laurent Pinchart
` (64 subsequent siblings)
73 siblings, 0 replies; 115+ messages in thread
From: Laurent Pinchart @ 2025-07-10 17:47 UTC (permalink / raw)
To: linux-media
Cc: Sakari Ailus, Mehdi Djait, Tony Lindgren, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, linux-omap, devicetree
The clock-frequency for camera sensors has been deprecated in favour of
the assigned-clocks and assigned-clock-rates properties. Replace it in
the device tree.
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
arch/arm/boot/dts/ti/omap/omap3-n900.dts | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/arch/arm/boot/dts/ti/omap/omap3-n900.dts b/arch/arm/boot/dts/ti/omap/omap3-n900.dts
index c50ca572d1b9..0d4ceaf96f66 100644
--- a/arch/arm/boot/dts/ti/omap/omap3-n900.dts
+++ b/arch/arm/boot/dts/ti/omap/omap3-n900.dts
@@ -792,7 +792,8 @@ cam1: camera@3e {
clocks = <&isp 0>;
clock-names = "extclk";
- clock-frequency = <9600000>;
+ assigned-clocks = <&isp 0>;
+ assigned-clock-rates = <9600000>;
reset-gpio = <&gpio4 6 GPIO_ACTIVE_HIGH>; /* 102 */
--
Regards,
Laurent Pinchart
^ permalink raw reply related [flat|nested] 115+ messages in thread
* [PATCH 10/72] ARM: dts: ti: omap3-n950: Replace clock-frequency in camera sensor node
2025-07-10 17:46 [PATCH 00/72] media: i2c: Reduce cargo-cult Laurent Pinchart
` (8 preceding siblings ...)
2025-07-10 17:47 ` [PATCH 09/72] ARM: dts: ti: omap3-n900: " Laurent Pinchart
@ 2025-07-10 17:47 ` Laurent Pinchart
2025-07-10 17:47 ` [PATCH 11/72] ARM: dts: ti: omap3-n9: " Laurent Pinchart
` (63 subsequent siblings)
73 siblings, 0 replies; 115+ messages in thread
From: Laurent Pinchart @ 2025-07-10 17:47 UTC (permalink / raw)
To: linux-media
Cc: Sakari Ailus, Mehdi Djait, Tony Lindgren, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, linux-omap, devicetree
The clock-frequency for camera sensors has been deprecated in favour of
the assigned-clocks and assigned-clock-rates properties. Replace it in
the device tree.
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
arch/arm/boot/dts/ti/omap/omap3-n950.dts | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/arch/arm/boot/dts/ti/omap/omap3-n950.dts b/arch/arm/boot/dts/ti/omap/omap3-n950.dts
index b99f97880204..2864ed8dd6c3 100644
--- a/arch/arm/boot/dts/ti/omap/omap3-n950.dts
+++ b/arch/arm/boot/dts/ti/omap/omap3-n950.dts
@@ -74,8 +74,11 @@ smia_1: camera@10 {
reg = <0x10>;
/* No reset gpio */
vana-supply = <&vaux3>;
+
clocks = <&isp 0>;
- clock-frequency = <9600000>;
+ assigned-clocks = <&isp 0>;
+ assigned-clock-rates = <9600000>;
+
flash-leds = <&as3645a_flash &as3645a_indicator>;
port {
smia_1_1: endpoint {
--
Regards,
Laurent Pinchart
^ permalink raw reply related [flat|nested] 115+ messages in thread
* [PATCH 11/72] ARM: dts: ti: omap3-n9: Replace clock-frequency in camera sensor node
2025-07-10 17:46 [PATCH 00/72] media: i2c: Reduce cargo-cult Laurent Pinchart
` (9 preceding siblings ...)
2025-07-10 17:47 ` [PATCH 10/72] ARM: dts: ti: omap3-n950: " Laurent Pinchart
@ 2025-07-10 17:47 ` Laurent Pinchart
2025-07-10 17:47 ` [PATCH 12/72] arm64: dts: qcom: sdm845-db845c-navigation-mezzanine: " Laurent Pinchart
` (62 subsequent siblings)
73 siblings, 0 replies; 115+ messages in thread
From: Laurent Pinchart @ 2025-07-10 17:47 UTC (permalink / raw)
To: linux-media
Cc: Sakari Ailus, Mehdi Djait, Tony Lindgren, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, linux-omap, devicetree
The clock-frequency for camera sensors has been deprecated in favour of
the assigned-clocks and assigned-clock-rates properties. Replace it in
the device tree.
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
arch/arm/boot/dts/ti/omap/omap3-n9.dts | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/arch/arm/boot/dts/ti/omap/omap3-n9.dts b/arch/arm/boot/dts/ti/omap/omap3-n9.dts
index a3cf3f443785..2edc1933449b 100644
--- a/arch/arm/boot/dts/ti/omap/omap3-n9.dts
+++ b/arch/arm/boot/dts/ti/omap/omap3-n9.dts
@@ -21,8 +21,11 @@ smia_1: camera@10 {
reg = <0x10>;
/* No reset gpio */
vana-supply = <&vaux3>;
+
clocks = <&isp 0>;
- clock-frequency = <9600000>;
+ assigned-clocks = <&isp 0>;
+ assigned-clock-rates = <9600000>;
+
flash-leds = <&as3645a_flash &as3645a_indicator>;
port {
smia_1_1: endpoint {
--
Regards,
Laurent Pinchart
^ permalink raw reply related [flat|nested] 115+ messages in thread
* [PATCH 12/72] arm64: dts: qcom: sdm845-db845c-navigation-mezzanine: Replace clock-frequency in camera sensor node
2025-07-10 17:46 [PATCH 00/72] media: i2c: Reduce cargo-cult Laurent Pinchart
` (10 preceding siblings ...)
2025-07-10 17:47 ` [PATCH 11/72] ARM: dts: ti: omap3-n9: " Laurent Pinchart
@ 2025-07-10 17:47 ` Laurent Pinchart
2025-07-11 12:25 ` Konrad Dybcio
2025-07-10 17:47 ` [PATCH 13/72] arm64: dts: renesas: aistarvision-mipi-adapter-2.1: Drop clock-frequency from " Laurent Pinchart
` (61 subsequent siblings)
73 siblings, 1 reply; 115+ messages in thread
From: Laurent Pinchart @ 2025-07-10 17:47 UTC (permalink / raw)
To: linux-media
Cc: Sakari Ailus, Mehdi Djait, Bjorn Andersson, Konrad Dybcio,
Rob Herring, Krzysztof Kozlowski, Conor Dooley, linux-arm-msm,
devicetree
The clock-frequency for camera sensors has been deprecated in favour of
the assigned-clocks and assigned-clock-rates properties. Replace it in
the device tree.
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
.../boot/dts/qcom/sdm845-db845c-navigation-mezzanine.dtso | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/arch/arm64/boot/dts/qcom/sdm845-db845c-navigation-mezzanine.dtso b/arch/arm64/boot/dts/qcom/sdm845-db845c-navigation-mezzanine.dtso
index 51f1a4883ab8..dbe1911d8e47 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-db845c-navigation-mezzanine.dtso
+++ b/arch/arm64/boot/dts/qcom/sdm845-db845c-navigation-mezzanine.dtso
@@ -44,7 +44,8 @@ camera@10 {
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>;
/*
* The &vreg_s4a_1p8 trace is powered on as a,
--
Regards,
Laurent Pinchart
^ permalink raw reply related [flat|nested] 115+ messages in thread
* [PATCH 13/72] arm64: dts: renesas: aistarvision-mipi-adapter-2.1: Drop clock-frequency from camera sensor node
2025-07-10 17:46 [PATCH 00/72] media: i2c: Reduce cargo-cult Laurent Pinchart
` (11 preceding siblings ...)
2025-07-10 17:47 ` [PATCH 12/72] arm64: dts: qcom: sdm845-db845c-navigation-mezzanine: " Laurent Pinchart
@ 2025-07-10 17:47 ` Laurent Pinchart
2025-07-28 14:19 ` Geert Uytterhoeven
2025-07-10 17:47 ` [PATCH 14/72] arm64: dts: renesas: rzg2l-smarc: " Laurent Pinchart
` (60 subsequent siblings)
73 siblings, 1 reply; 115+ messages in thread
From: Laurent Pinchart @ 2025-07-10 17:47 UTC (permalink / raw)
To: linux-media
Cc: Sakari Ailus, Mehdi Djait, Geert Uytterhoeven, Magnus Damm,
Rob Herring, Krzysztof Kozlowski, Conor Dooley, linux-renesas-soc,
devicetree
The clock-frequency for camera sensors has been deprecated in favour of
the assigned-clocks and assigned-clock-rates properties. As the clock
source for the sensor is a fixed-frequency oscillator, simply drop the
clock-frequency.
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
arch/arm64/boot/dts/renesas/aistarvision-mipi-adapter-2.1.dtsi | 1 -
1 file changed, 1 deletion(-)
diff --git a/arch/arm64/boot/dts/renesas/aistarvision-mipi-adapter-2.1.dtsi b/arch/arm64/boot/dts/renesas/aistarvision-mipi-adapter-2.1.dtsi
index 7cb5c958aece..529388f6bf2b 100644
--- a/arch/arm64/boot/dts/renesas/aistarvision-mipi-adapter-2.1.dtsi
+++ b/arch/arm64/boot/dts/renesas/aistarvision-mipi-adapter-2.1.dtsi
@@ -66,7 +66,6 @@ ov5645: ov5645@3c {
compatible = "ovti,ov5645";
reg = <0x3c>;
clocks = <&osc25250_clk>;
- clock-frequency = <24000000>;
vdddo-supply = <&ov5645_vdddo_1v8>;
vdda-supply = <&ov5645_vdda_2v8>;
vddd-supply = <&ov5645_vddd_1v5>;
--
Regards,
Laurent Pinchart
^ permalink raw reply related [flat|nested] 115+ messages in thread
* [PATCH 14/72] arm64: dts: renesas: rzg2l-smarc: Drop clock-frequency from camera sensor node
2025-07-10 17:46 [PATCH 00/72] media: i2c: Reduce cargo-cult Laurent Pinchart
` (12 preceding siblings ...)
2025-07-10 17:47 ` [PATCH 13/72] arm64: dts: renesas: aistarvision-mipi-adapter-2.1: Drop clock-frequency from " Laurent Pinchart
@ 2025-07-10 17:47 ` Laurent Pinchart
2025-07-28 14:20 ` Geert Uytterhoeven
2025-07-10 17:47 ` [PATCH 15/72] media: i2c: mt9v022: Drop unused mt9v022.h header Laurent Pinchart
` (59 subsequent siblings)
73 siblings, 1 reply; 115+ messages in thread
From: Laurent Pinchart @ 2025-07-10 17:47 UTC (permalink / raw)
To: linux-media
Cc: Sakari Ailus, Mehdi Djait, Geert Uytterhoeven, Magnus Damm,
Rob Herring, Krzysztof Kozlowski, Conor Dooley, linux-renesas-soc,
devicetree
The clock-frequency for camera sensors has been deprecated in favour of
the assigned-clocks and assigned-clock-rates properties. As the clock
source for the sensor is a fixed-frequency oscillator, simply drop the
clock-frequency.
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
arch/arm64/boot/dts/renesas/rz-smarc-cru-csi-ov5645.dtsi | 1 -
1 file changed, 1 deletion(-)
diff --git a/arch/arm64/boot/dts/renesas/rz-smarc-cru-csi-ov5645.dtsi b/arch/arm64/boot/dts/renesas/rz-smarc-cru-csi-ov5645.dtsi
index c5bb63c63b47..4d2b0655859a 100644
--- a/arch/arm64/boot/dts/renesas/rz-smarc-cru-csi-ov5645.dtsi
+++ b/arch/arm64/boot/dts/renesas/rz-smarc-cru-csi-ov5645.dtsi
@@ -64,7 +64,6 @@ ov5645: camera@3c {
compatible = "ovti,ov5645";
reg = <0x3c>;
clocks = <&ov5645_fixed_clk>;
- clock-frequency = <24000000>;
vdddo-supply = <&ov5645_vdddo_1v8>;
vdda-supply = <&ov5645_vdda_2v8>;
vddd-supply = <&ov5645_vddd_1v5>;
--
Regards,
Laurent Pinchart
^ permalink raw reply related [flat|nested] 115+ messages in thread
* [PATCH 15/72] media: i2c: mt9v022: Drop unused mt9v022.h header
2025-07-10 17:46 [PATCH 00/72] media: i2c: Reduce cargo-cult Laurent Pinchart
` (13 preceding siblings ...)
2025-07-10 17:47 ` [PATCH 14/72] arm64: dts: renesas: rzg2l-smarc: " Laurent Pinchart
@ 2025-07-10 17:47 ` Laurent Pinchart
2025-07-10 17:47 ` [PATCH 16/72] media: i2c: mt9v032: Replace client->dev usage Laurent Pinchart
` (58 subsequent siblings)
73 siblings, 0 replies; 115+ messages in thread
From: Laurent Pinchart @ 2025-07-10 17:47 UTC (permalink / raw)
To: linux-media; +Cc: Sakari Ailus, Mehdi Djait
The mt9v022 driver got removed in commit e7eab49132ba ("media:
staging/media/soc_camera: remove this driver"), but its platform header
file got left behind. Remove it.
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
include/media/i2c/mt9v022.h | 13 -------------
1 file changed, 13 deletions(-)
delete mode 100644 include/media/i2c/mt9v022.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
--
Regards,
Laurent Pinchart
^ permalink raw reply related [flat|nested] 115+ messages in thread
* [PATCH 16/72] media: i2c: mt9v032: Replace client->dev usage
2025-07-10 17:46 [PATCH 00/72] media: i2c: Reduce cargo-cult Laurent Pinchart
` (14 preceding siblings ...)
2025-07-10 17:47 ` [PATCH 15/72] media: i2c: mt9v022: Drop unused mt9v022.h header Laurent Pinchart
@ 2025-07-10 17:47 ` Laurent Pinchart
2025-07-10 17:47 ` [PATCH 17/72] media: i2c: mt9v032: Drop support for platform data Laurent Pinchart
` (57 subsequent siblings)
73 siblings, 0 replies; 115+ messages in thread
From: Laurent Pinchart @ 2025-07-10 17:47 UTC (permalink / raw)
To: linux-media; +Cc: Sakari Ailus, Mehdi Djait
The driver needs to access the struct device in many places, and
retrieves it from the i2c_client itself retrieved with
v4l2_get_subdevdata(). Store it as a pointer in struct mt9v032 and
access it from there instead, to simplify the driver.
While at it, fix mistakes in the sort order of include statements.
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
drivers/media/i2c/mt9v032.c | 52 +++++++++++++++++++------------------
1 file changed, 27 insertions(+), 25 deletions(-)
diff --git a/drivers/media/i2c/mt9v032.c b/drivers/media/i2c/mt9v032.c
index 9f4b4cb9853e..888f3280378d 100644
--- a/drivers/media/i2c/mt9v032.c
+++ b/drivers/media/i2c/mt9v032.c
@@ -15,14 +15,14 @@
#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>
@@ -183,6 +183,8 @@ static const struct mt9v032_model_version mt9v032_versions[] = {
};
struct mt9v032 {
+ struct device *dev;
+
struct v4l2_subdev subdev;
struct media_pad pad;
@@ -473,13 +475,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)
@@ -883,12 +884,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 +899,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 +911,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,25 +996,24 @@ 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 struct mt9v032_platform_data *mt9v032_get_pdata(struct mt9v032 *mt9v032)
{
struct mt9v032_platform_data *pdata = NULL;
struct v4l2_fwnode_endpoint endpoint = { .bus_type = 0 };
struct device_node *np;
struct property *prop;
- if (!IS_ENABLED(CONFIG_OF) || !client->dev.of_node)
- return client->dev.platform_data;
+ if (!IS_ENABLED(CONFIG_OF) || !mt9v032->dev->of_node)
+ return mt9v032->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;
if (v4l2_fwnode_endpoint_parse(of_fwnode_handle(np), &endpoint) < 0)
goto done;
- pdata = devm_kzalloc(&client->dev, sizeof(*pdata), GFP_KERNEL);
+ pdata = devm_kzalloc(mt9v032->dev, sizeof(*pdata), GFP_KERNEL);
if (!pdata)
goto done;
@@ -1022,7 +1022,7 @@ mt9v032_get_pdata(struct i2c_client *client)
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;
@@ -1045,7 +1045,6 @@ mt9v032_get_pdata(struct i2c_client *client)
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 +1053,29 @@ 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_v4l2_sensor_clk_get(&client->dev, NULL);
+ mt9v032->clk = devm_v4l2_sensor_clk_get(mt9v032->dev, NULL);
if (IS_ERR(mt9v032->clk))
- return dev_err_probe(&client->dev, 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->pdata = mt9v032_get_pdata(mt9v032);
mt9v032->model = i2c_get_match_data(client);
v4l2_ctrl_handler_init(&mt9v032->ctrls, 11 +
@@ -1120,7 +1121,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 && mt9v032->pdata->link_freqs) {
+ const struct mt9v032_platform_data *pdata = mt9v032->pdata;
unsigned int def = 0;
for (i = 0; pdata->link_freqs[i]; ++i) {
@@ -1140,7 +1142,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;
@@ -1178,7 +1180,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;
--
Regards,
Laurent Pinchart
^ permalink raw reply related [flat|nested] 115+ messages in thread
* [PATCH 17/72] media: i2c: mt9v032: Drop support for platform data
2025-07-10 17:46 [PATCH 00/72] media: i2c: Reduce cargo-cult Laurent Pinchart
` (15 preceding siblings ...)
2025-07-10 17:47 ` [PATCH 16/72] media: i2c: mt9v032: Replace client->dev usage Laurent Pinchart
@ 2025-07-10 17:47 ` Laurent Pinchart
2025-07-10 17:47 ` [PATCH 18/72] media: i2c: mt9v111: Do not set clock rate manually Laurent Pinchart
` (56 subsequent siblings)
73 siblings, 0 replies; 115+ messages in thread
From: Laurent Pinchart @ 2025-07-10 17:47 UTC (permalink / raw)
To: linux-media
Cc: Sakari Ailus, Mehdi Djait, Hans Verkuil, Hans de Goede,
André Apitzsch, Matthias Fend, Tarang Raval, Dongcheng Yan,
Sylvain Petinot, Benjamin Mugnier, Jingjing Xiong
The last user of the mt9v032 driver through board files and platform
data has long been removed. Drop support for platform data from the
driver.
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
MAINTAINERS | 1 -
drivers/media/i2c/Kconfig | 1 +
drivers/media/i2c/mt9v032.c | 66 +++++++++++++++----------------------
include/media/i2c/mt9v032.h | 12 -------
4 files changed, 28 insertions(+), 52 deletions(-)
delete mode 100644 include/media/i2c/mt9v032.h
diff --git a/MAINTAINERS b/MAINTAINERS
index 1ef99240a57e..2c9924b83a86 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -16980,7 +16980,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>
diff --git a/drivers/media/i2c/Kconfig b/drivers/media/i2c/Kconfig
index 6237fe804a5c..13859ab21d2c 100644
--- a/drivers/media/i2c/Kconfig
+++ b/drivers/media/i2c/Kconfig
@@ -317,6 +317,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
diff --git a/drivers/media/i2c/mt9v032.c b/drivers/media/i2c/mt9v032.c
index 888f3280378d..d4359d5b92bb 100644
--- a/drivers/media/i2c/mt9v032.c
+++ b/drivers/media/i2c/mt9v032.c
@@ -24,7 +24,6 @@
#include <linux/v4l2-mediabus.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,6 +181,13 @@ 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;
@@ -207,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;
@@ -332,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)
@@ -683,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;
@@ -996,26 +1002,19 @@ static const struct regmap_config mt9v032_regmap_config = {
* Driver initialization and probing
*/
-static struct mt9v032_platform_data *mt9v032_get_pdata(struct mt9v032 *mt9v032)
+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) || !mt9v032->dev->of_node)
- return mt9v032->dev->platform_data;
-
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(mt9v032->dev, sizeof(*pdata), GFP_KERNEL);
- if (!pdata)
- goto done;
+ return -EINVAL;
prop = of_find_property(np, "link-frequencies", NULL);
if (prop) {
@@ -1025,11 +1024,11 @@ static struct mt9v032_platform_data *mt9v032_get_pdata(struct mt9v032 *mt9v032)
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,9 +1037,7 @@ static struct mt9v032_platform_data *mt9v032_get_pdata(struct mt9v032 *mt9v032)
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)
@@ -1075,8 +1072,13 @@ static int mt9v032_probe(struct i2c_client *client)
return PTR_ERR(mt9v032->standby_gpio);
mutex_init(&mt9v032->power_lock);
- mt9v032->pdata = mt9v032_get_pdata(mt9v032);
- 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));
@@ -1121,8 +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 (mt9v032->pdata && mt9v032->pdata->link_freqs) {
- const struct mt9v032_platform_data *pdata = mt9v032->pdata;
+ 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) {
@@ -1264,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] },
@@ -1297,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/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
--
Regards,
Laurent Pinchart
^ permalink raw reply related [flat|nested] 115+ messages in thread
* [PATCH 18/72] media: i2c: mt9v111: Do not set clock rate manually
2025-07-10 17:46 [PATCH 00/72] media: i2c: Reduce cargo-cult Laurent Pinchart
` (16 preceding siblings ...)
2025-07-10 17:47 ` [PATCH 17/72] media: i2c: mt9v032: Drop support for platform data Laurent Pinchart
@ 2025-07-10 17:47 ` Laurent Pinchart
2025-07-10 17:47 ` [PATCH 19/72] media: i2c: ov6650: Drop unused driver Laurent Pinchart
` (55 subsequent siblings)
73 siblings, 0 replies; 115+ messages in thread
From: Laurent Pinchart @ 2025-07-10 17:47 UTC (permalink / raw)
To: linux-media; +Cc: Sakari Ailus, Mehdi Djait, Jacopo Mondi
The driver retrieves the rate of the external at probe time, and then
reprograms that clock with the same rate when powering on the device.
Setting the clock rate is not needed, drop it.
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
drivers/media/i2c/mt9v111.c | 2 --
1 file changed, 2 deletions(-)
diff --git a/drivers/media/i2c/mt9v111.c b/drivers/media/i2c/mt9v111.c
index 6aa80b504168..cdcdc9896e1e 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);
--
Regards,
Laurent Pinchart
^ permalink raw reply related [flat|nested] 115+ messages in thread
* [PATCH 19/72] media: i2c: ov6650: Drop unused driver
2025-07-10 17:46 [PATCH 00/72] media: i2c: Reduce cargo-cult Laurent Pinchart
` (17 preceding siblings ...)
2025-07-10 17:47 ` [PATCH 18/72] media: i2c: mt9v111: Do not set clock rate manually Laurent Pinchart
@ 2025-07-10 17:47 ` Laurent Pinchart
2025-07-10 17:47 ` [PATCH 20/72] media: i2c: hi556: Replace client->dev usage Laurent Pinchart
` (54 subsequent siblings)
73 siblings, 0 replies; 115+ messages in thread
From: Laurent Pinchart @ 2025-07-10 17:47 UTC (permalink / raw)
To: linux-media
Cc: Sakari Ailus, Mehdi Djait, Hans Verkuil, Hans de Goede,
Ricardo Ribalda, Bryan O'Donoghue, André Apitzsch,
Heimir Thor Sverrisson, Jingjing Xiong, Dongcheng Yan,
Benjamin Mugnier, Sylvain Petinot, Hao Yao
The ov6650 driver was introduced in v2.6.37 to support the OMAP1-based
Amstrad Delta video phone. The platform still has a board file in the
kernel, but support for the camera was dropped in commit ce548396a433
("media: mach-omap1: board-ams-delta.c: remove soc_camera dependencies")
in v5.9. The driver has been unused since as it has received neither
ACPI nor DT support.
The ov6650 driver is one of the last sensor drivers calling
clk_set_rate(). This is deprecated, and calls to the function are being
removed to avoid cargo-cult. As the driver is unlikely to ever be used
again, drop it instead of trying to avoid call clk_set_rate().
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
.../admin-guide/media/i2c-cardlist.rst | 1 -
drivers/media/i2c/Kconfig | 9 -
drivers/media/i2c/Makefile | 1 -
drivers/media/i2c/ov6650.c | 1147 -----------------
4 files changed, 1158 deletions(-)
delete mode 100644 drivers/media/i2c/ov6650.c
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/drivers/media/i2c/Kconfig b/drivers/media/i2c/Kconfig
index 13859ab21d2c..a1a8ef9f35c1 100644
--- a/drivers/media/i2c/Kconfig
+++ b/drivers/media/i2c/Kconfig
@@ -553,15 +553,6 @@ config VIDEO_OV64A40
To compile this driver as a module, choose M here: the
module will be called ov64a40.
-config VIDEO_OV6650
- tristate "OmniVision OV6650 sensor support"
- help
- This is a Video4Linux2 sensor driver for the OmniVision
- OV6650 camera.
-
- To compile this driver as a module, choose M here: the
- module will be called ov6650.
-
config VIDEO_OV7251
tristate "OmniVision OV7251 sensor support"
help
diff --git a/drivers/media/i2c/Makefile b/drivers/media/i2c/Makefile
index 5873d29433ee..59b4b150998b 100644
--- a/drivers/media/i2c/Makefile
+++ b/drivers/media/i2c/Makefile
@@ -104,7 +104,6 @@ obj-$(CONFIG_VIDEO_OV5675) += ov5675.o
obj-$(CONFIG_VIDEO_OV5693) += ov5693.o
obj-$(CONFIG_VIDEO_OV5695) += ov5695.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/ov6650.c b/drivers/media/i2c/ov6650.c
deleted file mode 100644
index 3e37a6436aeb..000000000000
--- a/drivers/media/i2c/ov6650.c
+++ /dev/null
@@ -1,1147 +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_v4l2_sensor_clk_get(&client->dev, NULL);
- if (IS_ERR(priv->clk))
- return dev_err_probe(&client->dev, PTR_ERR(priv->clk),
- "clk request err\n");
-
- 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");
--
Regards,
Laurent Pinchart
^ permalink raw reply related [flat|nested] 115+ messages in thread
* [PATCH 20/72] media: i2c: hi556: Replace client->dev usage
2025-07-10 17:46 [PATCH 00/72] media: i2c: Reduce cargo-cult Laurent Pinchart
` (18 preceding siblings ...)
2025-07-10 17:47 ` [PATCH 19/72] media: i2c: ov6650: Drop unused driver Laurent Pinchart
@ 2025-07-10 17:47 ` Laurent Pinchart
2025-07-10 17:47 ` [PATCH 21/72] media: i2c: hi556: Use V4L2 sensor clock helper Laurent Pinchart
` (53 subsequent siblings)
73 siblings, 0 replies; 115+ messages in thread
From: Laurent Pinchart @ 2025-07-10 17:47 UTC (permalink / raw)
To: linux-media; +Cc: Sakari Ailus, Mehdi Djait
The driver needs to access the struct device in many places, and
retrieves it from the i2c_client itself retrieved with
v4l2_get_subdevdata(). Store it as a pointer in struct hi556 and access
it from there instead, to simplify the driver.
While at it, fix a mistake in the sort order of include statements.
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
drivers/media/i2c/hi556.c | 72 +++++++++++++++++++--------------------
1 file changed, 35 insertions(+), 37 deletions(-)
diff --git a/drivers/media/i2c/hi556.c b/drivers/media/i2c/hi556.c
index 076c19fcf99c..cd7c3e4fd39c 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);
@@ -1289,7 +1285,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);
}
@@ -1347,40 +1343,42 @@ 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_clk_get_optional(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");
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 +1387,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 +1398,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 +1426,7 @@ static int hi556_probe(struct i2c_client *client)
probe_error_power_off:
if (full_power)
- hi556_suspend(&client->dev);
+ hi556_suspend(hi556->dev);
return ret;
}
--
Regards,
Laurent Pinchart
^ permalink raw reply related [flat|nested] 115+ messages in thread
* [PATCH 21/72] media: i2c: hi556: Use V4L2 sensor clock helper
2025-07-10 17:46 [PATCH 00/72] media: i2c: Reduce cargo-cult Laurent Pinchart
` (19 preceding siblings ...)
2025-07-10 17:47 ` [PATCH 20/72] media: i2c: hi556: Replace client->dev usage Laurent Pinchart
@ 2025-07-10 17:47 ` Laurent Pinchart
2025-07-10 17:47 ` [PATCH 22/72] media: i2c: hi847: Replace client->dev usage Laurent Pinchart
` (52 subsequent siblings)
73 siblings, 0 replies; 115+ messages in thread
From: Laurent Pinchart @ 2025-07-10 17:47 UTC (permalink / raw)
To: linux-media; +Cc: Sakari Ailus, Mehdi Djait
Several camera sensor drivers access the "clock-frequency" property
directly to retrieve the external clock rate, or modify the clock rate
of the external clock programmatically. Both behaviours are valid on
a subset of ACPI platforms, but are considered deprecated on OF
platforms, and do not support ACPI platforms that implement MIPI DisCo
for Imaging. Implementing them manually in drivers is deprecated, as
that can encourage cargo-cult and lead to differences in behaviour
between drivers. Instead, drivers should use the
devm_v4l2_sensor_clk_get() helper.
This driver supports ACPI platforms only. It retrieves the clock if
present, and retrieves the clock rate from the "clock-frequency"
property. If the rate does not match the expected rate, the driver fails
probing. This is correct behaviour for ACPI.
Switch to using the devm_v4l2_sensor_clk_get() helper. This does not
change the behaviour on ACPI platforms that specify a clock-frequency
property and don't provide a clock. On ACPI platforms that provide a
clock, the clock rate will be set to the value of the clock-frequency
property. This should not change the behaviour either as this driver
expects the clock to be set to that rate, and wouldn't operate correctly
otherwise.
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
drivers/media/i2c/hi556.c | 22 ++++++++--------------
1 file changed, 8 insertions(+), 14 deletions(-)
diff --git a/drivers/media/i2c/hi556.c b/drivers/media/i2c/hi556.c
index cd7c3e4fd39c..de573cee4451 100644
--- a/drivers/media/i2c/hi556.c
+++ b/drivers/media/i2c/hi556.c
@@ -1213,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;
@@ -1231,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);
@@ -1332,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;
@@ -1353,11 +1341,17 @@ static int hi556_probe(struct i2c_client *client)
return dev_err_probe(hi556->dev, PTR_ERR(hi556->reset_gpio),
"failed to get reset GPIO\n");
- hi556->clk = devm_clk_get_optional(hi556->dev, "clk");
+ hi556->clk = devm_v4l2_sensor_clk_get(hi556->dev, "clk");
if (IS_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];
--
Regards,
Laurent Pinchart
^ permalink raw reply related [flat|nested] 115+ messages in thread
* [PATCH 22/72] media: i2c: hi847: Replace client->dev usage
2025-07-10 17:46 [PATCH 00/72] media: i2c: Reduce cargo-cult Laurent Pinchart
` (20 preceding siblings ...)
2025-07-10 17:47 ` [PATCH 21/72] media: i2c: hi556: Use V4L2 sensor clock helper Laurent Pinchart
@ 2025-07-10 17:47 ` Laurent Pinchart
2025-07-10 17:47 ` [PATCH 23/72] media: i2c: hi847: Use V4L2 sensor clock helper Laurent Pinchart
` (51 subsequent siblings)
73 siblings, 0 replies; 115+ messages in thread
From: Laurent Pinchart @ 2025-07-10 17:47 UTC (permalink / raw)
To: linux-media; +Cc: Sakari Ailus, Mehdi Djait
The driver needs to access the struct device in many places, and
retrieves it from the i2c_client itself retrieved with
v4l2_get_subdevdata(). Store it as a pointer in struct hi847 and access
it from there instead, to simplify the driver.
While at it, fix a mistake in the sort order of include statements.
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
drivers/media/i2c/hi847.c | 58 +++++++++++++++++++--------------------
1 file changed, 28 insertions(+), 30 deletions(-)
diff --git a/drivers/media/i2c/hi847.c b/drivers/media/i2c/hi847.c
index 546833f5b5f5..384ccfc171c2 100644
--- a/drivers/media/i2c/hi847.c
+++ b/drivers/media/i2c/hi847.c
@@ -1,12 +1,13 @@
// SPDX-License-Identifier: GPL-2.0
// Copyright (c) 2022 Intel Corporation.
-#include <linux/unaligned.h>
#include <linux/acpi.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 +2167,8 @@ static const struct hi847_mode supported_modes[] = {
};
struct hi847 {
+ struct device *dev;
+
struct v4l2_subdev sd;
struct media_pad pad;
struct v4l2_ctrl_handler ctrl_handler;
@@ -2244,7 +2247,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 +2255,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 +2410,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 +2425,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 +2467,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 +2558,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 +2565,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 +2587,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 +2596,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 +2624,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 +2765,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 +2774,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;
}
@@ -2862,7 +2858,7 @@ 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);
}
@@ -2875,9 +2871,11 @@ static int hi847_probe(struct i2c_client *client)
if (!hi847)
return -ENOMEM;
- ret = hi847_check_hwcfg(&client->dev);
+ hi847->dev = &client->dev;
+
+ 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 +2883,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 +2891,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 +2902,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;
--
Regards,
Laurent Pinchart
^ permalink raw reply related [flat|nested] 115+ messages in thread
* [PATCH 23/72] media: i2c: hi847: Use V4L2 sensor clock helper
2025-07-10 17:46 [PATCH 00/72] media: i2c: Reduce cargo-cult Laurent Pinchart
` (21 preceding siblings ...)
2025-07-10 17:47 ` [PATCH 22/72] media: i2c: hi847: Replace client->dev usage Laurent Pinchart
@ 2025-07-10 17:47 ` Laurent Pinchart
2025-07-10 17:47 ` [PATCH 24/72] media: i2c: imx208: Replace client->dev usage Laurent Pinchart
` (50 subsequent siblings)
73 siblings, 0 replies; 115+ messages in thread
From: Laurent Pinchart @ 2025-07-10 17:47 UTC (permalink / raw)
To: linux-media; +Cc: Sakari Ailus, Mehdi Djait
Several camera sensor drivers access the "clock-frequency" property
directly to retrieve the external clock rate, or modify the clock rate
of the external clock programmatically. Both behaviours are valid on
a subset of ACPI platforms, but are considered deprecated on OF
platforms, and do not support ACPI platforms that implement MIPI DisCo
for Imaging. Implementing them manually in drivers is deprecated, as
that can encourage cargo-cult and lead to differences in behaviour
between drivers. Instead, drivers should use the
devm_v4l2_sensor_clk_get() helper.
This driver supports ACPI platforms only. It retrieves the clock rate
from the "clock-frequency" property. If the rate does not match the
expected rate, the driver fails probing. This is correct behaviour for
ACPI.
Switch to using the devm_v4l2_sensor_clk_get() helper. This does not
change the behaviour on ACPI platforms that specify a clock-frequency
property and don't provide a clock. On ACPI platforms that provide a
clock, the clock rate will be set to the value of the clock-frequency
property. This should not change the behaviour either as this driver
expects the clock to be set to that rate, and wouldn't operate correctly
otherwise.
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
drivers/media/i2c/hi847.c | 26 ++++++++++++++------------
1 file changed, 14 insertions(+), 12 deletions(-)
diff --git a/drivers/media/i2c/hi847.c b/drivers/media/i2c/hi847.c
index 384ccfc171c2..def01aa07b2f 100644
--- a/drivers/media/i2c/hi847.c
+++ b/drivers/media/i2c/hi847.c
@@ -2,6 +2,7 @@
// Copyright (c) 2022 Intel Corporation.
#include <linux/acpi.h>
+#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/i2c.h>
#include <linux/module.h>
@@ -2168,6 +2169,7 @@ static const struct hi847_mode supported_modes[] = {
struct hi847 {
struct device *dev;
+ struct clk *clk;
struct v4l2_subdev sd;
struct media_pad pad;
@@ -2789,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;
@@ -2865,6 +2855,7 @@ static void hi847_remove(struct i2c_client *client)
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);
@@ -2873,6 +2864,17 @@ static int hi847_probe(struct i2c_client *client)
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(hi847->dev, "failed to get HW configuration: %d",
--
Regards,
Laurent Pinchart
^ permalink raw reply related [flat|nested] 115+ messages in thread
* [PATCH 24/72] media: i2c: imx208: Replace client->dev usage
2025-07-10 17:46 [PATCH 00/72] media: i2c: Reduce cargo-cult Laurent Pinchart
` (22 preceding siblings ...)
2025-07-10 17:47 ` [PATCH 23/72] media: i2c: hi847: Use V4L2 sensor clock helper Laurent Pinchart
@ 2025-07-10 17:47 ` Laurent Pinchart
2025-07-10 17:47 ` [PATCH 25/72] media: i2c: imx208: Use V4L2 sensor clock helper Laurent Pinchart
` (49 subsequent siblings)
73 siblings, 0 replies; 115+ messages in thread
From: Laurent Pinchart @ 2025-07-10 17:47 UTC (permalink / raw)
To: linux-media; +Cc: Sakari Ailus, Mehdi Djait
The driver needs to access the struct device in many places, and
retrieves it from the i2c_client itself retrieved with
v4l2_get_subdevdata(). Store it as a pointer in struct imx208 and access
it from there instead, to simplify the driver.
While at it, fix a mistake in the sort order of include statements.
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
drivers/media/i2c/imx208.c | 68 ++++++++++++++++++--------------------
1 file changed, 33 insertions(+), 35 deletions(-)
diff --git a/drivers/media/i2c/imx208.c b/drivers/media/i2c/imx208.c
index 2b5a6ce7b1ae..5399a2549b3f 100644
--- a/drivers/media/i2c/imx208.c
+++ b/drivers/media/i2c/imx208.c
@@ -6,9 +6,10 @@
#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 +269,8 @@ static const struct imx208_mode supported_modes[] = {
};
struct imx208 {
+ struct device *dev;
+
struct v4l2_subdev sd;
struct media_pad pad;
@@ -372,7 +375,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 +382,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 +433,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 +472,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 +621,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 +630,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 +649,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 +661,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 +669,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 +686,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 +704,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 +724,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 +736,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 +775,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 +802,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 +832,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 +910,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;
}
@@ -954,15 +950,17 @@ static int imx208_probe(struct i2c_client *client)
if (!imx208)
return -ENOMEM;
+ imx208->dev = &client->dev;
+
/* 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 +970,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 +983,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 +991,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 +1025,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);
}
--
Regards,
Laurent Pinchart
^ permalink raw reply related [flat|nested] 115+ messages in thread
* [PATCH 25/72] media: i2c: imx208: Use V4L2 sensor clock helper
2025-07-10 17:46 [PATCH 00/72] media: i2c: Reduce cargo-cult Laurent Pinchart
` (23 preceding siblings ...)
2025-07-10 17:47 ` [PATCH 24/72] media: i2c: imx208: Replace client->dev usage Laurent Pinchart
@ 2025-07-10 17:47 ` Laurent Pinchart
2025-07-10 17:47 ` [PATCH 26/72] media: i2c: imx319: Replace client->dev usage Laurent Pinchart
` (48 subsequent siblings)
73 siblings, 0 replies; 115+ messages in thread
From: Laurent Pinchart @ 2025-07-10 17:47 UTC (permalink / raw)
To: linux-media; +Cc: Sakari Ailus, Mehdi Djait
Several camera sensor drivers access the "clock-frequency" property
directly to retrieve the external clock rate, or modify the clock rate
of the external clock programmatically. Both behaviours are valid on
a subset of ACPI platforms, but are considered deprecated on OF
platforms, and do not support ACPI platforms that implement MIPI DisCo
for Imaging. Implementing them manually in drivers is deprecated, as
that can encourage cargo-cult and lead to differences in behaviour
between drivers. Instead, drivers should use the
devm_v4l2_sensor_clk_get() helper.
This driver supports ACPI platforms only. It retrieves the clock rate
from the "clock-frequency" property. If the rate does not match the
expected rate, the driver fails probing. This is correct behaviour for
ACPI.
Switch to using the devm_v4l2_sensor_clk_get() helper. This does not
change the behaviour on ACPI platforms that specify a clock-frequency
property and don't provide a clock. On ACPI platforms that provide a
clock, the clock rate will be set to the value of the clock-frequency
property. This should not change the behaviour either as this driver
expects the clock to be set to that rate, and wouldn't operate correctly
otherwise.
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
drivers/media/i2c/imx208.c | 23 ++++++++++++++---------
1 file changed, 14 insertions(+), 9 deletions(-)
diff --git a/drivers/media/i2c/imx208.c b/drivers/media/i2c/imx208.c
index 5399a2549b3f..d5350bb46f14 100644
--- a/drivers/media/i2c/imx208.c
+++ b/drivers/media/i2c/imx208.c
@@ -2,6 +2,7 @@
// 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>
@@ -270,6 +271,7 @@ static const struct imx208_mode supported_modes[] = {
struct imx208 {
struct device *dev;
+ struct clk *clk;
struct v4l2_subdev sd;
struct media_pad pad;
@@ -934,17 +936,9 @@ 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)
@@ -952,6 +946,17 @@ static int imx208_probe(struct i2c_client *client)
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);
--
Regards,
Laurent Pinchart
^ permalink raw reply related [flat|nested] 115+ messages in thread
* [PATCH 26/72] media: i2c: imx319: Replace client->dev usage
2025-07-10 17:46 [PATCH 00/72] media: i2c: Reduce cargo-cult Laurent Pinchart
` (24 preceding siblings ...)
2025-07-10 17:47 ` [PATCH 25/72] media: i2c: imx208: Use V4L2 sensor clock helper Laurent Pinchart
@ 2025-07-10 17:47 ` Laurent Pinchart
2025-07-10 17:47 ` [PATCH 27/72] media: i2c: imx319: Use V4L2 sensor clock helper Laurent Pinchart
` (47 subsequent siblings)
73 siblings, 0 replies; 115+ messages in thread
From: Laurent Pinchart @ 2025-07-10 17:47 UTC (permalink / raw)
To: linux-media; +Cc: Sakari Ailus, Mehdi Djait, Bingbu Cao
The driver needs to access the struct device in many places, and
retrieves it from the i2c_client itself retrieved with
v4l2_get_subdevdata(). Store it as a pointer in struct imx319 and access
it from there instead, to simplify the driver.
While at it, fix a mistake in the sort order of include statements.
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
drivers/media/i2c/imx319.c | 63 +++++++++++++++++++-------------------
1 file changed, 31 insertions(+), 32 deletions(-)
diff --git a/drivers/media/i2c/imx319.c b/drivers/media/i2c/imx319.c
index 701840f4a5cc..f404d053873c 100644
--- a/drivers/media/i2c/imx319.c
+++ b/drivers/media/i2c/imx319.c
@@ -1,11 +1,12 @@
// SPDX-License-Identifier: GPL-2.0
// Copyright (C) 2018 Intel Corporation
-#include <linux/unaligned.h>
#include <linux/acpi.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>
@@ -111,6 +112,8 @@ struct imx319_hwcfg {
};
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;
}
@@ -2392,24 +2389,26 @@ static int imx319_probe(struct i2c_client *client)
if (!imx319)
return -ENOMEM;
+ imx319->dev = &client->dev;
+
mutex_init(&imx319->mutex);
/* 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 +2418,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 +2433,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 +2474,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);
}
--
Regards,
Laurent Pinchart
^ permalink raw reply related [flat|nested] 115+ messages in thread
* [PATCH 27/72] media: i2c: imx319: Use V4L2 sensor clock helper
2025-07-10 17:46 [PATCH 00/72] media: i2c: Reduce cargo-cult Laurent Pinchart
` (25 preceding siblings ...)
2025-07-10 17:47 ` [PATCH 26/72] media: i2c: imx319: Replace client->dev usage Laurent Pinchart
@ 2025-07-10 17:47 ` Laurent Pinchart
2025-07-10 17:47 ` [PATCH 28/72] media: i2c: imx355: Replace client->dev usage Laurent Pinchart
` (46 subsequent siblings)
73 siblings, 0 replies; 115+ messages in thread
From: Laurent Pinchart @ 2025-07-10 17:47 UTC (permalink / raw)
To: linux-media; +Cc: Sakari Ailus, Mehdi Djait, Bingbu Cao
Several camera sensor drivers access the "clock-frequency" property
directly to retrieve the external clock rate, or modify the clock rate
of the external clock programmatically. Both behaviours are valid on
a subset of ACPI platforms, but are considered deprecated on OF
platforms, and do not support ACPI platforms that implement MIPI DisCo
for Imaging. Implementing them manually in drivers is deprecated, as
that can encourage cargo-cult and lead to differences in behaviour
between drivers. Instead, drivers should use the
devm_v4l2_sensor_clk_get() helper.
This driver supports ACPI platforms only. It retrieves the clock rate
from the "clock-frequency" property. If the rate does not match the
expected rate, the driver fails probing. This is correct behaviour for
ACPI.
Switch to using the devm_v4l2_sensor_clk_get() helper. This does not
change the behaviour on ACPI platforms that specify a clock-frequency
property and don't provide a clock. On ACPI platforms that provide a
clock, the clock rate will be set to the value of the clock-frequency
property. This should not change the behaviour either as this driver
expects the clock to be set to that rate, and wouldn't operate correctly
otherwise.
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
drivers/media/i2c/imx319.c | 29 ++++++++++++++---------------
1 file changed, 14 insertions(+), 15 deletions(-)
diff --git a/drivers/media/i2c/imx319.c b/drivers/media/i2c/imx319.c
index f404d053873c..953310ef3046 100644
--- a/drivers/media/i2c/imx319.c
+++ b/drivers/media/i2c/imx319.c
@@ -2,6 +2,7 @@
// Copyright (C) 2018 Intel Corporation
#include <linux/acpi.h>
+#include <linux/clk.h>
#include <linux/i2c.h>
#include <linux/module.h>
#include <linux/pm_runtime.h>
@@ -107,7 +108,6 @@ struct imx319_mode {
};
struct imx319_hwcfg {
- u32 ext_clk; /* sensor external clk */
unsigned long link_freq_bitmap;
};
@@ -2347,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,
@@ -2382,6 +2368,8 @@ static struct imx319_hwcfg *imx319_get_hwcfg(struct device *dev)
static int imx319_probe(struct i2c_client *client)
{
struct imx319 *imx319;
+ unsigned long freq;
+ struct clk *clk;
bool full_power;
int ret;
@@ -2393,6 +2381,17 @@ static int imx319_probe(struct i2c_client *client)
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);
--
Regards,
Laurent Pinchart
^ permalink raw reply related [flat|nested] 115+ messages in thread
* [PATCH 28/72] media: i2c: imx355: Replace client->dev usage
2025-07-10 17:46 [PATCH 00/72] media: i2c: Reduce cargo-cult Laurent Pinchart
` (26 preceding siblings ...)
2025-07-10 17:47 ` [PATCH 27/72] media: i2c: imx319: Use V4L2 sensor clock helper Laurent Pinchart
@ 2025-07-10 17:47 ` Laurent Pinchart
2025-07-10 17:47 ` [PATCH 29/72] media: i2c: imx335: Use V4L2 sensor clock helper Laurent Pinchart
` (45 subsequent siblings)
73 siblings, 0 replies; 115+ messages in thread
From: Laurent Pinchart @ 2025-07-10 17:47 UTC (permalink / raw)
To: linux-media; +Cc: Sakari Ailus, Mehdi Djait, Tianshu Qiu
The driver needs to access the struct device in many places, and
retrieves it from the i2c_client itself retrieved with
v4l2_get_subdevdata(). Store it as a pointer in struct imx355 and access
it from there instead, to simplify the driver.
While at it, fix a mistake in the sort order of include statements.
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
drivers/media/i2c/imx355.c | 61 +++++++++++++++++++-------------------
1 file changed, 30 insertions(+), 31 deletions(-)
diff --git a/drivers/media/i2c/imx355.c b/drivers/media/i2c/imx355.c
index b2dce67c0b6b..2315393f32e7 100644
--- a/drivers/media/i2c/imx355.c
+++ b/drivers/media/i2c/imx355.c
@@ -1,11 +1,12 @@
// SPDX-License-Identifier: GPL-2.0
// Copyright (C) 2018 Intel Corporation
-#include <linux/unaligned.h>
#include <linux/acpi.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>
@@ -97,6 +98,8 @@ struct imx355_hwcfg {
};
struct imx355 {
+ struct device *dev;
+
struct v4l2_subdev sd;
struct media_pad pad;
@@ -1136,14 +1139,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 +1180,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 +1198,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 +1232,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 +1386,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 +1393,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 +1401,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 +1429,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 +1447,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 +1459,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 +1469,6 @@ static int imx355_set_stream(struct v4l2_subdev *sd, int enable)
/* 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 +1477,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 +1517,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 +1597,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;
@@ -1689,6 +1686,8 @@ static int imx355_probe(struct i2c_client *client)
if (!imx355)
return -ENOMEM;
+ imx355->dev = &client->dev;
+
mutex_init(&imx355->mutex);
/* Initialize subdev */
@@ -1697,13 +1696,13 @@ static int imx355_probe(struct i2c_client *client)
/* 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 +1712,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 +1727,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 +1735,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 +1746,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 +1768,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);
}
--
Regards,
Laurent Pinchart
^ permalink raw reply related [flat|nested] 115+ messages in thread
* [PATCH 29/72] media: i2c: imx335: Use V4L2 sensor clock helper
2025-07-10 17:46 [PATCH 00/72] media: i2c: Reduce cargo-cult Laurent Pinchart
` (27 preceding siblings ...)
2025-07-10 17:47 ` [PATCH 28/72] media: i2c: imx355: Replace client->dev usage Laurent Pinchart
@ 2025-07-10 17:47 ` Laurent Pinchart
2025-07-10 17:47 ` [PATCH 30/72] media: i2c: og01a1b: Replace client->dev usage Laurent Pinchart
` (44 subsequent siblings)
73 siblings, 0 replies; 115+ messages in thread
From: Laurent Pinchart @ 2025-07-10 17:47 UTC (permalink / raw)
To: linux-media; +Cc: Sakari Ailus, Mehdi Djait, Tianshu Qiu
Several camera sensor drivers access the "clock-frequency" property
directly to retrieve the external clock rate, or modify the clock rate
of the external clock programmatically. Both behaviours are valid on
a subset of ACPI platforms, but are considered deprecated on OF
platforms, and do not support ACPI platforms that implement MIPI DisCo
for Imaging. Implementing them manually in drivers is deprecated, as
that can encourage cargo-cult and lead to differences in behaviour
between drivers. Instead, drivers should use the
devm_v4l2_sensor_clk_get() helper.
This driver supports ACPI platforms only. It retrieves the clock rate
from the "clock-frequency" property. If the rate does not match the
expected rate, the driver fails probing. This is correct behaviour for
ACPI.
Switch to using the devm_v4l2_sensor_clk_get() helper. This does not
change the behaviour on ACPI platforms that specify a clock-frequency
property and don't provide a clock. On ACPI platforms that provide a
clock, the clock rate will be set to the value of the clock-frequency
property. This should not change the behaviour either as this driver
expects the clock to be set to that rate, and wouldn't operate correctly
otherwise.
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
drivers/media/i2c/imx355.c | 29 ++++++++++++++---------------
1 file changed, 14 insertions(+), 15 deletions(-)
diff --git a/drivers/media/i2c/imx355.c b/drivers/media/i2c/imx355.c
index 2315393f32e7..776107efe386 100644
--- a/drivers/media/i2c/imx355.c
+++ b/drivers/media/i2c/imx355.c
@@ -2,6 +2,7 @@
// Copyright (C) 2018 Intel Corporation
#include <linux/acpi.h>
+#include <linux/clk.h>
#include <linux/i2c.h>
#include <linux/module.h>
#include <linux/pm_runtime.h>
@@ -93,12 +94,12 @@ 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;
@@ -1645,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,
@@ -1680,6 +1667,7 @@ static struct imx355_hwcfg *imx355_get_hwcfg(struct device *dev)
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);
@@ -1690,6 +1678,17 @@ static int imx355_probe(struct i2c_client *client)
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);
--
Regards,
Laurent Pinchart
^ permalink raw reply related [flat|nested] 115+ messages in thread
* [PATCH 30/72] media: i2c: og01a1b: Replace client->dev usage
2025-07-10 17:46 [PATCH 00/72] media: i2c: Reduce cargo-cult Laurent Pinchart
` (28 preceding siblings ...)
2025-07-10 17:47 ` [PATCH 29/72] media: i2c: imx335: Use V4L2 sensor clock helper Laurent Pinchart
@ 2025-07-10 17:47 ` Laurent Pinchart
2025-07-10 17:47 ` [PATCH 31/72] media: i2c: og01a1b: Use V4L2 sensor clock helper Laurent Pinchart
` (43 subsequent siblings)
73 siblings, 0 replies; 115+ messages in thread
From: Laurent Pinchart @ 2025-07-10 17:47 UTC (permalink / raw)
To: linux-media; +Cc: Sakari Ailus, Mehdi Djait, Liam Girdwood, Mark Brown
The driver needs to access the struct device in many places, and
retrieves it from the i2c_client itself retrieved with
v4l2_get_subdevdata(). Store it as a pointer in struct og01a1b and
access it from there instead, to simplify the driver.
While at it, fix a mistake in the sort order of include statements.
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
drivers/media/i2c/og01a1b.c | 80 ++++++++++++++++++-------------------
1 file changed, 38 insertions(+), 42 deletions(-)
diff --git a/drivers/media/i2c/og01a1b.c b/drivers/media/i2c/og01a1b.c
index 78d5d406e4b7..59688bad7c98 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;
}
@@ -688,7 +688,6 @@ static void og01a1b_update_pad_format(const struct og01a1b_mode *mode,
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);
@@ -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,8 +904,7 @@ 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 = {
@@ -1066,7 +1060,7 @@ 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);
}
@@ -1079,34 +1073,36 @@ static int og01a1b_probe(struct i2c_client *client)
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);
+ og01a1b->xvclk = devm_clk_get_optional(og01a1b->dev, NULL);
if (IS_ERR(og01a1b->xvclk)) {
ret = PTR_ERR(og01a1b->xvclk);
- dev_err(&client->dev, "failed to get xvclk clock: %d\n", ret);
+ dev_err(og01a1b->dev, "failed to get xvclk clock: %d\n", ret);
return ret;
}
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 +1110,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 +1122,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 +1135,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 +1149,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 +1160,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 +1186,7 @@ static int og01a1b_probe(struct i2c_client *client)
mutex_destroy(&og01a1b->mutex);
power_off:
- og01a1b_power_off(&client->dev);
+ og01a1b_power_off(og01a1b->dev);
return ret;
}
--
Regards,
Laurent Pinchart
^ permalink raw reply related [flat|nested] 115+ messages in thread
* [PATCH 31/72] media: i2c: og01a1b: Use V4L2 sensor clock helper
2025-07-10 17:46 [PATCH 00/72] media: i2c: Reduce cargo-cult Laurent Pinchart
` (29 preceding siblings ...)
2025-07-10 17:47 ` [PATCH 30/72] media: i2c: og01a1b: Replace client->dev usage Laurent Pinchart
@ 2025-07-10 17:47 ` Laurent Pinchart
2025-07-15 11:44 ` Mehdi Djait
2025-07-10 17:47 ` [PATCH 32/72] media: i2c: ov02c10: Replace client->dev usage Laurent Pinchart
` (42 subsequent siblings)
73 siblings, 1 reply; 115+ messages in thread
From: Laurent Pinchart @ 2025-07-10 17:47 UTC (permalink / raw)
To: linux-media; +Cc: Sakari Ailus, Mehdi Djait
Several camera sensor drivers access the "clock-frequency" property
directly to retrieve the external clock rate, or modify the clock rate
of the external clock programmatically. Both behaviours are valid on
a subset of ACPI platforms, but are considered deprecated on OF
platforms, and do not support ACPI platforms that implement MIPI DisCo
for Imaging. Implementing them manually in drivers is deprecated, as
that can encourage cargo-cult and lead to differences in behaviour
between drivers. Instead, drivers should use the
devm_v4l2_sensor_clk_get() helper.
This driver supports ACPI and OF platforms. The "clocks" property is
specified as mandatory in the DT bindings and the "clock-frequency"
property is not allowed. The driver retrieves the clock if present,
retrieves the clock rate from the "clock-frequency" property and falls
back to retrieving it from the clock. If the rate does not match the
expected rate, the driver fails probing. This is correct behaviour for
ACPI, and for OF platforms that comply with the documented DT bindings.
Switch to using the devm_v4l2_sensor_clk_get() helper. This does not
change the behaviour on ACPI platforms that specify a clock-frequency
property and don't provide a clock. On ACPI platforms that provide a
clock, the clock rate will be set to the value of the clock-frequency
property. This should not change the behaviour either as this driver
expects the clock to be set to that rate, and wouldn't operate correctly
otherwise.
The behaviour is also unchanged on OF platforms that comply with the DT
bindings. Non-compliant platforms are not expected, but any regression
could easily be handled by switching to the
devm_v4l2_sensor_clk_get_legacy() helper designed to preserve
non-compliant behaviour.
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
drivers/media/i2c/og01a1b.c | 25 ++++++++-----------------
1 file changed, 8 insertions(+), 17 deletions(-)
diff --git a/drivers/media/i2c/og01a1b.c b/drivers/media/i2c/og01a1b.c
index 59688bad7c98..fe96ca9bb108 100644
--- a/drivers/media/i2c/og01a1b.c
+++ b/drivers/media/i2c/og01a1b.c
@@ -910,28 +910,12 @@ static int og01a1b_check_hwcfg(struct og01a1b *og01a1b)
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;
@@ -1067,6 +1051,7 @@ static void og01a1b_remove(struct i2c_client *client)
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);
@@ -1077,13 +1062,19 @@ static int og01a1b_probe(struct i2c_client *client)
v4l2_i2c_subdev_init(&og01a1b->sd, client, &og01a1b_subdev_ops);
- og01a1b->xvclk = devm_clk_get_optional(og01a1b->dev, NULL);
+ og01a1b->xvclk = devm_v4l2_sensor_clk_get(og01a1b->dev, NULL);
if (IS_ERR(og01a1b->xvclk)) {
ret = PTR_ERR(og01a1b->xvclk);
dev_err(og01a1b->dev, "failed to get xvclk clock: %d\n", ret);
return ret;
}
+ 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(og01a1b->dev, "failed to check HW configuration: %d",
--
Regards,
Laurent Pinchart
^ permalink raw reply related [flat|nested] 115+ messages in thread
* [PATCH 32/72] media: i2c: ov02c10: Replace client->dev usage
2025-07-10 17:46 [PATCH 00/72] media: i2c: Reduce cargo-cult Laurent Pinchart
` (30 preceding siblings ...)
2025-07-10 17:47 ` [PATCH 31/72] media: i2c: og01a1b: Use V4L2 sensor clock helper Laurent Pinchart
@ 2025-07-10 17:47 ` Laurent Pinchart
2025-07-10 17:47 ` [PATCH 33/72] media: i2c: ov02c10: Use V4L2 sensor clock helper Laurent Pinchart
` (41 subsequent siblings)
73 siblings, 0 replies; 115+ messages in thread
From: Laurent Pinchart @ 2025-07-10 17:47 UTC (permalink / raw)
To: linux-media
Cc: Sakari Ailus, Mehdi Djait, Hans de Goede, Bryan O'Donoghue
The driver needs to access the struct device in many places, and
retrieves it from the i2c_client itself retrieved with
v4l2_get_subdevdata(). Store it as a pointer in struct ov02c10 and
access it from there instead, to simplify the driver.
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
drivers/media/i2c/ov02c10.c | 69 +++++++++++++++++++------------------
1 file changed, 35 insertions(+), 34 deletions(-)
diff --git a/drivers/media/i2c/ov02c10.c b/drivers/media/i2c/ov02c10.c
index 089a4fd9627c..88ddfaaa1dea 100644
--- a/drivers/media/i2c/ov02c10.c
+++ b/drivers/media/i2c/ov02c10.c
@@ -373,6 +373,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 +420,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 +435,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 +468,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 +479,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 +542,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 +570,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 +583,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 +592,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 +603,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 +612,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 +776,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 +784,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,11 +792,12 @@ 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;
@@ -873,15 +871,16 @@ static int ov02c10_check_hwcfg(struct device *dev, struct ov02c10 *ov02c10)
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);
}
}
@@ -894,14 +893,16 @@ static int ov02c10_probe(struct i2c_client *client)
if (!ov02c10)
return -ENOMEM;
+ ov02c10->dev = &client->dev;
+
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 +910,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 +935,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 +971,7 @@ static int ov02c10_probe(struct i2c_client *client)
v4l2_ctrl_handler_free(ov02c10->sd.ctrl_handler);
probe_error_power_off:
- ov02c10_power_off(&client->dev);
+ ov02c10_power_off(ov02c10->dev);
return ret;
}
--
Regards,
Laurent Pinchart
^ permalink raw reply related [flat|nested] 115+ messages in thread
* [PATCH 33/72] media: i2c: ov02c10: Use V4L2 sensor clock helper
2025-07-10 17:46 [PATCH 00/72] media: i2c: Reduce cargo-cult Laurent Pinchart
` (31 preceding siblings ...)
2025-07-10 17:47 ` [PATCH 32/72] media: i2c: ov02c10: Replace client->dev usage Laurent Pinchart
@ 2025-07-10 17:47 ` Laurent Pinchart
2025-07-10 17:47 ` [PATCH 34/72] media: i2c: ov02e10: Replace client->dev usage Laurent Pinchart
` (40 subsequent siblings)
73 siblings, 0 replies; 115+ messages in thread
From: Laurent Pinchart @ 2025-07-10 17:47 UTC (permalink / raw)
To: linux-media
Cc: Sakari Ailus, Mehdi Djait, Hans de Goede, Bryan O'Donoghue
Several camera sensor drivers access the "clock-frequency" property
directly to retrieve the external clock rate, or modify the clock rate
of the external clock programmatically. Both behaviours are valid on
a subset of ACPI platforms, but are considered deprecated on OF
platforms, and do not support ACPI platforms that implement MIPI DisCo
for Imaging. Implementing them manually in drivers is deprecated, as
that can encourage cargo-cult and lead to differences in behaviour
between drivers. Instead, drivers should use the
devm_v4l2_sensor_clk_get() helper.
This driver supports ACPI and OF platforms. The "clocks" property is
specified as mandatory in the DT bindings and the "clock-frequency"
property is not allowed. The driver retrieves the clock and its rate if
present, and falls back to retrieving the rate from the
"clock-frequency" property otherwise. If the rate does not match the
expected rate, the driver fails probing. This is correct behaviour for
ACPI, and for OF platforms that comply with the documented DT bindings.
Switch to using the devm_v4l2_sensor_clk_get() helper. This does not
change the behaviour on ACPI platforms that specify a clock-frequency
property and don't provide a clock. On ACPI platforms that provide a
clock, the clock rate will be set to the value of the clock-frequency
property. This should not change the behaviour either as this driver
expects the clock to be set to that rate, and wouldn't operate correctly
otherwise.
The behaviour is also unchanged on OF platforms that comply with the DT
bindings. Non-compliant platforms are not expected, but any regression
could easily be handled by switching to the
devm_v4l2_sensor_clk_get_legacy() helper designed to preserve
non-compliant behaviour.
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
drivers/media/i2c/ov02c10.c | 38 ++++++++++++-------------------------
1 file changed, 12 insertions(+), 26 deletions(-)
diff --git a/drivers/media/i2c/ov02c10.c b/drivers/media/i2c/ov02c10.c
index 88ddfaaa1dea..f2b056854b1a 100644
--- a/drivers/media/i2c/ov02c10.c
+++ b/drivers/media/i2c/ov02c10.c
@@ -800,7 +800,6 @@ static int ov02c10_check_hwcfg(struct ov02c10 *ov02c10)
struct device *dev = ov02c10->dev;
struct fwnode_handle *ep, *fwnode = dev_fwnode(dev);
unsigned long link_freq_bitmap;
- u32 mclk;
int ret;
/*
@@ -812,31 +811,6 @@ static int ov02c10_check_hwcfg(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)
@@ -887,6 +861,7 @@ static void ov02c10_remove(struct i2c_client *client)
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);
@@ -895,6 +870,17 @@ static int ov02c10_probe(struct i2c_client *client)
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 */
--
Regards,
Laurent Pinchart
^ permalink raw reply related [flat|nested] 115+ messages in thread
* [PATCH 34/72] media: i2c: ov02e10: Replace client->dev usage
2025-07-10 17:46 [PATCH 00/72] media: i2c: Reduce cargo-cult Laurent Pinchart
` (32 preceding siblings ...)
2025-07-10 17:47 ` [PATCH 33/72] media: i2c: ov02c10: Use V4L2 sensor clock helper Laurent Pinchart
@ 2025-07-10 17:47 ` Laurent Pinchart
2025-07-10 17:47 ` [PATCH 35/72] media: i2c: ov02e10: Use V4L2 sensor clock helper Laurent Pinchart
` (39 subsequent siblings)
73 siblings, 0 replies; 115+ messages in thread
From: Laurent Pinchart @ 2025-07-10 17:47 UTC (permalink / raw)
To: linux-media
Cc: Sakari Ailus, Mehdi Djait, Bryan O'Donoghue, Hans de Goede
The driver needs to access the struct device in many places, and
retrieves it from the i2c_client itself retrieved with
v4l2_get_subdevdata(). Store it as a pointer in struct ov02e10 and
access it from there instead, to simplify the driver.
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
drivers/media/i2c/ov02e10.c | 67 +++++++++++++++++++------------------
1 file changed, 34 insertions(+), 33 deletions(-)
diff --git a/drivers/media/i2c/ov02e10.c b/drivers/media/i2c/ov02e10.c
index d74dc62e189d..3dcb169dfaa3 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,11 +740,12 @@ 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;
@@ -823,16 +821,17 @@ static int ov02e10_check_hwcfg(struct device *dev, struct ov02e10 *ov02e10)
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);
}
}
@@ -845,10 +844,12 @@ static int ov02e10_probe(struct i2c_client *client)
if (!ov02e10)
return -ENOMEM;
+ ov02e10->dev = &client->dev;
+
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 +858,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 +892,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 +928,7 @@ static int ov02e10_probe(struct i2c_client *client)
v4l2_ctrl_handler_free(ov02e10->sd.ctrl_handler);
probe_error_power_off:
- ov02e10_power_off(&client->dev);
+ ov02e10_power_off(ov02e10->dev);
return ret;
}
--
Regards,
Laurent Pinchart
^ permalink raw reply related [flat|nested] 115+ messages in thread
* [PATCH 35/72] media: i2c: ov02e10: Use V4L2 sensor clock helper
2025-07-10 17:46 [PATCH 00/72] media: i2c: Reduce cargo-cult Laurent Pinchart
` (33 preceding siblings ...)
2025-07-10 17:47 ` [PATCH 34/72] media: i2c: ov02e10: Replace client->dev usage Laurent Pinchart
@ 2025-07-10 17:47 ` Laurent Pinchart
2025-07-10 17:47 ` [PATCH 36/72] media: i2c: ov08d10: Replace client->dev usage Laurent Pinchart
` (38 subsequent siblings)
73 siblings, 0 replies; 115+ messages in thread
From: Laurent Pinchart @ 2025-07-10 17:47 UTC (permalink / raw)
To: linux-media
Cc: Sakari Ailus, Mehdi Djait, Bryan O'Donoghue, Hans de Goede
Several camera sensor drivers access the "clock-frequency" property
directly to retrieve the external clock rate, or modify the clock rate
of the external clock programmatically. Both behaviours are valid on
a subset of ACPI platforms, but are considered deprecated on OF
platforms, and do not support ACPI platforms that implement MIPI DisCo
for Imaging. Implementing them manually in drivers is deprecated, as
that can encourage cargo-cult and lead to differences in behaviour
between drivers. Instead, drivers should use the
devm_v4l2_sensor_clk_get() helper.
This driver supports ACPI and OF platforms. The "clocks" property is
specified as mandatory in the DT bindings and the "clock-frequency"
property is not allowed. The driver retrieves the clock and its rate if
present, and falls back to retrieving the rate from the
"clock-frequency" property otherwise. If the rate does not match the
expected rate, the driver fails probing. This is correct behaviour for
ACPI, and for OF platforms that comply with the documented DT bindings.
Switch to using the devm_v4l2_sensor_clk_get() helper. This does not
change the behaviour on ACPI platforms that specify a clock-frequency
property and don't provide a clock. On ACPI platforms that provide a
clock, the clock rate will be set to the value of the clock-frequency
property. This should not change the behaviour either as this driver
expects the clock to be set to that rate, and wouldn't operate correctly
otherwise.
The behaviour is also unchanged on OF platforms that comply with the DT
bindings. Non-compliant platforms are not expected, but any regression
could easily be handled by switching to the
devm_v4l2_sensor_clk_get_legacy() helper designed to preserve
non-compliant behaviour.
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
drivers/media/i2c/ov02e10.c | 38 ++++++++++++-------------------------
1 file changed, 12 insertions(+), 26 deletions(-)
diff --git a/drivers/media/i2c/ov02e10.c b/drivers/media/i2c/ov02e10.c
index 3dcb169dfaa3..7d7f43e77864 100644
--- a/drivers/media/i2c/ov02e10.c
+++ b/drivers/media/i2c/ov02e10.c
@@ -749,7 +749,6 @@ static int ov02e10_check_hwcfg(struct ov02e10 *ov02e10)
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);
@@ -762,31 +761,6 @@ static int ov02e10_check_hwcfg(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);
@@ -838,6 +812,7 @@ static void ov02e10_remove(struct i2c_client *client)
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);
@@ -846,6 +821,17 @@ static int ov02e10_probe(struct i2c_client *client)
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 */
--
Regards,
Laurent Pinchart
^ permalink raw reply related [flat|nested] 115+ messages in thread
* [PATCH 36/72] media: i2c: ov08d10: Replace client->dev usage
2025-07-10 17:46 [PATCH 00/72] media: i2c: Reduce cargo-cult Laurent Pinchart
` (34 preceding siblings ...)
2025-07-10 17:47 ` [PATCH 35/72] media: i2c: ov02e10: Use V4L2 sensor clock helper Laurent Pinchart
@ 2025-07-10 17:47 ` Laurent Pinchart
2025-07-10 17:47 ` [PATCH 37/72] media: i2c: ov08d10: Use V4L2 sensor clock helper Laurent Pinchart
` (37 subsequent siblings)
73 siblings, 0 replies; 115+ messages in thread
From: Laurent Pinchart @ 2025-07-10 17:47 UTC (permalink / raw)
To: linux-media; +Cc: Sakari Ailus, Mehdi Djait, Jimmy Su
The driver needs to access the struct device in many places, and
retrieves it from the i2c_client itself retrieved with
v4l2_get_subdevdata(). Store it as a pointer in struct ov08d10 and
access it from there instead, to simplify the driver.
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
drivers/media/i2c/ov08d10.c | 59 +++++++++++++++++++------------------
1 file changed, 31 insertions(+), 28 deletions(-)
diff --git a/drivers/media/i2c/ov08d10.c b/drivers/media/i2c/ov08d10.c
index 1bacbdfa4298..2523adcaacf7 100644
--- a/drivers/media/i2c/ov08d10.c
+++ b/drivers/media/i2c/ov08d10.c
@@ -515,6 +515,8 @@ static const char * const ov08d10_test_pattern_menu[] = {
};
struct ov08d10 {
+ struct device *dev;
+
struct v4l2_subdev sd;
struct media_pad pad;
struct v4l2_ctrl_handler ctrl_handler;
@@ -663,7 +665,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 +851,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 +866,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 +902,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 +1026,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 +1078,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 +1098,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 +1112,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 +1293,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,8 +1301,9 @@ 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 = {
@@ -1380,7 +1381,7 @@ 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);
}
@@ -1393,9 +1394,11 @@ static int ov08d10_probe(struct i2c_client *client)
if (!ov08d10)
return -ENOMEM;
- ret = ov08d10_get_hwcfg(ov08d10, &client->dev);
+ ov08d10->dev = &client->dev;
+
+ 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 +1407,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 +1415,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 +1425,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 +1440,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;
--
Regards,
Laurent Pinchart
^ permalink raw reply related [flat|nested] 115+ messages in thread
* [PATCH 37/72] media: i2c: ov08d10: Use V4L2 sensor clock helper
2025-07-10 17:46 [PATCH 00/72] media: i2c: Reduce cargo-cult Laurent Pinchart
` (35 preceding siblings ...)
2025-07-10 17:47 ` [PATCH 36/72] media: i2c: ov08d10: Replace client->dev usage Laurent Pinchart
@ 2025-07-10 17:47 ` Laurent Pinchart
2025-07-10 17:47 ` [PATCH 38/72] media: i2c: ov08x40: Replace client->dev usage Laurent Pinchart
` (36 subsequent siblings)
73 siblings, 0 replies; 115+ messages in thread
From: Laurent Pinchart @ 2025-07-10 17:47 UTC (permalink / raw)
To: linux-media; +Cc: Sakari Ailus, Mehdi Djait, Jimmy Su
Several camera sensor drivers access the "clock-frequency" property
directly to retrieve the external clock rate, or modify the clock rate
of the external clock programmatically. Both behaviours are valid on
a subset of ACPI platforms, but are considered deprecated on OF
platforms, and do not support ACPI platforms that implement MIPI DisCo
for Imaging. Implementing them manually in drivers is deprecated, as
that can encourage cargo-cult and lead to differences in behaviour
between drivers. Instead, drivers should use the
devm_v4l2_sensor_clk_get() helper.
This driver supports ACPI platforms only. It retrieves the clock rate
from the "clock-frequency" property. If the rate does not match the
expected rate, the driver prints a warning. This is correct behaviour
for ACPI.
Switch to using the devm_v4l2_sensor_clk_get() helper. This does not
change the behaviour on ACPI platforms that specify a clock-frequency
property and don't provide a clock. On ACPI platforms that provide a
clock, the clock rate will be set to the value of the clock-frequency
property. This should not change the behaviour either as this driver
expects the clock to be set to that rate, and wouldn't operate correctly
otherwise.
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
drivers/media/i2c/ov08d10.c | 23 ++++++++++++-----------
1 file changed, 12 insertions(+), 11 deletions(-)
diff --git a/drivers/media/i2c/ov08d10.c b/drivers/media/i2c/ov08d10.c
index 2523adcaacf7..43ec2a1f2fcf 100644
--- a/drivers/media/i2c/ov08d10.c
+++ b/drivers/media/i2c/ov08d10.c
@@ -516,13 +516,12 @@ 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;
@@ -1309,21 +1308,12 @@ static int ov08d10_get_hwcfg(struct ov08d10 *ov08d10)
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;
@@ -1388,6 +1378,7 @@ static void ov08d10_remove(struct i2c_client *client)
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);
@@ -1396,6 +1387,16 @@ static int ov08d10_probe(struct i2c_client *client)
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(ov08d10->dev, "failed to get HW configuration: %d",
--
Regards,
Laurent Pinchart
^ permalink raw reply related [flat|nested] 115+ messages in thread
* [PATCH 38/72] media: i2c: ov08x40: Replace client->dev usage
2025-07-10 17:46 [PATCH 00/72] media: i2c: Reduce cargo-cult Laurent Pinchart
` (36 preceding siblings ...)
2025-07-10 17:47 ` [PATCH 37/72] media: i2c: ov08d10: Use V4L2 sensor clock helper Laurent Pinchart
@ 2025-07-10 17:47 ` Laurent Pinchart
2025-07-10 17:47 ` [PATCH 39/72] media: i2c: ov08x40: Use V4L2 sensor clock helper Laurent Pinchart
` (35 subsequent siblings)
73 siblings, 0 replies; 115+ messages in thread
From: Laurent Pinchart @ 2025-07-10 17:47 UTC (permalink / raw)
To: linux-media; +Cc: Sakari Ailus, Mehdi Djait, Jason Chen
The driver needs to access the struct device in many places, and
retrieves it from the i2c_client itself retrieved with
v4l2_get_subdevdata(). Store it as a pointer in struct ov08x40 and
access it from there instead, to simplify the driver.
While at it, fix mistakes in the sort order of include statements.
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
drivers/media/i2c/ov08x40.c | 82 ++++++++++++++++++-------------------
1 file changed, 41 insertions(+), 41 deletions(-)
diff --git a/drivers/media/i2c/ov08x40.c b/drivers/media/i2c/ov08x40.c
index e0094305ca2a..15504344a4b1 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/gpio/consumer.h>
-#include <linux/module.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/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);
@@ -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;
@@ -2294,19 +2292,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 +2333,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 +2342,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 +2355,7 @@ static int ov08x40_probe(struct i2c_client *client)
ov08x40_free_controls(ov08x);
probe_power_off:
- ov08x40_power_off(&client->dev);
+ ov08x40_power_off(ov08x->dev);
return ret;
}
@@ -2369,10 +2369,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,
--
Regards,
Laurent Pinchart
^ permalink raw reply related [flat|nested] 115+ messages in thread
* [PATCH 39/72] media: i2c: ov08x40: Use V4L2 sensor clock helper
2025-07-10 17:46 [PATCH 00/72] media: i2c: Reduce cargo-cult Laurent Pinchart
` (37 preceding siblings ...)
2025-07-10 17:47 ` [PATCH 38/72] media: i2c: ov08x40: Replace client->dev usage Laurent Pinchart
@ 2025-07-10 17:47 ` Laurent Pinchart
2025-07-10 17:47 ` [PATCH 40/72] media: i2c: ov13858: Replace client->dev usage Laurent Pinchart
` (34 subsequent siblings)
73 siblings, 0 replies; 115+ messages in thread
From: Laurent Pinchart @ 2025-07-10 17:47 UTC (permalink / raw)
To: linux-media; +Cc: Sakari Ailus, Mehdi Djait, Jason Chen
Several camera sensor drivers access the "clock-frequency" property
directly to retrieve the external clock rate, or modify the clock rate
of the external clock programmatically. Both behaviours are valid on
a subset of ACPI platforms, but are considered deprecated on OF
platforms, and do not support ACPI platforms that implement MIPI DisCo
for Imaging. Implementing them manually in drivers is deprecated, as
that can encourage cargo-cult and lead to differences in behaviour
between drivers. Instead, drivers should use the
devm_v4l2_sensor_clk_get() helper.
This driver supports ACPI and OF platforms. The "clocks" property is
specified as mandatory in the DT bindings and the "clock-frequency"
property is not allowed. The driver retrieves the clock and its rate if
present, and falls back to retrieving the rate from the
"clock-frequency" property otherwise. If the rate does not match the
expected rate, the driver fails probing. This is correct behaviour for
ACPI, and for OF platforms that comply with the documented DT bindings.
Switch to using the devm_v4l2_sensor_clk_get() helper. This does not
change the behaviour on ACPI platforms that specify a clock-frequency
property and don't provide a clock. On ACPI platforms that provide a
clock, the clock rate will be set to the value of the clock-frequency
property. This should not change the behaviour either as this driver
expects the clock to be set to that rate, and wouldn't operate correctly
otherwise.
The behaviour is also unchanged on OF platforms that comply with the DT
bindings. Non-compliant platforms are not expected, but any regression
could easily be handled by switching to the
devm_v4l2_sensor_clk_get_legacy() helper designed to preserve
non-compliant behaviour.
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
drivers/media/i2c/ov08x40.c | 13 ++-----------
1 file changed, 2 insertions(+), 11 deletions(-)
diff --git a/drivers/media/i2c/ov08x40.c b/drivers/media/i2c/ov08x40.c
index 15504344a4b1..3a4bd8513db4 100644
--- a/drivers/media/i2c/ov08x40.c
+++ b/drivers/media/i2c/ov08x40.c
@@ -2230,23 +2230,14 @@ static int ov08x40_check_hwcfg(struct ov08x40 *ov08x)
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);
--
Regards,
Laurent Pinchart
^ permalink raw reply related [flat|nested] 115+ messages in thread
* [PATCH 40/72] media: i2c: ov13858: Replace client->dev usage
2025-07-10 17:46 [PATCH 00/72] media: i2c: Reduce cargo-cult Laurent Pinchart
` (38 preceding siblings ...)
2025-07-10 17:47 ` [PATCH 39/72] media: i2c: ov08x40: Use V4L2 sensor clock helper Laurent Pinchart
@ 2025-07-10 17:47 ` Laurent Pinchart
2025-07-10 17:47 ` [PATCH 41/72] media: i2c: ov13858: Use V4L2 sensor clock helper Laurent Pinchart
` (33 subsequent siblings)
73 siblings, 0 replies; 115+ messages in thread
From: Laurent Pinchart @ 2025-07-10 17:47 UTC (permalink / raw)
To: linux-media; +Cc: Sakari Ailus, Mehdi Djait
The driver needs to access the struct device in many places, and
retrieves it from the i2c_client itself retrieved with
v4l2_get_subdevdata(). Store it as a pointer in struct ov13858 and
access it from there instead, to simplify the driver.
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
drivers/media/i2c/ov13858.c | 50 ++++++++++++++++++-------------------
1 file changed, 24 insertions(+), 26 deletions(-)
diff --git a/drivers/media/i2c/ov13858.c b/drivers/media/i2c/ov13858.c
index 7a3fc1d28514..d93ad730d633 100644
--- a/drivers/media/i2c/ov13858.c
+++ b/drivers/media/i2c/ov13858.c
@@ -1028,6 +1028,8 @@ static const struct ov13858_mode supported_modes[] = {
};
struct ov13858 {
+ struct device *dev;
+
struct v4l2_subdev sd;
struct media_pad pad;
@@ -1117,7 +1119,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 +1127,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 +1210,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 +1228,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 +1256,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 +1408,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 +1415,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 +1425,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 +1433,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 +1457,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 +1475,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 +1483,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 +1493,6 @@ static int ov13858_set_stream(struct v4l2_subdev *sd, int enable)
/* 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 +1502,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 +1549,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 +1622,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;
@@ -1671,13 +1667,15 @@ static int ov13858_probe(struct i2c_client *client)
if (!ov13858)
return -ENOMEM;
+ ov13858->dev = &client->dev;
+
/* 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 +1697,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 +1709,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 +1720,7 @@ static int ov13858_probe(struct i2c_client *client)
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 +1734,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[] = {
--
Regards,
Laurent Pinchart
^ permalink raw reply related [flat|nested] 115+ messages in thread
* [PATCH 41/72] media: i2c: ov13858: Use V4L2 sensor clock helper
2025-07-10 17:46 [PATCH 00/72] media: i2c: Reduce cargo-cult Laurent Pinchart
` (39 preceding siblings ...)
2025-07-10 17:47 ` [PATCH 40/72] media: i2c: ov13858: Replace client->dev usage Laurent Pinchart
@ 2025-07-10 17:47 ` Laurent Pinchart
2025-07-10 17:47 ` [PATCH 42/72] media: i2c: ov13b10: Replace client->dev usage Laurent Pinchart
` (32 subsequent siblings)
73 siblings, 0 replies; 115+ messages in thread
From: Laurent Pinchart @ 2025-07-10 17:47 UTC (permalink / raw)
To: linux-media; +Cc: Sakari Ailus, Mehdi Djait
Several camera sensor drivers access the "clock-frequency" property
directly to retrieve the external clock rate, or modify the clock rate
of the external clock programmatically. Both behaviours are valid on
a subset of ACPI platforms, but are considered deprecated on OF
platforms, and do not support ACPI platforms that implement MIPI DisCo
for Imaging. Implementing them manually in drivers is deprecated, as
that can encourage cargo-cult and lead to differences in behaviour
between drivers. Instead, drivers should use the
devm_v4l2_sensor_clk_get() helper.
This driver supports ACPI platforms only. It retrieves the clock rate
from the "clock-frequency" property. If the rate does not match the
expected rate, the driver prints a warning. This is correct behaviour
for ACPI.
Switch to using the devm_v4l2_sensor_clk_get() helper. This does not
change the behaviour on ACPI platforms that specify a clock-frequency
property and don't provide a clock. On ACPI platforms that provide a
clock, the clock rate will be set to the value of the clock-frequency
property. This should not change the behaviour either as this driver
expects the clock to be set to that rate, and wouldn't operate correctly
otherwise.
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
drivers/media/i2c/ov13858.c | 19 ++++++++++++++-----
1 file changed, 14 insertions(+), 5 deletions(-)
diff --git a/drivers/media/i2c/ov13858.c b/drivers/media/i2c/ov13858.c
index d93ad730d633..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>
@@ -1029,6 +1030,7 @@ static const struct ov13858_mode supported_modes[] = {
struct ov13858 {
struct device *dev;
+ struct clk *clk;
struct v4l2_subdev sd;
struct media_pad pad;
@@ -1656,12 +1658,8 @@ 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)
@@ -1669,6 +1667,17 @@ static int ov13858_probe(struct i2c_client *client)
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);
--
Regards,
Laurent Pinchart
^ permalink raw reply related [flat|nested] 115+ messages in thread
* [PATCH 42/72] media: i2c: ov13b10: Replace client->dev usage
2025-07-10 17:46 [PATCH 00/72] media: i2c: Reduce cargo-cult Laurent Pinchart
` (40 preceding siblings ...)
2025-07-10 17:47 ` [PATCH 41/72] media: i2c: ov13858: Use V4L2 sensor clock helper Laurent Pinchart
@ 2025-07-10 17:47 ` Laurent Pinchart
2025-07-10 17:47 ` [PATCH 43/72] media: i2c: ov13b10: Use V4L2 sensor clock helper Laurent Pinchart
` (31 subsequent siblings)
73 siblings, 0 replies; 115+ messages in thread
From: Laurent Pinchart @ 2025-07-10 17:47 UTC (permalink / raw)
To: linux-media
Cc: Sakari Ailus, Mehdi Djait, Arec Kao, Liam Girdwood, Mark Brown
The driver needs to access the struct device in many places, and
retrieves it from the i2c_client itself retrieved with
v4l2_get_subdevdata(). Store it as a pointer in struct ov13b10 and
access it from there instead, to simplify the driver.
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
drivers/media/i2c/ov13b10.c | 89 ++++++++++++++++++-------------------
1 file changed, 43 insertions(+), 46 deletions(-)
diff --git a/drivers/media/i2c/ov13b10.c b/drivers/media/i2c/ov13b10.c
index e85c7d33a670..3f17cdd9f42c 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,39 +1470,38 @@ 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);
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_clk_get_optional(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");
+ 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;
@@ -1602,32 +1597,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 +1643,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 +1654,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 +1665,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 +1689,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,
--
Regards,
Laurent Pinchart
^ permalink raw reply related [flat|nested] 115+ messages in thread
* [PATCH 43/72] media: i2c: ov13b10: Use V4L2 sensor clock helper
2025-07-10 17:46 [PATCH 00/72] media: i2c: Reduce cargo-cult Laurent Pinchart
` (41 preceding siblings ...)
2025-07-10 17:47 ` [PATCH 42/72] media: i2c: ov13b10: Replace client->dev usage Laurent Pinchart
@ 2025-07-10 17:47 ` Laurent Pinchart
2025-07-10 17:47 ` [PATCH 44/72] media: i2c: ov2740: Replace client->dev usage Laurent Pinchart
` (30 subsequent siblings)
73 siblings, 0 replies; 115+ messages in thread
From: Laurent Pinchart @ 2025-07-10 17:47 UTC (permalink / raw)
To: linux-media; +Cc: Sakari Ailus, Mehdi Djait, Arec Kao
Several camera sensor drivers access the "clock-frequency" property
directly to retrieve the external clock rate, or modify the clock rate
of the external clock programmatically. Both behaviours are valid on
a subset of ACPI platforms, but are considered deprecated on OF
platforms, and do not support ACPI platforms that implement MIPI DisCo
for Imaging. Implementing them manually in drivers is deprecated, as
that can encourage cargo-cult and lead to differences in behaviour
between drivers. Instead, drivers should use the
devm_v4l2_sensor_clk_get() helper.
This driver supports ACPI platforms only. It retrieves the clock if
present, and retrieves the clock rate from the "clock-frequency"
property. If the rate does not match the expected rate, the driver fails
probing. This is correct behaviour for ACPI.
Switch to using the devm_v4l2_sensor_clk_get() helper. This does not
change the behaviour on ACPI platforms that specify a clock-frequency
property and don't provide a clock. On ACPI platforms that provide a
clock, the clock rate will be set to the value of the clock-frequency
property. This should not change the behaviour either as this driver
expects the clock to be set to that rate, and wouldn't operate correctly
otherwise.
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
drivers/media/i2c/ov13b10.c | 23 ++++++++---------------
1 file changed, 8 insertions(+), 15 deletions(-)
diff --git a/drivers/media/i2c/ov13b10.c b/drivers/media/i2c/ov13b10.c
index 3f17cdd9f42c..869bc78ed792 100644
--- a/drivers/media/i2c/ov13b10.c
+++ b/drivers/media/i2c/ov13b10.c
@@ -1472,6 +1472,7 @@ static void ov13b10_free_controls(struct ov13b10 *ov13b)
static int ov13b10_get_pm_resources(struct ov13b10 *ov13b)
{
+ unsigned long freq;
int ret;
ov13b->reset = devm_gpiod_get_optional(ov13b->dev, "reset", GPIOD_OUT_LOW);
@@ -1479,11 +1480,17 @@ static int ov13b10_get_pm_resources(struct ov13b10 *ov13b)
return dev_err_probe(ov13b->dev, PTR_ERR(ov13b->reset),
"failed to get reset gpio\n");
- ov13b->img_clk = devm_clk_get_optional(ov13b->dev, NULL);
+ ov13b->img_clk = devm_v4l2_sensor_clk_get(ov13b->dev, NULL);
if (IS_ERR(ov13b->img_clk))
return dev_err_probe(ov13b->dev, PTR_ERR(ov13b->img_clk),
"failed to get imaging clock\n");
+ 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);
@@ -1506,7 +1513,6 @@ static int ov13b10_check_hwcfg(struct ov13b10 *ov13b)
struct fwnode_handle *fwnode = dev_fwnode(dev);
unsigned int i, j;
int ret;
- u32 ext_clk;
u8 dlane;
if (!fwnode)
@@ -1516,19 +1522,6 @@ static int ov13b10_check_hwcfg(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)
--
Regards,
Laurent Pinchart
^ permalink raw reply related [flat|nested] 115+ messages in thread
* [PATCH 44/72] media: i2c: ov2740: Replace client->dev usage
2025-07-10 17:46 [PATCH 00/72] media: i2c: Reduce cargo-cult Laurent Pinchart
` (42 preceding siblings ...)
2025-07-10 17:47 ` [PATCH 43/72] media: i2c: ov13b10: Use V4L2 sensor clock helper Laurent Pinchart
@ 2025-07-10 17:47 ` Laurent Pinchart
2025-07-10 17:47 ` [PATCH 45/72] media: i2c: ov2740: Use V4L2 sensor clock helper Laurent Pinchart
` (29 subsequent siblings)
73 siblings, 0 replies; 115+ messages in thread
From: Laurent Pinchart @ 2025-07-10 17:47 UTC (permalink / raw)
To: linux-media; +Cc: Sakari Ailus, Mehdi Djait, Tianshu Qiu, Bingbu Cao
The driver needs to access the struct device in many places, and
retrieves it from the i2c_client itself retrieved with
v4l2_get_subdevdata(). Store it as a pointer in struct ov2740 and access
it from there instead, to simplify the driver.
While at it, fix mistakes in the sort order of include statements.
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
drivers/media/i2c/ov2740.c | 67 ++++++++++++++++++--------------------
1 file changed, 31 insertions(+), 36 deletions(-)
diff --git a/drivers/media/i2c/ov2740.c b/drivers/media/i2c/ov2740.c
index 4e959534e6e7..aedf62df6e93 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 @@ static int ov2740_load_otp_data(struct nvm_data *nvm)
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,10 +1125,9 @@ 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 = {
@@ -1270,7 +1263,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)
@@ -1357,10 +1350,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;
@@ -1397,7 +1392,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 +1430,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 +1442,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:
--
Regards,
Laurent Pinchart
^ permalink raw reply related [flat|nested] 115+ messages in thread
* [PATCH 45/72] media: i2c: ov2740: Use V4L2 sensor clock helper
2025-07-10 17:46 [PATCH 00/72] media: i2c: Reduce cargo-cult Laurent Pinchart
` (43 preceding siblings ...)
2025-07-10 17:47 ` [PATCH 44/72] media: i2c: ov2740: Replace client->dev usage Laurent Pinchart
@ 2025-07-10 17:47 ` Laurent Pinchart
2025-07-10 17:47 ` [PATCH 46/72] media: i2c: ov4689: " Laurent Pinchart
` (28 subsequent siblings)
73 siblings, 0 replies; 115+ messages in thread
From: Laurent Pinchart @ 2025-07-10 17:47 UTC (permalink / raw)
To: linux-media; +Cc: Sakari Ailus, Mehdi Djait, Tianshu Qiu, Bingbu Cao
Several camera sensor drivers access the "clock-frequency" property
directly to retrieve the external clock rate, or modify the clock rate
of the external clock programmatically. Both behaviours are valid on
a subset of ACPI platforms, but are considered deprecated on OF
platforms, and do not support ACPI platforms that implement MIPI DisCo
for Imaging. Implementing them manually in drivers is deprecated, as
that can encourage cargo-cult and lead to differences in behaviour
between drivers. Instead, drivers should use the
devm_v4l2_sensor_clk_get() helper.
This driver supports ACPI platforms only. It retrieves the clock if
present, and retrieves the clock rate from the "clock-frequency"
property. If the rate does not match the expected rate, the driver fails
probing. This is correct behaviour for ACPI.
Switch to using the devm_v4l2_sensor_clk_get() helper. This does not
change the behaviour on ACPI platforms that specify a clock-frequency
property and don't provide a clock. On ACPI platforms that provide a
clock, the clock rate will be set to the value of the clock-frequency
property. This should not change the behaviour either as this driver
expects the clock to be set to that rate, and wouldn't operate correctly
otherwise.
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
drivers/media/i2c/ov2740.c | 24 ++++++++----------------
1 file changed, 8 insertions(+), 16 deletions(-)
diff --git a/drivers/media/i2c/ov2740.c b/drivers/media/i2c/ov2740.c
index aedf62df6e93..fb590dfadda1 100644
--- a/drivers/media/i2c/ov2740.c
+++ b/drivers/media/i2c/ov2740.c
@@ -1133,7 +1133,6 @@ static int ov2740_check_hwcfg(struct ov2740 *ov2740)
struct v4l2_fwnode_endpoint bus_cfg = {
.bus_type = V4L2_MBUS_CSI2_DPHY
};
- u32 mclk;
int ret;
unsigned int i, j;
@@ -1146,20 +1145,6 @@ static int ov2740_check_hwcfg(struct ov2740 *ov2740)
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)
@@ -1342,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;
@@ -1379,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];
--
Regards,
Laurent Pinchart
^ permalink raw reply related [flat|nested] 115+ messages in thread
* [PATCH 46/72] media: i2c: ov4689: Use V4L2 sensor clock helper
2025-07-10 17:46 [PATCH 00/72] media: i2c: Reduce cargo-cult Laurent Pinchart
` (44 preceding siblings ...)
2025-07-10 17:47 ` [PATCH 45/72] media: i2c: ov2740: Use V4L2 sensor clock helper Laurent Pinchart
@ 2025-07-10 17:47 ` Laurent Pinchart
2025-07-10 17:47 ` [PATCH 47/72] media: i2c: ov5670: Replace client->dev usage Laurent Pinchart
` (27 subsequent siblings)
73 siblings, 0 replies; 115+ messages in thread
From: Laurent Pinchart @ 2025-07-10 17:47 UTC (permalink / raw)
To: linux-media; +Cc: Sakari Ailus, Mehdi Djait, Mikhail Rudenko
Several camera sensor drivers access the "clock-frequency" property
directly to retrieve the external clock rate, or modify the clock rate
of the external clock programmatically. Both behaviours are valid on
a subset of ACPI platforms, but are considered deprecated on OF
platforms, and do not support ACPI platforms that implement MIPI DisCo
for Imaging. Implementing them manually in drivers is deprecated, as
that can encourage cargo-cult and lead to differences in behaviour
between drivers. Instead, drivers should use the
devm_v4l2_sensor_clk_get() helper.
This driver supports OF platforms only. The "clocks" property has always
been specified as mandatory in the DT bindings and the "clock-frequency"
property has never been allowed. The driver retrieves the clock and its
rate if present, and falls back to retrieving the rate from the
"clock-frequency" property otherwise. If the rate does not match the
expected rate, the driver fails probing. This is deprecated on OF
platforms, but behaves correctly on platforms that comply with the DT
bindings.
Switch to using the devm_v4l2_sensor_clk_get() helper. This does not
change the behaviour on OF platforms that comply with the DT bindings.
Non-compliant platforms are not expected, but any regression could
easily be handled by switching to the devm_v4l2_sensor_clk_get_legacy()
helper designed to preserve non-compliant behaviour.
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
drivers/media/i2c/ov4689.c | 12 ++----------
1 file changed, 2 insertions(+), 10 deletions(-)
diff --git a/drivers/media/i2c/ov4689.c b/drivers/media/i2c/ov4689.c
index 1c3a449f9354..4e68f8c3d3de 100644
--- a/drivers/media/i2c/ov4689.c
+++ b/drivers/media/i2c/ov4689.c
@@ -909,20 +909,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",
--
Regards,
Laurent Pinchart
^ permalink raw reply related [flat|nested] 115+ messages in thread
* [PATCH 47/72] media: i2c: ov5670: Replace client->dev usage
2025-07-10 17:46 [PATCH 00/72] media: i2c: Reduce cargo-cult Laurent Pinchart
` (45 preceding siblings ...)
2025-07-10 17:47 ` [PATCH 46/72] media: i2c: ov4689: " Laurent Pinchart
@ 2025-07-10 17:47 ` Laurent Pinchart
2025-07-10 17:47 ` [PATCH 48/72] media: i2c: ov5670: Use V4L2 sensor clock helper Laurent Pinchart
` (26 subsequent siblings)
73 siblings, 0 replies; 115+ messages in thread
From: Laurent Pinchart @ 2025-07-10 17:47 UTC (permalink / raw)
To: linux-media; +Cc: Sakari Ailus, Mehdi Djait
The driver needs to access the struct device in many places, and
retrieves it from the i2c_client itself retrieved with
v4l2_get_subdevdata(). Store it as a pointer in struct ov5670 and access
it from there instead, to simplify the driver.
While at it, fix a mistake in the sort order of include statements.
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
drivers/media/i2c/ov5670.c | 99 ++++++++++++++++++--------------------
1 file changed, 47 insertions(+), 52 deletions(-)
diff --git a/drivers/media/i2c/ov5670.c b/drivers/media/i2c/ov5670.c
index b9efb2d2276a..f4af89bda902 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,20 @@ static int ov5670_probe(struct i2c_client *client)
if (!ov5670)
return -ENOMEM;
- ov5670->xvclk = devm_clk_get_optional(&client->dev, NULL);
+ ov5670->dev = &client->dev;
+
+ ov5670->xvclk = devm_clk_get_optional(ov5670->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",
+ device_property_read_u32(ov5670->dev, "clock-frequency",
&input_clk);
else
- return dev_err_probe(&client->dev, PTR_ERR(ov5670->xvclk),
+ return dev_err_probe(ov5670->dev, PTR_ERR(ov5670->xvclk),
"error getting clock\n");
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 +2677,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 +2699,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 +2724,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 +2737,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 +2770,7 @@ static int ov5670_probe(struct i2c_client *client)
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 +2788,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);
}
--
Regards,
Laurent Pinchart
^ permalink raw reply related [flat|nested] 115+ messages in thread
* [PATCH 48/72] media: i2c: ov5670: Use V4L2 sensor clock helper
2025-07-10 17:46 [PATCH 00/72] media: i2c: Reduce cargo-cult Laurent Pinchart
` (46 preceding siblings ...)
2025-07-10 17:47 ` [PATCH 47/72] media: i2c: ov5670: Replace client->dev usage Laurent Pinchart
@ 2025-07-10 17:47 ` Laurent Pinchart
2025-07-10 17:47 ` [PATCH 49/72] media: i2c: ov5675: Replace client->dev usage Laurent Pinchart
` (25 subsequent siblings)
73 siblings, 0 replies; 115+ messages in thread
From: Laurent Pinchart @ 2025-07-10 17:47 UTC (permalink / raw)
To: linux-media; +Cc: Sakari Ailus, Mehdi Djait
Several camera sensor drivers access the "clock-frequency" property
directly to retrieve the external clock rate, or modify the clock rate
of the external clock programmatically. Both behaviours are valid on
a subset of ACPI platforms, but are considered deprecated on OF
platforms, and do not support ACPI platforms that implement MIPI DisCo
for Imaging. Implementing them manually in drivers is deprecated, as
that can encourage cargo-cult and lead to differences in behaviour
between drivers. Instead, drivers should use the
devm_v4l2_sensor_clk_get() helper.
This driver supports ACPI and OF platforms. The "clocks" property has
always been specified as mandatory in the DT bindings, and the
"clock-frequency" property has never been allowed. The driver retrieves
the clock and its rate if present, and falls back to retrieving the rate
from the "clock-frequency" property otherwise. If the rate does not
match the expected rate, the driver fails probing. This is correct
behaviour for ACPI, and for OF platforms that comply with the documented
DT bindings.
Switch to using the devm_v4l2_sensor_clk_get() helper. This does not
change the behaviour on ACPI platforms that specify a clock-frequency
property and don't provide a clock. On ACPI platforms that provide a
clock, the clock rate will be set to the value of the clock-frequency
property. This should not change the behaviour either as this driver
expects the clock to be set to that rate, and wouldn't operate correctly
otherwise.
The behaviour is also unchanged on OF platforms that comply with the DT
bindings. Non-compliant platforms are not expected, but any regression
could easily be handled by switching to the
devm_v4l2_sensor_clk_get_legacy() helper designed to preserve
non-compliant behaviour.
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
drivers/media/i2c/ov5670.c | 10 +++-------
1 file changed, 3 insertions(+), 7 deletions(-)
diff --git a/drivers/media/i2c/ov5670.c b/drivers/media/i2c/ov5670.c
index f4af89bda902..04b3183b7bcb 100644
--- a/drivers/media/i2c/ov5670.c
+++ b/drivers/media/i2c/ov5670.c
@@ -2655,16 +2655,12 @@ static int ov5670_probe(struct i2c_client *client)
ov5670->dev = &client->dev;
- ov5670->xvclk = devm_clk_get_optional(ov5670->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(ov5670->dev, "clock-frequency",
- &input_clk);
- else
+ 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(ov5670->dev,
"Unsupported clock frequency %u\n", input_clk);
--
Regards,
Laurent Pinchart
^ permalink raw reply related [flat|nested] 115+ messages in thread
* [PATCH 49/72] media: i2c: ov5675: Replace client->dev usage
2025-07-10 17:46 [PATCH 00/72] media: i2c: Reduce cargo-cult Laurent Pinchart
` (47 preceding siblings ...)
2025-07-10 17:47 ` [PATCH 48/72] media: i2c: ov5670: Use V4L2 sensor clock helper Laurent Pinchart
@ 2025-07-10 17:47 ` Laurent Pinchart
2025-07-10 17:47 ` [PATCH 50/72] media: i2c: ov5675: Use V4L2 sensor clock helper Laurent Pinchart
` (24 subsequent siblings)
73 siblings, 0 replies; 115+ messages in thread
From: Laurent Pinchart @ 2025-07-10 17:47 UTC (permalink / raw)
To: linux-media; +Cc: Sakari Ailus, Mehdi Djait
The driver needs to access the struct device in many places, and
retrieves it from the i2c_client itself retrieved with
v4l2_get_subdevdata(). Store it as a pointer in struct ov5675 and access
it from there instead, to simplify the driver.
While at it, fix a mistake in the sort order of include statements.
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
drivers/media/i2c/ov5675.c | 74 +++++++++++++++++++-------------------
1 file changed, 36 insertions(+), 38 deletions(-)
diff --git a/drivers/media/i2c/ov5675.c b/drivers/media/i2c/ov5675.c
index e7aec281e9a4..fe16d5439e39 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 = {
@@ -1276,12 +1272,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 +1290,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 +1317,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 +1328,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 +1354,7 @@ static int ov5675_probe(struct i2c_client *client)
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;
}
--
Regards,
Laurent Pinchart
^ permalink raw reply related [flat|nested] 115+ messages in thread
* [PATCH 50/72] media: i2c: ov5675: Use V4L2 sensor clock helper
2025-07-10 17:46 [PATCH 00/72] media: i2c: Reduce cargo-cult Laurent Pinchart
` (48 preceding siblings ...)
2025-07-10 17:47 ` [PATCH 49/72] media: i2c: ov5675: Replace client->dev usage Laurent Pinchart
@ 2025-07-10 17:47 ` Laurent Pinchart
2025-07-10 17:47 ` [PATCH 51/72] media: i2c: ov5693: " Laurent Pinchart
` (23 subsequent siblings)
73 siblings, 0 replies; 115+ messages in thread
From: Laurent Pinchart @ 2025-07-10 17:47 UTC (permalink / raw)
To: linux-media; +Cc: Sakari Ailus, Mehdi Djait
Several camera sensor drivers access the "clock-frequency" property
directly to retrieve the external clock rate, or modify the clock rate
of the external clock programmatically. Both behaviours are valid on
a subset of ACPI platforms, but are considered deprecated on OF
platforms, and do not support ACPI platforms that implement MIPI DisCo
for Imaging. Implementing them manually in drivers is deprecated, as
that can encourage cargo-cult and lead to differences in behaviour
between drivers. Instead, drivers should use the
devm_v4l2_sensor_clk_get() helper.
This driver supports ACPI and OF platforms. The "clocks" property has
always been specified as mandatory in the DT bindings, and the
"clock-frequency" property has never been allowed. The driver retrieves
the clock and its rate if present, and falls back to retrieving the rate
from the "clock-frequency" property otherwise. If the rate does not
match the expected rate, the driver fails probing. This is correct
behaviour for ACPI, and for OF platforms that comply with the documented
DT bindings.
Switch to using the devm_v4l2_sensor_clk_get() helper. This does not
change the behaviour on ACPI platforms that specify a clock-frequency
property and don't provide a clock. On ACPI platforms that provide a
clock, the clock rate will be set to the value of the clock-frequency
property. This should not change the behaviour either as this driver
expects the clock to be set to that rate, and wouldn't operate correctly
otherwise.
The behaviour is also unchanged on OF platforms that comply with the DT
bindings. Non-compliant platforms are not expected, but any regression
could easily be handled by switching to the
devm_v4l2_sensor_clk_get_legacy() helper designed to preserve
non-compliant behaviour.
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
drivers/media/i2c/ov5675.c | 15 ++-------------
1 file changed, 2 insertions(+), 13 deletions(-)
diff --git a/drivers/media/i2c/ov5675.c b/drivers/media/i2c/ov5675.c
index fe16d5439e39..30e27d39ee44 100644
--- a/drivers/media/i2c/ov5675.c
+++ b/drivers/media/i2c/ov5675.c
@@ -1181,24 +1181,13 @@ static int ov5675_get_hwcfg(struct ov5675 *ov5675)
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);
--
Regards,
Laurent Pinchart
^ permalink raw reply related [flat|nested] 115+ messages in thread
* [PATCH 51/72] media: i2c: ov5693: Use V4L2 sensor clock helper
2025-07-10 17:46 [PATCH 00/72] media: i2c: Reduce cargo-cult Laurent Pinchart
` (49 preceding siblings ...)
2025-07-10 17:47 ` [PATCH 50/72] media: i2c: ov5675: Use V4L2 sensor clock helper Laurent Pinchart
@ 2025-07-10 17:47 ` Laurent Pinchart
2025-07-10 17:47 ` [PATCH 52/72] media: i2c: ov7251: " Laurent Pinchart
` (22 subsequent siblings)
73 siblings, 0 replies; 115+ messages in thread
From: Laurent Pinchart @ 2025-07-10 17:47 UTC (permalink / raw)
To: linux-media; +Cc: Sakari Ailus, Mehdi Djait, Daniel Scally
Several camera sensor drivers access the "clock-frequency" property
directly to retrieve the external clock rate, or modify the clock rate
of the external clock programmatically. Both behaviours are valid on
a subset of ACPI platforms, but are considered deprecated on OF
platforms, and do not support ACPI platforms that implement MIPI DisCo
for Imaging. Implementing them manually in drivers is deprecated, as
that can encourage cargo-cult and lead to differences in behaviour
between drivers. Instead, drivers should use the
devm_v4l2_sensor_clk_get() helper.
This driver supports ACPI and OF platforms. The "clocks" property has
always been specified as mandatory in the DT bindings, and the
"clock-frequency" property has never been allowed. The driver retrieves
the clock and its rate if present, and falls back to retrieving the rate
from the "clock-frequency" property otherwise. If the rate does not
match the expected rate, the driver fails probing. This is correct
behaviour for ACPI, and for OF platforms that comply with the documented
DT bindings.
Switch to using the devm_v4l2_sensor_clk_get() helper. This does not
change the behaviour on ACPI platforms that specify a clock-frequency
property and don't provide a clock. On ACPI platforms that provide a
clock, the clock rate will be set to the value of the clock-frequency
property. This should not change the behaviour either as this driver
expects the clock to be set to that rate, and wouldn't operate correctly
otherwise.
The behaviour is also unchanged on OF platforms that comply with the DT
bindings. Non-compliant platforms are not expected, but any regression
could easily be handled by switching to the
devm_v4l2_sensor_clk_get_legacy() helper designed to preserve
non-compliant behaviour.
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
drivers/media/i2c/ov5693.c | 16 ++--------------
1 file changed, 2 insertions(+), 14 deletions(-)
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);
--
Regards,
Laurent Pinchart
^ permalink raw reply related [flat|nested] 115+ messages in thread
* [PATCH 52/72] media: i2c: ov7251: Use V4L2 sensor clock helper
2025-07-10 17:46 [PATCH 00/72] media: i2c: Reduce cargo-cult Laurent Pinchart
` (50 preceding siblings ...)
2025-07-10 17:47 ` [PATCH 51/72] media: i2c: ov5693: " Laurent Pinchart
@ 2025-07-10 17:47 ` Laurent Pinchart
2025-07-10 17:47 ` [PATCH 53/72] media: i2c: ov9734: Replace client->dev usage Laurent Pinchart
` (21 subsequent siblings)
73 siblings, 0 replies; 115+ messages in thread
From: Laurent Pinchart @ 2025-07-10 17:47 UTC (permalink / raw)
To: linux-media; +Cc: Sakari Ailus, Mehdi Djait
Several camera sensor drivers access the "clock-frequency" property
directly to retrieve the external clock rate, or modify the clock rate
of the external clock programmatically. Both behaviours are valid on a
subset of ACPI platforms, but are considered deprecated on OF platforms,
and do not support ACPI platforms that implement MIPI DisCo for Imaging.
Implementing them manually in drivers is deprecated, as that can
encourage cargo-cult and lead to differences in behaviour between
drivers. Instead, drivers should use the devm_v4l2_sensor_clk_get()
helper.
This driver supports ACPI and OF platforms. The "clocks" property has
always been specified as mandatory in the DT bindings and the
"clock-frequency" property has always been optional. The driver
retrieves the clock and its rate if present, and falls back to
retrieving the rate from the "clock-frequency" property otherwise. If
the rate does not match one of the supported rates, the driver fails
probing.
If a clock is available and the "clock-frequency" property is set, the
driver sets the rate of the clock to the value of the property. It does
however use the rate initially retrieved from the clock for further
calculations, which is a bug if the rates don't match, and would prevent
the sensor from functioning properly. We can therefore assume that this
case never occurs, and that the driver behaves correctly for ACPI, and
for OF platforms that comply with the documented DT bindings.
Switch to using the devm_v4l2_sensor_clk_get() helper. This does not
change the behaviour on ACPI platforms that specify a clock-frequency
property and don't provide a clock. On ACPI platforms that provide a
clock, the clock rate will be set to the value of the clock-frequency
property. This should not change the behaviour either as this driver
expects the clock to be set to that rate, and wouldn't operate correctly
otherwise.
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
drivers/media/i2c/ov7251.c | 26 ++------------------------
1 file changed, 2 insertions(+), 24 deletions(-)
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])
--
Regards,
Laurent Pinchart
^ permalink raw reply related [flat|nested] 115+ messages in thread
* [PATCH 53/72] media: i2c: ov9734: Replace client->dev usage
2025-07-10 17:46 [PATCH 00/72] media: i2c: Reduce cargo-cult Laurent Pinchart
` (51 preceding siblings ...)
2025-07-10 17:47 ` [PATCH 52/72] media: i2c: ov7251: " Laurent Pinchart
@ 2025-07-10 17:47 ` Laurent Pinchart
2025-07-10 17:47 ` [PATCH 54/72] media: i2c: ov9734: Use V4L2 sensor clock helper Laurent Pinchart
` (20 subsequent siblings)
73 siblings, 0 replies; 115+ messages in thread
From: Laurent Pinchart @ 2025-07-10 17:47 UTC (permalink / raw)
To: linux-media; +Cc: Sakari Ailus, Mehdi Djait, Tianshu Qiu, Bingbu Cao
The driver needs to access the struct device in many places, and
retrieves it from the i2c_client itself retrieved with
v4l2_get_subdevdata(). Store it as a pointer in struct ov9734 and access
it from there instead, to simplify the driver.
While at it, fix a mistake in the sort order of include statements.
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
drivers/media/i2c/ov9734.c | 58 ++++++++++++++++++--------------------
1 file changed, 28 insertions(+), 30 deletions(-)
diff --git a/drivers/media/i2c/ov9734.c b/drivers/media/i2c/ov9734.c
index cae3aeefb616..d74d99344210 100644
--- a/drivers/media/i2c/ov9734.c
+++ b/drivers/media/i2c/ov9734.c
@@ -1,12 +1,13 @@
// SPDX-License-Identifier: GPL-2.0
// Copyright (c) 2020 Intel Corporation.
-#include <linux/unaligned.h>
#include <linux/acpi.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 +322,8 @@ static const struct ov9734_mode supported_modes[] = {
};
struct ov9734 {
+ struct device *dev;
+
struct v4l2_subdev sd;
struct media_pad pad;
struct v4l2_ctrl_handler ctrl_handler;
@@ -414,7 +417,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 +424,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 +478,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 +493,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 +526,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 +611,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 +618,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 +636,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 +666,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 +805,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 +813,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;
}
@@ -892,8 +888,8 @@ 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);
}
@@ -913,10 +909,12 @@ static int ov9734_probe(struct i2c_client *client)
if (!ov9734)
return -ENOMEM;
+ ov9734->dev = &client->dev;
+
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 +922,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 +933,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 +941,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 +955,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:
--
Regards,
Laurent Pinchart
^ permalink raw reply related [flat|nested] 115+ messages in thread
* [PATCH 54/72] media: i2c: ov9734: Use V4L2 sensor clock helper
2025-07-10 17:46 [PATCH 00/72] media: i2c: Reduce cargo-cult Laurent Pinchart
` (52 preceding siblings ...)
2025-07-10 17:47 ` [PATCH 53/72] media: i2c: ov9734: Replace client->dev usage Laurent Pinchart
@ 2025-07-10 17:47 ` Laurent Pinchart
2025-07-10 17:47 ` [PATCH 55/72] media: v4l2-common: Add legacy camera " Laurent Pinchart
` (19 subsequent siblings)
73 siblings, 0 replies; 115+ messages in thread
From: Laurent Pinchart @ 2025-07-10 17:47 UTC (permalink / raw)
To: linux-media; +Cc: Sakari Ailus, Mehdi Djait, Tianshu Qiu, Bingbu Cao
Several camera sensor drivers access the "clock-frequency" property
directly to retrieve the external clock rate, or modify the clock rate
of the external clock programmatically. Both behaviours are valid on
a subset of ACPI platforms, but are considered deprecated on OF
platforms, and do not support ACPI platforms that implement MIPI DisCo
for Imaging. Implementing them manually in drivers is deprecated, as
that can encourage cargo-cult and lead to differences in behaviour
between drivers. Instead, drivers should use the
devm_v4l2_sensor_clk_get() helper.
This driver supports ACPI platforms only. It retrieves the clock rate
from the "clock-frequency" property. If the rate does not match the
expected rate, the driver fails probing. This is correct behaviour for
ACPI.
Switch to using the devm_v4l2_sensor_clk_get() helper. This does not
change the behaviour on ACPI platforms that specify a clock-frequency
property and don't provide a clock. On ACPI platforms that provide a
clock, the clock rate will be set to the value of the clock-frequency
property. This should not change the behaviour either as this driver
expects the clock to be set to that rate, and wouldn't operate correctly
otherwise.
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
drivers/media/i2c/ov9734.c | 24 ++++++++++++++----------
1 file changed, 14 insertions(+), 10 deletions(-)
diff --git a/drivers/media/i2c/ov9734.c b/drivers/media/i2c/ov9734.c
index d74d99344210..0eaf33807fc9 100644
--- a/drivers/media/i2c/ov9734.c
+++ b/drivers/media/i2c/ov9734.c
@@ -2,6 +2,7 @@
// Copyright (c) 2020 Intel Corporation.
#include <linux/acpi.h>
+#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/i2c.h>
#include <linux/module.h>
@@ -323,6 +324,7 @@ static const struct ov9734_mode supported_modes[] = {
struct ov9734 {
struct device *dev;
+ struct clk *clk;
struct v4l2_subdev sd;
struct media_pad pad;
@@ -828,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;
@@ -896,6 +888,7 @@ static void ov9734_remove(struct i2c_client *client)
static int ov9734_probe(struct i2c_client *client)
{
struct ov9734 *ov9734;
+ unsigned long freq;
int ret;
ret = ov9734_check_hwcfg(&client->dev);
@@ -911,6 +904,17 @@ static int ov9734_probe(struct i2c_client *client)
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) {
--
Regards,
Laurent Pinchart
^ permalink raw reply related [flat|nested] 115+ messages in thread
* [PATCH 55/72] media: v4l2-common: Add legacy camera sensor clock helper
2025-07-10 17:46 [PATCH 00/72] media: i2c: Reduce cargo-cult Laurent Pinchart
` (53 preceding siblings ...)
2025-07-10 17:47 ` [PATCH 54/72] media: i2c: ov9734: Use V4L2 sensor clock helper Laurent Pinchart
@ 2025-07-10 17:47 ` Laurent Pinchart
2025-07-14 12:54 ` Mehdi Djait
2025-07-10 17:47 ` [PATCH 56/72] media: i2c: et8ek8: Drop support for per-mode external clock frequency Laurent Pinchart
` (18 subsequent siblings)
73 siblings, 1 reply; 115+ messages in thread
From: Laurent Pinchart @ 2025-07-10 17:47 UTC (permalink / raw)
To: linux-media
Cc: Sakari Ailus, Mehdi Djait, Hans Verkuil, Nicolas Dufresne,
Tomi Valkeinen, Jonas Karlman, Matthew Majewski,
Niklas Söderlund
The recently introduced devm_v4l2_sensor_clk_get() helper aims at
simplifying sensor drivers by centralizing clock handling code, as well
as reducing cargo-cult and deprecated behaviour.
A set of drivers implement external clock handling in a non-standard
way. This can't be changed as there is a high risk of breaking existing
platforms, but keeping the code as-is creates a risk of new drivers
copying deprecated behaviour.
To fix this, introduce a new devm_v4l2_sensor_clk_get_legacy() helper
and use it in those driver. Compared to devm_v4l2_sensor_clk_get(), the
new helper takes the "clock-frequency" property into account and sets
the external clock rate on OF platforms, and adds the ability to specify
a fixed default or fallback clock rate in case the "clock-frequency"
property is not present.
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
drivers/media/v4l2-core/v4l2-common.c | 39 +++++++++++++++++++------
include/media/v4l2-common.h | 41 ++++++++++++++++++++++++++-
2 files changed, 70 insertions(+), 10 deletions(-)
diff --git a/drivers/media/v4l2-core/v4l2-common.c b/drivers/media/v4l2-core/v4l2-common.c
index cfc78ea6276c..6f140a78e683 100644
--- a/drivers/media/v4l2-core/v4l2-common.c
+++ b/drivers/media/v4l2-core/v4l2-common.c
@@ -703,24 +703,40 @@ int v4l2_link_freq_to_bitmap(struct device *dev, const u64 *fw_link_freqs,
}
EXPORT_SYMBOL_GPL(v4l2_link_freq_to_bitmap);
-struct clk *devm_v4l2_sensor_clk_get(struct device *dev, const char *id)
+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;
- bool of_node;
- u32 rate;
- int ret;
+ u32 rate = clk_rate;
+ int ret = 0;
clk = devm_clk_get_optional(dev, id);
if (IS_ERR(clk))
return clk;
- ret = device_property_read_u32(dev, "clock-frequency", &rate);
- of_node = is_of_node(dev_fwnode(dev));
+ /*
+ * 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 != -EINVAL || !rate)
+ return ERR_PTR(-EINVAL);
+ }
if (clk) {
- if (!ret && !of_node) {
+ /*
+ * On non-OF platforms, or when legacy behaviour is requested,
+ * set the clock rate if a rate has been specified by the caller
+ * of 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",
@@ -731,9 +747,14 @@ struct clk *devm_v4l2_sensor_clk_get(struct device *dev, const char *id)
return clk;
}
- if (!IS_ENABLED(CONFIG_COMMON_CLK) || of_node)
+ /*
+ * 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);
@@ -750,4 +771,4 @@ struct clk *devm_v4l2_sensor_clk_get(struct device *dev, const char *id)
return clk_hw->clk;
}
-EXPORT_SYMBOL_GPL(devm_v4l2_sensor_clk_get);
+EXPORT_SYMBOL_GPL(__devm_v4l2_sensor_clk_get);
diff --git a/include/media/v4l2-common.h b/include/media/v4l2-common.h
index 9d6c236e8f14..d9f32df3942d 100644
--- a/include/media/v4l2-common.h
+++ b/include/media/v4l2-common.h
@@ -621,6 +621,10 @@ 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.
@@ -645,7 +649,42 @@ int v4l2_link_freq_to_bitmap(struct device *dev, const u64 *fw_link_freqs,
*
* Returns a pointer to a struct clk on success or an error pointer on failure.
*/
-struct clk *devm_v4l2_sensor_clk_get(struct device *dev, const char *id);
+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)
{
--
Regards,
Laurent Pinchart
^ permalink raw reply related [flat|nested] 115+ messages in thread
* [PATCH 56/72] media: i2c: et8ek8: Drop support for per-mode external clock frequency
2025-07-10 17:46 [PATCH 00/72] media: i2c: Reduce cargo-cult Laurent Pinchart
` (54 preceding siblings ...)
2025-07-10 17:47 ` [PATCH 55/72] media: v4l2-common: Add legacy camera " Laurent Pinchart
@ 2025-07-10 17:47 ` Laurent Pinchart
2025-07-10 17:47 ` [PATCH 57/72] media: i2c: et8ek8: Use V4L2 legacy sensor clock helper Laurent Pinchart
` (17 subsequent siblings)
73 siblings, 0 replies; 115+ messages in thread
From: Laurent Pinchart @ 2025-07-10 17:47 UTC (permalink / raw)
To: linux-media; +Cc: Sakari Ailus, Mehdi Djait, Pavel Machek
The et8ek8 driver supports programming different external clock
frequencies for different modes, but in practice all modes use a 9.6MHz
external clock. Drop support for this feature and use a hardcoded
frequency, in preparation for further refactoring of external clock
handling.
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
drivers/media/i2c/et8ek8/et8ek8_driver.c | 10 +---------
drivers/media/i2c/et8ek8/et8ek8_mode.c | 9 ---------
drivers/media/i2c/et8ek8/et8ek8_reg.h | 1 -
3 files changed, 1 insertion(+), 19 deletions(-)
diff --git a/drivers/media/i2c/et8ek8/et8ek8_driver.c b/drivers/media/i2c/et8ek8/et8ek8_driver.c
index 4787b2c430f8..d46fe7a0eec2 100644
--- a/drivers/media/i2c/et8ek8/et8ek8_driver.c
+++ b/drivers/media/i2c/et8ek8/et8ek8_driver.c
@@ -816,7 +816,7 @@ 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;
+ unsigned int xclk_freq = 9600000;
int val, rval;
rval = regulator_enable(sensor->vana);
@@ -825,11 +825,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",
@@ -1085,9 +1080,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);
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_ */
--
Regards,
Laurent Pinchart
^ permalink raw reply related [flat|nested] 115+ messages in thread
* [PATCH 57/72] media: i2c: et8ek8: Use V4L2 legacy sensor clock helper
2025-07-10 17:46 [PATCH 00/72] media: i2c: Reduce cargo-cult Laurent Pinchart
` (55 preceding siblings ...)
2025-07-10 17:47 ` [PATCH 56/72] media: i2c: et8ek8: Drop support for per-mode external clock frequency Laurent Pinchart
@ 2025-07-10 17:47 ` Laurent Pinchart
2025-07-10 17:47 ` [PATCH 58/72] media: i2c: gc05a2: " Laurent Pinchart
` (16 subsequent siblings)
73 siblings, 0 replies; 115+ messages in thread
From: Laurent Pinchart @ 2025-07-10 17:47 UTC (permalink / raw)
To: linux-media; +Cc: Sakari Ailus, Mehdi Djait, Pavel Machek
Several camera sensor drivers access the "clock-frequency" property
directly to retrieve the external clock rate, or modify the clock rate
of the external clock programmatically. Both behaviours are valid on a
subset of ACPI platforms, but are considered deprecated on OF platforms,
and do not support ACPI platforms that implement MIPI DisCo for Imaging.
Implementing them manually in drivers is deprecated, as that can
encourage copying deprecated behaviour for OF platforms in new drivers,
and lead to differences in behaviour between drivers. Instead, drivers
that need to preserve the deprecated OF behaviour should use the
devm_v4l2_sensor_clk_get_legacy() helper.
This driver supports OF platforms only. The "clocks" and
"clock-frequency" properties were initially mandatory in the DT bindings
and were both set in the upstream DT sources. The driver retrieves the
clock, retrieves and ignores the clock rate from the clock-frequency
property, and sets the clock rate to a fixed value. This is deprecated
behaviour for OF.
Switch to using the devm_v4l2_sensor_clk_get_legacy() helper. This
preserves setting the clock rate on OF platforms. Should support for OF
platforms that set the clock rate through clock-frequency be considered
unneeded in the future, the driver will only need to switch to
devm_v4l2_sensor_clk_get() without any other change.
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
drivers/media/i2c/et8ek8/et8ek8_driver.c | 19 ++++---------------
1 file changed, 4 insertions(+), 15 deletions(-)
diff --git a/drivers/media/i2c/et8ek8/et8ek8_driver.c b/drivers/media/i2c/et8ek8/et8ek8_driver.c
index d46fe7a0eec2..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 = 9600000;
int val, rval;
rval = regulator_enable(sensor->vana);
@@ -825,12 +824,6 @@ static int et8ek8_power_on(struct et8ek8_sensor *sensor)
return rval;
}
- 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");
@@ -844,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);
@@ -1425,17 +1418,13 @@ static int et8ek8_probe(struct i2c_client *client)
return PTR_ERR(sensor->vana);
}
- sensor->ext_clk = devm_v4l2_sensor_clk_get(dev, NULL);
+ 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);
--
Regards,
Laurent Pinchart
^ permalink raw reply related [flat|nested] 115+ messages in thread
* [PATCH 58/72] media: i2c: gc05a2: Use V4L2 legacy sensor clock helper
2025-07-10 17:46 [PATCH 00/72] media: i2c: Reduce cargo-cult Laurent Pinchart
` (56 preceding siblings ...)
2025-07-10 17:47 ` [PATCH 57/72] media: i2c: et8ek8: Use V4L2 legacy sensor clock helper Laurent Pinchart
@ 2025-07-10 17:47 ` Laurent Pinchart
2025-07-10 17:47 ` [PATCH 59/72] media: i2c: gc08a3: " Laurent Pinchart
` (15 subsequent siblings)
73 siblings, 0 replies; 115+ messages in thread
From: Laurent Pinchart @ 2025-07-10 17:47 UTC (permalink / raw)
To: linux-media; +Cc: Sakari Ailus, Mehdi Djait, Zhi Mao
Several camera sensor drivers access the "clock-frequency" property
directly to retrieve the external clock rate, or modify the clock rate
of the external clock programmatically. Both behaviours are valid on a
subset of ACPI platforms, but are considered deprecated on OF platforms,
and do not support ACPI platforms that implement MIPI DisCo for Imaging.
Implementing them manually in drivers is deprecated, as that can
encourage copying deprecated behaviour for OF platforms in new drivers,
and lead to differences in behaviour between drivers. Instead, drivers
that need to preserve the deprecated OF behaviour should use the
devm_v4l2_sensor_clk_get_legacy() helper.
This driver supports OF platforms only. The "clocks" and
"clock-frequency" properties were initially mandatory in the DT bindings
and were both set in the upstream DT sources. The driver retrieves the
clock, retrieves and ignores the clock rate from the clock-frequency
property, and sets the clock rate to a fixed value. This is deprecated
behaviour for OF.
Switch to using the devm_v4l2_sensor_clk_get_legacy() helper. This
preserves setting the clock rate on OF platforms. Should support for OF
platforms that set the clock rate through clock-frequency be considered
unneeded in the future, the driver will only need to switch to
devm_v4l2_sensor_clk_get() without any other change.
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
drivers/media/i2c/gc05a2.c | 8 ++------
1 file changed, 2 insertions(+), 6 deletions(-)
diff --git a/drivers/media/i2c/gc05a2.c b/drivers/media/i2c/gc05a2.c
index 4dadd25e6c90..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_v4l2_sensor_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,
--
Regards,
Laurent Pinchart
^ permalink raw reply related [flat|nested] 115+ messages in thread
* [PATCH 59/72] media: i2c: gc08a3: Use V4L2 legacy sensor clock helper
2025-07-10 17:46 [PATCH 00/72] media: i2c: Reduce cargo-cult Laurent Pinchart
` (57 preceding siblings ...)
2025-07-10 17:47 ` [PATCH 58/72] media: i2c: gc05a2: " Laurent Pinchart
@ 2025-07-10 17:47 ` Laurent Pinchart
2025-07-10 17:47 ` [PATCH 60/72] media: i2c: imx258: Replace client->dev usage Laurent Pinchart
` (14 subsequent siblings)
73 siblings, 0 replies; 115+ messages in thread
From: Laurent Pinchart @ 2025-07-10 17:47 UTC (permalink / raw)
To: linux-media; +Cc: Sakari Ailus, Mehdi Djait, Zhi Mao
Several camera sensor drivers access the "clock-frequency" property
directly to retrieve the external clock rate, or modify the clock rate
of the external clock programmatically. Both behaviours are valid on a
subset of ACPI platforms, but are considered deprecated on OF platforms,
and do not support ACPI platforms that implement MIPI DisCo for Imaging.
Implementing them manually in drivers is deprecated, as that can
encourage copying deprecated behaviour for OF platforms in new drivers,
and lead to differences in behaviour between drivers. Instead, drivers
that need to preserve the deprecated OF behaviour should use the
devm_v4l2_sensor_clk_get_legacy() helper.
This driver supports OF platforms only. The "clocks" and
"clock-frequency" properties were initially mandatory in the DT bindings
and were both set in the upstream DT sources. The driver retrieves the
clock, retrieves and ignores the clock rate from the clock-frequency
property, and sets the clock rate to a fixed value. This is deprecated
behaviour for OF.
Switch to using the devm_v4l2_sensor_clk_get_legacy() helper. This
preserves setting the clock rate on OF platforms. Should support for OF
platforms that set the clock rate through clock-frequency be considered
unneeded in the future, the driver will only need to switch to
devm_v4l2_sensor_clk_get() without any other change.
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
drivers/media/i2c/gc08a3.c | 8 ++------
1 file changed, 2 insertions(+), 6 deletions(-)
diff --git a/drivers/media/i2c/gc08a3.c b/drivers/media/i2c/gc08a3.c
index 5d38dfa9878e..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_v4l2_sensor_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,
--
Regards,
Laurent Pinchart
^ permalink raw reply related [flat|nested] 115+ messages in thread
* [PATCH 60/72] media: i2c: imx258: Replace client->dev usage
2025-07-10 17:46 [PATCH 00/72] media: i2c: Reduce cargo-cult Laurent Pinchart
` (58 preceding siblings ...)
2025-07-10 17:47 ` [PATCH 59/72] media: i2c: gc08a3: " Laurent Pinchart
@ 2025-07-10 17:47 ` Laurent Pinchart
2025-07-10 17:47 ` [PATCH 61/72] media: i2c: imx258: Use V4L2 legacy sensor clock helper Laurent Pinchart
` (13 subsequent siblings)
73 siblings, 0 replies; 115+ messages in thread
From: Laurent Pinchart @ 2025-07-10 17:47 UTC (permalink / raw)
To: linux-media; +Cc: Sakari Ailus, Mehdi Djait
The driver needs to access the struct device in many places, and
retrieves it from the i2c_client itself retrieved with
v4l2_get_subdevdata(). Store it as a pointer in struct imx258 and access
it from there instead, to simplify the driver.
While at it, fix a mistake in the sort order of include statements.
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
drivers/media/i2c/imx258.c | 100 ++++++++++++++++++-------------------
1 file changed, 49 insertions(+), 51 deletions(-)
diff --git a/drivers/media/i2c/imx258.c b/drivers/media/i2c/imx258.c
index 9e30fce1f223..88d0d7f9d4be 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 @@ static int imx258_set_stream(struct v4l2_subdev *sd, int enable)
/* 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,27 +1361,29 @@ 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_clk_get_optional(imx258->dev, NULL);
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,
+ dev_dbg(imx258->dev,
"no clock provided, using clock-frequency property\n");
- device_property_read_u32(&client->dev, "clock-frequency", &val);
+ device_property_read_u32(imx258->dev, "clock-frequency", &val);
} else {
val = clk_get_rate(imx258->clk);
}
@@ -1400,32 +1398,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 +1436,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 +1444,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 +1452,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 +1484,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 +1498,7 @@ static int imx258_probe(struct i2c_client *client)
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 +1515,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 = {
--
Regards,
Laurent Pinchart
^ permalink raw reply related [flat|nested] 115+ messages in thread
* [PATCH 61/72] media: i2c: imx258: Use V4L2 legacy sensor clock helper
2025-07-10 17:46 [PATCH 00/72] media: i2c: Reduce cargo-cult Laurent Pinchart
` (59 preceding siblings ...)
2025-07-10 17:47 ` [PATCH 60/72] media: i2c: imx258: Replace client->dev usage Laurent Pinchart
@ 2025-07-10 17:47 ` Laurent Pinchart
2025-07-10 17:47 ` [PATCH 62/72] media: i2c: imx290: " Laurent Pinchart
` (12 subsequent siblings)
73 siblings, 0 replies; 115+ messages in thread
From: Laurent Pinchart @ 2025-07-10 17:47 UTC (permalink / raw)
To: linux-media; +Cc: Sakari Ailus, Mehdi Djait
Several camera sensor drivers access the "clock-frequency" property
directly to retrieve the external clock rate, or modify the clock rate
of the external clock programmatically. Both behaviours are valid on a
subset of ACPI platforms, but are considered deprecated on OF platforms,
and do not support ACPI platforms that implement MIPI DisCo for Imaging.
Implementing them manually in drivers is deprecated, as that can
encourage copying deprecated behaviour for OF platforms in new drivers,
and lead to differences in behaviour between drivers. Instead, drivers
that need to preserve the deprecated OF behaviour should use the
devm_v4l2_sensor_clk_get_legacy() helper.
This driver supports ACPI and OF platforms. The "clocks" property was
not initially specified as mandatory in the DT bindings, and the
"clock-frequency" property has never been allowed. The driver retrieves
the clock and its rate if present, and falls back to retrieving the rate
from the "clock-frequency" property otherwise. If the rate does not
match the expected rate, the driver fails probing. This is correct
behaviour for ACPI, and deprecated behaviour for OF.
Switch to using the devm_v4l2_sensor_clk_get_legacy() helper. This
preserves setting the clock rate on OF platforms. Should support for OF
platforms that set the clock rate through clock-frequency be considered
unneeded in the future, the driver will only need to switch to
devm_v4l2_sensor_clk_get() without any other change.
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
drivers/media/i2c/imx258.c | 11 +++--------
1 file changed, 3 insertions(+), 8 deletions(-)
diff --git a/drivers/media/i2c/imx258.c b/drivers/media/i2c/imx258.c
index 88d0d7f9d4be..e50dcfd830f5 100644
--- a/drivers/media/i2c/imx258.c
+++ b/drivers/media/i2c/imx258.c
@@ -1375,18 +1375,13 @@ static int imx258_probe(struct i2c_client *client)
return dev_err_probe(imx258->dev, ret,
"failed to get regulators\n");
- imx258->clk = devm_clk_get_optional(imx258->dev, NULL);
+ imx258->clk = devm_v4l2_sensor_clk_get_legacy(imx258->dev, NULL, false,
+ 0);
if (IS_ERR(imx258->clk))
return dev_err_probe(imx258->dev, PTR_ERR(imx258->clk),
"error getting clock\n");
- if (!imx258->clk) {
- dev_dbg(imx258->dev,
- "no clock provided, using clock-frequency property\n");
- device_property_read_u32(imx258->dev, "clock-frequency", &val);
- } else {
- val = clk_get_rate(imx258->clk);
- }
+ val = clk_get_rate(imx258->clk);
switch (val) {
case 19200000:
--
Regards,
Laurent Pinchart
^ permalink raw reply related [flat|nested] 115+ messages in thread
* [PATCH 62/72] media: i2c: imx290: Use V4L2 legacy sensor clock helper
2025-07-10 17:46 [PATCH 00/72] media: i2c: Reduce cargo-cult Laurent Pinchart
` (60 preceding siblings ...)
2025-07-10 17:47 ` [PATCH 61/72] media: i2c: imx258: Use V4L2 legacy sensor clock helper Laurent Pinchart
@ 2025-07-10 17:47 ` Laurent Pinchart
2025-07-10 17:47 ` [PATCH 63/72] media: i2c: ov02a10: Replace client->dev usage Laurent Pinchart
` (11 subsequent siblings)
73 siblings, 0 replies; 115+ messages in thread
From: Laurent Pinchart @ 2025-07-10 17:47 UTC (permalink / raw)
To: linux-media; +Cc: Sakari Ailus, Mehdi Djait, Manivannan Sadhasivam
Several camera sensor drivers access the "clock-frequency" property
directly to retrieve the external clock rate, or modify the clock rate
of the external clock programmatically. Both behaviours are valid on a
subset of ACPI platforms, but are considered deprecated on OF platforms,
and do not support ACPI platforms that implement MIPI DisCo for Imaging.
Implementing them manually in drivers is deprecated, as that can
encourage copying deprecated behaviour for OF platforms in new drivers,
and lead to differences in behaviour between drivers. Instead, drivers
that need to preserve the deprecated OF behaviour should use the
devm_v4l2_sensor_clk_get_legacy() helper.
This driver supports OF platforms only. The "clocks" and
"clock-frequency" properties were initially mandatory in the DT
bindings. The driver retrieves the clock, retrieves the clock rate from
the "clock-frequency" property, and sets the clock rate to the retrieved
rate. If the rate does not match one of the expected rates, the driver
fails probing. This is deprecated behaviour for OF.
Switch to using the devm_v4l2_sensor_clk_get_legacy() helper. This
preserves setting the clock rate on OF platforms. Should support for OF
platforms that set the clock rate through clock-frequency be considered
unneeded in the future, the driver will only need to switch to
devm_v4l2_sensor_clk_get() without any other change.
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
drivers/media/i2c/imx290.c | 27 ++++++++-------------------
1 file changed, 8 insertions(+), 19 deletions(-)
diff --git a/drivers/media/i2c/imx290.c b/drivers/media/i2c/imx290.c
index 81c0af959df4..8b11f5030220 100644
--- a/drivers/media/i2c/imx290.c
+++ b/drivers/media/i2c/imx290.c
@@ -1425,14 +1425,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) {
@@ -1448,12 +1448,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;
}
@@ -1599,11 +1593,6 @@ static int imx290_probe(struct i2c_client *client)
return ret;
/* Acquire resources. */
- imx290->xclk = devm_v4l2_sensor_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");
@@ -1614,7 +1603,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;
--
Regards,
Laurent Pinchart
^ permalink raw reply related [flat|nested] 115+ messages in thread
* [PATCH 63/72] media: i2c: ov02a10: Replace client->dev usage
2025-07-10 17:46 [PATCH 00/72] media: i2c: Reduce cargo-cult Laurent Pinchart
` (61 preceding siblings ...)
2025-07-10 17:47 ` [PATCH 62/72] media: i2c: imx290: " Laurent Pinchart
@ 2025-07-10 17:47 ` Laurent Pinchart
2025-07-10 17:48 ` [PATCH 64/72] media: i2c: ov02a10: Use V4L2 legacy sensor clock helper Laurent Pinchart
` (10 subsequent siblings)
73 siblings, 0 replies; 115+ messages in thread
From: Laurent Pinchart @ 2025-07-10 17:47 UTC (permalink / raw)
To: linux-media; +Cc: Sakari Ailus, Mehdi Djait
The driver needs to access the struct device in many places, and
retrieves it from the i2c_client itself retrieved with
v4l2_get_subdevdata(). Store it as a pointer in struct ov02a10 and
access it from there instead, to simplify the driver.
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
drivers/media/i2c/ov02a10.c | 31 ++++++++++++++++---------------
1 file changed, 16 insertions(+), 15 deletions(-)
diff --git a/drivers/media/i2c/ov02a10.c b/drivers/media/i2c/ov02a10.c
index 74fc0687c849..6217164a7492 100644
--- a/drivers/media/i2c/ov02a10.c
+++ b/drivers/media/i2c/ov02a10.c
@@ -100,6 +100,8 @@ struct ov02a10_mode {
};
struct ov02a10 {
+ struct device *dev;
+
u32 eclk_freq;
/* Indication of MIPI transmission speed select */
u32 mipi_clock_voltage;
@@ -392,7 +394,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 +483,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 +532,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 +542,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 +554,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 +563,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 +663,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 +678,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 +699,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 +734,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 +789,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 +865,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,
@@ -985,10 +986,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);
}
--
Regards,
Laurent Pinchart
^ permalink raw reply related [flat|nested] 115+ messages in thread
* [PATCH 64/72] media: i2c: ov02a10: Use V4L2 legacy sensor clock helper
2025-07-10 17:46 [PATCH 00/72] media: i2c: Reduce cargo-cult Laurent Pinchart
` (62 preceding siblings ...)
2025-07-10 17:47 ` [PATCH 63/72] media: i2c: ov02a10: Replace client->dev usage Laurent Pinchart
@ 2025-07-10 17:48 ` Laurent Pinchart
2025-07-10 17:48 ` [PATCH 65/72] media: i2c: ov2685: " Laurent Pinchart
` (9 subsequent siblings)
73 siblings, 0 replies; 115+ messages in thread
From: Laurent Pinchart @ 2025-07-10 17:48 UTC (permalink / raw)
To: linux-media; +Cc: Sakari Ailus, Mehdi Djait
Several camera sensor drivers access the "clock-frequency" property
directly to retrieve the external clock rate, or modify the clock rate
of the external clock programmatically. Both behaviours are valid on a
subset of ACPI platforms, but are considered deprecated on OF platforms,
and do not support ACPI platforms that implement MIPI DisCo for Imaging.
Implementing them manually in drivers is deprecated, as that can
encourage copying deprecated behaviour for OF platforms in new drivers,
and lead to differences in behaviour between drivers. Instead, drivers
that need to preserve the deprecated OF behaviour should use the
devm_v4l2_sensor_clk_get_legacy() helper.
This driver supports OF platforms only. The "clocks" and
"clock-frequency" properties were initially mandatory in the DT
bindings. The driver retrieves the clock, retrieves the clock rate from
the "clock-frequency" property, and sets the clock rate to the retrieved
rate. If the rate does not match one of the expected rates, the driver
fails probing. This is deprecated behaviour for OF.
Switch to using the devm_v4l2_sensor_clk_get_legacy() helper. This
preserves setting the clock rate on OF platforms. Should support for OF
platforms that set the clock rate through clock-frequency be considered
unneeded in the future, the driver will only need to switch to
devm_v4l2_sensor_clk_get() without any other change.
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
drivers/media/i2c/ov02a10.c | 14 +-------------
1 file changed, 1 insertion(+), 13 deletions(-)
diff --git a/drivers/media/i2c/ov02a10.c b/drivers/media/i2c/ov02a10.c
index 6217164a7492..70d9d7c43f18 100644
--- a/drivers/media/i2c/ov02a10.c
+++ b/drivers/media/i2c/ov02a10.c
@@ -102,7 +102,6 @@ struct ov02a10_mode {
struct ov02a10 {
struct device *dev;
- u32 eclk_freq;
/* Indication of MIPI transmission speed select */
u32 mipi_clock_voltage;
@@ -886,22 +885,11 @@ static int ov02a10_probe(struct i2c_client *client)
ov02a10->fmt.code = MEDIA_BUS_FMT_SRGGB10_1X10;
}
- ov02a10->eclk = devm_v4l2_sensor_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");
--
Regards,
Laurent Pinchart
^ permalink raw reply related [flat|nested] 115+ messages in thread
* [PATCH 65/72] media: i2c: ov2685: Use V4L2 legacy sensor clock helper
2025-07-10 17:46 [PATCH 00/72] media: i2c: Reduce cargo-cult Laurent Pinchart
` (63 preceding siblings ...)
2025-07-10 17:48 ` [PATCH 64/72] media: i2c: ov02a10: Use V4L2 legacy sensor clock helper Laurent Pinchart
@ 2025-07-10 17:48 ` Laurent Pinchart
2025-07-10 17:48 ` [PATCH 66/72] media: i2c: ov5645: " Laurent Pinchart
` (8 subsequent siblings)
73 siblings, 0 replies; 115+ messages in thread
From: Laurent Pinchart @ 2025-07-10 17:48 UTC (permalink / raw)
To: linux-media; +Cc: Sakari Ailus, Mehdi Djait, Shunqian Zheng
Several camera sensor drivers access the "clock-frequency" property
directly to retrieve the external clock rate, or modify the clock rate
of the external clock programmatically. Both behaviours are valid on a
subset of ACPI platforms, but are considered deprecated on OF platforms,
and do not support ACPI platforms that implement MIPI DisCo for Imaging.
Implementing them manually in drivers is deprecated, as that can
encourage copying deprecated behaviour for OF platforms in new drivers,
and lead to differences in behaviour between drivers. Instead, drivers
that need to preserve the deprecated OF behaviour should use the
devm_v4l2_sensor_clk_get_legacy() helper.
This driver supports OF platforms only. The "clocks" property has always
been specified as mandatory in the DT bindings and the "clock-frequency"
property has never been allowed. The "clocks" property has always been
set in the upstream DT sources, and the "clock-frequency" never. The
driver retrieves the clock, and sets its rate to a fixed value. This is
deprecated behaviour for OF.
Switch to using the devm_v4l2_sensor_clk_get_legacy() helper. This
preserves setting the clock rate on OF platforms. Should support for OF
platforms that set the clock rate through clock-frequency be considered
unneeded in the future, the driver will only need to switch to
devm_v4l2_sensor_clk_get() without any other change.
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
drivers/media/i2c/ov2685.c | 8 ++------
1 file changed, 2 insertions(+), 6 deletions(-)
diff --git a/drivers/media/i2c/ov2685.c b/drivers/media/i2c/ov2685.c
index c435799514b9..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_v4l2_sensor_clk_get(dev, "xvclk");
+ 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");
- ret = clk_set_rate(ov2685->xvclk, OV2685_XVCLK_FREQ);
- if (ret < 0) {
- dev_err(dev, "Failed to set xvclk rate (24MHz)\n");
- return ret;
- }
if (clk_get_rate(ov2685->xvclk) != OV2685_XVCLK_FREQ)
dev_warn(dev, "xvclk mismatched, modes are based on 24MHz\n");
--
Regards,
Laurent Pinchart
^ permalink raw reply related [flat|nested] 115+ messages in thread
* [PATCH 66/72] media: i2c: ov5645: Use V4L2 legacy sensor clock helper
2025-07-10 17:46 [PATCH 00/72] media: i2c: Reduce cargo-cult Laurent Pinchart
` (64 preceding siblings ...)
2025-07-10 17:48 ` [PATCH 65/72] media: i2c: ov2685: " Laurent Pinchart
@ 2025-07-10 17:48 ` Laurent Pinchart
2025-07-10 17:48 ` [PATCH 67/72] media: i2c: ov5695: " Laurent Pinchart
` (7 subsequent siblings)
73 siblings, 0 replies; 115+ messages in thread
From: Laurent Pinchart @ 2025-07-10 17:48 UTC (permalink / raw)
To: linux-media; +Cc: Sakari Ailus, Mehdi Djait
Several camera sensor drivers access the "clock-frequency" property
directly to retrieve the external clock rate, or modify the clock rate
of the external clock programmatically. Both behaviours are valid on a
subset of ACPI platforms, but are considered deprecated on OF platforms,
and do not support ACPI platforms that implement MIPI DisCo for Imaging.
Implementing them manually in drivers is deprecated, as that can
encourage copying deprecated behaviour for OF platforms in new drivers,
and lead to differences in behaviour between drivers. Instead, drivers
that need to preserve the deprecated OF behaviour should use the
devm_v4l2_sensor_clk_get_legacy() helper.
This driver supports OF platforms only. The "clocks" property has always
been specified as mandatory in the DT bindings and the "clock-frequency"
property has always been optional. Both the "clocks" and
"clock-frequency" properties are set in the upstream DT sources. The
driver retrieves the clock, retrieves the clock rate from the
"clock-frequency" property, and sets the clock rate to the retrieved
rate. If the rate does not match the expected rates, the driver fails
probing. This is deprecated behaviour for OF.
Switch to using the devm_v4l2_sensor_clk_get_legacy() helper. This
preserves setting the clock rate on OF platforms. Should support for OF
platforms that set the clock rate through clock-frequency be considered
unneeded in the future, the driver will only need to switch to
devm_v4l2_sensor_clk_get() without any other change.
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
drivers/media/i2c/ov5645.c | 13 ++-----------
1 file changed, 2 insertions(+), 11 deletions(-)
diff --git a/drivers/media/i2c/ov5645.c b/drivers/media/i2c/ov5645.c
index 70b4cdb1b9af..a383e1a41b17 100644
--- a/drivers/media/i2c/ov5645.c
+++ b/drivers/media/i2c/ov5645.c
@@ -1044,27 +1044,18 @@ static int ov5645_probe(struct i2c_client *client)
"invalid bus type, must be CSI2\n");
/* get system clock (xclk) */
- ov5645->xclk = devm_v4l2_sensor_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];
--
Regards,
Laurent Pinchart
^ permalink raw reply related [flat|nested] 115+ messages in thread
* [PATCH 67/72] media: i2c: ov5695: Use V4L2 legacy sensor clock helper
2025-07-10 17:46 [PATCH 00/72] media: i2c: Reduce cargo-cult Laurent Pinchart
` (65 preceding siblings ...)
2025-07-10 17:48 ` [PATCH 66/72] media: i2c: ov5645: " Laurent Pinchart
@ 2025-07-10 17:48 ` Laurent Pinchart
2025-07-10 17:48 ` [PATCH 68/72] media: i2c: ov8856: Replace client->dev usage Laurent Pinchart
` (6 subsequent siblings)
73 siblings, 0 replies; 115+ messages in thread
From: Laurent Pinchart @ 2025-07-10 17:48 UTC (permalink / raw)
To: linux-media; +Cc: Sakari Ailus, Mehdi Djait, Shunqian Zheng
Several camera sensor drivers access the "clock-frequency" property
directly to retrieve the external clock rate, or modify the clock rate
of the external clock programmatically. Both behaviours are valid on a
subset of ACPI platforms, but are considered deprecated on OF platforms,
and do not support ACPI platforms that implement MIPI DisCo for Imaging.
Implementing them manually in drivers is deprecated, as that can
encourage copying deprecated behaviour for OF platforms in new drivers,
and lead to differences in behaviour between drivers. Instead, drivers
that need to preserve the deprecated OF behaviour should use the
devm_v4l2_sensor_clk_get_legacy() helper.
This driver supports OF platforms only. The "clocks" property has always
been specified as mandatory in the DT bindings and the "clock-frequency"
property has never been allowed. The "clocks" property is set in the
upstream DT sources and the "clock-frequency" property isn't. The driver
retrieves the clock and sets its rate to a fixed value. It then
retrieves the rate from the clock, and fails probing if the value
doesn't match. This is deprecated behaviour for OF.
Switch to using the devm_v4l2_sensor_clk_get_legacy() helper. This
preserves setting the clock rate on OF platforms. Should support for OF
platforms that set the clock rate through clock-frequency be considered
unneeded in the future, the driver will only need to switch to
devm_v4l2_sensor_clk_get() without any other change.
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
drivers/media/i2c/ov5695.c | 8 ++------
1 file changed, 2 insertions(+), 6 deletions(-)
diff --git a/drivers/media/i2c/ov5695.c b/drivers/media/i2c/ov5695.c
index fe7ad7b2c05a..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_v4l2_sensor_clk_get(dev, "xvclk");
+ 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");
- ret = clk_set_rate(ov5695->xvclk, OV5695_XVCLK_FREQ);
- if (ret < 0) {
- dev_err(dev, "Failed to set xvclk rate (24MHz)\n");
- return ret;
- }
if (clk_get_rate(ov5695->xvclk) != OV5695_XVCLK_FREQ)
dev_warn(dev, "xvclk mismatched, modes are based on 24MHz\n");
--
Regards,
Laurent Pinchart
^ permalink raw reply related [flat|nested] 115+ messages in thread
* [PATCH 68/72] media: i2c: ov8856: Replace client->dev usage
2025-07-10 17:46 [PATCH 00/72] media: i2c: Reduce cargo-cult Laurent Pinchart
` (66 preceding siblings ...)
2025-07-10 17:48 ` [PATCH 67/72] media: i2c: ov5695: " Laurent Pinchart
@ 2025-07-10 17:48 ` Laurent Pinchart
2025-07-10 17:48 ` [PATCH 69/72] media: i2c: ov8856: Use V4L2 legacy sensor clock helper Laurent Pinchart
` (5 subsequent siblings)
73 siblings, 0 replies; 115+ messages in thread
From: Laurent Pinchart @ 2025-07-10 17:48 UTC (permalink / raw)
To: linux-media; +Cc: Sakari Ailus, Mehdi Djait
The driver needs to access the struct device in many places, and
retrieves it from the i2c_client itself retrieved with
v4l2_get_subdevdata(). Store it as a pointer in struct ov8856 and access
it from there instead, to simplify the driver.
While at it, fix a mistake in the sort order of include statements.
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
drivers/media/i2c/ov8856.c | 69 +++++++++++++++++++-------------------
1 file changed, 34 insertions(+), 35 deletions(-)
diff --git a/drivers/media/i2c/ov8856.c b/drivers/media/i2c/ov8856.c
index b85051f053ff..674ee36e394c 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 = {
@@ -2363,10 +2360,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)
@@ -2379,23 +2376,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;
}
}
@@ -2405,7 +2404,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;
}
@@ -2416,22 +2415,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;
@@ -2443,7 +2442,7 @@ static int ov8856_probe(struct i2c_client *client)
mutex_destroy(&ov8856->mutex);
probe_power_off:
- ov8856_power_off(&client->dev);
+ ov8856_power_off(ov8856->dev);
return ret;
}
--
Regards,
Laurent Pinchart
^ permalink raw reply related [flat|nested] 115+ messages in thread
* [PATCH 69/72] media: i2c: ov8856: Use V4L2 legacy sensor clock helper
2025-07-10 17:46 [PATCH 00/72] media: i2c: Reduce cargo-cult Laurent Pinchart
` (67 preceding siblings ...)
2025-07-10 17:48 ` [PATCH 68/72] media: i2c: ov8856: Replace client->dev usage Laurent Pinchart
@ 2025-07-10 17:48 ` Laurent Pinchart
2025-07-10 17:48 ` [PATCH 70/72] media: i2c: s5c73m3: " Laurent Pinchart
` (4 subsequent siblings)
73 siblings, 0 replies; 115+ messages in thread
From: Laurent Pinchart @ 2025-07-10 17:48 UTC (permalink / raw)
To: linux-media; +Cc: Sakari Ailus, Mehdi Djait
Several camera sensor drivers access the "clock-frequency" property
directly to retrieve the external clock rate, or modify the clock rate
of the external clock programmatically. Both behaviours are valid on a
subset of ACPI platforms, but are considered deprecated on OF platforms,
and do not support ACPI platforms that implement MIPI DisCo for Imaging.
Implementing them manually in drivers is deprecated, as that can
encourage copying deprecated behaviour for OF platforms in new drivers,
and lead to differences in behaviour between drivers. Instead, drivers
that need to preserve the deprecated OF behaviour should use the
devm_v4l2_sensor_clk_get_legacy() helper.
This driver supports ACPI and OF platforms. The "clocks" and
"clock-frequency" properties were initially specified as mandatory in
the DT bindings and were both set in the upstream DT sources. The driver
retrieves the clock rate from the "clock-frequency" property. On OF
platforms, it retrieves the clock and sets its rate. If the rate does
not match the expected rate, the driver prints a warning. This is
correct behaviour for ACPI, and deprecated behaviour for OF.
Switch to using the devm_v4l2_sensor_clk_get_legacy() helper. This
preserves setting the clock rate on OF platforms. Should support for OF
platforms that set the clock rate through clock-frequency be considered
unneeded in the future, the driver will only need to switch to
devm_v4l2_sensor_clk_get() without any other change.
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
drivers/media/i2c/ov8856.c | 24 +++++++++---------------
1 file changed, 9 insertions(+), 15 deletions(-)
diff --git a/drivers/media/i2c/ov8856.c b/drivers/media/i2c/ov8856.c
index 674ee36e394c..e2998cfa0d18 100644
--- a/drivers/media/i2c/ov8856.c
+++ b/drivers/media/i2c/ov8856.c
@@ -2266,19 +2266,17 @@ static int ov8856_get_hwcfg(struct ov8856 *ov8856)
if (!fwnode)
return -ENXIO;
- ret = fwnode_property_read_u32(fwnode, "clock-frequency", &xvclk_rate);
- if (ret)
- return ret;
+ 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");
+
+ 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->xvclk = devm_v4l2_sensor_clk_get(dev, "xvclk");
- 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);
-
ov8856->reset_gpio = devm_gpiod_get_optional(dev, "reset",
GPIOD_OUT_LOW);
if (IS_ERR(ov8856->reset_gpio))
@@ -2294,10 +2292,6 @@ static int ov8856_get_hwcfg(struct ov8856 *ov8856)
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;
--
Regards,
Laurent Pinchart
^ permalink raw reply related [flat|nested] 115+ messages in thread
* [PATCH 70/72] media: i2c: s5c73m3: Use V4L2 legacy sensor clock helper
2025-07-10 17:46 [PATCH 00/72] media: i2c: Reduce cargo-cult Laurent Pinchart
` (68 preceding siblings ...)
2025-07-10 17:48 ` [PATCH 69/72] media: i2c: ov8856: Use V4L2 legacy sensor clock helper Laurent Pinchart
@ 2025-07-10 17:48 ` Laurent Pinchart
2025-07-10 17:48 ` [PATCH 71/72] media: i2c: s5k5baf: " Laurent Pinchart
` (3 subsequent siblings)
73 siblings, 0 replies; 115+ messages in thread
From: Laurent Pinchart @ 2025-07-10 17:48 UTC (permalink / raw)
To: linux-media; +Cc: Sakari Ailus, Mehdi Djait, Sylwester Nawrocki, Andrzej Hajda
Several camera sensor drivers access the "clock-frequency" property
directly to retrieve the external clock rate, or modify the clock rate
of the external clock programmatically. Both behaviours are valid on a
subset of ACPI platforms, but are considered deprecated on OF platforms,
and do not support ACPI platforms that implement MIPI DisCo for Imaging.
Implementing them manually in drivers is deprecated, as that can
encourage copying deprecated behaviour for OF platforms in new drivers,
and lead to differences in behaviour between drivers. Instead, drivers
that need to preserve the deprecated OF behaviour should use the
devm_v4l2_sensor_clk_get_legacy() helper.
This driver supports OF platforms only. No DT bindings are available.
The "clocks" and "clock-frequency" properties were initially both set in
the upstream DT sources. The driver retrieves the clock, retrieves the
clock rate from the "clock-frequency" property if available or uses a
fixed default otherwise, and sets the clock rate. This is deprecated
behaviour for OF.
Switch to using the devm_v4l2_sensor_clk_get_legacy() helper. This
preserves setting the clock rate on OF platforms. Should support for OF
platforms that set the clock rate through clock-frequency be considered
unneeded in the future, the driver will only need to switch to
devm_v4l2_sensor_clk_get() without any other change.
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
drivers/media/i2c/s5c73m3/s5c73m3-core.c | 15 +++------------
drivers/media/i2c/s5c73m3/s5c73m3.h | 2 --
2 files changed, 3 insertions(+), 14 deletions(-)
diff --git a/drivers/media/i2c/s5c73m3/s5c73m3-core.c b/drivers/media/i2c/s5c73m3/s5c73m3-core.c
index 088184da5dea..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,19 +1552,14 @@ static int s5c73m3_get_dt_data(struct s5c73m3 *state)
if (!node)
return -EINVAL;
- state->clock = devm_v4l2_sensor_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 dev_err_probe(dev, PTR_ERR(state->clock),
"Failed to get the clock %s\n",
S5C73M3_CLK_NAME);
- 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);
- }
-
/* Request GPIO lines asserted */
state->stby = devm_gpiod_get(dev, "standby", GPIOD_OUT_HIGH);
if (IS_ERR(state->stby))
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;
--
Regards,
Laurent Pinchart
^ permalink raw reply related [flat|nested] 115+ messages in thread
* [PATCH 71/72] media: i2c: s5k5baf: Use V4L2 legacy sensor clock helper
2025-07-10 17:46 [PATCH 00/72] media: i2c: Reduce cargo-cult Laurent Pinchart
` (69 preceding siblings ...)
2025-07-10 17:48 ` [PATCH 70/72] media: i2c: s5c73m3: " Laurent Pinchart
@ 2025-07-10 17:48 ` Laurent Pinchart
2025-07-10 17:48 ` [PATCH 72/72] media: i2c: s5k6a3: " Laurent Pinchart
` (2 subsequent siblings)
73 siblings, 0 replies; 115+ messages in thread
From: Laurent Pinchart @ 2025-07-10 17:48 UTC (permalink / raw)
To: linux-media; +Cc: Sakari Ailus, Mehdi Djait, Sylwester Nawrocki, Andrzej Hajda
Several camera sensor drivers access the "clock-frequency" property
directly to retrieve the external clock rate, or modify the clock rate
of the external clock programmatically. Both behaviours are valid on a
subset of ACPI platforms, but are considered deprecated on OF platforms,
and do not support ACPI platforms that implement MIPI DisCo for Imaging.
Implementing them manually in drivers is deprecated, as that can
encourage copying deprecated behaviour for OF platforms in new drivers,
and lead to differences in behaviour between drivers. Instead, drivers
that need to preserve the deprecated OF behaviour should use the
devm_v4l2_sensor_clk_get_legacy() helper.
This driver supports OF platforms only. The "clocks" property has always
been specified as mandatory in the DT bindings and the "clock-frequency"
property has always been optional. Both properties were initially set in
the upstream DT sources. The driver retrieves the clock, retrieves the
clock rate from the "clock-frequency" property if available or uses a
fixed default otherwise, and sets the clock rate. This is deprecated
behaviour for OF.
Switch to using the devm_v4l2_sensor_clk_get_legacy() helper. This
preserves setting the clock rate on OF platforms. Should support for OF
platforms that set the clock rate through clock-frequency be considered
unneeded in the future, the driver will only need to switch to
devm_v4l2_sensor_clk_get() without any other change.
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
drivers/media/i2c/s5k5baf.c | 19 ++++---------------
1 file changed, 4 insertions(+), 15 deletions(-)
diff --git a/drivers/media/i2c/s5k5baf.c b/drivers/media/i2c/s5k5baf.c
index 01d37f49e5ad..89bd951075f4 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,7 +1954,9 @@ static int s5k5baf_probe(struct i2c_client *c)
if (ret < 0)
goto err_me;
- state->clock = devm_v4l2_sensor_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;
goto err_me;
--
Regards,
Laurent Pinchart
^ permalink raw reply related [flat|nested] 115+ messages in thread
* [PATCH 72/72] media: i2c: s5k6a3: Use V4L2 legacy sensor clock helper
2025-07-10 17:46 [PATCH 00/72] media: i2c: Reduce cargo-cult Laurent Pinchart
` (70 preceding siblings ...)
2025-07-10 17:48 ` [PATCH 71/72] media: i2c: s5k5baf: " Laurent Pinchart
@ 2025-07-10 17:48 ` Laurent Pinchart
2025-07-24 11:42 ` [PATCH 00/72] media: i2c: Reduce cargo-cult Tarang Raval
2025-08-11 23:27 ` (subset) " Bjorn Andersson
73 siblings, 0 replies; 115+ messages in thread
From: Laurent Pinchart @ 2025-07-10 17:48 UTC (permalink / raw)
To: linux-media; +Cc: Sakari Ailus, Mehdi Djait
Several camera sensor drivers access the "clock-frequency" property
directly to retrieve the external clock rate, or modify the clock rate
of the external clock programmatically. Both behaviours are valid on a
subset of ACPI platforms, but are considered deprecated on OF platforms,
and do not support ACPI platforms that implement MIPI DisCo for Imaging.
Implementing them manually in drivers is deprecated, as that can
encourage copying deprecated behaviour for OF platforms in new drivers,
and lead to differences in behaviour between drivers. Instead, drivers
that need to preserve the deprecated OF behaviour should use the
devm_v4l2_sensor_clk_get_legacy() helper.
This driver supports OF platforms only. The "clocks" property has always
been specified as mandatory in the DT bindings and the "clock-frequency"
property has initially been optional. Both properties were initially set
in the upstream DT sources. The driver retrieves the clock, retrieves
the clock rate from the "clock-frequency" property if available or uses
a fixed default otherwise, and sets the clock rate. This is deprecated
behaviour for OF.
Switch to using the devm_v4l2_sensor_clk_get_legacy() helper. This
preserves setting the clock rate on OF platforms. Should support for OF
platforms that set the clock rate through clock-frequency be considered
unneeded in the future, the driver will only need to switch to
devm_v4l2_sensor_clk_get() without any other change.
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
drivers/media/i2c/s5k6a3.c | 17 +++--------------
1 file changed, 3 insertions(+), 14 deletions(-)
diff --git a/drivers/media/i2c/s5k6a3.c b/drivers/media/i2c/s5k6a3.c
index 4bf5f122b113..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,7 +286,9 @@ static int s5k6a3_probe(struct i2c_client *client)
mutex_init(&sensor->lock);
sensor->dev = dev;
- sensor->clock = devm_v4l2_sensor_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 dev_err_probe(sensor->dev, PTR_ERR(sensor->clock),
"failed to get extclk\n");
@@ -302,13 +298,6 @@ static int s5k6a3_probe(struct i2c_client *client)
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];
--
Regards,
Laurent Pinchart
^ permalink raw reply related [flat|nested] 115+ messages in thread
* Re: [PATCH 04/72] dt-bindings: media: imx274: Make clocks property required
2025-07-10 17:47 ` [PATCH 04/72] dt-bindings: media: imx274: " Laurent Pinchart
@ 2025-07-10 19:37 ` Rob Herring (Arm)
2025-07-10 20:33 ` Laurent Pinchart
0 siblings, 1 reply; 115+ messages in thread
From: Rob Herring (Arm) @ 2025-07-10 19:37 UTC (permalink / raw)
To: Laurent Pinchart
Cc: Sakari Ailus, linux-media, Conor Dooley, Krzysztof Kozlowski,
Mehdi Djait, devicetree, Leon Luo
On Thu, 10 Jul 2025 20:47:00 +0300, Laurent Pinchart wrote:
> The sensor requires an external clock, and drivers need to access the
> clock to retrieve its frequency in order to configure the sensor. This
> makes usage of the clocks property mandatory for a system to work
> properly. Mark the clocks and clock-names properties as required, and
> update the example accordingly.
>
> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> ---
> Documentation/devicetree/bindings/media/i2c/sony,imx274.yaml | 4 ++++
> 1 file changed, 4 insertions(+)
>
My bot found errors running 'make dt_binding_check' on your patch:
yamllint warnings/errors:
dtschema/dtc warnings/errors:
/builds/robherring/dt-review-ci/linux/Documentation/devicetree/bindings/media/i2c/ti,ds90ub960.example.dtb: sensor@1a (sony,imx274): 'clocks' is a required property
from schema $id: http://devicetree.org/schemas/media/i2c/sony,imx274.yaml#
/builds/robherring/dt-review-ci/linux/Documentation/devicetree/bindings/media/i2c/ti,ds90ub960.example.dtb: sensor@1a (sony,imx274): 'clock-names' is a required property
from schema $id: http://devicetree.org/schemas/media/i2c/sony,imx274.yaml#
doc reference errors (make refcheckdocs):
See https://patchwork.ozlabs.org/project/devicetree-bindings/patch/20250710174808.5361-5-laurent.pinchart@ideasonboard.com
The base for the series is generally the latest rc1. A different dependency
should be noted in *this* patch.
If you already ran 'make dt_binding_check' and didn't see the above
error(s), then make sure 'yamllint' is installed and dt-schema is up to
date:
pip3 install dtschema --upgrade
Please check and re-submit after running the above command yourself. Note
that DT_SCHEMA_FILES can be set to your schema file to speed up checking
your schema. However, it must be unset to test all examples with your schema.
^ permalink raw reply [flat|nested] 115+ messages in thread
* Re: [PATCH 06/72] ARM: dts: nxp: imx6qdl-wandboard: Replace clock-frequency in camera sensor node
2025-07-10 17:47 ` [PATCH 06/72] ARM: dts: nxp: imx6qdl-wandboard: " Laurent Pinchart
@ 2025-07-10 20:18 ` Frank Li
2025-07-10 20:34 ` Laurent Pinchart
0 siblings, 1 reply; 115+ messages in thread
From: Frank Li @ 2025-07-10 20:18 UTC (permalink / raw)
To: Laurent Pinchart
Cc: linux-media, Sakari Ailus, Mehdi Djait, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Shawn Guo, Sascha Hauer,
Pengutronix Kernel Team, Fabio Estevam, devicetree, imx,
linux-arm-kernel
On Thu, Jul 10, 2025 at 08:47:02PM +0300, Laurent Pinchart wrote:
> The clock-frequency for camera sensors has been deprecated in favour of
> the assigned-clocks and assigned-clock-rates properties. Replace it in
> the device tree.
>
> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> ---
> arch/arm/boot/dts/nxp/imx/imx6qdl-wandboard.dtsi | 5 ++++-
> 1 file changed, 4 insertions(+), 1 deletion(-)
>
> diff --git a/arch/arm/boot/dts/nxp/imx/imx6qdl-wandboard.dtsi b/arch/arm/boot/dts/nxp/imx/imx6qdl-wandboard.dtsi
> index 26489eccd5fb..e5ac78ffb31c 100644
> --- a/arch/arm/boot/dts/nxp/imx/imx6qdl-wandboard.dtsi
> +++ b/arch/arm/boot/dts/nxp/imx/imx6qdl-wandboard.dtsi
> @@ -136,8 +136,11 @@ camera@3c {
> pinctrl-names = "default";
> pinctrl-0 = <&pinctrl_ov5645>;
> reg = <0x3c>;
> +
unnecessary empty line here
Frank Li
> clocks = <&clks IMX6QDL_CLK_CKO2>;
> - clock-frequency = <24000000>;
> + assigned-clocks = <&clks IMX6QDL_CLK_CKO2>;
> + assigned-clock-rates = <24000000>;
> +
> vdddo-supply = <®_1p8v>;
> vdda-supply = <®_2p8v>;
> vddd-supply = <®_1p5v>;
> --
> Regards,
>
> Laurent Pinchart
>
^ permalink raw reply [flat|nested] 115+ messages in thread
* Re: [PATCH 05/72] ARM: dts: nxp: imx6qdl-pico: Replace clock-frequency in camera sensor node
2025-07-10 17:47 ` [PATCH 05/72] ARM: dts: nxp: imx6qdl-pico: Replace clock-frequency in camera sensor node Laurent Pinchart
@ 2025-07-10 20:19 ` Frank Li
0 siblings, 0 replies; 115+ messages in thread
From: Frank Li @ 2025-07-10 20:19 UTC (permalink / raw)
To: Laurent Pinchart
Cc: linux-media, Sakari Ailus, Mehdi Djait, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Shawn Guo, Sascha Hauer,
Pengutronix Kernel Team, Fabio Estevam, devicetree, imx,
linux-arm-kernel
On Thu, Jul 10, 2025 at 08:47:01PM +0300, Laurent Pinchart wrote:
> The clock-frequency for camera sensors has been deprecated in favour of
> the assigned-clocks and assigned-clock-rates properties. Replace it in
> the device tree.
>
> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> ---
> arch/arm/boot/dts/nxp/imx/imx6qdl-pico.dtsi | 5 ++++-
> 1 file changed, 4 insertions(+), 1 deletion(-)
>
> diff --git a/arch/arm/boot/dts/nxp/imx/imx6qdl-pico.dtsi b/arch/arm/boot/dts/nxp/imx/imx6qdl-pico.dtsi
> index c39a9ebdaba1..7821404687f4 100644
> --- a/arch/arm/boot/dts/nxp/imx/imx6qdl-pico.dtsi
> +++ b/arch/arm/boot/dts/nxp/imx/imx6qdl-pico.dtsi
> @@ -232,8 +232,11 @@ camera@3c {
> pinctrl-names = "default";
> pinctrl-0 = <&pinctrl_ov5645>;
> reg = <0x3c>;
> +
unnecessary empty line here
Frank
> clocks = <&clks IMX6QDL_CLK_CKO2>;
> - clock-frequency = <24000000>;
> + assigned-clocks = <&clks IMX6QDL_CLK_CKO2>;
> + assigned-clock-rates = <24000000>;
> +
> vdddo-supply = <®_1p8v>;
> vdda-supply = <®_2p8v>;
> vddd-supply = <®_1p5v>;
> --
> Regards,
>
> Laurent Pinchart
>
^ permalink raw reply [flat|nested] 115+ messages in thread
* Re: [PATCH 04/72] dt-bindings: media: imx274: Make clocks property required
2025-07-10 19:37 ` Rob Herring (Arm)
@ 2025-07-10 20:33 ` Laurent Pinchart
0 siblings, 0 replies; 115+ messages in thread
From: Laurent Pinchart @ 2025-07-10 20:33 UTC (permalink / raw)
To: Rob Herring (Arm)
Cc: Sakari Ailus, linux-media, Conor Dooley, Krzysztof Kozlowski,
Mehdi Djait, devicetree, Leon Luo
On Thu, Jul 10, 2025 at 02:37:15PM -0500, Rob Herring (Arm) wrote:
> On Thu, 10 Jul 2025 20:47:00 +0300, Laurent Pinchart wrote:
> > The sensor requires an external clock, and drivers need to access the
> > clock to retrieve its frequency in order to configure the sensor. This
> > makes usage of the clocks property mandatory for a system to work
> > properly. Mark the clocks and clock-names properties as required, and
> > update the example accordingly.
> >
> > Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> > ---
> > Documentation/devicetree/bindings/media/i2c/sony,imx274.yaml | 4 ++++
> > 1 file changed, 4 insertions(+)
> >
>
> My bot found errors running 'make dt_binding_check' on your patch:
>
> yamllint warnings/errors:
>
> dtschema/dtc warnings/errors:
> /builds/robherring/dt-review-ci/linux/Documentation/devicetree/bindings/media/i2c/ti,ds90ub960.example.dtb: sensor@1a (sony,imx274): 'clocks' is a required property
> from schema $id: http://devicetree.org/schemas/media/i2c/sony,imx274.yaml#
> /builds/robherring/dt-review-ci/linux/Documentation/devicetree/bindings/media/i2c/ti,ds90ub960.example.dtb: sensor@1a (sony,imx274): 'clock-names' is a required property
> from schema $id: http://devicetree.org/schemas/media/i2c/sony,imx274.yaml#
I noticed that after sending the patches. I checked the bindings I was
modifying, but forgot that some other bindings could reference them.
Sorry about that, I've already fixed the problem in my tree.
> doc reference errors (make refcheckdocs):
>
> See https://patchwork.ozlabs.org/project/devicetree-bindings/patch/20250710174808.5361-5-laurent.pinchart@ideasonboard.com
>
> The base for the series is generally the latest rc1. A different dependency
> should be noted in *this* patch.
>
> If you already ran 'make dt_binding_check' and didn't see the above
> error(s), then make sure 'yamllint' is installed and dt-schema is up to
> date:
>
> pip3 install dtschema --upgrade
>
> Please check and re-submit after running the above command yourself. Note
> that DT_SCHEMA_FILES can be set to your schema file to speed up checking
> your schema. However, it must be unset to test all examples with your schema.
--
Regards,
Laurent Pinchart
^ permalink raw reply [flat|nested] 115+ messages in thread
* Re: [PATCH 06/72] ARM: dts: nxp: imx6qdl-wandboard: Replace clock-frequency in camera sensor node
2025-07-10 20:18 ` Frank Li
@ 2025-07-10 20:34 ` Laurent Pinchart
2025-07-11 5:17 ` Frank Li
0 siblings, 1 reply; 115+ messages in thread
From: Laurent Pinchart @ 2025-07-10 20:34 UTC (permalink / raw)
To: Frank Li
Cc: linux-media, Sakari Ailus, Mehdi Djait, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Shawn Guo, Sascha Hauer,
Pengutronix Kernel Team, Fabio Estevam, devicetree, imx,
linux-arm-kernel
Hi Frank,
On Thu, Jul 10, 2025 at 04:18:39PM -0400, Frank Li wrote:
> On Thu, Jul 10, 2025 at 08:47:02PM +0300, Laurent Pinchart wrote:
> > The clock-frequency for camera sensors has been deprecated in favour of
> > the assigned-clocks and assigned-clock-rates properties. Replace it in
> > the device tree.
> >
> > Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> > ---
> > arch/arm/boot/dts/nxp/imx/imx6qdl-wandboard.dtsi | 5 ++++-
> > 1 file changed, 4 insertions(+), 1 deletion(-)
> >
> > diff --git a/arch/arm/boot/dts/nxp/imx/imx6qdl-wandboard.dtsi b/arch/arm/boot/dts/nxp/imx/imx6qdl-wandboard.dtsi
> > index 26489eccd5fb..e5ac78ffb31c 100644
> > --- a/arch/arm/boot/dts/nxp/imx/imx6qdl-wandboard.dtsi
> > +++ b/arch/arm/boot/dts/nxp/imx/imx6qdl-wandboard.dtsi
> > @@ -136,8 +136,11 @@ camera@3c {
> > pinctrl-names = "default";
> > pinctrl-0 = <&pinctrl_ov5645>;
> > reg = <0x3c>;
> > +
>
> unnecessary empty line here
There's often a blank line after the reg property. I don't mind dropping
it here if that's preferred. Same for the other patch you reviewed.
> > clocks = <&clks IMX6QDL_CLK_CKO2>;
> > - clock-frequency = <24000000>;
> > + assigned-clocks = <&clks IMX6QDL_CLK_CKO2>;
> > + assigned-clock-rates = <24000000>;
> > +
> > vdddo-supply = <®_1p8v>;
> > vdda-supply = <®_2p8v>;
> > vddd-supply = <®_1p5v>;
--
Regards,
Laurent Pinchart
^ permalink raw reply [flat|nested] 115+ messages in thread
* Re: [PATCH 01/72] dt-bindings: media: Deprecate clock-frequency property for camera sensors
2025-07-10 17:46 ` [PATCH 01/72] dt-bindings: media: Deprecate clock-frequency property for camera sensors Laurent Pinchart
@ 2025-07-10 23:10 ` Rob Herring (Arm)
0 siblings, 0 replies; 115+ messages in thread
From: Rob Herring (Arm) @ 2025-07-10 23:10 UTC (permalink / raw)
To: Laurent Pinchart
Cc: Conor Dooley, Lad Prabhakar, Sakari Ailus, devicetree,
Dongchun Zhu, Mehdi Djait, linux-media, Manivannan Sadhasivam,
Todor Tomov, Krzysztof Kozlowski
On Thu, 10 Jul 2025 20:46:57 +0300, Laurent Pinchart wrote:
> Usage of the clock-frequency property for camera sensors is discouraged
> in favour of using assigned-clock-rates (and assigned-clock-parents
> where needed). Mark the property as deprecated.
>
> Update the examples accordingly. In DT examples where the sensor input
> clock appears to come from a programmable clock generator, replace
> clock-frequency by the assigned-clocks and assigned-clock-rates
> properties. Otherwise, just drop clock-frequency.
>
> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> ---
> Documentation/devicetree/bindings/media/i2c/mipi-ccs.yaml | 7 +++++--
> .../devicetree/bindings/media/i2c/ovti,ov02a10.yaml | 3 +--
> .../devicetree/bindings/media/i2c/ovti,ov5645.yaml | 6 +++++-
> .../devicetree/bindings/media/i2c/ovti,ov7251.yaml | 6 +++++-
> .../devicetree/bindings/media/i2c/ovti,ov8856.yaml | 3 +--
> .../devicetree/bindings/media/i2c/samsung,s5k5baf.yaml | 6 +++++-
> .../devicetree/bindings/media/i2c/samsung,s5k6a3.yaml | 6 +++++-
> .../devicetree/bindings/media/i2c/sony,imx290.yaml | 5 +++--
> 8 files changed, 30 insertions(+), 12 deletions(-)
>
Reviewed-by: Rob Herring (Arm) <robh@kernel.org>
^ permalink raw reply [flat|nested] 115+ messages in thread
* Re: [PATCH 02/72] dt-bindings: media: et8ek8: Deprecate clock-frequency property
2025-07-10 17:46 ` [PATCH 02/72] dt-bindings: media: et8ek8: Deprecate clock-frequency property Laurent Pinchart
@ 2025-07-10 23:11 ` Rob Herring (Arm)
0 siblings, 0 replies; 115+ messages in thread
From: Rob Herring (Arm) @ 2025-07-10 23:11 UTC (permalink / raw)
To: Laurent Pinchart
Cc: linux-media, Krzysztof Kozlowski, Conor Dooley, Mehdi Djait,
devicetree, Sakari Ailus
On Thu, 10 Jul 2025 20:46:58 +0300, Laurent Pinchart wrote:
> Usage of the clock-frequency property for camera sensors is discouraged
> in favour of using assigned-clock-rates (and assigned-clock-parents
> where needed). Drop the property, and update the example accordingly.
>
> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> ---
> .../devicetree/bindings/media/i2c/toshiba,et8ek8.txt | 8 ++++----
> 1 file changed, 4 insertions(+), 4 deletions(-)
>
Acked-by: Rob Herring (Arm) <robh@kernel.org>
^ permalink raw reply [flat|nested] 115+ messages in thread
* Re: [PATCH 03/72] dt-bindings: media: imx258: Make clocks property required
2025-07-10 17:46 ` [PATCH 03/72] dt-bindings: media: imx258: Make clocks property required Laurent Pinchart
@ 2025-07-10 23:11 ` Rob Herring (Arm)
0 siblings, 0 replies; 115+ messages in thread
From: Rob Herring (Arm) @ 2025-07-10 23:11 UTC (permalink / raw)
To: Laurent Pinchart
Cc: Mehdi Djait, Conor Dooley, Krzysztof Kozlowski, devicetree,
linux-media, Sakari Ailus
On Thu, 10 Jul 2025 20:46:59 +0300, Laurent Pinchart wrote:
> The sensor requires an external clock, and drivers need to access the
> clock to retrieve its frequency in order to configure the sensor. This
> makes usage of the clocks property mandatory for a system to work
> properly. Mark the property as required.
>
> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> ---
> Documentation/devicetree/bindings/media/i2c/sony,imx258.yaml | 1 +
> 1 file changed, 1 insertion(+)
>
Acked-by: Rob Herring (Arm) <robh@kernel.org>
^ permalink raw reply [flat|nested] 115+ messages in thread
* Re: [PATCH 06/72] ARM: dts: nxp: imx6qdl-wandboard: Replace clock-frequency in camera sensor node
2025-07-10 20:34 ` Laurent Pinchart
@ 2025-07-11 5:17 ` Frank Li
0 siblings, 0 replies; 115+ messages in thread
From: Frank Li @ 2025-07-11 5:17 UTC (permalink / raw)
To: Laurent Pinchart
Cc: linux-media, Sakari Ailus, Mehdi Djait, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Shawn Guo, Sascha Hauer,
Pengutronix Kernel Team, Fabio Estevam, devicetree, imx,
linux-arm-kernel
On Thu, Jul 10, 2025 at 11:34:21PM +0300, Laurent Pinchart wrote:
> Hi Frank,
>
> On Thu, Jul 10, 2025 at 04:18:39PM -0400, Frank Li wrote:
> > On Thu, Jul 10, 2025 at 08:47:02PM +0300, Laurent Pinchart wrote:
> > > The clock-frequency for camera sensors has been deprecated in favour of
> > > the assigned-clocks and assigned-clock-rates properties. Replace it in
> > > the device tree.
> > >
> > > Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> > > ---
> > > arch/arm/boot/dts/nxp/imx/imx6qdl-wandboard.dtsi | 5 ++++-
> > > 1 file changed, 4 insertions(+), 1 deletion(-)
> > >
> > > diff --git a/arch/arm/boot/dts/nxp/imx/imx6qdl-wandboard.dtsi b/arch/arm/boot/dts/nxp/imx/imx6qdl-wandboard.dtsi
> > > index 26489eccd5fb..e5ac78ffb31c 100644
> > > --- a/arch/arm/boot/dts/nxp/imx/imx6qdl-wandboard.dtsi
> > > +++ b/arch/arm/boot/dts/nxp/imx/imx6qdl-wandboard.dtsi
> > > @@ -136,8 +136,11 @@ camera@3c {
> > > pinctrl-names = "default";
> > > pinctrl-0 = <&pinctrl_ov5645>;
> > > reg = <0x3c>;
> > > +
> >
> > unnecessary empty line here
>
> There's often a blank line after the reg property. I don't mind dropping
> it here if that's preferred. Same for the other patch you reviewed.
This patch just drop clock-frequency. empty line is not related this at
all. So I perfer drop it.
Frank
>
> > > clocks = <&clks IMX6QDL_CLK_CKO2>;
> > > - clock-frequency = <24000000>;
> > > + assigned-clocks = <&clks IMX6QDL_CLK_CKO2>;
> > > + assigned-clock-rates = <24000000>;
> > > +
> > > vdddo-supply = <®_1p8v>;
> > > vdda-supply = <®_2p8v>;
> > > vddd-supply = <®_1p5v>;
>
> --
> Regards,
>
> Laurent Pinchart
^ permalink raw reply [flat|nested] 115+ messages in thread
* Re: [PATCH 12/72] arm64: dts: qcom: sdm845-db845c-navigation-mezzanine: Replace clock-frequency in camera sensor node
2025-07-10 17:47 ` [PATCH 12/72] arm64: dts: qcom: sdm845-db845c-navigation-mezzanine: " Laurent Pinchart
@ 2025-07-11 12:25 ` Konrad Dybcio
2025-07-11 12:45 ` Laurent Pinchart
0 siblings, 1 reply; 115+ messages in thread
From: Konrad Dybcio @ 2025-07-11 12:25 UTC (permalink / raw)
To: Laurent Pinchart, linux-media
Cc: Sakari Ailus, Mehdi Djait, Bjorn Andersson, Konrad Dybcio,
Rob Herring, Krzysztof Kozlowski, Conor Dooley, linux-arm-msm,
devicetree
On 7/10/25 7:47 PM, Laurent Pinchart wrote:
> The clock-frequency for camera sensors has been deprecated in favour of
> the assigned-clocks and assigned-clock-rates properties. Replace it in
> the device tree.
>
> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> ---
> .../boot/dts/qcom/sdm845-db845c-navigation-mezzanine.dtso | 3 ++-
> 1 file changed, 2 insertions(+), 1 deletion(-)
>
> diff --git a/arch/arm64/boot/dts/qcom/sdm845-db845c-navigation-mezzanine.dtso b/arch/arm64/boot/dts/qcom/sdm845-db845c-navigation-mezzanine.dtso
> index 51f1a4883ab8..dbe1911d8e47 100644
> --- a/arch/arm64/boot/dts/qcom/sdm845-db845c-navigation-mezzanine.dtso
> +++ b/arch/arm64/boot/dts/qcom/sdm845-db845c-navigation-mezzanine.dtso
> @@ -44,7 +44,8 @@ camera@10 {
>
> 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>;
Reviewed-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
(although your patches still seem to leave clk_set_rate in
ov8856.c anyway?)
Konrad
^ permalink raw reply [flat|nested] 115+ messages in thread
* Re: [PATCH 12/72] arm64: dts: qcom: sdm845-db845c-navigation-mezzanine: Replace clock-frequency in camera sensor node
2025-07-11 12:25 ` Konrad Dybcio
@ 2025-07-11 12:45 ` Laurent Pinchart
2025-07-11 12:47 ` Konrad Dybcio
0 siblings, 1 reply; 115+ messages in thread
From: Laurent Pinchart @ 2025-07-11 12:45 UTC (permalink / raw)
To: Konrad Dybcio
Cc: linux-media, Sakari Ailus, Mehdi Djait, Bjorn Andersson,
Konrad Dybcio, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
linux-arm-msm, devicetree
Hi Konrad,
On Fri, Jul 11, 2025 at 02:25:14PM +0200, Konrad Dybcio wrote:
> On 7/10/25 7:47 PM, Laurent Pinchart wrote:
> > The clock-frequency for camera sensors has been deprecated in favour of
> > the assigned-clocks and assigned-clock-rates properties. Replace it in
> > the device tree.
> >
> > Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> > ---
> > .../boot/dts/qcom/sdm845-db845c-navigation-mezzanine.dtso | 3 ++-
> > 1 file changed, 2 insertions(+), 1 deletion(-)
> >
> > diff --git a/arch/arm64/boot/dts/qcom/sdm845-db845c-navigation-mezzanine.dtso b/arch/arm64/boot/dts/qcom/sdm845-db845c-navigation-mezzanine.dtso
> > index 51f1a4883ab8..dbe1911d8e47 100644
> > --- a/arch/arm64/boot/dts/qcom/sdm845-db845c-navigation-mezzanine.dtso
> > +++ b/arch/arm64/boot/dts/qcom/sdm845-db845c-navigation-mezzanine.dtso
> > @@ -44,7 +44,8 @@ camera@10 {
> >
> > 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>;
>
> Reviewed-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
>
> (although your patches still seem to leave clk_set_rate in
> ov8856.c anyway?)
The call gets removed in patch 69/72 ([1]). It gets replaced by
devm_v4l2_sensor_clk_get_legacy(), which internally calls
clk_set_rate(), so the behaviour is preserved to avoid breaking backward
compatibility with old DTs.
[1] https://lore.kernel.org/linux-media/20250710174808.5361-70-laurent.pinchart@ideasonboard.com
--
Regards,
Laurent Pinchart
^ permalink raw reply [flat|nested] 115+ messages in thread
* Re: [PATCH 12/72] arm64: dts: qcom: sdm845-db845c-navigation-mezzanine: Replace clock-frequency in camera sensor node
2025-07-11 12:45 ` Laurent Pinchart
@ 2025-07-11 12:47 ` Konrad Dybcio
0 siblings, 0 replies; 115+ messages in thread
From: Konrad Dybcio @ 2025-07-11 12:47 UTC (permalink / raw)
To: Laurent Pinchart
Cc: linux-media, Sakari Ailus, Mehdi Djait, Bjorn Andersson,
Konrad Dybcio, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
linux-arm-msm, devicetree
On 7/11/25 2:45 PM, Laurent Pinchart wrote:
> Hi Konrad,
>
> On Fri, Jul 11, 2025 at 02:25:14PM +0200, Konrad Dybcio wrote:
>> On 7/10/25 7:47 PM, Laurent Pinchart wrote:
>>> The clock-frequency for camera sensors has been deprecated in favour of
>>> the assigned-clocks and assigned-clock-rates properties. Replace it in
>>> the device tree.
>>>
>>> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
>>> ---
>>> .../boot/dts/qcom/sdm845-db845c-navigation-mezzanine.dtso | 3 ++-
>>> 1 file changed, 2 insertions(+), 1 deletion(-)
>>>
>>> diff --git a/arch/arm64/boot/dts/qcom/sdm845-db845c-navigation-mezzanine.dtso b/arch/arm64/boot/dts/qcom/sdm845-db845c-navigation-mezzanine.dtso
>>> index 51f1a4883ab8..dbe1911d8e47 100644
>>> --- a/arch/arm64/boot/dts/qcom/sdm845-db845c-navigation-mezzanine.dtso
>>> +++ b/arch/arm64/boot/dts/qcom/sdm845-db845c-navigation-mezzanine.dtso
>>> @@ -44,7 +44,8 @@ camera@10 {
>>>
>>> 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>;
>>
>> Reviewed-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
>>
>> (although your patches still seem to leave clk_set_rate in
>> ov8856.c anyway?)
>
> The call gets removed in patch 69/72 ([1]). It gets replaced by
> devm_v4l2_sensor_clk_get_legacy(), which internally calls
> clk_set_rate(), so the behaviour is preserved to avoid breaking backward
> compatibility with old DTs.
>
> [1] https://lore.kernel.org/linux-media/20250710174808.5361-70-laurent.pinchart@ideasonboard.com
Overlooked that, thanks
Konrad
^ permalink raw reply [flat|nested] 115+ messages in thread
* Re: [PATCH 55/72] media: v4l2-common: Add legacy camera sensor clock helper
2025-07-10 17:47 ` [PATCH 55/72] media: v4l2-common: Add legacy camera " Laurent Pinchart
@ 2025-07-14 12:54 ` Mehdi Djait
2025-07-14 13:12 ` Mehdi Djait
0 siblings, 1 reply; 115+ messages in thread
From: Mehdi Djait @ 2025-07-14 12:54 UTC (permalink / raw)
To: Laurent Pinchart
Cc: linux-media, Sakari Ailus, Hans Verkuil, Nicolas Dufresne,
Tomi Valkeinen, Jonas Karlman, Matthew Majewski,
Niklas Söderlund
Hi Laurent,
Thank you for the patches!
On Thu, Jul 10, 2025 at 08:47:51PM +0300, Laurent Pinchart wrote:
> The recently introduced devm_v4l2_sensor_clk_get() helper aims at
> simplifying sensor drivers by centralizing clock handling code, as well
> as reducing cargo-cult and deprecated behaviour.
>
> A set of drivers implement external clock handling in a non-standard
> way. This can't be changed as there is a high risk of breaking existing
> platforms, but keeping the code as-is creates a risk of new drivers
> copying deprecated behaviour.
>
> To fix this, introduce a new devm_v4l2_sensor_clk_get_legacy() helper
> and use it in those driver. Compared to devm_v4l2_sensor_clk_get(), the
> new helper takes the "clock-frequency" property into account and sets
> the external clock rate on OF platforms, and adds the ability to specify
> a fixed default or fallback clock rate in case the "clock-frequency"
> property is not present.
>
> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> ---
> drivers/media/v4l2-core/v4l2-common.c | 39 +++++++++++++++++++------
> include/media/v4l2-common.h | 41 ++++++++++++++++++++++++++-
> 2 files changed, 70 insertions(+), 10 deletions(-)
>
> diff --git a/drivers/media/v4l2-core/v4l2-common.c b/drivers/media/v4l2-core/v4l2-common.c
> index cfc78ea6276c..6f140a78e683 100644
> --- a/drivers/media/v4l2-core/v4l2-common.c
> +++ b/drivers/media/v4l2-core/v4l2-common.c
> @@ -703,24 +703,40 @@ int v4l2_link_freq_to_bitmap(struct device *dev, const u64 *fw_link_freqs,
> }
> EXPORT_SYMBOL_GPL(v4l2_link_freq_to_bitmap);
>
> -struct clk *devm_v4l2_sensor_clk_get(struct device *dev, const char *id)
> +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;
> - bool of_node;
> - u32 rate;
> - int ret;
> + u32 rate = clk_rate;
[..]
> + int ret = 0;
>
> clk = devm_clk_get_optional(dev, id);
> if (IS_ERR(clk))
> return clk;
>
> - ret = device_property_read_u32(dev, "clock-frequency", &rate);
> - of_node = is_of_node(dev_fwnode(dev));
> + /*
> + * 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 != -EINVAL || !rate)
[..]
Let's take the case of camera sensor on a DT-system:
it will call the following:
devm_v4l2_sensor_clk_get(dev, NULL);
-> __devm_v4l2_sensor_clk_get(dev, id, false, false, 0);
--> with fixed_rate = 0 and clk_rate = 0 which will be assigned to
u32 rate
so it will go into the if statement and try to read the
"clock-frequency" property, which does not exist.
ret from device_property_read_u32() is -EINVAL and that is handled but
rate will still be 0 so we will return ERR_PTR(-EINVAL)
> + return ERR_PTR(-EINVAL);
> + }
>
> if (clk) {
> - if (!ret && !of_node) {
> + /*
> + * On non-OF platforms, or when legacy behaviour is requested,
> + * set the clock rate if a rate has been specified by the caller
> + * of by the clock-frequency property.
|
nit: +-> or ?
> + */
> + if (rate && (!of_node || legacy)) {
> ret = clk_set_rate(clk, rate);
> if (ret) {
> dev_err(dev, "Failed to set clock rate: %u\n",
> @@ -731,9 +747,14 @@ struct clk *devm_v4l2_sensor_clk_get(struct device *dev, const char *id)
> return clk;
> }
>
> - if (!IS_ENABLED(CONFIG_COMMON_CLK) || of_node)
> + /*
> + * 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);
>
> @@ -750,4 +771,4 @@ struct clk *devm_v4l2_sensor_clk_get(struct device *dev, const char *id)
>
> return clk_hw->clk;
> }
> -EXPORT_SYMBOL_GPL(devm_v4l2_sensor_clk_get);
> +EXPORT_SYMBOL_GPL(__devm_v4l2_sensor_clk_get);
--
Kind Regards
Mehdi Djait
^ permalink raw reply [flat|nested] 115+ messages in thread
* Re: [PATCH 55/72] media: v4l2-common: Add legacy camera sensor clock helper
2025-07-14 12:54 ` Mehdi Djait
@ 2025-07-14 13:12 ` Mehdi Djait
2025-07-14 14:09 ` Laurent Pinchart
0 siblings, 1 reply; 115+ messages in thread
From: Mehdi Djait @ 2025-07-14 13:12 UTC (permalink / raw)
To: Laurent Pinchart
Cc: linux-media, Sakari Ailus, Hans Verkuil, Nicolas Dufresne,
Tomi Valkeinen, Jonas Karlman, Matthew Majewski,
Niklas Söderlund
Hi Laurent,
On Mon, Jul 14, 2025 at 02:55:02PM +0200, Mehdi Djait wrote:
> Hi Laurent,
>
> Thank you for the patches!
>
> On Thu, Jul 10, 2025 at 08:47:51PM +0300, Laurent Pinchart wrote:
> > The recently introduced devm_v4l2_sensor_clk_get() helper aims at
> > simplifying sensor drivers by centralizing clock handling code, as well
> > as reducing cargo-cult and deprecated behaviour.
> >
> > A set of drivers implement external clock handling in a non-standard
> > way. This can't be changed as there is a high risk of breaking existing
> > platforms, but keeping the code as-is creates a risk of new drivers
> > copying deprecated behaviour.
> >
> > To fix this, introduce a new devm_v4l2_sensor_clk_get_legacy() helper
> > and use it in those driver. Compared to devm_v4l2_sensor_clk_get(), the
> > new helper takes the "clock-frequency" property into account and sets
> > the external clock rate on OF platforms, and adds the ability to specify
> > a fixed default or fallback clock rate in case the "clock-frequency"
> > property is not present.
> >
> > Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> > ---
> > drivers/media/v4l2-core/v4l2-common.c | 39 +++++++++++++++++++------
> > include/media/v4l2-common.h | 41 ++++++++++++++++++++++++++-
> > 2 files changed, 70 insertions(+), 10 deletions(-)
> >
> > diff --git a/drivers/media/v4l2-core/v4l2-common.c b/drivers/media/v4l2-core/v4l2-common.c
> > index cfc78ea6276c..6f140a78e683 100644
> > --- a/drivers/media/v4l2-core/v4l2-common.c
> > +++ b/drivers/media/v4l2-core/v4l2-common.c
> > @@ -703,24 +703,40 @@ int v4l2_link_freq_to_bitmap(struct device *dev, const u64 *fw_link_freqs,
> > }
> > EXPORT_SYMBOL_GPL(v4l2_link_freq_to_bitmap);
> >
> > -struct clk *devm_v4l2_sensor_clk_get(struct device *dev, const char *id)
> > +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;
> > - bool of_node;
> > - u32 rate;
> > - int ret;
> > + u32 rate = clk_rate;
>
> [..]
>
> > + int ret = 0;
> >
> > clk = devm_clk_get_optional(dev, id);
> > if (IS_ERR(clk))
> > return clk;
> >
> > - ret = device_property_read_u32(dev, "clock-frequency", &rate);
> > - of_node = is_of_node(dev_fwnode(dev));
> > + /*
> > + * 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 != -EINVAL || !rate)
so according to the above comment, I think it should be:
if (ret != -EINVAL || (!rate && !ret))
>
> [..]
>
> Let's take the case of camera sensor on a DT-system:
>
> it will call the following:
> devm_v4l2_sensor_clk_get(dev, NULL);
> -> __devm_v4l2_sensor_clk_get(dev, id, false, false, 0);
> --> with fixed_rate = 0 and clk_rate = 0 which will be assigned to
> u32 rate
>
> so it will go into the if statement and try to read the
> "clock-frequency" property, which does not exist.
>
> ret from device_property_read_u32() is -EINVAL and that is handled but
> rate will still be 0 so we will return ERR_PTR(-EINVAL)
>
> > + return ERR_PTR(-EINVAL);
> > + }
> >
> > if (clk) {
> > - if (!ret && !of_node) {
> > + /*
> > + * On non-OF platforms, or when legacy behaviour is requested,
> > + * set the clock rate if a rate has been specified by the caller
> > + * of by the clock-frequency property.
> |
> nit: +-> or ?
>
> > + */
> > + if (rate && (!of_node || legacy)) {
> > ret = clk_set_rate(clk, rate);
> > if (ret) {
> > dev_err(dev, "Failed to set clock rate: %u\n",
> > @@ -731,9 +747,14 @@ struct clk *devm_v4l2_sensor_clk_get(struct device *dev, const char *id)
> > return clk;
> > }
> >
> > - if (!IS_ENABLED(CONFIG_COMMON_CLK) || of_node)
> > + /*
> > + * 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);
> >
> > @@ -750,4 +771,4 @@ struct clk *devm_v4l2_sensor_clk_get(struct device *dev, const char *id)
> >
> > return clk_hw->clk;
> > }
> > -EXPORT_SYMBOL_GPL(devm_v4l2_sensor_clk_get);
> > +EXPORT_SYMBOL_GPL(__devm_v4l2_sensor_clk_get);
>
--
Kind Regards
Mehdi Djait
^ permalink raw reply [flat|nested] 115+ messages in thread
* Re: [PATCH 55/72] media: v4l2-common: Add legacy camera sensor clock helper
2025-07-14 13:12 ` Mehdi Djait
@ 2025-07-14 14:09 ` Laurent Pinchart
2025-07-14 21:15 ` Mehdi Djait
0 siblings, 1 reply; 115+ messages in thread
From: Laurent Pinchart @ 2025-07-14 14:09 UTC (permalink / raw)
To: Mehdi Djait
Cc: linux-media, Sakari Ailus, Hans Verkuil, Nicolas Dufresne,
Tomi Valkeinen, Jonas Karlman, Matthew Majewski,
Niklas Söderlund
Hi Mehdi,
On Mon, Jul 14, 2025 at 03:12:28PM +0200, Mehdi Djait wrote:
> On Mon, Jul 14, 2025 at 02:55:02PM +0200, Mehdi Djait wrote:
> > On Thu, Jul 10, 2025 at 08:47:51PM +0300, Laurent Pinchart wrote:
> > > The recently introduced devm_v4l2_sensor_clk_get() helper aims at
> > > simplifying sensor drivers by centralizing clock handling code, as well
> > > as reducing cargo-cult and deprecated behaviour.
> > >
> > > A set of drivers implement external clock handling in a non-standard
> > > way. This can't be changed as there is a high risk of breaking existing
> > > platforms, but keeping the code as-is creates a risk of new drivers
> > > copying deprecated behaviour.
> > >
> > > To fix this, introduce a new devm_v4l2_sensor_clk_get_legacy() helper
> > > and use it in those driver. Compared to devm_v4l2_sensor_clk_get(), the
> > > new helper takes the "clock-frequency" property into account and sets
> > > the external clock rate on OF platforms, and adds the ability to specify
> > > a fixed default or fallback clock rate in case the "clock-frequency"
> > > property is not present.
> > >
> > > Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> > > ---
> > > drivers/media/v4l2-core/v4l2-common.c | 39 +++++++++++++++++++------
> > > include/media/v4l2-common.h | 41 ++++++++++++++++++++++++++-
> > > 2 files changed, 70 insertions(+), 10 deletions(-)
> > >
> > > diff --git a/drivers/media/v4l2-core/v4l2-common.c b/drivers/media/v4l2-core/v4l2-common.c
> > > index cfc78ea6276c..6f140a78e683 100644
> > > --- a/drivers/media/v4l2-core/v4l2-common.c
> > > +++ b/drivers/media/v4l2-core/v4l2-common.c
> > > @@ -703,24 +703,40 @@ int v4l2_link_freq_to_bitmap(struct device *dev, const u64 *fw_link_freqs,
> > > }
> > > EXPORT_SYMBOL_GPL(v4l2_link_freq_to_bitmap);
> > >
> > > -struct clk *devm_v4l2_sensor_clk_get(struct device *dev, const char *id)
> > > +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;
> > > - bool of_node;
> > > - u32 rate;
> > > - int ret;
> > > + u32 rate = clk_rate;
> >
> > [..]
> >
> > > + int ret = 0;
> > >
> > > clk = devm_clk_get_optional(dev, id);
> > > if (IS_ERR(clk))
> > > return clk;
> > >
> > > - ret = device_property_read_u32(dev, "clock-frequency", &rate);
> > > - of_node = is_of_node(dev_fwnode(dev));
> > > + /*
> > > + * 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 != -EINVAL || !rate)
>
> so according to the above comment, I think it should be:
> if (ret != -EINVAL || (!rate && !ret))
You're right, there's an issue here.
We need to return an error iif
- clock-frequency can't be read for a reason different than the property
being absent (to support ACPI platforms where the property could be
created dynamically at a later time) ; or
- clock-frequency can be read, and returns a 0 rate
That translates to
if ((ret && ret != -EINVAL) || (!ret && !rate))
Omitting the initial ret test would return -EINVAL when clock-frequency
can be read correctly, which is not right. Do you agree with that ?
> >
> > [..]
> >
> > Let's take the case of camera sensor on a DT-system:
> >
> > it will call the following:
> > devm_v4l2_sensor_clk_get(dev, NULL);
> > -> __devm_v4l2_sensor_clk_get(dev, id, false, false, 0);
> > --> with fixed_rate = 0 and clk_rate = 0 which will be assigned to
> > u32 rate
> >
> > so it will go into the if statement and try to read the
> > "clock-frequency" property, which does not exist.
> >
> > ret from device_property_read_u32() is -EINVAL and that is handled but
> > rate will still be 0 so we will return ERR_PTR(-EINVAL)
> >
> > > + return ERR_PTR(-EINVAL);
> > > + }
> > >
> > > if (clk) {
> > > - if (!ret && !of_node) {
> > > + /*
> > > + * On non-OF platforms, or when legacy behaviour is requested,
> > > + * set the clock rate if a rate has been specified by the caller
> > > + * of by the clock-frequency property.
> > |
> > nit: +-> or ?
Oops. I'll fix the typo.
> > > + */
> > > + if (rate && (!of_node || legacy)) {
> > > ret = clk_set_rate(clk, rate);
> > > if (ret) {
> > > dev_err(dev, "Failed to set clock rate: %u\n",
> > > @@ -731,9 +747,14 @@ struct clk *devm_v4l2_sensor_clk_get(struct device *dev, const char *id)
> > > return clk;
> > > }
> > >
> > > - if (!IS_ENABLED(CONFIG_COMMON_CLK) || of_node)
> > > + /*
> > > + * 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);
> > >
> > > @@ -750,4 +771,4 @@ struct clk *devm_v4l2_sensor_clk_get(struct device *dev, const char *id)
> > >
> > > return clk_hw->clk;
> > > }
> > > -EXPORT_SYMBOL_GPL(devm_v4l2_sensor_clk_get);
> > > +EXPORT_SYMBOL_GPL(__devm_v4l2_sensor_clk_get);
--
Regards,
Laurent Pinchart
^ permalink raw reply [flat|nested] 115+ messages in thread
* Re: [PATCH 55/72] media: v4l2-common: Add legacy camera sensor clock helper
2025-07-14 14:09 ` Laurent Pinchart
@ 2025-07-14 21:15 ` Mehdi Djait
0 siblings, 0 replies; 115+ messages in thread
From: Mehdi Djait @ 2025-07-14 21:15 UTC (permalink / raw)
To: Laurent Pinchart
Cc: linux-media, Sakari Ailus, Hans Verkuil, Nicolas Dufresne,
Tomi Valkeinen, Jonas Karlman, Matthew Majewski,
Niklas Söderlund
Hi Laurent,
On Mon, Jul 14, 2025 at 05:09:47PM +0300, Laurent Pinchart wrote:
> Hi Mehdi,
>
> On Mon, Jul 14, 2025 at 03:12:28PM +0200, Mehdi Djait wrote:
> > On Mon, Jul 14, 2025 at 02:55:02PM +0200, Mehdi Djait wrote:
> > > On Thu, Jul 10, 2025 at 08:47:51PM +0300, Laurent Pinchart wrote:
> > > > The recently introduced devm_v4l2_sensor_clk_get() helper aims at
> > > > simplifying sensor drivers by centralizing clock handling code, as well
> > > > as reducing cargo-cult and deprecated behaviour.
> > > >
> > > > A set of drivers implement external clock handling in a non-standard
> > > > way. This can't be changed as there is a high risk of breaking existing
> > > > platforms, but keeping the code as-is creates a risk of new drivers
> > > > copying deprecated behaviour.
> > > >
> > > > To fix this, introduce a new devm_v4l2_sensor_clk_get_legacy() helper
> > > > and use it in those driver. Compared to devm_v4l2_sensor_clk_get(), the
> > > > new helper takes the "clock-frequency" property into account and sets
> > > > the external clock rate on OF platforms, and adds the ability to specify
> > > > a fixed default or fallback clock rate in case the "clock-frequency"
> > > > property is not present.
> > > >
> > > > Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> > > > ---
> > > > drivers/media/v4l2-core/v4l2-common.c | 39 +++++++++++++++++++------
> > > > include/media/v4l2-common.h | 41 ++++++++++++++++++++++++++-
> > > > 2 files changed, 70 insertions(+), 10 deletions(-)
> > > >
> > > > diff --git a/drivers/media/v4l2-core/v4l2-common.c b/drivers/media/v4l2-core/v4l2-common.c
> > > > index cfc78ea6276c..6f140a78e683 100644
> > > > --- a/drivers/media/v4l2-core/v4l2-common.c
> > > > +++ b/drivers/media/v4l2-core/v4l2-common.c
> > > > @@ -703,24 +703,40 @@ int v4l2_link_freq_to_bitmap(struct device *dev, const u64 *fw_link_freqs,
> > > > }
> > > > EXPORT_SYMBOL_GPL(v4l2_link_freq_to_bitmap);
> > > >
> > > > -struct clk *devm_v4l2_sensor_clk_get(struct device *dev, const char *id)
> > > > +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;
> > > > - bool of_node;
> > > > - u32 rate;
> > > > - int ret;
> > > > + u32 rate = clk_rate;
> > >
> > > [..]
> > >
> > > > + int ret = 0;
> > > >
> > > > clk = devm_clk_get_optional(dev, id);
> > > > if (IS_ERR(clk))
> > > > return clk;
> > > >
> > > > - ret = device_property_read_u32(dev, "clock-frequency", &rate);
> > > > - of_node = is_of_node(dev_fwnode(dev));
> > > > + /*
> > > > + * 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 != -EINVAL || !rate)
> >
> > so according to the above comment, I think it should be:
> > if (ret != -EINVAL || (!rate && !ret))
>
> You're right, there's an issue here.
>
> We need to return an error iif
>
> - clock-frequency can't be read for a reason different than the property
> being absent (to support ACPI platforms where the property could be
> created dynamically at a later time) ; or
>
> - clock-frequency can be read, and returns a 0 rate
>
> That translates to
>
> if ((ret && ret != -EINVAL) || (!ret && !rate))
>
> Omitting the initial ret test would return -EINVAL when clock-frequency
> can be read correctly, which is not right. Do you agree with that ?
Yes, I agree with this approach.
>
> > >
> > > [..]
> > >
> > > Let's take the case of camera sensor on a DT-system:
> > >
> > > it will call the following:
> > > devm_v4l2_sensor_clk_get(dev, NULL);
> > > -> __devm_v4l2_sensor_clk_get(dev, id, false, false, 0);
> > > --> with fixed_rate = 0 and clk_rate = 0 which will be assigned to
> > > u32 rate
> > >
> > > so it will go into the if statement and try to read the
> > > "clock-frequency" property, which does not exist.
> > >
> > > ret from device_property_read_u32() is -EINVAL and that is handled but
> > > rate will still be 0 so we will return ERR_PTR(-EINVAL)
> > >
> > > > + return ERR_PTR(-EINVAL);
> > > > + }
> > > >
> > > > if (clk) {
> > > > - if (!ret && !of_node) {
> > > > + /*
> > > > + * On non-OF platforms, or when legacy behaviour is requested,
> > > > + * set the clock rate if a rate has been specified by the caller
> > > > + * of by the clock-frequency property.
> > > |
> > > nit: +-> or ?
>
> Oops. I'll fix the typo.
>
> > > > + */
> > > > + if (rate && (!of_node || legacy)) {
> > > > ret = clk_set_rate(clk, rate);
> > > > if (ret) {
> > > > dev_err(dev, "Failed to set clock rate: %u\n",
> > > > @@ -731,9 +747,14 @@ struct clk *devm_v4l2_sensor_clk_get(struct device *dev, const char *id)
> > > > return clk;
> > > > }
> > > >
> > > > - if (!IS_ENABLED(CONFIG_COMMON_CLK) || of_node)
> > > > + /*
> > > > + * 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);
> > > >
> > > > @@ -750,4 +771,4 @@ struct clk *devm_v4l2_sensor_clk_get(struct device *dev, const char *id)
> > > >
> > > > return clk_hw->clk;
> > > > }
> > > > -EXPORT_SYMBOL_GPL(devm_v4l2_sensor_clk_get);
> > > > +EXPORT_SYMBOL_GPL(__devm_v4l2_sensor_clk_get);
>
> --
> Regards,
>
> Laurent Pinchart
--
Kind Regards
Mehdi Djait
^ permalink raw reply [flat|nested] 115+ messages in thread
* Re: [PATCH 31/72] media: i2c: og01a1b: Use V4L2 sensor clock helper
2025-07-10 17:47 ` [PATCH 31/72] media: i2c: og01a1b: Use V4L2 sensor clock helper Laurent Pinchart
@ 2025-07-15 11:44 ` Mehdi Djait
2025-07-15 18:41 ` Laurent Pinchart
0 siblings, 1 reply; 115+ messages in thread
From: Mehdi Djait @ 2025-07-15 11:44 UTC (permalink / raw)
To: Laurent Pinchart; +Cc: linux-media, Sakari Ailus
Hi Laurent,
Thank you for the patch!
On Thu, Jul 10, 2025 at 08:47:27PM +0300, Laurent Pinchart wrote:
[..]
> - og01a1b->xvclk = devm_clk_get_optional(og01a1b->dev, NULL);
> + og01a1b->xvclk = devm_v4l2_sensor_clk_get(og01a1b->dev, NULL);
> if (IS_ERR(og01a1b->xvclk)) {
> ret = PTR_ERR(og01a1b->xvclk);
> dev_err(og01a1b->dev, "failed to get xvclk clock: %d\n", ret);
> return ret;
> }
while at it, you can change this driver to
return dev_err_probe(og01a1b->dev, PTR_ERR(og01a1b->xvclk),
"failed to get xvclk clock\n");
the only driver that remains weird when handling an err in this series is:
drivers/media/i2c/s5k5baf.c
Feel free to change it or leave it as is.
>
> + freq = clk_get_rate(og01a1b->xvclk);
> + if (freq != OG01A1B_MCLK)
> + return dev_err_probe(og01a1b->dev, -EINVAL,
> + "external clock %lu is not supported",
> + freq);
> +
--
Kind Regards
Mehdi Djait
^ permalink raw reply [flat|nested] 115+ messages in thread
* Re: [PATCH 31/72] media: i2c: og01a1b: Use V4L2 sensor clock helper
2025-07-15 11:44 ` Mehdi Djait
@ 2025-07-15 18:41 ` Laurent Pinchart
0 siblings, 0 replies; 115+ messages in thread
From: Laurent Pinchart @ 2025-07-15 18:41 UTC (permalink / raw)
To: Mehdi Djait; +Cc: linux-media, Sakari Ailus
On Tue, Jul 15, 2025 at 01:44:47PM +0200, Mehdi Djait wrote:
> Hi Laurent,
>
> Thank you for the patch!
>
> On Thu, Jul 10, 2025 at 08:47:27PM +0300, Laurent Pinchart wrote:
>
> [..]
>
> > - og01a1b->xvclk = devm_clk_get_optional(og01a1b->dev, NULL);
> > + og01a1b->xvclk = devm_v4l2_sensor_clk_get(og01a1b->dev, NULL);
> > if (IS_ERR(og01a1b->xvclk)) {
> > ret = PTR_ERR(og01a1b->xvclk);
> > dev_err(og01a1b->dev, "failed to get xvclk clock: %d\n", ret);
> > return ret;
> > }
>
> while at it, you can change this driver to
> return dev_err_probe(og01a1b->dev, PTR_ERR(og01a1b->xvclk),
> "failed to get xvclk clock\n");
I'll do that in v2.
> the only driver that remains weird when handling an err in this series is:
> drivers/media/i2c/s5k5baf.c
Indeed. I think I can clean that up too, devm_v4l2_sensor_clk_get()
should return -EPROBE_DEFER in the cases that are meaningful for this
driver.
> Feel free to change it or leave it as is.
>
> >
> > + freq = clk_get_rate(og01a1b->xvclk);
> > + if (freq != OG01A1B_MCLK)
> > + return dev_err_probe(og01a1b->dev, -EINVAL,
> > + "external clock %lu is not supported",
> > + freq);
> > +
--
Regards,
Laurent Pinchart
^ permalink raw reply [flat|nested] 115+ messages in thread
* Re: [PATCH 00/72] media: i2c: Reduce cargo-cult
2025-07-10 17:46 [PATCH 00/72] media: i2c: Reduce cargo-cult Laurent Pinchart
` (71 preceding siblings ...)
2025-07-10 17:48 ` [PATCH 72/72] media: i2c: s5k6a3: " Laurent Pinchart
@ 2025-07-24 11:42 ` Tarang Raval
2025-07-24 11:52 ` Laurent Pinchart
2025-08-11 23:27 ` (subset) " Bjorn Andersson
73 siblings, 1 reply; 115+ messages in thread
From: Tarang Raval @ 2025-07-24 11:42 UTC (permalink / raw)
To: Laurent Pinchart
Cc: linux-media@vger.kernel.org, Sakari Ailus, Mehdi Djait,
Alim Akhtar, André Apitzsch, Andrzej Hajda, Arec Kao,
Benjamin Mugnier, Bingbu Cao, Bjorn Andersson,
Bryan O'Donoghue, Bryan O'Donoghue, Conor Dooley,
Daniel Scally, Dongcheng Yan, Dongchun Zhu, Fabio Estevam,
Geert Uytterhoeven, Hans de Goede, Hans Verkuil, Hao Yao,
Heimir Thor Sverrisson, Jacopo Mondi, Jason Chen, Jimmy Su,
Jingjing Xiong, Jonas Karlman, Konrad Dybcio, Krzysztof Kozlowski,
Lad Prabhakar, Leon Luo, Liam Girdwood, Magnus Damm,
Manivannan Sadhasivam, Mark Brown, Matthew Majewski,
Matthias Fend, Mikhail Rudenko, Nicolas Dufresne,
Niklas Söderlund, Pavel Machek, Pengutronix Kernel Team,
Ricardo Ribalda, Rob Herring, Sascha Hauer, Shawn Guo,
Shunqian Zheng, Sylvain Petinot, Sylwester Nawrocki, Tianshu Qiu,
Todor Tomov, Tomi Valkeinen, Tony Lindgren, Zhi Mao,
devicetree@vger.kernel.org, imx@lists.linux.dev,
linux-arm-kernel@lists.infradead.org,
linux-arm-msm@vger.kernel.org, linux-omap@vger.kernel.org,
linux-renesas-soc@vger.kernel.org,
linux-samsung-soc@vger.kernel.org
Hi Laurent,
> This patch series build on top of Mehdi's introduction of the
> devm_v4l2_sensor_clk_get() helper (see [1]) to drastically reduce
> cargo-cult in camera sensor drivers.
>
> A large number of camera sensor drivers directly use the
> "clock-frequency" property to retrieve the effective or desired external
> clock rate. This is standard behaviour on ACPI platforms that don't
> implement MIPI DisCo for Imaging, but usage of the property has leaked
> to OF-based platforms, due to a combination of historical reasons (using
> "clock-frequency" was initially considered right until before the
> introduction of "assigned-clock-rates") and plain cargo-cult.
>
> A large number of camera sensor drivers also set the rate of the
> external clock with clk_set_rate(). This behaviour is also fine on ACPI
> platforms, and has also leaked to OF-based platforms for the same
> reasons.
>
> Mehdi's "[PATCH v2 00/48] media: Add a helper for obtaining the clock
> producer" series improves the situation by centralizing clock handling
> for camera sensor in one helper function that implements the correct
> behaviour for all types of platforms (and should later allow support of
> MIPI DisCo for Imaging transparently for camera sensor drivers). It
> doesn't however address direct access of the "clock-frequency" property
> or direct calls to clk_set_rate() in drivers.
>
> This series builds on top of the new helper to replace manual handling
> of the clock frequency in camera sensor drivers. It starts by addressing
> the DT bindings and reprecating the clock-frequency property for camera
> sensor drivers in all YAML bindings (01/72) and in the et8ek8 text
> bindings (02/72). After that, patches 03/72 and 04/72 make the clocks
> property mandatory in the two camera sensor DT bindings that specified
> it as optional. Finally for the DT side, patches 05/72 to 14/72 replace
> clock-frequency with assigned-clock-rates, or drops the property
> altogether when the source clock has a fixed rate. This aligns the DT
> bindings and device tree sources to the current recommended practice.
>
> After that, the next 5 patches are assorted drive-by changes. Patch
> 15/72 drops an unused header the belonged to a long gone driver, and
> patch 17/72 drops unusued support for platform data in the mt9v032
> driver. Patch 18/72 is the first that addresses clock rate handling by
> dropping unneeded clock rate setting in the mt9v111 driver. Patch 19/72
> takes a harsher approach for the ov6650 by dropping the driver
> completely as the driver hasn't been used since v5.9.
>
> The next part of the series replaces manual clock rate handling with
> usage of the devm_v4l2_sensor_clk_get() helper in a large number of
> camera sensor drivers that implement clock rate handling in a standard
> way. This is done in patches 20/72 to 54/72. This interleaves the clock
> rate handling changes with drive-by refactoring (in separate patches) to
> make the code easier to deal with.
>
> The final part of the series addresses the remaining drivers that
> implement non-standard behaviours. It starts in 55/72 by adding a new
> devm_v4l2_sensor_clk_get_legacy() helper function for those drivers,
> similar to devm_v4l2_sensor_clk_get() but with a few more quirks. This
> function should not be used in any new driver. The remaining patches,
> from 53/72 to 72/72, use the new helper in drivers, interleaved with
> drive-by refactoring similarly to the previous part.
>
> Before this series, with Mehdi's series applied, 29 drivers read the
> "clock-frequency" property and 18 drivers set the external clock rate.
> With these series we go down to 1 and 3 respectively, namely the ccs,
> mt9p031 and mt9v032 drivers. Clock handling in the CCS driver is a bit
> more convoluted so I will leave to Sakari the honour of dropping the
> last direct user of "clock-frequency" :-) As for the mt9p031 and mt9v032
> driver, addressing the issue there is more difficult and likely not
> worth it.
>
> [1] https://lore.kernel.org/linux-media/cover.1750942967.git.mehdi.djait@linux.intel.com
>
> Laurent Pinchart (72):
> dt-bindings: media: Deprecate clock-frequency property for camera
> sensors
> dt-bindings: media: et8ek8: Deprecate clock-frequency property
> dt-bindings: media: imx258: Make clocks property required
> dt-bindings: media: imx274: Make clocks property required
> ARM: dts: nxp: imx6qdl-pico: Replace clock-frequency in camera sensor
> node
> ARM: dts: nxp: imx6qdl-wandboard: Replace clock-frequency in camera
> sensor node
> ARM: dts: samsung: exynos4210-i9100: Replace clock-frequency in camera
> sensor node
> ARM: dts: samsung: exynos4412-midas: Replace clock-frequency in camera
> sensor node
> ARM: dts: ti: omap3-n900: Replace clock-frequency in camera sensor
> node
> ARM: dts: ti: omap3-n950: Replace clock-frequency in camera sensor
> node
> ARM: dts: ti: omap3-n9: Replace clock-frequency in camera sensor node
> arm64: dts: qcom: sdm845-db845c-navigation-mezzanine: Replace
> clock-frequency in camera sensor node
> arm64: dts: renesas: aistarvision-mipi-adapter-2.1: Drop
> clock-frequency from camera sensor node
> arm64: dts: renesas: rzg2l-smarc: Drop clock-frequency from camera
> sensor node
> media: i2c: mt9v022: Drop unused mt9v022.h header
> media: i2c: mt9v032: Replace client->dev usage
> media: i2c: mt9v032: Drop support for platform data
> media: i2c: mt9v111: Do not set clock rate manually
> media: i2c: ov6650: Drop unused driver
> media: i2c: hi556: Replace client->dev usage
> media: i2c: hi556: Use V4L2 sensor clock helper
> media: i2c: hi847: Replace client->dev usage
> media: i2c: hi847: Use V4L2 sensor clock helper
> media: i2c: imx208: Replace client->dev usage
> media: i2c: imx208: Use V4L2 sensor clock helper
> media: i2c: imx319: Replace client->dev usage
> media: i2c: imx319: Use V4L2 sensor clock helper
> media: i2c: imx355: Replace client->dev usage
> media: i2c: imx335: Use V4L2 sensor clock helper
> media: i2c: og01a1b: Replace client->dev usage
> media: i2c: og01a1b: Use V4L2 sensor clock helper
> media: i2c: ov02c10: Replace client->dev usage
> media: i2c: ov02c10: Use V4L2 sensor clock helper
> media: i2c: ov02e10: Replace client->dev usage
> media: i2c: ov02e10: Use V4L2 sensor clock helper
> media: i2c: ov08d10: Replace client->dev usage
> media: i2c: ov08d10: Use V4L2 sensor clock helper
> media: i2c: ov08x40: Replace client->dev usage
> media: i2c: ov08x40: Use V4L2 sensor clock helper
> media: i2c: ov13858: Replace client->dev usage
> media: i2c: ov13858: Use V4L2 sensor clock helper
> media: i2c: ov13b10: Replace client->dev usage
> media: i2c: ov13b10: Use V4L2 sensor clock helper
> media: i2c: ov2740: Replace client->dev usage
> media: i2c: ov2740: Use V4L2 sensor clock helper
> media: i2c: ov4689: Use V4L2 sensor clock helper
> media: i2c: ov5670: Replace client->dev usage
> media: i2c: ov5670: Use V4L2 sensor clock helper
> media: i2c: ov5675: Replace client->dev usage
> media: i2c: ov5675: Use V4L2 sensor clock helper
> media: i2c: ov5693: Use V4L2 sensor clock helper
> media: i2c: ov7251: Use V4L2 sensor clock helper
> media: i2c: ov9734: Replace client->dev usage
> media: i2c: ov9734: Use V4L2 sensor clock helper
> media: v4l2-common: Add legacy camera sensor clock helper
> media: i2c: et8ek8: Drop support for per-mode external clock frequency
> media: i2c: et8ek8: Use V4L2 legacy sensor clock helper
> media: i2c: gc05a2: Use V4L2 legacy sensor clock helper
> media: i2c: gc08a3: Use V4L2 legacy sensor clock helper
> media: i2c: imx258: Replace client->dev usage
> media: i2c: imx258: Use V4L2 legacy sensor clock helper
> media: i2c: imx290: Use V4L2 legacy sensor clock helper
> media: i2c: ov02a10: Replace client->dev usage
> media: i2c: ov02a10: Use V4L2 legacy sensor clock helper
> media: i2c: ov2685: Use V4L2 legacy sensor clock helper
> media: i2c: ov5645: Use V4L2 legacy sensor clock helper
> media: i2c: ov5695: Use V4L2 legacy sensor clock helper
> media: i2c: ov8856: Replace client->dev usage
> media: i2c: ov8856: Use V4L2 legacy sensor clock helper
> media: i2c: s5c73m3: Use V4L2 legacy sensor clock helper
> media: i2c: s5k5baf: Use V4L2 legacy sensor clock helper
> media: i2c: s5k6a3: Use V4L2 legacy sensor clock helper
If you are planning a v2 version of this patch series, please consider
incorporating the following improvements:
1. In the imx219 driver, you can also replace direct client->dev usage.
2. In the regulator code, you can reduce boilerplate by using
devm_regulator_bulk_get_enable().
Otherwise, I will submit a separate patch series on top of yours to
address these points.
Best Regards,
Tarang
^ permalink raw reply [flat|nested] 115+ messages in thread
* Re: [PATCH 00/72] media: i2c: Reduce cargo-cult
2025-07-24 11:42 ` [PATCH 00/72] media: i2c: Reduce cargo-cult Tarang Raval
@ 2025-07-24 11:52 ` Laurent Pinchart
[not found] ` <PN3P287MB1829C9E8C78ADD70259A68F08B5EA@PN3P287MB1829.INDP287.PROD.OUTLOOK.COM>
0 siblings, 1 reply; 115+ messages in thread
From: Laurent Pinchart @ 2025-07-24 11:52 UTC (permalink / raw)
To: Tarang Raval
Cc: linux-media@vger.kernel.org, Sakari Ailus, Mehdi Djait,
Alim Akhtar, André Apitzsch, Andrzej Hajda, Arec Kao,
Benjamin Mugnier, Bingbu Cao, Bjorn Andersson,
Bryan O'Donoghue, Bryan O'Donoghue, Conor Dooley,
Daniel Scally, Dongcheng Yan, Dongchun Zhu, Fabio Estevam,
Geert Uytterhoeven, Hans de Goede, Hans Verkuil, Hao Yao,
Heimir Thor Sverrisson, Jacopo Mondi, Jason Chen, Jimmy Su,
Jingjing Xiong, Jonas Karlman, Konrad Dybcio, Krzysztof Kozlowski,
Lad Prabhakar, Leon Luo, Liam Girdwood, Magnus Damm,
Manivannan Sadhasivam, Mark Brown, Matthew Majewski,
Matthias Fend, Mikhail Rudenko, Nicolas Dufresne,
Niklas Söderlund, Pavel Machek, Pengutronix Kernel Team,
Ricardo Ribalda, Rob Herring, Sascha Hauer, Shawn Guo,
Shunqian Zheng, Sylvain Petinot, Sylwester Nawrocki, Tianshu Qiu,
Todor Tomov, Tomi Valkeinen, Tony Lindgren, Zhi Mao,
devicetree@vger.kernel.org, imx@lists.linux.dev,
linux-arm-kernel@lists.infradead.org,
linux-arm-msm@vger.kernel.org, linux-omap@vger.kernel.org,
linux-renesas-soc@vger.kernel.org,
linux-samsung-soc@vger.kernel.org
On Thu, Jul 24, 2025 at 11:42:55AM +0000, Tarang Raval wrote:
> Hi Laurent,
>
> > This patch series build on top of Mehdi's introduction of the
> > devm_v4l2_sensor_clk_get() helper (see [1]) to drastically reduce
> > cargo-cult in camera sensor drivers.
> >
> > A large number of camera sensor drivers directly use the
> > "clock-frequency" property to retrieve the effective or desired external
> > clock rate. This is standard behaviour on ACPI platforms that don't
> > implement MIPI DisCo for Imaging, but usage of the property has leaked
> > to OF-based platforms, due to a combination of historical reasons (using
> > "clock-frequency" was initially considered right until before the
> > introduction of "assigned-clock-rates") and plain cargo-cult.
> >
> > A large number of camera sensor drivers also set the rate of the
> > external clock with clk_set_rate(). This behaviour is also fine on ACPI
> > platforms, and has also leaked to OF-based platforms for the same
> > reasons.
> >
> > Mehdi's "[PATCH v2 00/48] media: Add a helper for obtaining the clock
> > producer" series improves the situation by centralizing clock handling
> > for camera sensor in one helper function that implements the correct
> > behaviour for all types of platforms (and should later allow support of
> > MIPI DisCo for Imaging transparently for camera sensor drivers). It
> > doesn't however address direct access of the "clock-frequency" property
> > or direct calls to clk_set_rate() in drivers.
> >
> > This series builds on top of the new helper to replace manual handling
> > of the clock frequency in camera sensor drivers. It starts by addressing
> > the DT bindings and reprecating the clock-frequency property for camera
> > sensor drivers in all YAML bindings (01/72) and in the et8ek8 text
> > bindings (02/72). After that, patches 03/72 and 04/72 make the clocks
> > property mandatory in the two camera sensor DT bindings that specified
> > it as optional. Finally for the DT side, patches 05/72 to 14/72 replace
> > clock-frequency with assigned-clock-rates, or drops the property
> > altogether when the source clock has a fixed rate. This aligns the DT
> > bindings and device tree sources to the current recommended practice.
> >
> > After that, the next 5 patches are assorted drive-by changes. Patch
> > 15/72 drops an unused header the belonged to a long gone driver, and
> > patch 17/72 drops unusued support for platform data in the mt9v032
> > driver. Patch 18/72 is the first that addresses clock rate handling by
> > dropping unneeded clock rate setting in the mt9v111 driver. Patch 19/72
> > takes a harsher approach for the ov6650 by dropping the driver
> > completely as the driver hasn't been used since v5.9.
> >
> > The next part of the series replaces manual clock rate handling with
> > usage of the devm_v4l2_sensor_clk_get() helper in a large number of
> > camera sensor drivers that implement clock rate handling in a standard
> > way. This is done in patches 20/72 to 54/72. This interleaves the clock
> > rate handling changes with drive-by refactoring (in separate patches) to
> > make the code easier to deal with.
> >
> > The final part of the series addresses the remaining drivers that
> > implement non-standard behaviours. It starts in 55/72 by adding a new
> > devm_v4l2_sensor_clk_get_legacy() helper function for those drivers,
> > similar to devm_v4l2_sensor_clk_get() but with a few more quirks. This
> > function should not be used in any new driver. The remaining patches,
> > from 53/72 to 72/72, use the new helper in drivers, interleaved with
> > drive-by refactoring similarly to the previous part.
> >
> > Before this series, with Mehdi's series applied, 29 drivers read the
> > "clock-frequency" property and 18 drivers set the external clock rate.
> > With these series we go down to 1 and 3 respectively, namely the ccs,
> > mt9p031 and mt9v032 drivers. Clock handling in the CCS driver is a bit
> > more convoluted so I will leave to Sakari the honour of dropping the
> > last direct user of "clock-frequency" :-) As for the mt9p031 and mt9v032
> > driver, addressing the issue there is more difficult and likely not
> > worth it.
> >
> > [1] https://lore.kernel.org/linux-media/cover.1750942967.git.mehdi.djait@linux.intel.com
> >
> > Laurent Pinchart (72):
> > dt-bindings: media: Deprecate clock-frequency property for camera
> > sensors
> > dt-bindings: media: et8ek8: Deprecate clock-frequency property
> > dt-bindings: media: imx258: Make clocks property required
> > dt-bindings: media: imx274: Make clocks property required
> > ARM: dts: nxp: imx6qdl-pico: Replace clock-frequency in camera sensor
> > node
> > ARM: dts: nxp: imx6qdl-wandboard: Replace clock-frequency in camera
> > sensor node
> > ARM: dts: samsung: exynos4210-i9100: Replace clock-frequency in camera
> > sensor node
> > ARM: dts: samsung: exynos4412-midas: Replace clock-frequency in camera
> > sensor node
> > ARM: dts: ti: omap3-n900: Replace clock-frequency in camera sensor
> > node
> > ARM: dts: ti: omap3-n950: Replace clock-frequency in camera sensor
> > node
> > ARM: dts: ti: omap3-n9: Replace clock-frequency in camera sensor node
> > arm64: dts: qcom: sdm845-db845c-navigation-mezzanine: Replace
> > clock-frequency in camera sensor node
> > arm64: dts: renesas: aistarvision-mipi-adapter-2.1: Drop
> > clock-frequency from camera sensor node
> > arm64: dts: renesas: rzg2l-smarc: Drop clock-frequency from camera
> > sensor node
> > media: i2c: mt9v022: Drop unused mt9v022.h header
> > media: i2c: mt9v032: Replace client->dev usage
> > media: i2c: mt9v032: Drop support for platform data
> > media: i2c: mt9v111: Do not set clock rate manually
> > media: i2c: ov6650: Drop unused driver
> > media: i2c: hi556: Replace client->dev usage
> > media: i2c: hi556: Use V4L2 sensor clock helper
> > media: i2c: hi847: Replace client->dev usage
> > media: i2c: hi847: Use V4L2 sensor clock helper
> > media: i2c: imx208: Replace client->dev usage
> > media: i2c: imx208: Use V4L2 sensor clock helper
> > media: i2c: imx319: Replace client->dev usage
> > media: i2c: imx319: Use V4L2 sensor clock helper
> > media: i2c: imx355: Replace client->dev usage
> > media: i2c: imx335: Use V4L2 sensor clock helper
> > media: i2c: og01a1b: Replace client->dev usage
> > media: i2c: og01a1b: Use V4L2 sensor clock helper
> > media: i2c: ov02c10: Replace client->dev usage
> > media: i2c: ov02c10: Use V4L2 sensor clock helper
> > media: i2c: ov02e10: Replace client->dev usage
> > media: i2c: ov02e10: Use V4L2 sensor clock helper
> > media: i2c: ov08d10: Replace client->dev usage
> > media: i2c: ov08d10: Use V4L2 sensor clock helper
> > media: i2c: ov08x40: Replace client->dev usage
> > media: i2c: ov08x40: Use V4L2 sensor clock helper
> > media: i2c: ov13858: Replace client->dev usage
> > media: i2c: ov13858: Use V4L2 sensor clock helper
> > media: i2c: ov13b10: Replace client->dev usage
> > media: i2c: ov13b10: Use V4L2 sensor clock helper
> > media: i2c: ov2740: Replace client->dev usage
> > media: i2c: ov2740: Use V4L2 sensor clock helper
> > media: i2c: ov4689: Use V4L2 sensor clock helper
> > media: i2c: ov5670: Replace client->dev usage
> > media: i2c: ov5670: Use V4L2 sensor clock helper
> > media: i2c: ov5675: Replace client->dev usage
> > media: i2c: ov5675: Use V4L2 sensor clock helper
> > media: i2c: ov5693: Use V4L2 sensor clock helper
> > media: i2c: ov7251: Use V4L2 sensor clock helper
> > media: i2c: ov9734: Replace client->dev usage
> > media: i2c: ov9734: Use V4L2 sensor clock helper
> > media: v4l2-common: Add legacy camera sensor clock helper
> > media: i2c: et8ek8: Drop support for per-mode external clock frequency
> > media: i2c: et8ek8: Use V4L2 legacy sensor clock helper
> > media: i2c: gc05a2: Use V4L2 legacy sensor clock helper
> > media: i2c: gc08a3: Use V4L2 legacy sensor clock helper
> > media: i2c: imx258: Replace client->dev usage
> > media: i2c: imx258: Use V4L2 legacy sensor clock helper
> > media: i2c: imx290: Use V4L2 legacy sensor clock helper
> > media: i2c: ov02a10: Replace client->dev usage
> > media: i2c: ov02a10: Use V4L2 legacy sensor clock helper
> > media: i2c: ov2685: Use V4L2 legacy sensor clock helper
> > media: i2c: ov5645: Use V4L2 legacy sensor clock helper
> > media: i2c: ov5695: Use V4L2 legacy sensor clock helper
> > media: i2c: ov8856: Replace client->dev usage
> > media: i2c: ov8856: Use V4L2 legacy sensor clock helper
> > media: i2c: s5c73m3: Use V4L2 legacy sensor clock helper
> > media: i2c: s5k5baf: Use V4L2 legacy sensor clock helper
> > media: i2c: s5k6a3: Use V4L2 legacy sensor clock helper
>
> If you are planning a v2 version of this patch series, please consider
> incorporating the following improvements:
>
> 1. In the imx219 driver, you can also replace direct client->dev usage.
The series doesn't touch the imx219 driver. The patches that replace
client->dev usage were meant to simplify the other changes. Additional
client->dev removal should be done on top (and likely through all camera
sensor drivers in one go).
> 2. In the regulator code, you can reduce boilerplate by using
> devm_regulator_bulk_get_enable().
devm_regulator_bulk_get_enable() doesn't seem to be a good idea. You
generally don't want to enable power everywhere unconditionally, and
sensors very often need a guaranteed power up sequence.
> Otherwise, I will submit a separate patch series on top of yours to
> address these points.
--
Regards,
Laurent Pinchart
^ permalink raw reply [flat|nested] 115+ messages in thread
* Re: [PATCH 00/72] media: i2c: Reduce cargo-cult
[not found] ` <PN3P287MB1829C9E8C78ADD70259A68F08B5EA@PN3P287MB1829.INDP287.PROD.OUTLOOK.COM>
@ 2025-07-24 13:37 ` Mark Brown
2025-07-24 13:52 ` Laurent Pinchart
1 sibling, 0 replies; 115+ messages in thread
From: Mark Brown @ 2025-07-24 13:37 UTC (permalink / raw)
To: Tarang Raval
Cc: Laurent Pinchart, linux-media@vger.kernel.org, Sakari Ailus,
Mehdi Djait, Alim Akhtar, André Apitzsch, Andrzej Hajda,
Arec Kao, Benjamin Mugnier, Bingbu Cao, Bjorn Andersson,
Bryan O'Donoghue, Bryan O'Donoghue, Conor Dooley,
Daniel Scally, Dongcheng Yan, Dongchun Zhu, Fabio Estevam,
Geert Uytterhoeven, Hans de Goede, Hans Verkuil, Hao Yao,
Heimir Thor Sverrisson, Jacopo Mondi, Jason Chen, Jimmy Su,
Jingjing Xiong, Jonas Karlman, Konrad Dybcio, Krzysztof Kozlowski,
Lad Prabhakar, Leon Luo, Liam Girdwood, Magnus Damm,
Manivannan Sadhasivam, Matthew Majewski, Matthias Fend,
Mikhail Rudenko, Nicolas Dufresne, Niklas Söderlund,
Pavel Machek, Pengutronix Kernel Team, Ricardo Ribalda,
Rob Herring, Sascha Hauer, Shawn Guo, Shunqian Zheng,
Sylvain Petinot, Sylwester Nawrocki, Tianshu Qiu, Todor Tomov,
Tomi Valkeinen, Tony Lindgren, Zhi Mao,
devicetree@vger.kernel.org, imx@lists.linux.dev,
linux-arm-kernel@lists.infradead.org,
linux-arm-msm@vger.kernel.org, linux-omap@vger.kernel.org,
linux-renesas-soc@vger.kernel.org,
linux-samsung-soc@vger.kernel.org
[-- Attachment #1: Type: text/plain, Size: 613 bytes --]
On Thu, Jul 24, 2025 at 01:24:24PM +0000, Tarang Raval wrote:
> > > 2. In the regulator code, you can reduce boilerplate by using
> > > devm_regulator_bulk_get_enable().
> > devm_regulator_bulk_get_enable() doesn't seem to be a good idea. You
> > generally don't want to enable power everywhere unconditionally, and
> > sensors very often need a guaranteed power up sequence.
> The regulators are optional, we supply power to the camera sensor directly
> through dedicated power rails and there is no strict enable sequence
> required in this case.
Those dedicated power rails getting their power from....
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]
^ permalink raw reply [flat|nested] 115+ messages in thread
* Re: [PATCH 00/72] media: i2c: Reduce cargo-cult
[not found] ` <PN3P287MB1829C9E8C78ADD70259A68F08B5EA@PN3P287MB1829.INDP287.PROD.OUTLOOK.COM>
2025-07-24 13:37 ` Mark Brown
@ 2025-07-24 13:52 ` Laurent Pinchart
2025-07-24 14:20 ` Tarang Raval
1 sibling, 1 reply; 115+ messages in thread
From: Laurent Pinchart @ 2025-07-24 13:52 UTC (permalink / raw)
To: Tarang Raval
Cc: linux-media@vger.kernel.org, Sakari Ailus, Mehdi Djait,
Alim Akhtar, André Apitzsch, Andrzej Hajda, Arec Kao,
Benjamin Mugnier, Bingbu Cao, Bjorn Andersson,
Bryan O'Donoghue, Bryan O'Donoghue, Conor Dooley,
Daniel Scally, Dongcheng Yan, Dongchun Zhu, Fabio Estevam,
Geert Uytterhoeven, Hans de Goede, Hans Verkuil, Hao Yao,
Heimir Thor Sverrisson, Jacopo Mondi, Jason Chen, Jimmy Su,
Jingjing Xiong, Jonas Karlman, Konrad Dybcio, Krzysztof Kozlowski,
Lad Prabhakar, Leon Luo, Liam Girdwood, Magnus Damm,
Manivannan Sadhasivam, Mark Brown, Matthew Majewski,
Matthias Fend, Mikhail Rudenko, Nicolas Dufresne,
Niklas Söderlund, Pavel Machek, Pengutronix Kernel Team,
Ricardo Ribalda, Rob Herring, Sascha Hauer, Shawn Guo,
Shunqian Zheng, Sylvain Petinot, Sylwester Nawrocki, Tianshu Qiu,
Todor Tomov, Tomi Valkeinen, Tony Lindgren, Zhi Mao,
devicetree@vger.kernel.org, imx@lists.linux.dev,
linux-arm-kernel@lists.infradead.org,
linux-arm-msm@vger.kernel.org, linux-omap@vger.kernel.org,
linux-renesas-soc@vger.kernel.org,
linux-samsung-soc@vger.kernel.org
On Thu, Jul 24, 2025 at 01:24:24PM +0000, Tarang Raval wrote:
> > On Thu, Jul 24, 2025 at 11:42:55AM +0000, Tarang Raval wrote:
> > > Hi Laurent,
> > >
> > > > This patch series build on top of Mehdi's introduction of the
> > > > devm_v4l2_sensor_clk_get() helper (see [1]) to drastically reduce
> > > > cargo-cult in camera sensor drivers.
> > > >
> > > > A large number of camera sensor drivers directly use the
> > > > "clock-frequency" property to retrieve the effective or desired external
> > > > clock rate. This is standard behaviour on ACPI platforms that don't
> > > > implement MIPI DisCo for Imaging, but usage of the property has leaked
> > > > to OF-based platforms, due to a combination of historical reasons (using
> > > > "clock-frequency" was initially considered right until before the
> > > > introduction of "assigned-clock-rates") and plain cargo-cult.
> > > >
> > > > A large number of camera sensor drivers also set the rate of the
> > > > external clock with clk_set_rate(). This behaviour is also fine on ACPI
> > > > platforms, and has also leaked to OF-based platforms for the same
> > > > reasons.
> > > >
> > > > Mehdi's "[PATCH v2 00/48] media: Add a helper for obtaining the clock
> > > > producer" series improves the situation by centralizing clock handling
> > > > for camera sensor in one helper function that implements the correct
> > > > behaviour for all types of platforms (and should later allow support of
> > > > MIPI DisCo for Imaging transparently for camera sensor drivers). It
> > > > doesn't however address direct access of the "clock-frequency" property
> > > > or direct calls to clk_set_rate() in drivers.
> > > >
> > > > This series builds on top of the new helper to replace manual handling
> > > > of the clock frequency in camera sensor drivers. It starts by addressing
> > > > the DT bindings and reprecating the clock-frequency property for camera
> > > > sensor drivers in all YAML bindings (01/72) and in the et8ek8 text
> > > > bindings (02/72). After that, patches 03/72 and 04/72 make the clocks
> > > > property mandatory in the two camera sensor DT bindings that specified
> > > > it as optional. Finally for the DT side, patches 05/72 to 14/72 replace
> > > > clock-frequency with assigned-clock-rates, or drops the property
> > > > altogether when the source clock has a fixed rate. This aligns the DT
> > > > bindings and device tree sources to the current recommended practice.
> > > >
> > > > After that, the next 5 patches are assorted drive-by changes. Patch
> > > > 15/72 drops an unused header the belonged to a long gone driver, and
> > > > patch 17/72 drops unusued support for platform data in the mt9v032
> > > > driver. Patch 18/72 is the first that addresses clock rate handling by
> > > > dropping unneeded clock rate setting in the mt9v111 driver. Patch 19/72
> > > > takes a harsher approach for the ov6650 by dropping the driver
> > > > completely as the driver hasn't been used since v5.9.
> > > >
> > > > The next part of the series replaces manual clock rate handling with
> > > > usage of the devm_v4l2_sensor_clk_get() helper in a large number of
> > > > camera sensor drivers that implement clock rate handling in a standard
> > > > way. This is done in patches 20/72 to 54/72. This interleaves the clock
> > > > rate handling changes with drive-by refactoring (in separate patches) to
> > > > make the code easier to deal with.
> > > >
> > > > The final part of the series addresses the remaining drivers that
> > > > implement non-standard behaviours. It starts in 55/72 by adding a new
> > > > devm_v4l2_sensor_clk_get_legacy() helper function for those drivers,
> > > > similar to devm_v4l2_sensor_clk_get() but with a few more quirks. This
> > > > function should not be used in any new driver. The remaining patches,
> > > > from 53/72 to 72/72, use the new helper in drivers, interleaved with
> > > > drive-by refactoring similarly to the previous part.
> > > >
> > > > Before this series, with Mehdi's series applied, 29 drivers read the
> > > > "clock-frequency" property and 18 drivers set the external clock rate.
> > > > With these series we go down to 1 and 3 respectively, namely the ccs,
> > > > mt9p031 and mt9v032 drivers. Clock handling in the CCS driver is a bit
> > > > more convoluted so I will leave to Sakari the honour of dropping the
> > > > last direct user of "clock-frequency" :-) As for the mt9p031 and mt9v032
> > > > driver, addressing the issue there is more difficult and likely not
> > > > worth it.
> > > >
> > > > [1] https://lore.kernel.org/linux-media/
> cover.1750942967.git.mehdi.djait@linux.intel.com
> > > >
> > > > Laurent Pinchart (72):
> > > > dt-bindings: media: Deprecate clock-frequency property for camera sensors
> > > > dt-bindings: media: et8ek8: Deprecate clock-frequency property
> > > > dt-bindings: media: imx258: Make clocks property required
> > > > dt-bindings: media: imx274: Make clocks property required
> > > > ARM: dts: nxp: imx6qdl-pico: Replace clock-frequency in camera sensor node
> > > > ARM: dts: nxp: imx6qdl-wandboard: Replace clock-frequency in camera sensor node
> > > > ARM: dts: samsung: exynos4210-i9100: Replace clock-frequency in camera sensor node
> > > > ARM: dts: samsung: exynos4412-midas: Replace clock-frequency in camera sensor node
> > > > ARM: dts: ti: omap3-n900: Replace clock-frequency in camera sensor node
> > > > ARM: dts: ti: omap3-n950: Replace clock-frequency in camera sensor node
> > > > ARM: dts: ti: omap3-n9: Replace clock-frequency in camera sensor node
> > > > arm64: dts: qcom: sdm845-db845c-navigation-mezzanine: Replace clock-frequency in camera sensor node
> > > > arm64: dts: renesas: aistarvision-mipi-adapter-2.1: Drop clock-frequency from camera sensor node
> > > > arm64: dts: renesas: rzg2l-smarc: Drop clock-frequency from camera sensor node
> > > > media: i2c: mt9v022: Drop unused mt9v022.h header
> > > > media: i2c: mt9v032: Replace client->dev usage
> > > > media: i2c: mt9v032: Drop support for platform data
> > > > media: i2c: mt9v111: Do not set clock rate manually
> > > > media: i2c: ov6650: Drop unused driver
> > > > media: i2c: hi556: Replace client->dev usage
> > > > media: i2c: hi556: Use V4L2 sensor clock helper
> > > > media: i2c: hi847: Replace client->dev usage
> > > > media: i2c: hi847: Use V4L2 sensor clock helper
> > > > media: i2c: imx208: Replace client->dev usage
> > > > media: i2c: imx208: Use V4L2 sensor clock helper
> > > > media: i2c: imx319: Replace client->dev usage
> > > > media: i2c: imx319: Use V4L2 sensor clock helper
> > > > media: i2c: imx355: Replace client->dev usage
> > > > media: i2c: imx335: Use V4L2 sensor clock helper
> > > > media: i2c: og01a1b: Replace client->dev usage
> > > > media: i2c: og01a1b: Use V4L2 sensor clock helper
> > > > media: i2c: ov02c10: Replace client->dev usage
> > > > media: i2c: ov02c10: Use V4L2 sensor clock helper
> > > > media: i2c: ov02e10: Replace client->dev usage
> > > > media: i2c: ov02e10: Use V4L2 sensor clock helper
> > > > media: i2c: ov08d10: Replace client->dev usage
> > > > media: i2c: ov08d10: Use V4L2 sensor clock helper
> > > > media: i2c: ov08x40: Replace client->dev usage
> > > > media: i2c: ov08x40: Use V4L2 sensor clock helper
> > > > media: i2c: ov13858: Replace client->dev usage
> > > > media: i2c: ov13858: Use V4L2 sensor clock helper
> > > > media: i2c: ov13b10: Replace client->dev usage
> > > > media: i2c: ov13b10: Use V4L2 sensor clock helper
> > > > media: i2c: ov2740: Replace client->dev usage
> > > > media: i2c: ov2740: Use V4L2 sensor clock helper
> > > > media: i2c: ov4689: Use V4L2 sensor clock helper
> > > > media: i2c: ov5670: Replace client->dev usage
> > > > media: i2c: ov5670: Use V4L2 sensor clock helper
> > > > media: i2c: ov5675: Replace client->dev usage
> > > > media: i2c: ov5675: Use V4L2 sensor clock helper
> > > > media: i2c: ov5693: Use V4L2 sensor clock helper
> > > > media: i2c: ov7251: Use V4L2 sensor clock helper
> > > > media: i2c: ov9734: Replace client->dev usage
> > > > media: i2c: ov9734: Use V4L2 sensor clock helper
> > > > media: v4l2-common: Add legacy camera sensor clock helper
> > > > media: i2c: et8ek8: Drop support for per-mode external clock frequency
> > > > media: i2c: et8ek8: Use V4L2 legacy sensor clock helper
> > > > media: i2c: gc05a2: Use V4L2 legacy sensor clock helper
> > > > media: i2c: gc08a3: Use V4L2 legacy sensor clock helper
> > > > media: i2c: imx258: Replace client->dev usage
> > > > media: i2c: imx258: Use V4L2 legacy sensor clock helper
> > > > media: i2c: imx290: Use V4L2 legacy sensor clock helper
> > > > media: i2c: ov02a10: Replace client->dev usage
> > > > media: i2c: ov02a10: Use V4L2 legacy sensor clock helper
> > > > media: i2c: ov2685: Use V4L2 legacy sensor clock helper
> > > > media: i2c: ov5645: Use V4L2 legacy sensor clock helper
> > > > media: i2c: ov5695: Use V4L2 legacy sensor clock helper
> > > > media: i2c: ov8856: Replace client->dev usage
> > > > media: i2c: ov8856: Use V4L2 legacy sensor clock helper
> > > > media: i2c: s5c73m3: Use V4L2 legacy sensor clock helper
> > > > media: i2c: s5k5baf: Use V4L2 legacy sensor clock helper
> > > > media: i2c: s5k6a3: Use V4L2 legacy sensor clock helper
> > >
> > > If you are planning a v2 version of this patch series, please consider
> > > incorporating the following improvements:
> > >
> > > 1. In the imx219 driver, you can also replace direct client->dev usage.
> >
> > The series doesn't touch the imx219 driver. The patches that replace
> > client->dev usage were meant to simplify the other changes. Additional
> > client->dev removal should be done on top (and likely through all camera
> > sensor drivers in one go).
>
> Okay, great
>
> > > 2. In the regulator code, you can reduce boilerplate by using
> > > devm_regulator_bulk_get_enable().
> >
> > devm_regulator_bulk_get_enable() doesn't seem to be a good idea. You
> > generally don't want to enable power everywhere unconditionally, and
> > sensors very often need a guaranteed power up sequence.
>
> The regulators are optional, we supply power to the camera sensor directly
> through dedicated power rails and there is no strict enable sequence
> required in this case.
What exactly do you mean by "this case" ? Are you talking about one
particular sensor ? One particular camera module ?
> However, if you feel it's better to retain explicit handling for clarity
> and flexibility, I’m happy to stick with the current approach.
--
Regards,
Laurent Pinchart
^ permalink raw reply [flat|nested] 115+ messages in thread
* Re: [PATCH 00/72] media: i2c: Reduce cargo-cult
2025-07-24 13:52 ` Laurent Pinchart
@ 2025-07-24 14:20 ` Tarang Raval
2025-07-24 14:26 ` Mark Brown
2025-07-24 15:44 ` Laurent Pinchart
0 siblings, 2 replies; 115+ messages in thread
From: Tarang Raval @ 2025-07-24 14:20 UTC (permalink / raw)
To: Laurent Pinchart
Cc: linux-media@vger.kernel.org, Sakari Ailus, Mehdi Djait,
Alim Akhtar, André Apitzsch, Andrzej Hajda, Arec Kao,
Benjamin Mugnier, Bingbu Cao, Bjorn Andersson,
Bryan O'Donoghue, Bryan O'Donoghue, Conor Dooley,
Daniel Scally, Dongcheng Yan, Dongchun Zhu, Fabio Estevam,
Geert Uytterhoeven, Hans de Goede, Hans Verkuil, Hao Yao,
Heimir Thor Sverrisson, Jacopo Mondi, Jason Chen, Jimmy Su,
Jingjing Xiong, Jonas Karlman, Konrad Dybcio, Krzysztof Kozlowski,
Lad Prabhakar, Leon Luo, Liam Girdwood, Magnus Damm,
Manivannan Sadhasivam, Mark Brown, Matthew Majewski,
Matthias Fend, Mikhail Rudenko, Nicolas Dufresne,
Niklas Söderlund, Pavel Machek, Pengutronix Kernel Team,
Ricardo Ribalda, Rob Herring, Sascha Hauer, Shawn Guo,
Shunqian Zheng, Sylvain Petinot, Sylwester Nawrocki, Tianshu Qiu,
Todor Tomov, Tomi Valkeinen, Tony Lindgren, Zhi Mao,
devicetree@vger.kernel.org, imx@lists.linux.dev,
linux-arm-kernel@lists.infradead.org,
linux-arm-msm@vger.kernel.org, linux-omap@vger.kernel.org,
linux-renesas-soc@vger.kernel.org,
linux-samsung-soc@vger.kernel.org
> > > > 2. In the regulator code, you can reduce boilerplate by using
> > > > devm_regulator_bulk_get_enable().
> > >
> > > devm_regulator_bulk_get_enable() doesn't seem to be a good idea. You
> > > generally don't want to enable power everywhere unconditionally, and
> > > sensors very often need a guaranteed power up sequence.
> >
> > The regulators are optional, we supply power to the camera sensor directly
> > through dedicated power rails and there is no strict enable sequence
> > required in this case.
>
> What exactly do you mean by "this case" ? Are you talking about one
> particular sensor ? One particular camera module ?
Laurent, by “this case” I meant the common scenario where power to the
camera sensor is supplied by a PMIC regulator that is always-on. In such
setups, the regulator is fixed and cannot be enabled or disabled from the
driver, the sensor is always powered.
This is what I’ve seen in most platforms, where the CSI input connector
provides fixed 3.3V/1.8V power rails directly to the camera module.
Of course, if the camera supply comes from a dedicated regulator controlled
via a GPIO, then the driver would need to handle enable/disable sequencing
explicitly. But I’m specifically referring to the first case, where the power rails
are always-on.
Mark, depending on the hardware, the power rails could come either from a
PMIC or from a regulator controlled by GPIO, but I’m talking about the always-on
PMIC case here.
Best Regards,
Tarang
^ permalink raw reply [flat|nested] 115+ messages in thread
* Re: [PATCH 00/72] media: i2c: Reduce cargo-cult
2025-07-24 14:20 ` Tarang Raval
@ 2025-07-24 14:26 ` Mark Brown
2025-07-24 15:44 ` Laurent Pinchart
1 sibling, 0 replies; 115+ messages in thread
From: Mark Brown @ 2025-07-24 14:26 UTC (permalink / raw)
To: Tarang Raval
Cc: Laurent Pinchart, linux-media@vger.kernel.org, Sakari Ailus,
Mehdi Djait, Alim Akhtar, André Apitzsch, Andrzej Hajda,
Arec Kao, Benjamin Mugnier, Bingbu Cao, Bjorn Andersson,
Bryan O'Donoghue, Bryan O'Donoghue, Conor Dooley,
Daniel Scally, Dongcheng Yan, Dongchun Zhu, Fabio Estevam,
Geert Uytterhoeven, Hans de Goede, Hans Verkuil, Hao Yao,
Heimir Thor Sverrisson, Jacopo Mondi, Jason Chen, Jimmy Su,
Jingjing Xiong, Jonas Karlman, Konrad Dybcio, Krzysztof Kozlowski,
Lad Prabhakar, Leon Luo, Liam Girdwood, Magnus Damm,
Manivannan Sadhasivam, Matthew Majewski, Matthias Fend,
Mikhail Rudenko, Nicolas Dufresne, Niklas Söderlund,
Pavel Machek, Pengutronix Kernel Team, Ricardo Ribalda,
Rob Herring, Sascha Hauer, Shawn Guo, Shunqian Zheng,
Sylvain Petinot, Sylwester Nawrocki, Tianshu Qiu, Todor Tomov,
Tomi Valkeinen, Tony Lindgren, Zhi Mao,
devicetree@vger.kernel.org, imx@lists.linux.dev,
linux-arm-kernel@lists.infradead.org,
linux-arm-msm@vger.kernel.org, linux-omap@vger.kernel.org,
linux-renesas-soc@vger.kernel.org,
linux-samsung-soc@vger.kernel.org
[-- Attachment #1: Type: text/plain, Size: 418 bytes --]
On Thu, Jul 24, 2025 at 02:20:10PM +0000, Tarang Raval wrote:
> Mark, depending on the hardware, the power rails could come either from a
> PMIC or from a regulator controlled by GPIO, but I’m talking about the always-on
> PMIC case here.
All of those things are regulators. My point is that a supply being
optional means it can be physically absent from the device which does
happen but quite rarely.
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 484 bytes --]
^ permalink raw reply [flat|nested] 115+ messages in thread
* Re: [PATCH 00/72] media: i2c: Reduce cargo-cult
2025-07-24 14:20 ` Tarang Raval
2025-07-24 14:26 ` Mark Brown
@ 2025-07-24 15:44 ` Laurent Pinchart
2025-07-25 7:00 ` Tarang Raval
1 sibling, 1 reply; 115+ messages in thread
From: Laurent Pinchart @ 2025-07-24 15:44 UTC (permalink / raw)
To: Tarang Raval
Cc: linux-media@vger.kernel.org, Sakari Ailus, Mehdi Djait,
Alim Akhtar, André Apitzsch, Andrzej Hajda, Arec Kao,
Benjamin Mugnier, Bingbu Cao, Bjorn Andersson,
Bryan O'Donoghue, Bryan O'Donoghue, Conor Dooley,
Daniel Scally, Dongcheng Yan, Dongchun Zhu, Fabio Estevam,
Geert Uytterhoeven, Hans de Goede, Hans Verkuil, Hao Yao,
Heimir Thor Sverrisson, Jacopo Mondi, Jason Chen, Jimmy Su,
Jingjing Xiong, Jonas Karlman, Konrad Dybcio, Krzysztof Kozlowski,
Lad Prabhakar, Leon Luo, Liam Girdwood, Magnus Damm,
Manivannan Sadhasivam, Mark Brown, Matthew Majewski,
Matthias Fend, Mikhail Rudenko, Nicolas Dufresne,
Niklas Söderlund, Pavel Machek, Pengutronix Kernel Team,
Ricardo Ribalda, Rob Herring, Sascha Hauer, Shawn Guo,
Shunqian Zheng, Sylvain Petinot, Sylwester Nawrocki, Tianshu Qiu,
Todor Tomov, Tomi Valkeinen, Tony Lindgren, Zhi Mao,
devicetree@vger.kernel.org, imx@lists.linux.dev,
linux-arm-kernel@lists.infradead.org,
linux-arm-msm@vger.kernel.org, linux-omap@vger.kernel.org,
linux-renesas-soc@vger.kernel.org,
linux-samsung-soc@vger.kernel.org
On Thu, Jul 24, 2025 at 02:20:10PM +0000, Tarang Raval wrote:
> > > > > 2. In the regulator code, you can reduce boilerplate by using
> > > > > devm_regulator_bulk_get_enable().
> > > >
> > > > devm_regulator_bulk_get_enable() doesn't seem to be a good idea. You
> > > > generally don't want to enable power everywhere unconditionally, and
> > > > sensors very often need a guaranteed power up sequence.
> > >
> > > The regulators are optional, we supply power to the camera sensor directly
> > > through dedicated power rails and there is no strict enable sequence
> > > required in this case.
> >
> > What exactly do you mean by "this case" ? Are you talking about one
> > particular sensor ? One particular camera module ?
>
> Laurent, by “this case” I meant the common scenario where power to the
> camera sensor is supplied by a PMIC regulator that is always-on. In such
> setups, the regulator is fixed and cannot be enabled or disabled from the
> driver, the sensor is always powered.
>
> This is what I’ve seen in most platforms, where the CSI input connector
> provides fixed 3.3V/1.8V power rails directly to the camera module.
>
> Of course, if the camera supply comes from a dedicated regulator controlled
> via a GPIO, then the driver would need to handle enable/disable sequencing
> explicitly. But I’m specifically referring to the first case, where the power rails
> are always-on.
How does the sensor driver know which of those two cases it is dealing
with ?
> Mark, depending on the hardware, the power rails could come either from a
> PMIC or from a regulator controlled by GPIO, but I’m talking about the always-on
> PMIC case here.
--
Regards,
Laurent Pinchart
^ permalink raw reply [flat|nested] 115+ messages in thread
* Re: [PATCH 00/72] media: i2c: Reduce cargo-cult
2025-07-24 15:44 ` Laurent Pinchart
@ 2025-07-25 7:00 ` Tarang Raval
2025-07-25 9:38 ` Laurent Pinchart
2025-07-25 12:35 ` Mark Brown
0 siblings, 2 replies; 115+ messages in thread
From: Tarang Raval @ 2025-07-25 7:00 UTC (permalink / raw)
To: Laurent Pinchart
Cc: linux-media@vger.kernel.org, Sakari Ailus, Mehdi Djait,
Alim Akhtar, André Apitzsch, Andrzej Hajda, Arec Kao,
Benjamin Mugnier, Bingbu Cao, Bjorn Andersson,
Bryan O'Donoghue, Bryan O'Donoghue, Conor Dooley,
Daniel Scally, Dongcheng Yan, Fabio Estevam, Geert Uytterhoeven,
Hans de Goede, Hans Verkuil, Hao Yao, Heimir Thor Sverrisson,
Jacopo Mondi, Jimmy Su, Jingjing Xiong, Jonas Karlman,
Konrad Dybcio, Krzysztof Kozlowski, Lad Prabhakar, Leon Luo,
Liam Girdwood, Magnus Damm, Manivannan Sadhasivam, Mark Brown,
Matthew Majewski, Matthias Fend, Mikhail Rudenko,
Nicolas Dufresne, Niklas Söderlund, Pavel Machek,
Pengutronix Kernel Team, Ricardo Ribalda, Rob Herring,
Sascha Hauer, Shawn Guo, Shunqian Zheng, Sylvain Petinot,
Sylwester Nawrocki, Tianshu Qiu, Todor Tomov, Tomi Valkeinen,
Tony Lindgren, Zhi Mao, devicetree@vger.kernel.org,
imx@lists.linux.dev, linux-arm-kernel@lists.infradead.org,
linux-arm-msm@vger.kernel.org, linux-omap@vger.kernel.org,
linux-renesas-soc@vger.kernel.org,
linux-samsung-soc@vger.kernel.org
> On Thu, Jul 24, 2025 at 02:20:10PM +0000, Tarang Raval wrote:
> > > > > > 2. In the regulator code, you can reduce boilerplate by using
> > > > > > devm_regulator_bulk_get_enable().
> > > > >
> > > > > devm_regulator_bulk_get_enable() doesn't seem to be a good idea. You
> > > > > generally don't want to enable power everywhere unconditionally, and
> > > > > sensors very often need a guaranteed power up sequence.
-----(1)
> > > >
> > > > The regulators are optional, we supply power to the camera sensor directly
> > > > through dedicated power rails and there is no strict enable sequence
> > > > required in this case.
> > >
> > > What exactly do you mean by "this case" ? Are you talking about one
> > > particular sensor ? One particular camera module ?
> >
> > Laurent, by “this case” I meant the common scenario where power to the
> > camera sensor is supplied by a PMIC regulator that is always-on. In such
> > setups, the regulator is fixed and cannot be enabled or disabled from the
> > driver, the sensor is always powered.
> >
> > This is what I’ve seen in most platforms, where the CSI input connector
> > provides fixed 3.3V/1.8V power rails directly to the camera module.
> >
> > Of course, if the camera supply comes from a dedicated regulator controlled
> > via a GPIO, then the driver would need to handle enable/disable sequencing
> > explicitly. But I’m specifically referring to the first case, where the power rails
> > are always-on.
>
> How does the sensor driver know which of those two cases it is dealing
> with ?
The sensor driver typically determines this via the presence (or absence)
of regulator supply entries in the Device Tree. If a supply is not defined,
it's assumed to be always-on (e.g., provided by the board via fixed rails).
When defined, the driver retrieves and manages the regulator. This approach
allows a single driver to support both cases, by treating supplies as optional
and only enabling them when explicitly defined.
At comment (1): you gave two reasons why we cannot use devm_regulator_bulk_get_enable.
What I’m trying to say is:
You mentioned "generally don't want to enable power everywhere unconditionally,"
but on almost every platform, the power rails are always-on.
And regarding the second point — "sensors very often need a guaranteed power-up sequence"
I don’t understand why this would be an issue. Even if we use devm_regulator_bulk_get_enable,
the power-up sequence remains the same. So how is it not a good option in this case?
Best Regards,
Tarang
^ permalink raw reply [flat|nested] 115+ messages in thread
* Re: [PATCH 00/72] media: i2c: Reduce cargo-cult
2025-07-25 7:00 ` Tarang Raval
@ 2025-07-25 9:38 ` Laurent Pinchart
2025-07-25 10:35 ` Tarang Raval
2025-07-25 12:35 ` Mark Brown
1 sibling, 1 reply; 115+ messages in thread
From: Laurent Pinchart @ 2025-07-25 9:38 UTC (permalink / raw)
To: Tarang Raval
Cc: linux-media@vger.kernel.org, Sakari Ailus, Mehdi Djait,
Alim Akhtar, André Apitzsch, Andrzej Hajda, Arec Kao,
Benjamin Mugnier, Bingbu Cao, Bjorn Andersson,
Bryan O'Donoghue, Bryan O'Donoghue, Conor Dooley,
Daniel Scally, Dongcheng Yan, Fabio Estevam, Geert Uytterhoeven,
Hans de Goede, Hans Verkuil, Hao Yao, Heimir Thor Sverrisson,
Jacopo Mondi, Jimmy Su, Jingjing Xiong, Jonas Karlman,
Konrad Dybcio, Krzysztof Kozlowski, Lad Prabhakar, Leon Luo,
Liam Girdwood, Magnus Damm, Manivannan Sadhasivam, Mark Brown,
Matthew Majewski, Matthias Fend, Mikhail Rudenko,
Nicolas Dufresne, Niklas Söderlund, Pavel Machek,
Pengutronix Kernel Team, Ricardo Ribalda, Rob Herring,
Sascha Hauer, Shawn Guo, Shunqian Zheng, Sylvain Petinot,
Sylwester Nawrocki, Tianshu Qiu, Todor Tomov, Tomi Valkeinen,
Tony Lindgren, Zhi Mao, devicetree@vger.kernel.org,
imx@lists.linux.dev, linux-arm-kernel@lists.infradead.org,
linux-arm-msm@vger.kernel.org, linux-omap@vger.kernel.org,
linux-renesas-soc@vger.kernel.org,
linux-samsung-soc@vger.kernel.org
On Fri, Jul 25, 2025 at 07:00:40AM +0000, Tarang Raval wrote:
> > On Thu, Jul 24, 2025 at 02:20:10PM +0000, Tarang Raval wrote:
> > > > > > > 2. In the regulator code, you can reduce boilerplate by using
> > > > > > > devm_regulator_bulk_get_enable().
> > > > > >
> > > > > > devm_regulator_bulk_get_enable() doesn't seem to be a good idea. You
> > > > > > generally don't want to enable power everywhere unconditionally, and
> > > > > > sensors very often need a guaranteed power up sequence.
>
> -----(1)
>
> > > > >
> > > > > The regulators are optional, we supply power to the camera sensor directly
> > > > > through dedicated power rails and there is no strict enable sequence
> > > > > required in this case.
> > > >
> > > > What exactly do you mean by "this case" ? Are you talking about one
> > > > particular sensor ? One particular camera module ?
> > >
> > > Laurent, by “this case” I meant the common scenario where power to the
> > > camera sensor is supplied by a PMIC regulator that is always-on. In such
> > > setups, the regulator is fixed and cannot be enabled or disabled from the
> > > driver, the sensor is always powered.
> > >
> > > This is what I’ve seen in most platforms, where the CSI input connector
> > > provides fixed 3.3V/1.8V power rails directly to the camera module.
> > >
> > > Of course, if the camera supply comes from a dedicated regulator controlled
> > > via a GPIO, then the driver would need to handle enable/disable sequencing
> > > explicitly. But I’m specifically referring to the first case, where the power rails
> > > are always-on.
> >
> > How does the sensor driver know which of those two cases it is dealing
> > with ?
>
> The sensor driver typically determines this via the presence (or absence)
> of regulator supply entries in the Device Tree. If a supply is not defined,
> it's assumed to be always-on (e.g., provided by the board via fixed rails).
Do we have sensor drivers that check the presense of supply properties ?
Drivers generally shouldn't.
> When defined, the driver retrieves and manages the regulator. This approach
> allows a single driver to support both cases, by treating supplies as optional
> and only enabling them when explicitly defined.
I don't see what you're trying to do here. A sensor always needs
supplies, regardless of whether or not they're always on. Drivers should
get the supplies with regulator_get() (or possibly the bulk API), and
then implement the power enable/disable sequences that the sensor
requires. If all suplies are manually controllable, this will produce
the correct sequence. If the supplies are always on, it will be a no-op.
That's a single implementation in the driver, you don't need to care
about the nature of the supplies, or their presence in DT.
> At comment (1): you gave two reasons why we cannot use devm_regulator_bulk_get_enable.
>
> What I’m trying to say is:
>
> You mentioned "generally don't want to enable power everywhere unconditionally,"
> but on almost every platform, the power rails are always-on.
"almost every platform" doesn't sound right to me. It does happen though.
> And regarding the second point — "sensors very often need a guaranteed power-up sequence"
> I don’t understand why this would be an issue. Even if we use devm_regulator_bulk_get_enable,
> the power-up sequence remains the same. So how is it not a good option in this case?
Because the bulk API enables all regulators in parallel, it doesn't
guarantee sequencing.
Don't use devm_regulator_bulk_get_enable() in sensor drivers, implement
power enable/disable functions that do the right thing. That's the code
pattern I want to see.
--
Regards,
Laurent Pinchart
^ permalink raw reply [flat|nested] 115+ messages in thread
* Re: [PATCH 00/72] media: i2c: Reduce cargo-cult
2025-07-25 9:38 ` Laurent Pinchart
@ 2025-07-25 10:35 ` Tarang Raval
2025-07-25 11:00 ` Laurent Pinchart
0 siblings, 1 reply; 115+ messages in thread
From: Tarang Raval @ 2025-07-25 10:35 UTC (permalink / raw)
To: Laurent Pinchart
Cc: linux-media@vger.kernel.org, Sakari Ailus, Mehdi Djait,
Alim Akhtar, André Apitzsch, Andrzej Hajda, Arec Kao,
Benjamin Mugnier, Bingbu Cao, Bjorn Andersson,
Bryan O'Donoghue, Bryan O'Donoghue, Conor Dooley,
Daniel Scally, Dongcheng Yan, Fabio Estevam, Geert Uytterhoeven,
Hans de Goede, Hans Verkuil, Hao Yao, Heimir Thor Sverrisson,
Jacopo Mondi, Jimmy Su, Jingjing Xiong, Jonas Karlman,
Konrad Dybcio, Krzysztof Kozlowski, Lad Prabhakar, Leon Luo,
Liam Girdwood, Magnus Damm, Manivannan Sadhasivam, Mark Brown,
Matthew Majewski, Matthias Fend, Mikhail Rudenko,
Nicolas Dufresne, Niklas Söderlund, Pavel Machek,
Pengutronix Kernel Team, Ricardo Ribalda, Rob Herring,
Sascha Hauer, Shawn Guo, Shunqian Zheng, Sylvain Petinot,
Sylwester Nawrocki, Tianshu Qiu, Todor Tomov, Tomi Valkeinen,
Tony Lindgren, Zhi Mao, devicetree@vger.kernel.org,
imx@lists.linux.dev, linux-arm-kernel@lists.infradead.org,
linux-arm-msm@vger.kernel.org, linux-omap@vger.kernel.org,
linux-renesas-soc@vger.kernel.org,
linux-samsung-soc@vger.kernel.org
> On Fri, Jul 25, 2025 at 07:00:40AM +0000, Tarang Raval wrote:
> > > On Thu, Jul 24, 2025 at 02:20:10PM +0000, Tarang Raval wrote:
> > > > > > > > 2. In the regulator code, you can reduce boilerplate by using
> > > > > > > > devm_regulator_bulk_get_enable().
> > > > > > >
> > > > > > > devm_regulator_bulk_get_enable() doesn't seem to be a good idea. You
> > > > > > > generally don't want to enable power everywhere unconditionally, and
> > > > > > > sensors very often need a guaranteed power up sequence.
> >
> > -----(1)
> >
> > > > > >
> > > > > > The regulators are optional, we supply power to the camera sensor directly
> > > > > > through dedicated power rails and there is no strict enable sequence
> > > > > > required in this case.
> > > > >
> > > > > What exactly do you mean by "this case" ? Are you talking about one
> > > > > particular sensor ? One particular camera module ?
> > > >
> > > > Laurent, by “this case” I meant the common scenario where power to the
> > > > camera sensor is supplied by a PMIC regulator that is always-on. In such
> > > > setups, the regulator is fixed and cannot be enabled or disabled from the
> > > > driver, the sensor is always powered.
> > > >
> > > > This is what I’ve seen in most platforms, where the CSI input connector
> > > > provides fixed 3.3V/1.8V power rails directly to the camera module.
> > > >
> > > > Of course, if the camera supply comes from a dedicated regulator controlled
> > > > via a GPIO, then the driver would need to handle enable/disable sequencing
> > > > explicitly. But I’m specifically referring to the first case, where the power rails
> > > > are always-on.
> > >
> > > How does the sensor driver know which of those two cases it is dealing
> > > with ?
> >
> > The sensor driver typically determines this via the presence (or absence)
> > of regulator supply entries in the Device Tree. If a supply is not defined,
> > it's assumed to be always-on (e.g., provided by the board via fixed rails).
>
> Do we have sensor drivers that check the presense of supply properties ?
> Drivers generally shouldn't.
>
> > When defined, the driver retrieves and manages the regulator. This approach
> > allows a single driver to support both cases, by treating supplies as optional
> > and only enabling them when explicitly defined.
>
> I don't see what you're trying to do here. A sensor always needs
> supplies, regardless of whether or not they're always on. Drivers should
> get the supplies with regulator_get() (or possibly the bulk API), and
> then implement the power enable/disable sequences that the sensor
> requires. If all suplies are manually controllable, this will produce
> the correct sequence. If the supplies are always on, it will be a no-op.
> That's a single implementation in the driver, you don't need to care
> about the nature of the supplies, or their presence in DT.
>
> > At comment (1): you gave two reasons why we cannot use devm_regulator_bulk_get_enable.
> >
> > What I’m trying to say is:
> >
> > You mentioned "generally don't want to enable power everywhere unconditionally,"
> > but on almost every platform, the power rails are always-on.
>
> "almost every platform" doesn't sound right to me. It does happen though.
>
> > And regarding the second point — "sensors very often need a guaranteed power-up sequence"
> > I don’t understand why this would be an issue. Even if we use devm_regulator_bulk_get_enable,
> > the power-up sequence remains the same. So how is it not a good option in this case?
>
> Because the bulk API enables all regulators in parallel, it doesn't
> guarantee sequencing.
Except for a few drivers, almost all camera drivers use the bulk API, which suggests
that a guaranteed power-up sequence may not be strictly required in most cases.
> Don't use devm_regulator_bulk_get_enable() in sensor drivers, implement
> power enable/disable functions that do the right thing. That's the code
> pattern I want to see.
Perhaps I wasnt clear in my explanation. If you look at the patch below, you'll
see that we are not changing any sequencing behavior.
I am not suggesting we use this API everywhere, only where it's appropriate and
doesn't compromise sequencing requirements.
Best Regards,
Tarang
------
diff --git a/drivers/media/i2c/imx283.c b/drivers/media/i2c/imx283.c
index da618c8cbadc..4dbf7215cef4 100644
--- a/drivers/media/i2c/imx283.c
+++ b/drivers/media/i2c/imx283.c
@@ -1176,8 +1176,8 @@ static int imx283_power_on(struct device *dev)
struct imx283 *imx283 = to_imx283(sd);
int ret;
- ret = regulator_bulk_enable(ARRAY_SIZE(imx283_supply_name),
- imx283->supplies);
+ ret = devm_regulator_bulk_get_enable(dev, ARRAY_SIZE(imx283_supply_name),
+ imx283_supply_name);
if (ret) {
dev_err(imx283->dev, "failed to enable regulators\n");
return ret;
@@ -1186,7 +1186,7 @@ static int imx283_power_on(struct device *dev)
ret = clk_prepare_enable(imx283->xclk);
if (ret) {
dev_err(imx283->dev, "failed to enable clock\n");
- goto reg_off;
+ return ret;
}
gpiod_set_value_cansleep(imx283->reset_gpio, 0);
@@ -1195,10 +1195,6 @@ static int imx283_power_on(struct device *dev)
IMX283_XCLR_MIN_DELAY_US + IMX283_XCLR_DELAY_RANGE_US);
return 0;
-
-reg_off:
- regulator_bulk_disable(ARRAY_SIZE(imx283_supply_name), imx283->supplies);
- return ret;
}
static int imx283_power_off(struct device *dev)
@@ -1207,24 +1203,11 @@ static int imx283_power_off(struct device *dev)
struct imx283 *imx283 = to_imx283(sd);
gpiod_set_value_cansleep(imx283->reset_gpio, 1);
- regulator_bulk_disable(ARRAY_SIZE(imx283_supply_name), imx283->supplies);
clk_disable_unprepare(imx283->xclk);
return 0;
}
-static int imx283_get_regulators(struct imx283 *imx283)
-{
- unsigned int i;
-
- for (i = 0; i < ARRAY_SIZE(imx283_supply_name); i++)
- imx283->supplies[i].supply = imx283_supply_name[i];
-
- return devm_regulator_bulk_get(imx283->dev,
- ARRAY_SIZE(imx283_supply_name),
- imx283->supplies);
-}
-
/* Verify chip ID */
static int imx283_identify_module(struct imx283 *imx283)
{
@@ -1480,12 +1463,6 @@ static int imx283_probe(struct i2c_client *client)
return -EINVAL;
}
- ret = imx283_get_regulators(imx283);
- if (ret) {
- return dev_err_probe(imx283->dev, ret,
- "failed to get regulators\n");
- }
-
ret = imx283_parse_endpoint(imx283);
if (ret) {
dev_err(imx283->dev, "failed to parse endpoint configuration\n");
^ permalink raw reply related [flat|nested] 115+ messages in thread
* Re: [PATCH 00/72] media: i2c: Reduce cargo-cult
2025-07-25 10:35 ` Tarang Raval
@ 2025-07-25 11:00 ` Laurent Pinchart
2025-07-25 11:31 ` Tarang Raval
0 siblings, 1 reply; 115+ messages in thread
From: Laurent Pinchart @ 2025-07-25 11:00 UTC (permalink / raw)
To: Tarang Raval
Cc: linux-media@vger.kernel.org, Sakari Ailus, Mehdi Djait,
Alim Akhtar, André Apitzsch, Andrzej Hajda, Arec Kao,
Benjamin Mugnier, Bingbu Cao, Bjorn Andersson,
Bryan O'Donoghue, Bryan O'Donoghue, Conor Dooley,
Daniel Scally, Dongcheng Yan, Fabio Estevam, Geert Uytterhoeven,
Hans de Goede, Hans Verkuil, Hao Yao, Heimir Thor Sverrisson,
Jacopo Mondi, Jimmy Su, Jingjing Xiong, Jonas Karlman,
Konrad Dybcio, Krzysztof Kozlowski, Lad Prabhakar, Leon Luo,
Liam Girdwood, Magnus Damm, Manivannan Sadhasivam, Mark Brown,
Matthew Majewski, Matthias Fend, Mikhail Rudenko,
Nicolas Dufresne, Niklas Söderlund, Pavel Machek,
Pengutronix Kernel Team, Ricardo Ribalda, Rob Herring,
Sascha Hauer, Shawn Guo, Shunqian Zheng, Sylvain Petinot,
Sylwester Nawrocki, Tianshu Qiu, Todor Tomov, Tomi Valkeinen,
Tony Lindgren, Zhi Mao, devicetree@vger.kernel.org,
imx@lists.linux.dev, linux-arm-kernel@lists.infradead.org,
linux-arm-msm@vger.kernel.org, linux-omap@vger.kernel.org,
linux-renesas-soc@vger.kernel.org,
linux-samsung-soc@vger.kernel.org
On Fri, Jul 25, 2025 at 10:35:28AM +0000, Tarang Raval wrote:
> > On Fri, Jul 25, 2025 at 07:00:40AM +0000, Tarang Raval wrote:
> > > > On Thu, Jul 24, 2025 at 02:20:10PM +0000, Tarang Raval wrote:
> > > > > > > > > 2. In the regulator code, you can reduce boilerplate by using
> > > > > > > > > devm_regulator_bulk_get_enable().
> > > > > > > >
> > > > > > > > devm_regulator_bulk_get_enable() doesn't seem to be a good idea. You
> > > > > > > > generally don't want to enable power everywhere unconditionally, and
> > > > > > > > sensors very often need a guaranteed power up sequence.
> > >
> > > -----(1)
> > >
> > > > > > >
> > > > > > > The regulators are optional, we supply power to the camera sensor directly
> > > > > > > through dedicated power rails and there is no strict enable sequence
> > > > > > > required in this case.
> > > > > >
> > > > > > What exactly do you mean by "this case" ? Are you talking about one
> > > > > > particular sensor ? One particular camera module ?
> > > > >
> > > > > Laurent, by “this case” I meant the common scenario where power to the
> > > > > camera sensor is supplied by a PMIC regulator that is always-on. In such
> > > > > setups, the regulator is fixed and cannot be enabled or disabled from the
> > > > > driver, the sensor is always powered.
> > > > >
> > > > > This is what I’ve seen in most platforms, where the CSI input connector
> > > > > provides fixed 3.3V/1.8V power rails directly to the camera module.
> > > > >
> > > > > Of course, if the camera supply comes from a dedicated regulator controlled
> > > > > via a GPIO, then the driver would need to handle enable/disable sequencing
> > > > > explicitly. But I’m specifically referring to the first case, where the power rails
> > > > > are always-on.
> > > >
> > > > How does the sensor driver know which of those two cases it is dealing
> > > > with ?
> > >
> > > The sensor driver typically determines this via the presence (or absence)
> > > of regulator supply entries in the Device Tree. If a supply is not defined,
> > > it's assumed to be always-on (e.g., provided by the board via fixed rails).
> >
> > Do we have sensor drivers that check the presense of supply properties ?
> > Drivers generally shouldn't.
> >
> > > When defined, the driver retrieves and manages the regulator. This approach
> > > allows a single driver to support both cases, by treating supplies as optional
> > > and only enabling them when explicitly defined.
> >
> > I don't see what you're trying to do here. A sensor always needs
> > supplies, regardless of whether or not they're always on. Drivers should
> > get the supplies with regulator_get() (or possibly the bulk API), and
> > then implement the power enable/disable sequences that the sensor
> > requires. If all suplies are manually controllable, this will produce
> > the correct sequence. If the supplies are always on, it will be a no-op.
> > That's a single implementation in the driver, you don't need to care
> > about the nature of the supplies, or their presence in DT.
> >
> > > At comment (1): you gave two reasons why we cannot use devm_regulator_bulk_get_enable.
> > >
> > > What I’m trying to say is:
> > >
> > > You mentioned "generally don't want to enable power everywhere unconditionally,"
> > > but on almost every platform, the power rails are always-on.
> >
> > "almost every platform" doesn't sound right to me. It does happen though.
> >
> > > And regarding the second point — "sensors very often need a guaranteed power-up sequence"
> > > I don’t understand why this would be an issue. Even if we use devm_regulator_bulk_get_enable,
> > > the power-up sequence remains the same. So how is it not a good option in this case?
> >
> > Because the bulk API enables all regulators in parallel, it doesn't
> > guarantee sequencing.
>
> Except for a few drivers, almost all camera drivers use the bulk API, which suggests
> that a guaranteed power-up sequence may not be strictly required in most cases.
>
> > Don't use devm_regulator_bulk_get_enable() in sensor drivers, implement
> > power enable/disable functions that do the right thing. That's the code
> > pattern I want to see.
>
> Perhaps I wasnt clear in my explanation. If you look at the patch below, you'll
> see that we are not changing any sequencing behavior.
You end up getting regulators every time power is enabled, and you don't
turn the supplies off at power off time. How is that even supposed to
work ? It completely breaks power management.
> I am not suggesting we use this API everywhere, only where it's appropriate and
> doesn't compromise sequencing requirements.
>
> Best Regards,
> Tarang
>
> ------
>
> diff --git a/drivers/media/i2c/imx283.c b/drivers/media/i2c/imx283.c
> index da618c8cbadc..4dbf7215cef4 100644
> --- a/drivers/media/i2c/imx283.c
> +++ b/drivers/media/i2c/imx283.c
> @@ -1176,8 +1176,8 @@ static int imx283_power_on(struct device *dev)
> struct imx283 *imx283 = to_imx283(sd);
> int ret;
>
> - ret = regulator_bulk_enable(ARRAY_SIZE(imx283_supply_name),
> - imx283->supplies);
> + ret = devm_regulator_bulk_get_enable(dev, ARRAY_SIZE(imx283_supply_name),
> + imx283_supply_name);
> if (ret) {
> dev_err(imx283->dev, "failed to enable regulators\n");
> return ret;
> @@ -1186,7 +1186,7 @@ static int imx283_power_on(struct device *dev)
> ret = clk_prepare_enable(imx283->xclk);
> if (ret) {
> dev_err(imx283->dev, "failed to enable clock\n");
> - goto reg_off;
> + return ret;
> }
>
> gpiod_set_value_cansleep(imx283->reset_gpio, 0);
> @@ -1195,10 +1195,6 @@ static int imx283_power_on(struct device *dev)
> IMX283_XCLR_MIN_DELAY_US + IMX283_XCLR_DELAY_RANGE_US);
>
> return 0;
> -
> -reg_off:
> - regulator_bulk_disable(ARRAY_SIZE(imx283_supply_name), imx283->supplies);
> - return ret;
> }
>
> static int imx283_power_off(struct device *dev)
> @@ -1207,24 +1203,11 @@ static int imx283_power_off(struct device *dev)
> struct imx283 *imx283 = to_imx283(sd);
>
> gpiod_set_value_cansleep(imx283->reset_gpio, 1);
> - regulator_bulk_disable(ARRAY_SIZE(imx283_supply_name), imx283->supplies);
> clk_disable_unprepare(imx283->xclk);
>
> return 0;
> }
>
> -static int imx283_get_regulators(struct imx283 *imx283)
> -{
> - unsigned int i;
> -
> - for (i = 0; i < ARRAY_SIZE(imx283_supply_name); i++)
> - imx283->supplies[i].supply = imx283_supply_name[i];
> -
> - return devm_regulator_bulk_get(imx283->dev,
> - ARRAY_SIZE(imx283_supply_name),
> - imx283->supplies);
> -}
> -
> /* Verify chip ID */
> static int imx283_identify_module(struct imx283 *imx283)
> {
> @@ -1480,12 +1463,6 @@ static int imx283_probe(struct i2c_client *client)
> return -EINVAL;
> }
>
> - ret = imx283_get_regulators(imx283);
> - if (ret) {
> - return dev_err_probe(imx283->dev, ret,
> - "failed to get regulators\n");
> - }
> -
> ret = imx283_parse_endpoint(imx283);
> if (ret) {
> dev_err(imx283->dev, "failed to parse endpoint configuration\n");
--
Regards,
Laurent Pinchart
^ permalink raw reply [flat|nested] 115+ messages in thread
* Re: [PATCH 00/72] media: i2c: Reduce cargo-cult
2025-07-25 11:00 ` Laurent Pinchart
@ 2025-07-25 11:31 ` Tarang Raval
0 siblings, 0 replies; 115+ messages in thread
From: Tarang Raval @ 2025-07-25 11:31 UTC (permalink / raw)
To: Laurent Pinchart
Cc: linux-media@vger.kernel.org, Sakari Ailus, Mehdi Djait,
Alim Akhtar, André Apitzsch, Andrzej Hajda, Arec Kao,
Benjamin Mugnier, Bingbu Cao, Bjorn Andersson,
Bryan O'Donoghue, Bryan O'Donoghue, Conor Dooley,
Daniel Scally, Dongcheng Yan, Fabio Estevam, Geert Uytterhoeven,
Hans de Goede, Hans Verkuil, Hao Yao, Heimir Thor Sverrisson,
Jacopo Mondi, Jimmy Su, Jingjing Xiong, Jonas Karlman,
Konrad Dybcio, Krzysztof Kozlowski, Lad Prabhakar, Leon Luo,
Liam Girdwood, Magnus Damm, Manivannan Sadhasivam, Mark Brown,
Matthew Majewski, Matthias Fend, Mikhail Rudenko,
Nicolas Dufresne, Niklas Söderlund, Pavel Machek,
Pengutronix Kernel Team, Ricardo Ribalda, Rob Herring,
Sascha Hauer, Shawn Guo, Shunqian Zheng, Sylvain Petinot,
Sylwester Nawrocki, Tianshu Qiu, Todor Tomov, Tomi Valkeinen,
Tony Lindgren, Zhi Mao, devicetree@vger.kernel.org,
imx@lists.linux.dev, linux-arm-kernel@lists.infradead.org,
linux-arm-msm@vger.kernel.org, linux-omap@vger.kernel.org,
linux-renesas-soc@vger.kernel.org,
linux-samsung-soc@vger.kernel.org
> On Fri, Jul 25, 2025 at 10:35:28AM +0000, Tarang Raval wrote:
> > > On Fri, Jul 25, 2025 at 07:00:40AM +0000, Tarang Raval wrote:
> > > > > On Thu, Jul 24, 2025 at 02:20:10PM +0000, Tarang Raval wrote:
> > > > > > > > > > 2. In the regulator code, you can reduce boilerplate by using
> > > > > > > > > > devm_regulator_bulk_get_enable().
> > > > > > > > >
> > > > > > > > > devm_regulator_bulk_get_enable() doesn't seem to be a good idea. You
> > > > > > > > > generally don't want to enable power everywhere unconditionally, and
> > > > > > > > > sensors very often need a guaranteed power up sequence.
> > > >
> > > > -----(1)
> > > >
> > > > > > > >
> > > > > > > > The regulators are optional, we supply power to the camera sensor directly
> > > > > > > > through dedicated power rails and there is no strict enable sequence
> > > > > > > > required in this case.
> > > > > > >
> > > > > > > What exactly do you mean by "this case" ? Are you talking about one
> > > > > > > particular sensor ? One particular camera module ?
> > > > > >
> > > > > > Laurent, by “this case” I meant the common scenario where power to the
> > > > > > camera sensor is supplied by a PMIC regulator that is always-on. In such
> > > > > > setups, the regulator is fixed and cannot be enabled or disabled from the
> > > > > > driver, the sensor is always powered.
> > > > > >
> > > > > > This is what I’ve seen in most platforms, where the CSI input connector
> > > > > > provides fixed 3.3V/1.8V power rails directly to the camera module.
> > > > > >
> > > > > > Of course, if the camera supply comes from a dedicated regulator controlled
> > > > > > via a GPIO, then the driver would need to handle enable/disable sequencing
> > > > > > explicitly. But I’m specifically referring to the first case, where the power rails
> > > > > > are always-on.
> > > > >
> > > > > How does the sensor driver know which of those two cases it is dealing
> > > > > with ?
> > > >
> > > > The sensor driver typically determines this via the presence (or absence)
> > > > of regulator supply entries in the Device Tree. If a supply is not defined,
> > > > it's assumed to be always-on (e.g., provided by the board via fixed rails).
> > >
> > > Do we have sensor drivers that check the presense of supply properties ?
> > > Drivers generally shouldn't.
> > >
> > > > When defined, the driver retrieves and manages the regulator. This approach
> > > > allows a single driver to support both cases, by treating supplies as optional
> > > > and only enabling them when explicitly defined.
> > >
> > > I don't see what you're trying to do here. A sensor always needs
> > > supplies, regardless of whether or not they're always on. Drivers should
> > > get the supplies with regulator_get() (or possibly the bulk API), and
> > > then implement the power enable/disable sequences that the sensor
> > > requires. If all suplies are manually controllable, this will produce
> > > the correct sequence. If the supplies are always on, it will be a no-op.
> > > That's a single implementation in the driver, you don't need to care
> > > about the nature of the supplies, or their presence in DT.
> > >
> > > > At comment (1): you gave two reasons why we cannot use devm_regulator_bulk_get_enable.
> > > >
> > > > What I’m trying to say is:
> > > >
> > > > You mentioned "generally don't want to enable power everywhere unconditionally,"
> > > > but on almost every platform, the power rails are always-on.
> > >
> > > "almost every platform" doesn't sound right to me. It does happen though.
> > >
> > > > And regarding the second point — "sensors very often need a guaranteed power-up sequence"
> > > > I don’t understand why this would be an issue. Even if we use devm_regulator_bulk_get_enable,
> > > > the power-up sequence remains the same. So how is it not a good option in this case?
> > >
> > > Because the bulk API enables all regulators in parallel, it doesn't
> > > guarantee sequencing.
> >
> > Except for a few drivers, almost all camera drivers use the bulk API, which suggests
> > that a guaranteed power-up sequence may not be strictly required in most cases.
> >
> > > Don't use devm_regulator_bulk_get_enable() in sensor drivers, implement
> > > power enable/disable functions that do the right thing. That's the code
> > > pattern I want to see.
> >
> > Perhaps I wasnt clear in my explanation. If you look at the patch below, you'll
> > see that we are not changing any sequencing behavior.
>
> You end up getting regulators every time power is enabled, and you don't
> turn the supplies off at power off time. How is that even supposed to
> work ? It completely breaks power management.
Got it. The regulators stay enabled until the device is unbound.
If the power rails are always on, there’s effectively nothing to disable.
Why would that break power management?
This is a little bit confusing.
However, I now agree that we should not use it.
Best Regards,
Tarang
^ permalink raw reply [flat|nested] 115+ messages in thread
* Re: [PATCH 00/72] media: i2c: Reduce cargo-cult
2025-07-25 7:00 ` Tarang Raval
2025-07-25 9:38 ` Laurent Pinchart
@ 2025-07-25 12:35 ` Mark Brown
2025-07-26 6:17 ` Tarang Raval
1 sibling, 1 reply; 115+ messages in thread
From: Mark Brown @ 2025-07-25 12:35 UTC (permalink / raw)
To: Tarang Raval
Cc: Laurent Pinchart, linux-media@vger.kernel.org, Sakari Ailus,
Mehdi Djait, Alim Akhtar, André Apitzsch, Andrzej Hajda,
Arec Kao, Benjamin Mugnier, Bingbu Cao, Bjorn Andersson,
Bryan O'Donoghue, Bryan O'Donoghue, Conor Dooley,
Daniel Scally, Dongcheng Yan, Fabio Estevam, Geert Uytterhoeven,
Hans de Goede, Hans Verkuil, Hao Yao, Heimir Thor Sverrisson,
Jacopo Mondi, Jimmy Su, Jingjing Xiong, Jonas Karlman,
Konrad Dybcio, Krzysztof Kozlowski, Lad Prabhakar, Leon Luo,
Liam Girdwood, Magnus Damm, Manivannan Sadhasivam,
Matthew Majewski, Matthias Fend, Mikhail Rudenko,
Nicolas Dufresne, Niklas Söderlund, Pavel Machek,
Pengutronix Kernel Team, Ricardo Ribalda, Rob Herring,
Sascha Hauer, Shawn Guo, Shunqian Zheng, Sylvain Petinot,
Sylwester Nawrocki, Tianshu Qiu, Todor Tomov, Tomi Valkeinen,
Tony Lindgren, Zhi Mao, devicetree@vger.kernel.org,
imx@lists.linux.dev, linux-arm-kernel@lists.infradead.org,
linux-arm-msm@vger.kernel.org, linux-omap@vger.kernel.org,
linux-renesas-soc@vger.kernel.org,
linux-samsung-soc@vger.kernel.org
[-- Attachment #1: Type: text/plain, Size: 404 bytes --]
On Fri, Jul 25, 2025 at 07:00:40AM +0000, Tarang Raval wrote:
> The sensor driver typically determines this via the presence (or absence)
> of regulator supply entries in the Device Tree. If a supply is not defined,
> it's assumed to be always-on (e.g., provided by the board via fixed rails).
No, this is broken. The driver should unconditionally request whatever
supplies the device needs.
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]
^ permalink raw reply [flat|nested] 115+ messages in thread
* Re: [PATCH 00/72] media: i2c: Reduce cargo-cult
2025-07-25 12:35 ` Mark Brown
@ 2025-07-26 6:17 ` Tarang Raval
0 siblings, 0 replies; 115+ messages in thread
From: Tarang Raval @ 2025-07-26 6:17 UTC (permalink / raw)
To: Mark Brown
Cc: Laurent Pinchart, linux-media@vger.kernel.org, Sakari Ailus,
Mehdi Djait, Alim Akhtar, André Apitzsch, Andrzej Hajda,
Arec Kao, Benjamin Mugnier, Bingbu Cao, Bjorn Andersson,
Bryan O'Donoghue, Bryan O'Donoghue, Conor Dooley,
Daniel Scally, Dongcheng Yan, Fabio Estevam, Geert Uytterhoeven,
Hans de Goede, Hans Verkuil, Hao Yao, Heimir Thor Sverrisson,
Jacopo Mondi, Jimmy Su, Jingjing Xiong, Jonas Karlman,
Konrad Dybcio, Krzysztof Kozlowski, Lad Prabhakar, Leon Luo,
Liam Girdwood, Magnus Damm, Manivannan Sadhasivam,
Matthew Majewski, Matthias Fend, Mikhail Rudenko,
Nicolas Dufresne, Niklas Söderlund, Pavel Machek,
Pengutronix Kernel Team, Ricardo Ribalda, Rob Herring,
Sascha Hauer, Shawn Guo, Shunqian Zheng, Sylvain Petinot,
Sylwester Nawrocki, Tianshu Qiu, Todor Tomov, Tomi Valkeinen,
Tony Lindgren, Zhi Mao, devicetree@vger.kernel.org,
imx@lists.linux.dev, linux-arm-kernel@lists.infradead.org,
linux-arm-msm@vger.kernel.org, linux-omap@vger.kernel.org,
linux-renesas-soc@vger.kernel.org,
linux-samsung-soc@vger.kernel.org
> > The sensor driver typically determines this via the presence (or absence)
> > of regulator supply entries in the Device Tree. If a supply is not defined,
> > it's assumed to be always-on (e.g., provided by the board via fixed rails).
>
> No, this is broken. The driver should unconditionally request whatever
> supplies the device needs.
Yes, that’s clear from Laurent’s explanation:
"A sensor always needs
supplies, regardless of whether or not they're always on. Drivers should
get the supplies with regulator_get() (or possibly the bulk API)"
Thanks, Mark, for the clarification.
Best Regards,
Tarang
^ permalink raw reply [flat|nested] 115+ messages in thread
* Re: [PATCH 13/72] arm64: dts: renesas: aistarvision-mipi-adapter-2.1: Drop clock-frequency from camera sensor node
2025-07-10 17:47 ` [PATCH 13/72] arm64: dts: renesas: aistarvision-mipi-adapter-2.1: Drop clock-frequency from " Laurent Pinchart
@ 2025-07-28 14:19 ` Geert Uytterhoeven
2025-07-28 15:08 ` Laurent Pinchart
0 siblings, 1 reply; 115+ messages in thread
From: Geert Uytterhoeven @ 2025-07-28 14:19 UTC (permalink / raw)
To: Laurent Pinchart
Cc: linux-media, Sakari Ailus, Mehdi Djait, Geert Uytterhoeven,
Magnus Damm, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
linux-renesas-soc, devicetree
Hi Laurent,
On Thu, 10 Jul 2025 at 19:49, Laurent Pinchart
<laurent.pinchart@ideasonboard.com> wrote:
> The clock-frequency for camera sensors has been deprecated in favour of
> the assigned-clocks and assigned-clock-rates properties. As the clock
> source for the sensor is a fixed-frequency oscillator, simply drop the
> clock-frequency.
>
> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Thanks for your patch!
Reviewed-by: Geert Uytterhoeven <geert+renesas@glider.be>
Doesn't this patch have a hard dependency on "[PATCH 66/72] media:
i2c: ov5645: Use V4L2 legacy sensor clock helper", and thus shouldn't
this patch be moved after the latter in this series?
Gr{oetje,eeting}s,
Geert
--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org
In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
-- Linus Torvalds
^ permalink raw reply [flat|nested] 115+ messages in thread
* Re: [PATCH 14/72] arm64: dts: renesas: rzg2l-smarc: Drop clock-frequency from camera sensor node
2025-07-10 17:47 ` [PATCH 14/72] arm64: dts: renesas: rzg2l-smarc: " Laurent Pinchart
@ 2025-07-28 14:20 ` Geert Uytterhoeven
0 siblings, 0 replies; 115+ messages in thread
From: Geert Uytterhoeven @ 2025-07-28 14:20 UTC (permalink / raw)
To: Laurent Pinchart
Cc: linux-media, Sakari Ailus, Mehdi Djait, Magnus Damm, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, linux-renesas-soc, devicetree
Hi Laurent,
On Thu, 10 Jul 2025 at 19:49, Laurent Pinchart
<laurent.pinchart@ideasonboard.com> wrote:
> The clock-frequency for camera sensors has been deprecated in favour of
> the assigned-clocks and assigned-clock-rates properties. As the clock
> source for the sensor is a fixed-frequency oscillator, simply drop the
> clock-frequency.
>
> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Thanks for your patch!
Reviewed-by: Geert Uytterhoeven <geert+renesas@glider.be>
Doesn't this patch have a hard dependency on "[PATCH 66/72] media:
i2c: ov5645: Use V4L2 legacy sensor clock helper", and thus shouldn't
this patch be moved after the latter in this series?
Gr{oetje,eeting}s,
Geert
--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org
In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
-- Linus Torvalds
^ permalink raw reply [flat|nested] 115+ messages in thread
* Re: [PATCH 13/72] arm64: dts: renesas: aistarvision-mipi-adapter-2.1: Drop clock-frequency from camera sensor node
2025-07-28 14:19 ` Geert Uytterhoeven
@ 2025-07-28 15:08 ` Laurent Pinchart
0 siblings, 0 replies; 115+ messages in thread
From: Laurent Pinchart @ 2025-07-28 15:08 UTC (permalink / raw)
To: Geert Uytterhoeven
Cc: linux-media, Sakari Ailus, Mehdi Djait, Geert Uytterhoeven,
Magnus Damm, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
linux-renesas-soc, devicetree
On Mon, Jul 28, 2025 at 04:19:49PM +0200, Geert Uytterhoeven wrote:
> On Thu, 10 Jul 2025 at 19:49, Laurent Pinchart wrote:
> > The clock-frequency for camera sensors has been deprecated in favour of
> > the assigned-clocks and assigned-clock-rates properties. As the clock
> > source for the sensor is a fixed-frequency oscillator, simply drop the
> > clock-frequency.
> >
> > Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
>
> Thanks for your patch!
>
> Reviewed-by: Geert Uytterhoeven <geert+renesas@glider.be>
>
> Doesn't this patch have a hard dependency on "[PATCH 66/72] media:
> i2c: ov5645: Use V4L2 legacy sensor clock helper", and thus shouldn't
> this patch be moved after the latter in this series?
Apparently it does. I'll move the DT changes to the end of the series.
--
Regards,
Laurent Pinchart
^ permalink raw reply [flat|nested] 115+ messages in thread
* Re: (subset) [PATCH 00/72] media: i2c: Reduce cargo-cult
2025-07-10 17:46 [PATCH 00/72] media: i2c: Reduce cargo-cult Laurent Pinchart
` (72 preceding siblings ...)
2025-07-24 11:42 ` [PATCH 00/72] media: i2c: Reduce cargo-cult Tarang Raval
@ 2025-08-11 23:27 ` Bjorn Andersson
2025-08-12 8:51 ` Laurent Pinchart
73 siblings, 1 reply; 115+ messages in thread
From: Bjorn Andersson @ 2025-08-11 23:27 UTC (permalink / raw)
To: linux-media, Laurent Pinchart
Cc: Sakari Ailus, Mehdi Djait, Alim Akhtar, André Apitzsch,
Andrzej Hajda, Arec Kao, Benjamin Mugnier, Bingbu Cao,
Bryan O'Donoghue, Bryan O'Donoghue, Conor Dooley,
Daniel Scally, Dongcheng Yan, Dongchun Zhu, Fabio Estevam,
Geert Uytterhoeven, Hans de Goede, Hans Verkuil, Hao Yao,
Heimir Thor Sverrisson, Jacopo Mondi, Jason Chen, Jimmy Su,
Jingjing Xiong, Jonas Karlman, Konrad Dybcio, Krzysztof Kozlowski,
Lad Prabhakar, Leon Luo, Liam Girdwood, Magnus Damm,
Manivannan Sadhasivam, Mark Brown, Matthew Majewski,
Matthias Fend, Mikhail Rudenko, Nicolas Dufresne,
Niklas Söderlund, Pavel Machek, Pengutronix Kernel Team,
Ricardo Ribalda, Rob Herring, Sascha Hauer, Shawn Guo,
Shunqian Zheng, Sylvain Petinot, Sylwester Nawrocki, Tarang Raval,
Tianshu Qiu, Todor Tomov, Tomi Valkeinen, Tony Lindgren, Zhi Mao,
devicetree, imx, linux-arm-kernel, linux-arm-msm, linux-omap,
linux-renesas-soc, linux-samsung-soc
On Thu, 10 Jul 2025 20:46:56 +0300, Laurent Pinchart wrote:
> This patch series build on top of Mehdi's introduction of the
> devm_v4l2_sensor_clk_get() helper (see [1]) to drastically reduce
> cargo-cult in camera sensor drivers.
>
> A large number of camera sensor drivers directly use the
> "clock-frequency" property to retrieve the effective or desired external
> clock rate. This is standard behaviour on ACPI platforms that don't
> implement MIPI DisCo for Imaging, but usage of the property has leaked
> to OF-based platforms, due to a combination of historical reasons (using
> "clock-frequency" was initially considered right until before the
> introduction of "assigned-clock-rates") and plain cargo-cult.
>
> [...]
Applied, thanks!
[12/72] arm64: dts: qcom: sdm845-db845c-navigation-mezzanine: Replace clock-frequency in camera sensor node
commit: 5433560caa5e7e677a8d4310bbec08312be765b4
Best regards,
--
Bjorn Andersson <andersson@kernel.org>
^ permalink raw reply [flat|nested] 115+ messages in thread
* Re: (subset) [PATCH 00/72] media: i2c: Reduce cargo-cult
2025-08-11 23:27 ` (subset) " Bjorn Andersson
@ 2025-08-12 8:51 ` Laurent Pinchart
2025-08-12 8:58 ` Krzysztof Kozlowski
0 siblings, 1 reply; 115+ messages in thread
From: Laurent Pinchart @ 2025-08-12 8:51 UTC (permalink / raw)
To: Bjorn Andersson
Cc: linux-media, Sakari Ailus, Mehdi Djait, Alim Akhtar,
André Apitzsch, Andrzej Hajda, Arec Kao, Benjamin Mugnier,
Bingbu Cao, Bryan O'Donoghue, Bryan O'Donoghue,
Conor Dooley, Daniel Scally, Dongcheng Yan, Dongchun Zhu,
Fabio Estevam, Geert Uytterhoeven, Hans de Goede, Hans Verkuil,
Hao Yao, Heimir Thor Sverrisson, Jacopo Mondi, Jason Chen,
Jimmy Su, Jingjing Xiong, Jonas Karlman, Konrad Dybcio,
Krzysztof Kozlowski, Lad Prabhakar, Leon Luo, Liam Girdwood,
Magnus Damm, Manivannan Sadhasivam, Mark Brown, Matthew Majewski,
Matthias Fend, Mikhail Rudenko, Nicolas Dufresne,
Niklas Söderlund, Pavel Machek, Pengutronix Kernel Team,
Ricardo Ribalda, Rob Herring, Sascha Hauer, Shawn Guo,
Shunqian Zheng, Sylvain Petinot, Sylwester Nawrocki, Tarang Raval,
Tianshu Qiu, Todor Tomov, Tomi Valkeinen, Tony Lindgren, Zhi Mao,
devicetree, imx, linux-arm-kernel, linux-arm-msm, linux-omap,
linux-renesas-soc, linux-samsung-soc
Hi Bjorn,
On Mon, Aug 11, 2025 at 06:27:01PM -0500, Bjorn Andersson wrote:
> On Thu, 10 Jul 2025 20:46:56 +0300, Laurent Pinchart wrote:
> > This patch series build on top of Mehdi's introduction of the
> > devm_v4l2_sensor_clk_get() helper (see [1]) to drastically reduce
> > cargo-cult in camera sensor drivers.
> >
> > A large number of camera sensor drivers directly use the
> > "clock-frequency" property to retrieve the effective or desired external
> > clock rate. This is standard behaviour on ACPI platforms that don't
> > implement MIPI DisCo for Imaging, but usage of the property has leaked
> > to OF-based platforms, due to a combination of historical reasons (using
> > "clock-frequency" was initially considered right until before the
> > introduction of "assigned-clock-rates") and plain cargo-cult.
> >
> > [...]
>
> Applied, thanks!
>
> [12/72] arm64: dts: qcom: sdm845-db845c-navigation-mezzanine: Replace clock-frequency in camera sensor node
> commit: 5433560caa5e7e677a8d4310bbec08312be765b4
I'm afraid that's too soon. This will introduce a breakage without a
corresponding change to the camera sensor driver.
I will post a v2 with the patches reordered. We could merge the V4L2
side in a rc1-based stable branch and merge than in the arm-soc tree as
well, but I think we can also delay the .dts changes to the next kernel
version. Do you have a preference ?
--
Regards,
Laurent Pinchart
^ permalink raw reply [flat|nested] 115+ messages in thread
* Re: (subset) [PATCH 00/72] media: i2c: Reduce cargo-cult
2025-08-12 8:51 ` Laurent Pinchart
@ 2025-08-12 8:58 ` Krzysztof Kozlowski
2025-08-12 9:39 ` Laurent Pinchart
0 siblings, 1 reply; 115+ messages in thread
From: Krzysztof Kozlowski @ 2025-08-12 8:58 UTC (permalink / raw)
To: Laurent Pinchart, Bjorn Andersson
Cc: linux-media, Sakari Ailus, Mehdi Djait, Alim Akhtar,
André Apitzsch, Andrzej Hajda, Arec Kao, Benjamin Mugnier,
Bingbu Cao, Bryan O'Donoghue, Bryan O'Donoghue,
Conor Dooley, Daniel Scally, Dongcheng Yan, Dongchun Zhu,
Fabio Estevam, Geert Uytterhoeven, Hans de Goede, Hans Verkuil,
Hao Yao, Heimir Thor Sverrisson, Jacopo Mondi, Jason Chen,
Jimmy Su, Jingjing Xiong, Jonas Karlman, Konrad Dybcio,
Krzysztof Kozlowski, Lad Prabhakar, Leon Luo, Liam Girdwood,
Magnus Damm, Manivannan Sadhasivam, Mark Brown, Matthew Majewski,
Matthias Fend, Mikhail Rudenko, Nicolas Dufresne,
Niklas Söderlund, Pavel Machek, Pengutronix Kernel Team,
Ricardo Ribalda, Rob Herring, Sascha Hauer, Shawn Guo,
Shunqian Zheng, Sylvain Petinot, Sylwester Nawrocki, Tarang Raval,
Tianshu Qiu, Todor Tomov, Tomi Valkeinen, Tony Lindgren, Zhi Mao,
devicetree, imx, linux-arm-kernel, linux-arm-msm, linux-omap,
linux-renesas-soc, linux-samsung-soc
On 12/08/2025 10:51, Laurent Pinchart wrote:
> Hi Bjorn,
>
> On Mon, Aug 11, 2025 at 06:27:01PM -0500, Bjorn Andersson wrote:
>> On Thu, 10 Jul 2025 20:46:56 +0300, Laurent Pinchart wrote:
>>> This patch series build on top of Mehdi's introduction of the
>>> devm_v4l2_sensor_clk_get() helper (see [1]) to drastically reduce
>>> cargo-cult in camera sensor drivers.
>>>
>>> A large number of camera sensor drivers directly use the
>>> "clock-frequency" property to retrieve the effective or desired external
>>> clock rate. This is standard behaviour on ACPI platforms that don't
>>> implement MIPI DisCo for Imaging, but usage of the property has leaked
>>> to OF-based platforms, due to a combination of historical reasons (using
>>> "clock-frequency" was initially considered right until before the
>>> introduction of "assigned-clock-rates") and plain cargo-cult.
>>>
>>> [...]
>>
>> Applied, thanks!
>>
>> [12/72] arm64: dts: qcom: sdm845-db845c-navigation-mezzanine: Replace clock-frequency in camera sensor node
>> commit: 5433560caa5e7e677a8d4310bbec08312be765b4
>
> I'm afraid that's too soon. This will introduce a breakage without a
> corresponding change to the camera sensor driver.
>
> I will post a v2 with the patches reordered. We could merge the V4L2
> side in a rc1-based stable branch and merge than in the arm-soc tree as
You cannot ("cannot" as not following the process) merge drivers into
DTS branch.
> well, but I think we can also delay the .dts changes to the next kernel
All users of DTS will be anyway affected and commit msg should address that.
> version. Do you have a preference ?
Best regards,
Krzysztof
^ permalink raw reply [flat|nested] 115+ messages in thread
* Re: (subset) [PATCH 00/72] media: i2c: Reduce cargo-cult
2025-08-12 8:58 ` Krzysztof Kozlowski
@ 2025-08-12 9:39 ` Laurent Pinchart
2025-08-12 10:28 ` Krzysztof Kozlowski
0 siblings, 1 reply; 115+ messages in thread
From: Laurent Pinchart @ 2025-08-12 9:39 UTC (permalink / raw)
To: Krzysztof Kozlowski
Cc: Bjorn Andersson, linux-media, Sakari Ailus, Mehdi Djait,
Alim Akhtar, André Apitzsch, Andrzej Hajda, Arec Kao,
Benjamin Mugnier, Bingbu Cao, Bryan O'Donoghue,
Bryan O'Donoghue, Conor Dooley, Daniel Scally, Dongcheng Yan,
Dongchun Zhu, Fabio Estevam, Geert Uytterhoeven, Hans de Goede,
Hans Verkuil, Hao Yao, Heimir Thor Sverrisson, Jacopo Mondi,
Jason Chen, Jimmy Su, Jingjing Xiong, Jonas Karlman,
Konrad Dybcio, Krzysztof Kozlowski, Lad Prabhakar, Leon Luo,
Liam Girdwood, Magnus Damm, Manivannan Sadhasivam, Mark Brown,
Matthew Majewski, Matthias Fend, Mikhail Rudenko,
Nicolas Dufresne, Niklas Söderlund, Pavel Machek,
Pengutronix Kernel Team, Ricardo Ribalda, Rob Herring,
Sascha Hauer, Shawn Guo, Shunqian Zheng, Sylvain Petinot,
Sylwester Nawrocki, Tarang Raval, Tianshu Qiu, Todor Tomov,
Tomi Valkeinen, Tony Lindgren, Zhi Mao, devicetree, imx,
linux-arm-kernel, linux-arm-msm, linux-omap, linux-renesas-soc,
linux-samsung-soc
On Tue, Aug 12, 2025 at 10:58:30AM +0200, Krzysztof Kozlowski wrote:
> On 12/08/2025 10:51, Laurent Pinchart wrote:
> > On Mon, Aug 11, 2025 at 06:27:01PM -0500, Bjorn Andersson wrote:
> >> On Thu, 10 Jul 2025 20:46:56 +0300, Laurent Pinchart wrote:
> >>> This patch series build on top of Mehdi's introduction of the
> >>> devm_v4l2_sensor_clk_get() helper (see [1]) to drastically reduce
> >>> cargo-cult in camera sensor drivers.
> >>>
> >>> A large number of camera sensor drivers directly use the
> >>> "clock-frequency" property to retrieve the effective or desired external
> >>> clock rate. This is standard behaviour on ACPI platforms that don't
> >>> implement MIPI DisCo for Imaging, but usage of the property has leaked
> >>> to OF-based platforms, due to a combination of historical reasons (using
> >>> "clock-frequency" was initially considered right until before the
> >>> introduction of "assigned-clock-rates") and plain cargo-cult.
> >>>
> >>> [...]
> >>
> >> Applied, thanks!
> >>
> >> [12/72] arm64: dts: qcom: sdm845-db845c-navigation-mezzanine: Replace clock-frequency in camera sensor node
> >> commit: 5433560caa5e7e677a8d4310bbec08312be765b4
> >
> > I'm afraid that's too soon. This will introduce a breakage without a
> > corresponding change to the camera sensor driver.
> >
> > I will post a v2 with the patches reordered. We could merge the V4L2
> > side in a rc1-based stable branch and merge than in the arm-soc tree as
>
> You cannot ("cannot" as not following the process) merge drivers into
> DTS branch.
Ah, I wasn't aware of that. DTS trees don't allow merging stable
branches shared with other subsystems ? Does it mean that a DTS change
that depends on a driver change always need to be delayed by one kernel
version ?
> > well, but I think we can also delay the .dts changes to the next kernel
>
> All users of DTS will be anyway affected and commit msg should address that.
Which commit message, the one for the driver changes or the one for the
DTS changes ? I plan in the next version to indicate that the DT changes
depend on the driver changes.
> > version. Do you have a preference ?
--
Regards,
Laurent Pinchart
^ permalink raw reply [flat|nested] 115+ messages in thread
* Re: (subset) [PATCH 00/72] media: i2c: Reduce cargo-cult
2025-08-12 9:39 ` Laurent Pinchart
@ 2025-08-12 10:28 ` Krzysztof Kozlowski
2025-08-12 10:34 ` Laurent Pinchart
2025-08-12 20:10 ` Laurent Pinchart
0 siblings, 2 replies; 115+ messages in thread
From: Krzysztof Kozlowski @ 2025-08-12 10:28 UTC (permalink / raw)
To: Laurent Pinchart
Cc: Bjorn Andersson, linux-media, Sakari Ailus, Mehdi Djait,
Alim Akhtar, André Apitzsch, Andrzej Hajda, Arec Kao,
Benjamin Mugnier, Bingbu Cao, Bryan O'Donoghue,
Bryan O'Donoghue, Conor Dooley, Daniel Scally, Dongcheng Yan,
Dongchun Zhu, Fabio Estevam, Geert Uytterhoeven, Hans de Goede,
Hans Verkuil, Hao Yao, Heimir Thor Sverrisson, Jacopo Mondi,
Jason Chen, Jimmy Su, Jingjing Xiong, Jonas Karlman,
Konrad Dybcio, Krzysztof Kozlowski, Lad Prabhakar, Leon Luo,
Liam Girdwood, Magnus Damm, Manivannan Sadhasivam, Mark Brown,
Matthew Majewski, Matthias Fend, Mikhail Rudenko,
Nicolas Dufresne, Niklas Söderlund, Pavel Machek,
Pengutronix Kernel Team, Ricardo Ribalda, Rob Herring,
Sascha Hauer, Shawn Guo, Shunqian Zheng, Sylvain Petinot,
Sylwester Nawrocki, Tarang Raval, Tianshu Qiu, Todor Tomov,
Tomi Valkeinen, Tony Lindgren, Zhi Mao, devicetree, imx,
linux-arm-kernel, linux-arm-msm, linux-omap, linux-renesas-soc,
linux-samsung-soc
On 12/08/2025 11:39, Laurent Pinchart wrote:
>>>>
>>>> [12/72] arm64: dts: qcom: sdm845-db845c-navigation-mezzanine: Replace clock-frequency in camera sensor node
>>>> commit: 5433560caa5e7e677a8d4310bbec08312be765b4
>>>
>>> I'm afraid that's too soon. This will introduce a breakage without a
>>> corresponding change to the camera sensor driver.
>>>
>>> I will post a v2 with the patches reordered. We could merge the V4L2
>>> side in a rc1-based stable branch and merge than in the arm-soc tree as
>>
>> You cannot ("cannot" as not following the process) merge drivers into
>> DTS branch.
>
> Ah, I wasn't aware of that. DTS trees don't allow merging stable
> branches shared with other subsystems ? Does it mean that a DTS change
Not with driver subsystems. Why? Because it breaks encapsulation of
hardware description being entirely independent of given Linux driver
implementation.
BTW, it is already documented in maintainer-soc in ABI stability (I will
fix "devicetree" ambiguity to DTS) and driver branch dependencies.
> that depends on a driver change always need to be delayed by one kernel
> version ?
This is one solution, although as I mentioned later it still affects all
other users of DTS, so it has its own drawbacks.
Other solution is to keep both properties for more than one cycle.
>
>>> well, but I think we can also delay the .dts changes to the next kernel
>>
>> All users of DTS will be anyway affected and commit msg should address that.
>
> Which commit message, the one for the driver changes or the one for the
> DTS changes ? I plan in the next version to indicate that the DT changes
> depend on the driver changes.
DTS changes, so the soc maintainers can judge whether they care about
other DTS users or they do not.
Best regards,
Krzysztof
^ permalink raw reply [flat|nested] 115+ messages in thread
* Re: (subset) [PATCH 00/72] media: i2c: Reduce cargo-cult
2025-08-12 10:28 ` Krzysztof Kozlowski
@ 2025-08-12 10:34 ` Laurent Pinchart
2025-08-12 20:10 ` Laurent Pinchart
1 sibling, 0 replies; 115+ messages in thread
From: Laurent Pinchart @ 2025-08-12 10:34 UTC (permalink / raw)
To: Krzysztof Kozlowski
Cc: Bjorn Andersson, linux-media, Sakari Ailus, Mehdi Djait,
Alim Akhtar, André Apitzsch, Andrzej Hajda, Arec Kao,
Benjamin Mugnier, Bingbu Cao, Bryan O'Donoghue,
Bryan O'Donoghue, Conor Dooley, Daniel Scally, Dongcheng Yan,
Dongchun Zhu, Fabio Estevam, Geert Uytterhoeven, Hans de Goede,
Hans Verkuil, Hao Yao, Heimir Thor Sverrisson, Jacopo Mondi,
Jason Chen, Jimmy Su, Jingjing Xiong, Jonas Karlman,
Konrad Dybcio, Krzysztof Kozlowski, Lad Prabhakar, Leon Luo,
Liam Girdwood, Magnus Damm, Manivannan Sadhasivam, Mark Brown,
Matthew Majewski, Matthias Fend, Mikhail Rudenko,
Nicolas Dufresne, Niklas Söderlund, Pavel Machek,
Pengutronix Kernel Team, Ricardo Ribalda, Rob Herring,
Sascha Hauer, Shawn Guo, Shunqian Zheng, Sylvain Petinot,
Sylwester Nawrocki, Tarang Raval, Tianshu Qiu, Todor Tomov,
Tomi Valkeinen, Tony Lindgren, Zhi Mao, devicetree, imx,
linux-arm-kernel, linux-arm-msm, linux-omap, linux-renesas-soc,
linux-samsung-soc
On Tue, Aug 12, 2025 at 12:28:28PM +0200, Krzysztof Kozlowski wrote:
> On 12/08/2025 11:39, Laurent Pinchart wrote:
> >>>>
> >>>> [12/72] arm64: dts: qcom: sdm845-db845c-navigation-mezzanine: Replace clock-frequency in camera sensor node
> >>>> commit: 5433560caa5e7e677a8d4310bbec08312be765b4
> >>>
> >>> I'm afraid that's too soon. This will introduce a breakage without a
> >>> corresponding change to the camera sensor driver.
> >>>
> >>> I will post a v2 with the patches reordered. We could merge the V4L2
> >>> side in a rc1-based stable branch and merge than in the arm-soc tree as
> >>
> >> You cannot ("cannot" as not following the process) merge drivers into
> >> DTS branch.
> >
> > Ah, I wasn't aware of that. DTS trees don't allow merging stable
> > branches shared with other subsystems ? Does it mean that a DTS change
>
> Not with driver subsystems. Why? Because it breaks encapsulation of
> hardware description being entirely independent of given Linux driver
> implementation.
>
> BTW, it is already documented in maintainer-soc in ABI stability (I will
> fix "devicetree" ambiguity to DTS) and driver branch dependencies.
>
> > that depends on a driver change always need to be delayed by one kernel
> > version ?
>
> This is one solution, although as I mentioned later it still affects all
> other users of DTS, so it has its own drawbacks.
>
> Other solution is to keep both properties for more than one cycle.
OK.
There's no urgency to merge the .dts changes, so I think delaying them
by one kernel release is the simplest option.
> >>> well, but I think we can also delay the .dts changes to the next kernel
> >>
> >> All users of DTS will be anyway affected and commit msg should address that.
> >
> > Which commit message, the one for the driver changes or the one for the
> > DTS changes ? I plan in the next version to indicate that the DT changes
> > depend on the driver changes.
>
> DTS changes, so the soc maintainers can judge whether they care about
> other DTS users or they do not.
Thank you for the clarification. I will do that.
--
Regards,
Laurent Pinchart
^ permalink raw reply [flat|nested] 115+ messages in thread
* Re: (subset) [PATCH 00/72] media: i2c: Reduce cargo-cult
2025-08-12 10:28 ` Krzysztof Kozlowski
2025-08-12 10:34 ` Laurent Pinchart
@ 2025-08-12 20:10 ` Laurent Pinchart
1 sibling, 0 replies; 115+ messages in thread
From: Laurent Pinchart @ 2025-08-12 20:10 UTC (permalink / raw)
To: Krzysztof Kozlowski
Cc: Bjorn Andersson, linux-media, Sakari Ailus, Mehdi Djait,
Alim Akhtar, André Apitzsch, Andrzej Hajda, Arec Kao,
Benjamin Mugnier, Bingbu Cao, Bryan O'Donoghue,
Bryan O'Donoghue, Conor Dooley, Daniel Scally, Dongcheng Yan,
Dongchun Zhu, Fabio Estevam, Geert Uytterhoeven, Hans de Goede,
Hans Verkuil, Hao Yao, Heimir Thor Sverrisson, Jacopo Mondi,
Jason Chen, Jimmy Su, Jingjing Xiong, Jonas Karlman,
Konrad Dybcio, Krzysztof Kozlowski, Lad Prabhakar, Leon Luo,
Liam Girdwood, Magnus Damm, Manivannan Sadhasivam, Mark Brown,
Matthew Majewski, Matthias Fend, Mikhail Rudenko,
Nicolas Dufresne, Niklas Söderlund, Pavel Machek,
Pengutronix Kernel Team, Ricardo Ribalda, Rob Herring,
Sascha Hauer, Shawn Guo, Shunqian Zheng, Sylvain Petinot,
Sylwester Nawrocki, Tarang Raval, Tianshu Qiu, Todor Tomov,
Tomi Valkeinen, Tony Lindgren, Zhi Mao, devicetree, imx,
linux-arm-kernel, linux-arm-msm, linux-omap, linux-renesas-soc,
linux-samsung-soc
On Tue, Aug 12, 2025 at 12:28:28PM +0200, Krzysztof Kozlowski wrote:
> On 12/08/2025 11:39, Laurent Pinchart wrote:
> >>>>
> >>>> [12/72] arm64: dts: qcom: sdm845-db845c-navigation-mezzanine: Replace clock-frequency in camera sensor node
> >>>> commit: 5433560caa5e7e677a8d4310bbec08312be765b4
> >>>
> >>> I'm afraid that's too soon. This will introduce a breakage without a
> >>> corresponding change to the camera sensor driver.
> >>>
> >>> I will post a v2 with the patches reordered. We could merge the V4L2
> >>> side in a rc1-based stable branch and merge than in the arm-soc tree as
> >>
> >> You cannot ("cannot" as not following the process) merge drivers into
> >> DTS branch.
> >
> > Ah, I wasn't aware of that. DTS trees don't allow merging stable
> > branches shared with other subsystems ? Does it mean that a DTS change
>
> Not with driver subsystems. Why? Because it breaks encapsulation of
> hardware description being entirely independent of given Linux driver
> implementation.
>
> BTW, it is already documented in maintainer-soc in ABI stability (I will
> fix "devicetree" ambiguity to DTS) and driver branch dependencies.
I've just read that document, and didn't interpret it as stricly
forbidding merging a driver branch in the arm-soc tree. The rule makes
sense though, as it makes it easier to ensure that backward
compatibility isn't broken by accident. The downside is that it can slow
down merging patches in some cases.
> > that depends on a driver change always need to be delayed by one kernel
> > version ?
>
> This is one solution, although as I mentioned later it still affects all
> other users of DTS, so it has its own drawbacks.
>
> Other solution is to keep both properties for more than one cycle.
>
> >>> well, but I think we can also delay the .dts changes to the next kernel
> >>
> >> All users of DTS will be anyway affected and commit msg should address that.
> >
> > Which commit message, the one for the driver changes or the one for the
> > DTS changes ? I plan in the next version to indicate that the DT changes
> > depend on the driver changes.
>
> DTS changes, so the soc maintainers can judge whether they care about
> other DTS users or they do not.
--
Regards,
Laurent Pinchart
^ permalink raw reply [flat|nested] 115+ messages in thread
end of thread, other threads:[~2025-08-12 20:10 UTC | newest]
Thread overview: 115+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-07-10 17:46 [PATCH 00/72] media: i2c: Reduce cargo-cult Laurent Pinchart
2025-07-10 17:46 ` [PATCH 01/72] dt-bindings: media: Deprecate clock-frequency property for camera sensors Laurent Pinchart
2025-07-10 23:10 ` Rob Herring (Arm)
2025-07-10 17:46 ` [PATCH 02/72] dt-bindings: media: et8ek8: Deprecate clock-frequency property Laurent Pinchart
2025-07-10 23:11 ` Rob Herring (Arm)
2025-07-10 17:46 ` [PATCH 03/72] dt-bindings: media: imx258: Make clocks property required Laurent Pinchart
2025-07-10 23:11 ` Rob Herring (Arm)
2025-07-10 17:47 ` [PATCH 04/72] dt-bindings: media: imx274: " Laurent Pinchart
2025-07-10 19:37 ` Rob Herring (Arm)
2025-07-10 20:33 ` Laurent Pinchart
2025-07-10 17:47 ` [PATCH 05/72] ARM: dts: nxp: imx6qdl-pico: Replace clock-frequency in camera sensor node Laurent Pinchart
2025-07-10 20:19 ` Frank Li
2025-07-10 17:47 ` [PATCH 06/72] ARM: dts: nxp: imx6qdl-wandboard: " Laurent Pinchart
2025-07-10 20:18 ` Frank Li
2025-07-10 20:34 ` Laurent Pinchart
2025-07-11 5:17 ` Frank Li
2025-07-10 17:47 ` [PATCH 07/72] ARM: dts: samsung: exynos4210-i9100: " Laurent Pinchart
2025-07-10 17:47 ` [PATCH 08/72] ARM: dts: samsung: exynos4412-midas: " Laurent Pinchart
2025-07-10 17:47 ` [PATCH 09/72] ARM: dts: ti: omap3-n900: " Laurent Pinchart
2025-07-10 17:47 ` [PATCH 10/72] ARM: dts: ti: omap3-n950: " Laurent Pinchart
2025-07-10 17:47 ` [PATCH 11/72] ARM: dts: ti: omap3-n9: " Laurent Pinchart
2025-07-10 17:47 ` [PATCH 12/72] arm64: dts: qcom: sdm845-db845c-navigation-mezzanine: " Laurent Pinchart
2025-07-11 12:25 ` Konrad Dybcio
2025-07-11 12:45 ` Laurent Pinchart
2025-07-11 12:47 ` Konrad Dybcio
2025-07-10 17:47 ` [PATCH 13/72] arm64: dts: renesas: aistarvision-mipi-adapter-2.1: Drop clock-frequency from " Laurent Pinchart
2025-07-28 14:19 ` Geert Uytterhoeven
2025-07-28 15:08 ` Laurent Pinchart
2025-07-10 17:47 ` [PATCH 14/72] arm64: dts: renesas: rzg2l-smarc: " Laurent Pinchart
2025-07-28 14:20 ` Geert Uytterhoeven
2025-07-10 17:47 ` [PATCH 15/72] media: i2c: mt9v022: Drop unused mt9v022.h header Laurent Pinchart
2025-07-10 17:47 ` [PATCH 16/72] media: i2c: mt9v032: Replace client->dev usage Laurent Pinchart
2025-07-10 17:47 ` [PATCH 17/72] media: i2c: mt9v032: Drop support for platform data Laurent Pinchart
2025-07-10 17:47 ` [PATCH 18/72] media: i2c: mt9v111: Do not set clock rate manually Laurent Pinchart
2025-07-10 17:47 ` [PATCH 19/72] media: i2c: ov6650: Drop unused driver Laurent Pinchart
2025-07-10 17:47 ` [PATCH 20/72] media: i2c: hi556: Replace client->dev usage Laurent Pinchart
2025-07-10 17:47 ` [PATCH 21/72] media: i2c: hi556: Use V4L2 sensor clock helper Laurent Pinchart
2025-07-10 17:47 ` [PATCH 22/72] media: i2c: hi847: Replace client->dev usage Laurent Pinchart
2025-07-10 17:47 ` [PATCH 23/72] media: i2c: hi847: Use V4L2 sensor clock helper Laurent Pinchart
2025-07-10 17:47 ` [PATCH 24/72] media: i2c: imx208: Replace client->dev usage Laurent Pinchart
2025-07-10 17:47 ` [PATCH 25/72] media: i2c: imx208: Use V4L2 sensor clock helper Laurent Pinchart
2025-07-10 17:47 ` [PATCH 26/72] media: i2c: imx319: Replace client->dev usage Laurent Pinchart
2025-07-10 17:47 ` [PATCH 27/72] media: i2c: imx319: Use V4L2 sensor clock helper Laurent Pinchart
2025-07-10 17:47 ` [PATCH 28/72] media: i2c: imx355: Replace client->dev usage Laurent Pinchart
2025-07-10 17:47 ` [PATCH 29/72] media: i2c: imx335: Use V4L2 sensor clock helper Laurent Pinchart
2025-07-10 17:47 ` [PATCH 30/72] media: i2c: og01a1b: Replace client->dev usage Laurent Pinchart
2025-07-10 17:47 ` [PATCH 31/72] media: i2c: og01a1b: Use V4L2 sensor clock helper Laurent Pinchart
2025-07-15 11:44 ` Mehdi Djait
2025-07-15 18:41 ` Laurent Pinchart
2025-07-10 17:47 ` [PATCH 32/72] media: i2c: ov02c10: Replace client->dev usage Laurent Pinchart
2025-07-10 17:47 ` [PATCH 33/72] media: i2c: ov02c10: Use V4L2 sensor clock helper Laurent Pinchart
2025-07-10 17:47 ` [PATCH 34/72] media: i2c: ov02e10: Replace client->dev usage Laurent Pinchart
2025-07-10 17:47 ` [PATCH 35/72] media: i2c: ov02e10: Use V4L2 sensor clock helper Laurent Pinchart
2025-07-10 17:47 ` [PATCH 36/72] media: i2c: ov08d10: Replace client->dev usage Laurent Pinchart
2025-07-10 17:47 ` [PATCH 37/72] media: i2c: ov08d10: Use V4L2 sensor clock helper Laurent Pinchart
2025-07-10 17:47 ` [PATCH 38/72] media: i2c: ov08x40: Replace client->dev usage Laurent Pinchart
2025-07-10 17:47 ` [PATCH 39/72] media: i2c: ov08x40: Use V4L2 sensor clock helper Laurent Pinchart
2025-07-10 17:47 ` [PATCH 40/72] media: i2c: ov13858: Replace client->dev usage Laurent Pinchart
2025-07-10 17:47 ` [PATCH 41/72] media: i2c: ov13858: Use V4L2 sensor clock helper Laurent Pinchart
2025-07-10 17:47 ` [PATCH 42/72] media: i2c: ov13b10: Replace client->dev usage Laurent Pinchart
2025-07-10 17:47 ` [PATCH 43/72] media: i2c: ov13b10: Use V4L2 sensor clock helper Laurent Pinchart
2025-07-10 17:47 ` [PATCH 44/72] media: i2c: ov2740: Replace client->dev usage Laurent Pinchart
2025-07-10 17:47 ` [PATCH 45/72] media: i2c: ov2740: Use V4L2 sensor clock helper Laurent Pinchart
2025-07-10 17:47 ` [PATCH 46/72] media: i2c: ov4689: " Laurent Pinchart
2025-07-10 17:47 ` [PATCH 47/72] media: i2c: ov5670: Replace client->dev usage Laurent Pinchart
2025-07-10 17:47 ` [PATCH 48/72] media: i2c: ov5670: Use V4L2 sensor clock helper Laurent Pinchart
2025-07-10 17:47 ` [PATCH 49/72] media: i2c: ov5675: Replace client->dev usage Laurent Pinchart
2025-07-10 17:47 ` [PATCH 50/72] media: i2c: ov5675: Use V4L2 sensor clock helper Laurent Pinchart
2025-07-10 17:47 ` [PATCH 51/72] media: i2c: ov5693: " Laurent Pinchart
2025-07-10 17:47 ` [PATCH 52/72] media: i2c: ov7251: " Laurent Pinchart
2025-07-10 17:47 ` [PATCH 53/72] media: i2c: ov9734: Replace client->dev usage Laurent Pinchart
2025-07-10 17:47 ` [PATCH 54/72] media: i2c: ov9734: Use V4L2 sensor clock helper Laurent Pinchart
2025-07-10 17:47 ` [PATCH 55/72] media: v4l2-common: Add legacy camera " Laurent Pinchart
2025-07-14 12:54 ` Mehdi Djait
2025-07-14 13:12 ` Mehdi Djait
2025-07-14 14:09 ` Laurent Pinchart
2025-07-14 21:15 ` Mehdi Djait
2025-07-10 17:47 ` [PATCH 56/72] media: i2c: et8ek8: Drop support for per-mode external clock frequency Laurent Pinchart
2025-07-10 17:47 ` [PATCH 57/72] media: i2c: et8ek8: Use V4L2 legacy sensor clock helper Laurent Pinchart
2025-07-10 17:47 ` [PATCH 58/72] media: i2c: gc05a2: " Laurent Pinchart
2025-07-10 17:47 ` [PATCH 59/72] media: i2c: gc08a3: " Laurent Pinchart
2025-07-10 17:47 ` [PATCH 60/72] media: i2c: imx258: Replace client->dev usage Laurent Pinchart
2025-07-10 17:47 ` [PATCH 61/72] media: i2c: imx258: Use V4L2 legacy sensor clock helper Laurent Pinchart
2025-07-10 17:47 ` [PATCH 62/72] media: i2c: imx290: " Laurent Pinchart
2025-07-10 17:47 ` [PATCH 63/72] media: i2c: ov02a10: Replace client->dev usage Laurent Pinchart
2025-07-10 17:48 ` [PATCH 64/72] media: i2c: ov02a10: Use V4L2 legacy sensor clock helper Laurent Pinchart
2025-07-10 17:48 ` [PATCH 65/72] media: i2c: ov2685: " Laurent Pinchart
2025-07-10 17:48 ` [PATCH 66/72] media: i2c: ov5645: " Laurent Pinchart
2025-07-10 17:48 ` [PATCH 67/72] media: i2c: ov5695: " Laurent Pinchart
2025-07-10 17:48 ` [PATCH 68/72] media: i2c: ov8856: Replace client->dev usage Laurent Pinchart
2025-07-10 17:48 ` [PATCH 69/72] media: i2c: ov8856: Use V4L2 legacy sensor clock helper Laurent Pinchart
2025-07-10 17:48 ` [PATCH 70/72] media: i2c: s5c73m3: " Laurent Pinchart
2025-07-10 17:48 ` [PATCH 71/72] media: i2c: s5k5baf: " Laurent Pinchart
2025-07-10 17:48 ` [PATCH 72/72] media: i2c: s5k6a3: " Laurent Pinchart
2025-07-24 11:42 ` [PATCH 00/72] media: i2c: Reduce cargo-cult Tarang Raval
2025-07-24 11:52 ` Laurent Pinchart
[not found] ` <PN3P287MB1829C9E8C78ADD70259A68F08B5EA@PN3P287MB1829.INDP287.PROD.OUTLOOK.COM>
2025-07-24 13:37 ` Mark Brown
2025-07-24 13:52 ` Laurent Pinchart
2025-07-24 14:20 ` Tarang Raval
2025-07-24 14:26 ` Mark Brown
2025-07-24 15:44 ` Laurent Pinchart
2025-07-25 7:00 ` Tarang Raval
2025-07-25 9:38 ` Laurent Pinchart
2025-07-25 10:35 ` Tarang Raval
2025-07-25 11:00 ` Laurent Pinchart
2025-07-25 11:31 ` Tarang Raval
2025-07-25 12:35 ` Mark Brown
2025-07-26 6:17 ` Tarang Raval
2025-08-11 23:27 ` (subset) " Bjorn Andersson
2025-08-12 8:51 ` Laurent Pinchart
2025-08-12 8:58 ` Krzysztof Kozlowski
2025-08-12 9:39 ` Laurent Pinchart
2025-08-12 10:28 ` Krzysztof Kozlowski
2025-08-12 10:34 ` Laurent Pinchart
2025-08-12 20:10 ` Laurent Pinchart
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).