* [PATCH v4 00/10] Add device tree support for Exynos4 SoC camera subsystem
@ 2014-02-20 19:40 Sylwester Nawrocki
2014-02-20 19:40 ` Sylwester Nawrocki
` (10 more replies)
0 siblings, 11 replies; 20+ messages in thread
From: Sylwester Nawrocki @ 2014-02-20 19:40 UTC (permalink / raw)
To: linux-media, devicetree
Cc: linux-samsung-soc, linux-arm-kernel, robh+dt, mark.rutland, galak,
kyungmin.park, kgene.kim, a.hajda, Sylwester Nawrocki
This series adds devicetree support for the front and rear camera of
the Exynos4412 SoC Trats2 board. It converts related drivers to use
the v4l2-async API. The SoC output clocks are provided to external image
image sensors through the common clock API.
I'd appreciate a DT binding maintainer reviewed patches 2/10, 3/10.
With an Ack I could finally push these things upstream.
Sylwester Nawrocki (10):
Documentation: dt: Add DT binding documentation for S5K6A3 image
sensor
Documentation: dt: Add DT binding documentation for S5C73M3 camera
Documentation: devicetree: Update Samsung FIMC DT binding
V4L: Add driver for s5k6a3 image sensor
V4L: s5c73m3: Add device tree support
exynos4-is: Use external s5k6a3 sensor driver
exynos4-is: Add clock provider for the SCLK_CAM clock outputs
exynos4-is: Add support for asynchronous subdevices registration
ARM: dts: Add rear camera nodes for Exynos4412 TRATS2 board
ARM: dts: exynos4: Update clk provider part of the camera subsystem
.../devicetree/bindings/media/samsung-fimc.txt | 36 +-
.../devicetree/bindings/media/samsung-s5c73m3.txt | 97 +++++
.../devicetree/bindings/media/samsung-s5k6a3.txt | 33 ++
arch/arm/boot/dts/exynos4.dtsi | 6 +-
arch/arm/boot/dts/exynos4412-trats2.dts | 86 ++++-
drivers/media/i2c/Kconfig | 8 +
drivers/media/i2c/Makefile | 1 +
drivers/media/i2c/s5c73m3/s5c73m3-core.c | 207 ++++++++---
drivers/media/i2c/s5c73m3/s5c73m3-spi.c | 6 +
drivers/media/i2c/s5c73m3/s5c73m3.h | 4 +
drivers/media/i2c/s5k6a3.c | 388 ++++++++++++++++++++
drivers/media/platform/exynos4-is/fimc-is-regs.c | 2 +-
drivers/media/platform/exynos4-is/fimc-is-sensor.c | 285 +-------------
drivers/media/platform/exynos4-is/fimc-is-sensor.h | 49 +--
drivers/media/platform/exynos4-is/fimc-is.c | 97 ++---
drivers/media/platform/exynos4-is/fimc-is.h | 4 +-
drivers/media/platform/exynos4-is/media-dev.c | 329 ++++++++++++-----
drivers/media/platform/exynos4-is/media-dev.h | 32 +-
18 files changed, 1127 insertions(+), 543 deletions(-)
create mode 100644 Documentation/devicetree/bindings/media/samsung-s5c73m3.txt
create mode 100644 Documentation/devicetree/bindings/media/samsung-s5k6a3.txt
create mode 100644 drivers/media/i2c/s5k6a3.c
--
1.7.9.5
^ permalink raw reply [flat|nested] 20+ messages in thread
* [PATCH v4 00/10] Add device tree support for Exynos4 SoC camera subsystem
2014-02-20 19:40 [PATCH v4 00/10] Add device tree support for Exynos4 SoC camera subsystem Sylwester Nawrocki
@ 2014-02-20 19:40 ` Sylwester Nawrocki
2014-02-20 19:40 ` [PATCH v4 01/10] Documentation: dt: Add DT binding documentation for S5K6A3 image sensor Sylwester Nawrocki
` (9 subsequent siblings)
10 siblings, 0 replies; 20+ messages in thread
From: Sylwester Nawrocki @ 2014-02-20 19:40 UTC (permalink / raw)
To: linux-media, devicetree
Cc: linux-samsung-soc, linux-arm-kernel, robh+dt, mark.rutland, galak,
kyungmin.park, kgene.kim, a.hajda, Sylwester Nawrocki
This series adds devicetree support for the front and rear camera of
the Exynos4412 SoC Trats2 board. It converts related drivers to use
the v4l2-async API. The SoC output clocks are provided to external image
image sensors through the common clock API.
I'd appreciate a DT binding maintainer reviewed patches 2/11, 3/11.
With an Ack I could finally push these things upstream.
Sylwester Nawrocki (10):
Documentation: dt: Add DT binding documentation for S5K6A3 image
sensor
Documentation: dt: Add DT binding documentation for S5C73M3 camera
Documentation: devicetree: Update Samsung FIMC DT binding
V4L: Add driver for s5k6a3 image sensor
V4L: s5c73m3: Add device tree support
exynos4-is: Use external s5k6a3 sensor driver
exynos4-is: Add clock provider for the SCLK_CAM clock outputs
exynos4-is: Add support for asynchronous subdevices registration
ARM: dts: Add rear camera nodes for Exynos4412 TRATS2 board
ARM: dts: exynos4: Update clk provider part of the camera subsystem
.../devicetree/bindings/media/samsung-fimc.txt | 36 +-
.../devicetree/bindings/media/samsung-s5c73m3.txt | 97 +++++
.../devicetree/bindings/media/samsung-s5k6a3.txt | 33 ++
arch/arm/boot/dts/exynos4.dtsi | 6 +-
arch/arm/boot/dts/exynos4412-trats2.dts | 86 ++++-
drivers/media/i2c/Kconfig | 8 +
drivers/media/i2c/Makefile | 1 +
drivers/media/i2c/s5c73m3/s5c73m3-core.c | 207 ++++++++---
drivers/media/i2c/s5c73m3/s5c73m3-spi.c | 6 +
drivers/media/i2c/s5c73m3/s5c73m3.h | 4 +
drivers/media/i2c/s5k6a3.c | 388 ++++++++++++++++++++
drivers/media/platform/exynos4-is/fimc-is-regs.c | 2 +-
drivers/media/platform/exynos4-is/fimc-is-sensor.c | 285 +-------------
drivers/media/platform/exynos4-is/fimc-is-sensor.h | 49 +--
drivers/media/platform/exynos4-is/fimc-is.c | 97 ++---
drivers/media/platform/exynos4-is/fimc-is.h | 4 +-
drivers/media/platform/exynos4-is/media-dev.c | 329 ++++++++++++-----
drivers/media/platform/exynos4-is/media-dev.h | 32 +-
18 files changed, 1127 insertions(+), 543 deletions(-)
create mode 100644 Documentation/devicetree/bindings/media/samsung-s5c73m3.txt
create mode 100644 Documentation/devicetree/bindings/media/samsung-s5k6a3.txt
create mode 100644 drivers/media/i2c/s5k6a3.c
--
1.7.9.5
^ permalink raw reply [flat|nested] 20+ messages in thread
* [PATCH v4 01/10] Documentation: dt: Add DT binding documentation for S5K6A3 image sensor
2014-02-20 19:40 [PATCH v4 00/10] Add device tree support for Exynos4 SoC camera subsystem Sylwester Nawrocki
2014-02-20 19:40 ` Sylwester Nawrocki
@ 2014-02-20 19:40 ` Sylwester Nawrocki
2014-02-20 19:40 ` [PATCH v4 02/10] Documentation: dt: Add DT binding documentation for S5C73M3 camera Sylwester Nawrocki
` (8 subsequent siblings)
10 siblings, 0 replies; 20+ messages in thread
From: Sylwester Nawrocki @ 2014-02-20 19:40 UTC (permalink / raw)
To: linux-media, devicetree
Cc: linux-samsung-soc, linux-arm-kernel, robh+dt, mark.rutland, galak,
kyungmin.park, kgene.kim, a.hajda, Sylwester Nawrocki
This patch adds binding documentation for the Samsung S5K6A3(YX)
raw image sensor.
Signed-off-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
Acked-by: Kyungmin Park <kyungmin.park@samsung.com>
Acked-by: Mark Rutland <mark.rutland@arm.com>
---
Changes since v3:
-none.
Changes since v2:
- rephrased 'clocks' and 'clock-names' properties' description;
---
.../devicetree/bindings/media/samsung-s5k6a3.txt | 33 ++++++++++++++++++++
1 file changed, 33 insertions(+)
create mode 100644 Documentation/devicetree/bindings/media/samsung-s5k6a3.txt
diff --git a/Documentation/devicetree/bindings/media/samsung-s5k6a3.txt b/Documentation/devicetree/bindings/media/samsung-s5k6a3.txt
new file mode 100644
index 0000000..cce01e8
--- /dev/null
+++ b/Documentation/devicetree/bindings/media/samsung-s5k6a3.txt
@@ -0,0 +1,33 @@
+Samsung S5K6A3(YX) raw image sensor
+---------------------------------
+
+S5K6A3(YX) is a raw image sensor with MIPI CSI-2 and CCP2 image data interfaces
+and CCI (I2C compatible) control bus.
+
+Required properties:
+
+- compatible : "samsung,s5k6a3";
+- reg : I2C slave address of the sensor;
+- svdda-supply : core voltage supply;
+- svddio-supply : I/O voltage supply;
+- afvdd-supply : AF (actuator) voltage supply;
+- gpios : specifier of a GPIO connected to the RESET pin;
+- clocks : should contain list of phandle and clock specifier pairs
+ according to common clock bindings for the clocks described
+ in the clock-names property;
+- clock-names : should contain "extclk" entry for the sensor's EXTCLK clock;
+
+Optional properties:
+
+- clock-frequency : the frequency at which the "extclk" clock should be
+ configured to operate, in Hz; if this property is not
+ specified default 24 MHz value will be used.
+
+The common video interfaces bindings (see video-interfaces.txt) should be
+used to specify link to the image data receiver. The S5K6A3(YX) device
+node should contain one 'port' child node with an 'endpoint' subnode.
+
+Following properties are valid for the endpoint node:
+
+- data-lanes : (optional) specifies MIPI CSI-2 data lanes as covered in
+ video-interfaces.txt. The sensor supports only one data lane.
--
1.7.9.5
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH v4 02/10] Documentation: dt: Add DT binding documentation for S5C73M3 camera
2014-02-20 19:40 [PATCH v4 00/10] Add device tree support for Exynos4 SoC camera subsystem Sylwester Nawrocki
2014-02-20 19:40 ` Sylwester Nawrocki
2014-02-20 19:40 ` [PATCH v4 01/10] Documentation: dt: Add DT binding documentation for S5K6A3 image sensor Sylwester Nawrocki
@ 2014-02-20 19:40 ` Sylwester Nawrocki
2014-02-21 15:42 ` Mark Rutland
2014-02-20 19:40 ` [PATCH v4 03/10] Documentation: devicetree: Update Samsung FIMC DT binding Sylwester Nawrocki
` (7 subsequent siblings)
10 siblings, 1 reply; 20+ messages in thread
From: Sylwester Nawrocki @ 2014-02-20 19:40 UTC (permalink / raw)
To: linux-media, devicetree
Cc: linux-samsung-soc, linux-arm-kernel, robh+dt, mark.rutland, galak,
kyungmin.park, kgene.kim, a.hajda, Sylwester Nawrocki
This adds DT binding documentation for Samsung S5C73M3 camera sensor
with an embedded ISP.
Signed-off-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
Acked-by: Kyungmin Park <kyungmin.park@samsung.com>
---
Changes since v3:
- DT binding documentation separated into this patch;
Changes since v2:
- rephrased 'clocks' and 'clock-names' properties' description;
---
.../devicetree/bindings/media/samsung-s5c73m3.txt | 97 ++++++++++++++++++++
1 file changed, 97 insertions(+)
create mode 100644 Documentation/devicetree/bindings/media/samsung-s5c73m3.txt
diff --git a/Documentation/devicetree/bindings/media/samsung-s5c73m3.txt b/Documentation/devicetree/bindings/media/samsung-s5c73m3.txt
new file mode 100644
index 0000000..4dd3776
--- /dev/null
+++ b/Documentation/devicetree/bindings/media/samsung-s5c73m3.txt
@@ -0,0 +1,97 @@
+Samsung S5C73M3 8Mp camera ISP
+------------------------------
+
+The S5C73M3 camera ISP supports MIPI CSI-2 and parallel (ITU-R BT.656) video
+data busses. The I2C bus is the main control bus and additionally the SPI bus
+is used, mostly for transferring the firmware to and from the device. Two
+slave device nodes corresponding to these control bus interfaces are required
+and should be placed under respective bus controller nodes.
+
+I2C slave device node
+---------------------
+
+Required properties:
+
+- compatible : "samsung,s5c73m3";
+- reg : I2C slave address of the sensor;
+- vdd-int-supply : digital power supply (1.2V);
+- vdda-supply : analog power supply (1.2V);
+- vdd-reg-supply : regulator input power supply (2.8V);
+- vddio-host-supply : host I/O power supply (1.8V to 2.8V);
+- vddio-cis-supply : CIS I/O power supply (1.2V to 1.8V);
+- vdd-af-supply : lens power supply (2.8V);
+- xshutdown-gpios : specifier of GPIO connected to the XSHUTDOWN pin;
+- standby-gpios : specifier of GPIO connected to the STANDBY pin;
+- clocks : should contain list of phandle and clock specifier pairs
+ according to common clock bindings for the clocks described
+ in the clock-names property;
+- clock-names : should contain "cis_extclk" entry for the CIS_EXTCLK clock;
+
+Optional properties:
+
+- clock-frequency : the frequency at which the "cis_extclk" clock should be
+ configured to operate, in Hz; if this property is not
+ specified default 24 MHz value will be used.
+
+The common video interfaces bindings (see video-interfaces.txt) should be used
+to specify link from the S5C73M3 to an external image data receiver. The S5C73M3
+device node should contain one 'port' child node with an 'endpoint' subnode for
+this purpose. The data link from a raw image sensor to the S5C73M3 can be
+similarly specified, but it is optional since the S5C73M3 ISP and a raw image
+sensor are usually inseparable and form a hybrid module.
+
+Following properties are valid for the endpoint node(s):
+
+endpoint subnode
+----------------
+
+- data-lanes : (optional) specifies MIPI CSI-2 data lanes as covered in
+ video-interfaces.txt. This sensor doesn't support data lane remapping
+ and physical lane indexes in subsequent elements of the array should
+ be only consecutive ascending values.
+
+SPI device node
+---------------
+
+Required properties:
+
+- compatible : "samsung,s5c73m3";
+
+For more details see description of the SPI busses bindings
+(../spi/spi-bus.txt) and bindings of a specific bus controller.
+
+Example:
+
+i2c@138A000000 {
+ ...
+ s5c73m3@3c {
+ compatible = "samsung,s5c73m3";
+ reg = <0x3c>;
+ vdd-int-supply = <&buck9_reg>;
+ vdda-supply = <&ldo17_reg>;
+ vdd-reg-supply = <&cam_io_reg>;
+ vddio-host-supply = <&ldo18_reg>;
+ vddio-cis-supply = <&ldo9_reg>;
+ vdd-af-supply = <&cam_af_reg>;
+ clock-frequency = <24000000>;
+ clocks = <&clk 0>;
+ clock-names = "cis_extclk";
+ reset-gpios = <&gpf1 3 1>;
+ standby-gpios = <&gpm0 1 1>;
+ port {
+ s5c73m3_ep: endpoint {
+ remote-endpoint = <&csis0_ep>;
+ data-lanes = <1 2 3 4>;
+ };
+ };
+ };
+};
+
+spi@1392000 {
+ ...
+ s5c73m3_spi: s5c73m3 {
+ compatible = "samsung,s5c73m3";
+ reg = <0>;
+ ...
+ };
+};
--
1.7.9.5
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH v4 03/10] Documentation: devicetree: Update Samsung FIMC DT binding
2014-02-20 19:40 [PATCH v4 00/10] Add device tree support for Exynos4 SoC camera subsystem Sylwester Nawrocki
` (2 preceding siblings ...)
2014-02-20 19:40 ` [PATCH v4 02/10] Documentation: dt: Add DT binding documentation for S5C73M3 camera Sylwester Nawrocki
@ 2014-02-20 19:40 ` Sylwester Nawrocki
2014-02-21 15:50 ` Mark Rutland
[not found] ` <1392925237-31394-1-git-send-email-s.nawrocki-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org>
` (6 subsequent siblings)
10 siblings, 1 reply; 20+ messages in thread
From: Sylwester Nawrocki @ 2014-02-20 19:40 UTC (permalink / raw)
To: linux-media, devicetree
Cc: linux-samsung-soc, linux-arm-kernel, robh+dt, mark.rutland, galak,
kyungmin.park, kgene.kim, a.hajda, Sylwester Nawrocki
This patch documents following updates of the Exynos4 SoC camera subsystem
devicetree binding:
- addition of #clock-cells property to 'camera' node - the #clock-cells
property is needed when the sensor sub-devices use clock provided by
the camera host interface;
- addition of an optional clock-output-names property;
- change of the clock-frequency at image sensor node from mandatory to
an optional property - there should be no need to require this property
by the camera host device binding, a default frequency value can ofen
be used;
- addition of a requirement of specific order of values in clocks/
clock-names properties, so the first two entry in the clock-names
property can be used as parent clock names for the camera master
clock provider. It happens all in-kernel dts files list the clock
in such order, thus there should be no regression as far as in-kernel
dts files are concerned.
Signed-off-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
Acked-by: Kyungmin Park <kyungmin.park@samsung.com>
---
.../devicetree/bindings/media/samsung-fimc.txt | 36 +++++++++++++++-----
1 file changed, 28 insertions(+), 8 deletions(-)
diff --git a/Documentation/devicetree/bindings/media/samsung-fimc.txt b/Documentation/devicetree/bindings/media/samsung-fimc.txt
index 96312f6..1a5820d 100644
--- a/Documentation/devicetree/bindings/media/samsung-fimc.txt
+++ b/Documentation/devicetree/bindings/media/samsung-fimc.txt
@@ -20,6 +20,7 @@ Required properties:
the clock-names property;
- clock-names : must contain "sclk_cam0", "sclk_cam1", "pxl_async0",
"pxl_async1" entries, matching entries in the clocks property.
+ First two entries must be "sclk_cam0", "sclk_cam1".
The pinctrl bindings defined in ../pinctrl/pinctrl-bindings.txt must be used
to define a required pinctrl state named "default" and optional pinctrl states:
@@ -32,6 +33,22 @@ way around.
The 'camera' node must include at least one 'fimc' child node.
+Optional properties (*:
+
+- #clock-cells: from the common clock bindings (../clock/clock-bindings.txt),
+ must be 1. A clock provider is associated with the 'camera' node and it should
+ be referenced by external sensors that use clocks provided by the SoC on
+ CAM_*_CLKOUT pins. The clock specifier cell stores an index of a clock.
+ The indices are 0, 1 for CAM_A_CLKOUT, CAM_B_CLKOUT clocks respectively.
+
+- clock-output-names: from the common clock bindings, should contain names of
+ clocks registered by the camera subsystem corresponding to CAM_A_CLKOUT,
+ CAM_B_CLKOUT output clocks, in this order. Parent clock of these clocks are
+ specified be first two entries of the clock-names property.
+
+(* #clock-cells and clock-output-names are mandatory properties if external
+image sensor devices reference 'camera' device node as a clock provider.
+
'fimc' device nodes
-------------------
@@ -97,8 +114,8 @@ Image sensor nodes
The sensor device nodes should be added to their control bus controller (e.g.
I2C0) nodes and linked to a port node in the csis or the parallel-ports node,
using the common video interfaces bindings, defined in video-interfaces.txt.
-The implementation of this bindings requires clock-frequency property to be
-present in the sensor device nodes.
+An optional clock-frequency property needs to be present in the sensor device
+nodes. Default value when this property is not present is 24 MHz.
Example:
@@ -114,7 +131,7 @@ Example:
vddio-supply = <...>;
clock-frequency = <24000000>;
- clocks = <...>;
+ clocks = <&camera 1>;
clock-names = "mclk";
port {
@@ -135,7 +152,7 @@ Example:
vddio-supply = <...>;
clock-frequency = <24000000>;
- clocks = <...>;
+ clocks = <&camera 0>;
clock-names = "mclk";
port {
@@ -149,12 +166,15 @@ Example:
camera {
compatible = "samsung,fimc", "simple-bus";
- #address-cells = <1>;
- #size-cells = <1>;
- status = "okay";
-
+ clocks = <&clock 132>, <&clock 133>;
+ clock-names = "sclk_cam0", "sclk_cam1";
+ #clock-cells = <1>;
+ clock-output-names = "cam_mclk_a", "cam_mclk_b";
pinctrl-names = "default";
pinctrl-0 = <&cam_port_a_clk_active>;
+ status = "okay";
+ #address-cells = <1>;
+ #size-cells = <1>;
/* parallel camera ports */
parallel-ports {
--
1.7.9.5
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH v4 04/10] V4L: Add driver for s5k6a3 image sensor
[not found] ` <1392925237-31394-1-git-send-email-s.nawrocki-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org>
@ 2014-02-20 19:40 ` Sylwester Nawrocki
0 siblings, 0 replies; 20+ messages in thread
From: Sylwester Nawrocki @ 2014-02-20 19:40 UTC (permalink / raw)
To: linux-media-u79uwXL29TY76Z2rM5mHXA,
devicetree-u79uwXL29TY76Z2rM5mHXA
Cc: linux-samsung-soc-u79uwXL29TY76Z2rM5mHXA,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
robh+dt-DgEjT+Ai2ygdnm+yROfE0A, mark.rutland-5wv7dgnIgG8,
galak-sgV2jX0FEOL9JmXXK+q4OQ,
kyungmin.park-Sze3O3UU22JBDgjK7y7TUQ,
kgene.kim-Sze3O3UU22JBDgjK7y7TUQ, a.hajda-Sze3O3UU22JBDgjK7y7TUQ,
Sylwester Nawrocki
This patch adds subdev driver for Samsung S5K6A3 raw image sensor.
As it is intended at the moment to be used only with the Exynos
FIMC-IS (camera ISP) subsystem it is pretty minimal subdev driver.
It doesn't do any I2C communication since the sensor is controlled
by the ISP and its own firmware.
This driver, if needed, can be updated in future into a regular
subdev driver where the main CPU communicates with the sensor
directly.
Signed-off-by: Sylwester Nawrocki <s.nawrocki-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org>
Acked-by: Kyungmin Park <kyungmin.park-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org>
---
Changes since v3:
- clk_get() called moved from s_power() to driver probe() callback.
Changes since v1:
- added missing pm_runtime_disable(),
- removed subdev name overriding,
- s/S5K6A3_DEF_PIX/S5K6A3_DEFAULT_,
- merged patch adding v4l2-async API support,
- clock-frequency property is now optional and a default frequency
value will be used when it is missing, rather than bailing out,
- reset GPIO made mandatory as it is required for proper power
on/off sequences and all known boards use it,
- maximum image size is now 1412x1412 pixels, as specified in
in the S5K6A3YX datasheet.
- regulator_enable()/disable() used instead of the regulator bulk
API to ensure proper regulators enable/disable sequences.
Signed-off-by: Sylwester Nawrocki <s.nawrocki-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org>
---
drivers/media/i2c/Kconfig | 8 +
drivers/media/i2c/Makefile | 1 +
drivers/media/i2c/s5k6a3.c | 388 ++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 397 insertions(+)
create mode 100644 drivers/media/i2c/s5k6a3.c
diff --git a/drivers/media/i2c/Kconfig b/drivers/media/i2c/Kconfig
index 4aa9c531..ac2d5b7 100644
--- a/drivers/media/i2c/Kconfig
+++ b/drivers/media/i2c/Kconfig
@@ -579,6 +579,14 @@ config VIDEO_S5K6AA
This is a V4L2 sensor-level driver for Samsung S5K6AA(FX) 1.3M
camera sensor with an embedded SoC image signal processor.
+config VIDEO_S5K6A3
+ tristate "Samsung S5K6A3 sensor support"
+ depends on MEDIA_CAMERA_SUPPORT
+ depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API && OF
+ ---help---
+ This is a V4L2 sensor-level driver for Samsung S5K6A3 raw
+ camera sensor.
+
config VIDEO_S5K4ECGX
tristate "Samsung S5K4ECGX sensor support"
depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API
diff --git a/drivers/media/i2c/Makefile b/drivers/media/i2c/Makefile
index 48888ae..ab5aa34 100644
--- a/drivers/media/i2c/Makefile
+++ b/drivers/media/i2c/Makefile
@@ -66,6 +66,7 @@ obj-$(CONFIG_VIDEO_MT9V032) += mt9v032.o
obj-$(CONFIG_VIDEO_SR030PC30) += sr030pc30.o
obj-$(CONFIG_VIDEO_NOON010PC30) += noon010pc30.o
obj-$(CONFIG_VIDEO_S5K6AA) += s5k6aa.o
+obj-$(CONFIG_VIDEO_S5K6A3) += s5k6a3.o
obj-$(CONFIG_VIDEO_S5K4ECGX) += s5k4ecgx.o
obj-$(CONFIG_VIDEO_S5K5BAF) += s5k5baf.o
obj-$(CONFIG_VIDEO_S5C73M3) += s5c73m3/
diff --git a/drivers/media/i2c/s5k6a3.c b/drivers/media/i2c/s5k6a3.c
new file mode 100644
index 0000000..d0b52cd
--- /dev/null
+++ b/drivers/media/i2c/s5k6a3.c
@@ -0,0 +1,388 @@
+/*
+ * Samsung S5K6A3 image sensor driver
+ *
+ * Copyright (C) 2013 Samsung Electronics Co., Ltd.
+ * Author: Sylwester Nawrocki <s.nawrocki-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/errno.h>
+#include <linux/gpio.h>
+#include <linux/i2c.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of_gpio.h>
+#include <linux/pm_runtime.h>
+#include <linux/regulator/consumer.h>
+#include <linux/slab.h>
+#include <linux/videodev2.h>
+#include <media/v4l2-async.h>
+#include <media/v4l2-subdev.h>
+
+#define S5K6A3_SENSOR_MAX_WIDTH 1412
+#define S5K6A3_SENSOR_MAX_HEIGHT 1412
+#define S5K6A3_SENSOR_MIN_WIDTH 32
+#define S5K6A3_SENSOR_MIN_HEIGHT 32
+
+#define S5K6A3_DEFAULT_WIDTH 1296
+#define S5K6A3_DEFAULT_HEIGHT 732
+
+#define S5K6A3_DRV_NAME "S5K6A3"
+#define S5K6A3_CLK_NAME "extclk"
+#define S5K6A3_DEFAULT_CLK_FREQ 24000000U
+
+enum {
+ S5K6A3_SUPP_VDDA,
+ S5K6A3_SUPP_VDDIO,
+ S5K6A3_SUPP_AFVDD,
+ S5K6A3_NUM_SUPPLIES,
+};
+
+/**
+ * struct s5k6a3 - fimc-is sensor data structure
+ * @dev: pointer to this I2C client device structure
+ * @subdev: the image sensor's v4l2 subdev
+ * @pad: subdev media source pad
+ * @supplies: image sensor's voltage regulator supplies
+ * @gpio_reset: GPIO connected to the sensor's reset pin
+ * @lock: mutex protecting the structure's members below
+ * @format: media bus format at the sensor's source pad
+ */
+struct s5k6a3 {
+ struct device *dev;
+ struct v4l2_subdev subdev;
+ struct media_pad pad;
+ struct regulator_bulk_data supplies[S5K6A3_NUM_SUPPLIES];
+ int gpio_reset;
+ struct mutex lock;
+ struct v4l2_mbus_framefmt format;
+ struct clk *clock;
+ u32 clock_frequency;
+ int power_count;
+};
+
+static const char * const s5k6a3_supply_names[] = {
+ [S5K6A3_SUPP_VDDA] = "svdda",
+ [S5K6A3_SUPP_VDDIO] = "svddio",
+ [S5K6A3_SUPP_AFVDD] = "afvdd",
+};
+
+static inline struct s5k6a3 *sd_to_s5k6a3(struct v4l2_subdev *sd)
+{
+ return container_of(sd, struct s5k6a3, subdev);
+}
+
+static const struct v4l2_mbus_framefmt s5k6a3_formats[] = {
+ {
+ .code = V4L2_MBUS_FMT_SGRBG10_1X10,
+ .colorspace = V4L2_COLORSPACE_SRGB,
+ .field = V4L2_FIELD_NONE,
+ }
+};
+
+static const struct v4l2_mbus_framefmt *find_sensor_format(
+ struct v4l2_mbus_framefmt *mf)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(s5k6a3_formats); i++)
+ if (mf->code == s5k6a3_formats[i].code)
+ return &s5k6a3_formats[i];
+
+ return &s5k6a3_formats[0];
+}
+
+static int s5k6a3_enum_mbus_code(struct v4l2_subdev *sd,
+ struct v4l2_subdev_fh *fh,
+ struct v4l2_subdev_mbus_code_enum *code)
+{
+ if (code->index >= ARRAY_SIZE(s5k6a3_formats))
+ return -EINVAL;
+
+ code->code = s5k6a3_formats[code->index].code;
+ return 0;
+}
+
+static void s5k6a3_try_format(struct v4l2_mbus_framefmt *mf)
+{
+ const struct v4l2_mbus_framefmt *fmt;
+
+ fmt = find_sensor_format(mf);
+ mf->code = fmt->code;
+ v4l_bound_align_image(&mf->width, S5K6A3_SENSOR_MIN_WIDTH,
+ S5K6A3_SENSOR_MAX_WIDTH, 0,
+ &mf->height, S5K6A3_SENSOR_MIN_HEIGHT,
+ S5K6A3_SENSOR_MAX_HEIGHT, 0, 0);
+}
+
+static struct v4l2_mbus_framefmt *__s5k6a3_get_format(
+ struct s5k6a3 *sensor, struct v4l2_subdev_fh *fh,
+ u32 pad, enum v4l2_subdev_format_whence which)
+{
+ if (which == V4L2_SUBDEV_FORMAT_TRY)
+ return fh ? v4l2_subdev_get_try_format(fh, pad) : NULL;
+
+ return &sensor->format;
+}
+
+static int s5k6a3_set_fmt(struct v4l2_subdev *sd,
+ struct v4l2_subdev_fh *fh,
+ struct v4l2_subdev_format *fmt)
+{
+ struct s5k6a3 *sensor = sd_to_s5k6a3(sd);
+ struct v4l2_mbus_framefmt *mf;
+
+ s5k6a3_try_format(&fmt->format);
+
+ mf = __s5k6a3_get_format(sensor, fh, fmt->pad, fmt->which);
+ if (mf) {
+ mutex_lock(&sensor->lock);
+ if (fmt->which == V4L2_SUBDEV_FORMAT_ACTIVE)
+ *mf = fmt->format;
+ mutex_unlock(&sensor->lock);
+ }
+ return 0;
+}
+
+static int s5k6a3_get_fmt(struct v4l2_subdev *sd,
+ struct v4l2_subdev_fh *fh,
+ struct v4l2_subdev_format *fmt)
+{
+ struct s5k6a3 *sensor = sd_to_s5k6a3(sd);
+ struct v4l2_mbus_framefmt *mf;
+
+ mf = __s5k6a3_get_format(sensor, fh, fmt->pad, fmt->which);
+
+ mutex_lock(&sensor->lock);
+ fmt->format = *mf;
+ mutex_unlock(&sensor->lock);
+ return 0;
+}
+
+static struct v4l2_subdev_pad_ops s5k6a3_pad_ops = {
+ .enum_mbus_code = s5k6a3_enum_mbus_code,
+ .get_fmt = s5k6a3_get_fmt,
+ .set_fmt = s5k6a3_set_fmt,
+};
+
+static int s5k6a3_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
+{
+ struct v4l2_mbus_framefmt *format = v4l2_subdev_get_try_format(fh, 0);
+
+ *format = s5k6a3_formats[0];
+ format->width = S5K6A3_DEFAULT_WIDTH;
+ format->height = S5K6A3_DEFAULT_HEIGHT;
+
+ return 0;
+}
+
+static const struct v4l2_subdev_internal_ops s5k6a3_sd_internal_ops = {
+ .open = s5k6a3_open,
+};
+
+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)
+ return ret;
+
+ ret = regulator_enable(sensor->supplies[i].consumer);
+ if (ret < 0)
+ goto error_rpm_put;
+
+ ret = clk_prepare_enable(sensor->clock);
+ if (ret < 0)
+ goto error_reg_dis;
+
+ for (i++; i < S5K6A3_NUM_SUPPLIES; i++) {
+ ret = regulator_enable(sensor->supplies[i].consumer);
+ if (ret < 0)
+ goto error_reg_dis;
+ }
+
+ gpio_set_value(sensor->gpio_reset, 1);
+ usleep_range(600, 800);
+ gpio_set_value(sensor->gpio_reset, 0);
+ usleep_range(600, 800);
+ gpio_set_value(sensor->gpio_reset, 1);
+
+ /* Delay needed for the sensor initialization */
+ msleep(20);
+ return 0;
+
+error_reg_dis:
+ for (--i; i >= 0; --i)
+ regulator_disable(sensor->supplies[i].consumer);
+error_rpm_put:
+ pm_runtime_put(sensor->dev);
+ return ret;
+}
+
+static int __s5k6a3_power_off(struct s5k6a3 *sensor)
+{
+ int i;
+
+ gpio_set_value(sensor->gpio_reset, 0);
+
+ for (i = S5K6A3_NUM_SUPPLIES - 1; i >= 0; i--)
+ regulator_disable(sensor->supplies[i].consumer);
+
+ clk_disable_unprepare(sensor->clock);
+ pm_runtime_put(sensor->dev);
+ return 0;
+}
+
+static int s5k6a3_s_power(struct v4l2_subdev *sd, int on)
+{
+ struct s5k6a3 *sensor = sd_to_s5k6a3(sd);
+ int ret = 0;
+
+ mutex_lock(&sensor->lock);
+
+ if (sensor->power_count == !on) {
+ if (on)
+ ret = __s5k6a3_power_on(sensor);
+ else
+ ret = __s5k6a3_power_off(sensor);
+
+ if (ret == 0)
+ sensor->power_count += on ? 1 : -1;
+ }
+
+ mutex_unlock(&sensor->lock);
+ return ret;
+}
+
+static struct v4l2_subdev_core_ops s5k6a3_core_ops = {
+ .s_power = s5k6a3_s_power,
+};
+
+static struct v4l2_subdev_ops s5k6a3_subdev_ops = {
+ .core = &s5k6a3_core_ops,
+ .pad = &s5k6a3_pad_ops,
+};
+
+static int s5k6a3_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct device *dev = &client->dev;
+ struct s5k6a3 *sensor;
+ struct v4l2_subdev *sd;
+ int gpio, i, ret;
+
+ sensor = devm_kzalloc(dev, sizeof(*sensor), GFP_KERNEL);
+ if (!sensor)
+ return -ENOMEM;
+
+ mutex_init(&sensor->lock);
+ sensor->gpio_reset = -EINVAL;
+ sensor->clock = ERR_PTR(-EINVAL);
+ sensor->dev = dev;
+
+ sensor->clock = devm_clk_get(sensor->dev, S5K6A3_CLK_NAME);
+ if (IS_ERR(sensor->clock))
+ return PTR_ERR(sensor->clock);
+
+ gpio = of_get_gpio_flags(dev->of_node, 0, NULL);
+ if (!gpio_is_valid(gpio))
+ return gpio;
+
+ ret = devm_gpio_request_one(dev, gpio, GPIOF_OUT_INIT_LOW,
+ S5K6A3_DRV_NAME);
+ if (ret < 0)
+ return ret;
+
+ sensor->gpio_reset = gpio;
+
+ 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];
+
+ ret = devm_regulator_bulk_get(&client->dev, S5K6A3_NUM_SUPPLIES,
+ sensor->supplies);
+ if (ret < 0)
+ return ret;
+
+ sd = &sensor->subdev;
+ v4l2_i2c_subdev_init(sd, client, &s5k6a3_subdev_ops);
+ sensor->subdev.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
+
+ sensor->format.code = s5k6a3_formats[0].code;
+ sensor->format.width = S5K6A3_DEFAULT_WIDTH;
+ sensor->format.height = S5K6A3_DEFAULT_HEIGHT;
+
+ sensor->pad.flags = MEDIA_PAD_FL_SOURCE;
+ ret = media_entity_init(&sd->entity, 1, &sensor->pad, 0);
+ if (ret < 0)
+ return ret;
+
+ pm_runtime_no_callbacks(dev);
+ pm_runtime_enable(dev);
+
+ ret = v4l2_async_register_subdev(sd);
+
+ if (ret < 0) {
+ pm_runtime_disable(&client->dev);
+ media_entity_cleanup(&sd->entity);
+ }
+
+ return ret;
+}
+
+static int s5k6a3_remove(struct i2c_client *client)
+{
+ struct v4l2_subdev *sd = i2c_get_clientdata(client);
+
+ pm_runtime_disable(&client->dev);
+ v4l2_async_unregister_subdev(sd);
+ media_entity_cleanup(&sd->entity);
+ return 0;
+}
+
+static const struct i2c_device_id s5k6a3_ids[] = {
+ { }
+};
+
+#ifdef CONFIG_OF
+static const struct of_device_id s5k6a3_of_match[] = {
+ { .compatible = "samsung,s5k6a3" },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, s5k6a3_of_match);
+#endif
+
+static struct i2c_driver s5k6a3_driver = {
+ .driver = {
+ .of_match_table = of_match_ptr(s5k6a3_of_match),
+ .name = S5K6A3_DRV_NAME,
+ .owner = THIS_MODULE,
+ },
+ .probe = s5k6a3_probe,
+ .remove = s5k6a3_remove,
+ .id_table = s5k6a3_ids,
+};
+
+module_i2c_driver(s5k6a3_driver);
+
+MODULE_DESCRIPTION("S5K6A3 image sensor subdev driver");
+MODULE_AUTHOR("Sylwester Nawrocki <s.nawrocki-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org>");
+MODULE_LICENSE("GPL v2");
--
1.7.9.5
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH v4 05/10] V4L: s5c73m3: Add device tree support
2014-02-20 19:40 [PATCH v4 00/10] Add device tree support for Exynos4 SoC camera subsystem Sylwester Nawrocki
` (4 preceding siblings ...)
[not found] ` <1392925237-31394-1-git-send-email-s.nawrocki-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org>
@ 2014-02-20 19:40 ` Sylwester Nawrocki
2014-02-20 19:40 ` [PATCH v4 06/10] exynos4-is: Use external s5k6a3 sensor driver Sylwester Nawrocki
` (4 subsequent siblings)
10 siblings, 0 replies; 20+ messages in thread
From: Sylwester Nawrocki @ 2014-02-20 19:40 UTC (permalink / raw)
To: linux-media, devicetree
Cc: linux-samsung-soc, linux-arm-kernel, robh+dt, mark.rutland, galak,
kyungmin.park, kgene.kim, a.hajda, Sylwester Nawrocki
This patch adds the V4L2 asynchronous subdev registration and
device tree support. Common clock API is used to control the
sensor master clock from within the subdev.
Signed-off-by: Andrzej Hajda <a.hajda@samsung.com>
Signed-off-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
Acked-by: Kyungmin Park <kyungmin.park@samsung.com>
---
Changes since v3:
- move clk_get from subdev s_power() to driver probe() callback and
make it devm_clk_get(),
- pass any errors from dev_clk_get() through, rather than overwriting
with EPROBE_DEFER. Patch [1] is required for things to work correctly
after this change.
[1] http://www.spinics.net/lists/arm-kernel/msg306072.html
---
drivers/media/i2c/s5c73m3/s5c73m3-core.c | 207 ++++++++++++++++++++++--------
drivers/media/i2c/s5c73m3/s5c73m3-spi.c | 6 +
drivers/media/i2c/s5c73m3/s5c73m3.h | 4 +
3 files changed, 167 insertions(+), 50 deletions(-)
diff --git a/drivers/media/i2c/s5c73m3/s5c73m3-core.c b/drivers/media/i2c/s5c73m3/s5c73m3-core.c
index e7f555c..a445930 100644
--- a/drivers/media/i2c/s5c73m3/s5c73m3-core.c
+++ b/drivers/media/i2c/s5c73m3/s5c73m3-core.c
@@ -15,7 +15,7 @@
* GNU General Public License for more details.
*/
-#include <linux/sizes.h>
+#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/firmware.h>
#include <linux/gpio.h>
@@ -23,7 +23,9 @@
#include <linux/init.h>
#include <linux/media.h>
#include <linux/module.h>
+#include <linux/of_gpio.h>
#include <linux/regulator/consumer.h>
+#include <linux/sizes.h>
#include <linux/slab.h>
#include <linux/spi/spi.h>
#include <linux/videodev2.h>
@@ -33,6 +35,7 @@
#include <media/v4l2-subdev.h>
#include <media/v4l2-mediabus.h>
#include <media/s5c73m3.h>
+#include <media/v4l2-of.h>
#include "s5c73m3.h"
@@ -46,6 +49,8 @@ static int update_fw;
module_param(update_fw, int, 0644);
#define S5C73M3_EMBEDDED_DATA_MAXLEN SZ_4K
+#define S5C73M3_MIPI_DATA_LANES 4
+#define S5C73M3_CLK_NAME "cis_extclk"
static const char * const s5c73m3_supply_names[S5C73M3_MAX_SUPPLIES] = {
"vdd-int", /* Digital Core supply (1.2V), CAM_ISP_CORE_1.2V */
@@ -1355,9 +1360,20 @@ static int __s5c73m3_power_on(struct s5c73m3 *state)
for (i = 0; i < S5C73M3_MAX_SUPPLIES; i++) {
ret = regulator_enable(state->supplies[i].consumer);
if (ret)
- goto err;
+ 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;
+
+ v4l2_dbg(1, s5c73m3_dbg, &state->oif_sd, "clock frequency: %ld\n",
+ clk_get_rate(state->clock));
+
s5c73m3_gpio_deassert(state, STBY);
usleep_range(100, 200);
@@ -1365,7 +1381,8 @@ static int __s5c73m3_power_on(struct s5c73m3 *state)
usleep_range(50, 100);
return 0;
-err:
+
+err_reg_dis:
for (--i; i >= 0; i--)
regulator_disable(state->supplies[i].consumer);
return ret;
@@ -1380,6 +1397,9 @@ static int __s5c73m3_power_off(struct s5c73m3 *state)
if (s5c73m3_gpio_assert(state, STBY))
usleep_range(100, 200);
+
+ clk_disable_unprepare(state->clock);
+
state->streaming = 0;
state->isp_ready = 0;
@@ -1388,6 +1408,7 @@ static int __s5c73m3_power_off(struct s5c73m3 *state)
if (ret)
goto err;
}
+
return 0;
err:
for (++i; i < S5C73M3_MAX_SUPPLIES; i++) {
@@ -1396,6 +1417,8 @@ err:
v4l2_err(&state->oif_sd, "Failed to reenable %s: %d\n",
state->supplies[i].supply, r);
}
+
+ clk_prepare_enable(state->clock);
return ret;
}
@@ -1451,17 +1474,6 @@ static int s5c73m3_oif_registered(struct v4l2_subdev *sd)
S5C73M3_JPEG_PAD, &state->oif_sd.entity, OIF_JPEG_PAD,
MEDIA_LNK_FL_IMMUTABLE | MEDIA_LNK_FL_ENABLED);
- mutex_lock(&state->lock);
- ret = __s5c73m3_power_on(state);
- if (ret == 0)
- s5c73m3_get_fw_version(state);
-
- __s5c73m3_power_off(state);
- mutex_unlock(&state->lock);
-
- v4l2_dbg(1, s5c73m3_dbg, sd, "%s: Booting %s (%d)\n",
- __func__, ret ? "failed" : "succeeded", ret);
-
return ret;
}
@@ -1519,41 +1531,112 @@ static const struct v4l2_subdev_ops oif_subdev_ops = {
.video = &s5c73m3_oif_video_ops,
};
-static int s5c73m3_configure_gpios(struct s5c73m3 *state,
- const struct s5c73m3_platform_data *pdata)
+static int s5c73m3_configure_gpios(struct s5c73m3 *state)
+{
+ static const char * const gpio_names[] = {
+ "S5C73M3_STBY", "S5C73M3_RST"
+ };
+ struct i2c_client *c = state->i2c_client;
+ struct s5c73m3_gpio *g = state->gpio;
+ int ret, i;
+
+ for (i = 0; i < GPIO_NUM; ++i) {
+ unsigned int flags = GPIOF_DIR_OUT;
+ if (g[i].level)
+ flags |= GPIOF_INIT_HIGH;
+ ret = devm_gpio_request_one(&c->dev, g[i].gpio, flags,
+ gpio_names[i]);
+ if (ret) {
+ v4l2_err(c, "failed to request gpio %s\n",
+ gpio_names[i]);
+ return ret;
+ }
+ }
+ return 0;
+}
+
+static int s5c73m3_parse_gpios(struct s5c73m3 *state)
+{
+ static const char * const prop_names[] = {
+ "standby-gpios", "xshutdown-gpios",
+ };
+ struct device *dev = &state->i2c_client->dev;
+ struct device_node *node = dev->of_node;
+ int ret, i;
+
+ for (i = 0; i < GPIO_NUM; ++i) {
+ enum of_gpio_flags of_flags;
+
+ ret = of_get_named_gpio_flags(node, prop_names[i],
+ 0, &of_flags);
+ if (ret < 0) {
+ dev_err(dev, "failed to parse %s DT property\n",
+ prop_names[i]);
+ return -EINVAL;
+ }
+ state->gpio[i].gpio = ret;
+ state->gpio[i].level = !(of_flags & OF_GPIO_ACTIVE_LOW);
+ }
+ return 0;
+}
+
+static int s5c73m3_get_platform_data(struct s5c73m3 *state)
{
struct device *dev = &state->i2c_client->dev;
- const struct s5c73m3_gpio *gpio;
- unsigned long flags;
+ const struct s5c73m3_platform_data *pdata = dev->platform_data;
+ struct device_node *node = dev->of_node;
+ struct device_node *node_ep;
+ struct v4l2_of_endpoint ep;
int ret;
- state->gpio[STBY].gpio = -EINVAL;
- state->gpio[RST].gpio = -EINVAL;
+ if (!node) {
+ if (!pdata) {
+ dev_err(dev, "Platform data not specified\n");
+ return -EINVAL;
+ }
- gpio = &pdata->gpio_stby;
- if (gpio_is_valid(gpio->gpio)) {
- flags = (gpio->level ? GPIOF_OUT_INIT_HIGH : GPIOF_OUT_INIT_LOW)
- | GPIOF_EXPORT;
- ret = devm_gpio_request_one(dev, gpio->gpio, flags,
- "S5C73M3_STBY");
- if (ret < 0)
- return ret;
+ state->mclk_frequency = pdata->mclk_frequency;
+ state->gpio[STBY] = pdata->gpio_stby;
+ state->gpio[RST] = pdata->gpio_reset;
+ return 0;
+ }
+
+ state->clock = devm_clk_get(dev, S5C73M3_CLK_NAME);
+ if (IS_ERR(state->clock))
+ return PTR_ERR(state->clock);
- state->gpio[STBY] = *gpio;
+ 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);
}
- gpio = &pdata->gpio_reset;
- if (gpio_is_valid(gpio->gpio)) {
- flags = (gpio->level ? GPIOF_OUT_INIT_HIGH : GPIOF_OUT_INIT_LOW)
- | GPIOF_EXPORT;
- ret = devm_gpio_request_one(dev, gpio->gpio, flags,
- "S5C73M3_RST");
- if (ret < 0)
- return ret;
+ ret = s5c73m3_parse_gpios(state);
+ if (ret < 0)
+ return -EINVAL;
- state->gpio[RST] = *gpio;
+ node_ep = v4l2_of_get_next_endpoint(node, NULL);
+ if (!node_ep) {
+ dev_warn(dev, "no endpoint defined for node: %s\n",
+ node->full_name);
+ return 0;
}
+ v4l2_of_parse_endpoint(node_ep, &ep);
+ of_node_put(node_ep);
+
+ if (ep.bus_type != V4L2_MBUS_CSI2) {
+ dev_err(dev, "unsupported bus type\n");
+ return -EINVAL;
+ }
+ /*
+ * Number of MIPI CSI-2 data lanes is currently not configurable,
+ * always a default value of 4 lanes is used.
+ */
+ if (ep.bus.mipi_csi2.num_data_lanes != S5C73M3_MIPI_DATA_LANES)
+ dev_info(dev, "falling back to 4 MIPI CSI-2 data lanes\n");
+
return 0;
}
@@ -1561,21 +1644,20 @@ static int s5c73m3_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct device *dev = &client->dev;
- const struct s5c73m3_platform_data *pdata = client->dev.platform_data;
struct v4l2_subdev *sd;
struct v4l2_subdev *oif_sd;
struct s5c73m3 *state;
int ret, i;
- if (pdata == NULL) {
- dev_err(&client->dev, "Platform data not specified\n");
- return -EINVAL;
- }
-
state = devm_kzalloc(dev, sizeof(*state), GFP_KERNEL);
if (!state)
return -ENOMEM;
+ state->i2c_client = client;
+ ret = s5c73m3_get_platform_data(state);
+ if (ret < 0)
+ return ret;
+
mutex_init(&state->lock);
sd = &state->sensor_sd;
oif_sd = &state->oif_sd;
@@ -1613,11 +1695,7 @@ static int s5c73m3_probe(struct i2c_client *client,
if (ret < 0)
return ret;
- state->mclk_frequency = pdata->mclk_frequency;
- state->bus_type = pdata->bus_type;
- state->i2c_client = client;
-
- ret = s5c73m3_configure_gpios(state, pdata);
+ ret = s5c73m3_configure_gpios(state);
if (ret)
goto out_err;
@@ -1651,9 +1729,29 @@ static int s5c73m3_probe(struct i2c_client *client,
if (ret < 0)
goto out_err;
+ oif_sd->dev = dev;
+
+ ret = __s5c73m3_power_on(state);
+ if (ret < 0)
+ goto out_err1;
+
+ ret = s5c73m3_get_fw_version(state);
+ __s5c73m3_power_off(state);
+
+ if (ret < 0) {
+ dev_err(dev, "Device detection failed: %d\n", ret);
+ goto out_err1;
+ }
+
+ ret = v4l2_async_register_subdev(oif_sd);
+ if (ret < 0)
+ goto out_err1;
+
v4l2_info(sd, "%s: completed successfully\n", __func__);
return 0;
+out_err1:
+ s5c73m3_unregister_spi_driver(state);
out_err:
media_entity_cleanup(&sd->entity);
return ret;
@@ -1665,7 +1763,7 @@ static int s5c73m3_remove(struct i2c_client *client)
struct s5c73m3 *state = oif_sd_to_s5c73m3(oif_sd);
struct v4l2_subdev *sensor_sd = &state->sensor_sd;
- v4l2_device_unregister_subdev(oif_sd);
+ v4l2_async_unregister_subdev(oif_sd);
v4l2_ctrl_handler_free(oif_sd->ctrl_handler);
media_entity_cleanup(&oif_sd->entity);
@@ -1684,8 +1782,17 @@ static const struct i2c_device_id s5c73m3_id[] = {
};
MODULE_DEVICE_TABLE(i2c, s5c73m3_id);
+#ifdef CONFIG_OF
+static const struct of_device_id s5c73m3_of_match[] = {
+ { .compatible = "samsung,s5c73m3" },
+ { }
+};
+MODULE_DEVICE_TABLE(of, s5c73m3_of_match);
+#endif
+
static struct i2c_driver s5c73m3_i2c_driver = {
.driver = {
+ .of_match_table = of_match_ptr(s5c73m3_of_match),
.name = DRIVER_NAME,
},
.probe = s5c73m3_probe,
diff --git a/drivers/media/i2c/s5c73m3/s5c73m3-spi.c b/drivers/media/i2c/s5c73m3/s5c73m3-spi.c
index 8079e26..f60b265 100644
--- a/drivers/media/i2c/s5c73m3/s5c73m3-spi.c
+++ b/drivers/media/i2c/s5c73m3/s5c73m3-spi.c
@@ -27,6 +27,11 @@
#define S5C73M3_SPI_DRV_NAME "S5C73M3-SPI"
+static const struct of_device_id s5c73m3_spi_ids[] = {
+ { .compatible = "samsung,s5c73m3" },
+ { }
+};
+
enum spi_direction {
SPI_DIR_RX,
SPI_DIR_TX
@@ -146,6 +151,7 @@ int s5c73m3_register_spi_driver(struct s5c73m3 *state)
spidrv->driver.name = S5C73M3_SPI_DRV_NAME;
spidrv->driver.bus = &spi_bus_type;
spidrv->driver.owner = THIS_MODULE;
+ spidrv->driver.of_match_table = s5c73m3_spi_ids;
return spi_register_driver(spidrv);
}
diff --git a/drivers/media/i2c/s5c73m3/s5c73m3.h b/drivers/media/i2c/s5c73m3/s5c73m3.h
index 9dfa516..9656b67 100644
--- a/drivers/media/i2c/s5c73m3/s5c73m3.h
+++ b/drivers/media/i2c/s5c73m3/s5c73m3.h
@@ -17,6 +17,7 @@
#ifndef S5C73M3_H_
#define S5C73M3_H_
+#include <linux/clk.h>
#include <linux/kernel.h>
#include <linux/regulator/consumer.h>
#include <media/v4l2-common.h>
@@ -321,6 +322,7 @@ enum s5c73m3_oif_pads {
#define S5C73M3_MAX_SUPPLIES 6
+#define S5C73M3_DEFAULT_MCLK_FREQ 24000000U
struct s5c73m3_ctrls {
struct v4l2_ctrl_handler handler;
@@ -391,6 +393,8 @@ struct s5c73m3 {
struct regulator_bulk_data supplies[S5C73M3_MAX_SUPPLIES];
struct s5c73m3_gpio gpio[GPIO_NUM];
+ struct clk *clock;
+
/* External master clock frequency */
u32 mclk_frequency;
/* Video bus type - MIPI-CSI2/parallel */
--
1.7.9.5
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH v4 06/10] exynos4-is: Use external s5k6a3 sensor driver
2014-02-20 19:40 [PATCH v4 00/10] Add device tree support for Exynos4 SoC camera subsystem Sylwester Nawrocki
` (5 preceding siblings ...)
2014-02-20 19:40 ` [PATCH v4 05/10] V4L: s5c73m3: Add device tree support Sylwester Nawrocki
@ 2014-02-20 19:40 ` Sylwester Nawrocki
2014-02-20 19:40 ` [PATCH v4 07/10] exynos4-is: Add clock provider for the SCLK_CAM clock outputs Sylwester Nawrocki
` (3 subsequent siblings)
10 siblings, 0 replies; 20+ messages in thread
From: Sylwester Nawrocki @ 2014-02-20 19:40 UTC (permalink / raw)
To: linux-media, devicetree
Cc: linux-samsung-soc, linux-arm-kernel, robh+dt, mark.rutland, galak,
kyungmin.park, kgene.kim, a.hajda, Sylwester Nawrocki
This patch removes the common fimc-is-sensor driver for image sensors
that are normally controlled by the FIMC-IS firmware. The FIMC-IS
driver now contains only a table of properties specific to each sensor.
The sensor properties required for the ISP's firmware are parsed from
device tree and retrieved from the internal table, which is selected
based on the compatible property of an image sensor.
To use the Exynos4x12 internal ISP the S5K6A3 sensor driver (drivers/
media/i2c/s5k6a3.c) is now required.
Signed-off-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
Acked-by: Kyungmin Park <kyungmin.park@samsung.com>
---
drivers/media/platform/exynos4-is/fimc-is-regs.c | 2 +-
drivers/media/platform/exynos4-is/fimc-is-sensor.c | 285 +-------------------
drivers/media/platform/exynos4-is/fimc-is-sensor.h | 49 +---
drivers/media/platform/exynos4-is/fimc-is.c | 97 +++----
drivers/media/platform/exynos4-is/fimc-is.h | 4 +-
5 files changed, 57 insertions(+), 380 deletions(-)
diff --git a/drivers/media/platform/exynos4-is/fimc-is-regs.c b/drivers/media/platform/exynos4-is/fimc-is-regs.c
index 2628733..5c7bd2a 100644
--- a/drivers/media/platform/exynos4-is/fimc-is-regs.c
+++ b/drivers/media/platform/exynos4-is/fimc-is-regs.c
@@ -112,7 +112,7 @@ void fimc_is_hw_set_sensor_num(struct fimc_is *is)
mcuctl_write(IH_REPLY_DONE, is, MCUCTL_REG_ISSR(0));
mcuctl_write(is->sensor_index, is, MCUCTL_REG_ISSR(1));
mcuctl_write(IHC_GET_SENSOR_NUM, is, MCUCTL_REG_ISSR(2));
- mcuctl_write(FIMC_IS_SENSOR_NUM, is, MCUCTL_REG_ISSR(3));
+ mcuctl_write(FIMC_IS_SENSORS_NUM, is, MCUCTL_REG_ISSR(3));
}
void fimc_is_hw_close_sensor(struct fimc_is *is, unsigned int index)
diff --git a/drivers/media/platform/exynos4-is/fimc-is-sensor.c b/drivers/media/platform/exynos4-is/fimc-is-sensor.c
index 6647421..10e82e2 100644
--- a/drivers/media/platform/exynos4-is/fimc-is-sensor.c
+++ b/drivers/media/platform/exynos4-is/fimc-is-sensor.c
@@ -2,276 +2,21 @@
* Samsung EXYNOS4x12 FIMC-IS (Imaging Subsystem) driver
*
* Copyright (C) 2013 Samsung Electronics Co., Ltd.
- *
* Author: Sylwester Nawrocki <s.nawrocki@samsung.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
-#include <linux/delay.h>
-#include <linux/device.h>
-#include <linux/errno.h>
-#include <linux/gpio.h>
-#include <linux/i2c.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/of_gpio.h>
-#include <linux/pm_runtime.h>
-#include <linux/regulator/consumer.h>
-#include <linux/slab.h>
-#include <media/v4l2-subdev.h>
-#include "fimc-is.h"
#include "fimc-is-sensor.h"
-#define DRIVER_NAME "FIMC-IS-SENSOR"
-
-static const char * const sensor_supply_names[] = {
- "svdda",
- "svddio",
-};
-
-static const struct v4l2_mbus_framefmt fimc_is_sensor_formats[] = {
- {
- .code = V4L2_MBUS_FMT_SGRBG10_1X10,
- .colorspace = V4L2_COLORSPACE_SRGB,
- .field = V4L2_FIELD_NONE,
- }
-};
-
-static const struct v4l2_mbus_framefmt *find_sensor_format(
- struct v4l2_mbus_framefmt *mf)
-{
- int i;
-
- for (i = 0; i < ARRAY_SIZE(fimc_is_sensor_formats); i++)
- if (mf->code == fimc_is_sensor_formats[i].code)
- return &fimc_is_sensor_formats[i];
-
- return &fimc_is_sensor_formats[0];
-}
-
-static int fimc_is_sensor_enum_mbus_code(struct v4l2_subdev *sd,
- struct v4l2_subdev_fh *fh,
- struct v4l2_subdev_mbus_code_enum *code)
-{
- if (code->index >= ARRAY_SIZE(fimc_is_sensor_formats))
- return -EINVAL;
-
- code->code = fimc_is_sensor_formats[code->index].code;
- return 0;
-}
-
-static void fimc_is_sensor_try_format(struct fimc_is_sensor *sensor,
- struct v4l2_mbus_framefmt *mf)
-{
- const struct sensor_drv_data *dd = sensor->drvdata;
- const struct v4l2_mbus_framefmt *fmt;
-
- fmt = find_sensor_format(mf);
- mf->code = fmt->code;
- v4l_bound_align_image(&mf->width, 16 + 8, dd->width, 0,
- &mf->height, 12 + 8, dd->height, 0, 0);
-}
-
-static struct v4l2_mbus_framefmt *__fimc_is_sensor_get_format(
- struct fimc_is_sensor *sensor, struct v4l2_subdev_fh *fh,
- u32 pad, enum v4l2_subdev_format_whence which)
-{
- if (which == V4L2_SUBDEV_FORMAT_TRY)
- return fh ? v4l2_subdev_get_try_format(fh, pad) : NULL;
-
- return &sensor->format;
-}
-
-static int fimc_is_sensor_set_fmt(struct v4l2_subdev *sd,
- struct v4l2_subdev_fh *fh,
- struct v4l2_subdev_format *fmt)
-{
- struct fimc_is_sensor *sensor = sd_to_fimc_is_sensor(sd);
- struct v4l2_mbus_framefmt *mf;
-
- fimc_is_sensor_try_format(sensor, &fmt->format);
-
- mf = __fimc_is_sensor_get_format(sensor, fh, fmt->pad, fmt->which);
- if (mf) {
- mutex_lock(&sensor->lock);
- if (fmt->which == V4L2_SUBDEV_FORMAT_ACTIVE)
- *mf = fmt->format;
- mutex_unlock(&sensor->lock);
- }
- return 0;
-}
-
-static int fimc_is_sensor_get_fmt(struct v4l2_subdev *sd,
- struct v4l2_subdev_fh *fh,
- struct v4l2_subdev_format *fmt)
-{
- struct fimc_is_sensor *sensor = sd_to_fimc_is_sensor(sd);
- struct v4l2_mbus_framefmt *mf;
-
- mf = __fimc_is_sensor_get_format(sensor, fh, fmt->pad, fmt->which);
-
- mutex_lock(&sensor->lock);
- fmt->format = *mf;
- mutex_unlock(&sensor->lock);
- return 0;
-}
-
-static struct v4l2_subdev_pad_ops fimc_is_sensor_pad_ops = {
- .enum_mbus_code = fimc_is_sensor_enum_mbus_code,
- .get_fmt = fimc_is_sensor_get_fmt,
- .set_fmt = fimc_is_sensor_set_fmt,
-};
-
-static int fimc_is_sensor_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
-{
- struct v4l2_mbus_framefmt *format = v4l2_subdev_get_try_format(fh, 0);
-
- *format = fimc_is_sensor_formats[0];
- format->width = FIMC_IS_SENSOR_DEF_PIX_WIDTH;
- format->height = FIMC_IS_SENSOR_DEF_PIX_HEIGHT;
-
- return 0;
-}
-
-static const struct v4l2_subdev_internal_ops fimc_is_sensor_sd_internal_ops = {
- .open = fimc_is_sensor_open,
-};
-
-static int fimc_is_sensor_s_power(struct v4l2_subdev *sd, int on)
-{
- struct fimc_is_sensor *sensor = sd_to_fimc_is_sensor(sd);
- int gpio = sensor->gpio_reset;
- int ret;
-
- if (on) {
- ret = pm_runtime_get(sensor->dev);
- if (ret < 0)
- return ret;
-
- ret = regulator_bulk_enable(SENSOR_NUM_SUPPLIES,
- sensor->supplies);
- if (ret < 0) {
- pm_runtime_put(sensor->dev);
- return ret;
- }
- if (gpio_is_valid(gpio)) {
- gpio_set_value(gpio, 1);
- usleep_range(600, 800);
- gpio_set_value(gpio, 0);
- usleep_range(10000, 11000);
- gpio_set_value(gpio, 1);
- }
-
- /* A delay needed for the sensor initialization. */
- msleep(20);
- } else {
- if (gpio_is_valid(gpio))
- gpio_set_value(gpio, 0);
-
- ret = regulator_bulk_disable(SENSOR_NUM_SUPPLIES,
- sensor->supplies);
- if (!ret)
- pm_runtime_put(sensor->dev);
- }
-
- pr_info("%s:%d: on: %d, ret: %d\n", __func__, __LINE__, on, ret);
-
- return ret;
-}
-
-static struct v4l2_subdev_core_ops fimc_is_sensor_core_ops = {
- .s_power = fimc_is_sensor_s_power,
-};
-
-static struct v4l2_subdev_ops fimc_is_sensor_subdev_ops = {
- .core = &fimc_is_sensor_core_ops,
- .pad = &fimc_is_sensor_pad_ops,
-};
-
-static const struct of_device_id fimc_is_sensor_of_match[];
-
-static int fimc_is_sensor_probe(struct i2c_client *client,
- const struct i2c_device_id *id)
-{
- struct device *dev = &client->dev;
- struct fimc_is_sensor *sensor;
- const struct of_device_id *of_id;
- struct v4l2_subdev *sd;
- int gpio, i, ret;
-
- sensor = devm_kzalloc(dev, sizeof(*sensor), GFP_KERNEL);
- if (!sensor)
- return -ENOMEM;
-
- mutex_init(&sensor->lock);
- sensor->gpio_reset = -EINVAL;
-
- gpio = of_get_gpio_flags(dev->of_node, 0, NULL);
- if (gpio_is_valid(gpio)) {
- ret = devm_gpio_request_one(dev, gpio, GPIOF_OUT_INIT_LOW,
- DRIVER_NAME);
- if (ret < 0)
- return ret;
- }
- sensor->gpio_reset = gpio;
-
- for (i = 0; i < SENSOR_NUM_SUPPLIES; i++)
- sensor->supplies[i].supply = sensor_supply_names[i];
-
- ret = devm_regulator_bulk_get(&client->dev, SENSOR_NUM_SUPPLIES,
- sensor->supplies);
- if (ret < 0)
- return ret;
-
- of_id = of_match_node(fimc_is_sensor_of_match, dev->of_node);
- if (!of_id)
- return -ENODEV;
-
- sensor->drvdata = of_id->data;
- sensor->dev = dev;
-
- sd = &sensor->subdev;
- v4l2_i2c_subdev_init(sd, client, &fimc_is_sensor_subdev_ops);
- snprintf(sd->name, sizeof(sd->name), sensor->drvdata->subdev_name);
- sensor->subdev.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
-
- sensor->format.code = fimc_is_sensor_formats[0].code;
- sensor->format.width = FIMC_IS_SENSOR_DEF_PIX_WIDTH;
- sensor->format.height = FIMC_IS_SENSOR_DEF_PIX_HEIGHT;
-
- sensor->pad.flags = MEDIA_PAD_FL_SOURCE;
- ret = media_entity_init(&sd->entity, 1, &sensor->pad, 0);
- if (ret < 0)
- return ret;
-
- pm_runtime_no_callbacks(dev);
- pm_runtime_enable(dev);
-
- return ret;
-}
-
-static int fimc_is_sensor_remove(struct i2c_client *client)
-{
- struct v4l2_subdev *sd = i2c_get_clientdata(client);
- media_entity_cleanup(&sd->entity);
- return 0;
-}
-
-static const struct i2c_device_id fimc_is_sensor_ids[] = {
- { }
-};
-
static const struct sensor_drv_data s5k6a3_drvdata = {
.id = FIMC_IS_SENSOR_ID_S5K6A3,
- .subdev_name = "S5K6A3",
- .width = S5K6A3_SENSOR_WIDTH,
- .height = S5K6A3_SENSOR_HEIGHT,
+ .open_timeout = S5K6A3_OPEN_TIMEOUT,
};
-static const struct of_device_id fimc_is_sensor_of_match[] = {
+static const struct of_device_id fimc_is_sensor_of_ids[] = {
{
.compatible = "samsung,s5k6a3",
.data = &s5k6a3_drvdata,
@@ -279,27 +24,11 @@ static const struct of_device_id fimc_is_sensor_of_match[] = {
{ }
};
-static struct i2c_driver fimc_is_sensor_driver = {
- .driver = {
- .of_match_table = fimc_is_sensor_of_match,
- .name = DRIVER_NAME,
- .owner = THIS_MODULE,
- },
- .probe = fimc_is_sensor_probe,
- .remove = fimc_is_sensor_remove,
- .id_table = fimc_is_sensor_ids,
-};
-
-int fimc_is_register_sensor_driver(void)
+const struct sensor_drv_data *fimc_is_sensor_get_drvdata(
+ struct device_node *node)
{
- return i2c_add_driver(&fimc_is_sensor_driver);
-}
+ const struct of_device_id *of_id;
-void fimc_is_unregister_sensor_driver(void)
-{
- i2c_del_driver(&fimc_is_sensor_driver);
+ of_id = of_match_node(fimc_is_sensor_of_ids, node);
+ return of_id ? of_id->data : NULL;
}
-
-MODULE_AUTHOR("Sylwester Nawrocki <s.nawrocki@samsung.com>");
-MODULE_DESCRIPTION("Exynos4x12 FIMC-IS image sensor subdev driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/media/platform/exynos4-is/fimc-is-sensor.h b/drivers/media/platform/exynos4-is/fimc-is-sensor.h
index 6036d49..173ccff 100644
--- a/drivers/media/platform/exynos4-is/fimc-is-sensor.h
+++ b/drivers/media/platform/exynos4-is/fimc-is-sensor.h
@@ -13,24 +13,13 @@
#ifndef FIMC_IS_SENSOR_H_
#define FIMC_IS_SENSOR_H_
-#include <linux/clk.h>
-#include <linux/device.h>
-#include <linux/kernel.h>
-#include <linux/platform_device.h>
-#include <linux/regulator/consumer.h>
-#include <linux/videodev2.h>
-#include <media/v4l2-subdev.h>
-
-#define FIMC_IS_SENSOR_OPEN_TIMEOUT 2000 /* ms */
-
-#define FIMC_IS_SENSOR_DEF_PIX_WIDTH 1296
-#define FIMC_IS_SENSOR_DEF_PIX_HEIGHT 732
+#include <linux/of.h>
+#include <linux/types.h>
+#define S5K6A3_OPEN_TIMEOUT 2000 /* ms */
#define S5K6A3_SENSOR_WIDTH 1392
#define S5K6A3_SENSOR_HEIGHT 1392
-#define SENSOR_NUM_SUPPLIES 2
-
enum fimc_is_sensor_id {
FIMC_IS_SENSOR_ID_S5K3H2 = 1,
FIMC_IS_SENSOR_ID_S5K6A3,
@@ -45,45 +34,23 @@ enum fimc_is_sensor_id {
struct sensor_drv_data {
enum fimc_is_sensor_id id;
- const char * const subdev_name;
- unsigned int width;
- unsigned int height;
+ /* sensor open timeout in ms */
+ unsigned short open_timeout;
};
/**
* struct fimc_is_sensor - fimc-is sensor data structure
- * @dev: pointer to this I2C client device structure
- * @subdev: the image sensor's v4l2 subdev
- * @pad: subdev media source pad
- * @supplies: image sensor's voltage regulator supplies
- * @gpio_reset: GPIO connected to the sensor's reset pin
* @drvdata: a pointer to the sensor's parameters data structure
* @i2c_bus: ISP I2C bus index (0...1)
* @test_pattern: true to enable video test pattern
- * @lock: mutex protecting the structure's members below
- * @format: media bus format at the sensor's source pad
*/
struct fimc_is_sensor {
- struct device *dev;
- struct v4l2_subdev subdev;
- struct media_pad pad;
- struct regulator_bulk_data supplies[SENSOR_NUM_SUPPLIES];
- int gpio_reset;
const struct sensor_drv_data *drvdata;
unsigned int i2c_bus;
- bool test_pattern;
-
- struct mutex lock;
- struct v4l2_mbus_framefmt format;
+ u8 test_pattern;
};
-static inline
-struct fimc_is_sensor *sd_to_fimc_is_sensor(struct v4l2_subdev *sd)
-{
- return container_of(sd, struct fimc_is_sensor, subdev);
-}
-
-int fimc_is_register_sensor_driver(void);
-void fimc_is_unregister_sensor_driver(void);
+const struct sensor_drv_data *fimc_is_sensor_get_drvdata(
+ struct device_node *node);
#endif /* FIMC_IS_SENSOR_H_ */
diff --git a/drivers/media/platform/exynos4-is/fimc-is.c b/drivers/media/platform/exynos4-is/fimc-is.c
index 13a4228..a8f5845 100644
--- a/drivers/media/platform/exynos4-is/fimc-is.c
+++ b/drivers/media/platform/exynos4-is/fimc-is.c
@@ -161,78 +161,66 @@ static void fimc_is_disable_clocks(struct fimc_is *is)
}
}
-static int fimc_is_parse_sensor_config(struct fimc_is_sensor *sensor,
- struct device_node *np)
+static int fimc_is_parse_sensor_config(struct fimc_is *is, unsigned int index,
+ struct device_node *node)
{
+ struct fimc_is_sensor *sensor = &is->sensor[index];
u32 tmp = 0;
int ret;
- np = v4l2_of_get_next_endpoint(np, NULL);
- if (!np)
+ sensor->drvdata = fimc_is_sensor_get_drvdata(node);
+ if (!sensor->drvdata) {
+ dev_err(&is->pdev->dev, "no driver data found for: %s\n",
+ node->full_name);
+ return -EINVAL;
+ }
+
+ node = v4l2_of_get_next_endpoint(node, NULL);
+ if (!node)
return -ENXIO;
- np = v4l2_of_get_remote_port(np);
- if (!np)
+
+ node = v4l2_of_get_remote_port(node);
+ if (!node)
return -ENXIO;
/* Use MIPI-CSIS channel id to determine the ISP I2C bus index. */
- ret = of_property_read_u32(np, "reg", &tmp);
- sensor->i2c_bus = tmp - FIMC_INPUT_MIPI_CSI2_0;
+ ret = of_property_read_u32(node, "reg", &tmp);
+ if (ret < 0) {
+ dev_err(&is->pdev->dev, "reg property not found at: %s\n",
+ node->full_name);
+ return ret;
+ }
- return ret;
+ sensor->i2c_bus = tmp - FIMC_INPUT_MIPI_CSI2_0;
+ return 0;
}
static int fimc_is_register_subdevs(struct fimc_is *is)
{
- struct device_node *adapter, *child;
- int ret;
+ struct device_node *i2c_bus, *child;
+ int ret, index = 0;
ret = fimc_isp_subdev_create(&is->isp);
if (ret < 0)
return ret;
- for_each_compatible_node(adapter, NULL, FIMC_IS_I2C_COMPATIBLE) {
- if (!of_find_device_by_node(adapter)) {
- of_node_put(adapter);
- return -EPROBE_DEFER;
- }
+ for_each_compatible_node(i2c_bus, NULL, FIMC_IS_I2C_COMPATIBLE) {
+ for_each_available_child_of_node(i2c_bus, child) {
+ ret = fimc_is_parse_sensor_config(is, index, child);
- for_each_available_child_of_node(adapter, child) {
- struct i2c_client *client;
- struct v4l2_subdev *sd;
-
- client = of_find_i2c_device_by_node(child);
- if (!client)
- goto e_retry;
-
- sd = i2c_get_clientdata(client);
- if (!sd)
- goto e_retry;
-
- /* FIXME: Add support for multiple sensors. */
- if (WARN_ON(is->sensor))
- continue;
-
- is->sensor = sd_to_fimc_is_sensor(sd);
-
- if (fimc_is_parse_sensor_config(is->sensor, child)) {
- dev_warn(&is->pdev->dev, "DT parse error: %s\n",
- child->full_name);
+ if (ret < 0 || index >= FIMC_IS_SENSORS_NUM) {
+ of_node_put(child);
+ return ret;
}
- pr_debug("%s(): registered subdev: %p\n",
- __func__, sd->name);
+ index++;
}
}
return 0;
-
-e_retry:
- of_node_put(child);
- return -EPROBE_DEFER;
}
static int fimc_is_unregister_subdevs(struct fimc_is *is)
{
fimc_isp_subdev_destroy(&is->isp);
- is->sensor = NULL;
return 0;
}
@@ -647,7 +635,7 @@ static int fimc_is_hw_open_sensor(struct fimc_is *is,
fimc_is_hw_set_intgr0_gd0(is);
return fimc_is_wait_event(is, IS_ST_OPEN_SENSOR, 1,
- FIMC_IS_SENSOR_OPEN_TIMEOUT);
+ sensor->drvdata->open_timeout);
}
@@ -661,8 +649,8 @@ int fimc_is_hw_initialize(struct fimc_is *is)
u32 prev_id;
int i, ret;
- /* Sensor initialization. */
- ret = fimc_is_hw_open_sensor(is, is->sensor);
+ /* Sensor initialization. Only one sensor is currently supported. */
+ ret = fimc_is_hw_open_sensor(is, &is->sensor[0]);
if (ret < 0)
return ret;
@@ -977,27 +965,20 @@ static int fimc_is_module_init(void)
{
int ret;
- ret = fimc_is_register_sensor_driver();
- if (ret < 0)
- return ret;
-
ret = fimc_is_register_i2c_driver();
if (ret < 0)
- goto err_sens;
+ return ret;
ret = platform_driver_register(&fimc_is_driver);
- if (!ret)
- return ret;
- fimc_is_unregister_i2c_driver();
-err_sens:
- fimc_is_unregister_sensor_driver();
+ if (ret < 0)
+ fimc_is_unregister_i2c_driver();
+
return ret;
}
static void fimc_is_module_exit(void)
{
- fimc_is_unregister_sensor_driver();
fimc_is_unregister_i2c_driver();
platform_driver_unregister(&fimc_is_driver);
}
diff --git a/drivers/media/platform/exynos4-is/fimc-is.h b/drivers/media/platform/exynos4-is/fimc-is.h
index 61bb012..01f802f 100644
--- a/drivers/media/platform/exynos4-is/fimc-is.h
+++ b/drivers/media/platform/exynos4-is/fimc-is.h
@@ -39,7 +39,7 @@
#define FIMC_IS_FW_LOAD_TIMEOUT 1000 /* ms */
#define FIMC_IS_POWER_ON_TIMEOUT 1000 /* us */
-#define FIMC_IS_SENSOR_NUM 2
+#define FIMC_IS_SENSORS_NUM 2
/* Memory definitions */
#define FIMC_IS_CPU_MEM_SIZE (0xa00000)
@@ -253,7 +253,7 @@ struct fimc_is {
struct firmware *f_w;
struct fimc_isp isp;
- struct fimc_is_sensor *sensor;
+ struct fimc_is_sensor sensor[FIMC_IS_SENSORS_NUM];
struct fimc_is_setfile setfile;
struct vb2_alloc_ctx *alloc_ctx;
--
1.7.9.5
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH v4 07/10] exynos4-is: Add clock provider for the SCLK_CAM clock outputs
2014-02-20 19:40 [PATCH v4 00/10] Add device tree support for Exynos4 SoC camera subsystem Sylwester Nawrocki
` (6 preceding siblings ...)
2014-02-20 19:40 ` [PATCH v4 06/10] exynos4-is: Use external s5k6a3 sensor driver Sylwester Nawrocki
@ 2014-02-20 19:40 ` Sylwester Nawrocki
2014-02-21 16:05 ` Mark Rutland
2014-02-20 19:40 ` [PATCH v4 08/10] exynos4-is: Add support for asynchronous subdevices registration Sylwester Nawrocki
` (2 subsequent siblings)
10 siblings, 1 reply; 20+ messages in thread
From: Sylwester Nawrocki @ 2014-02-20 19:40 UTC (permalink / raw)
To: linux-media, devicetree
Cc: linux-samsung-soc, linux-arm-kernel, robh+dt, mark.rutland, galak,
kyungmin.park, kgene.kim, a.hajda, Sylwester Nawrocki
This patch adds clock provider so the the SCLK_CAM0/1 output clocks
can be accessed by image sensor devices through the clk API.
Signed-off-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
Acked-by: Kyungmin Park <kyungmin.park@samsung.com>
---
Changes since v3:
- use clock-output-names DT property instead of hard coding names
of registered clocks in the driver; first two entries of the
clock-names property value are used to specify parent clocks of
cam_{a,b}_clkout clocks, rather than hard coding it to sclk_cam{0,1}
in the driver.
- addressed issues pointed out in review by Mauro.
Changes since v2:
- use 'camera' DT node drirectly as clock provider node, rather than
creating additional clock-controller child node.
- DT binding documentation moved to a separate patch.
---
drivers/media/platform/exynos4-is/media-dev.c | 110 +++++++++++++++++++++++++
drivers/media/platform/exynos4-is/media-dev.h | 19 ++++-
2 files changed, 128 insertions(+), 1 deletion(-)
diff --git a/drivers/media/platform/exynos4-is/media-dev.c b/drivers/media/platform/exynos4-is/media-dev.c
index c1bce17..dfc3131 100644
--- a/drivers/media/platform/exynos4-is/media-dev.c
+++ b/drivers/media/platform/exynos4-is/media-dev.c
@@ -11,6 +11,8 @@
*/
#include <linux/bug.h>
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
#include <linux/device.h>
#include <linux/errno.h>
#include <linux/i2c.h>
@@ -1437,6 +1439,103 @@ static int fimc_md_get_pinctrl(struct fimc_md *fmd)
return 0;
}
+#ifdef CONFIG_OF
+static int cam_clk_prepare(struct clk_hw *hw)
+{
+ struct cam_clk *camclk = to_cam_clk(hw);
+ int ret;
+
+ if (camclk->fmd->pmf == NULL)
+ return -ENODEV;
+
+ ret = pm_runtime_get_sync(camclk->fmd->pmf);
+ return ret < 0 ? ret : 0;
+}
+
+static void cam_clk_unprepare(struct clk_hw *hw)
+{
+ struct cam_clk *camclk = to_cam_clk(hw);
+
+ if (camclk->fmd->pmf == NULL)
+ return;
+
+ pm_runtime_put_sync(camclk->fmd->pmf);
+}
+
+static const struct clk_ops cam_clk_ops = {
+ .prepare = cam_clk_prepare,
+ .unprepare = cam_clk_unprepare,
+};
+
+static void fimc_md_unregister_clk_provider(struct fimc_md *fmd)
+{
+ struct cam_clk_provider *cp = &fmd->clk_provider;
+ unsigned int i;
+
+ if (cp->of_node)
+ of_clk_del_provider(cp->of_node);
+
+ for (i = 0; i < cp->num_clocks; i++)
+ clk_unregister(cp->clks[i]);
+}
+
+static int fimc_md_register_clk_provider(struct fimc_md *fmd)
+{
+ struct cam_clk_provider *cp = &fmd->clk_provider;
+ struct device *dev = &fmd->pdev->dev;
+ int i, ret;
+
+ for (i = 0; i < ARRAY_SIZE(cp->clks); i++) {
+ struct cam_clk *camclk = &cp->camclk[i];
+ struct clk_init_data init;
+
+ ret = of_property_read_string_index(dev->of_node,
+ "clock-output-names", i, &init.name);
+ if (ret < 0)
+ break;
+
+ ret = of_property_read_string_index(dev->of_node,
+ "clock-names", i, init.parent_names);
+ if (ret < 0)
+ break;
+
+ init.num_parents = 1;
+ init.ops = &cam_clk_ops;
+ init.flags = CLK_SET_RATE_PARENT;
+ camclk->hw.init = &init;
+ camclk->fmd = fmd;
+
+ cp->clks[i] = clk_register(NULL, &camclk->hw);
+ if (IS_ERR(cp->clks[i])) {
+ dev_err(dev, "failed to register clock: %s (%ld)\n",
+ init.name, PTR_ERR(cp->clks[i]));
+ ret = PTR_ERR(cp->clks[i]);
+ goto err;
+ }
+ cp->num_clocks++;
+ }
+
+ if (cp->num_clocks == 0) {
+ dev_warn(dev, "clk provider not registered\n");
+ return 0;
+ }
+
+ cp->clk_data.clks = cp->clks;
+ cp->clk_data.clk_num = cp->num_clocks;
+ cp->of_node = dev->of_node;
+ ret = of_clk_add_provider(dev->of_node, of_clk_src_onecell_get,
+ &cp->clk_data);
+ if (ret == 0)
+ return 0;
+err:
+ fimc_md_unregister_clk_provider(fmd);
+ return ret;
+}
+#else
+#define fimc_md_register_clk_provider(fmd) (0)
+#define fimc_md_unregister_clk_provider(fmd) (0)
+#endif
+
static int fimc_md_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
@@ -1464,16 +1563,24 @@ static int fimc_md_probe(struct platform_device *pdev)
fmd->use_isp = fimc_md_is_isp_available(dev->of_node);
+ ret = fimc_md_register_clk_provider(fmd);
+ if (ret < 0) {
+ v4l2_err(v4l2_dev, "clock provider registration failed\n");
+ return ret;
+ }
+
ret = v4l2_device_register(dev, &fmd->v4l2_dev);
if (ret < 0) {
v4l2_err(v4l2_dev, "Failed to register v4l2_device: %d\n", ret);
return ret;
}
+
ret = media_device_register(&fmd->media_dev);
if (ret < 0) {
v4l2_err(v4l2_dev, "Failed to register media device: %d\n", ret);
goto err_md;
}
+
ret = fimc_md_get_clocks(fmd);
if (ret)
goto err_clk;
@@ -1507,6 +1614,7 @@ static int fimc_md_probe(struct platform_device *pdev)
ret = fimc_md_create_links(fmd);
if (ret)
goto err_unlock;
+
ret = v4l2_device_register_subdev_nodes(&fmd->v4l2_dev);
if (ret)
goto err_unlock;
@@ -1527,6 +1635,7 @@ err_clk:
media_device_unregister(&fmd->media_dev);
err_md:
v4l2_device_unregister(&fmd->v4l2_dev);
+ fimc_md_unregister_clk_provider(fmd);
return ret;
}
@@ -1537,6 +1646,7 @@ static int fimc_md_remove(struct platform_device *pdev)
if (!fmd)
return 0;
+ fimc_md_unregister_clk_provider(fmd);
v4l2_device_unregister(&fmd->v4l2_dev);
device_remove_file(&pdev->dev, &dev_attr_subdev_conf_mode);
fimc_md_unregister_entities(fmd);
diff --git a/drivers/media/platform/exynos4-is/media-dev.h b/drivers/media/platform/exynos4-is/media-dev.h
index 62599fd..a88cee5 100644
--- a/drivers/media/platform/exynos4-is/media-dev.h
+++ b/drivers/media/platform/exynos4-is/media-dev.h
@@ -10,6 +10,7 @@
#define FIMC_MDEVICE_H_
#include <linux/clk.h>
+#include <linux/clk-provider.h>
#include <linux/platform_device.h>
#include <linux/mutex.h>
#include <linux/of.h>
@@ -89,6 +90,12 @@ struct fimc_sensor_info {
struct fimc_dev *host;
};
+struct cam_clk {
+ struct clk_hw hw;
+ struct fimc_md *fmd;
+};
+#define to_cam_clk(_hw) container_of(_hw, struct cam_clk, hw)
+
/**
* struct fimc_md - fimc media device information
* @csis: MIPI CSIS subdevs data
@@ -105,6 +112,7 @@ struct fimc_sensor_info {
* @pinctrl: camera port pinctrl handle
* @state_default: pinctrl default state handle
* @state_idle: pinctrl idle state handle
+ * @cam_clk_provider: CAMCLK clock provider structure
* @user_subdev_api: true if subdevs are not configured by the host driver
* @slock: spinlock protecting @sensor array
*/
@@ -122,13 +130,22 @@ struct fimc_md {
struct media_device media_dev;
struct v4l2_device v4l2_dev;
struct platform_device *pdev;
+
struct fimc_pinctrl {
struct pinctrl *pinctrl;
struct pinctrl_state *state_default;
struct pinctrl_state *state_idle;
} pinctl;
- bool user_subdev_api;
+ struct cam_clk_provider {
+ struct clk *clks[FIMC_MAX_CAMCLKS];
+ struct clk_onecell_data clk_data;
+ struct device_node *of_node;
+ struct cam_clk camclk[FIMC_MAX_CAMCLKS];
+ int num_clocks;
+ } clk_provider;
+
+ bool user_subdev_api;
spinlock_t slock;
struct list_head pipelines;
};
--
1.7.9.5
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH v4 08/10] exynos4-is: Add support for asynchronous subdevices registration
2014-02-20 19:40 [PATCH v4 00/10] Add device tree support for Exynos4 SoC camera subsystem Sylwester Nawrocki
` (7 preceding siblings ...)
2014-02-20 19:40 ` [PATCH v4 07/10] exynos4-is: Add clock provider for the SCLK_CAM clock outputs Sylwester Nawrocki
@ 2014-02-20 19:40 ` Sylwester Nawrocki
2014-02-20 19:40 ` [PATCH v4 09/10] ARM: dts: Add rear camera nodes for Exynos4412 TRATS2 board Sylwester Nawrocki
2014-02-20 19:40 ` [PATCH v4 10/10] ARM: dts: exynos4: Update clk provider part of the camera subsystem Sylwester Nawrocki
10 siblings, 0 replies; 20+ messages in thread
From: Sylwester Nawrocki @ 2014-02-20 19:40 UTC (permalink / raw)
To: linux-media, devicetree
Cc: linux-samsung-soc, linux-arm-kernel, robh+dt, mark.rutland, galak,
kyungmin.park, kgene.kim, a.hajda, Sylwester Nawrocki
Add support for registering external sensor subdevs using v4l2-async
API. The async API is used only for sensor subdevs and only for DT
platforms.
Signed-off-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
Acked-by: Kyungmin Park <kyungmin.park@samsung.com>
---
drivers/media/platform/exynos4-is/media-dev.c | 233 ++++++++++++++-----------
drivers/media/platform/exynos4-is/media-dev.h | 13 +-
2 files changed, 144 insertions(+), 102 deletions(-)
diff --git a/drivers/media/platform/exynos4-is/media-dev.c b/drivers/media/platform/exynos4-is/media-dev.c
index dfc3131..127ced9 100644
--- a/drivers/media/platform/exynos4-is/media-dev.c
+++ b/drivers/media/platform/exynos4-is/media-dev.c
@@ -26,6 +26,7 @@
#include <linux/pm_runtime.h>
#include <linux/types.h>
#include <linux/slab.h>
+#include <media/v4l2-async.h>
#include <media/v4l2-ctrls.h>
#include <media/v4l2-of.h>
#include <media/media-device.h>
@@ -220,6 +221,7 @@ static int __fimc_pipeline_open(struct exynos_media_pipeline *ep,
if (ret < 0)
return ret;
}
+
ret = fimc_md_set_camclk(sd, true);
if (ret < 0)
goto err_wbclk;
@@ -380,77 +382,18 @@ static void fimc_md_unregister_sensor(struct v4l2_subdev *sd)
struct i2c_client *client = v4l2_get_subdevdata(sd);
struct i2c_adapter *adapter;
- if (!client)
+ if (!client || client->dev.of_node)
return;
v4l2_device_unregister_subdev(sd);
- if (!client->dev.of_node) {
- adapter = client->adapter;
- i2c_unregister_device(client);
- if (adapter)
- i2c_put_adapter(adapter);
- }
+ adapter = client->adapter;
+ i2c_unregister_device(client);
+ if (adapter)
+ i2c_put_adapter(adapter);
}
#ifdef CONFIG_OF
-/* Register I2C client subdev associated with @node. */
-static int fimc_md_of_add_sensor(struct fimc_md *fmd,
- struct device_node *node, int index)
-{
- struct fimc_sensor_info *si;
- struct i2c_client *client;
- struct v4l2_subdev *sd;
- int ret;
-
- if (WARN_ON(index >= ARRAY_SIZE(fmd->sensor)))
- return -EINVAL;
- si = &fmd->sensor[index];
-
- client = of_find_i2c_device_by_node(node);
- if (!client)
- return -EPROBE_DEFER;
-
- device_lock(&client->dev);
-
- if (!client->dev.driver ||
- !try_module_get(client->dev.driver->owner)) {
- ret = -EPROBE_DEFER;
- v4l2_info(&fmd->v4l2_dev, "No driver found for %s\n",
- node->full_name);
- goto dev_put;
- }
-
- /* Enable sensor's master clock */
- ret = __fimc_md_set_camclk(fmd, &si->pdata, true);
- if (ret < 0)
- goto mod_put;
- sd = i2c_get_clientdata(client);
-
- ret = v4l2_device_register_subdev(&fmd->v4l2_dev, sd);
- __fimc_md_set_camclk(fmd, &si->pdata, false);
- if (ret < 0)
- goto mod_put;
-
- v4l2_set_subdev_hostdata(sd, &si->pdata);
- if (si->pdata.fimc_bus_type == FIMC_BUS_TYPE_ISP_WRITEBACK)
- sd->grp_id = GRP_ID_FIMC_IS_SENSOR;
- else
- sd->grp_id = GRP_ID_SENSOR;
-
- si->subdev = sd;
- v4l2_info(&fmd->v4l2_dev, "Registered sensor subdevice: %s (%d)\n",
- sd->name, fmd->num_sensors);
- fmd->num_sensors++;
-
-mod_put:
- module_put(client->dev.driver->owner);
-dev_put:
- device_unlock(&client->dev);
- put_device(&client->dev);
- return ret;
-}
-
/* Parse port node and register as a sub-device any sensor specified there. */
static int fimc_md_parse_port_node(struct fimc_md *fmd,
struct device_node *port,
@@ -459,7 +402,6 @@ static int fimc_md_parse_port_node(struct fimc_md *fmd,
struct device_node *rem, *ep, *np;
struct fimc_source_info *pd;
struct v4l2_of_endpoint endpoint;
- int ret;
u32 val;
pd = &fmd->sensor[index].pdata;
@@ -487,6 +429,8 @@ static int fimc_md_parse_port_node(struct fimc_md *fmd,
if (!of_property_read_u32(rem, "clock-frequency", &val))
pd->clk_frequency = val;
+ else
+ pd->clk_frequency = DEFAULT_SENSOR_CLK_FREQ;
if (pd->clk_frequency == 0) {
v4l2_err(&fmd->v4l2_dev, "Wrong clock frequency at node %s\n",
@@ -526,10 +470,17 @@ static int fimc_md_parse_port_node(struct fimc_md *fmd,
else
pd->fimc_bus_type = pd->sensor_bus_type;
- ret = fimc_md_of_add_sensor(fmd, rem, index);
- of_node_put(rem);
+ if (WARN_ON(index >= ARRAY_SIZE(fmd->sensor)))
+ return -EINVAL;
- return ret;
+ fmd->sensor[index].asd.match_type = V4L2_ASYNC_MATCH_OF;
+ fmd->sensor[index].asd.match.of.node = rem;
+ fmd->async_subdevs[index] = &fmd->sensor[index].asd;
+
+ fmd->num_sensors++;
+
+ of_node_put(rem);
+ return 0;
}
/* Register all SoC external sub-devices */
@@ -885,11 +836,13 @@ static void fimc_md_unregister_entities(struct fimc_md *fmd)
v4l2_device_unregister_subdev(fmd->csis[i].sd);
fmd->csis[i].sd = NULL;
}
- for (i = 0; i < fmd->num_sensors; i++) {
- if (fmd->sensor[i].subdev == NULL)
- continue;
- fimc_md_unregister_sensor(fmd->sensor[i].subdev);
- fmd->sensor[i].subdev = NULL;
+ if (fmd->pdev->dev.of_node == NULL) {
+ for (i = 0; i < fmd->num_sensors; i++) {
+ if (fmd->sensor[i].subdev == NULL)
+ continue;
+ fimc_md_unregister_sensor(fmd->sensor[i].subdev);
+ fmd->sensor[i].subdev = NULL;
+ }
}
if (fmd->fimc_is)
@@ -1224,6 +1177,14 @@ static int __fimc_md_set_camclk(struct fimc_md *fmd,
struct fimc_camclk_info *camclk;
int ret = 0;
+ /*
+ * When device tree is used the sensor drivers are supposed to
+ * control the clock themselves. This whole function will be
+ * removed once S5PV210 platform is converted to the device tree.
+ */
+ if (fmd->pdev->dev.of_node)
+ return 0;
+
if (WARN_ON(si->clk_id >= FIMC_MAX_CAMCLKS) || !fmd || !fmd->pmf)
return -EINVAL;
@@ -1536,6 +1497,56 @@ err:
#define fimc_md_unregister_clk_provider(fmd) (0)
#endif
+static int subdev_notifier_bound(struct v4l2_async_notifier *notifier,
+ struct v4l2_subdev *subdev,
+ struct v4l2_async_subdev *asd)
+{
+ struct fimc_md *fmd = notifier_to_fimc_md(notifier);
+ struct fimc_sensor_info *si = NULL;
+ int i;
+
+ /* Find platform data for this sensor subdev */
+ for (i = 0; i < ARRAY_SIZE(fmd->sensor); i++)
+ if (fmd->sensor[i].asd.match.of.node == subdev->dev->of_node)
+ si = &fmd->sensor[i];
+
+ if (si == NULL)
+ return -EINVAL;
+
+ v4l2_set_subdev_hostdata(subdev, &si->pdata);
+
+ if (si->pdata.fimc_bus_type == FIMC_BUS_TYPE_ISP_WRITEBACK)
+ subdev->grp_id = GRP_ID_FIMC_IS_SENSOR;
+ else
+ subdev->grp_id = GRP_ID_SENSOR;
+
+ si->subdev = subdev;
+
+ v4l2_info(&fmd->v4l2_dev, "Registered sensor subdevice: %s (%d)\n",
+ subdev->name, fmd->num_sensors);
+
+ fmd->num_sensors++;
+
+ return 0;
+}
+
+static int subdev_notifier_complete(struct v4l2_async_notifier *notifier)
+{
+ struct fimc_md *fmd = notifier_to_fimc_md(notifier);
+ int ret;
+
+ mutex_lock(&fmd->media_dev.graph_mutex);
+
+ ret = fimc_md_create_links(fmd);
+ if (ret < 0)
+ goto unlock;
+
+ ret = v4l2_device_register_subdev_nodes(&fmd->v4l2_dev);
+unlock:
+ mutex_unlock(&fmd->media_dev.graph_mutex);
+ return ret;
+}
+
static int fimc_md_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
@@ -1563,12 +1574,6 @@ static int fimc_md_probe(struct platform_device *pdev)
fmd->use_isp = fimc_md_is_isp_available(dev->of_node);
- ret = fimc_md_register_clk_provider(fmd);
- if (ret < 0) {
- v4l2_err(v4l2_dev, "clock provider registration failed\n");
- return ret;
- }
-
ret = v4l2_device_register(dev, &fmd->v4l2_dev);
if (ret < 0) {
v4l2_err(v4l2_dev, "Failed to register v4l2_device: %d\n", ret);
@@ -1578,64 +1583,87 @@ static int fimc_md_probe(struct platform_device *pdev)
ret = media_device_register(&fmd->media_dev);
if (ret < 0) {
v4l2_err(v4l2_dev, "Failed to register media device: %d\n", ret);
- goto err_md;
+ goto err_v4l2_dev;
}
ret = fimc_md_get_clocks(fmd);
if (ret)
- goto err_clk;
+ goto err_md;
fmd->user_subdev_api = (dev->of_node != NULL);
- /* Protect the media graph while we're registering entities */
- mutex_lock(&fmd->media_dev.graph_mutex);
-
ret = fimc_md_get_pinctrl(fmd);
if (ret < 0) {
if (ret != EPROBE_DEFER)
dev_err(dev, "Failed to get pinctrl: %d\n", ret);
- goto err_unlock;
+ goto err_clk;
}
+ platform_set_drvdata(pdev, fmd);
+
+ /* Protect the media graph while we're registering entities */
+ mutex_lock(&fmd->media_dev.graph_mutex);
+
if (dev->of_node)
ret = fimc_md_register_of_platform_entities(fmd, dev->of_node);
else
ret = bus_for_each_dev(&platform_bus_type, NULL, fmd,
fimc_md_pdev_match);
- if (ret)
- goto err_unlock;
+ if (ret) {
+ mutex_unlock(&fmd->media_dev.graph_mutex);
+ goto err_clk;
+ }
if (dev->platform_data || dev->of_node) {
ret = fimc_md_register_sensor_entities(fmd);
- if (ret)
- goto err_unlock;
+ if (ret) {
+ mutex_unlock(&fmd->media_dev.graph_mutex);
+ goto err_m_ent;
+ }
}
- ret = fimc_md_create_links(fmd);
- if (ret)
- goto err_unlock;
+ mutex_unlock(&fmd->media_dev.graph_mutex);
- ret = v4l2_device_register_subdev_nodes(&fmd->v4l2_dev);
+ ret = device_create_file(&pdev->dev, &dev_attr_subdev_conf_mode);
if (ret)
- goto err_unlock;
+ goto err_m_ent;
+ /*
+ * FIMC platform devices need to be registered before the sclk_cam
+ * clocks provider, as one of these devices needs to be activated
+ * to enable the clock.
+ */
+ ret = fimc_md_register_clk_provider(fmd);
+ if (ret < 0) {
+ v4l2_err(v4l2_dev, "clock provider registration failed\n");
+ goto err_attr;
+ }
- ret = device_create_file(&pdev->dev, &dev_attr_subdev_conf_mode);
+ fmd->subdev_notifier.subdevs = fmd->async_subdevs;
+ fmd->subdev_notifier.num_subdevs = fmd->num_sensors;
+ fmd->subdev_notifier.bound = subdev_notifier_bound;
+ fmd->subdev_notifier.complete = subdev_notifier_complete;
+ fmd->num_sensors = 0;
+
+ ret = v4l2_async_notifier_register(&fmd->v4l2_dev,
+ &fmd->subdev_notifier);
if (ret)
- goto err_unlock;
+ goto err_clk_p;
- platform_set_drvdata(pdev, fmd);
- mutex_unlock(&fmd->media_dev.graph_mutex);
return 0;
-err_unlock:
- mutex_unlock(&fmd->media_dev.graph_mutex);
+err_clk_p:
+ fimc_md_unregister_clk_provider(fmd);
+err_attr:
+ device_remove_file(&pdev->dev, &dev_attr_subdev_conf_mode);
err_clk:
fimc_md_put_clocks(fmd);
+err_m_ent:
fimc_md_unregister_entities(fmd);
media_device_unregister(&fmd->media_dev);
err_md:
+ media_device_unregister(&fmd->media_dev);
+err_v4l2_dev:
v4l2_device_unregister(&fmd->v4l2_dev);
- fimc_md_unregister_clk_provider(fmd);
return ret;
}
@@ -1647,12 +1675,15 @@ static int fimc_md_remove(struct platform_device *pdev)
return 0;
fimc_md_unregister_clk_provider(fmd);
+ v4l2_async_notifier_unregister(&fmd->subdev_notifier);
+
v4l2_device_unregister(&fmd->v4l2_dev);
device_remove_file(&pdev->dev, &dev_attr_subdev_conf_mode);
fimc_md_unregister_entities(fmd);
fimc_md_pipelines_free(fmd);
media_device_unregister(&fmd->media_dev);
fimc_md_put_clocks(fmd);
+
return 0;
}
diff --git a/drivers/media/platform/exynos4-is/media-dev.h b/drivers/media/platform/exynos4-is/media-dev.h
index a88cee5..ee1e251 100644
--- a/drivers/media/platform/exynos4-is/media-dev.h
+++ b/drivers/media/platform/exynos4-is/media-dev.h
@@ -32,8 +32,9 @@
#define PINCTRL_STATE_IDLE "idle"
-#define FIMC_MAX_SENSORS 8
+#define FIMC_MAX_SENSORS 4
#define FIMC_MAX_CAMCLKS 2
+#define DEFAULT_SENSOR_CLK_FREQ 24000000U
/* LCD/ISP Writeback clocks (PIXELASYNCMx) */
enum {
@@ -79,6 +80,7 @@ struct fimc_camclk_info {
/**
* struct fimc_sensor_info - image data source subdev information
* @pdata: sensor's atrributes passed as media device's platform data
+ * @asd: asynchronous subdev registration data structure
* @subdev: image sensor v4l2 subdev
* @host: fimc device the sensor is currently linked to
*
@@ -86,6 +88,7 @@ struct fimc_camclk_info {
*/
struct fimc_sensor_info {
struct fimc_source_info pdata;
+ struct v4l2_async_subdev asd;
struct v4l2_subdev *subdev;
struct fimc_dev *host;
};
@@ -145,6 +148,9 @@ struct fimc_md {
int num_clocks;
} clk_provider;
+ struct v4l2_async_notifier subdev_notifier;
+ struct v4l2_async_subdev *async_subdevs[FIMC_MAX_SENSORS];
+
bool user_subdev_api;
spinlock_t slock;
struct list_head pipelines;
@@ -162,6 +168,11 @@ static inline struct fimc_md *entity_to_fimc_mdev(struct media_entity *me)
container_of(me->parent, struct fimc_md, media_dev);
}
+static inline struct fimc_md *notifier_to_fimc_md(struct v4l2_async_notifier *n)
+{
+ return container_of(n, struct fimc_md, subdev_notifier);
+}
+
static inline void fimc_md_graph_lock(struct exynos_video_entity *ve)
{
mutex_lock(&ve->vdev.entity.parent->graph_mutex);
--
1.7.9.5
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH v4 09/10] ARM: dts: Add rear camera nodes for Exynos4412 TRATS2 board
2014-02-20 19:40 [PATCH v4 00/10] Add device tree support for Exynos4 SoC camera subsystem Sylwester Nawrocki
` (8 preceding siblings ...)
2014-02-20 19:40 ` [PATCH v4 08/10] exynos4-is: Add support for asynchronous subdevices registration Sylwester Nawrocki
@ 2014-02-20 19:40 ` Sylwester Nawrocki
2014-02-20 19:40 ` [PATCH v4 10/10] ARM: dts: exynos4: Update clk provider part of the camera subsystem Sylwester Nawrocki
10 siblings, 0 replies; 20+ messages in thread
From: Sylwester Nawrocki @ 2014-02-20 19:40 UTC (permalink / raw)
To: linux-media, devicetree
Cc: linux-samsung-soc, linux-arm-kernel, robh+dt, mark.rutland, galak,
kyungmin.park, kgene.kim, a.hajda, Sylwester Nawrocki
This patch enables the rear facing camera (s5c73m3) on TRATS2 board
by adding the I2C0 bus controller, s5c73m3 sensor, MIPI CSI-2 receiver
and the sensor's voltage regulator supply nodes.
Signed-off-by: Andrzej Hajda <a.hajda@samsung.com>
Acked-by: Kyungmin Park <kyungmin.park@samsung.com>
---
arch/arm/boot/dts/exynos4412-trats2.dts | 86 +++++++++++++++++++++++++++++--
1 file changed, 81 insertions(+), 5 deletions(-)
diff --git a/arch/arm/boot/dts/exynos4412-trats2.dts b/arch/arm/boot/dts/exynos4412-trats2.dts
index 4f851cc..d7e13a4 100644
--- a/arch/arm/boot/dts/exynos4412-trats2.dts
+++ b/arch/arm/boot/dts/exynos4412-trats2.dts
@@ -71,7 +71,33 @@
enable-active-high;
};
- /* More to come */
+ cam_af_reg: voltage-regulator-2 {
+ compatible = "regulator-fixed";
+ regulator-name = "CAM_AF";
+ regulator-min-microvolt = <2800000>;
+ regulator-max-microvolt = <2800000>;
+ gpio = <&gpm0 4 0>;
+ enable-active-high;
+ };
+
+ cam_isp_core_reg: voltage-regulator-3 {
+ compatible = "regulator-fixed";
+ regulator-name = "CAM_ISP_CORE_1.2V_EN";
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1200000>;
+ gpio = <&gpm0 3 0>;
+ enable-active-high;
+ regulator-always-on;
+ };
+
+ lcd_vdd3_reg: voltage-regulator-4 {
+ compatible = "regulator-fixed";
+ regulator-name = "LCD_VDD_2.2V";
+ regulator-min-microvolt = <2200000>;
+ regulator-max-microvolt = <2200000>;
+ gpio = <&gpc0 1 0>;
+ enable-active-high;
+ };
};
gpio-keys {
@@ -106,6 +132,38 @@
};
};
+ i2c_0: i2c@13860000 {
+ samsung,i2c-sda-delay = <100>;
+ samsung,i2c-slave-addr = <0x10>;
+ samsung,i2c-max-bus-freq = <400000>;
+ pinctrl-0 = <&i2c0_bus>;
+ pinctrl-names = "default";
+ status = "okay";
+
+ s5c73m3@3c {
+ compatible = "samsung,s5c73m3";
+ reg = <0x3c>;
+ standby-gpios = <&gpm0 1 1>; /* ISP_STANDBY */
+ xshutdown-gpios = <&gpf1 3 1>; /* ISP_RESET */
+ vdd-int-supply = <&buck9_reg>;
+ vddio-cis-supply = <&ldo9_reg>;
+ vdda-supply = <&ldo17_reg>;
+ vddio-host-supply = <&ldo18_reg>;
+ vdd-af-supply = <&cam_af_reg>;
+ vdd-reg-supply = <&cam_io_reg>;
+ clock-frequency = <24000000>;
+ /* CAM_A_CLKOUT */
+ clocks = <&camera 0>;
+ clock-names = "cis_extclk";
+ port {
+ s5c73m3_ep: endpoint {
+ remote-endpoint = <&csis0_ep>;
+ data-lanes = <1 2 3 4>;
+ };
+ };
+ };
+ };
+
i2c@13890000 {
samsung,i2c-sda-delay = <100>;
samsung,i2c-slave-addr = <0x10>;
@@ -511,8 +569,8 @@
};
};
- camera {
- pinctrl-0 = <&cam_port_b_clk_active>;
+ camera: camera {
+ pinctrl-0 = <&cam_port_a_clk_active &cam_port_b_clk_active>;
pinctrl-names = "default";
status = "okay";
@@ -532,6 +590,23 @@
status = "okay";
};
+ csis_0: csis@11880000 {
+ status = "okay";
+ vddcore-supply = <&ldo8_reg>;
+ vddio-supply = <&ldo10_reg>;
+ clock-frequency = <176000000>;
+
+ /* Camera C (3) MIPI CSI-2 (CSIS0) */
+ port@3 {
+ reg = <3>;
+ csis0_ep: endpoint {
+ remote-endpoint = <&s5c73m3_ep>;
+ data-lanes = <1 2 3 4>;
+ samsung,csis-hs-settle = <12>;
+ };
+ };
+ };
+
csis_1: csis@11890000 {
vddcore-supply = <&ldo8_reg>;
vddio-supply = <&ldo10_reg>;
@@ -572,10 +647,11 @@
reg = <0x10>;
svdda-supply = <&cam_io_reg>;
svddio-supply = <&ldo19_reg>;
+ afvdd-supply = <&ldo19_reg>;
clock-frequency = <24000000>;
/* CAM_B_CLKOUT */
- clocks = <&clock_cam 1>;
- clock-names = "mclk";
+ clocks = <&camera 1>;
+ clock-names = "extclk";
samsung,camclk-out = <1>;
gpios = <&gpm1 6 0>;
--
1.7.9.5
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH v4 10/10] ARM: dts: exynos4: Update clk provider part of the camera subsystem
2014-02-20 19:40 [PATCH v4 00/10] Add device tree support for Exynos4 SoC camera subsystem Sylwester Nawrocki
` (9 preceding siblings ...)
2014-02-20 19:40 ` [PATCH v4 09/10] ARM: dts: Add rear camera nodes for Exynos4412 TRATS2 board Sylwester Nawrocki
@ 2014-02-20 19:40 ` Sylwester Nawrocki
10 siblings, 0 replies; 20+ messages in thread
From: Sylwester Nawrocki @ 2014-02-20 19:40 UTC (permalink / raw)
To: linux-media, devicetree
Cc: linux-samsung-soc, linux-arm-kernel, robh+dt, mark.rutland, galak,
kyungmin.park, kgene.kim, a.hajda, Sylwester Nawrocki
Remove unused /camera/clock-controller node and required clock properties
to the camera node. This is required for a clock provider that will be
referenced by image sensor devices.
Signed-off-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
Acked-by: Kyungmin Park <kyungmin.park@samsung.com>
---
arch/arm/boot/dts/exynos4.dtsi | 6 ++----
1 file changed, 2 insertions(+), 4 deletions(-)
diff --git a/arch/arm/boot/dts/exynos4.dtsi b/arch/arm/boot/dts/exynos4.dtsi
index 08452e1..d1ee347 100644
--- a/arch/arm/boot/dts/exynos4.dtsi
+++ b/arch/arm/boot/dts/exynos4.dtsi
@@ -109,12 +109,10 @@
status = "disabled";
#address-cells = <1>;
#size-cells = <1>;
+ #clock-cells = <1>;
+ clock-output-names = "cam_mclk_a", "cam_mclk_b";
ranges;
- clock_cam: clock-controller {
- #clock-cells = <1>;
- };
-
fimc_0: fimc@11800000 {
compatible = "samsung,exynos4210-fimc";
reg = <0x11800000 0x1000>;
--
1.7.9.5
^ permalink raw reply related [flat|nested] 20+ messages in thread
* Re: [PATCH v4 02/10] Documentation: dt: Add DT binding documentation for S5C73M3 camera
2014-02-20 19:40 ` [PATCH v4 02/10] Documentation: dt: Add DT binding documentation for S5C73M3 camera Sylwester Nawrocki
@ 2014-02-21 15:42 ` Mark Rutland
2014-02-21 17:52 ` Sylwester Nawrocki
0 siblings, 1 reply; 20+ messages in thread
From: Mark Rutland @ 2014-02-21 15:42 UTC (permalink / raw)
To: Sylwester Nawrocki
Cc: linux-media@vger.kernel.org, devicetree@vger.kernel.org,
linux-samsung-soc@vger.kernel.org,
linux-arm-kernel@lists.infradead.org, robh+dt@kernel.org,
galak@codeaurora.org, kyungmin.park@samsung.com,
kgene.kim@samsung.com, a.hajda@samsung.com
On Thu, Feb 20, 2014 at 07:40:29PM +0000, Sylwester Nawrocki wrote:
> This adds DT binding documentation for Samsung S5C73M3 camera sensor
> with an embedded ISP.
>
> Signed-off-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
> Acked-by: Kyungmin Park <kyungmin.park@samsung.com>
> ---
> Changes since v3:
> - DT binding documentation separated into this patch;
>
> Changes since v2:
> - rephrased 'clocks' and 'clock-names' properties' description;
> ---
> .../devicetree/bindings/media/samsung-s5c73m3.txt | 97 ++++++++++++++++++++
> 1 file changed, 97 insertions(+)
> create mode 100644 Documentation/devicetree/bindings/media/samsung-s5c73m3.txt
>
> diff --git a/Documentation/devicetree/bindings/media/samsung-s5c73m3.txt b/Documentation/devicetree/bindings/media/samsung-s5c73m3.txt
> new file mode 100644
> index 0000000..4dd3776
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/media/samsung-s5c73m3.txt
> @@ -0,0 +1,97 @@
> +Samsung S5C73M3 8Mp camera ISP
> +------------------------------
> +
> +The S5C73M3 camera ISP supports MIPI CSI-2 and parallel (ITU-R BT.656) video
> +data busses. The I2C bus is the main control bus and additionally the SPI bus
> +is used, mostly for transferring the firmware to and from the device. Two
> +slave device nodes corresponding to these control bus interfaces are required
> +and should be placed under respective bus controller nodes.
So this has both an I2C interface and an SPI interface that are used at
the same time?
> +
> +I2C slave device node
> +---------------------
> +
> +Required properties:
> +
> +- compatible : "samsung,s5c73m3";
> +- reg : I2C slave address of the sensor;
> +- vdd-int-supply : digital power supply (1.2V);
> +- vdda-supply : analog power supply (1.2V);
> +- vdd-reg-supply : regulator input power supply (2.8V);
> +- vddio-host-supply : host I/O power supply (1.8V to 2.8V);
> +- vddio-cis-supply : CIS I/O power supply (1.2V to 1.8V);
> +- vdd-af-supply : lens power supply (2.8V);
> +- xshutdown-gpios : specifier of GPIO connected to the XSHUTDOWN pin;
> +- standby-gpios : specifier of GPIO connected to the STANDBY pin;
> +- clocks : should contain list of phandle and clock specifier pairs
> + according to common clock bindings for the clocks described
> + in the clock-names property;
> +- clock-names : should contain "cis_extclk" entry for the CIS_EXTCLK clock;
> +
> +Optional properties:
> +
> +- clock-frequency : the frequency at which the "cis_extclk" clock should be
> + configured to operate, in Hz; if this property is not
> + specified default 24 MHz value will be used.
> +
> +The common video interfaces bindings (see video-interfaces.txt) should be used
> +to specify link from the S5C73M3 to an external image data receiver. The S5C73M3
> +device node should contain one 'port' child node with an 'endpoint' subnode for
> +this purpose. The data link from a raw image sensor to the S5C73M3 can be
> +similarly specified, but it is optional since the S5C73M3 ISP and a raw image
> +sensor are usually inseparable and form a hybrid module.
> +
> +Following properties are valid for the endpoint node(s):
> +
> +endpoint subnode
> +----------------
> +
> +- data-lanes : (optional) specifies MIPI CSI-2 data lanes as covered in
> + video-interfaces.txt. This sensor doesn't support data lane remapping
> + and physical lane indexes in subsequent elements of the array should
> + be only consecutive ascending values.
> +
> +SPI device node
> +---------------
> +
> +Required properties:
> +
> +- compatible : "samsung,s5c73m3";
It might make sense to explicitly link these two nodes somehow, in case
multiple instances appear somewhere. However, that can come later in the
case of a multi-instance device, and isn't necessary now.
> +
> +For more details see description of the SPI busses bindings
> +(../spi/spi-bus.txt) and bindings of a specific bus controller.
> +
> +Example:
> +
> +i2c@138A000000 {
> + ...
> + s5c73m3@3c {
> + compatible = "samsung,s5c73m3";
> + reg = <0x3c>;
> + vdd-int-supply = <&buck9_reg>;
> + vdda-supply = <&ldo17_reg>;
> + vdd-reg-supply = <&cam_io_reg>;
> + vddio-host-supply = <&ldo18_reg>;
> + vddio-cis-supply = <&ldo9_reg>;
> + vdd-af-supply = <&cam_af_reg>;
> + clock-frequency = <24000000>;
> + clocks = <&clk 0>;
> + clock-names = "cis_extclk";
> + reset-gpios = <&gpf1 3 1>;
> + standby-gpios = <&gpm0 1 1>;
> + port {
> + s5c73m3_ep: endpoint {
> + remote-endpoint = <&csis0_ep>;
> + data-lanes = <1 2 3 4>;
> + };
> + };
> + };
> +};
> +
> +spi@1392000 {
> + ...
> + s5c73m3_spi: s5c73m3 {
Nit: this should have a 0 unit-address to match the reg.
> + compatible = "samsung,s5c73m3";
> + reg = <0>;
> + ...
> + };
> +};
Otherwise I don't see anything problematic about the binding.
Acked-by: Mark Rutland <mark.rutland@arm.com>
Cheers,
Mark.
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH v4 03/10] Documentation: devicetree: Update Samsung FIMC DT binding
2014-02-20 19:40 ` [PATCH v4 03/10] Documentation: devicetree: Update Samsung FIMC DT binding Sylwester Nawrocki
@ 2014-02-21 15:50 ` Mark Rutland
2014-02-22 22:02 ` Sylwester Nawrocki
0 siblings, 1 reply; 20+ messages in thread
From: Mark Rutland @ 2014-02-21 15:50 UTC (permalink / raw)
To: Sylwester Nawrocki
Cc: linux-media@vger.kernel.org, devicetree@vger.kernel.org,
linux-samsung-soc@vger.kernel.org,
linux-arm-kernel@lists.infradead.org, robh+dt@kernel.org,
galak@codeaurora.org, kyungmin.park@samsung.com,
kgene.kim@samsung.com, a.hajda@samsung.com
On Thu, Feb 20, 2014 at 07:40:30PM +0000, Sylwester Nawrocki wrote:
> This patch documents following updates of the Exynos4 SoC camera subsystem
> devicetree binding:
> - addition of #clock-cells property to 'camera' node - the #clock-cells
> property is needed when the sensor sub-devices use clock provided by
> the camera host interface;
> - addition of an optional clock-output-names property;
> - change of the clock-frequency at image sensor node from mandatory to
> an optional property - there should be no need to require this property
> by the camera host device binding, a default frequency value can ofen
> be used;
> - addition of a requirement of specific order of values in clocks/
> clock-names properties, so the first two entry in the clock-names
> property can be used as parent clock names for the camera master
> clock provider. It happens all in-kernel dts files list the clock
> in such order, thus there should be no regression as far as in-kernel
> dts files are concerned.
I'm not sure I follow the reasoning here. Why does this matter? Why can
child nodes not get these by name if they have to?
>
> Signed-off-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
> Acked-by: Kyungmin Park <kyungmin.park@samsung.com>
> ---
> .../devicetree/bindings/media/samsung-fimc.txt | 36 +++++++++++++++-----
> 1 file changed, 28 insertions(+), 8 deletions(-)
>
> diff --git a/Documentation/devicetree/bindings/media/samsung-fimc.txt b/Documentation/devicetree/bindings/media/samsung-fimc.txt
> index 96312f6..1a5820d 100644
> --- a/Documentation/devicetree/bindings/media/samsung-fimc.txt
> +++ b/Documentation/devicetree/bindings/media/samsung-fimc.txt
> @@ -20,6 +20,7 @@ Required properties:
> the clock-names property;
> - clock-names : must contain "sclk_cam0", "sclk_cam1", "pxl_async0",
> "pxl_async1" entries, matching entries in the clocks property.
> + First two entries must be "sclk_cam0", "sclk_cam1".
I don't think this is a good idea.
>
> The pinctrl bindings defined in ../pinctrl/pinctrl-bindings.txt must be used
> to define a required pinctrl state named "default" and optional pinctrl states:
> @@ -32,6 +33,22 @@ way around.
>
> The 'camera' node must include at least one 'fimc' child node.
>
> +Optional properties (*:
Is that a smiley face?
> +
> +- #clock-cells: from the common clock bindings (../clock/clock-bindings.txt),
> + must be 1. A clock provider is associated with the 'camera' node and it should
> + be referenced by external sensors that use clocks provided by the SoC on
> + CAM_*_CLKOUT pins. The clock specifier cell stores an index of a clock.
> + The indices are 0, 1 for CAM_A_CLKOUT, CAM_B_CLKOUT clocks respectively.
> +
> +- clock-output-names: from the common clock bindings, should contain names of
> + clocks registered by the camera subsystem corresponding to CAM_A_CLKOUT,
> + CAM_B_CLKOUT output clocks, in this order. Parent clock of these clocks are
> + specified be first two entries of the clock-names property.
Do you need this?
That's not how clock-names is supposed to work. The clock-names property
is for the names of the _input_ clock lines on the device, not the
output names on whichever parent clock they came from.
Any clock-names property description should define absolutely the set of
names. As this does not, NAK.
> +
> +(* #clock-cells and clock-output-names are mandatory properties if external
> +image sensor devices reference 'camera' device node as a clock provider.
s/(*/Note:/
> +
> 'fimc' device nodes
> -------------------
>
> @@ -97,8 +114,8 @@ Image sensor nodes
> The sensor device nodes should be added to their control bus controller (e.g.
> I2C0) nodes and linked to a port node in the csis or the parallel-ports node,
> using the common video interfaces bindings, defined in video-interfaces.txt.
> -The implementation of this bindings requires clock-frequency property to be
> -present in the sensor device nodes.
> +An optional clock-frequency property needs to be present in the sensor device
> +nodes. Default value when this property is not present is 24 MHz.
s/needs to/should/ ?
What is this the frequency of?
Thanks,
Mark.
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH v4 07/10] exynos4-is: Add clock provider for the SCLK_CAM clock outputs
2014-02-20 19:40 ` [PATCH v4 07/10] exynos4-is: Add clock provider for the SCLK_CAM clock outputs Sylwester Nawrocki
@ 2014-02-21 16:05 ` Mark Rutland
[not found] ` <20140221160504.GG20449-NuALmloUBlrZROr8t4l/smS4ubULX0JqMm0uRHvK7Nw@public.gmane.org>
0 siblings, 1 reply; 20+ messages in thread
From: Mark Rutland @ 2014-02-21 16:05 UTC (permalink / raw)
To: Sylwester Nawrocki
Cc: linux-media@vger.kernel.org, devicetree@vger.kernel.org,
linux-samsung-soc@vger.kernel.org,
linux-arm-kernel@lists.infradead.org, robh+dt@kernel.org,
galak@codeaurora.org, kyungmin.park@samsung.com,
kgene.kim@samsung.com, a.hajda@samsung.com
On Thu, Feb 20, 2014 at 07:40:34PM +0000, Sylwester Nawrocki wrote:
> This patch adds clock provider so the the SCLK_CAM0/1 output clocks
> can be accessed by image sensor devices through the clk API.
>
> Signed-off-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
> Acked-by: Kyungmin Park <kyungmin.park@samsung.com>
> ---
> Changes since v3:
> - use clock-output-names DT property instead of hard coding names
> of registered clocks in the driver; first two entries of the
> clock-names property value are used to specify parent clocks of
> cam_{a,b}_clkout clocks, rather than hard coding it to sclk_cam{0,1}
> in the driver.
> - addressed issues pointed out in review by Mauro.
>
> Changes since v2:
> - use 'camera' DT node drirectly as clock provider node, rather than
> creating additional clock-controller child node.
> - DT binding documentation moved to a separate patch.
> ---
> drivers/media/platform/exynos4-is/media-dev.c | 110 +++++++++++++++++++++++++
> drivers/media/platform/exynos4-is/media-dev.h | 19 ++++-
> 2 files changed, 128 insertions(+), 1 deletion(-)
[...]
> +static int fimc_md_register_clk_provider(struct fimc_md *fmd)
> +{
> + struct cam_clk_provider *cp = &fmd->clk_provider;
> + struct device *dev = &fmd->pdev->dev;
> + int i, ret;
> +
> + for (i = 0; i < ARRAY_SIZE(cp->clks); i++) {
> + struct cam_clk *camclk = &cp->camclk[i];
> + struct clk_init_data init;
> +
> + ret = of_property_read_string_index(dev->of_node,
> + "clock-output-names", i, &init.name);
Are there not well-defined names for the clock outputs of the block?
> + if (ret < 0)
> + break;
> +
> + ret = of_property_read_string_index(dev->of_node,
> + "clock-names", i, init.parent_names);
This shouldn't be a parent name. It should be the input line name.
I don't think this makes sense.
Why do you need the name of the parent clock?
> + if (ret < 0)
> + break;
> +
> + init.num_parents = 1;
> + init.ops = &cam_clk_ops;
> + init.flags = CLK_SET_RATE_PARENT;
> + camclk->hw.init = &init;
> + camclk->fmd = fmd;
> +
> + cp->clks[i] = clk_register(NULL, &camclk->hw);
> + if (IS_ERR(cp->clks[i])) {
> + dev_err(dev, "failed to register clock: %s (%ld)\n",
> + init.name, PTR_ERR(cp->clks[i]));
> + ret = PTR_ERR(cp->clks[i]);
> + goto err;
> + }
> + cp->num_clocks++;
> + }
> +
> + if (cp->num_clocks == 0) {
> + dev_warn(dev, "clk provider not registered\n");
> + return 0;
> + }
> +
> + cp->clk_data.clks = cp->clks;
> + cp->clk_data.clk_num = cp->num_clocks;
> + cp->of_node = dev->of_node;
> + ret = of_clk_add_provider(dev->of_node, of_clk_src_onecell_get,
> + &cp->clk_data);
Are _all_ of the input clock lines available to children in hardware?
The binding and commit message(s) implied only two clocks were, so
what's the point in exporting clocks which aren't available?
Thanks,
Mark.
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH v4 02/10] Documentation: dt: Add DT binding documentation for S5C73M3 camera
2014-02-21 15:42 ` Mark Rutland
@ 2014-02-21 17:52 ` Sylwester Nawrocki
0 siblings, 0 replies; 20+ messages in thread
From: Sylwester Nawrocki @ 2014-02-21 17:52 UTC (permalink / raw)
To: Mark Rutland
Cc: linux-media@vger.kernel.org, devicetree@vger.kernel.org,
linux-samsung-soc@vger.kernel.org,
linux-arm-kernel@lists.infradead.org, robh+dt@kernel.org,
galak@codeaurora.org, kyungmin.park@samsung.com,
kgene.kim@samsung.com, a.hajda@samsung.com
On 21/02/14 16:42, Mark Rutland wrote:
[...]
>> +++ b/Documentation/devicetree/bindings/media/samsung-s5c73m3.txt
>> @@ -0,0 +1,97 @@
>> +Samsung S5C73M3 8Mp camera ISP
>> +------------------------------
>> +
>> +The S5C73M3 camera ISP supports MIPI CSI-2 and parallel (ITU-R BT.656) video
>> +data busses. The I2C bus is the main control bus and additionally the SPI bus
>> +is used, mostly for transferring the firmware to and from the device. Two
>> +slave device nodes corresponding to these control bus interfaces are required
>> +and should be placed under respective bus controller nodes.
>
> So this has both an I2C interface and an SPI interface that are used at
> the same time?
Yes, both are needed. AFAIU SPI is added so the firmware upload is faster.
>> +I2C slave device node
>> +---------------------
>> +
>> +Required properties:
>> +
>> +- compatible : "samsung,s5c73m3";
>> +- reg : I2C slave address of the sensor;
>> +- vdd-int-supply : digital power supply (1.2V);
>> +- vdda-supply : analog power supply (1.2V);
>> +- vdd-reg-supply : regulator input power supply (2.8V);
>> +- vddio-host-supply : host I/O power supply (1.8V to 2.8V);
>> +- vddio-cis-supply : CIS I/O power supply (1.2V to 1.8V);
>> +- vdd-af-supply : lens power supply (2.8V);
>> +- xshutdown-gpios : specifier of GPIO connected to the XSHUTDOWN pin;
>> +- standby-gpios : specifier of GPIO connected to the STANDBY pin;
>> +- clocks : should contain list of phandle and clock specifier pairs
>> + according to common clock bindings for the clocks described
>> + in the clock-names property;
>> +- clock-names : should contain "cis_extclk" entry for the CIS_EXTCLK clock;
>> +
>> +Optional properties:
>> +
>> +- clock-frequency : the frequency at which the "cis_extclk" clock should be
>> + configured to operate, in Hz; if this property is not
>> + specified default 24 MHz value will be used.
>> +
>> +The common video interfaces bindings (see video-interfaces.txt) should be used
>> +to specify link from the S5C73M3 to an external image data receiver. The S5C73M3
>> +device node should contain one 'port' child node with an 'endpoint' subnode for
>> +this purpose. The data link from a raw image sensor to the S5C73M3 can be
>> +similarly specified, but it is optional since the S5C73M3 ISP and a raw image
>> +sensor are usually inseparable and form a hybrid module.
>> +
>> +Following properties are valid for the endpoint node(s):
>> +
>> +endpoint subnode
>> +----------------
>> +
>> +- data-lanes : (optional) specifies MIPI CSI-2 data lanes as covered in
>> + video-interfaces.txt. This sensor doesn't support data lane remapping
>> + and physical lane indexes in subsequent elements of the array should
>> + be only consecutive ascending values.
>> +
>> +SPI device node
>> +---------------
>> +
>> +Required properties:
>> +
>> +- compatible : "samsung,s5c73m3";
>
> It might make sense to explicitly link these two nodes somehow, in case
> multiple instances appear somewhere. However, that can come later in the
> case of a multi-instance device, and isn't necessary now.
I guess a phandle at the I2C slave device node, pointing to the SPI node
and/or the other way around would do. I don't expect these devices to be
used in multiple instances though and would prefer to address that when
necessary.
We could try and create a root node for this device with an interesting
structure, if we wanted to go much into details. But it could get a bit
complicated given the scheme the I2C/SPI bus binding are structured now.
Presumably that's something that could be handled later with a different
compatible string if required.
>> +For more details see description of the SPI busses bindings
>> +(../spi/spi-bus.txt) and bindings of a specific bus controller.
>> +
>> +Example:
>> +
>> +i2c@138A000000 {
>> + ...
>> + s5c73m3@3c {
>> + compatible = "samsung,s5c73m3";
>> + reg = <0x3c>;
>> + vdd-int-supply = <&buck9_reg>;
>> + vdda-supply = <&ldo17_reg>;
>> + vdd-reg-supply = <&cam_io_reg>;
>> + vddio-host-supply = <&ldo18_reg>;
>> + vddio-cis-supply = <&ldo9_reg>;
>> + vdd-af-supply = <&cam_af_reg>;
>> + clock-frequency = <24000000>;
>> + clocks = <&clk 0>;
>> + clock-names = "cis_extclk";
>> + reset-gpios = <&gpf1 3 1>;
>> + standby-gpios = <&gpm0 1 1>;
>> + port {
>> + s5c73m3_ep: endpoint {
>> + remote-endpoint = <&csis0_ep>;
>> + data-lanes = <1 2 3 4>;
>> + };
>> + };
>> + };
>> +};
>> +
>> +spi@1392000 {
>> + ...
>> + s5c73m3_spi: s5c73m3 {
>
> Nit: this should have a 0 unit-address to match the reg.
OK, I'll correct that.
>> + compatible = "samsung,s5c73m3";
>> + reg = <0>;
>> + ...
>> + };
>> +};
>
> Otherwise I don't see anything problematic about the binding.
>
> Acked-by: Mark Rutland <mark.rutland@arm.com>
Thanks for the review.
--
Regards,
Sylwester
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH v4 03/10] Documentation: devicetree: Update Samsung FIMC DT binding
2014-02-21 15:50 ` Mark Rutland
@ 2014-02-22 22:02 ` Sylwester Nawrocki
2014-02-22 22:26 ` Tomasz Figa
0 siblings, 1 reply; 20+ messages in thread
From: Sylwester Nawrocki @ 2014-02-22 22:02 UTC (permalink / raw)
To: Mark Rutland
Cc: Sylwester Nawrocki, linux-media@vger.kernel.org,
devicetree@vger.kernel.org, linux-samsung-soc@vger.kernel.org,
linux-arm-kernel@lists.infradead.org, robh+dt@kernel.org,
galak@codeaurora.org, kyungmin.park@samsung.com,
kgene.kim@samsung.com, a.hajda@samsung.com
On 02/21/2014 04:50 PM, Mark Rutland wrote:
> On Thu, Feb 20, 2014 at 07:40:30PM +0000, Sylwester Nawrocki wrote:
>> This patch documents following updates of the Exynos4 SoC camera subsystem
>> devicetree binding:
>> - addition of #clock-cells property to 'camera' node - the #clock-cells
>> property is needed when the sensor sub-devices use clock provided by
>> the camera host interface;
>> - addition of an optional clock-output-names property;
>> - change of the clock-frequency at image sensor node from mandatory to
>> an optional property - there should be no need to require this property
>> by the camera host device binding, a default frequency value can ofen
>> be used;
>> - addition of a requirement of specific order of values in clocks/
>> clock-names properties, so the first two entry in the clock-names
>> property can be used as parent clock names for the camera master
>> clock provider. It happens all in-kernel dts files list the clock
>> in such order, thus there should be no regression as far as in-kernel
>> dts files are concerned.
>
> I'm not sure I follow the reasoning here. Why does this matter? Why can
> child nodes not get these by name if they have to?
These input clocks won't be used directly by child nodes. More details
below...
>> Signed-off-by: Sylwester Nawrocki<s.nawrocki@samsung.com>
>> Acked-by: Kyungmin Park<kyungmin.park@samsung.com>
>> ---
>> .../devicetree/bindings/media/samsung-fimc.txt | 36 +++++++++++++++-----
>> 1 file changed, 28 insertions(+), 8 deletions(-)
>>
>> diff --git a/Documentation/devicetree/bindings/media/samsung-fimc.txt b/Documentation/devicetree/bindings/media/samsung-fimc.txt
>> index 96312f6..1a5820d 100644
>> --- a/Documentation/devicetree/bindings/media/samsung-fimc.txt
>> +++ b/Documentation/devicetree/bindings/media/samsung-fimc.txt
>> @@ -20,6 +20,7 @@ Required properties:
>> the clock-names property;
>> - clock-names : must contain "sclk_cam0", "sclk_cam1", "pxl_async0",
>> "pxl_async1" entries, matching entries in the clocks property.
>> + First two entries must be "sclk_cam0", "sclk_cam1".
>
> I don't think this is a good idea.
>
>>
>> The pinctrl bindings defined in ../pinctrl/pinctrl-bindings.txt must be used
>> to define a required pinctrl state named "default" and optional pinctrl states:
>> @@ -32,6 +33,22 @@ way around.
>>
>> The 'camera' node must include at least one 'fimc' child node.
>>
>> +Optional properties (*:
>
> Is that a smiley face?
Sorry, it was supposed to be a reference mark, will remove this.
>> +- #clock-cells: from the common clock bindings (../clock/clock-bindings.txt),
>> + must be 1. A clock provider is associated with the 'camera' node and it should
>> + be referenced by external sensors that use clocks provided by the SoC on
>> + CAM_*_CLKOUT pins. The clock specifier cell stores an index of a clock.
>> + The indices are 0, 1 for CAM_A_CLKOUT, CAM_B_CLKOUT clocks respectively.
>> +
>> +- clock-output-names: from the common clock bindings, should contain names of
>> + clocks registered by the camera subsystem corresponding to CAM_A_CLKOUT,
>> + CAM_B_CLKOUT output clocks, in this order. Parent clock of these clocks are
>> + specified be first two entries of the clock-names property.
>
> Do you need this?
All right, that might have been a bad idea, it mixes names of clocks
registered
by the main clock controller with names of clock input lines at the device.
It's a mistake I have been usually sensitive to and now made it myself. :/
My intention was to maintain the clock tree, since the camera block doesn't
generate the clock itself, it merely passes through the clocks from the
SoC main
clock controller (CMU). So clk parents need to be properly set and since
there
is no clock-output-names property at the CMU DT node,
of_clk_get_parent_name()
cannot be used.
So presumably the DT binding would be only specifying that the sclk_cam0,
sclk_cam1 clock input entries are associated with output clocks named as
in clock-output-names property.
And the driver could either:
1) hard code those (well defined) CMU clock (clk parent) names,
2) clk_get() its input clock, retrieve name with __clk_get_name() and
pass
it as parent name to clk_register() - it sounds a bit hacky though.
The output clock names could be also well defined by the binding per the
IP's
compatible. Nevertheless using clock-output-names seems cleaner to me than
defining character strings in the driver.
What do you think ?
> That's not how clock-names is supposed to work. The clock-names property
> is for the names of the _input_ clock lines on the device, not the
> output names on whichever parent clock they came from.
Yes, I agree, that was a pretty bad abuse of the bindings.
> Any clock-names property description should define absolutely the set of
> names. As this does not, NAK.
>
>> +
>> +(* #clock-cells and clock-output-names are mandatory properties if external
>> +image sensor devices reference 'camera' device node as a clock provider.
>
> s/(*/Note:/
Thanks, will fix that.
>> 'fimc' device nodes
>> -------------------
>>
>> @@ -97,8 +114,8 @@ Image sensor nodes
>> The sensor device nodes should be added to their control bus controller (e.g.
>> I2C0) nodes and linked to a port node in the csis or the parallel-ports node,
>> using the common video interfaces bindings, defined in video-interfaces.txt.
>> -The implementation of this bindings requires clock-frequency property to be
>> -present in the sensor device nodes.
>> +An optional clock-frequency property needs to be present in the sensor device
>> +nodes. Default value when this property is not present is 24 MHz.
>
> s/needs to/should/ ?
Sounds better, I'll change it.
> What is this the frequency of?
It's frequency of an external sensor's master clock, which is provided
by the SoC.
Since the sensors have now possibility to control the clock themselves
the host
interface (binding) doesn't have to care about that frequency. This is
supposed
to be an assigned frequency, it has been discussed already on devicetree
mailing
list a few months ago.
--
Regards,
Sylwester
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH v4 07/10] exynos4-is: Add clock provider for the SCLK_CAM clock outputs
[not found] ` <20140221160504.GG20449-NuALmloUBlrZROr8t4l/smS4ubULX0JqMm0uRHvK7Nw@public.gmane.org>
@ 2014-02-22 22:18 ` Sylwester Nawrocki
0 siblings, 0 replies; 20+ messages in thread
From: Sylwester Nawrocki @ 2014-02-22 22:18 UTC (permalink / raw)
To: Mark Rutland
Cc: Sylwester Nawrocki,
linux-media-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
linux-samsung-soc-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org,
robh+dt-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org,
galak-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org,
kyungmin.park-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org,
kgene.kim-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org,
a.hajda-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org
On 02/21/2014 05:05 PM, Mark Rutland wrote:
>> ---
>> drivers/media/platform/exynos4-is/media-dev.c | 110 +++++++++++++++++++++++++
>> drivers/media/platform/exynos4-is/media-dev.h | 19 ++++-
>> 2 files changed, 128 insertions(+), 1 deletion(-)
...
>
>> +static int fimc_md_register_clk_provider(struct fimc_md *fmd)
>> +{
>> + struct cam_clk_provider *cp =&fmd->clk_provider;
>> + struct device *dev =&fmd->pdev->dev;
>> + int i, ret;
>> +
>> + for (i = 0; i< ARRAY_SIZE(cp->clks); i++) {
>> + struct cam_clk *camclk =&cp->camclk[i];
>> + struct clk_init_data init;
>> +
>> + ret = of_property_read_string_index(dev->of_node,
>> + "clock-output-names", i,&init.name);
>
> Are there not well-defined names for the clock outputs of the block?
There are, but this driver handles multiple SoCs so I thought it's better
to define these names in devicetree. They are supposed to be unique. Isn't
that what the clock-output-names property is for ?
>> + if (ret< 0)
>> + break;
>> +
>> + ret = of_property_read_string_index(dev->of_node,
>> + "clock-names", i, init.parent_names);
>
> This shouldn't be a parent name. It should be the input line name.
>
> I don't think this makes sense.
>
> Why do you need the name of the parent clock?
As explained in previous e-mail, it is needed to maintain the clock tree,
the parent clock names must be set properly. As the above is not correct
I could hard code these names or retrieve with __clk_get_name() from proper
input clocks. of_clk_get_parent_name() cannot be used.
>> + if (ret< 0)
>> + break;
>> +
>> + init.num_parents = 1;
>> + init.ops =&cam_clk_ops;
>> + init.flags = CLK_SET_RATE_PARENT;
>> + camclk->hw.init =&init;
>> + camclk->fmd = fmd;
>> +
>> + cp->clks[i] = clk_register(NULL,&camclk->hw);
>> + if (IS_ERR(cp->clks[i])) {
>> + dev_err(dev, "failed to register clock: %s (%ld)\n",
>> + init.name, PTR_ERR(cp->clks[i]));
>> + ret = PTR_ERR(cp->clks[i]);
>> + goto err;
>> + }
>> + cp->num_clocks++;
>> + }
>> +
>> + if (cp->num_clocks == 0) {
>> + dev_warn(dev, "clk provider not registered\n");
>> + return 0;
>> + }
>> +
>> + cp->clk_data.clks = cp->clks;
>> + cp->clk_data.clk_num = cp->num_clocks;
>> + cp->of_node = dev->of_node;
>> + ret = of_clk_add_provider(dev->of_node, of_clk_src_onecell_get,
>> + &cp->clk_data);
>
> Are _all_ of the input clock lines available to children in hardware?
This code is only for two clocks, ARRAY_SIZE(cp->clks) == 2 and
cp->num_clocks can't be greater than 2. Nevertheless, for some SoC
variants this driver handles (e.g. S5PV210) there can be only up to
two clocks listed in the camera node.
The camera interface IP block doesn't generate the clock itself, it just
passes it through when is active, i.e. its other clocks are enabled and
the power domain activated.
> The binding and commit message(s) implied only two clocks were, so
> what's the point in exporting clocks which aren't available?
I'm not sure what makes you think there is more than two ?
--
Regards,
Sylwester
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH v4 03/10] Documentation: devicetree: Update Samsung FIMC DT binding
2014-02-22 22:02 ` Sylwester Nawrocki
@ 2014-02-22 22:26 ` Tomasz Figa
2014-02-22 22:52 ` Sylwester Nawrocki
0 siblings, 1 reply; 20+ messages in thread
From: Tomasz Figa @ 2014-02-22 22:26 UTC (permalink / raw)
To: Sylwester Nawrocki, Mark Rutland
Cc: devicetree@vger.kernel.org, linux-samsung-soc@vger.kernel.org,
Mike Turquette, Tomasz Figa, a.hajda@samsung.com,
kyungmin.park@samsung.com, robh+dt@kernel.org, Sylwester Nawrocki,
galak@codeaurora.org, kgene.kim@samsung.com,
linux-arm-kernel@lists.infradead.org, linux-media@vger.kernel.org
[Ccing Mike]
On 22.02.2014 23:02, Sylwester Nawrocki wrote:
> On 02/21/2014 04:50 PM, Mark Rutland wrote:
>> On Thu, Feb 20, 2014 at 07:40:30PM +0000, Sylwester Nawrocki wrote:
>>> +- #clock-cells: from the common clock bindings
>>> (../clock/clock-bindings.txt),
>>> + must be 1. A clock provider is associated with the 'camera' node
>>> and it should
>>> + be referenced by external sensors that use clocks provided by the
>>> SoC on
>>> + CAM_*_CLKOUT pins. The clock specifier cell stores an index of a
>>> clock.
>>> + The indices are 0, 1 for CAM_A_CLKOUT, CAM_B_CLKOUT clocks
>>> respectively.
>>> +
>>> +- clock-output-names: from the common clock bindings, should contain
>>> names of
>>> + clocks registered by the camera subsystem corresponding to
>>> CAM_A_CLKOUT,
>>> + CAM_B_CLKOUT output clocks, in this order. Parent clock of these
>>> clocks are
>>> + specified be first two entries of the clock-names property.
>>
>> Do you need this?
>
> All right, that might have been a bad idea, it mixes names of clocks
> registered
> by the main clock controller with names of clock input lines at the device.
> It's a mistake I have been usually sensitive to and now made it myself. :/
>
> My intention was to maintain the clock tree, since the camera block doesn't
> generate the clock itself, it merely passes through the clocks from the
> SoC main
> clock controller (CMU). So clk parents need to be properly set and since
> there
> is no clock-output-names property at the CMU DT node,
> of_clk_get_parent_name()
> cannot be used.
>
> So presumably the DT binding would be only specifying that the sclk_cam0,
> sclk_cam1 clock input entries are associated with output clocks named as
> in clock-output-names property.
>
> And the driver could either:
> 1) hard code those (well defined) CMU clock (clk parent) names,
I don't think this would be a good idea, as those CMU clock names may
vary between SoCs.
> 2) clk_get() its input clock, retrieve name with __clk_get_name() and
> pass
> it as parent name to clk_register() - it sounds a bit hacky though.
This looks fine, at least until proper interface is added to CCF. Exynos
audio subsystem clock driver does exactly the same.
However, the right thing would be to make it possible to use pointers to
struct clk instead of strings to list parent(s). This could be done by
adding .parents field (struct clk **) to clk_init_data struct and make
clk_register() use it if available.
>
> The output clock names could be also well defined by the binding per the
> IP's
> compatible. Nevertheless using clock-output-names seems cleaner to me than
> defining character strings in the driver.
>
> What do you think ?
<RANT>
Personally, I don't like clock-output-names at all. The idea of having a
global namespace for all clock providers looks flawed to me. This
property only tries to work around the not-quite-right design by giving
device tree the right to force CCF to use particular internal clock
identifiers and avoid collisions if two providers happen to have the
same internal clock names.
I believe there should be completely no need for clock-output-names,
(other than a textual label for debugging purposes, analogically to
regulator-name). If one clock provider needs a clock from another, then
you should list it using clock bindings in node of the former, not rely
on some static name assignments.
Then, after eliminating the need to use static names anymore, the
namespace could be split into per-provider namespaces and we would have
no collision issue anymore.
Of course it's probably to late already for such changes, as there are
already systems relying on clock-output-names (i.e. without inter-IP
clock dependencies listed using clock bindings) and we would have to
keep backwards compatibility anyway...
</RANT>
Best regards,
Tomasz
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH v4 03/10] Documentation: devicetree: Update Samsung FIMC DT binding
2014-02-22 22:26 ` Tomasz Figa
@ 2014-02-22 22:52 ` Sylwester Nawrocki
0 siblings, 0 replies; 20+ messages in thread
From: Sylwester Nawrocki @ 2014-02-22 22:52 UTC (permalink / raw)
To: Tomasz Figa
Cc: Mark Rutland, Sylwester Nawrocki, linux-media@vger.kernel.org,
devicetree@vger.kernel.org, linux-samsung-soc@vger.kernel.org,
linux-arm-kernel@lists.infradead.org, robh+dt@kernel.org,
galak@codeaurora.org, kyungmin.park@samsung.com,
kgene.kim@samsung.com, a.hajda@samsung.com, Mike Turquette,
Tomasz Figa
On 02/22/2014 11:26 PM, Tomasz Figa wrote:
> [Ccing Mike]
>
> On 22.02.2014 23:02, Sylwester Nawrocki wrote:
>> On 02/21/2014 04:50 PM, Mark Rutland wrote:
>>> On Thu, Feb 20, 2014 at 07:40:30PM +0000, Sylwester Nawrocki wrote:
>>>> +- #clock-cells: from the common clock bindings
>>>> (../clock/clock-bindings.txt),
>>>> + must be 1. A clock provider is associated with the 'camera' node
>>>> and it should
>>>> + be referenced by external sensors that use clocks provided by the
>>>> SoC on
>>>> + CAM_*_CLKOUT pins. The clock specifier cell stores an index of a
>>>> clock.
>>>> + The indices are 0, 1 for CAM_A_CLKOUT, CAM_B_CLKOUT clocks
>>>> respectively.
>>>> +
>>>> +- clock-output-names: from the common clock bindings, should contain
>>>> names of
>>>> + clocks registered by the camera subsystem corresponding to
>>>> CAM_A_CLKOUT,
>>>> + CAM_B_CLKOUT output clocks, in this order. Parent clock of these
>>>> clocks are
>>>> + specified be first two entries of the clock-names property.
>>>
>>> Do you need this?
>>
>> All right, that might have been a bad idea, it mixes names of clocks
>> registered
>> by the main clock controller with names of clock input lines at the
>> device.
>> It's a mistake I have been usually sensitive to and now made it
>> myself. :/
>>
>> My intention was to maintain the clock tree, since the camera block
>> doesn't
>> generate the clock itself, it merely passes through the clocks from the
>> SoC main
>> clock controller (CMU). So clk parents need to be properly set and since
>> there is no clock-output-names property at the CMU DT node,
>> of_clk_get_parent_name() cannot be used.
>>
>> So presumably the DT binding would be only specifying that the sclk_cam0,
>> sclk_cam1 clock input entries are associated with output clocks named as
>> in clock-output-names property.
>>
>> And the driver could either:
>> 1) hard code those (well defined) CMU clock (clk parent) names,
>
> I don't think this would be a good idea, as those CMU clock names may
> vary between SoCs.
For the record, I'm not in favour of this approach, even though these clock
names happen to be same for all relevant SoCs.
>> 2) clk_get() its input clock, retrieve name with __clk_get_name() and
>> pass
>> it as parent name to clk_register() - it sounds a bit hacky though.
>
> This looks fine, at least until proper interface is added to CCF. Exynos
> audio subsystem clock driver does exactly the same.
Hmm, I looked at this driver and somehow missed that.
> However, the right thing would be to make it possible to use pointers to
> struct clk instead of strings to list parent(s). This could be done by
> adding .parents field (struct clk **) to clk_init_data struct and make
> clk_register() use it if available.
We would just need to ensure the locking is done properly.
--
Regards,
Sylwester
^ permalink raw reply [flat|nested] 20+ messages in thread
end of thread, other threads:[~2014-02-22 22:52 UTC | newest]
Thread overview: 20+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-02-20 19:40 [PATCH v4 00/10] Add device tree support for Exynos4 SoC camera subsystem Sylwester Nawrocki
2014-02-20 19:40 ` Sylwester Nawrocki
2014-02-20 19:40 ` [PATCH v4 01/10] Documentation: dt: Add DT binding documentation for S5K6A3 image sensor Sylwester Nawrocki
2014-02-20 19:40 ` [PATCH v4 02/10] Documentation: dt: Add DT binding documentation for S5C73M3 camera Sylwester Nawrocki
2014-02-21 15:42 ` Mark Rutland
2014-02-21 17:52 ` Sylwester Nawrocki
2014-02-20 19:40 ` [PATCH v4 03/10] Documentation: devicetree: Update Samsung FIMC DT binding Sylwester Nawrocki
2014-02-21 15:50 ` Mark Rutland
2014-02-22 22:02 ` Sylwester Nawrocki
2014-02-22 22:26 ` Tomasz Figa
2014-02-22 22:52 ` Sylwester Nawrocki
[not found] ` <1392925237-31394-1-git-send-email-s.nawrocki-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org>
2014-02-20 19:40 ` [PATCH v4 04/10] V4L: Add driver for s5k6a3 image sensor Sylwester Nawrocki
2014-02-20 19:40 ` [PATCH v4 05/10] V4L: s5c73m3: Add device tree support Sylwester Nawrocki
2014-02-20 19:40 ` [PATCH v4 06/10] exynos4-is: Use external s5k6a3 sensor driver Sylwester Nawrocki
2014-02-20 19:40 ` [PATCH v4 07/10] exynos4-is: Add clock provider for the SCLK_CAM clock outputs Sylwester Nawrocki
2014-02-21 16:05 ` Mark Rutland
[not found] ` <20140221160504.GG20449-NuALmloUBlrZROr8t4l/smS4ubULX0JqMm0uRHvK7Nw@public.gmane.org>
2014-02-22 22:18 ` Sylwester Nawrocki
2014-02-20 19:40 ` [PATCH v4 08/10] exynos4-is: Add support for asynchronous subdevices registration Sylwester Nawrocki
2014-02-20 19:40 ` [PATCH v4 09/10] ARM: dts: Add rear camera nodes for Exynos4412 TRATS2 board Sylwester Nawrocki
2014-02-20 19:40 ` [PATCH v4 10/10] ARM: dts: exynos4: Update clk provider part of the camera subsystem Sylwester Nawrocki
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).