Devicetree
 help / color / mirror / Atom feed
* [PATCH net-next v3 1/4] phylib: Add device reset delay support
From: Richard Leitner @ 2017-12-05 13:25 UTC (permalink / raw)
  To: robh+dt, mark.rutland, fugang.duan, andrew, f.fainelli,
	frowand.list
  Cc: davem, geert+renesas, sergei.shtylyov, baruch, david.wu, lukma,
	netdev, devicetree, linux-kernel, richard.leitner
In-Reply-To: <20171205132600.13796-1-dev@g0hl1n.net>

From: Richard Leitner <richard.leitner@skidata.com>

Some PHYs need a minimum time after the reset gpio was asserted and/or
deasserted. To ensure we meet these timing requirements add two new
optional devicetree parameters for the phy: reset-delay-us and
reset-post-delay-us.

This patch depends on the "phylib: Add device reset GPIO support" patch
submitted by Geert Uytterhoeven/Sergei Shtylyov, see:
	https://patchwork.kernel.org/patch/10090149/

Signed-off-by: Richard Leitner <richard.leitner@skidata.com>
---
 Documentation/devicetree/bindings/net/phy.txt | 10 ++++++++++
 drivers/net/phy/mdio_device.c                 | 13 +++++++++++--
 drivers/of/of_mdio.c                          |  8 ++++++++
 include/linux/mdio.h                          |  2 ++
 4 files changed, 31 insertions(+), 2 deletions(-)

diff --git a/Documentation/devicetree/bindings/net/phy.txt b/Documentation/devicetree/bindings/net/phy.txt
index c05479f5ac7c..72860ce7f610 100644
--- a/Documentation/devicetree/bindings/net/phy.txt
+++ b/Documentation/devicetree/bindings/net/phy.txt
@@ -55,6 +55,12 @@ Optional Properties:
 
 - reset-gpios: The GPIO phandle and specifier for the PHY reset signal.
 
+- reset-delay-us: Delay after the reset was asserted in microseconds.
+  If this property is missing the delay will be skipped.
+
+- reset-post-delay-us: Delay after the reset was deasserted in microseconds.
+  If this property is missing the delay will be skipped.
+
 Example:
 
 ethernet-phy@0 {
@@ -62,4 +68,8 @@ ethernet-phy@0 {
 	interrupt-parent = <&PIC>;
 	interrupts = <35 IRQ_TYPE_EDGE_RISING>;
 	reg = <0>;
+
+	reset-gpios = <&gpio1 4 GPIO_ACTIVE_LOW>;
+	reset-delay-us = <1000>;
+	reset-post-delay-us = <2000>;
 };
diff --git a/drivers/net/phy/mdio_device.c b/drivers/net/phy/mdio_device.c
index 75d97dd9fb28..ca3ff43f8ee8 100644
--- a/drivers/net/phy/mdio_device.c
+++ b/drivers/net/phy/mdio_device.c
@@ -24,6 +24,7 @@
 #include <linux/slab.h>
 #include <linux/string.h>
 #include <linux/unistd.h>
+#include <linux/delay.h>
 
 void mdio_device_free(struct mdio_device *mdiodev)
 {
@@ -118,8 +119,16 @@ EXPORT_SYMBOL(mdio_device_remove);
 
 void mdio_device_reset(struct mdio_device *mdiodev, int value)
 {
-	if (mdiodev->reset)
-		gpiod_set_value(mdiodev->reset, value);
+	if (!mdiodev->reset)
+		return;
+
+	gpiod_set_value(mdiodev->reset, value);
+
+	if (value && mdiodev->reset_delay)
+		usleep_range(mdiodev->reset_delay, mdiodev->reset_delay + 100);
+	else if (!value && mdiodev->reset_post_delay)
+		usleep_range(mdiodev->reset_post_delay,
+			     mdiodev->reset_post_delay + 100);
 }
 EXPORT_SYMBOL(mdio_device_reset);
 
diff --git a/drivers/of/of_mdio.c b/drivers/of/of_mdio.c
index 98258583abb0..fb56486dfaa0 100644
--- a/drivers/of/of_mdio.c
+++ b/drivers/of/of_mdio.c
@@ -77,6 +77,14 @@ static int of_mdiobus_register_phy(struct mii_bus *mdio,
 	if (of_property_read_bool(child, "broken-turn-around"))
 		mdio->phy_ignore_ta_mask |= 1 << addr;
 
+	if (of_property_read_u32(child, "reset-delay-us",
+				 &phy->mdio.reset_delay))
+		phy->mdio.reset_delay = 0;
+
+	if (of_property_read_u32(child, "reset-post-delay-us",
+				 &phy->mdio.reset_post_delay))
+		phy->mdio.reset_post_delay = 0;
+
 	/* Associate the OF node with the device structure so it
 	 * can be looked up later */
 	of_node_get(child);
diff --git a/include/linux/mdio.h b/include/linux/mdio.h
index 92d4e55ffe67..e37c21d8eb19 100644
--- a/include/linux/mdio.h
+++ b/include/linux/mdio.h
@@ -41,6 +41,8 @@ struct mdio_device {
 	int addr;
 	int flags;
 	struct gpio_desc *reset;
+	unsigned int reset_delay;
+	unsigned int reset_post_delay;
 };
 #define to_mdio_device(d) container_of(d, struct mdio_device, dev)
 
-- 
2.11.0

^ permalink raw reply related

* [PATCH net-next v3 0/4] net: fec: fix refclk enable for SMSC LAN8710/20
From: Richard Leitner @ 2017-12-05 13:25 UTC (permalink / raw)
  To: robh+dt, mark.rutland, fugang.duan, andrew, f.fainelli,
	frowand.list
  Cc: davem, geert+renesas, sergei.shtylyov, baruch, david.wu, lukma,
	netdev, devicetree, linux-kernel, richard.leitner

From: Richard Leitner <richard.leitner@skidata.com>

This patch series fixes the use of the SMSC LAN8710/20 with a Freescale ETH
when the refclk is generated by the FSL.

This patch depends on the "phylib: Add device reset GPIO support" patch
submitted by Geert Uytterhoeven/Sergei Shtylyov, see:
	https://patchwork.kernel.org/patch/10090149/

Changes v3:
	- use phylib to hard-reset the PHY
	- implement reset delays in phylib
	- add new phylib API & flag (PHY_RST_AFTER_CLK_EN) to determine if a PHY
	  is affected

Changes v2:
	- simplify and fix fec_reset_phy function to support multiple calls
	- include: linux: phy: harmonize phy_id{,_mask} type
	- reset the phy instead of not turning the clock on and off
	  (which would have caused a power consumption regression)

Richard Leitner (4):
  phylib: Add device reset delay support
  phylib: add reset after clk enable support
  net: phy: smsc: LAN8710/20: add PHY_RST_AFTER_CLK_EN flag
  net: fec: add phy_reset_after_clk_enable() support

 Documentation/devicetree/bindings/net/phy.txt | 10 ++++++++++
 drivers/net/ethernet/freescale/fec_main.c     |  7 +++++++
 drivers/net/phy/mdio_device.c                 | 13 +++++++++++--
 drivers/net/phy/phy_device.c                  | 24 ++++++++++++++++++++++++
 drivers/net/phy/smsc.c                        |  2 +-
 drivers/of/of_mdio.c                          |  8 ++++++++
 include/linux/mdio.h                          |  2 ++
 include/linux/phy.h                           |  2 ++
 8 files changed, 65 insertions(+), 3 deletions(-)

-- 
2.11.0

^ permalink raw reply

* Re: [PATCH v6 4/6] dt: bindings: lp8860: Update the bindings to the standard
From: Dan Murphy @ 2017-12-05 13:06 UTC (permalink / raw)
  To: Rob Herring, Jacek Anaszewski
  Cc: rpurdie-Fm38FmjxZ/leoWH0uzbU5w, pavel-+ZI9xUNit7I,
	linux-leds-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
In-Reply-To: <20171204223500.f6ukdorpcmerzwot@rob-hp-laptop>

Rob

On 12/04/2017 04:35 PM, Rob Herring wrote:
> On Sun, Dec 03, 2017 at 02:27:20PM +0100, Jacek Anaszewski wrote:
>> Dan,
>>
>> On 12/01/2017 05:56 PM, Dan Murphy wrote:
>>> Update the lp8860 dt binding to the LED standard where
>>> the LED should have a child node and also adding a
>>> LED trigger entry.
>>>
>>> Signed-off-by: Dan Murphy <dmurphy-l0cyMroinI0@public.gmane.org>
>>> ---
>>>
>>> v6 - New patch to fix binding documentation
>>>
>>>  Documentation/devicetree/bindings/leds/leds-lp8860.txt | 15 +++++++++++----
>>>  1 file changed, 11 insertions(+), 4 deletions(-)
>>>
>>> diff --git a/Documentation/devicetree/bindings/leds/leds-lp8860.txt b/Documentation/devicetree/bindings/leds/leds-lp8860.txt
>>> index aad38dd94d4b..4cf396de6eba 100644
>>> --- a/Documentation/devicetree/bindings/leds/leds-lp8860.txt
>>> +++ b/Documentation/devicetree/bindings/leds/leds-lp8860.txt
>>> @@ -12,17 +12,24 @@ Required properties:
>>>  	- label - Used for naming LEDs
>>>  
>>>  Optional properties:
>>> -	- enable-gpio - gpio pin to enable/disable the device.
>>> -	- supply - "vled" - LED supply
>>> +	- enable-gpios : gpio pin to enable/disable the device.
>>> +	- vled-supply : LED supply
>>> +	- label : see Documentation/devicetree/bindings/leds/common.txt
>>> +	- linux,default-trigger : (optional)
>>> +	   see Documentation/devicetree/bindings/leds/common.txt
>>>  
>>>  Example:
>>>  
>>> -leds: leds@6 {
>>> +lp8860@2d {
> 
> leds@2d

Ack

> 
>>>  	compatible = "ti,lp8860";
>>>  	reg = <0x2d>;
>>> -	label = "display_cluster";
>>>  	enable-gpio = <&gpio1 28 GPIO_ACTIVE_HIGH>;
>>>  	vled-supply = <&vbatt>;
>>> +
>>> +	backlight: backlight@0 {
> 
> unit-address requires a 'reg' property. Building your dts files with W=1 
> will tell you this.

I will add this.  There is so much noise when enabling this option on the dts
I missed the warning.

Dan

<snip>

-- 
------------------
Dan Murphy
--
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

* Re: [PATCH v4 3/5] staging: Introduce NVIDIA Tegra video decoder driver
From: Hans Verkuil @ 2017-12-05 13:03 UTC (permalink / raw)
  To: Dmitry Osipenko, Thierry Reding, Jonathan Hunter,
	Greg Kroah-Hartman, Rob Herring, Mauro Carvalho Chehab,
	Stephen Warren, Vladimir Zapolskiy
  Cc: devel, devicetree, linux-kernel, linux-tegra, Maxime Ripard,
	Giulio Benetti, Dan Carpenter, linux-media
In-Reply-To: <3ac6a087-def2-014f-673d-1be9d5094635@gmail.com>

On 12/05/17 13:17, Dmitry Osipenko wrote:
> Hi Hans,
> 
> On 04.12.2017 17:04, Hans Verkuil wrote:
>> Hi Dmitry,
>>
>> As you already mention in the TODO, this should become a v4l2 codec driver.
>>
>> Good existing examples are the coda, qcom/venus and mtk-vcodec drivers.
>>
>> One thing that is not clear from this code is if the tegra hardware is a
>> stateful or stateless codec, i.e. does it keep track of the decoder state
>> in the hardware, or does the application have to keep track of the state and
>> provide the state information together with the video data?
>>
>> I ask because at the moment only stateful codecs are supported. Work is ongoing
>> to support stateless codecs, but we don't support that for now.
>>
> 
> It is stateless. Is there anything ready to try out? If yes, could you please
> give a reference to that work?

I rebased my two year old 'requests2' branch to the latest mainline version and
gave it the imaginative name 'requests3':

https://git.linuxtv.org/hverkuil/media_tree.git/log/?h=requests3

(Note: only compile tested!)

This is what ChromeOS has been using (actually they use a slightly older version)
and the new version that is currently being developed will be similar, so any work
you do on top of this will carry over to the final version without too much effort.

At least, that's the intention :-)

I've CC-ed Maxime and Giulio as well: they are looking into adding support for
the stateless allwinner codec based on this code as well. There may well be
opportunities for you to work together, esp. on the userspace side. Note that
Rockchip has the same issue, they too have a stateless HW codec.

> 
>> Anyway, I'm OK with merging this in staging. Although I think it should go
>> to staging/media since we want to keep track of it.
>>
> 
> Awesome, I'll move driver to staging/media in V5. Thanks!

Nice, thanks!

	Hans

^ permalink raw reply

* Re: [PATCH] arm64: dts: allwinner: a64: bananapi-m64: Add LED device node
From: Chen-Yu Tsai @ 2017-12-05 13:00 UTC (permalink / raw)
  To: Maxime Ripard; +Cc: Chen-Yu Tsai, devicetree, linux-arm-kernel, linux-sunxi
In-Reply-To: <20171205100511.ohxcqlrozxfgq6id-ZC1Zs529Oq4@public.gmane.org>

On Tue, Dec 5, 2017 at 6:05 PM, Maxime Ripard
<maxime.ripard-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org> wrote:
> Hi,
>
> On Sat, Dec 02, 2017 at 12:27:33AM +0800, Chen-Yu Tsai wrote:
>> The Bananapi-M64 has 3 LEDS in red, green, and blue. These are toggled
>> via GPIO lines, which drive transistors that control current across the
>> LEDS. The red LED is by default on, via an additional pull-up on the
>> control line. We consider this means that it is a power indicator.
>> So we set the "default-on" property for it.
>>
>> The pingroups the GPIO lines belong to require external regulators be
>> enabled to be able to drive the GPIO high. These regulators also have
>> other purposes. However the pin controller does not have bindings for
>> regulators. Here we just set them to always-on.
>
> I guess we should take the opportunity to do just that.
>
> We have been deferring this for quite some time now, this is a perfect
> occasion to do it once and for all :)

True. But right now I don't see an elegant solution. What is the purpose
of having the regulator tied to pinctrl / GPIO? You can't have the pinctrl
driver asking for the regulator at probe time, as it might not be available
or even have a cyclic dependency (because the PMIC is I2C driven, which
needs an I2C controller, which needs the pinctrl). If you defer fetching
the regulator to a later point, you might end up with an inconsistent state.
Again with the I2C driven regulator example, what happens if the regulator
core decides to turn the regulator off before the pinctrl side has a chance
to take a reference and enable it?


Regards
ChenYu

^ permalink raw reply

* Applied "regulator: Add Spreadtrum SC2731 regulator documentation" to the regulator tree
From: Mark Brown @ 2017-12-05 12:48 UTC (permalink / raw)
  Cc: Mark Brown
In-Reply-To: <d1e3a79db9b9a0b6c3116e06b34942b92b629ccc.1512455819.git.erick.chen@spreadtrum.com>

The patch

   regulator: Add Spreadtrum SC2731 regulator documentation

has been applied to the regulator tree at

   https://git.kernel.org/pub/scm/linux/kernel/git/broonie/regulator.git 

All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent to Linus during
the next merge window (or sooner if it is a bug fix), however if
problems are discovered then the patch may be dropped or reverted.  

You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.

If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.

Please add any relevant lists and maintainers to the CCs when replying
to this mail.

Thanks,
Mark

>From 5149b685b122d3bee78bd3403997f9ddb1223f4a Mon Sep 17 00:00:00 2001
From: Erick Chen <erick.chen@spreadtrum.com>
Date: Tue, 5 Dec 2017 14:35:45 +0800
Subject: [PATCH] regulator: Add Spreadtrum SC2731 regulator documentation

This patch adds support for the Spreadtrum SC2731
voltage regulator device.

Signed-off-by: Erick Chen <erick.chen@spreadtrum.com>
Signed-off-by: Mark Brown <broonie@kernel.org>
---
 .../bindings/regulator/sprd,sc2731-regulator.txt   | 43 ++++++++++++++++++++++
 1 file changed, 43 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/regulator/sprd,sc2731-regulator.txt

diff --git a/Documentation/devicetree/bindings/regulator/sprd,sc2731-regulator.txt b/Documentation/devicetree/bindings/regulator/sprd,sc2731-regulator.txt
new file mode 100644
index 000000000000..63dc07877cd6
--- /dev/null
+++ b/Documentation/devicetree/bindings/regulator/sprd,sc2731-regulator.txt
@@ -0,0 +1,43 @@
+Spreadtrum SC2731 Voltage regulators
+
+The SC2731 integrates low-voltage and low quiescent current DCDC/LDO.
+14 LDO and 3 DCDCs are designed for external use. All DCDCs/LDOs have
+their own bypass (power-down) control signals. External tantalum or MLCC
+ceramic capacitors are recommended to use with these LDOs.
+
+Required properties:
+ - compatible: should be "sprd,sc27xx-regulator".
+
+List of regulators provided by this controller. It is named according to
+its regulator type, BUCK_<name> and LDO_<name>. The definition for each
+of these nodes is defined using the standard binding for regulators at
+Documentation/devicetree/bindings/regulator/regulator.txt.
+
+The valid names for regulators are:
+BUCK:
+	BUCK_CPU0, BUCK_CPU1, BUCK_RF
+LDO:
+	LDO_CAMA0, LDO_CAMA1, LDO_CAMMOT, LDO_VLDO, LDO_EMMCCORE, LDO_SDCORE,
+	LDO_SDIO, LDO_WIFIPA, LDO_USB33, LDO_CAMD0, LDO_CAMD1, LDO_CON,
+	LDO_CAMIO, LDO_SRAM
+
+Example:
+	regulators {
+		compatible = "sprd,sc27xx-regulator";
+
+		vddarm0: BUCK_CPU0 {
+			regulator-name = "vddarm0";
+			regulator-min-microvolt = <400000>;
+			regulator-max-microvolt = <1996875>;
+			regulator-ramp-delay = <25000>;
+			regulator-always-on;
+		};
+
+		vddcama0: LDO_CAMA0 {
+			regulator-name = "vddcama0";
+			regulator-min-microvolt = <1200000>;
+			regulator-max-microvolt = <3750000>;
+			regulator-enable-ramp-delay = <100>;
+		};
+		...
+	};
-- 
2.15.0

^ permalink raw reply related

* Applied "regulator: sc2731: Add regulator driver to support Spreadtrum SC2731 PMIC" to the regulator tree
From: Mark Brown @ 2017-12-05 12:48 UTC (permalink / raw)
  Cc: Mark Brown
In-Reply-To: <78c65665948c11d0abc410a11cb1ecfd7c81f237.1512455819.git.erick.chen-lxIno14LUO0EEoCn2XhGlw@public.gmane.org>

The patch

   regulator: sc2731: Add regulator driver to support Spreadtrum SC2731 PMIC

has been applied to the regulator tree at

   https://git.kernel.org/pub/scm/linux/kernel/git/broonie/regulator.git 

All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent to Linus during
the next merge window (or sooner if it is a bug fix), however if
problems are discovered then the patch may be dropped or reverted.  

You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.

If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.

Please add any relevant lists and maintainers to the CCs when replying
to this mail.

Thanks,
Mark

>From 433c9bb77b8131ef340148565996b3818fbf2f23 Mon Sep 17 00:00:00 2001
From: Erick Chen <erick.chen-lxIno14LUO0EEoCn2XhGlw@public.gmane.org>
Date: Tue, 5 Dec 2017 14:35:46 +0800
Subject: [PATCH] regulator: sc2731: Add regulator driver to support Spreadtrum
 SC2731 PMIC

Add regulator driver for Spreadtrum SC2731 device.
It has 17 general purpose LDOs, BUCKs generator and
digital output to control regulators.

Signed-off-by: Erick Chen <erick.chen-lxIno14LUO0EEoCn2XhGlw@public.gmane.org>
Reviewed-by: Baolin Wang <baolin.wang-lxIno14LUO0EEoCn2XhGlw@public.gmane.org>
Signed-off-by: Mark Brown <broonie-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
---
 drivers/regulator/Kconfig            |   7 +
 drivers/regulator/Makefile           |   1 +
 drivers/regulator/sc2731-regulator.c | 256 +++++++++++++++++++++++++++++++++++
 3 files changed, 264 insertions(+)
 create mode 100644 drivers/regulator/sc2731-regulator.c

diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig
index 96cd55f9e3c5..b27417ca188a 100644
--- a/drivers/regulator/Kconfig
+++ b/drivers/regulator/Kconfig
@@ -744,6 +744,13 @@ config REGULATOR_S5M8767
 	 via I2C bus. S5M8767A have 9 Bucks and 28 LDOs output and
 	 supports DVS mode with 8bits of output voltage control.
 
+config REGULATOR_SC2731
+	tristate "Spreadtrum SC2731 power regulator driver"
+	depends on MFD_SC27XX_PMIC || COMPILE_TEST
+	help
+	  This driver provides support for the voltage regulators on the
+	  SC2731 PMIC.
+
 config REGULATOR_SKY81452
 	tristate "Skyworks Solutions SKY81452 voltage regulator"
 	depends on MFD_SKY81452
diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile
index 80ffc57a9ca3..19fea09ba10a 100644
--- a/drivers/regulator/Makefile
+++ b/drivers/regulator/Makefile
@@ -95,6 +95,7 @@ obj-$(CONFIG_REGULATOR_RT5033)	+= rt5033-regulator.o
 obj-$(CONFIG_REGULATOR_S2MPA01) += s2mpa01.o
 obj-$(CONFIG_REGULATOR_S2MPS11) += s2mps11.o
 obj-$(CONFIG_REGULATOR_S5M8767) += s5m8767.o
+obj-$(CONFIG_REGULATOR_SC2731) += sc2731-regulator.o
 obj-$(CONFIG_REGULATOR_SKY81452) += sky81452-regulator.o
 obj-$(CONFIG_REGULATOR_STM32_VREFBUF) += stm32-vrefbuf.o
 obj-$(CONFIG_REGULATOR_STW481X_VMMC) += stw481x-vmmc.o
diff --git a/drivers/regulator/sc2731-regulator.c b/drivers/regulator/sc2731-regulator.c
new file mode 100644
index 000000000000..794fcd504b3d
--- /dev/null
+++ b/drivers/regulator/sc2731-regulator.c
@@ -0,0 +1,256 @@
+ //SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2017 Spreadtrum Communications Inc.
+ */
+
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/regulator/driver.h>
+#include <linux/regulator/of_regulator.h>
+
+/*
+ * SC2731 regulator lock register
+ */
+#define SC2731_PWR_WR_PROT_VALUE	0xf0c
+#define SC2731_WR_UNLOCK		0x6e7f
+
+/*
+ * SC2731 enable register
+ */
+#define SC2731_POWER_PD_SW		0xc28
+#define SC2731_LDO_CAMA0_PD		0xcfc
+#define SC2731_LDO_CAMA1_PD		0xd04
+#define SC2731_LDO_CAMMOT_PD		0xd0c
+#define SC2731_LDO_VLDO_PD		0xd6c
+#define SC2731_LDO_EMMCCORE_PD		0xd2c
+#define SC2731_LDO_SDCORE_PD		0xd74
+#define SC2731_LDO_SDIO_PD		0xd70
+#define SC2731_LDO_WIFIPA_PD		0xd4c
+#define SC2731_LDO_USB33_PD		0xd5c
+#define SC2731_LDO_CAMD0_PD		0xd7c
+#define SC2731_LDO_CAMD1_PD		0xd84
+#define SC2731_LDO_CON_PD		0xd8c
+#define SC2731_LDO_CAMIO_PD		0xd94
+#define SC2731_LDO_SRAM_PD		0xd78
+
+/*
+ * SC2731 enable mask
+ */
+#define SC2731_DCDC_CPU0_PD_MASK	BIT(4)
+#define SC2731_DCDC_CPU1_PD_MASK	BIT(3)
+#define SC2731_DCDC_RF_PD_MASK		BIT(11)
+#define SC2731_LDO_CAMA0_PD_MASK	BIT(0)
+#define SC2731_LDO_CAMA1_PD_MASK	BIT(0)
+#define SC2731_LDO_CAMMOT_PD_MASK	BIT(0)
+#define SC2731_LDO_VLDO_PD_MASK		BIT(0)
+#define SC2731_LDO_EMMCCORE_PD_MASK	BIT(0)
+#define SC2731_LDO_SDCORE_PD_MASK	BIT(0)
+#define SC2731_LDO_SDIO_PD_MASK		BIT(0)
+#define SC2731_LDO_WIFIPA_PD_MASK	BIT(0)
+#define SC2731_LDO_USB33_PD_MASK	BIT(0)
+#define SC2731_LDO_CAMD0_PD_MASK	BIT(0)
+#define SC2731_LDO_CAMD1_PD_MASK	BIT(0)
+#define SC2731_LDO_CON_PD_MASK		BIT(0)
+#define SC2731_LDO_CAMIO_PD_MASK	BIT(0)
+#define SC2731_LDO_SRAM_PD_MASK		BIT(0)
+
+/*
+ * SC2731 vsel register
+ */
+#define SC2731_DCDC_CPU0_VOL		0xc54
+#define SC2731_DCDC_CPU1_VOL		0xc64
+#define SC2731_DCDC_RF_VOL		0xcb8
+#define SC2731_LDO_CAMA0_VOL		0xd00
+#define SC2731_LDO_CAMA1_VOL		0xd08
+#define SC2731_LDO_CAMMOT_VOL		0xd10
+#define SC2731_LDO_VLDO_VOL		0xd28
+#define SC2731_LDO_EMMCCORE_VOL		0xd30
+#define SC2731_LDO_SDCORE_VOL		0xd38
+#define SC2731_LDO_SDIO_VOL		0xd40
+#define SC2731_LDO_WIFIPA_VOL		0xd50
+#define SC2731_LDO_USB33_VOL		0xd60
+#define SC2731_LDO_CAMD0_VOL		0xd80
+#define SC2731_LDO_CAMD1_VOL		0xd88
+#define SC2731_LDO_CON_VOL		0xd90
+#define SC2731_LDO_CAMIO_VOL		0xd98
+#define SC2731_LDO_SRAM_VOL		0xdB0
+
+/*
+ * SC2731 vsel register mask
+ */
+#define SC2731_DCDC_CPU0_VOL_MASK	GENMASK(8, 0)
+#define SC2731_DCDC_CPU1_VOL_MASK	GENMASK(8, 0)
+#define SC2731_DCDC_RF_VOL_MASK		GENMASK(8, 0)
+#define SC2731_LDO_CAMA0_VOL_MASK	GENMASK(7, 0)
+#define SC2731_LDO_CAMA1_VOL_MASK	GENMASK(7, 0)
+#define SC2731_LDO_CAMMOT_VOL_MASK	GENMASK(7, 0)
+#define SC2731_LDO_VLDO_VOL_MASK	GENMASK(7, 0)
+#define SC2731_LDO_EMMCCORE_VOL_MASK	GENMASK(7, 0)
+#define SC2731_LDO_SDCORE_VOL_MASK	GENMASK(7, 0)
+#define SC2731_LDO_SDIO_VOL_MASK	GENMASK(7, 0)
+#define SC2731_LDO_WIFIPA_VOL_MASK	GENMASK(7, 0)
+#define SC2731_LDO_USB33_VOL_MASK	GENMASK(7, 0)
+#define SC2731_LDO_CAMD0_VOL_MASK	GENMASK(6, 0)
+#define SC2731_LDO_CAMD1_VOL_MASK	GENMASK(6, 0)
+#define SC2731_LDO_CON_VOL_MASK		GENMASK(6, 0)
+#define SC2731_LDO_CAMIO_VOL_MASK	GENMASK(6, 0)
+#define SC2731_LDO_SRAM_VOL_MASK	GENMASK(6, 0)
+
+enum sc2731_regulator_id {
+	SC2731_BUCK_CPU0,
+	SC2731_BUCK_CPU1,
+	SC2731_BUCK_RF,
+	SC2731_LDO_CAMA0,
+	SC2731_LDO_CAMA1,
+	SC2731_LDO_CAMMOT,
+	SC2731_LDO_VLDO,
+	SC2731_LDO_EMMCCORE,
+	SC2731_LDO_SDCORE,
+	SC2731_LDO_SDIO,
+	SC2731_LDO_WIFIPA,
+	SC2731_LDO_USB33,
+	SC2731_LDO_CAMD0,
+	SC2731_LDO_CAMD1,
+	SC2731_LDO_CON,
+	SC2731_LDO_CAMIO,
+	SC2731_LDO_SRAM,
+};
+
+static const struct regulator_ops sc2731_regu_linear_ops = {
+	.enable = regulator_enable_regmap,
+	.disable = regulator_disable_regmap,
+	.is_enabled = regulator_is_enabled_regmap,
+	.list_voltage = regulator_list_voltage_linear,
+	.get_voltage_sel = regulator_get_voltage_sel_regmap,
+	.set_voltage_sel = regulator_set_voltage_sel_regmap,
+};
+
+#define SC2731_REGU_LINEAR(_id, en_reg, en_mask, vreg, vmask,	\
+			  vstep, vmin, vmax) {			\
+	.name			= #_id,				\
+	.of_match		= of_match_ptr(#_id),		\
+	.ops			= &sc2731_regu_linear_ops,	\
+	.type			= REGULATOR_VOLTAGE,		\
+	.id			= SC2731_##_id,			\
+	.owner			= THIS_MODULE,			\
+	.min_uV			= vmin,				\
+	.n_voltages		= ((vmax) - (vmin)) / (vstep) + 1,	\
+	.uV_step		= vstep,			\
+	.enable_is_inverted	= true,				\
+	.enable_val		= 0,				\
+	.enable_reg		= en_reg,			\
+	.enable_mask		= en_mask,			\
+	.vsel_reg		= vreg,				\
+	.vsel_mask		= vmask,			\
+}
+
+static struct regulator_desc regulators[] = {
+	SC2731_REGU_LINEAR(BUCK_CPU0, SC2731_POWER_PD_SW,
+			   SC2731_DCDC_CPU0_PD_MASK, SC2731_DCDC_CPU0_VOL,
+			   SC2731_DCDC_CPU0_VOL_MASK, 3125, 400000, 1996875),
+	SC2731_REGU_LINEAR(BUCK_CPU1, SC2731_POWER_PD_SW,
+			   SC2731_DCDC_CPU1_PD_MASK, SC2731_DCDC_CPU1_VOL,
+			   SC2731_DCDC_CPU1_VOL_MASK, 3125, 400000, 1996875),
+	SC2731_REGU_LINEAR(BUCK_RF, SC2731_POWER_PD_SW, SC2731_DCDC_RF_PD_MASK,
+			   SC2731_DCDC_RF_VOL, SC2731_DCDC_RF_VOL_MASK,
+			   3125, 600000, 2196875),
+	SC2731_REGU_LINEAR(LDO_CAMA0, SC2731_LDO_CAMA0_PD,
+			   SC2731_LDO_CAMA0_PD_MASK, SC2731_LDO_CAMA0_VOL,
+			   SC2731_LDO_CAMA0_VOL_MASK, 10000, 1200000, 3750000),
+	SC2731_REGU_LINEAR(LDO_CAMA1, SC2731_LDO_CAMA1_PD,
+			   SC2731_LDO_CAMA1_PD_MASK, SC2731_LDO_CAMA1_VOL,
+			   SC2731_LDO_CAMA1_VOL_MASK, 10000, 1200000, 3750000),
+	SC2731_REGU_LINEAR(LDO_CAMMOT, SC2731_LDO_CAMMOT_PD,
+			   SC2731_LDO_CAMMOT_PD_MASK, SC2731_LDO_CAMMOT_VOL,
+			   SC2731_LDO_CAMMOT_VOL_MASK, 10000, 1200000, 3750000),
+	SC2731_REGU_LINEAR(LDO_VLDO, SC2731_LDO_VLDO_PD,
+			   SC2731_LDO_VLDO_PD_MASK, SC2731_LDO_VLDO_VOL,
+			   SC2731_LDO_VLDO_VOL_MASK, 10000, 1200000, 3750000),
+	SC2731_REGU_LINEAR(LDO_EMMCCORE, SC2731_LDO_EMMCCORE_PD,
+			   SC2731_LDO_EMMCCORE_PD_MASK, SC2731_LDO_EMMCCORE_VOL,
+			   SC2731_LDO_EMMCCORE_VOL_MASK, 10000, 1200000,
+			   3750000),
+	SC2731_REGU_LINEAR(LDO_SDCORE, SC2731_LDO_SDCORE_PD,
+			   SC2731_LDO_SDCORE_PD_MASK, SC2731_LDO_SDCORE_VOL,
+			   SC2731_LDO_SDCORE_VOL_MASK, 10000, 1200000, 3750000),
+	SC2731_REGU_LINEAR(LDO_SDIO, SC2731_LDO_SDIO_PD,
+			   SC2731_LDO_SDIO_PD_MASK, SC2731_LDO_SDIO_VOL,
+			   SC2731_LDO_SDIO_VOL_MASK, 10000, 1200000, 3750000),
+	SC2731_REGU_LINEAR(LDO_WIFIPA, SC2731_LDO_WIFIPA_PD,
+			   SC2731_LDO_WIFIPA_PD_MASK, SC2731_LDO_WIFIPA_VOL,
+			   SC2731_LDO_WIFIPA_VOL_MASK, 10000, 1200000, 3750000),
+	SC2731_REGU_LINEAR(LDO_USB33, SC2731_LDO_USB33_PD,
+			   SC2731_LDO_USB33_PD_MASK, SC2731_LDO_USB33_VOL,
+			   SC2731_LDO_USB33_VOL_MASK, 10000, 1200000, 3750000),
+	SC2731_REGU_LINEAR(LDO_CAMD0, SC2731_LDO_CAMD0_PD,
+			   SC2731_LDO_CAMD0_PD_MASK, SC2731_LDO_CAMD0_VOL,
+			   SC2731_LDO_CAMD0_VOL_MASK, 6250, 1000000, 1793750),
+	SC2731_REGU_LINEAR(LDO_CAMD1, SC2731_LDO_CAMD1_PD,
+			   SC2731_LDO_CAMD1_PD_MASK, SC2731_LDO_CAMD1_VOL,
+			   SC2731_LDO_CAMD1_VOL_MASK, 6250, 1000000, 1793750),
+	SC2731_REGU_LINEAR(LDO_CON, SC2731_LDO_CON_PD,
+			   SC2731_LDO_CON_PD_MASK, SC2731_LDO_CON_VOL,
+			   SC2731_LDO_CON_VOL_MASK, 6250, 1000000, 1793750),
+	SC2731_REGU_LINEAR(LDO_CAMIO, SC2731_LDO_CAMIO_PD,
+			   SC2731_LDO_CAMIO_PD_MASK, SC2731_LDO_CAMIO_VOL,
+			   SC2731_LDO_CAMIO_VOL_MASK, 6250, 1000000, 1793750),
+	SC2731_REGU_LINEAR(LDO_SRAM, SC2731_LDO_SRAM_PD,
+			   SC2731_LDO_SRAM_PD_MASK, SC2731_LDO_SRAM_VOL,
+			   SC2731_LDO_SRAM_VOL_MASK, 6250, 1000000, 1793750),
+};
+
+static int sc2731_regulator_unlock(struct regmap *regmap)
+{
+	return regmap_write(regmap, SC2731_PWR_WR_PROT_VALUE,
+			    SC2731_WR_UNLOCK);
+}
+
+static int sc2731_regulator_probe(struct platform_device *pdev)
+{
+	int i, ret;
+	struct regmap *regmap;
+	struct regulator_config config = { };
+	struct regulator_dev *rdev;
+
+	regmap = dev_get_regmap(pdev->dev.parent, NULL);
+	if (!regmap) {
+		dev_err(&pdev->dev, "failed to get regmap.\n");
+		return -ENODEV;
+	}
+
+	ret = sc2731_regulator_unlock(regmap);
+	if (ret) {
+		dev_err(&pdev->dev, "failed to release regulator lock\n");
+		return ret;
+	}
+
+	config.dev = &pdev->dev;
+	config.regmap = regmap;
+
+	for (i = 0; i < ARRAY_SIZE(regulators); i++) {
+		rdev = devm_regulator_register(&pdev->dev, &regulators[i],
+					       &config);
+		if (IS_ERR(rdev)) {
+			dev_err(&pdev->dev, "failed to register regulator %s\n",
+				regulators[i].name);
+			return PTR_ERR(rdev);
+		}
+	}
+
+	return 0;
+}
+
+static struct platform_driver sc2731_regulator_driver = {
+	.driver = {
+		.name = "sc27xx-regulator",
+	},
+	.probe = sc2731_regulator_probe,
+};
+
+module_platform_driver(sc2731_regulator_driver);
+
+MODULE_AUTHOR("Chen Junhui <erick.chen-lxIno14LUO0EEoCn2XhGlw@public.gmane.org>");
+MODULE_DESCRIPTION("Spreadtrum SC2731 regulator driver");
+MODULE_LICENSE("GPL v2");
-- 
2.15.0

--
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

* Re: [PATCH v4 3/5] staging: Introduce NVIDIA Tegra video decoder driver
From: Dmitry Osipenko @ 2017-12-05 12:17 UTC (permalink / raw)
  To: Hans Verkuil, Thierry Reding, Jonathan Hunter, Greg Kroah-Hartman,
	Rob Herring, Mauro Carvalho Chehab, Stephen Warren,
	Vladimir Zapolskiy
  Cc: Dan Carpenter, linux-media-u79uwXL29TY76Z2rM5mHXA,
	linux-tegra-u79uwXL29TY76Z2rM5mHXA,
	devel-gWbeCf7V1WCQmaza687I9mD2FQJk+8+b,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <ad2da9f4-8899-7db3-493f-5aa15297c33c-qWit8jRvyhVmR6Xm/wNWPw@public.gmane.org>

Hi Hans,

On 04.12.2017 17:04, Hans Verkuil wrote:
> Hi Dmitry,
> 
> As you already mention in the TODO, this should become a v4l2 codec driver.
> 
> Good existing examples are the coda, qcom/venus and mtk-vcodec drivers.
> 
> One thing that is not clear from this code is if the tegra hardware is a
> stateful or stateless codec, i.e. does it keep track of the decoder state
> in the hardware, or does the application have to keep track of the state and
> provide the state information together with the video data?
> 
> I ask because at the moment only stateful codecs are supported. Work is ongoing
> to support stateless codecs, but we don't support that for now.
> 

It is stateless. Is there anything ready to try out? If yes, could you please
give a reference to that work?

> Anyway, I'm OK with merging this in staging. Although I think it should go
> to staging/media since we want to keep track of it.
> 

Awesome, I'll move driver to staging/media in V5. Thanks!

^ permalink raw reply

* Re: [PATCH 5/8] ASoC: uniphier: add support for UniPhier AIO driver
From: Mark Brown @ 2017-12-05 12:14 UTC (permalink / raw)
  To: Katsuhiro Suzuki
  Cc: devicetree, alsa-devel, Masami Hiramatsu,
	Yamada, Masahiro/山田 真弘, linux-kernel,
	Jassi Brar, Rob Herring, linux-arm-kernel
In-Reply-To: <002b01d36d84$51d80aa0$f5881fe0$@socionext.com>


[-- Attachment #1.1: Type: text/plain, Size: 2448 bytes --]

On Tue, Dec 05, 2017 at 01:48:39PM +0900, Katsuhiro Suzuki wrote:

Please fix your mail client to word wrap within paragraphs at something
substantially less than 80 columns.  Doing this makes your messages much
easier to read and reply to.

> > Is there a mux in the SoC here?

> Sorry for confusing, It's not mux.

> uniphier_srcport_reset() resets HW SRC (sampling rate converter) block.
> Audio data out ports of UniPhier audio system have HW SRC.

Is the SRC just a single block sitting between the DMA and the external
audio port or is there more going on?  Some of the other code made me
think the hardware was more flexible than this (all the writing to
registers with names like RXSEL for example).

> > > +#endif /* CONFIG_SND_SOC_UNIPHIER_LD11 */

> > Why is there an ifdef here?  There's no other conditional code in here,
> > it seems pointless.

> This config is used to support or not LD11 SoC.
> aio-ld11.c is not build and 'uniphier_aio_ldxx_spec' is undefined if this config is disabled.
> 
> aio-ld11.c defines SoC dependent resources (port, HW ring buffer, DMA ch, etc.)
> and fixed settings.
> I know it's better to move such information into device-tree, but register areas of
> UniPhier's audio system is very strange and interleaved. It's hard to split each nodes...

I'd expect this code to be structured more like a library - have a
driver that handles the specific IPs then have it call into a shared
block of code that does the generic bits.  Though in this case the
device specific bit looks like a couple of tiny data tables so I'm not
sure it's worth making it conditional or separate at all.

> > This looks awfully like compressed audio support...  should there be
> > integration with the compressed audio API/

> Thanks, I'll try it. Is there Documentation in sound/designes/compress-offload.rst?
> And best sample is... Intel's driver?

Yes.

> (Summary)
> I think I should fix as follows:

>   - Split DMA, DAI patches from large one
>   - Validate parameters in hw_params
>   - Add description about HW SRC (or fix bad name 'srcport')
>   - Add comments about uniphier_aiodma_irq()
>   - Expose clocking and audio routing to userspace, or at the very
>     least machine driver configuration
>   - Support compress-audio API for S/PDIF

> and post V2.

At least.  I do think we need to get to the bottom of how flexible the
hardware is first though.

[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

[-- Attachment #2: Type: text/plain, Size: 0 bytes --]



^ permalink raw reply

* Re: [PATCH 4/8] ASoC: uniphier: add support for UniPhier EVEA codec
From: Mark Brown @ 2017-12-05 11:59 UTC (permalink / raw)
  To: Masahiro Yamada
  Cc: devicetree, alsa-devel, Masami Hiramatsu, Greg Kroah-Hartman,
	Linux Kernel Mailing List, Katsuhiro Suzuki, Jassi Brar,
	Rob Herring, Thomas Gleixner, linux-arm-kernel
In-Reply-To: <CAK7LNAR=-vHN5k6irpaDcAUYcH2kjCXLJpf10RMuq=GZB3huog@mail.gmail.com>


[-- Attachment #1.1: Type: text/plain, Size: 553 bytes --]

On Tue, Dec 05, 2017 at 09:58:54AM +0900, Masahiro Yamada wrote:

> Indeed ugly,
> but I think this is intentional to make the SPDX line stand out.

> 
> Linus suggested this as far as I understood from the following:
> https://patchwork.kernel.org/patch/10016201/

> If you use C++ comment style for the entire block,
> it will not stand out.

It's the first line of the file to make it stand out, if you google
around you can find some other conversation about how C++ comments are
a good idea in general and this might encourage them.

[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

[-- Attachment #2: Type: text/plain, Size: 0 bytes --]



^ permalink raw reply

* RE: [PATCH v4 07/12] [media] cxd2880: Add top level of the driver
From: Takiguchi, Yasunari @ 2017-12-05 11:47 UTC (permalink / raw)
  To: Sean Young
  Cc: linux-kernel@vger.kernel.org, devicetree@vger.kernel.org,
	linux-media@vger.kernel.org, tbird20d@gmail.com,
	frowand.list@gmail.com, Yamamoto, Masayuki, Nozawa, Hideki (STWN),
	Yonezawa, Kota, Matsumoto, Toshihiko, Watanabe, Satoshi (SSS),
	Takiguchi, Yasunari
In-Reply-To: <20171203225911.v6unmy5b2k3yc2tf@gofer.mess.org>

Dear Sean

Hi, Thanks for your review.

We will refer to your comments and consider how to respond for them.

> > +	u8 rdata[2];
> > +	int ret;
> > +
> > +	if ((!tnrdmd) || (!pre_bit_err) || (!pre_bit_count))
> > +		return -EINVAL;
> > +
> > +	if (tnrdmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_SUB)
> > +		return -EINVAL;
> 
> divermode: this should say drivermode, correct?

diver_mode is not typo, because cxd2880 has diversity function.

> > +MODULE_DESCRIPTION(
> > +"Sony CXD2880 DVB-T2/T tuner + demodulator drvier");
> 
> drvier => driver
Yes. It is typo. We will also re-check other patch files.

Thanks
Takiguchi

^ permalink raw reply

* [PATCH] [linux][master][v1] devicetree: misc: Add binding for logicoreIP xlnx,vcu
From: Dhaval Shah @ 2017-12-05 11:07 UTC (permalink / raw)
  To: robh+dt-DgEjT+Ai2ygdnm+yROfE0A, mark.rutland-5wv7dgnIgG8
  Cc: devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	michal.simek-gjFFaj9aHVfQT0dZR+AlfA, hyunk-gjFFaj9aHVfQT0dZR+AlfA,
	Dhaval Shah, Dhaval Shah

From: Dhaval Shah <dhaval.shah-gjFFaj9aHVfQT0dZR+AlfA@public.gmane.org>

Added the txt file which contain the xlnx,vcu DT node
properties information. This also provides the information
of it's child node as well.

Signed-off-by: Dhaval Shah <dshah-gjFFaj9aHVfQT0dZR+AlfA@public.gmane.org>
---
 .../devicetree/bindings/misc/xlnx,vcu.txt          | 59 ++++++++++++++++++++++
 1 file changed, 59 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/misc/xlnx,vcu.txt

diff --git a/Documentation/devicetree/bindings/misc/xlnx,vcu.txt b/Documentation/devicetree/bindings/misc/xlnx,vcu.txt
new file mode 100644
index 0000000..e722ff3
--- /dev/null
+++ b/Documentation/devicetree/bindings/misc/xlnx,vcu.txt
@@ -0,0 +1,59 @@
+Xilinx VCU init Driver
+-----------------------------
+
+General concept
+---------------
+
+Xilinx VCU init driver is developed to handle the LogiCore related
+new implementation. In this directory, The DT node of the Xilinx
+VCU init driver represents as a top level node.
+
+Required properties:
+- compatible: Must be "xlnx,vcu".
+- reg, reg-names: There are two sets of registers need to provide.
+	1. vcu slcr
+	2. Logicore
+	reg-names should contain name for the each register sequence.
+- clocks: phandle for aclk and pll_ref clocksource
+- clock-names: The identification string, "aclk", is always required for
+   the axi clock. "pll_ref" is required for pll.
+- ranges
+- VCU Init driver node define the following child nodes:
+	* Allegro encoder driver node
+		- compatible: Must be "al,al5e"
+		- reg: There is a one set of register.
+		- interrupts: interrupt number to the cpu.
+		- interrupt-parent: the phandle for the interrupt controller
+		  that services interrupts for this device.
+	* Allegro decoder driver node
+		- compatible: Must be "al,al5d"
+		- reg: There is a one set of register.
+		- interrupts: interrupt number to the cpu.
+		- interrupt-parent: the phandle for the interrupt controller
+		  that services interrupts for this device.
+Example:
+
+	xlnx_vcu: vcu@a0040000 {
+		compatible = "xlnx,vcu";
+		#address-cells = <2>;
+		#size-cells = <2>;
+		reg = <0x0 0xa0040000 0x0 0x1000>,
+			 <0x0 0xa0041000 0x0 0x1000>;
+		reg-names = "vcu_slcr", "logicore";
+		clocks = <&si570_1>, <&clkc 71>;
+		clock-names = "pll_ref", "aclk";
+		ranges;
+		encoder: al5e@a0000000 {
+			compatible = "al,al5e";
+			reg = <0x0 0xa0000000 0x0 0x10000>;
+			interrupts = <0 89 4>;
+			interrupt-parent = <&gic>;
+		};
+
+		decoder: al5d@a0020000 {
+			compatible = "al,al5d";
+			reg = <0x0 0xa0020000 0x0 0x10000>;
+			interrupts = <0 89 4>;
+			interrupt-parent = <&gic>;
+		};
+	};
-- 
2.7.4

--
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

* Re: [PATCH v2 1/2] of: overlay: Fix memory leak in of_overlay_apply() error path
From: Geert Uytterhoeven @ 2017-12-05 10:49 UTC (permalink / raw)
  To: Frank Rowand
  Cc: Geert Uytterhoeven, Pantelis Antoniou, Rob Herring, Colin King,
	Dan Carpenter, devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
In-Reply-To: <CAMuHMdUzuJuKYQ6xtOAb3ctzPqakKZCtPQr9JVQP78VvK6qq3g-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>

Hi Frank,

On Tue, Dec 5, 2017 at 9:01 AM, Geert Uytterhoeven <geert-Td1EMuHUCqxL1ZNQvxDV9g@public.gmane.org> wrote:
> On Tue, Dec 5, 2017 at 3:07 AM, Frank Rowand <frowand.list-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:
>> On 12/04/17 10:47, Geert Uytterhoeven wrote:
>>> If of_resolve_phandles() fails, free_overlay_changeset() is called in
>>> the error path.  However, that function returns early if the list hasn't
>>> been initialized yet, before freeing the object.
>>>
>>> Explicitly calling kfree() instead would solve that issue. However, that
>>> complicates matter, by having to consider which of two different methods
>>> to use to dispose of the same object.
>>>
>>> Hence make free_overlay_changeset() consider initialization state of the
>>> different parts of the object, making it always safe to call (once!) to
>>> dispose of a (partially) initialized overlay_changeset:
>>>   - Only destroy the changeset if the list was initialized,
>>>   - Ignore uninitialized IDs (zero).
>>>
>>> Reported-by: Colin King <colin.king-Z7WLFzj8eWMS+FvcfC7Uqw@public.gmane.org>
>>> Fixes: f948d6d8b792bb90 ("of: overlay: avoid race condition between applying multiple overlays")
>>> Signed-off-by: Geert Uytterhoeven <geert+renesas-gXvu3+zWzMSzQB+pC5nmwQ@public.gmane.org>
>>> ---
>>>  drivers/of/overlay.c | 7 +++----
>>>  1 file changed, 3 insertions(+), 4 deletions(-)
>>>
>>> diff --git a/drivers/of/overlay.c b/drivers/of/overlay.c
>>> index 3b7a3980ff50d6bf..312cd658bec0083b 100644
>>> --- a/drivers/of/overlay.c
>>> +++ b/drivers/of/overlay.c
>>> @@ -630,11 +630,10 @@ static void free_overlay_changeset(struct overlay_changeset *ovcs)
>>>  {
>>>       int i;
>>>
>>> -     if (!ovcs->cset.entries.next)
>>> -             return;
>>> -     of_changeset_destroy(&ovcs->cset);
>>> +     if (ovcs->cset.entries.next)
>>> +             of_changeset_destroy(&ovcs->cset);
>>>
>>
>> OK
>>
>>> -     if (ovcs->id)
>>> +     if (ovcs->id > 0)
>>
>> Instead of this change, could you please make a change in init_overlay_changeset()?
>>
>> Current init_overlay_changeset():
>>
>>         ovcs->id = idr_alloc(&ovcs_idr, ovcs, 1, 0, GFP_KERNEL);
>>         if (ovcs->id <= 0)
>>                 return ovcs->id;
>>
>> My proposed version:
>>
>>         ret = idr_alloc(&ovcs_idr, ovcs, 1, 0, GFP_KERNEL);
>>         if (ret <= 0)
>>                 return ret;
>>         ovcs->id = ret;
>
> Sure.

Actually we should use a temporary variable id here, just like for cnt
and fragments, and store into ovcs->id if everything succeeds.

Else both init_overlay_changeset() and free_overlay_changeset() will
free the ID if something goes wrong. It seems IDR can handle that, but
better safe than sorry.

Gr{oetje,eeting}s,

                        Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert-Td1EMuHUCqxL1ZNQvxDV9g@public.gmane.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
                                -- Linus Torvalds
--
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

* Re: [PATCH v6 2/2] media: i2c: Add the ov7740 image sensor driver
From: Sakari Ailus @ 2017-12-05 10:45 UTC (permalink / raw)
  To: Wenyou Yang
  Cc: Mauro Carvalho Chehab, Rob Herring, Mark Rutland,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA, Nicolas Ferre,
	devicetree-u79uwXL29TY76Z2rM5mHXA, Jonathan Corbet, Hans Verkuil,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	Linux Media Mailing List, Songjun Wu
In-Reply-To: <20171204065858.3138-3-wenyou.yang-UWL1GkI3JZL3oGB3hsPCZA@public.gmane.org>

Hi Wenyou,

On Mon, Dec 04, 2017 at 02:58:58PM +0800, Wenyou Yang wrote:
> The ov7740 (color) image sensor is a high performance VGA CMOS
> image snesor, which supports for output formats: RAW RGB and YUV
> and image sizes: VGA, and QVGA, CIF and any size smaller.
> 
> Signed-off-by: Songjun Wu <songjun.wu-UWL1GkI3JZL3oGB3hsPCZA@public.gmane.org>
> Signed-off-by: Wenyou Yang <wenyou.yang-UWL1GkI3JZL3oGB3hsPCZA@public.gmane.org>
> ---
> 
> Changes in v6:
>  - Remove unnecessary #include <linux/init>.
>  - Remove unnecessary comments and extra newline.
>  - Add const for some structures.
>  - Add the check of the return value from regmap_write().
>  - Simplify the calling of __v4l2_ctrl_handler_setup().
>  - Add the default format initialization function.
>  - Integrate the set_power() and enable/disable the clock into
>    one function.
> 
> Changes in v5:
>  - Squash the driver and MAINTAINERS entry patches to one.
>  - Precede the driver patch with the bindings patch.
> 
> Changes in v4:
>  - Assign 'val' a initial value to avoid warning: 'val' may be
>    used uninitialized.
>  - Rename REG_REG15 to avoid warning: "REG_REG15" redefined.
> 
> Changes in v3:
>  - Put the MAINTAINERS change to a separate patch.
> 
> Changes in v2:
>  - Split off the bindings into a separate patch.
>  - Add a new entry to the MAINTAINERS file.
> 
>  MAINTAINERS                |    8 +
>  drivers/media/i2c/Kconfig  |    8 +
>  drivers/media/i2c/Makefile |    1 +
>  drivers/media/i2c/ov7740.c | 1226 ++++++++++++++++++++++++++++++++++++++++++++
>  4 files changed, 1243 insertions(+)
>  create mode 100644 drivers/media/i2c/ov7740.c
> 
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 7a52a66aa991..1de965009b13 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -10053,6 +10053,14 @@ S:	Maintained
>  F:	drivers/media/i2c/ov7670.c
>  F:	Documentation/devicetree/bindings/media/i2c/ov7670.txt
>  
> +OMNIVISION OV7740 SENSOR DRIVER
> +M:	Wenyou Yang <wenyou.yang-UWL1GkI3JZL3oGB3hsPCZA@public.gmane.org>
> +L:	linux-media-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
> +T:	git git://linuxtv.org/media_tree.git
> +S:	Maintained
> +F:	drivers/media/i2c/ov7740.c
> +F:	Documentation/devicetree/bindings/media/i2c/ov7740.txt
> +
>  ONENAND FLASH DRIVER
>  M:	Kyungmin Park <kyungmin.park-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org>
>  L:	linux-mtd-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org
> diff --git a/drivers/media/i2c/Kconfig b/drivers/media/i2c/Kconfig
> index cb5d7ff82915..00b1c4c031d4 100644
> --- a/drivers/media/i2c/Kconfig
> +++ b/drivers/media/i2c/Kconfig
> @@ -665,6 +665,14 @@ config VIDEO_OV7670
>  	  OV7670 VGA camera.  It currently only works with the M88ALP01
>  	  controller.
>  
> +config VIDEO_OV7740
> +	tristate "OmniVision OV7740 sensor support"
> +	depends on I2C && VIDEO_V4L2
> +	depends on MEDIA_CAMERA_SUPPORT
> +	---help---
> +	  This is a Video4Linux2 sensor-level driver for the OmniVision
> +	  OV7740 VGA camera sensor.
> +
>  config VIDEO_OV9650
>  	tristate "OmniVision OV9650/OV9652 sensor support"
>  	depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API
> diff --git a/drivers/media/i2c/Makefile b/drivers/media/i2c/Makefile
> index 548a9efce966..9b19ec7fcaf4 100644
> --- a/drivers/media/i2c/Makefile
> +++ b/drivers/media/i2c/Makefile
> @@ -68,6 +68,7 @@ obj-$(CONFIG_VIDEO_OV5670) += ov5670.o
>  obj-$(CONFIG_VIDEO_OV6650) += ov6650.o
>  obj-$(CONFIG_VIDEO_OV7640) += ov7640.o
>  obj-$(CONFIG_VIDEO_OV7670) += ov7670.o
> +obj-$(CONFIG_VIDEO_OV7740) += ov7740.o
>  obj-$(CONFIG_VIDEO_OV9650) += ov9650.o
>  obj-$(CONFIG_VIDEO_OV13858) += ov13858.o
>  obj-$(CONFIG_VIDEO_MT9M032) += mt9m032.o
> diff --git a/drivers/media/i2c/ov7740.c b/drivers/media/i2c/ov7740.c
> new file mode 100644
> index 000000000000..42c25277d005
> --- /dev/null
> +++ b/drivers/media/i2c/ov7740.c
> @@ -0,0 +1,1226 @@
> +/*
> + * Copyright (c) 2017 Microchip Corporation.
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public License version
> + * 2 as published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> + *
> + */
> +#include <linux/clk.h>
> +#include <linux/delay.h>
> +#include <linux/gpio.h>
> +#include <linux/i2c.h>
> +#include <linux/module.h>
> +#include <linux/pm_runtime.h>
> +#include <linux/regmap.h>
> +#include <media/v4l2-ctrls.h>
> +#include <media/v4l2-event.h>
> +#include <media/v4l2-image-sizes.h>
> +#include <media/v4l2-subdev.h>
> +
> +#define REG_OUTSIZE_LSB 0x34
> +
> +/* OV7740 register tables */
> +#define REG_GAIN	0x00	/* Gain lower 8 bits (rest in vref) */
> +#define REG_BGAIN	0x01	/* blue gain */
> +#define REG_RGAIN	0x02	/* red gain */
> +#define REG_GGAIN	0x03	/* green gain */
> +#define REG_REG04	0x04	/* analog setting, dont change*/
> +#define REG_BAVG	0x05	/* b channel average */
> +#define REG_GAVG	0x06	/* g channel average */
> +#define REG_RAVG	0x07	/* r channel average */
> +
> +#define REG_REG0C	0x0C	/* filp enable */
> +#define REG0C_IMG_FLIP		0x80
> +#define REG0C_IMG_MIRROR	0x40
> +
> +#define REG_REG0E	0x0E	/* blc line */
> +#define REG_HAEC	0x0F	/* auto exposure cntrl */
> +#define REG_AEC		0x10	/* auto exposure cntrl */
> +
> +#define REG_CLK		0x11	/* Clock control */
> +#define REG_REG55	0x55	/* Clock PLL DIV/PreDiv */
> +
> +#define REG_REG12	0x12
> +
> +#define REG_REG13	0x13	/* auto/manual AGC, AEC, Write Balance*/
> +#define REG13_AEC_EN	0x01
> +#define REG13_AGC_EN	0x04
> +
> +#define REG_REG14	0x14
> +#define REG_CTRL15	0x15
> +#define REG15_GAIN_MSB	0x03
> +
> +#define REG_REG16	0x16
> +
> +#define REG_MIDH	0x1C	/* manufacture id byte */
> +#define REG_MIDL	0x1D	/* manufacture id byre */
> +#define REG_PIDH	0x0A	/* Product ID MSB */
> +#define REG_PIDL	0x0B	/* Product ID LSB */
> +
> +#define REG_84		0x84	/* lots of stuff */
> +#define REG_REG38	0x38	/* sub-addr */
> +
> +#define REG_AHSTART	0x17	/* Horiz start high bits */
> +#define REG_AHSIZE	0x18
> +#define REG_AVSTART	0x19	/* Vert start high bits */
> +#define REG_AVSIZE	0x1A
> +#define REG_PSHFT	0x1b	/* Pixel delay after HREF */
> +
> +#define REG_HOUTSIZE	0x31
> +#define REG_VOUTSIZE	0x32
> +#define REG_HVSIZEOFF	0x33
> +#define REG_REG34	0x34	/* DSP output size H/V LSB*/
> +
> +#define REG_ISP_CTRL00	0x80
> +#define ISPCTRL00_AWB_EN	0x10
> +#define ISPCTRL00_AWB_GAIN_EN	0x04
> +
> +#define	REG_YGAIN	0xE2	/* ygain for contrast control */
> +
> +#define	REG_YBRIGHT	  0xE3
> +#define	REG_SGNSET	  0xE4
> +#define	SGNSET_YBRIGHT_MASK	  0x08
> +
> +#define REG_USAT	0xDD
> +#define REG_VSAT	0xDE
> +
> +
> +struct ov7740 {
> +	struct v4l2_subdev subdev;
> +#if defined(CONFIG_MEDIA_CONTROLLER)
> +	struct media_pad pad;
> +#endif
> +	struct v4l2_mbus_framefmt format;
> +	const struct ov7740_pixfmt *fmt;  /* Current format */
> +	const struct ov7740_framesize *frmsize;
> +	struct regmap *regmap;
> +	struct clk *xvclk;
> +	struct v4l2_ctrl_handler ctrl_handler;
> +	struct {
> +		/* gain cluster */
> +		struct v4l2_ctrl *auto_gain;
> +		struct v4l2_ctrl *gain;
> +	};
> +	struct {
> +		struct v4l2_ctrl *auto_wb;
> +		struct v4l2_ctrl *blue_balance;
> +		struct v4l2_ctrl *red_balance;
> +	};
> +	struct {
> +		struct v4l2_ctrl *hflip;
> +		struct v4l2_ctrl *vflip;
> +	};
> +	struct {
> +		/* exposure cluster */
> +		struct v4l2_ctrl *auto_exposure;
> +		struct v4l2_ctrl *exposure;
> +	};
> +	struct {
> +		/* saturation/hue cluster */
> +		struct v4l2_ctrl *saturation;
> +		struct v4l2_ctrl *hue;
> +	};
> +	struct v4l2_ctrl *brightness;
> +	struct v4l2_ctrl *contrast;
> +
> +	struct mutex mutex;	/* To serialize asynchronus callbacks */
> +	bool streaming;		/* Streaming on/off */
> +
> +	struct gpio_desc *resetb_gpio;
> +	struct gpio_desc *pwdn_gpio;
> +};
> +
> +struct ov7740_pixfmt {
> +	u32 mbus_code;
> +	enum v4l2_colorspace colorspace;
> +	const struct reg_sequence *regs;
> +	u32 reg_num;
> +};
> +
> +struct ov7740_framesize {
> +	u16 width;
> +	u16 height;
> +	const struct reg_sequence *regs;
> +	u32 reg_num;
> +};
> +
> +static const struct reg_sequence ov7740_vga[] = {
> +	{0x55, 0x40},
> +	{0x11, 0x02},
> +
> +	{0xd5, 0x10},
> +	{0x0c, 0x12},
> +	{0x0d, 0x34},
> +	{0x17, 0x25},
> +	{0x18, 0xa0},
> +	{0x19, 0x03},
> +	{0x1a, 0xf0},
> +	{0x1b, 0x89},
> +	{0x22, 0x03},
> +	{0x29, 0x18},
> +	{0x2b, 0xf8},
> +	{0x2c, 0x01},
> +	{REG_HOUTSIZE, 0xa0},
> +	{REG_VOUTSIZE, 0xf0},
> +	{0x33, 0xc4},
> +	{REG_OUTSIZE_LSB, 0x0},
> +	{0x35, 0x05},
> +	{0x04, 0x60},
> +	{0x27, 0x80},
> +	{0x3d, 0x0f},
> +	{0x3e, 0x80},
> +	{0x3f, 0x40},
> +	{0x40, 0x7f},
> +	{0x41, 0x6a},
> +	{0x42, 0x29},
> +	{0x44, 0x22},
> +	{0x45, 0x41},
> +	{0x47, 0x02},
> +	{0x49, 0x64},
> +	{0x4a, 0xa1},
> +	{0x4b, 0x40},
> +	{0x4c, 0x1a},
> +	{0x4d, 0x50},
> +	{0x4e, 0x13},
> +	{0x64, 0x00},
> +	{0x67, 0x88},
> +	{0x68, 0x1a},
> +
> +	{0x14, 0x28},
> +	{0x24, 0x3c},
> +	{0x25, 0x30},
> +	{0x26, 0x72},
> +	{0x50, 0x97},
> +	{0x51, 0x1f},
> +	{0x52, 0x00},
> +	{0x53, 0x00},
> +	{0x20, 0x00},
> +	{0x21, 0xcf},
> +	{0x50, 0x4b},
> +	{0x38, 0x14},
> +	{0xe9, 0x00},
> +	{0x56, 0x55},
> +	{0x57, 0xff},
> +	{0x58, 0xff},
> +	{0x59, 0xff},
> +	{0x5f, 0x04},
> +	{0xec, 0x00},
> +	{0x13, 0xff},
> +
> +	{0x81, 0x3f},
> +	{0x82, 0x32},
> +	{0x38, 0x11},
> +	{0x84, 0x70},
> +	{0x85, 0x00},
> +	{0x86, 0x03},
> +	{0x87, 0x01},
> +	{0x88, 0x05},
> +	{0x89, 0x30},
> +	{0x8d, 0x30},
> +	{0x8f, 0x85},
> +	{0x93, 0x30},
> +	{0x95, 0x85},
> +	{0x99, 0x30},
> +	{0x9b, 0x85},
> +
> +	{0x9c, 0x08},
> +	{0x9d, 0x12},
> +	{0x9e, 0x23},
> +	{0x9f, 0x45},
> +	{0xa0, 0x55},
> +	{0xa1, 0x64},
> +	{0xa2, 0x72},
> +	{0xa3, 0x7f},
> +	{0xa4, 0x8b},
> +	{0xa5, 0x95},
> +	{0xa6, 0xa7},
> +	{0xa7, 0xb5},
> +	{0xa8, 0xcb},
> +	{0xa9, 0xdd},
> +	{0xaa, 0xec},
> +	{0xab, 0x1a},
> +
> +	{0xce, 0x78},
> +	{0xcf, 0x6e},
> +	{0xd0, 0x0a},
> +	{0xd1, 0x0c},
> +	{0xd2, 0x84},
> +	{0xd3, 0x90},
> +	{0xd4, 0x1e},
> +
> +	{0x5a, 0x24},
> +	{0x5b, 0x1f},
> +	{0x5c, 0x88},
> +	{0x5d, 0x60},
> +
> +	{0xac, 0x6e},
> +	{0xbe, 0xff},
> +	{0xbf, 0x00},
> +
> +	{0x0f, 0x1d},
> +	{0x0f, 0x1f},
> +};
> +
> +static const struct ov7740_framesize ov7740_framesizes[] = {
> +	{
> +		.width		= VGA_WIDTH,
> +		.height		= VGA_HEIGHT,
> +		.regs		= ov7740_vga,
> +		.reg_num	= ARRAY_SIZE(ov7740_vga),
> +	},
> +};
> +
> +#ifdef CONFIG_VIDEO_ADV_DEBUG
> +static int ov7740_get_register(struct v4l2_subdev *sd,
> +			       struct v4l2_dbg_register *reg)
> +{
> +	struct ov7740 *ov7740 = container_of(sd, struct ov7740, subdev);
> +	struct regmap *regmap = ov7740->regmap;
> +	unsigned int val = 0;
> +	int ret;
> +
> +	ret = regmap_read(regmap, reg->reg & 0xff, &val);
> +	reg->val = val;
> +	reg->size = 1;
> +
> +	return 0;
> +}
> +
> +static int ov7740_set_register(struct v4l2_subdev *sd,
> +			       const struct v4l2_dbg_register *reg)
> +{
> +	struct ov7740 *ov7740 = container_of(sd, struct ov7740, subdev);
> +	struct regmap *regmap = ov7740->regmap;
> +
> +	regmap_write(regmap, reg->reg & 0xff, reg->val & 0xff);
> +
> +	return 0;
> +}
> +#endif
> +
> +static int ov7740_set_power(struct ov7740 *ov7740, int on)
> +{
> +	int ret;
> +
> +	if (on) {
> +		ret = clk_prepare_enable(ov7740->xvclk);
> +		if (ret)
> +			return ret;
> +
> +		if (ov7740->pwdn_gpio)
> +			gpiod_direction_output(ov7740->pwdn_gpio, 0);
> +
> +		if (ov7740->resetb_gpio) {
> +			gpiod_set_value(ov7740->resetb_gpio, 1);
> +			usleep_range(500, 1000);
> +			gpiod_set_value(ov7740->resetb_gpio, 0);
> +			usleep_range(3000, 5000);
> +		}
> +	} else {
> +		clk_disable_unprepare(ov7740->xvclk);
> +
> +		if (ov7740->pwdn_gpio)
> +			gpiod_direction_output(ov7740->pwdn_gpio, 0);
> +	}
> +
> +	return 0;
> +}
> +
> +static struct v4l2_subdev_core_ops ov7740_subdev_core_ops = {
> +	.log_status = v4l2_ctrl_subdev_log_status,
> +#ifdef CONFIG_VIDEO_ADV_DEBUG
> +	.g_register = ov7740_get_register,
> +	.s_register = ov7740_set_register,
> +#endif
> +	.subscribe_event = v4l2_ctrl_subdev_subscribe_event,
> +	.unsubscribe_event = v4l2_event_subdev_unsubscribe,
> +};
> +
> +static int ov7740_set_white_balance(struct ov7740 *ov7740, int awb)
> +{
> +	struct regmap *regmap = ov7740->regmap;
> +	unsigned int value;
> +	int ret;
> +
> +	ret = regmap_read(regmap, REG_ISP_CTRL00, &value);
> +	if (!ret) {
> +		if (awb)
> +			value |= (ISPCTRL00_AWB_EN | ISPCTRL00_AWB_GAIN_EN);
> +		else
> +			value &= ~(ISPCTRL00_AWB_EN | ISPCTRL00_AWB_GAIN_EN);
> +		ret = regmap_write(regmap, REG_ISP_CTRL00, value);
> +		if (ret)
> +			return ret;
> +	}
> +
> +	if (!awb) {
> +		ret = regmap_write(regmap, REG_BGAIN,
> +				   ov7740->blue_balance->val);
> +		if (ret)
> +			return ret;
> +
> +		ret = regmap_write(regmap, REG_RGAIN, ov7740->red_balance->val);
> +		if (ret)
> +			return ret;
> +	}
> +
> +	return 0;
> +}
> +
> +static int ov7740_set_saturation(struct regmap *regmap, int value)
> +{
> +	int ret;
> +
> +	ret = regmap_write(regmap, REG_USAT, (unsigned char)value);
> +	if (ret)
> +		return ret;
> +
> +	return regmap_write(regmap, REG_VSAT, (unsigned char)value);
> +}
> +
> +static int ov7740_set_gain(struct regmap *regmap, int value)
> +{
> +	int ret;
> +
> +	ret = regmap_write(regmap, REG_GAIN, value & 0xff);
> +	if (ret)
> +		return ret;
> +
> +	ret = regmap_update_bits(regmap, REG_CTRL15,
> +				 REG15_GAIN_MSB, (value >> 8) & 0x3);
> +	if (!ret)
> +		ret = regmap_update_bits(regmap, REG_REG13, REG13_AGC_EN, 0);
> +
> +	return ret;
> +}
> +
> +static int ov7740_set_autogain(struct regmap *regmap, int value)
> +{
> +	unsigned int reg;
> +	int ret;
> +
> +	ret = regmap_read(regmap, REG_REG13, &reg);
> +	if (ret)
> +		return ret;
> +	if (value)
> +		reg |= REG13_AGC_EN;
> +	else
> +		reg &= ~REG13_AGC_EN;
> +	return regmap_write(regmap, REG_REG13, reg);
> +}
> +
> +static int ov7740_set_brightness(struct regmap *regmap, int value)
> +{
> +	/* Turn off AEC/AGC */
> +	regmap_update_bits(regmap, REG_REG13, REG13_AEC_EN, 0);
> +	regmap_update_bits(regmap, REG_REG13, REG13_AGC_EN, 0);
> +
> +	if (value >= 0) {
> +		regmap_write(regmap, REG_YBRIGHT, (unsigned char)value);
> +		regmap_update_bits(regmap, REG_SGNSET, SGNSET_YBRIGHT_MASK, 0);
> +	} else{
> +		regmap_write(regmap, REG_YBRIGHT, (unsigned char)(-value));
> +		regmap_update_bits(regmap, REG_SGNSET, SGNSET_YBRIGHT_MASK, 1);
> +	}
> +
> +	return 0;
> +}
> +
> +static int ov7740_set_contrast(struct regmap *regmap, int value)
> +{
> +	return regmap_write(regmap, REG_YGAIN, (unsigned char)value);
> +}
> +
> +static int ov7740_get_gain(struct ov7740 *ov7740, struct v4l2_ctrl *ctrl)
> +{
> +	struct regmap *regmap = ov7740->regmap;
> +	unsigned int value0, value1;
> +	int ret;
> +
> +	if (!ctrl->val)
> +		return 0;
> +
> +	ret = regmap_read(regmap, REG_GAIN, &value0);
> +	if (ret)
> +		return ret;
> +	ret = regmap_read(regmap, REG_CTRL15, &value1);
> +	if (ret)
> +		return ret;
> +
> +	ov7740->gain->val = (value1 << 8) | (value0 & 0xff);
> +
> +	return 0;
> +}
> +
> +static int ov7740_set_exp(struct regmap *regmap, int value)
> +{
> +	int ret;
> +
> +	/* Turn off AEC/AGC */
> +	ret = regmap_update_bits(regmap, REG_REG13,
> +				 REG13_AEC_EN | REG13_AGC_EN, 0);
> +	if (ret)
> +		return ret;
> +
> +	ret = regmap_write(regmap, REG_AEC, (unsigned char)value);
> +	if (ret)
> +		return ret;
> +
> +	return regmap_write(regmap, REG_HAEC, (unsigned char)(value >> 8));
> +}
> +
> +static int ov7740_set_autoexp(struct regmap *regmap,
> +			      enum v4l2_exposure_auto_type value)
> +{
> +	unsigned int reg;
> +	int ret;
> +
> +	ret = regmap_read(regmap, REG_REG13, &reg);
> +	if (!ret) {
> +		if (value == V4L2_EXPOSURE_AUTO)
> +			reg |= (REG13_AEC_EN | REG13_AGC_EN);
> +		else
> +			reg &= ~(REG13_AEC_EN | REG13_AGC_EN);
> +		ret = regmap_write(regmap, REG_REG13, reg);
> +	}
> +
> +	return ret;
> +}
> +
> +
> +static int ov7740_get_volatile_ctrl(struct v4l2_ctrl *ctrl)
> +{
> +	struct ov7740 *ov7740 = container_of(ctrl->handler,
> +					     struct ov7740, ctrl_handler);
> +	int ret;
> +
> +	switch (ctrl->id) {
> +	case V4L2_CID_AUTOGAIN:
> +		ret = ov7740_get_gain(ov7740, ctrl);
> +		break;
> +	default:
> +		ret = -EINVAL;
> +		break;
> +	}
> +	return ret;
> +}
> +
> +static int ov7740_set_ctrl(struct v4l2_ctrl *ctrl)
> +{
> +	struct ov7740 *ov7740 = container_of(ctrl->handler,
> +					     struct ov7740, ctrl_handler);
> +	struct i2c_client *client = v4l2_get_subdevdata(&ov7740->subdev);
> +	struct regmap *regmap = ov7740->regmap;
> +	int ret;
> +	u8 val = 0;
> +
> +	if (pm_runtime_get_if_in_use(&client->dev) <= 0)
> +		return 0;
> +
> +	switch (ctrl->id) {
> +	case V4L2_CID_AUTO_WHITE_BALANCE:
> +		ret = ov7740_set_white_balance(ov7740, ctrl->val);
> +		break;
> +	case V4L2_CID_SATURATION:
> +		ret = ov7740_set_saturation(regmap, ctrl->val);
> +		break;
> +	case V4L2_CID_BRIGHTNESS:
> +		ret = ov7740_set_brightness(regmap, ctrl->val);
> +		break;
> +	case V4L2_CID_CONTRAST:
> +		ret = ov7740_set_contrast(regmap, ctrl->val);
> +		break;
> +	case V4L2_CID_VFLIP:
> +		ret = regmap_update_bits(regmap, REG_REG0C,
> +					 REG0C_IMG_FLIP, val);
> +		break;
> +	case V4L2_CID_HFLIP:
> +		val = ctrl->val ? REG0C_IMG_MIRROR : 0x00;
> +		ret = regmap_update_bits(regmap, REG_REG0C,
> +					 REG0C_IMG_MIRROR, val);
> +		break;
> +	case V4L2_CID_AUTOGAIN:
> +		if (!ctrl->val)
> +			return ov7740_set_gain(regmap, ov7740->gain->val);
> +
> +		ret = ov7740_set_autogain(regmap, ctrl->val);
> +		break;
> +
> +	case V4L2_CID_EXPOSURE_AUTO:
> +		if (ctrl->val == V4L2_EXPOSURE_MANUAL)
> +			return ov7740_set_exp(regmap, ov7740->exposure->val);
> +
> +		ret = ov7740_set_autoexp(regmap, ctrl->val);
> +		break;
> +	default:
> +		ret = -EINVAL;
> +		break;
> +	}
> +
> +	pm_runtime_put(&client->dev);
> +
> +	return ret;
> +}
> +
> +static const struct v4l2_ctrl_ops ov7740_ctrl_ops = {
> +	.g_volatile_ctrl = ov7740_get_volatile_ctrl,
> +	.s_ctrl = ov7740_set_ctrl,
> +};
> +
> +static int ov7740_start_streaming(struct ov7740 *ov7740)
> +{
> +	return __v4l2_ctrl_handler_setup(ov7740->subdev.ctrl_handler);
> +}
> +
> +static int ov7740_set_stream(struct v4l2_subdev *sd, int enable)
> +{
> +	struct ov7740 *ov7740 = container_of(sd, struct ov7740, subdev);
> +	struct i2c_client *client = v4l2_get_subdevdata(sd);
> +	int ret = 0;
> +
> +	mutex_lock(&ov7740->mutex);
> +	if (ov7740->streaming == enable) {
> +		mutex_unlock(&ov7740->mutex);
> +		return 0;
> +	}
> +
> +	if (enable) {
> +		ret = pm_runtime_get_sync(&client->dev);
> +		if (ret < 0) {
> +			pm_runtime_put_noidle(&client->dev);
> +			goto err_unlock;
> +		}
> +
> +		ret = ov7740_start_streaming(ov7740);
> +		if (ret)
> +			goto err_rpm_put;
> +	} else {
> +		pm_runtime_put(&client->dev);
> +	}
> +
> +	ov7740->streaming = enable;
> +
> +	mutex_unlock(&ov7740->mutex);
> +	return ret;
> +
> +err_rpm_put:
> +	pm_runtime_put(&client->dev);
> +err_unlock:
> +	mutex_unlock(&ov7740->mutex);
> +	return ret;
> +}
> +
> +static int ov7740_get_parm(struct v4l2_subdev *sd,
> +			   struct v4l2_streamparm *parms)
> +{
> +	struct v4l2_captureparm *cp = &parms->parm.capture;
> +	struct v4l2_fract *tpf = &cp->timeperframe;
> +
> +	if (parms->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
> +		return -EINVAL;
> +
> +	memset(cp, 0, sizeof(struct v4l2_captureparm));
> +	cp->capability = V4L2_CAP_TIMEPERFRAME;
> +
> +	tpf->numerator = 1;
> +	tpf->denominator = 60;
> +
> +	return 0;
> +}
> +
> +static int ov7740_set_parm(struct v4l2_subdev *sd,
> +			   struct v4l2_streamparm *parms)
> +{
> +	struct v4l2_captureparm *cp = &parms->parm.capture;
> +	struct v4l2_fract *tpf = &cp->timeperframe;
> +
> +	if (parms->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
> +		return -EINVAL;
> +	if (cp->extendedmode != 0)
> +		return -EINVAL;
> +
> +	cp->capability = V4L2_CAP_TIMEPERFRAME;
> +
> +	tpf->numerator = 1;
> +	tpf->denominator = 60;
> +
> +	return 0;
> +}
> +
> +static struct v4l2_subdev_video_ops ov7740_subdev_video_ops = {
> +	.s_stream = ov7740_set_stream,
> +	.s_parm = ov7740_set_parm,
> +	.g_parm = ov7740_get_parm,
> +};
> +
> +static const struct reg_sequence ov7740_format_yuyv[] = {
> +	{0x12, 0x00},
> +	{0x36, 0x3f},
> +	{0x80, 0x7f},
> +	{0x83, 0x01},
> +};
> +
> +static const struct reg_sequence ov7740_format_bggr8[] = {
> +	{0x36, 0x2f},
> +	{0x80, 0x01},
> +	{0x83, 0x04},
> +};
> +
> +static const struct ov7740_pixfmt ov7740_formats[] = {
> +	{
> +		.mbus_code = MEDIA_BUS_FMT_YUYV8_2X8,
> +		.colorspace = V4L2_COLORSPACE_SRGB,
> +		.regs = ov7740_format_yuyv,
> +		.reg_num = ARRAY_SIZE(ov7740_format_yuyv),
> +	},
> +	{
> +		.mbus_code = MEDIA_BUS_FMT_SBGGR8_1X8,
> +		.colorspace = V4L2_COLORSPACE_SRGB,
> +		.regs = ov7740_format_bggr8,
> +		.reg_num = ARRAY_SIZE(ov7740_format_bggr8),
> +	}
> +};
> +#define N_OV7740_FMTS ARRAY_SIZE(ov7740_formats)
> +
> +static int ov7740_enum_mbus_code(struct v4l2_subdev *sd,
> +				 struct v4l2_subdev_pad_config *cfg,
> +				 struct v4l2_subdev_mbus_code_enum *code)
> +{
> +	if (code->pad || code->index >= N_OV7740_FMTS)
> +		return -EINVAL;
> +
> +	code->code = ov7740_formats[code->index].mbus_code;
> +
> +	return 0;
> +}
> +
> +static int ov7740_enum_frame_interval(struct v4l2_subdev *sd,
> +				struct v4l2_subdev_pad_config *cfg,
> +				struct v4l2_subdev_frame_interval_enum *fie)
> +{
> +	if (fie->pad)
> +		return -EINVAL;
> +
> +	if (fie->index >= 1)
> +		return -EINVAL;
> +
> +	if ((fie->width != VGA_WIDTH) || (fie->height != VGA_HEIGHT))
> +		return -EINVAL;
> +
> +	fie->interval.numerator = 1;
> +	fie->interval.denominator = 60;
> +
> +	return 0;
> +}
> +
> +static int ov7740_enum_frame_size(struct v4l2_subdev *sd,
> +				  struct v4l2_subdev_pad_config *cfg,
> +				  struct v4l2_subdev_frame_size_enum *fse)
> +{
> +	if (fse->pad)
> +		return -EINVAL;
> +
> +	if (fse->index > 0)
> +		return -EINVAL;
> +
> +	fse->min_width = fse->max_width = VGA_WIDTH;
> +	fse->min_height = fse->max_height = VGA_HEIGHT;
> +
> +	return 0;
> +}
> +
> +static int ov7740_try_fmt_internal(struct v4l2_subdev *sd,
> +				   struct v4l2_mbus_framefmt *fmt,
> +				   const struct ov7740_pixfmt **ret_fmt,
> +				   const struct ov7740_framesize **ret_frmsize)
> +{
> +	struct ov7740 *ov7740 = container_of(sd, struct ov7740, subdev);
> +	const struct ov7740_framesize *fsize = &ov7740_framesizes[0];
> +	int index, i;
> +
> +	for (index = 0; index < N_OV7740_FMTS; index++) {
> +		if (ov7740_formats[index].mbus_code == fmt->code)
> +			break;
> +	}
> +	if (index >= N_OV7740_FMTS) {
> +		/* default to first format */
> +		index = 0;
> +		fmt->code = ov7740_formats[0].mbus_code;
> +	}
> +	if (ret_fmt != NULL)
> +		*ret_fmt = ov7740_formats + index;
> +
> +	for (i = 0; i < ARRAY_SIZE(ov7740_framesizes); i++) {
> +		if ((fsize->width >= fmt->width) &&
> +		    (fsize->height >= fmt->height)) {
> +			fmt->width = fsize->width;
> +			fmt->height = fsize->height;
> +			break;
> +		}
> +
> +		fsize++;
> +	}
> +
> +	if (ret_frmsize != NULL)
> +		*ret_frmsize = fsize;
> +
> +	fmt->field = V4L2_FIELD_NONE;
> +	fmt->colorspace = ov7740_formats[index].colorspace;
> +
> +	ov7740->format = *fmt;
> +
> +	return 0;
> +}
> +
> +static int ov7740_set_fmt(struct v4l2_subdev *sd,
> +			  struct v4l2_subdev_pad_config *cfg,
> +			  struct v4l2_subdev_format *format)
> +{
> +	struct ov7740 *ov7740 = container_of(sd, struct ov7740, subdev);
> +	const struct ov7740_pixfmt *ovfmt;
> +	const struct ov7740_framesize *fsize;
> +#ifdef CONFIG_VIDEO_V4L2_SUBDEV_API
> +	struct v4l2_mbus_framefmt *mbus_fmt;
> +#endif
> +	int ret;
> +
> +	mutex_lock(&ov7740->mutex);
> +	if (format->pad) {
> +		ret = -EINVAL;
> +		goto error;
> +	}
> +
> +	if (format->which == V4L2_SUBDEV_FORMAT_TRY) {
> +		ret = ov7740_try_fmt_internal(sd, &format->format, NULL, NULL);
> +		if (ret)
> +			goto error;
> +#ifdef CONFIG_VIDEO_V4L2_SUBDEV_API
> +		mbus_fmt = v4l2_subdev_get_try_format(sd, cfg, format->pad);
> +		*mbus_fmt = format->format;
> +
> +		mutex_unlock(&ov7740->mutex);
> +		return 0;
> +#else
> +		ret = -ENOTTY;
> +		goto error;
> +#endif
> +	}
> +
> +	ret = ov7740_try_fmt_internal(sd, &format->format, &ovfmt, &fsize);
> +	if (ret)
> +		goto error;
> +
> +	if (format->which == V4L2_SUBDEV_FORMAT_ACTIVE) {
> +		regmap_multi_reg_write(ov7740->regmap,
> +				       ovfmt->regs, ovfmt->reg_num);
> +
> +		regmap_multi_reg_write(ov7740->regmap,
> +				       fsize->regs, fsize->reg_num);
> +	}
> +
> +	ov7740->fmt = ovfmt;
> +
> +	mutex_unlock(&ov7740->mutex);
> +	return 0;
> +
> +error:
> +	mutex_unlock(&ov7740->mutex);
> +	return ret;
> +}
> +
> +static int ov7740_get_fmt(struct v4l2_subdev *sd,
> +			  struct v4l2_subdev_pad_config *cfg,
> +			  struct v4l2_subdev_format *format)
> +{
> +	struct ov7740 *ov7740 = container_of(sd, struct ov7740, subdev);
> +#ifdef CONFIG_VIDEO_V4L2_SUBDEV_API
> +	struct v4l2_mbus_framefmt *mbus_fmt;
> +#endif
> +	int ret = 0;
> +
> +	mutex_lock(&ov7740->mutex);
> +	if (format->which == V4L2_SUBDEV_FORMAT_TRY) {
> +#ifdef CONFIG_VIDEO_V4L2_SUBDEV_API
> +		mbus_fmt = v4l2_subdev_get_try_format(sd, cfg, 0);
> +		format->format = *mbus_fmt;
> +		ret = 0;
> +#else
> +		ret = -ENOTTY;
> +#endif
> +	} else {
> +		format->format = ov7740->format;
> +	}
> +	mutex_unlock(&ov7740->mutex);
> +
> +	return ret;
> +}
> +
> +static const struct v4l2_subdev_pad_ops ov7740_subdev_pad_ops = {
> +	.enum_frame_interval = ov7740_enum_frame_interval,
> +	.enum_frame_size = ov7740_enum_frame_size,
> +	.enum_mbus_code = ov7740_enum_mbus_code,
> +	.get_fmt = ov7740_get_fmt,
> +	.set_fmt = ov7740_set_fmt,
> +};
> +
> +static const struct v4l2_subdev_ops ov7740_subdev_ops = {
> +	.core	= &ov7740_subdev_core_ops,
> +	.video	= &ov7740_subdev_video_ops,
> +	.pad	= &ov7740_subdev_pad_ops,
> +};
> +
> +static void ov7740_get_default_format(struct v4l2_subdev *sd,
> +				      struct v4l2_mbus_framefmt *format)
> +{
> +	struct ov7740 *ov7740 = container_of(sd, struct ov7740, subdev);
> +
> +	format->width = ov7740->frmsize->width;
> +	format->height = ov7740->frmsize->height;
> +	format->colorspace = ov7740->fmt->colorspace;
> +	format->code = ov7740->fmt->mbus_code;
> +	format->field = V4L2_FIELD_NONE;
> +}
> +
> +#ifdef CONFIG_VIDEO_V4L2_SUBDEV_API
> +static int ov7740_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
> +{
> +	struct ov7740 *ov7740 = container_of(sd, struct ov7740, subdev);
> +	struct v4l2_mbus_framefmt *format =
> +				v4l2_subdev_get_try_format(sd, fh->pad, 0);
> +
> +	mutex_lock(&ov7740->mutex);
> +	ov7740_get_default_format(sd, format);
> +	mutex_unlock(&ov7740->mutex);
> +
> +	return 0;
> +}
> +
> +static const struct v4l2_subdev_internal_ops ov7740_subdev_internal_ops = {
> +	.open = ov7740_open,
> +};
> +#endif
> +
> +static void ov7740_init_default_format(struct ov7740 *ov7740)
> +{
> +	ov7740->frmsize = &ov7740_framesizes[0];
> +	ov7740->fmt = &ov7740_formats[0];
> +
> +	regmap_multi_reg_write(ov7740->regmap,
> +			       ov7740->fmt->regs, ov7740->fmt->reg_num);
> +
> +	regmap_multi_reg_write(ov7740->regmap,
> +			       ov7740->frmsize->regs, ov7740->frmsize->reg_num);
> +}
> +
> +static int ov7740_probe_dt(struct i2c_client *client,
> +			   struct ov7740 *ov7740)
> +{
> +	ov7740->resetb_gpio = devm_gpiod_get_optional(&client->dev, "reset",
> +			GPIOD_OUT_HIGH);
> +	if (IS_ERR(ov7740->resetb_gpio)) {
> +		dev_info(&client->dev, "can't get %s GPIO\n", "reset");
> +		return PTR_ERR(ov7740->resetb_gpio);
> +	}
> +
> +	ov7740->pwdn_gpio = devm_gpiod_get_optional(&client->dev, "powerdown",
> +			GPIOD_OUT_LOW);
> +	if (IS_ERR(ov7740->pwdn_gpio)) {
> +		dev_info(&client->dev, "can't get %s GPIO\n", "powerdown");
> +		return PTR_ERR(ov7740->pwdn_gpio);
> +	}
> +
> +	return 0;
> +}
> +
> +static int ov7740_detect(struct ov7740 *ov7740)
> +{
> +	struct regmap *regmap = ov7740->regmap;
> +	unsigned int midh, midl, pidh, pidl;
> +	int ret;
> +
> +	ret = regmap_read(regmap, REG_MIDH, &midh);
> +	if (ret)
> +		return ret;
> +	if (midh != 0x7f)
> +		return -ENODEV;
> +
> +	ret = regmap_read(regmap, REG_MIDL, &midl);
> +	if (ret)
> +		return ret;
> +	if (midl != 0xa2)
> +		return -ENODEV;
> +
> +	ret = regmap_read(regmap, REG_PIDH, &pidh);
> +	if (ret)
> +		return ret;
> +	if (pidh != 0x77)
> +		return -ENODEV;
> +
> +	ret = regmap_read(regmap, REG_PIDL, &pidl);
> +	if (ret)
> +		return ret;
> +	if ((pidl != 0x40) && (pidl != 0x41) && (pidl != 0x42))
> +		return -ENODEV;
> +
> +	return 0;
> +}
> +
> +static int ov7740_init_controls(struct ov7740 *ov7740)
> +{
> +	struct i2c_client *client = v4l2_get_subdevdata(&ov7740->subdev);
> +	struct v4l2_ctrl_handler *ctrl_hdlr = &ov7740->ctrl_handler;
> +	int ret;
> +
> +	ret = v4l2_ctrl_handler_init(ctrl_hdlr, 2);
> +	if (ret < 0)
> +		return ret;
> +
> +	ctrl_hdlr->lock = &ov7740->mutex;
> +	ov7740->auto_wb = v4l2_ctrl_new_std(ctrl_hdlr, &ov7740_ctrl_ops,
> +					  V4L2_CID_AUTO_WHITE_BALANCE,
> +					  0, 1, 1, 1);
> +	ov7740->blue_balance = v4l2_ctrl_new_std(ctrl_hdlr, &ov7740_ctrl_ops,
> +					       V4L2_CID_BLUE_BALANCE,
> +					       0, 0xff, 1, 0x80);
> +	ov7740->red_balance = v4l2_ctrl_new_std(ctrl_hdlr, &ov7740_ctrl_ops,
> +					      V4L2_CID_RED_BALANCE,
> +					      0, 0xff, 1, 0x80);
> +
> +	ov7740->brightness = v4l2_ctrl_new_std(ctrl_hdlr, &ov7740_ctrl_ops,
> +					     V4L2_CID_BRIGHTNESS,
> +					     -255, 255, 1, 0);
> +	ov7740->contrast = v4l2_ctrl_new_std(ctrl_hdlr, &ov7740_ctrl_ops,
> +					   V4L2_CID_CONTRAST,
> +					   0, 127, 1, 0x20);
> +	ov7740->saturation = v4l2_ctrl_new_std(ctrl_hdlr, &ov7740_ctrl_ops,
> +			  V4L2_CID_SATURATION, 0, 256, 1, 0x80);
> +	ov7740->hflip = v4l2_ctrl_new_std(ctrl_hdlr, &ov7740_ctrl_ops,
> +					V4L2_CID_HFLIP, 0, 1, 1, 0);
> +	ov7740->vflip = v4l2_ctrl_new_std(ctrl_hdlr, &ov7740_ctrl_ops,
> +					V4L2_CID_VFLIP, 0, 1, 1, 0);
> +	ov7740->gain = v4l2_ctrl_new_std(ctrl_hdlr, &ov7740_ctrl_ops,
> +				       V4L2_CID_GAIN, 0, 1023, 1, 500);
> +	ov7740->auto_gain = v4l2_ctrl_new_std(ctrl_hdlr, &ov7740_ctrl_ops,
> +					    V4L2_CID_AUTOGAIN, 0, 1, 1, 1);
> +	ov7740->exposure = v4l2_ctrl_new_std(ctrl_hdlr, &ov7740_ctrl_ops,
> +					   V4L2_CID_EXPOSURE, 0, 65535, 1, 500);
> +	ov7740->auto_exposure = v4l2_ctrl_new_std_menu(ctrl_hdlr,
> +					&ov7740_ctrl_ops,
> +					V4L2_CID_EXPOSURE_AUTO,
> +					V4L2_EXPOSURE_MANUAL, 0,
> +					V4L2_EXPOSURE_AUTO);
> +
> +	ov7740->gain->flags |= V4L2_CTRL_FLAG_VOLATILE;
> +	ov7740->exposure->flags |= V4L2_CTRL_FLAG_VOLATILE;
> +
> +	v4l2_ctrl_auto_cluster(3, &ov7740->auto_wb, 0, false);
> +	v4l2_ctrl_auto_cluster(2, &ov7740->auto_gain, 0, true);
> +	v4l2_ctrl_auto_cluster(2, &ov7740->auto_exposure,
> +			       V4L2_EXPOSURE_MANUAL, false);
> +	v4l2_ctrl_cluster(2, &ov7740->hflip);
> +
> +	ret = v4l2_ctrl_handler_setup(ctrl_hdlr);
> +	if (ret) {
> +		dev_err(&client->dev, "%s control init failed (%d)\n",
> +			__func__, ret);
> +		goto error;
> +	}
> +
> +	ov7740->subdev.ctrl_handler = ctrl_hdlr;
> +	return 0;
> +
> +error:
> +	v4l2_ctrl_handler_free(ctrl_hdlr);
> +	mutex_destroy(&ov7740->mutex);
> +	return ret;
> +}
> +
> +static void ov7740_free_controls(struct ov7740 *ov7740)
> +{
> +	v4l2_ctrl_handler_free(ov7740->subdev.ctrl_handler);
> +	mutex_destroy(&ov7740->mutex);
> +}
> +
> +#define OV7740_MAX_REGISTER     0xff
> +static const struct regmap_config ov7740_regmap_config = {
> +	.reg_bits	= 8,
> +	.val_bits	= 8,
> +	.max_register	= OV7740_MAX_REGISTER,
> +};
> +
> +static int ov7740_probe(struct i2c_client *client,
> +			const struct i2c_device_id *id)
> +{
> +	struct ov7740 *ov7740;
> +	struct v4l2_subdev *sd;
> +	int ret;
> +
> +	if (!i2c_check_functionality(client->adapter,
> +				     I2C_FUNC_SMBUS_BYTE_DATA)) {
> +		dev_err(&client->dev,
> +			"OV7740: I2C-Adapter doesn't support SMBUS\n");
> +		return -EIO;
> +	}
> +
> +	ov7740 = devm_kzalloc(&client->dev, sizeof(*ov7740), GFP_KERNEL);
> +	if (!ov7740)
> +		return -ENOMEM;
> +
> +	ov7740->xvclk = devm_clk_get(&client->dev, "xvclk");
> +	if (IS_ERR(ov7740->xvclk)) {
> +		ret = PTR_ERR(ov7740->xvclk);
> +		dev_err(&client->dev,
> +			"OV7740: fail to get xvclk: %d\n", ret);
> +		return ret;
> +	}
> +
> +	ret = ov7740_probe_dt(client, ov7740);
> +	if (ret)
> +		return ret;
> +
> +	ov7740->regmap = devm_regmap_init_i2c(client, &ov7740_regmap_config);
> +	if (IS_ERR(ov7740->regmap)) {
> +		ret = PTR_ERR(ov7740->regmap);
> +		dev_err(&client->dev, "Failed to allocate register map: %d\n",
> +			ret);
> +		return ret;
> +	}
> +
> +	sd = &ov7740->subdev;
> +	client->flags |= I2C_CLIENT_SCCB;
> +	v4l2_i2c_subdev_init(sd, client, &ov7740_subdev_ops);
> +
> +#ifdef CONFIG_VIDEO_V4L2_SUBDEV_API
> +	sd->internal_ops = &ov7740_subdev_internal_ops;
> +	sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
> +#endif
> +
> +#if defined(CONFIG_MEDIA_CONTROLLER)
> +	ov7740->pad.flags = MEDIA_PAD_FL_SOURCE;
> +	sd->entity.function = MEDIA_ENT_F_CAM_SENSOR;
> +	ret = media_entity_pads_init(&sd->entity, 1, &ov7740->pad);
> +	if (ret)
> +		return ret;
> +#endif
> +
> +	ret = ov7740_set_power(ov7740, 1);
> +	if (ret)
> +		return ret;
> +
> +	ret = ov7740_detect(ov7740);
> +	if (ret)
> +		goto error_detect;
> +
> +	mutex_init(&ov7740->mutex);
> +
> +	ret = ov7740_init_controls(ov7740);
> +	if (ret)
> +		goto error_init_controls;
> +
> +	v4l_info(client, "chip found @ 0x%02x (%s)\n",
> +			client->addr << 1, client->adapter->name);
> +
> +	ov7740_init_default_format(ov7740);

This doesn't yet address the issue. The sensor will be powered off just a
few lines below, so the device state will be lost. You need to ensure the
registers get programmed after the sensor is powered on and before
streaming is started.

> +
> +	ov7740_get_default_format(sd, &ov7740->format);
> +
> +	ret = v4l2_async_register_subdev(sd);
> +	if (ret)
> +		goto error_async_register;
> +
> +	pm_runtime_set_active(&client->dev);
> +	pm_runtime_enable(&client->dev);
> +	pm_runtime_idle(&client->dev);
> +
> +	return 0;
> +
> +error_async_register:
> +	v4l2_ctrl_handler_free(ov7740->subdev.ctrl_handler);
> +error_init_controls:
> +	ov7740_free_controls(ov7740);
> +error_detect:
> +	ov7740_set_power(ov7740, 0);
> +	media_entity_cleanup(&ov7740->subdev.entity);
> +
> +	return ret;
> +}
> +
> +static int ov7740_remove(struct i2c_client *client)
> +{
> +	struct v4l2_subdev *sd = i2c_get_clientdata(client);
> +	struct ov7740 *ov7740 = container_of(sd, struct ov7740, subdev);
> +
> +	mutex_destroy(&ov7740->mutex);
> +	v4l2_ctrl_handler_free(ov7740->subdev.ctrl_handler);
> +#if defined(CONFIG_MEDIA_CONTROLLER)
> +	media_entity_cleanup(&ov7740->subdev.entity);
> +#endif
> +	v4l2_async_unregister_subdev(sd);
> +	ov7740_free_controls(ov7740);
> +
> +	pm_runtime_get_sync(&client->dev);
> +	pm_runtime_disable(&client->dev);
> +	pm_runtime_set_suspended(&client->dev);
> +	pm_runtime_put_noidle(&client->dev);
> +
> +	ov7740_set_power(ov7740, 0);
> +	return 0;
> +}
> +
> +static int __maybe_unused ov7740_runtime_suspend(struct device *dev)
> +{
> +	struct i2c_client *client = to_i2c_client(dev);
> +	struct v4l2_subdev *sd = i2c_get_clientdata(client);
> +	struct ov7740 *ov7740 = container_of(sd, struct ov7740, subdev);
> +
> +	ov7740_set_power(ov7740, 0);
> +
> +	return 0;
> +}
> +
> +static int __maybe_unused ov7740_runtime_resume(struct device *dev)
> +{
> +	struct i2c_client *client = to_i2c_client(dev);
> +	struct v4l2_subdev *sd = i2c_get_clientdata(client);
> +	struct ov7740 *ov7740 = container_of(sd, struct ov7740, subdev);
> +
> +	return ov7740_set_power(ov7740, 1);
> +}
> +
> +static const struct i2c_device_id ov7740_id[] = {
> +	{ "ov7740", 0 },
> +	{ /* sentinel */ }
> +};
> +MODULE_DEVICE_TABLE(i2c, ov7740_id);
> +
> +static const struct dev_pm_ops ov7740_pm_ops = {
> +	SET_RUNTIME_PM_OPS(ov7740_runtime_suspend, ov7740_runtime_resume, NULL)
> +};
> +
> +static const struct of_device_id ov7740_of_match[] = {
> +	{.compatible = "ovti,ov7740", },
> +	{ /* sentinel */ },
> +};
> +MODULE_DEVICE_TABLE(of, ov7740_of_match);
> +
> +static struct i2c_driver ov7740_i2c_driver = {
> +	.driver = {
> +		.name = "ov7740",
> +		.pm = &ov7740_pm_ops,
> +		.of_match_table = of_match_ptr(ov7740_of_match),
> +	},
> +	.probe    = ov7740_probe,
> +	.remove   = ov7740_remove,
> +	.id_table = ov7740_id,
> +};
> +module_i2c_driver(ov7740_i2c_driver);
> +
> +MODULE_DESCRIPTION("The V4L2 driver for Omnivision 7740 sensor");
> +MODULE_AUTHOR("Songjun Wu <songjun.wu-AIFe0yeh4nAAvxtiuMwx3w@public.gmane.org>");
> +MODULE_LICENSE("GPL v2");
> -- 
> 2.15.0
> 

-- 
Sakari Ailus
e-mail: sakari.ailus-X3B1VOXEql0@public.gmane.org
--
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

* [RFC 2/2] dt-bindings: mipi-dsi: Add dual-channel DSI related info
From: Archit Taneja @ 2017-12-05 10:33 UTC (permalink / raw)
  To: robh+dt-DgEjT+Ai2ygdnm+yROfE0A
  Cc: tomi.valkeinen-l0cyMroinI0, eric-WhKQ6XTQaPysTnJN9+BGXg,
	philippe.cornu-qxv4g6HH51o,
	laurent.pinchart-ryLnwIuWjnjg/C1BVhZhaw,
	thierry.reding-Re5JQEeQqe8AvxtiuMwx3w,
	nickey.yang-TNX95d0MmH7DzftRWevZcw,
	dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
	p.zabel-bIcnvbaLZ9MEGnE8C9+IrQ, devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-msm-u79uwXL29TY76Z2rM5mHXA,
	seanpaul-F7+t8E8rja9g9hUCZPvPmw,
	briannorris-F7+t8E8rja9g9hUCZPvPmw,
	maxime.ripard-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8,
	boris.brezillon-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8,
	a.hajda-Sze3O3UU22JBDgjK7y7TUQ, Archit Taneja
In-Reply-To: <20171205103356.9917-1-architt-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>

Add binding info for peripherals that support dual-channel DSI. Add
corresponding optional bindings for DSI host controllers that may
be configured in this mode.

Signed-off-by: Archit Taneja <architt-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
---
 .../devicetree/bindings/display/mipi-dsi-bus.txt   | 77 ++++++++++++++++++++++
 1 file changed, 77 insertions(+)

diff --git a/Documentation/devicetree/bindings/display/mipi-dsi-bus.txt b/Documentation/devicetree/bindings/display/mipi-dsi-bus.txt
index 77a7cec15f5b..f556aaafdf22 100644
--- a/Documentation/devicetree/bindings/display/mipi-dsi-bus.txt
+++ b/Documentation/devicetree/bindings/display/mipi-dsi-bus.txt
@@ -29,6 +29,12 @@ Required properties:
 - #size-cells: Should be 0. There are cases where it makes sense to use a
   different value here. See below.
 
+Optional properties:
+- clock-master: A DSI host controller may be used in conjunction with another DSI
+  host to drive the same peripheral. Hardware supporting such a configuration
+  generally requires the data on both the busses to be driven by the same clock.
+  The DSI host instance controlling this clock should contain this property.
+
 DSI peripheral
 ==============
 
@@ -61,6 +67,17 @@ primary control bus, but are also connected to a DSI bus (mostly for the data
 path). Connections between such peripherals and a DSI host can be represented
 using the graph bindings [1], [2].
 
+Peripherals that support dual channel DSI
+-----------------------------------------
+
+Peripherals with higher bandwidth requirements can be connected to 2 DSI
+busses. Each DSI bus/channel drives some portion of the pixel data (generally
+left/right half of each line of the display, or even/odd lines of the display).
+The graph bindings should be used to represent the multiple DSI busses that are
+connected to this peripheral. Each DSI host's output endpoint can be linked to
+an input endpoint of the DSI peripheral.
+
+
 [1] Documentation/devicetree/bindings/graph.txt
 [2] Documentation/devicetree/bindings/media/video-interfaces.txt
 
@@ -70,6 +87,8 @@ Examples
   with different virtual channel configurations.
 - (4) is an example of a peripheral on a I2C control bus connected with to
   a DSI host using of-graph bindings.
+- (5) is an example of 2 DSI hosts driving a dual-channel DSI peripheral,
+  which uses I2C as its primary control bus.
 
 1)
 	dsi-host {
@@ -157,3 +176,61 @@ Examples
 			};
 		};
 	};
+
+5)
+	i2c-host {
+		dsi-bridge@35 {
+			compatible = "...";
+			reg = <0x35>;
+
+			ports {
+				...
+
+				port@0 {
+					dsi0_in: endpoint {
+						remote-endpoint = <&dsi0_out>;
+					};
+				};
+
+				port@1 {
+					dsi1_in: endpoint {
+						remote-endpoint = <&dsi1_out>;
+					};
+				};
+			};
+		};
+	};
+
+	dsi0-host {
+		...
+
+		/*
+		 * this DSI instance drives the clock for both the host
+		 * controllers
+		 */
+		clock-master;
+
+		ports {
+			...
+
+			port@0 {
+				dsi0_out: endpoint {
+					remote-endpoint = <&dsi0_in>;
+				};
+			};
+		};
+	};
+
+	dsi1-host {
+		...
+
+		ports {
+			...
+
+			port@0 {
+				dsi1_out: endpoint {
+					remote-endpoint = <&dsi1_in>;
+				};
+			};
+		};
+	};
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation

--
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

* [RFC 1/2] dt-bindings: mipi-dsi: Add info about peripherals with non-DSI control bus
From: Archit Taneja @ 2017-12-05 10:33 UTC (permalink / raw)
  To: robh+dt
  Cc: tomi.valkeinen, eric, philippe.cornu, laurent.pinchart,
	thierry.reding, nickey.yang, dri-devel, p.zabel, devicetree,
	linux-arm-msm, seanpaul, briannorris, maxime.ripard,
	boris.brezillon, a.hajda, Archit Taneja
In-Reply-To: <20171205103356.9917-1-architt@codeaurora.org>

Add a section that describes dt-bindings for peripherals that support
MIPI DSI, but have a different bus as the primary control bus. Add an
example for such peripherals.

Signed-off-by: Archit Taneja <architt@codeaurora.org>
---
 .../devicetree/bindings/display/mipi-dsi-bus.txt   | 75 ++++++++++++++++++++--
 1 file changed, 68 insertions(+), 7 deletions(-)

diff --git a/Documentation/devicetree/bindings/display/mipi-dsi-bus.txt b/Documentation/devicetree/bindings/display/mipi-dsi-bus.txt
index 973c27273772..77a7cec15f5b 100644
--- a/Documentation/devicetree/bindings/display/mipi-dsi-bus.txt
+++ b/Documentation/devicetree/bindings/display/mipi-dsi-bus.txt
@@ -16,7 +16,7 @@ The following assumes that only a single peripheral is connected to a DSI
 host. Experience shows that this is true for the large majority of setups.
 
 DSI host
---------
+========
 
 In addition to the standard properties and those defined by the parent bus of
 a DSI host, the following properties apply to a node representing a DSI host.
@@ -30,11 +30,15 @@ Required properties:
   different value here. See below.
 
 DSI peripheral
---------------
+==============
 
-Peripherals are represented as child nodes of the DSI host's node. Properties
-described here apply to all DSI peripherals, but individual bindings may want
-to define additional, device-specific properties.
+Peripherals with DSI as control bus
+------------------------------------
+
+Peripherals with the DSI bus as the primary control path are represented as
+child nodes of the DSI host's node. Properties described here apply to all DSI
+peripherals, but individual bindings may want to define additional,
+device-specific properties.
 
 Required properties:
 - reg: The virtual channel number of a DSI peripheral. Must be in the range
@@ -49,9 +53,25 @@ case two alternative representations can be chosen:
   property is the number of the first virtual channel and the second cell is
   the number of consecutive virtual channels.
 
-Example
--------
+Peripherals with a different control bus
+----------------------------------------
+
+There are peripherals that have I2C/SPI (or some other non-DSI bus) as the
+primary control bus, but are also connected to a DSI bus (mostly for the data
+path). Connections between such peripherals and a DSI host can be represented
+using the graph bindings [1], [2].
+
+[1] Documentation/devicetree/bindings/graph.txt
+[2] Documentation/devicetree/bindings/media/video-interfaces.txt
 
+Examples
+========
+- (1), (2) and (3) are examples of a DSI host and peripheral on the DSI bus
+  with different virtual channel configurations.
+- (4) is an example of a peripheral on a I2C control bus connected with to
+  a DSI host using of-graph bindings.
+
+1)
 	dsi-host {
 		...
 
@@ -67,6 +87,7 @@ Example
 		...
 	};
 
+2)
 	dsi-host {
 		...
 
@@ -82,6 +103,7 @@ Example
 		...
 	};
 
+3)
 	dsi-host {
 		...
 
@@ -96,3 +118,42 @@ Example
 
 		...
 	};
+
+4)
+	i2c-host {
+		...
+
+		dsi-bridge@35 {
+			compatible = "...";
+			reg = <0x35>;
+
+			ports {
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				...
+
+				port@0 {
+					bridge_mipi_in: endpoint {
+						remote-endpoint = <&host_mipi_out>;
+					};
+				};
+			};
+		};
+	};
+
+	dsi-host {
+		...
+
+		ports {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			...
+
+			port@0 {
+				host_mipi_out: endpoint {
+					remote-endpoint = <&bridge_mipi_in>;
+				};
+			};
+		};
+	};
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation

^ permalink raw reply related

* [RFC 0/2] dt-bindings: mipi-dsi: dual-channel DSI bindings
From: Archit Taneja @ 2017-12-05 10:33 UTC (permalink / raw)
  To: robh+dt-DgEjT+Ai2ygdnm+yROfE0A
  Cc: tomi.valkeinen-l0cyMroinI0, eric-WhKQ6XTQaPysTnJN9+BGXg,
	philippe.cornu-qxv4g6HH51o,
	laurent.pinchart-ryLnwIuWjnjg/C1BVhZhaw,
	thierry.reding-Re5JQEeQqe8AvxtiuMwx3w,
	nickey.yang-TNX95d0MmH7DzftRWevZcw,
	dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
	p.zabel-bIcnvbaLZ9MEGnE8C9+IrQ, devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-msm-u79uwXL29TY76Z2rM5mHXA,
	seanpaul-F7+t8E8rja9g9hUCZPvPmw,
	briannorris-F7+t8E8rja9g9hUCZPvPmw,
	maxime.ripard-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8,
	boris.brezillon-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8,
	a.hajda-Sze3O3UU22JBDgjK7y7TUQ, Archit Taneja

DSI host controllers these days can be ganged together to drive larger
displays. Every SoC vendor supporting this is trying to add their own
DT property so that the corresponding drivers can identify that they
need to operate in the dual DSI mode. If we use the graph bindings, we
don't really need an additional DT property in the DSI host controller
to tell it that it's operating in dual-channel mode. It's something that
can be inferred 

I don't know much about how dual-channel is implemented on anything apart
from MSM chipsets, but one thing that seems universal is that the clock
driving both the DSI controllers (and corresponding PHYs) should have the
same clock source. The DSI instance that drives this clock is generally
called the "master", and the other instance the "slave". A "clock-master"
DT property has been proposed for the same.

There are some open item(s) that aren't described in the mipi DSI/DCS
spec, but we might need to have either as bindings or some sort of DSI
flags:

- When sending commands over DSI to peripherals with 2 DSI channels,
  some peripherals seem to have a requirement that both the DSIs trigger
  the same command at the same time. Otherwise, the controller on the
  peripheral goes a bit nuts. Is this common to all peripherals? Or are
  there devices where we just need to send the DCS/generic commands to
  the "master" DSI channel?

- When trying to read something back from the panel (a DCS read command
  followed by a BTA etc.), should both the DSI controllers be listening
  for data, or only the master?

- Anything else?

The first patch adds some explanation on how to deal with peripherals
that do DSI, but have a different control bus. This is something we've
already started using, but didn't have properly documented anywhere.

The second patch proposes bindings for DSI hosts/peripherals that
implement dual-channel DSI. 

Archit Taneja (2):
  dt-bindings: mipi-dsi: Add info about peripherals with non-DSI control
    bus
  dt-bindings: mipi-dsi: Add dual-channel DSI related info

 .../devicetree/bindings/display/mipi-dsi-bus.txt   | 152 ++++++++++++++++++++-
 1 file changed, 145 insertions(+), 7 deletions(-)

-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation

--
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

* Re: [PATCH 1/2] dt-binding: can: mcp2517fd: document device tree bindings
From: Martin Sperl @ 2017-12-05 10:26 UTC (permalink / raw)
  To: Patrick Menschel; +Cc: linux-can-u79uwXL29TY76Z2rM5mHXA, devicetree
In-Reply-To: <1ac487f7-17e3-c8a0-0f99-8138fe867373-1KBjaw7Xf1+zQB+pC5nmwQ@public.gmane.org>

Hi Patrick!


I had a quick look starting to implement gpiolib,

but I believe I would need to implement pin-ctrl on top to

make the Alternate functions work propperly.

I wonder if this effort is really worth it.

Martin

On 11/30/2017 06:49 PM, Patrick Menschel wrote:
> Am 30.11.2017 um 17:58 schriebkernel-TqfNSX0MhmxHKSADF0wUEw@public.gmane.org:
>>> drivers/tty/serial/max310x.c
>>> Documentation/devicetree/bindings/serial/maxim,max310x.txt
>>> Look for "#ifdef CONFIG_GPIOLIB”.
>> This is a gpio-controller, for which this is what I would implement.
>>
> Hi,
>
> you are mistaken about that, max310x chips are spi to uart bridges with
> strong ties to rs485 which is very similar to CAN except for the missing
> arbitration in hardware. Max14830 has GPIOs with clocking support, so
> this chip's driver also fused the main function with secondary gpio
> functions.
> https://datasheets.maximintegrated.com/en/ds/MAX14830.pdf
>
> Anyway I'm curious what is best practice for this sort of configuration.
>
> Regards,
> Patrick
>

--
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

* Re: [PATCH v8 0/6] stm32 clocksource driver rework
From: Alexandre Torgue @ 2017-12-05 10:16 UTC (permalink / raw)
  To: Daniel Lezcano, Benjamin Gaignard, robh+dt, mark.rutland, linux,
	mcoquelin.stm32, tglx, ludovic.barre, julien.thierry,
	sudeep.holla, arnd
  Cc: devicetree, linux-kernel, linux-arm-kernel
In-Reply-To: <1f3d581f-e001-5011-829e-bf79e2f639a7@linaro.org>



On 12/05/2017 11:15 AM, Daniel Lezcano wrote:
> On 05/12/2017 11:12, Alexandre Torgue wrote:
> [ ... ]
> 
>>> Benjamin Gaignard (6):
>>>     clocksource: timer_of: rename timer_of_exit to timer_of_cleanup
>>>     clocksource: stm32: convert driver to timer_of
>>>     clocksource: stm32: increase min delta value
>>>     clocksource: stm32: only use 32 bits timers
>>>     clocksource: stm32: add clocksource support
>>>     arm: dts: stm32: remove useless clocksource nodes
>>>
>>>    arch/arm/boot/dts/stm32f429.dtsi  |  32 -----
>>>    arch/arm/boot/dts/stm32f746.dtsi  |  32 -----
>>>    drivers/clocksource/Kconfig       |   1 +
>>>    drivers/clocksource/timer-of.c    |   9 +-
>>>    drivers/clocksource/timer-of.h    |   2 +-
>>>    drivers/clocksource/timer-stm32.c | 242
>>> ++++++++++++++++++++------------------
>>>    6 files changed, 138 insertions(+), 180 deletions(-)
>>>
>>
>> What is the status of this patch-set ? Is there a chance to have it for
>> v4.16 ?
> 
> I will take care of reviewing them this week. It is in my todo list.
> 
> 
Thanks Daniel

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply

* Re: [PATCH v8 0/6] stm32 clocksource driver rework
From: Daniel Lezcano @ 2017-12-05 10:15 UTC (permalink / raw)
  To: Alexandre Torgue, Benjamin Gaignard, robh+dt, mark.rutland, linux,
	mcoquelin.stm32, tglx, ludovic.barre, julien.thierry,
	sudeep.holla, arnd
  Cc: devicetree, linux-arm-kernel, linux-kernel
In-Reply-To: <dcff2fd0-58ca-51bb-ea2d-dfd1c5ca0cc3@st.com>

On 05/12/2017 11:12, Alexandre Torgue wrote:
[ ... ]

>> Benjamin Gaignard (6):
>>    clocksource: timer_of: rename timer_of_exit to timer_of_cleanup
>>    clocksource: stm32: convert driver to timer_of
>>    clocksource: stm32: increase min delta value
>>    clocksource: stm32: only use 32 bits timers
>>    clocksource: stm32: add clocksource support
>>    arm: dts: stm32: remove useless clocksource nodes
>>
>>   arch/arm/boot/dts/stm32f429.dtsi  |  32 -----
>>   arch/arm/boot/dts/stm32f746.dtsi  |  32 -----
>>   drivers/clocksource/Kconfig       |   1 +
>>   drivers/clocksource/timer-of.c    |   9 +-
>>   drivers/clocksource/timer-of.h    |   2 +-
>>   drivers/clocksource/timer-stm32.c | 242
>> ++++++++++++++++++++------------------
>>   6 files changed, 138 insertions(+), 180 deletions(-)
>>
> 
> What is the status of this patch-set ? Is there a chance to have it for
> v4.16 ?

I will take care of reviewing them this week. It is in my todo list.


-- 
 <http://www.linaro.org/> Linaro.org │ Open source software for ARM SoCs

Follow Linaro:  <http://www.facebook.com/pages/Linaro> Facebook |
<http://twitter.com/#!/linaroorg> Twitter |
<http://www.linaro.org/linaro-blog/> Blog

^ permalink raw reply

* Re: [PATCH v8 0/6] stm32 clocksource driver rework
From: Alexandre Torgue @ 2017-12-05 10:12 UTC (permalink / raw)
  To: Benjamin Gaignard, robh+dt, mark.rutland, linux, mcoquelin.stm32,
	daniel.lezcano, tglx, ludovic.barre, julien.thierry, sudeep.holla,
	arnd
  Cc: devicetree, linux-arm-kernel, linux-kernel
In-Reply-To: <1510649563-22975-1-git-send-email-benjamin.gaignard@linaro.org>

Hi

On 11/14/2017 09:52 AM, Benjamin Gaignard wrote:
> version 8:
>   - rebased on timers/core
>   - change timer_of_exit() name to timer_of_cleanup()
>   - update stm32 clocksource driver to use this function
> 
> version 7:
>   - reword "clocksource: stm32: only use 32 bits timers" commit message
>     to give more details about why 16 bits are problematics.
> 
> version 6:
>   - add dedicated patch min delta change
>   - rework commit messages, I hope it will be better now
>   - change new function name from timer_of_deinit to timer_of_exit
>   - make stm32_clock_event_set_next_event() safer like done in other
>     drivers
> 
> version 6:
> - add timer_of_deinit function in core
> - rework failure cases in probe function
> 
> version 5:
> - rebase on top of timer/core branch
> - rework commit message of the first patch
> 
> version 4:
> - split patch in 3 parts
>    - convert code to timer_of
>    - only use 32 bits timers
>    - add clocksource support
> 
> version 3:
> - fix comments done by Daniel
> - use timer_of helper functions
> 
> version 2:
> - fix uninitialized variable
> 
> Benjamin Gaignard (6):
>    clocksource: timer_of: rename timer_of_exit to timer_of_cleanup
>    clocksource: stm32: convert driver to timer_of
>    clocksource: stm32: increase min delta value
>    clocksource: stm32: only use 32 bits timers
>    clocksource: stm32: add clocksource support
>    arm: dts: stm32: remove useless clocksource nodes
> 
>   arch/arm/boot/dts/stm32f429.dtsi  |  32 -----
>   arch/arm/boot/dts/stm32f746.dtsi  |  32 -----
>   drivers/clocksource/Kconfig       |   1 +
>   drivers/clocksource/timer-of.c    |   9 +-
>   drivers/clocksource/timer-of.h    |   2 +-
>   drivers/clocksource/timer-stm32.c | 242 ++++++++++++++++++++------------------
>   6 files changed, 138 insertions(+), 180 deletions(-)
> 

What is the status of this patch-set ? Is there a chance to have it for 
v4.16 ?

Thanks
Alex

^ permalink raw reply

* Re: [PATCH] arm64: dts: allwinner: a64: bananapi-m64: Add LED device node
From: Maxime Ripard @ 2017-12-05 10:05 UTC (permalink / raw)
  To: Chen-Yu Tsai
  Cc: devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-sunxi-/JYPxA39Uh5TLH3MbocFFw
In-Reply-To: <20171201162733.23156-1-wens-jdAy2FN1RRM@public.gmane.org>

[-- Attachment #1: Type: text/plain, Size: 942 bytes --]

Hi,

On Sat, Dec 02, 2017 at 12:27:33AM +0800, Chen-Yu Tsai wrote:
> The Bananapi-M64 has 3 LEDS in red, green, and blue. These are toggled
> via GPIO lines, which drive transistors that control current across the
> LEDS. The red LED is by default on, via an additional pull-up on the
> control line. We consider this means that it is a power indicator.
> So we set the "default-on" property for it.
> 
> The pingroups the GPIO lines belong to require external regulators be
> enabled to be able to drive the GPIO high. These regulators also have
> other purposes. However the pin controller does not have bindings for
> regulators. Here we just set them to always-on.

I guess we should take the opportunity to do just that.

We have been deferring this for quite some time now, this is a perfect
occasion to do it once and for all :)

Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com

^ permalink raw reply

* Re: [PATCH v3 1/3] dt-bindings: hwrng: Add Samsung Exynos 5250+ True RNG bindings
From: Krzysztof Kozlowski @ 2017-12-05 10:04 UTC (permalink / raw)
  To: Łukasz Stelmach
  Cc: Rob Herring, Andrew F . Davis, PrasannaKumar Muralidharan,
	Matt Mackall, Herbert Xu, Kukjin Kim, devicetree, linux-crypto,
	linux-samsung-soc, linux-kernel, Marek Szyprowski,
	Bartlomiej Zolnierkiewicz
In-Reply-To: <878tehbjyu.fsf%l.stelmach@samsung.com>

On Tue, Dec 5, 2017 at 10:30 AM, Łukasz Stelmach <l.stelmach@samsung.com> wrote:
> It was <2017-12-04 pon 14:13>, when Krzysztof Kozlowski wrote:
>> On Mon, Dec 4, 2017 at 1:53 PM, Łukasz Stelmach <l.stelmach@samsung.com> wrote:
>>> Add binding documentation for the True Random Number Generator
>>> found on Samsung Exynos 5250+ SoCs.
>>>
>>> Signed-off-by: Łukasz Stelmach <l.stelmach@samsung.com>
>>> ---
>>>  .../devicetree/bindings/rng/samsung,exynos5250-trng.txt | 17 +++++++++++++++++
>>>  1 file changed, 17 insertions(+)
>>>  create mode 100644 Documentation/devicetree/bindings/rng/samsung,exynos5250-trng.txt
>>>
>>> diff --git
>>> a/Documentation/devicetree/bindings/rng/samsung,exynos5250-trng.txt
>>> b/Documentation/devicetree/bindings/rng/samsung,exynos5250-trng.txt
>>> new file mode 100644
>>> index 000000000000..5a613a4ec780
>>> --- /dev/null
>>> +++ b/Documentation/devicetree/bindings/rng/samsung,exynos5250-trng.txt
>>> @@ -0,0 +1,17 @@
>>> +Exynos True Random Number Generator
>>> +
>>> +Required properties:
>>> +
>>> +- compatible  : Should be "samsung,exynos5250-trng".
>>> +- reg         : Specifies base physical address and size of the registers map.
>>> +- clocks      : Phandle to clock-controller plus clock-specifier pair.
>>> +- clock-names : "secss" as a clock name.
>>> +
>>> +Example:
>>> +
>>> +       rng@10830600 {
>>> +               compatible = "samsung,exynos5250-trng";
>>> +               reg = <0x10830600 0x100>;
>>> +               clocks = <&clock CLK_SSS>;
>>> +               clock-names = "secss";
>>> +       };
>>> --
>>> 2.11.0
>>
>> Mine and Rob's tags disappeared and I think you did not introduce any
>> major changes here, right?
>
> A very experienced kernel developer adviced me to remove them.

In that case:
Reviewed-by: Krzysztof Kozlowski <krzk@kernel.org>

BR,
Krzysztof

^ permalink raw reply

* Re: [PATCH v2] ARM: dts: sun8i: h3: Add dts file for Libre Computer Board ALL-H3-CC H3 ver.
From: Maxime Ripard @ 2017-12-05 10:03 UTC (permalink / raw)
  To: Chen-Yu Tsai
  Cc: devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-sunxi-/JYPxA39Uh5TLH3MbocFFw
In-Reply-To: <20171205060615.14349-1-wens-jdAy2FN1RRM@public.gmane.org>

[-- Attachment #1: Type: text/plain, Size: 2187 bytes --]

On Tue, Dec 05, 2017 at 02:06:15PM +0800, Chen-Yu Tsai wrote:
> The Libre Computer Board ALL-H3-CC from Libre Technology is a Raspberry
> Pi B+ form factor single board computer based on the Allwinner H3 SoC.
> The board has 1GB DDR3 SDRAM, provided by 4 2Gb chips. The mounting holes
> and connectors are in the exact same position as on the Raspberry Pi B+.
> 
> Raspberry Pi B+ like peripherals supported on this board include:
> 
>   - Power input through micro-USB connector (without USB OTG)
>   - Native 100 Mbps ethernet using the internal PHY, as opposed to
>     USB-based on the RPi
>   - 4x USB 2.0 host ports, directly connected to the SoC, as opposed to
>     being connected through a USB 2.0 hub on the RPi
>   - TV and audio output on a 3.5mm TRRS jack
>   - HDMI output
>   - Micro-SD card slot
>   - Standard RPi B+ GPIO header, with the standard peripherals routed to
>     the same pins.
> 
>     * 5V, 3.3V power, and ground
>     * I2C0 on the H3 is routed to I2C1 pins on the RPi header
>     * I2C1 on the H3 is routed to I2C0 pins on the RPi header
>     * UART1 on the H3 is routed to UART0 pins on the RPi header
>     * SPI0 on the H3 is routed to SPI0 pins on the RPi header,
>       with GPIO pin PA17 replacing the missing Chip Select 1
>     * I2S1 on the H3 is routed to PCM pins on the RPi header
> 
>   - Additional peripherals from the H3 are available on different pins.
>     These include I2S0, JTAG, PWM1, SPDIF, SPI1, and UART3
> 
> In addition, there are a number of new features:
> 
>   - Console UART header
>   - Consumer IR receiver
>   - Camera interface (not compatible with RPi)
>   - Onboard microphone
>   - eMMC expansion module port
>   - Heatsink mounting holes
>   - Power button
> 
> The power button requires corresponding software for the embedded
> coprocessor to properly function.
> 
> This patch adds a dts file for this board that enables all "onboard"
> peripherals currently supported. This means no display or camera
> support.
> 
> Signed-off-by: Chen-Yu Tsai <wens-jdAy2FN1RRM@public.gmane.org>

Applied, thanks!
Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com

^ permalink raw reply

* RE: [PATCH] Documentation: binding: Update endianness usage
From: Prabhakar Kushwaha @ 2017-12-05  9:45 UTC (permalink / raw)
  To: Scott Wood,
	linux-mtd-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org,
	devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
  Cc: dedekind1-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org,
	computersforpeace-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org
In-Reply-To: <1512441957.10062.6.camel-fOR+EgIDQEHk1uMJSBkQmQ@public.gmane.org>

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain; charset="utf-8", Size: 2924 bytes --]


> -----Original Message-----
> From: Scott Wood [mailto:oss@buserror.net]
> Sent: Tuesday, December 05, 2017 8:16 AM
> To: Prabhakar Kushwaha <prabhakar.kushwaha@nxp.com>; linux-
> mtd@lists.infradead.org; devicetree@vger.kernel.org
> Cc: dedekind1@gmail.com; computersforpeace@gmail.com
> Subject: Re: [PATCH] Documentation: binding: Update endianness usage
> 
> On Mon, 2017-12-04 at 04:33 +0000, Prabhakar Kushwaha wrote:
> > > -----Original Message-----
> > > From: Scott Wood [mailto:oss@buserror.net]
> > > Sent: Saturday, December 02, 2017 3:25 AM
> > > To: Prabhakar Kushwaha <prabhakar.kushwaha@nxp.com>; linux-
> > > mtd@lists.infradead.org; devicetree-discuss@lists.ozlabs.org
> > > Cc: dedekind1@gmail.com; computersforpeace@gmail.com
> > > Subject: Re: [PATCH] Documentation: binding: Update endianness usage
> > >
> > > On Fri, 2017-12-01 at 08:42 +0000, Prabhakar Kushwaha wrote:
> > > > > -----Original Message-----
> > > > > From: Scott Wood [mailto:oss@buserror.net]
> > > > > Sent: Friday, December 01, 2017 10:43 AM
> > > > > To: Prabhakar Kushwaha <prabhakar.kushwaha@nxp.com>; linux-
> > > > > mtd@lists.infradead.org; devicetree-discuss@lists.ozlabs.org
> > > > > Cc: dedekind1@gmail.com; computersforpeace@gmail.com
> > > > > Subject: Re: [PATCH] Documentation: binding: Update endianness usage
> > > > >
> > > > > If big endian is the default, is this change really
> > > > > necessary?  Particularly
> > > > > since the big endian chips are older and thus have existing device
> > > > > trees.
> > > > >
> > > >
> > > > Earlier endianness information was only used for "how to"  access IFC-
> > > > NAND
> > > > register access.
> > > > Now this info  will also be used for defining swap requirement of NOR
> > > > flash.
> > >
> > > Is this a difference between LS1021A and PPC-based chips?
> > >
> >
> > Yes.
> > CONFIG_MTD_CFI_BE_BYTE_SWAP needs to be defined For LS1021A, LS1043A,
> > LS1046A
> 
> Only because you're running a little-endian kernel on those chips.  I still
> don't see why the absence of a little-endian property isn't sufficient to
> communicate that the hardware is big-endian given that that's the established
> default.
> 
> I now see your patch to of_flash_probe... where is the non-IFC-specific
> binding that says the *parent* of a CFI node should be looked at for this?
> Where in general are endian properties kept in the parent of the node with
> "reg"?  The right answer is to add endianness to mtd-physmap.txt.
> 

Flashes are always littler endian. 
It is because of IFC controller behavior, endianness is required.  
So as per my understanding, this info should go in IFC binding. 

Please help me if I am not able to understand your view.

--prabhakar


N‹§²æìr¸›yúèšØb²X¬¶Ç§vØ^–)Þº{.nÇ+‰·zøœzÚÞz)í…æèw*\x1fjg¬±¨\x1e¶‰šŽŠÝ¢j.ïÛ°\½½MŽúgjÌæa×\x02››–' ™©Þ¢¸\f¢·¦j:+v‰¨ŠwèjØm¶Ÿÿ¾\a«‘êçzZ+ƒùšŽŠÝ¢j"ú!¶i

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox