Devicetree
 help / color / mirror / Atom feed
* [PATCH 1/4] dt-bindings: add multidomain support to i.MX GPC DT binding
From: Lucas Stach @ 2017-01-20 15:52 UTC (permalink / raw)
  To: Shawn Guo
  Cc: Fabio Estevam, Rob Herring, Mark Rutland,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	kernel-bIcnvbaLZ9MEGnE8C9+IrQ,
	patchwork-lst-bIcnvbaLZ9MEGnE8C9+IrQ
In-Reply-To: <20170120155225.31905-1-l.stach-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>

This adds a new binding for the Freescale i.MX GPC block, which allows
to describe multiple power domains in a more natural way. The driver
will continue to support the old binding for existing DTBs, but new
features like the additional domains present on i.MX6SX will only be
usable with the new binding.

Signed-off-by: Lucas Stach <l.stach-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
---
 .../devicetree/bindings/power/fsl,imx-gpc.txt      | 81 ++++++++++++++--------
 1 file changed, 54 insertions(+), 27 deletions(-)

diff --git a/Documentation/devicetree/bindings/power/fsl,imx-gpc.txt b/Documentation/devicetree/bindings/power/fsl,imx-gpc.txt
index 65cc0345747d..e5b660018d63 100644
--- a/Documentation/devicetree/bindings/power/fsl,imx-gpc.txt
+++ b/Documentation/devicetree/bindings/power/fsl,imx-gpc.txt
@@ -1,22 +1,41 @@
 Freescale i.MX General Power Controller
 =======================================
 
-The i.MX6Q General Power Control (GPC) block contains DVFS load tracking
-counters and Power Gating Control (PGC) for the CPU and PU (GPU/VPU) power
-domains.
+The i.MX6 General Power Control (GPC) block contains DVFS load tracking
+counters and Power Gating Control (PGC).
 
 Required properties:
 - compatible: Should be "fsl,imx6q-gpc" or "fsl,imx6sl-gpc"
 - reg: should be register base and length as documented in the
   datasheet
-- interrupts: Should contain GPC interrupt request 1
-- pu-supply: Link to the LDO regulator powering the PU power domain
-- clocks: Clock phandles to devices in the PU power domain that need
-	  to be enabled during domain power-up for reset propagation.
-- #power-domain-cells: Should be 1, see below:
+- interrupts: Should contain one interrupt specifier for the GPC interrupt
+- clocks: Must contain an entry for each entry in clock-names.
+  See Documentation/devicetree/bindings/clocks/clock-bindings.txt for details.
+- clock-names: Must include the following entries:
+  - ipg
+- pgc: a list of child nodes describing the SoC power domains controlled by the
+  power gating controller.
 
-The gpc node is a power-controller as documented by the generic power domain
-bindings in Documentation/devicetree/bindings/power/power_domain.txt.
+The power domains are generic power domain providers as documented in
+Documentation/devicetree/bindings/power/power_domain.txt. They are described as
+subnodes of the GPC and should contain the following
+
+Required properties:
+- reg: the DOMAIN_INDEX as used by the client devices to refer to this
+  power domain
+  The following DOMAIN_INDEX values are valid for i.MX6Q:
+  ARM_DOMAIN     0
+  PU_DOMAIN      1
+  The following additional DOMAIN_INDEX value is valid for i.MX6SL:
+  DISPLAY_DOMAIN 2
+
+- #power-domain-cells: Should be 0
+
+Optional properties:
+- clocks: a number of phandles to clocks that need to be enabled during domain
+  power-up sequencing to ensure reset propagation into devices located inside
+  this power domain
+- domain-supply: a phandle to the regulator powering this domain
 
 Example:
 
@@ -25,14 +44,29 @@ Example:
 		reg = <0x020dc000 0x4000>;
 		interrupts = <0 89 IRQ_TYPE_LEVEL_HIGH>,
 			     <0 90 IRQ_TYPE_LEVEL_HIGH>;
-		pu-supply = <&reg_pu>;
-		clocks = <&clks IMX6QDL_CLK_GPU3D_CORE>,
-			 <&clks IMX6QDL_CLK_GPU3D_SHADER>,
-			 <&clks IMX6QDL_CLK_GPU2D_CORE>,
-			 <&clks IMX6QDL_CLK_GPU2D_AXI>,
-			 <&clks IMX6QDL_CLK_OPENVG_AXI>,
-			 <&clks IMX6QDL_CLK_VPU_AXI>;
-		#power-domain-cells = <1>;
+		clocks = <&clks IMX6QDL_CLK_IPG>;
+		clock-names = "ipg";
+		
+		pgc {
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			power-domain@0 {
+				reg = <0>;
+				#power-domain-cells = <0>;
+			};
+			pd_pu: power-domain@1 {
+				reg = <1>;
+				#power-domain-cells = <0>;
+				domain-supply = <&reg_pu>;
+				clocks = <&clks IMX6QDL_CLK_GPU3D_CORE>,
+				         <&clks IMX6QDL_CLK_GPU3D_SHADER>,
+				         <&clks IMX6QDL_CLK_GPU2D_CORE>,
+				         <&clks IMX6QDL_CLK_GPU2D_AXI>,
+				         <&clks IMX6QDL_CLK_OPENVG_AXI>,
+				         <&clks IMX6QDL_CLK_VPU_AXI>;
+			};
+		};
 	};
 
 
@@ -40,20 +74,13 @@ Specifying power domain for IP modules
 ======================================
 
 IP cores belonging to a power domain should contain a 'power-domains' property
-that is a phandle pointing to the gpc device node and a DOMAIN_INDEX specifying
-the power domain the device belongs to.
+that is a phandle pointing to the power domain the device belongs to.
 
 Example of a device that is part of the PU power domain:
 
 	vpu: vpu@02040000 {
 		reg = <0x02040000 0x3c000>;
 		/* ... */
-		power-domains = <&gpc 1>;
+		power-domains = <&pd_pu>;
 		/* ... */
 	};
-
-The following DOMAIN_INDEX values are valid for i.MX6Q:
-ARM_DOMAIN     0
-PU_DOMAIN      1
-The following additional DOMAIN_INDEX value is valid for i.MX6SL:
-DISPLAY_DOMAIN 2
-- 
2.11.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

* [PATCH 0/4] i.MX6 power gating controller rework
From: Lucas Stach @ 2017-01-20 15:52 UTC (permalink / raw)
  To: Shawn Guo
  Cc: Fabio Estevam, Rob Herring, Mark Rutland,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	kernel-bIcnvbaLZ9MEGnE8C9+IrQ,
	patchwork-lst-bIcnvbaLZ9MEGnE8C9+IrQ

This is a new attempt at rewriting the i.MX6 GPC driver to properly
support multiple power domains. This needs a new DT binding to properly
describe the power domain properties in the devicetree. Newer SoCs
like the i.MX6SX are exposing more than 1 device power domain.

This new series splits out the PGC part of the GPC driver and moves it
from the architecture code to drivers/soc. It is essentially a complete
re-write of the driver, so this time I didn't try to keep it in one
commit, as this seems to cause more confusion than good for the reviewers.

The new driver keeps compatibility with the old DT binding, but new
features will only be added using the new binding.

Lucas Stach (4):
  dt-bindings: add multidomain support to i.MX GPC DT binding
  ARM: imx6: remove PGC handling from GPC driver
  soc/imx: add new GPC driver
  ARM: imx6: adopt DT to new GPC binding

 .../devicetree/bindings/power/fsl,imx-gpc.txt      |  81 ++--
 arch/arm/boot/dts/imx6q.dtsi                       |   2 +-
 arch/arm/boot/dts/imx6qdl.dtsi                     |  38 +-
 arch/arm/mach-imx/gpc.c                            | 217 ----------
 drivers/soc/Makefile                               |   1 +
 drivers/soc/imx/Makefile                           |   1 +
 drivers/soc/imx/gpc.c                              | 480 +++++++++++++++++++++
 7 files changed, 564 insertions(+), 256 deletions(-)
 create mode 100644 drivers/soc/imx/Makefile
 create mode 100644 drivers/soc/imx/gpc.c

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

* RE: [PATCH v3 1/3] mmc: sh_mobile_sdhi: add support for 2 clocks
From: Chris Brandt @ 2017-01-20 15:52 UTC (permalink / raw)
  To: Ulf Hansson
  Cc: Rob Herring, Mark Rutland, Simon Horman, Wolfram Sang,
	Geert Uytterhoeven,
	devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
	linux-mmc-u79uwXL29TY76Z2rM5mHXA@public.gmane.org, Linux-Renesas
In-Reply-To: <CAPDyKFqO3YrDdKqOqJ=xKSH7uAiZ+rCPEDKMZ+c8Y5RKaVK4kg-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>

Hello Ulf,


On Friday, January 20, 2017, Ulf Hansson wrote:
> On 18 January 2017 at 18:25, Chris Brandt <chris.brandt@renesas.com>
> wrote:
> > Some controllers have 2 clock sources instead of 1, so they both need
> > to be turned on/off.
> 
> This doesn't tell me enough. Please elaborate.
> 
> For example, tell how you treat the clocks, which of them that is optional
> and why.

Basically, the chip designers went in and broke out the logic that just does
the card detect (more or less it's probably just some simple IRQ logic) so
that you could shut off the IP block, but if you put in a card, the internal
interrupt signal still went to the interrupt controller and registered the
interrupt even though the rest of the IP block (including the register space)
was dead.

The idea seems to be that you could put the entire chip into low power mode
and wake it up if you stuck a card in.

My guess is that this was for some customer request or something.

Personally...you could have done the same thing if you laid out a board
and tied one of the extra IRQ lines to the cd signal...but I'm not sure if
anyone thought about that at the time.


So to your request, I could put all this ugly info into the documentation,
but basically all I'm trying to do is join the 2 clocks back together
to make it work like all the other SoCs since this new 'feature' might
not really be practical to every use in this environment.



> >  static int sh_mobile_sdhi_card_busy(struct mmc_host *mmc) @@ -572,6
> > +581,10 @@ static int sh_mobile_sdhi_probe(struct platform_device *pdev)
> >                 goto eprobe;
> >         }
> >
> > +       priv->clk_cd = devm_clk_get(&pdev->dev, "cd");
> > +       if (IS_ERR(priv->clk_cd))
> > +               priv->clk_cd = NULL;
> 
> Is this clock solely about card detection? So in cases when you have a
> GPIO card detect, the clock isn't needed?
> 
> Just trying to understand things a bit better...

According to the hardware manual, enabling the "core" clock but not the
"cd" clock is not a valid setting. So in our case, it's always all or
nothing.


Chris

^ permalink raw reply

* Re: [PATCH 0/3] ARM64: meson-gxbb: Add WeTek Boards
From: Kevin Hilman @ 2017-01-20 15:50 UTC (permalink / raw)
  To: Neil Armstrong
  Cc: carlo, linux-amlogic, linux-arm-kernel, linux-kernel, devicetree
In-Reply-To: <1484736642-5451-1-git-send-email-narmstrong@baylibre.com>

Neil Armstrong <narmstrong@baylibre.com> writes:

> This serie adds support for the WeTek Hub and Play2 boards.
> The Hub is an extremely small IPTv Set-Top-Box and the Play2 is a more
> traditionnal Satellite or Terrestrial and IPTv Set-Top-Box.
>
> Both are based on the p200 Reference Design and out-of-tree support is
> based on OpenELEC kernel at [1].

Applied to v4.11/dt64 after s/OpenELEC/LibreELEC/

Kevin

> [1] https://github.com/wetek-enigma/linux-amlogic
>
> Neil Armstrong (3):
>   dt-bindings: vendor-prefix: Add wetek vendor prefix
>   ARM64: dts: meson-gxbb: Add support for WeTek Hub and Play
>   dt-bindings: amlogic: Add WeTek boards
>
>  Documentation/devicetree/bindings/arm/amlogic.txt  |  2 +
>  .../devicetree/bindings/vendor-prefixes.txt        |  1 +
>  arch/arm64/boot/dts/amlogic/Makefile               |  2 +
>  .../boot/dts/amlogic/meson-gxbb-wetek-hub.dts      | 66 +++++++++++++++
>  .../boot/dts/amlogic/meson-gxbb-wetek-play2.dts    | 94 ++++++++++++++++++++++
>  5 files changed, 165 insertions(+)
>  create mode 100644 arch/arm64/boot/dts/amlogic/meson-gxbb-wetek-hub.dts
>  create mode 100644 arch/arm64/boot/dts/amlogic/meson-gxbb-wetek-play2.dts

^ permalink raw reply

* Re: [PATCH v3 2/4] clk: gxbb: add the SAR ADC clocks and expose them
From: Kevin Hilman @ 2017-01-20 15:46 UTC (permalink / raw)
  To: Stephen Boyd
  Cc: Martin Blumenstingl, jic23, knaack.h, lars, pmeerw, robh+dt,
	mark.rutland, linux-iio, devicetree, linux-amlogic, linux-clk,
	carlo, catalin.marinas, will.deacon, mturquette, narmstrong,
	linux-arm-kernel
In-Reply-To: <20170119191332.GA7829@codeaurora.org>

Stephen Boyd <sboyd@codeaurora.org> writes:

> On 01/19, Martin Blumenstingl wrote:
>> The HHI_SAR_CLK_CNTL contains three SAR ADC specific clocks:
>> - a mux clock to choose between different ADC reference clocks (this is
>>   2-bit wide, but the datasheet only lists the parents for the first
>>   bit)
>> - a divider for the input/reference clock
>> - a gate which enables the ADC clock
>> 
>> Additionally this exposes the ADC core clock (CLKID_SAR_ADC) and
>> CLKID_SANA (which seems to enable the analog inputs, but unfortunately
>> there is no documentation for this - we just mimic what the vendor
>> driver does).
>> 
>> Signed-off-by: Martin Blumenstingl <martin.blumenstingl@googlemail.com>
>> Tested-by: Neil Armstrong <narmstrong@baylibre.com>
>> ---
>
> Acked-by: Stephen Boyd <sboyd@codeaurora.org>
>
> This should go through arm-soc along with the other patch to dts.

Applied to v4.11/dt64 of the amlogic tree.

Kevin

^ permalink raw reply

* Re: [PATCH v4 0/7] Add support for Video Data Order Adapter
From: Philipp Zabel @ 2017-01-20 15:44 UTC (permalink / raw)
  To: Hans Verkuil
  Cc: Michael Tretter, linux-media, devicetree, Hans Verkuil,
	Mauro Carvalho Chehab, kernel
In-Reply-To: <ff15e17c-fd62-f00e-e0f9-c141263868ea@xs4all.nl>

Hi Hans,

On Fri, 2017-01-20 at 15:54 +0100, Hans Verkuil wrote:
> Looks good to me.
>
> Philipp, just let me know if this is ready for merging, or you can make a pull
> request for Mauro yourself if you prefer.

Yes, with the recent fixes I think this is ready for merging.
If you don't mind picking it up, please go ahead.

regards
Philipp

> Regards,
> 
> 	Hans
> 
> On 01/20/2017 03:00 PM, Michael Tretter wrote:
> > Hello,
> > 
> > This is v4 of a patch series that adds support for the Video Data Order
> > Adapter (VDOA) that can be found on Freescale i.MX6. It converts the
> > macroblock tiled format produced by the CODA 960 video decoder to a
> > raster-ordered format for scanout.
> > 
> > Changes since v3:
> > 
> > - Patch 2/7: Add my copyright to vdoa copyright header
> > - Patch 2/7: Fix offset of chroma plane to be page-aligned
> > - Patch 6/7: Fix oops when releasing the coda driver by destroying vdoa
> >   context after removing all buffers
> > - Patch 6/7: Fix missing vdoa disable when switching from tiled to linear
> >   format
> > 
> > Changes since v2:
> > 
> > - Patch 1/7: Update commit message to include binding change; fix
> >   spelling/style in binding documentation
> > 
> > Changes since v1:
> > 
> > - Dropped patch 8/9 of v1
> > - Patch 1/7: Add devicetree binding documentation for fsl-vdoa
> > - Patch 6/7: I merged patch 5/9 and patch 8/9 of v1 into a single patch
> > - Patch 6/7: Use dt compatible instead of a phandle to find VDOA device
> > - Patch 6/7: Always check VDOA availability even if disabled via module
> >   parameter and do not print a message if VDOA cannot be found
> > - Patch 6/7: Do not change the CODA context in coda_try_fmt()
> > - Patch 6/7: Allocate an additional internal frame if the VDOA is in use
> > 
> > Michael Tretter (3):
> >   [media] coda: fix frame index to returned error
> >   [media] coda: use VDOA for un-tiling custom macroblock format
> >   [media] coda: support YUYV output if VDOA is used
> > 
> > Philipp Zabel (4):
> >   [media] dt-bindings: Add a binding for Video Data Order Adapter
> >   [media] coda: add i.MX6 VDOA driver
> >   [media] coda: correctly set capture compose rectangle
> >   [media] coda: add debug output about tiling
> > 
> >  .../devicetree/bindings/media/fsl-vdoa.txt         |  21 ++
> >  arch/arm/boot/dts/imx6qdl.dtsi                     |   2 +
> >  drivers/media/platform/Kconfig                     |   3 +
> >  drivers/media/platform/coda/Makefile               |   1 +
> >  drivers/media/platform/coda/coda-bit.c             |  93 ++++--
> >  drivers/media/platform/coda/coda-common.c          | 175 ++++++++++-
> >  drivers/media/platform/coda/coda.h                 |   3 +
> >  drivers/media/platform/coda/imx-vdoa.c             | 338 +++++++++++++++++++++
> >  drivers/media/platform/coda/imx-vdoa.h             |  58 ++++
> >  9 files changed, 652 insertions(+), 42 deletions(-)
> >  create mode 100644 Documentation/devicetree/bindings/media/fsl-vdoa.txt
> >  create mode 100644 drivers/media/platform/coda/imx-vdoa.c
> >  create mode 100644 drivers/media/platform/coda/imx-vdoa.h
> > 
> 
> 

^ permalink raw reply

* Re: [PATCH v3 0/9] meson-gx: reset RGMII PHYs and configure TX delay
From: Martin Blumenstingl @ 2017-01-20 15:32 UTC (permalink / raw)
  To: linux-amlogic-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	khilman-rdvid1DuHRBWk0Htik3J/w, carlo-KA+7E9HrN00dnm+yROfE0A
  Cc: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	devicetree-u79uwXL29TY76Z2rM5mHXA, will.deacon-5wv7dgnIgG8,
	catalin.marinas-5wv7dgnIgG8, mark.rutland-5wv7dgnIgG8,
	robh+dt-DgEjT+Ai2ygdnm+yROfE0A, narmstrong-rdvid1DuHRBWk0Htik3J/w,
	jbrunet-rdvid1DuHRBWk0Htik3J/w, Martin Blumenstingl
In-Reply-To: <20170120152232.13943-1-martin.blumenstingl-gM/Ye1E23mwN+BqQ9rBEUg@public.gmane.org>

On Fri, Jan 20, 2017 at 4:22 PM, Martin Blumenstingl
<martin.blumenstingl-gM/Ye1E23mwN+BqQ9rBEUg@public.gmane.org> wrote:
> This series adds the reset GPIOs for the (external) ethernet PHYs on all
> GXBB boards.
> Additionally it provides a ethernet PHY node which can be used to specify
> PHY-specific properties (this may be required if more boards require the
> "eee-broken-1000t" for the RTL8211F ethernet PHY). To make all board .dts
> consistent I chose to add the PHY node also for boards which don't have a
> RTL8211F PHY.
>
> Patch #7 from this series also removes ethernet support for the P200
> board because it was broken anyways and nobody seems to have a board
> available for testing. This was the outcome of the discussion from [0]
>
> Patch #8 was taken from (older versions of) my other series (see [1]):
> "[PATCH net-next v3 0/2] stmmac: dwmac-meson8b: configurable
> RGMII TX delay".
> The binding changes for amlogic,tx-delay-ns were ACK'ed already.
>
> Changes since v2:
> - fixed patch #2 to really update the P200 board (as it's the P200 which
>   actually uses a Micrel KSZ9031 RGMII PHY). Thanks to Neil Armstrong for
>   spotting this huge mistake!
> - instead of dropping ethernet support for P201 we simply re-configure it
>   to RMII mode (replaces patch #7) without a MDIO node (which keeps PHY
>   auto-scanning enabled). This got Neil Armstrong's ACK off-list already
>
> Changes since v1:
> - do not move the MDIO bus to meson-gx as this disables PHY auto-scanning
>   in the stmmac driver (this drops patch #1 from v1)
> - add the ethernet PHY reset GPIO for nexbox a95x which was forgotten in
>   v1
> - add the ethernet PHY reset GPIO for boards which were added since v1
>   (wetek hub and wetek play2)
> - rebased to apply against the current v4.11/dt64 branch
> - new in v2 (patch #7): disabled ethernet support for the P200 board (see
>   the commit description for more information). this patch is optional
> - new in v2 (patch #9): removed the phy-mode property from meson-gx (see
>   the commit description for more information). this patch is optional
>
>
> [0] http://lists.infradead.org/pipermail/linux-amlogic/2017-January/002053.html
> [1] http://lists.infradead.org/pipermail/linux-amlogic/2016-December/001834.html
>
> Martin Blumenstingl (9):
>   ARM64: dts: meson-gxbb-odroidc2: add the ethernet PHY's reset GPIO
>   ARM64: dts: meson-gxbb-p200: add the ethernet PHY's reset GPIO
>   ARM64: dts: meson-gxbb-vega-s95: add the ethernet PHY's reset GPIO
>   ARM64: dts: meson-gxbb-nexbox-a95x: add the ethernet PHY's reset GPIO
>   ARM64: dts: meson-gxbb-wetek-hub: add the ethernet PHY's reset GPIO
>   ARM64: dts: meson-gxbb-wetek-play2: add the ethernet PHY's reset GPIO
>   ARM64: dts: meson-gxbb-p201: fix ethernet support
>   ARM64: dts: amlogic: add the ethernet TX delay configuration
>   ARM64: dts: meson-gx: remove the phy-mode property from meson-gx
>
>  arch/arm64/boot/dts/amlogic/meson-gx.dtsi          |  1 -
>  .../boot/dts/amlogic/meson-gxbb-nexbox-a95x.dts    | 17 ++++++++++++++
>  .../arm64/boot/dts/amlogic/meson-gxbb-odroidc2.dts |  7 ++++++
>  arch/arm64/boot/dts/amlogic/meson-gxbb-p200.dts    | 26 ++++++++++++++++++++++
>  arch/arm64/boot/dts/amlogic/meson-gxbb-p201.dts    | 11 +++++++++
>  arch/arm64/boot/dts/amlogic/meson-gxbb-p20x.dtsi   |  6 -----
>  .../boot/dts/amlogic/meson-gxbb-vega-s95.dtsi      | 20 +++++++++++++++++
>  .../boot/dts/amlogic/meson-gxbb-wetek-hub.dts      | 26 ++++++++++++++++++++++
>  .../boot/dts/amlogic/meson-gxbb-wetek-play2.dts    | 26 ++++++++++++++++++++++
>  .../boot/dts/amlogic/meson-gxl-s905d-p230.dts      |  2 ++
>  .../arm64/boot/dts/amlogic/meson-gxm-nexbox-a1.dts |  2 ++
>  arch/arm64/boot/dts/amlogic/meson-gxm-q200.dts     |  2 ++
>  12 files changed, 139 insertions(+), 7 deletions(-)
I totally forgot to mention:
this applies to Kevin's v4.11/dt64 branch with Jerome's Odroid-C2
ethernet fix [0] applied on top of it


[0] https://git.kernel.org/cgit/linux/kernel/git/khilman/linux-amlogic.git/commit/?h=v4.11/integ&id=5a2288a68582ad3f1b42ed63ae5a3ca54e000965
--
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 v14 5/5] arm64: dt: hikey: Add optee node
From: Wei Xu @ 2017-01-20 15:30 UTC (permalink / raw)
  To: Jens Wiklander, Greg Kroah-Hartman, Arnd Bergmann, Olof Johansson,
	Andrew Morton
  Cc: linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	devicetree-u79uwXL29TY76Z2rM5mHXA, Al Viro,
	valentin.manea-hv44wF8Li93QT0dZR+AlfA,
	jean-michel.delorme-qxv4g6HH51o, emmanuel.michel-qxv4g6HH51o,
	javier-5MUHepqpBA1BDgjK7y7TUQ, Jason Gunthorpe, Mark Rutland,
	Michal Simek, Rob Herring, Will Deacon, Nishanth Menon,
	Andrew F . Davis, broonie-DgEjT+Ai2ygdnm+yROfE0A,
	scott.branden-dY08KVG/lbpWk0Htik3J/w, Jerome Forissier
In-Reply-To: <1484744296-30003-6-git-send-email-jens.wiklander-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>

Hi Jens,

On 2017/1/18 12:58, Jens Wiklander wrote:
> From: Jerome Forissier <jerome.forissier-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
> 
> Signed-off-by: Jerome Forissier <jerome.forissier-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
> Signed-off-by: Jens Wiklander <jens.wiklander-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>

Thanks!
Fine to me.
Acked-by: Wei Xu <xuwei5-C8/M+/jPZTeaMJb+Lgu22Q@public.gmane.org>

Best Regards,
Wei

> ---
>  arch/arm64/boot/dts/hisilicon/hi6220-hikey.dts | 7 +++++++
>  1 file changed, 7 insertions(+)
> 
> diff --git a/arch/arm64/boot/dts/hisilicon/hi6220-hikey.dts b/arch/arm64/boot/dts/hisilicon/hi6220-hikey.dts
> index dba3c131c62c..89c15399bec2 100644
> --- a/arch/arm64/boot/dts/hisilicon/hi6220-hikey.dts
> +++ b/arch/arm64/boot/dts/hisilicon/hi6220-hikey.dts
> @@ -406,6 +406,13 @@
>  			};
>  		};
>  	};
> +
> +	firmware {
> +		optee {
> +			compatible = "linaro,optee-tz";
> +			method = "smc";
> +		};
> +	};
>  };
>  
>  &uart2 {
> 

--
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 v3 0/9] meson-gx: reset RGMII PHYs and configure TX delay
From: Jerome Brunet @ 2017-01-20 15:27 UTC (permalink / raw)
  To: Martin Blumenstingl, linux-amlogic, khilman, carlo
  Cc: mark.rutland, devicetree, narmstrong, catalin.marinas,
	will.deacon, robh+dt, linux-arm-kernel
In-Reply-To: <20170120152232.13943-1-martin.blumenstingl@googlemail.com>

On Fri, 2017-01-20 at 16:22 +0100, Martin Blumenstingl wrote:
> This series adds the reset GPIOs for the (external) ethernet PHYs on
> all
> GXBB boards.
> Additionally it provides a ethernet PHY node which can be used to
> specify
> PHY-specific properties (this may be required if more boards require
> the
> "eee-broken-1000t" for the RTL8211F ethernet PHY). To make all board
> .dts
> consistent I chose to add the PHY node also for boards which don't
> have a
> RTL8211F PHY.
> 
> Patch #7 from this series also removes ethernet support for the P200
> board because it was broken anyways and nobody seems to have a board
> available for testing. This was the outcome of the discussion from
> [0]
> 
> Patch #8 was taken from (older versions of) my other series (see
> [1]):
> "[PATCH net-next v3 0/2] stmmac: dwmac-meson8b: configurable
> RGMII TX delay".
> The binding changes for amlogic,tx-delay-ns were ACK'ed already.
> 
> Changes since v2:
> - fixed patch #2 to really update the P200 board (as it's the P200
> which
>   actually uses a Micrel KSZ9031 RGMII PHY). Thanks to Neil Armstrong
> for
>   spotting this huge mistake!
> - instead of dropping ethernet support for P201 we simply re-
> configure it
>   to RMII mode (replaces patch #7) without a MDIO node (which keeps
> PHY
>   auto-scanning enabled). This got Neil Armstrong's ACK off-list
> already
> 
> Changes since v1:
> - do not move the MDIO bus to meson-gx as this disables PHY auto-
> scanning
>   in the stmmac driver (this drops patch #1 from v1)
> - add the ethernet PHY reset GPIO for nexbox a95x which was forgotten
> in
>   v1
> - add the ethernet PHY reset GPIO for boards which were added since
> v1
>   (wetek hub and wetek play2)
> - rebased to apply against the current v4.11/dt64 branch
> - new in v2 (patch #7): disabled ethernet support for the P200 board
> (see
>   the commit description for more information). this patch is
> optional
> - new in v2 (patch #9): removed the phy-mode property from meson-gx
> (see
>   the commit description for more information). this patch is
> optional
> 
> 
> [0] http://lists.infradead.org/pipermail/linux-amlogic/2017-January/0
> 02053.html
> [1] http://lists.infradead.org/pipermail/linux-amlogic/2016-December/
> 001834.html
> 
> Martin Blumenstingl (9):
>   ARM64: dts: meson-gxbb-odroidc2: add the ethernet PHY's reset GPIO
>   ARM64: dts: meson-gxbb-p200: add the ethernet PHY's reset GPIO
>   ARM64: dts: meson-gxbb-vega-s95: add the ethernet PHY's reset GPIO
>   ARM64: dts: meson-gxbb-nexbox-a95x: add the ethernet PHY's reset
> GPIO
>   ARM64: dts: meson-gxbb-wetek-hub: add the ethernet PHY's reset GPIO
>   ARM64: dts: meson-gxbb-wetek-play2: add the ethernet PHY's reset
> GPIO
>   ARM64: dts: meson-gxbb-p201: fix ethernet support
>   ARM64: dts: amlogic: add the ethernet TX delay configuration
>   ARM64: dts: meson-gx: remove the phy-mode property from meson-gx
> 
>  arch/arm64/boot/dts/amlogic/meson-gx.dtsi          |  1 -
>  .../boot/dts/amlogic/meson-gxbb-nexbox-a95x.dts    | 17
> ++++++++++++++
>  .../arm64/boot/dts/amlogic/meson-gxbb-odroidc2.dts |  7 ++++++
>  arch/arm64/boot/dts/amlogic/meson-gxbb-p200.dts    | 26
> ++++++++++++++++++++++
>  arch/arm64/boot/dts/amlogic/meson-gxbb-p201.dts    | 11 +++++++++
>  arch/arm64/boot/dts/amlogic/meson-gxbb-p20x.dtsi   |  6 -----
>  .../boot/dts/amlogic/meson-gxbb-vega-s95.dtsi      | 20
> +++++++++++++++++
>  .../boot/dts/amlogic/meson-gxbb-wetek-hub.dts      | 26
> ++++++++++++++++++++++
>  .../boot/dts/amlogic/meson-gxbb-wetek-play2.dts    | 26
> ++++++++++++++++++++++
>  .../boot/dts/amlogic/meson-gxl-s905d-p230.dts      |  2 ++
>  .../arm64/boot/dts/amlogic/meson-gxm-nexbox-a1.dts |  2 ++
>  arch/arm64/boot/dts/amlogic/meson-gxm-q200.dts     |  2 ++
>  12 files changed, 139 insertions(+), 7 deletions(-)

Looks good.

Reviewed-by: Jerome Brunet <jbrunet@baylibre.com>

> 

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

^ permalink raw reply

* [PATCH v3 9/9] ARM64: dts: meson-gx: remove the phy-mode property from meson-gx
From: Martin Blumenstingl @ 2017-01-20 15:22 UTC (permalink / raw)
  To: linux-amlogic-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	khilman-rdvid1DuHRBWk0Htik3J/w, carlo-KA+7E9HrN00dnm+yROfE0A
  Cc: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	devicetree-u79uwXL29TY76Z2rM5mHXA, will.deacon-5wv7dgnIgG8,
	catalin.marinas-5wv7dgnIgG8, mark.rutland-5wv7dgnIgG8,
	robh+dt-DgEjT+Ai2ygdnm+yROfE0A, narmstrong-rdvid1DuHRBWk0Htik3J/w,
	jbrunet-rdvid1DuHRBWk0Htik3J/w, Martin Blumenstingl
In-Reply-To: <20170120152232.13943-1-martin.blumenstingl-gM/Ye1E23mwN+BqQ9rBEUg@public.gmane.org>

The ethmac node has to be configured for each board due to different
pinctrl nodes for RGMII/RMII. Thus the phy-mode should be specified at
the same place (= in the board .dts), making it easier to read the board
.dts file (because the phy-mode is stated explicitly, without requiring
developers to read all "parent" .dtsi as well).

Signed-off-by: Martin Blumenstingl <martin.blumenstingl-gM/Ye1E23mwN+BqQ9rBEUg@public.gmane.org>
---
 arch/arm64/boot/dts/amlogic/meson-gx.dtsi | 1 -
 1 file changed, 1 deletion(-)

diff --git a/arch/arm64/boot/dts/amlogic/meson-gx.dtsi b/arch/arm64/boot/dts/amlogic/meson-gx.dtsi
index c1291007b37c..85bce028c76e 100644
--- a/arch/arm64/boot/dts/amlogic/meson-gx.dtsi
+++ b/arch/arm64/boot/dts/amlogic/meson-gx.dtsi
@@ -395,7 +395,6 @@
 			       0x0 0xc8834540 0x0 0x4>;
 			interrupts = <0 8 1>;
 			interrupt-names = "macirq";
-			phy-mode = "rgmii";
 			status = "disabled";
 		};
 
-- 
2.11.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

* [PATCH v3 8/9] ARM64: dts: amlogic: add the ethernet TX delay configuration
From: Martin Blumenstingl @ 2017-01-20 15:22 UTC (permalink / raw)
  To: linux-amlogic-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	khilman-rdvid1DuHRBWk0Htik3J/w, carlo-KA+7E9HrN00dnm+yROfE0A
  Cc: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	devicetree-u79uwXL29TY76Z2rM5mHXA, will.deacon-5wv7dgnIgG8,
	catalin.marinas-5wv7dgnIgG8, mark.rutland-5wv7dgnIgG8,
	robh+dt-DgEjT+Ai2ygdnm+yROfE0A, narmstrong-rdvid1DuHRBWk0Htik3J/w,
	jbrunet-rdvid1DuHRBWk0Htik3J/w, Martin Blumenstingl
In-Reply-To: <20170120152232.13943-1-martin.blumenstingl-gM/Ye1E23mwN+BqQ9rBEUg@public.gmane.org>

This adds the amlogic,tx-delay-ns property with the old (hardcoded)
default value of 2ns to all boards which are using an RGMII ethernet
PHY.

Signed-off-by: Martin Blumenstingl <martin.blumenstingl-gM/Ye1E23mwN+BqQ9rBEUg@public.gmane.org>
---
 arch/arm64/boot/dts/amlogic/meson-gxbb-odroidc2.dts    | 2 ++
 arch/arm64/boot/dts/amlogic/meson-gxbb-p200.dts        | 2 ++
 arch/arm64/boot/dts/amlogic/meson-gxbb-vega-s95.dtsi   | 2 ++
 arch/arm64/boot/dts/amlogic/meson-gxbb-wetek-hub.dts   | 2 ++
 arch/arm64/boot/dts/amlogic/meson-gxbb-wetek-play2.dts | 2 ++
 arch/arm64/boot/dts/amlogic/meson-gxl-s905d-p230.dts   | 2 ++
 arch/arm64/boot/dts/amlogic/meson-gxm-nexbox-a1.dts    | 2 ++
 arch/arm64/boot/dts/amlogic/meson-gxm-q200.dts         | 2 ++
 8 files changed, 16 insertions(+)

diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb-odroidc2.dts b/arch/arm64/boot/dts/amlogic/meson-gxbb-odroidc2.dts
index 6b5579522587..e63ed98d6c25 100644
--- a/arch/arm64/boot/dts/amlogic/meson-gxbb-odroidc2.dts
+++ b/arch/arm64/boot/dts/amlogic/meson-gxbb-odroidc2.dts
@@ -154,6 +154,8 @@
 	phy-handle = <&eth_phy0>;
 	phy-mode = "rgmii";
 
+	amlogic,tx-delay-ns = <2>;
+
 	snps,reset-gpio = <&gpio GPIOZ_14 0>;
 	snps,reset-delays-us = <0 10000 1000000>;
 	snps,reset-active-low;
diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb-p200.dts b/arch/arm64/boot/dts/amlogic/meson-gxbb-p200.dts
index fa0f84cfeaa9..6c7e914e9bd9 100644
--- a/arch/arm64/boot/dts/amlogic/meson-gxbb-p200.dts
+++ b/arch/arm64/boot/dts/amlogic/meson-gxbb-p200.dts
@@ -58,6 +58,8 @@
 	phy-handle = <&eth_phy0>;
 	phy-mode = "rgmii";
 
+	amlogic,tx-delay-ns = <2>;
+
 	snps,reset-gpio = <&gpio GPIOZ_14 0>;
 	snps,reset-delays-us = <0 10000 1000000>;
 	snps,reset-active-low;
diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb-vega-s95.dtsi b/arch/arm64/boot/dts/amlogic/meson-gxbb-vega-s95.dtsi
index 358ab5159bd5..4301ad860a76 100644
--- a/arch/arm64/boot/dts/amlogic/meson-gxbb-vega-s95.dtsi
+++ b/arch/arm64/boot/dts/amlogic/meson-gxbb-vega-s95.dtsi
@@ -131,6 +131,8 @@
 	phy-handle = <&eth_phy0>;
 	phy-mode = "rgmii";
 
+	amlogic,tx-delay-ns = <2>;
+
 	snps,reset-gpio = <&gpio GPIOZ_14 0>;
 	snps,reset-delays-us = <0 10000 1000000>;
 	snps,reset-active-low;
diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb-wetek-hub.dts b/arch/arm64/boot/dts/amlogic/meson-gxbb-wetek-hub.dts
index 47fe4e444f33..f6d8c70a26a2 100644
--- a/arch/arm64/boot/dts/amlogic/meson-gxbb-wetek-hub.dts
+++ b/arch/arm64/boot/dts/amlogic/meson-gxbb-wetek-hub.dts
@@ -72,6 +72,8 @@
 	phy-handle = <&eth_phy0>;
 	phy-mode = "rgmii";
 
+	amlogic,tx-delay-ns = <2>;
+
 	snps,reset-gpio = <&gpio GPIOZ_14 0>;
 	snps,reset-delays-us = <0 10000 1000000>;
 	snps,reset-active-low;
diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb-wetek-play2.dts b/arch/arm64/boot/dts/amlogic/meson-gxbb-wetek-play2.dts
index 9a8e2f492b97..1a222ce60a30 100644
--- a/arch/arm64/boot/dts/amlogic/meson-gxbb-wetek-play2.dts
+++ b/arch/arm64/boot/dts/amlogic/meson-gxbb-wetek-play2.dts
@@ -94,6 +94,8 @@
 	phy-handle = <&eth_phy0>;
 	phy-mode = "rgmii";
 
+	amlogic,tx-delay-ns = <2>;
+
 	snps,reset-gpio = <&gpio GPIOZ_14 0>;
 	snps,reset-delays-us = <0 10000 1000000>;
 	snps,reset-active-low;
diff --git a/arch/arm64/boot/dts/amlogic/meson-gxl-s905d-p230.dts b/arch/arm64/boot/dts/amlogic/meson-gxl-s905d-p230.dts
index f66939cacd37..7663d6775823 100644
--- a/arch/arm64/boot/dts/amlogic/meson-gxl-s905d-p230.dts
+++ b/arch/arm64/boot/dts/amlogic/meson-gxl-s905d-p230.dts
@@ -59,6 +59,8 @@
 	/* Select external PHY by default */
 	phy-handle = <&external_phy>;
 
+	amlogic,tx-delay-ns = <2>;
+
 	/* External PHY reset is shared with internal PHY Led signals */
 	snps,reset-gpio = <&gpio GPIOZ_14 0>;
 	snps,reset-delays-us = <0 10000 1000000>;
diff --git a/arch/arm64/boot/dts/amlogic/meson-gxm-nexbox-a1.dts b/arch/arm64/boot/dts/amlogic/meson-gxm-nexbox-a1.dts
index 5a337d339df1..a0bc746adb42 100644
--- a/arch/arm64/boot/dts/amlogic/meson-gxm-nexbox-a1.dts
+++ b/arch/arm64/boot/dts/amlogic/meson-gxm-nexbox-a1.dts
@@ -162,6 +162,8 @@
 	/* Select external PHY by default */
 	phy-handle = <&external_phy>;
 
+	amlogic,tx-delay-ns = <2>;
+
 	snps,reset-gpio = <&gpio GPIOZ_14 0>;
 	snps,reset-delays-us = <0 10000 1000000>;
 	snps,reset-active-low;
diff --git a/arch/arm64/boot/dts/amlogic/meson-gxm-q200.dts b/arch/arm64/boot/dts/amlogic/meson-gxm-q200.dts
index 5dbc66088355..e6ac39b712b7 100644
--- a/arch/arm64/boot/dts/amlogic/meson-gxm-q200.dts
+++ b/arch/arm64/boot/dts/amlogic/meson-gxm-q200.dts
@@ -59,6 +59,8 @@
 	/* Select external PHY by default */
 	phy-handle = <&external_phy>;
 
+	amlogic,tx-delay-ns = <2>;
+
 	/* External PHY reset is shared with internal PHY Led signals */
 	snps,reset-gpio = <&gpio GPIOZ_14 0>;
 	snps,reset-delays-us = <0 10000 1000000>;
-- 
2.11.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

* [PATCH v3 7/9] ARM64: dts: meson-gxbb-p201: fix ethernet support
From: Martin Blumenstingl @ 2017-01-20 15:22 UTC (permalink / raw)
  To: linux-amlogic-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	khilman-rdvid1DuHRBWk0Htik3J/w, carlo-KA+7E9HrN00dnm+yROfE0A
  Cc: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	devicetree-u79uwXL29TY76Z2rM5mHXA, will.deacon-5wv7dgnIgG8,
	catalin.marinas-5wv7dgnIgG8, mark.rutland-5wv7dgnIgG8,
	robh+dt-DgEjT+Ai2ygdnm+yROfE0A, narmstrong-rdvid1DuHRBWk0Htik3J/w,
	jbrunet-rdvid1DuHRBWk0Htik3J/w, Martin Blumenstingl
In-Reply-To: <20170120152232.13943-1-martin.blumenstingl-gM/Ye1E23mwN+BqQ9rBEUg@public.gmane.org>

Amlogic's own .dts specifies that the P201 board uses a RMII PHY (with
the reset GPIO being GPIOZ_14).
However our P201 board .dts simply inherits the phy-mode setting from
from meson-gx.dtsi where it defaults to RGMII mode.
Remove all ethernet settings from meson-gxbb-p20x.dtsi as it only
specifies the RGMII pins which are only valid for the P200 board.
Instead we add the ethmac node to the meson-gxbb-p201.dts and configure
the pinctrl property and the phy-mode for an RMII PHY.

An MDIO node (which would also specify the PHY) is not added since we
don't know which PHY is being used (and thus which PHY address would
have to be used).

Signed-off-by: Martin Blumenstingl <martin.blumenstingl-gM/Ye1E23mwN+BqQ9rBEUg@public.gmane.org>
Acked-by: Neil Armstrong <narmstrong-rdvid1DuHRBWk0Htik3J/w@public.gmane.org>
---
 arch/arm64/boot/dts/amlogic/meson-gxbb-p201.dts  | 11 +++++++++++
 arch/arm64/boot/dts/amlogic/meson-gxbb-p20x.dtsi |  6 ------
 2 files changed, 11 insertions(+), 6 deletions(-)

diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb-p201.dts b/arch/arm64/boot/dts/amlogic/meson-gxbb-p201.dts
index 39bb037a3e47..ae3194663d64 100644
--- a/arch/arm64/boot/dts/amlogic/meson-gxbb-p201.dts
+++ b/arch/arm64/boot/dts/amlogic/meson-gxbb-p201.dts
@@ -50,3 +50,14 @@
 	compatible = "amlogic,p201", "amlogic,meson-gxbb";
 	model = "Amlogic Meson GXBB P201 Development Board";
 };
+
+&ethmac {
+	status = "okay";
+	pinctrl-0 = <&eth_rmii_pins>;
+	pinctrl-names = "default";
+	phy-mode = "rmii";
+
+	snps,reset-gpio = <&gpio GPIOZ_14 0>;
+	snps,reset-delays-us = <0 10000 1000000>;
+	snps,reset-active-low;
+};
diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb-p20x.dtsi b/arch/arm64/boot/dts/amlogic/meson-gxbb-p20x.dtsi
index 4a96e0f6f926..17ebe46e48d4 100644
--- a/arch/arm64/boot/dts/amlogic/meson-gxbb-p20x.dtsi
+++ b/arch/arm64/boot/dts/amlogic/meson-gxbb-p20x.dtsi
@@ -144,12 +144,6 @@
 	pinctrl-names = "default";
 };
 
-&ethmac {
-	status = "okay";
-	pinctrl-0 = <&eth_rgmii_pins>;
-	pinctrl-names = "default";
-};
-
 &ir {
 	status = "okay";
 	pinctrl-0 = <&remote_input_ao_pins>;
-- 
2.11.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

* [PATCH v3 6/9] ARM64: dts: meson-gxbb-wetek-play2: add the ethernet PHY's reset GPIO
From: Martin Blumenstingl @ 2017-01-20 15:22 UTC (permalink / raw)
  To: linux-amlogic-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	khilman-rdvid1DuHRBWk0Htik3J/w, carlo-KA+7E9HrN00dnm+yROfE0A
  Cc: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	devicetree-u79uwXL29TY76Z2rM5mHXA, will.deacon-5wv7dgnIgG8,
	catalin.marinas-5wv7dgnIgG8, mark.rutland-5wv7dgnIgG8,
	robh+dt-DgEjT+Ai2ygdnm+yROfE0A, narmstrong-rdvid1DuHRBWk0Htik3J/w,
	jbrunet-rdvid1DuHRBWk0Htik3J/w, Martin Blumenstingl
In-Reply-To: <20170120152232.13943-1-martin.blumenstingl-gM/Ye1E23mwN+BqQ9rBEUg@public.gmane.org>

This resets the ethernet PHY during boot to get the PHY into a "clean"
state.
While here also specify the phy-handle of the ethmac node to make the
PHY configuration similar to the one we have on GXL devices. This will
allow us to specify OF-properties for the PHY itself.

Signed-off-by: Martin Blumenstingl <martin.blumenstingl-gM/Ye1E23mwN+BqQ9rBEUg@public.gmane.org>
---
 .../boot/dts/amlogic/meson-gxbb-wetek-play2.dts    | 24 ++++++++++++++++++++++
 1 file changed, 24 insertions(+)

diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb-wetek-play2.dts b/arch/arm64/boot/dts/amlogic/meson-gxbb-wetek-play2.dts
index ea79fdd2c248..9a8e2f492b97 100644
--- a/arch/arm64/boot/dts/amlogic/meson-gxbb-wetek-play2.dts
+++ b/arch/arm64/boot/dts/amlogic/meson-gxbb-wetek-play2.dts
@@ -87,6 +87,30 @@
 	};
 };
 
+&ethmac {
+	status = "okay";
+	pinctrl-0 = <&eth_rgmii_pins>;
+	pinctrl-names = "default";
+	phy-handle = <&eth_phy0>;
+	phy-mode = "rgmii";
+
+	snps,reset-gpio = <&gpio GPIOZ_14 0>;
+	snps,reset-delays-us = <0 10000 1000000>;
+	snps,reset-active-low;
+
+	mdio {
+		compatible = "snps,dwmac-mdio";
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		eth_phy0: ethernet-phy@0 {
+			compatible = "ethernet-phy-id001c.c916",
+				     "ethernet-phy-ieee802.3-c22";
+			reg = <0>;
+		};
+	};
+};
+
 &i2c_A {
 	status = "okay";
 	pinctrl-0 = <&i2c_a_pins>;
-- 
2.11.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

* [PATCH v3 5/9] ARM64: dts: meson-gxbb-wetek-hub: add the ethernet PHY's reset GPIO
From: Martin Blumenstingl @ 2017-01-20 15:22 UTC (permalink / raw)
  To: linux-amlogic-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	khilman-rdvid1DuHRBWk0Htik3J/w, carlo-KA+7E9HrN00dnm+yROfE0A
  Cc: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	devicetree-u79uwXL29TY76Z2rM5mHXA, will.deacon-5wv7dgnIgG8,
	catalin.marinas-5wv7dgnIgG8, mark.rutland-5wv7dgnIgG8,
	robh+dt-DgEjT+Ai2ygdnm+yROfE0A, narmstrong-rdvid1DuHRBWk0Htik3J/w,
	jbrunet-rdvid1DuHRBWk0Htik3J/w, Martin Blumenstingl
In-Reply-To: <20170120152232.13943-1-martin.blumenstingl-gM/Ye1E23mwN+BqQ9rBEUg@public.gmane.org>

This resets the ethernet PHY during boot to get the PHY into a "clean"
state.
While here also specify the phy-handle of the ethmac node to make the
PHY configuration similar to the one we have on GXL devices. This will
allow us to specify OF-properties for the PHY itself.

Signed-off-by: Martin Blumenstingl <martin.blumenstingl-gM/Ye1E23mwN+BqQ9rBEUg@public.gmane.org>
---
 .../boot/dts/amlogic/meson-gxbb-wetek-hub.dts      | 24 ++++++++++++++++++++++
 1 file changed, 24 insertions(+)

diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb-wetek-hub.dts b/arch/arm64/boot/dts/amlogic/meson-gxbb-wetek-hub.dts
index 56f855901262..47fe4e444f33 100644
--- a/arch/arm64/boot/dts/amlogic/meson-gxbb-wetek-hub.dts
+++ b/arch/arm64/boot/dts/amlogic/meson-gxbb-wetek-hub.dts
@@ -64,3 +64,27 @@
 		status = "disabled";
 	};
 };
+
+&ethmac {
+	status = "okay";
+	pinctrl-0 = <&eth_rgmii_pins>;
+	pinctrl-names = "default";
+	phy-handle = <&eth_phy0>;
+	phy-mode = "rgmii";
+
+	snps,reset-gpio = <&gpio GPIOZ_14 0>;
+	snps,reset-delays-us = <0 10000 1000000>;
+	snps,reset-active-low;
+
+	mdio {
+		compatible = "snps,dwmac-mdio";
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		eth_phy0: ethernet-phy@0 {
+			compatible = "ethernet-phy-id001c.c916",
+				     "ethernet-phy-ieee802.3-c22";
+			reg = <0>;
+		};
+	};
+};
-- 
2.11.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

* [PATCH v3 4/9] ARM64: dts: meson-gxbb-nexbox-a95x: add the ethernet PHY's reset GPIO
From: Martin Blumenstingl @ 2017-01-20 15:22 UTC (permalink / raw)
  To: linux-amlogic-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	khilman-rdvid1DuHRBWk0Htik3J/w, carlo-KA+7E9HrN00dnm+yROfE0A
  Cc: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	devicetree-u79uwXL29TY76Z2rM5mHXA, will.deacon-5wv7dgnIgG8,
	catalin.marinas-5wv7dgnIgG8, mark.rutland-5wv7dgnIgG8,
	robh+dt-DgEjT+Ai2ygdnm+yROfE0A, narmstrong-rdvid1DuHRBWk0Htik3J/w,
	jbrunet-rdvid1DuHRBWk0Htik3J/w, Martin Blumenstingl
In-Reply-To: <20170120152232.13943-1-martin.blumenstingl-gM/Ye1E23mwN+BqQ9rBEUg@public.gmane.org>

This resets the ethernet PHY during boot to get the PHY into a "clean"
state.
While here also specify the phy-handle of the ethmac node to make the
PHY configuration similar to the one we have on GXL devices. This will
allow us to specify OF-properties for the PHY itself.

Signed-off-by: Martin Blumenstingl <martin.blumenstingl-gM/Ye1E23mwN+BqQ9rBEUg@public.gmane.org>
---
 arch/arm64/boot/dts/amlogic/meson-gxbb-nexbox-a95x.dts | 17 +++++++++++++++++
 1 file changed, 17 insertions(+)

diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb-nexbox-a95x.dts b/arch/arm64/boot/dts/amlogic/meson-gxbb-nexbox-a95x.dts
index 4cbd626a9e88..c7e3ea008566 100644
--- a/arch/arm64/boot/dts/amlogic/meson-gxbb-nexbox-a95x.dts
+++ b/arch/arm64/boot/dts/amlogic/meson-gxbb-nexbox-a95x.dts
@@ -164,7 +164,24 @@
 	status = "okay";
 	pinctrl-0 = <&eth_rmii_pins>;
 	pinctrl-names = "default";
+	phy-handle = <&eth_phy0>;
 	phy-mode = "rmii";
+
+	snps,reset-gpio = <&gpio GPIOZ_14 0>;
+	snps,reset-delays-us = <0 10000 1000000>;
+	snps,reset-active-low;
+
+	mdio {
+		compatible = "snps,dwmac-mdio";
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		eth_phy0: ethernet-phy@0 {
+			compatible = "ethernet-phy-id0243.0c54",
+				     "ethernet-phy-ieee802.3-c22";
+			reg = <0>;
+		};
+	};
 };
 
 &ir {
-- 
2.11.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

* [PATCH v3 3/9] ARM64: dts: meson-gxbb-vega-s95: add the ethernet PHY's reset GPIO
From: Martin Blumenstingl @ 2017-01-20 15:22 UTC (permalink / raw)
  To: linux-amlogic-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	khilman-rdvid1DuHRBWk0Htik3J/w, carlo-KA+7E9HrN00dnm+yROfE0A
  Cc: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	devicetree-u79uwXL29TY76Z2rM5mHXA, will.deacon-5wv7dgnIgG8,
	catalin.marinas-5wv7dgnIgG8, mark.rutland-5wv7dgnIgG8,
	robh+dt-DgEjT+Ai2ygdnm+yROfE0A, narmstrong-rdvid1DuHRBWk0Htik3J/w,
	jbrunet-rdvid1DuHRBWk0Htik3J/w, Martin Blumenstingl
In-Reply-To: <20170120152232.13943-1-martin.blumenstingl-gM/Ye1E23mwN+BqQ9rBEUg@public.gmane.org>

This resets the ethernet PHY during boot to get the PHY into a "clean"
state.
While here also specify the phy-handle of the ethmac node to make the
PHY configuration similar to the one we have on GXL devices. This will
allow us to specify OF-properties for the PHY itself.

Signed-off-by: Martin Blumenstingl <martin.blumenstingl-gM/Ye1E23mwN+BqQ9rBEUg@public.gmane.org>
---
 arch/arm64/boot/dts/amlogic/meson-gxbb-vega-s95.dtsi | 18 ++++++++++++++++++
 1 file changed, 18 insertions(+)

diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb-vega-s95.dtsi b/arch/arm64/boot/dts/amlogic/meson-gxbb-vega-s95.dtsi
index 86709929fd20..358ab5159bd5 100644
--- a/arch/arm64/boot/dts/amlogic/meson-gxbb-vega-s95.dtsi
+++ b/arch/arm64/boot/dts/amlogic/meson-gxbb-vega-s95.dtsi
@@ -128,6 +128,24 @@
 	status = "okay";
 	pinctrl-0 = <&eth_rgmii_pins>;
 	pinctrl-names = "default";
+	phy-handle = <&eth_phy0>;
+	phy-mode = "rgmii";
+
+	snps,reset-gpio = <&gpio GPIOZ_14 0>;
+	snps,reset-delays-us = <0 10000 1000000>;
+	snps,reset-active-low;
+
+	mdio {
+		compatible = "snps,dwmac-mdio";
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		eth_phy0: ethernet-phy@0 {
+			compatible = "ethernet-phy-id001c.c916",
+				     "ethernet-phy-ieee802.3-c22";
+			reg = <0>;
+		};
+	};
 };
 
 &usb0_phy {
-- 
2.11.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

* [PATCH v3 2/9] ARM64: dts: meson-gxbb-p200: add the ethernet PHY's reset GPIO
From: Martin Blumenstingl @ 2017-01-20 15:22 UTC (permalink / raw)
  To: linux-amlogic-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	khilman-rdvid1DuHRBWk0Htik3J/w, carlo-KA+7E9HrN00dnm+yROfE0A
  Cc: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	devicetree-u79uwXL29TY76Z2rM5mHXA, will.deacon-5wv7dgnIgG8,
	catalin.marinas-5wv7dgnIgG8, mark.rutland-5wv7dgnIgG8,
	robh+dt-DgEjT+Ai2ygdnm+yROfE0A, narmstrong-rdvid1DuHRBWk0Htik3J/w,
	jbrunet-rdvid1DuHRBWk0Htik3J/w, Martin Blumenstingl
In-Reply-To: <20170120152232.13943-1-martin.blumenstingl-gM/Ye1E23mwN+BqQ9rBEUg@public.gmane.org>

This resets the ethernet PHY during boot to get the PHY into a "clean"
state.
While here also specify the phy-handle of the ethmac node to make the
PHY configuration similar to the one we have on GXL devices. This will
allow us to specify OF-properties for the PHY itself.

Signed-off-by: Martin Blumenstingl <martin.blumenstingl-gM/Ye1E23mwN+BqQ9rBEUg@public.gmane.org>
---
 arch/arm64/boot/dts/amlogic/meson-gxbb-p200.dts | 24 ++++++++++++++++++++++++
 1 file changed, 24 insertions(+)

diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb-p200.dts b/arch/arm64/boot/dts/amlogic/meson-gxbb-p200.dts
index 03e3d76626dd..fa0f84cfeaa9 100644
--- a/arch/arm64/boot/dts/amlogic/meson-gxbb-p200.dts
+++ b/arch/arm64/boot/dts/amlogic/meson-gxbb-p200.dts
@@ -51,6 +51,30 @@
 	model = "Amlogic Meson GXBB P200 Development Board";
 };
 
+&ethmac {
+	status = "okay";
+	pinctrl-0 = <&eth_rgmii_pins>;
+	pinctrl-names = "default";
+	phy-handle = <&eth_phy0>;
+	phy-mode = "rgmii";
+
+	snps,reset-gpio = <&gpio GPIOZ_14 0>;
+	snps,reset-delays-us = <0 10000 1000000>;
+	snps,reset-active-low;
+
+	mdio {
+		compatible = "snps,dwmac-mdio";
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		eth_phy0: ethernet-phy@0 {
+			compatible = "ethernet-phy-id0022.1620",
+				     "ethernet-phy-ieee802.3-c22";
+			reg = <3>;
+		};
+	};
+};
+
 &i2c_B {
 	status = "okay";
 	pinctrl-0 = <&i2c_b_pins>;
-- 
2.11.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

* [PATCH v3 1/9] ARM64: dts: meson-gxbb-odroidc2: add the ethernet PHY's reset GPIO
From: Martin Blumenstingl @ 2017-01-20 15:22 UTC (permalink / raw)
  To: linux-amlogic-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	khilman-rdvid1DuHRBWk0Htik3J/w, carlo-KA+7E9HrN00dnm+yROfE0A
  Cc: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	devicetree-u79uwXL29TY76Z2rM5mHXA, will.deacon-5wv7dgnIgG8,
	catalin.marinas-5wv7dgnIgG8, mark.rutland-5wv7dgnIgG8,
	robh+dt-DgEjT+Ai2ygdnm+yROfE0A, narmstrong-rdvid1DuHRBWk0Htik3J/w,
	jbrunet-rdvid1DuHRBWk0Htik3J/w, Martin Blumenstingl
In-Reply-To: <20170120152232.13943-1-martin.blumenstingl-gM/Ye1E23mwN+BqQ9rBEUg@public.gmane.org>

This resets the ethernet PHY during boot to get the PHY into a "clean"
state. While here also explicitly specify the phy-mode instead of
relying on the default-value from meson-gx.dtsi.

Signed-off-by: Martin Blumenstingl <martin.blumenstingl-gM/Ye1E23mwN+BqQ9rBEUg@public.gmane.org>
---
 arch/arm64/boot/dts/amlogic/meson-gxbb-odroidc2.dts | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb-odroidc2.dts b/arch/arm64/boot/dts/amlogic/meson-gxbb-odroidc2.dts
index c59403adb387..6b5579522587 100644
--- a/arch/arm64/boot/dts/amlogic/meson-gxbb-odroidc2.dts
+++ b/arch/arm64/boot/dts/amlogic/meson-gxbb-odroidc2.dts
@@ -152,6 +152,11 @@
 	pinctrl-0 = <&eth_rgmii_pins>;
 	pinctrl-names = "default";
 	phy-handle = <&eth_phy0>;
+	phy-mode = "rgmii";
+
+	snps,reset-gpio = <&gpio GPIOZ_14 0>;
+	snps,reset-delays-us = <0 10000 1000000>;
+	snps,reset-active-low;
 
 	mdio {
 		compatible = "snps,dwmac-mdio";
-- 
2.11.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

* [PATCH v3 0/9] meson-gx: reset RGMII PHYs and configure TX delay
From: Martin Blumenstingl @ 2017-01-20 15:22 UTC (permalink / raw)
  To: linux-amlogic, khilman, carlo
  Cc: mark.rutland, devicetree, narmstrong, Martin Blumenstingl,
	catalin.marinas, will.deacon, robh+dt, linux-arm-kernel, jbrunet
In-Reply-To: <20170120132650.9784-1-martin.blumenstingl@googlemail.com>

This series adds the reset GPIOs for the (external) ethernet PHYs on all
GXBB boards.
Additionally it provides a ethernet PHY node which can be used to specify
PHY-specific properties (this may be required if more boards require the
"eee-broken-1000t" for the RTL8211F ethernet PHY). To make all board .dts
consistent I chose to add the PHY node also for boards which don't have a
RTL8211F PHY.

Patch #7 from this series also removes ethernet support for the P200
board because it was broken anyways and nobody seems to have a board
available for testing. This was the outcome of the discussion from [0]

Patch #8 was taken from (older versions of) my other series (see [1]):
"[PATCH net-next v3 0/2] stmmac: dwmac-meson8b: configurable
RGMII TX delay".
The binding changes for amlogic,tx-delay-ns were ACK'ed already.

Changes since v2:
- fixed patch #2 to really update the P200 board (as it's the P200 which
  actually uses a Micrel KSZ9031 RGMII PHY). Thanks to Neil Armstrong for
  spotting this huge mistake!
- instead of dropping ethernet support for P201 we simply re-configure it
  to RMII mode (replaces patch #7) without a MDIO node (which keeps PHY
  auto-scanning enabled). This got Neil Armstrong's ACK off-list already

Changes since v1:
- do not move the MDIO bus to meson-gx as this disables PHY auto-scanning
  in the stmmac driver (this drops patch #1 from v1)
- add the ethernet PHY reset GPIO for nexbox a95x which was forgotten in
  v1
- add the ethernet PHY reset GPIO for boards which were added since v1
  (wetek hub and wetek play2)
- rebased to apply against the current v4.11/dt64 branch
- new in v2 (patch #7): disabled ethernet support for the P200 board (see
  the commit description for more information). this patch is optional
- new in v2 (patch #9): removed the phy-mode property from meson-gx (see
  the commit description for more information). this patch is optional


[0] http://lists.infradead.org/pipermail/linux-amlogic/2017-January/002053.html
[1] http://lists.infradead.org/pipermail/linux-amlogic/2016-December/001834.html

Martin Blumenstingl (9):
  ARM64: dts: meson-gxbb-odroidc2: add the ethernet PHY's reset GPIO
  ARM64: dts: meson-gxbb-p200: add the ethernet PHY's reset GPIO
  ARM64: dts: meson-gxbb-vega-s95: add the ethernet PHY's reset GPIO
  ARM64: dts: meson-gxbb-nexbox-a95x: add the ethernet PHY's reset GPIO
  ARM64: dts: meson-gxbb-wetek-hub: add the ethernet PHY's reset GPIO
  ARM64: dts: meson-gxbb-wetek-play2: add the ethernet PHY's reset GPIO
  ARM64: dts: meson-gxbb-p201: fix ethernet support
  ARM64: dts: amlogic: add the ethernet TX delay configuration
  ARM64: dts: meson-gx: remove the phy-mode property from meson-gx

 arch/arm64/boot/dts/amlogic/meson-gx.dtsi          |  1 -
 .../boot/dts/amlogic/meson-gxbb-nexbox-a95x.dts    | 17 ++++++++++++++
 .../arm64/boot/dts/amlogic/meson-gxbb-odroidc2.dts |  7 ++++++
 arch/arm64/boot/dts/amlogic/meson-gxbb-p200.dts    | 26 ++++++++++++++++++++++
 arch/arm64/boot/dts/amlogic/meson-gxbb-p201.dts    | 11 +++++++++
 arch/arm64/boot/dts/amlogic/meson-gxbb-p20x.dtsi   |  6 -----
 .../boot/dts/amlogic/meson-gxbb-vega-s95.dtsi      | 20 +++++++++++++++++
 .../boot/dts/amlogic/meson-gxbb-wetek-hub.dts      | 26 ++++++++++++++++++++++
 .../boot/dts/amlogic/meson-gxbb-wetek-play2.dts    | 26 ++++++++++++++++++++++
 .../boot/dts/amlogic/meson-gxl-s905d-p230.dts      |  2 ++
 .../arm64/boot/dts/amlogic/meson-gxm-nexbox-a1.dts |  2 ++
 arch/arm64/boot/dts/amlogic/meson-gxm-q200.dts     |  2 ++
 12 files changed, 139 insertions(+), 7 deletions(-)

-- 
2.11.0

^ permalink raw reply

* Re: [PATCH v9 0/4] arm64: arch_timer: Add workaround for hisilicon-161010101 erratum
From: Mark Rutland @ 2017-01-20 15:04 UTC (permalink / raw)
  To: Ding Tianhong, catalin.marinas-5wv7dgnIgG8,
	will.deacon-5wv7dgnIgG8, Daniel Lezcano, Thomas Gleixner
  Cc: marc.zyngier-5wv7dgnIgG8, oss-fOR+EgIDQEHk1uMJSBkQmQ,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	shawnguo-DgEjT+Ai2ygdnm+yROfE0A, stuart.yoder-3arQi8VN3Tc,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linuxarm-hv44wF8Li93QT0dZR+AlfA
In-Reply-To: <1484832916-7248-1-git-send-email-dingtianhong-hv44wF8Li93QT0dZR+AlfA@public.gmane.org>

On Thu, Jan 19, 2017 at 09:35:12PM +0800, Ding Tianhong wrote:
> Ding Tianhong (4):
>   arm64: arch_timer: Add device tree binding for hisilicon-161010101
>     erratum
>   arm64: arch_timer: Introduce a generic erratum handing mechanism for
>     fsl-a008585
>   arm64: arch_timer: Work around Erratum Hisilicon-161010101
>   arm64: arch timer: Add timer erratum property for Hip05-d02 and
>     Hip06-d03
> 
>  Documentation/admin-guide/kernel-parameters.txt    |   9 --
>  Documentation/arm64/silicon-errata.txt             |  43 +++---
>  .../devicetree/bindings/arm/arch_timer.txt         |   6 +
>  arch/arm64/boot/dts/hisilicon/hip05.dtsi           |   1 +
>  arch/arm64/boot/dts/hisilicon/hip06.dtsi           |   1 +
>  arch/arm64/include/asm/arch_timer.h                |  38 ++----
>  drivers/clocksource/Kconfig                        |  18 +++
>  drivers/clocksource/arm_arch_timer.c               | 150 +++++++++++++++------
>  8 files changed, 171 insertions(+), 95 deletions(-)

I've picked these up (with a few local cleanups), given that some local
testing, and pushed the result to a branch [1] on my git repo.

There are likely to be clashes with the arm64 tree (e.g. for
silicon-errata.txt), and we're also likely to have more arch timer
updates shortly for the GTDT stuff, so I think the best bet is for both
arm64 and the clocksource tree to pull that branch for v4.11.

Alternatively, we could take this all through the arm64 tree, if the
clocksource maintainers are happy with that.

Thoughts?

Thanks,
Mark.

[1] git://git.kernel.org/pub/scm/linux/kernel/git/mark/linux.git arch-timer/hisi-161010101
--
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 v5 00/14] ARM: da850-lcdk: add SATA support
From: Tejun Heo @ 2017-01-20 15:00 UTC (permalink / raw)
  To: Sekhar Nori
  Cc: Bartosz Golaszewski, Kevin Hilman, Patrick Titiano,
	Michael Turquette, Rob Herring, Mark Rutland, Russell King,
	David Lechner, linux-ide-u79uwXL29TY76Z2rM5mHXA, linux-devicetree,
	LKML, arm-soc, Olof Johansson, Arnd Bergmann
In-Reply-To: <f9055043-507f-74de-b2b8-9eb0eae5dad6-l0cyMroinI0@public.gmane.org>

Hello, Sekhar.

On Fri, Jan 20, 2017 at 07:52:35PM +0530, Sekhar Nori wrote:
> Tejun, I am open to queuing the driver changes through ARM-SoC. I guess
> with that there is little chance that SATA will be broken on linux-next
> for a longish period of time.

Yeah, I'd prefer the patchset staying together.  That's how it was
developed and tested.  Don't wanna break it apart unnecessarily.  The
chance for conflicts is low and even when that happens dealing with
them is pretty easy.  Please feel free to add my acked-by and route
the patches through ARM-SoC.

Thanks.

-- 
tejun
--
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: [V2 1/2] document: dt: add binding for Hi3660 SoC
From: Wei Xu @ 2017-01-20 14:56 UTC (permalink / raw)
  To: Chen Feng, robh+dt, mark.rutland, catalin.marinas, will.deacon,
	linux-arm-kernel, devicetree, linux-kernel
  Cc: dan.zhao, xuyiping, puck.chen, suzhuangluan, saberlily.xia,
	qijiwen
In-Reply-To: <1484034915-48879-1-git-send-email-puck.chen@hisilicon.com>

Hi Chen Feng,

On 2017/1/10 7:55, Chen Feng wrote:
> Add binding for hisilicon Hi3660 SoC and HiKey960 Board.
> 
> Signed-off-by: Chen Feng <puck.chen@hisilicon.com>
> Acked-by: Rob Herring <robh@kernel.org>
> ---

Applied both to the hisilicon SoC tree
with minimal changes about the format.
Thanks!

Best Regards,
Wei

>  Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt | 4 ++++
>  1 file changed, 4 insertions(+)
> 
> diff --git a/Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt b/Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt
> index 7df79a7..6de2398 100644
> --- a/Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt
> +++ b/Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt
> @@ -8,6 +8,10 @@ Hi6220 SoC
>  Required root node properties:
>  	- compatible = "hisilicon,hi6220";
>  
> +Hi3660 SoC
> +Required root node properties:
> +	- compatible = "hisilicon,hi3660";
> +
>  HiKey Board
>  Required root node properties:
>  	- compatible = "hisilicon,hi6220-hikey", "hisilicon,hi6220";
> 

^ permalink raw reply

* Re: [PATCH v4 0/7] Add support for Video Data Order Adapter
From: Hans Verkuil @ 2017-01-20 14:54 UTC (permalink / raw)
  To: Michael Tretter, linux-media
  Cc: Philipp Zabel, devicetree, Hans Verkuil, Mauro Carvalho Chehab,
	kernel
In-Reply-To: <20170120140025.3338-1-m.tretter@pengutronix.de>

Looks good to me.

Philipp, just let me know if this is ready for merging, or you can make a pull
request for Mauro yourself if you prefer.

Regards,

	Hans

On 01/20/2017 03:00 PM, Michael Tretter wrote:
> Hello,
> 
> This is v4 of a patch series that adds support for the Video Data Order
> Adapter (VDOA) that can be found on Freescale i.MX6. It converts the
> macroblock tiled format produced by the CODA 960 video decoder to a
> raster-ordered format for scanout.
> 
> Changes since v3:
> 
> - Patch 2/7: Add my copyright to vdoa copyright header
> - Patch 2/7: Fix offset of chroma plane to be page-aligned
> - Patch 6/7: Fix oops when releasing the coda driver by destroying vdoa
>   context after removing all buffers
> - Patch 6/7: Fix missing vdoa disable when switching from tiled to linear
>   format
> 
> Changes since v2:
> 
> - Patch 1/7: Update commit message to include binding change; fix
>   spelling/style in binding documentation
> 
> Changes since v1:
> 
> - Dropped patch 8/9 of v1
> - Patch 1/7: Add devicetree binding documentation for fsl-vdoa
> - Patch 6/7: I merged patch 5/9 and patch 8/9 of v1 into a single patch
> - Patch 6/7: Use dt compatible instead of a phandle to find VDOA device
> - Patch 6/7: Always check VDOA availability even if disabled via module
>   parameter and do not print a message if VDOA cannot be found
> - Patch 6/7: Do not change the CODA context in coda_try_fmt()
> - Patch 6/7: Allocate an additional internal frame if the VDOA is in use
> 
> Michael Tretter (3):
>   [media] coda: fix frame index to returned error
>   [media] coda: use VDOA for un-tiling custom macroblock format
>   [media] coda: support YUYV output if VDOA is used
> 
> Philipp Zabel (4):
>   [media] dt-bindings: Add a binding for Video Data Order Adapter
>   [media] coda: add i.MX6 VDOA driver
>   [media] coda: correctly set capture compose rectangle
>   [media] coda: add debug output about tiling
> 
>  .../devicetree/bindings/media/fsl-vdoa.txt         |  21 ++
>  arch/arm/boot/dts/imx6qdl.dtsi                     |   2 +
>  drivers/media/platform/Kconfig                     |   3 +
>  drivers/media/platform/coda/Makefile               |   1 +
>  drivers/media/platform/coda/coda-bit.c             |  93 ++++--
>  drivers/media/platform/coda/coda-common.c          | 175 ++++++++++-
>  drivers/media/platform/coda/coda.h                 |   3 +
>  drivers/media/platform/coda/imx-vdoa.c             | 338 +++++++++++++++++++++
>  drivers/media/platform/coda/imx-vdoa.h             |  58 ++++
>  9 files changed, 652 insertions(+), 42 deletions(-)
>  create mode 100644 Documentation/devicetree/bindings/media/fsl-vdoa.txt
>  create mode 100644 drivers/media/platform/coda/imx-vdoa.c
>  create mode 100644 drivers/media/platform/coda/imx-vdoa.h
> 

^ permalink raw reply

* Re: [PATCH v3 0/4] Add support for es8388 on the rock2
From: Romain Perier @ 2017-01-20 14:54 UTC (permalink / raw)
  To: Jaroslav Kysela, Takashi Iwai, alsa-devel-K7yf7f+aM1XWsZ/bQMPhNw,
	Heiko Stuebner
  Cc: Mark Rutland, devicetree-u79uwXL29TY76Z2rM5mHXA, Pawel Moll,
	Ian Campbell, linux-rockchip-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	Sjoerd Simons, Rob Herring, Kumar Gala
In-Reply-To: <20170117081705.14107-1-romain.perier-ZGY8ohtN/8qB+jHODAdFcQ@public.gmane.org>

Hello,

Le 17/01/2017 à 09:17, Romain Perier a écrit :
> This set of patches adds a machine driver for rockchip boards that use
> ES8388 codecs. It also adds slave mode to the es8328 driver that
> currently only supported the master mode. Then, it adds the required DT
> definitions to link rockchip-i2s to the es8388 analog output.
>
> This work is based on the initial work that was done by Sjoerd Simons
> <sjoerd.simons-ZGY8ohtN/8pPYcu2f3hruQ@public.gmane.org> with some improvements, changes and more
> commits.
>
> Changes in v3:
>  - Cosmetic changes in rockchip_es8388.c
>  - Added missing email to MODULE_AUTHOR in rockchip_es8388.c
> Changes in v2:
>  - Fixed wrong use of the data structure i2c_device_id
>  - Fixed wrong dependencies for SND_SOC_ROCKCHIP_ES8388
>
> Romain Perier (4):
>   ASoC: es8328-i2c: Add compatible for ES8388
>   ASoC: es8328: Add support for slave mode
>   ASoC: rockchip: Add machine driver for ES8388 codecs
>   arm: dts: Add support for ES8388 to the Radxa Rock 2
>
>  Documentation/devicetree/bindings/sound/es8328.txt |   2 +-
>  .../devicetree/bindings/sound/rockchip-es8388.txt  |  28 +++
>  arch/arm/boot/dts/rk3288-rock2-square.dts          |  37 +++
>  sound/soc/codecs/es8328-i2c.c                      |   2 +
>  sound/soc/codecs/es8328.c                          |  28 ++-
>  sound/soc/rockchip/Kconfig                         |   9 +
>  sound/soc/rockchip/Makefile                        |   2 +
>  sound/soc/rockchip/rockchip_es8388.c               | 269 +++++++++++++++++++++
>  8 files changed, 370 insertions(+), 7 deletions(-)
>  create mode 100644 Documentation/devicetree/bindings/sound/rockchip-es8388.txt
>  create mode 100644 sound/soc/rockchip/rockchip_es8388.c

Please ignore this v3, I will re-submit it with some improvements.

Regards,

Romain

^ permalink raw reply

* Re: [PATCH v3 22/24] media: imx: Add MIPI CSI-2 OV5640 sensor subdev driver
From: Hans Verkuil @ 2017-01-20 14:48 UTC (permalink / raw)
  To: Steve Longerbeam, robh+dt, mark.rutland, shawnguo, kernel,
	fabio.estevam, linux, mchehab, nick, markus.heiser, p.zabel,
	laurent.pinchart+renesas, bparrot, geert, arnd, sudipm.mukherjee,
	minghsiu.tsai, tiffany.lin, jean-christophe.trotin, horms+renesas,
	niklas.soderlund+renesas, robert.jarzmik, songjun.wu,
	andrew-ct.chen, gregkh
  Cc: devicetree, linux-kernel, linux-arm-kernel, linux-media, devel,
	Steve Longerbeam
In-Reply-To: <1483755102-24785-23-git-send-email-steve_longerbeam@mentor.com>

On 01/07/2017 03:11 AM, Steve Longerbeam wrote:
> This driver is based on ov5640_mipi.c from Freescale imx_3.10.17_1.0.0_beta
> branch, modified heavily to bring forward to latest interfaces and code
> cleanup.
> 
> Signed-off-by: Steve Longerbeam <steve_longerbeam@mentor.com>
> ---
>  drivers/staging/media/imx/Kconfig       |    8 +
>  drivers/staging/media/imx/Makefile      |    2 +
>  drivers/staging/media/imx/ov5640-mipi.c | 2348 +++++++++++++++++++++++++++++++
>  3 files changed, 2358 insertions(+)
>  create mode 100644 drivers/staging/media/imx/ov5640-mipi.c
> 
> diff --git a/drivers/staging/media/imx/Kconfig b/drivers/staging/media/imx/Kconfig
> index ce2d2c8..09f373d 100644
> --- a/drivers/staging/media/imx/Kconfig
> +++ b/drivers/staging/media/imx/Kconfig
> @@ -17,5 +17,13 @@ config VIDEO_IMX_CAMERA
>  	---help---
>  	  A video4linux camera capture driver for i.MX5/6.
>  
> +config IMX_OV5640_MIPI
> +       tristate "OmniVision OV5640 MIPI CSI-2 camera support"
> +       depends on GPIOLIB && VIDEO_IMX_CAMERA
> +       select IMX_MIPI_CSI2
> +       default y
> +       ---help---
> +         MIPI CSI-2 OV5640 Camera support.
> +
>  endmenu
>  endif
> diff --git a/drivers/staging/media/imx/Makefile b/drivers/staging/media/imx/Makefile
> index 0decef7..aa954c1 100644
> --- a/drivers/staging/media/imx/Makefile
> +++ b/drivers/staging/media/imx/Makefile
> @@ -10,3 +10,5 @@ obj-$(CONFIG_VIDEO_IMX_CAMERA) += imx-csi.o
>  obj-$(CONFIG_VIDEO_IMX_CAMERA) += imx-smfc.o
>  obj-$(CONFIG_VIDEO_IMX_CAMERA) += imx-camif.o
>  obj-$(CONFIG_VIDEO_IMX_CAMERA) += imx-mipi-csi2.o
> +
> +obj-$(CONFIG_IMX_OV5640_MIPI) += ov5640-mipi.o
> diff --git a/drivers/staging/media/imx/ov5640-mipi.c b/drivers/staging/media/imx/ov5640-mipi.c
> new file mode 100644
> index 0000000..54647a7
> --- /dev/null
> +++ b/drivers/staging/media/imx/ov5640-mipi.c
> @@ -0,0 +1,2348 @@
> +/*
> + * Copyright (c) 2014 Mentor Graphics Inc.
> + * Copyright (C) 2011-2013 Freescale Semiconductor, Inc. All Rights Reserved.
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + */
> +
> +#include <linux/module.h>
> +#include <linux/init.h>
> +#include <linux/slab.h>
> +#include <linux/ctype.h>
> +#include <linux/types.h>
> +#include <linux/delay.h>
> +#include <linux/device.h>
> +#include <linux/i2c.h>
> +#include <linux/of_device.h>
> +#include <linux/gpio/consumer.h>
> +#include <linux/regulator/consumer.h>
> +#include <linux/clk.h>
> +#include <linux/clk-provider.h>
> +#include <linux/clkdev.h>
> +#include <media/v4l2-device.h>
> +#include <media/v4l2-subdev.h>
> +#include <media/v4l2-async.h>
> +#include <media/v4l2-of.h>
> +#include <media/v4l2-ctrls.h>
> +
> +#define OV5640_VOLTAGE_ANALOG               2800000
> +#define OV5640_VOLTAGE_DIGITAL_CORE         1500000
> +#define OV5640_VOLTAGE_DIGITAL_IO           1800000
> +
> +#define MIN_FPS 15
> +#define MAX_FPS 30
> +#define DEFAULT_FPS 30
> +
> +/* min/typical/max system clock (xclk) frequencies */
> +#define OV5640_XCLK_MIN  6000000
> +#define OV5640_XCLK_TYP 24000000
> +#define OV5640_XCLK_MAX 54000000
> +
> +/* min/typical/max pixel clock (mclk) frequencies */
> +#define OV5640_MCLK_MIN 48000000
> +#define OV5640_MCLK_TYP 48000000
> +#define OV5640_MCLK_MAX 96000000
> +
> +#define OV5640_CHIP_ID  0x300A
> +#define OV5640_SLAVE_ID 0x3100
> +#define OV5640_DEFAULT_SLAVE_ID 0x3c
> +
> +#define OV5640_MAX_CONTROLS 64
> +
> +enum ov5640_mode {
> +	ov5640_mode_MIN = 0,
> +	ov5640_mode_QCIF_176_144 = 0,
> +	ov5640_mode_QVGA_320_240,
> +	ov5640_mode_VGA_640_480,
> +	ov5640_mode_NTSC_720_480,
> +	ov5640_mode_PAL_720_576,
> +	ov5640_mode_XGA_1024_768,
> +	ov5640_mode_720P_1280_720,
> +	ov5640_mode_1080P_1920_1080,
> +	ov5640_mode_QSXGA_2592_1944,
> +	ov5640_num_modes,
> +	ov5640_mode_INIT = 0xff, /*only for sensor init*/
> +};
> +
> +enum ov5640_frame_rate {
> +	ov5640_15_fps,
> +	ov5640_30_fps
> +};
> +
> +static int ov5640_framerates[] = {
> +	[ov5640_15_fps] = 15,
> +	[ov5640_30_fps] = 30,
> +};
> +#define ov5640_num_framerates ARRAY_SIZE(ov5640_framerates)
> +
> +/* image size under 1280 * 960 are SUBSAMPLING
> + * image size upper 1280 * 960 are SCALING
> + */
> +enum ov5640_downsize_mode {
> +	SUBSAMPLING,
> +	SCALING,
> +};
> +
> +struct reg_value {
> +	u16 reg_addr;
> +	u8 val;
> +	u8 mask;
> +	u32 delay_ms;
> +};
> +
> +struct ov5640_mode_info {
> +	enum ov5640_mode mode;
> +	enum ov5640_downsize_mode dn_mode;
> +	u32 width;
> +	u32 height;
> +	struct reg_value *init_data_ptr;
> +	u32 init_data_size;
> +};
> +
> +struct ov5640_dev {
> +	struct i2c_client *i2c_client;
> +	struct device *dev;
> +	struct v4l2_subdev sd;
> +	struct media_pad pad;
> +	struct v4l2_ctrl_handler ctrl_hdl;
> +	struct v4l2_of_endpoint ep; /* the parsed DT endpoint info */
> +	struct v4l2_mbus_framefmt fmt;
> +	struct v4l2_captureparm streamcap;
> +	struct clk *xclk; /* system clock to OV5640 */
> +	int xclk_freq;    /* requested xclk freq from devicetree */
> +
> +	enum ov5640_mode current_mode;
> +	enum ov5640_frame_rate current_fr;
> +
> +	bool on;
> +	bool awb_on;
> +	bool agc_on;
> +
> +	/* cached control settings */
> +	int ctrl_cache[OV5640_MAX_CONTROLS];

This is just duplicating the cached value in the control framework. I think this can be dropped.

> +
> +	struct gpio_desc *reset_gpio;
> +	struct gpio_desc *pwdn_gpio;
> +	struct gpio_desc *gp_gpio;
> +
> +	int prev_sysclk, prev_hts;
> +	int ae_low, ae_high, ae_target;
> +
> +	struct regulator *io_regulator;
> +	struct regulator *core_regulator;
> +	struct regulator *analog_regulator;
> +	struct regulator *gpo_regulator;
> +};
> +
> +static inline struct ov5640_dev *to_ov5640_dev(struct v4l2_subdev *sd)
> +{
> +	return container_of(sd, struct ov5640_dev, sd);
> +}
> +
> +static inline struct ov5640_dev *ctrl_to_ov5640_dev(struct v4l2_ctrl *ctrl)
> +{
> +	return container_of(ctrl->handler, struct ov5640_dev, ctrl_hdl);
> +}
> +
> +struct ov5640_control {
> +	struct v4l2_queryctrl ctrl;
> +	int (*set)(struct ov5640_dev *sensor, int value);
> +};
> +
> +static void ov5640_power(struct ov5640_dev *sensor, bool enable);
> +static void ov5640_reset(struct ov5640_dev *sensor);
> +static int ov5640_restore_ctrls(struct ov5640_dev *sensor);
> +static int ov5640_set_agc(struct ov5640_dev *sensor, int value);
> +static int ov5640_set_exposure(struct ov5640_dev *sensor, int value);
> +static int ov5640_get_exposure(struct ov5640_dev *sensor);
> +static int ov5640_set_gain(struct ov5640_dev *sensor, int value);
> +static int ov5640_get_gain(struct ov5640_dev *sensor);
> +
> +static struct reg_value ov5640_init_setting_30fps_VGA[] = {
> +
> +	{0x3103, 0x11, 0, 0}, {0x3008, 0x82, 0, 5}, {0x3008, 0x42, 0, 0},
> +	{0x3103, 0x03, 0, 0}, {0x3017, 0x00, 0, 0}, {0x3018, 0x00, 0, 0},
> +	{0x3034, 0x18, 0, 0}, {0x3035, 0x14, 0, 0}, {0x3036, 0x38, 0, 0},
> +	{0x3037, 0x13, 0, 0}, {0x3108, 0x01, 0, 0}, {0x3630, 0x36, 0, 0},
> +	{0x3631, 0x0e, 0, 0}, {0x3632, 0xe2, 0, 0}, {0x3633, 0x12, 0, 0},
> +	{0x3621, 0xe0, 0, 0}, {0x3704, 0xa0, 0, 0}, {0x3703, 0x5a, 0, 0},
> +	{0x3715, 0x78, 0, 0}, {0x3717, 0x01, 0, 0}, {0x370b, 0x60, 0, 0},
> +	{0x3705, 0x1a, 0, 0}, {0x3905, 0x02, 0, 0}, {0x3906, 0x10, 0, 0},
> +	{0x3901, 0x0a, 0, 0}, {0x3731, 0x12, 0, 0}, {0x3600, 0x08, 0, 0},
> +	{0x3601, 0x33, 0, 0}, {0x302d, 0x60, 0, 0}, {0x3620, 0x52, 0, 0},
> +	{0x371b, 0x20, 0, 0}, {0x471c, 0x50, 0, 0}, {0x3a13, 0x43, 0, 0},
> +	{0x3a18, 0x00, 0, 0}, {0x3a19, 0xf8, 0, 0}, {0x3635, 0x13, 0, 0},
> +	{0x3636, 0x03, 0, 0}, {0x3634, 0x40, 0, 0}, {0x3622, 0x01, 0, 0},
> +	{0x3c01, 0xa4, 0, 0}, {0x3c04, 0x28, 0, 0}, {0x3c05, 0x98, 0, 0},
> +	{0x3c06, 0x00, 0, 0}, {0x3c07, 0x08, 0, 0}, {0x3c08, 0x00, 0, 0},
> +	{0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0}, {0x3c0b, 0x40, 0, 0},
> +	{0x3820, 0x41, 0, 0}, {0x3821, 0x07, 0, 0}, {0x3814, 0x31, 0, 0},
> +	{0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0},
> +	{0x3802, 0x00, 0, 0}, {0x3803, 0x04, 0, 0}, {0x3804, 0x0a, 0, 0},
> +	{0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0}, {0x3807, 0x9b, 0, 0},
> +	{0x3808, 0x02, 0, 0}, {0x3809, 0x80, 0, 0}, {0x380a, 0x01, 0, 0},
> +	{0x380b, 0xe0, 0, 0}, {0x380c, 0x07, 0, 0}, {0x380d, 0x68, 0, 0},
> +	{0x380e, 0x03, 0, 0}, {0x380f, 0xd8, 0, 0}, {0x3810, 0x00, 0, 0},
> +	{0x3811, 0x10, 0, 0}, {0x3812, 0x00, 0, 0}, {0x3813, 0x06, 0, 0},
> +	{0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0}, {0x3708, 0x64, 0, 0},
> +	{0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x03, 0, 0},
> +	{0x3a03, 0xd8, 0, 0}, {0x3a08, 0x01, 0, 0}, {0x3a09, 0x27, 0, 0},
> +	{0x3a0a, 0x00, 0, 0}, {0x3a0b, 0xf6, 0, 0}, {0x3a0e, 0x03, 0, 0},
> +	{0x3a0d, 0x04, 0, 0}, {0x3a14, 0x03, 0, 0}, {0x3a15, 0xd8, 0, 0},
> +	{0x4001, 0x02, 0, 0}, {0x4004, 0x02, 0, 0}, {0x3000, 0x00, 0, 0},
> +	{0x3002, 0x1c, 0, 0}, {0x3004, 0xff, 0, 0}, {0x3006, 0xc3, 0, 0},
> +	{0x300e, 0x45, 0, 0}, {0x302e, 0x08, 0, 0}, {0x4300, 0x3f, 0, 0},
> +	{0x501f, 0x00, 0, 0}, {0x4713, 0x03, 0, 0}, {0x4407, 0x04, 0, 0},
> +	{0x440e, 0x00, 0, 0}, {0x460b, 0x35, 0, 0}, {0x460c, 0x22, 0, 0},
> +	{0x4837, 0x0a, 0, 0}, {0x4800, 0x04, 0, 0}, {0x3824, 0x02, 0, 0},
> +	{0x5000, 0xa7, 0, 0}, {0x5001, 0xa3, 0, 0}, {0x5180, 0xff, 0, 0},
> +	{0x5181, 0xf2, 0, 0}, {0x5182, 0x00, 0, 0}, {0x5183, 0x14, 0, 0},
> +	{0x5184, 0x25, 0, 0}, {0x5185, 0x24, 0, 0}, {0x5186, 0x09, 0, 0},
> +	{0x5187, 0x09, 0, 0}, {0x5188, 0x09, 0, 0}, {0x5189, 0x88, 0, 0},
> +	{0x518a, 0x54, 0, 0}, {0x518b, 0xee, 0, 0}, {0x518c, 0xb2, 0, 0},
> +	{0x518d, 0x50, 0, 0}, {0x518e, 0x34, 0, 0}, {0x518f, 0x6b, 0, 0},
> +	{0x5190, 0x46, 0, 0}, {0x5191, 0xf8, 0, 0}, {0x5192, 0x04, 0, 0},
> +	{0x5193, 0x70, 0, 0}, {0x5194, 0xf0, 0, 0}, {0x5195, 0xf0, 0, 0},
> +	{0x5196, 0x03, 0, 0}, {0x5197, 0x01, 0, 0}, {0x5198, 0x04, 0, 0},
> +	{0x5199, 0x6c, 0, 0}, {0x519a, 0x04, 0, 0}, {0x519b, 0x00, 0, 0},
> +	{0x519c, 0x09, 0, 0}, {0x519d, 0x2b, 0, 0}, {0x519e, 0x38, 0, 0},
> +	{0x5381, 0x1e, 0, 0}, {0x5382, 0x5b, 0, 0}, {0x5383, 0x08, 0, 0},
> +	{0x5384, 0x0a, 0, 0}, {0x5385, 0x7e, 0, 0}, {0x5386, 0x88, 0, 0},
> +	{0x5387, 0x7c, 0, 0}, {0x5388, 0x6c, 0, 0}, {0x5389, 0x10, 0, 0},
> +	{0x538a, 0x01, 0, 0}, {0x538b, 0x98, 0, 0}, {0x5300, 0x08, 0, 0},
> +	{0x5301, 0x30, 0, 0}, {0x5302, 0x10, 0, 0}, {0x5303, 0x00, 0, 0},
> +	{0x5304, 0x08, 0, 0}, {0x5305, 0x30, 0, 0}, {0x5306, 0x08, 0, 0},
> +	{0x5307, 0x16, 0, 0}, {0x5309, 0x08, 0, 0}, {0x530a, 0x30, 0, 0},
> +	{0x530b, 0x04, 0, 0}, {0x530c, 0x06, 0, 0}, {0x5480, 0x01, 0, 0},
> +	{0x5481, 0x08, 0, 0}, {0x5482, 0x14, 0, 0}, {0x5483, 0x28, 0, 0},
> +	{0x5484, 0x51, 0, 0}, {0x5485, 0x65, 0, 0}, {0x5486, 0x71, 0, 0},
> +	{0x5487, 0x7d, 0, 0}, {0x5488, 0x87, 0, 0}, {0x5489, 0x91, 0, 0},
> +	{0x548a, 0x9a, 0, 0}, {0x548b, 0xaa, 0, 0}, {0x548c, 0xb8, 0, 0},
> +	{0x548d, 0xcd, 0, 0}, {0x548e, 0xdd, 0, 0}, {0x548f, 0xea, 0, 0},
> +	{0x5490, 0x1d, 0, 0}, {0x5580, 0x02, 0, 0}, {0x5583, 0x40, 0, 0},
> +	{0x5584, 0x10, 0, 0}, {0x5589, 0x10, 0, 0}, {0x558a, 0x00, 0, 0},
> +	{0x558b, 0xf8, 0, 0}, {0x5800, 0x23, 0, 0}, {0x5801, 0x14, 0, 0},
> +	{0x5802, 0x0f, 0, 0}, {0x5803, 0x0f, 0, 0}, {0x5804, 0x12, 0, 0},
> +	{0x5805, 0x26, 0, 0}, {0x5806, 0x0c, 0, 0}, {0x5807, 0x08, 0, 0},
> +	{0x5808, 0x05, 0, 0}, {0x5809, 0x05, 0, 0}, {0x580a, 0x08, 0, 0},
> +	{0x580b, 0x0d, 0, 0}, {0x580c, 0x08, 0, 0}, {0x580d, 0x03, 0, 0},
> +	{0x580e, 0x00, 0, 0}, {0x580f, 0x00, 0, 0}, {0x5810, 0x03, 0, 0},
> +	{0x5811, 0x09, 0, 0}, {0x5812, 0x07, 0, 0}, {0x5813, 0x03, 0, 0},
> +	{0x5814, 0x00, 0, 0}, {0x5815, 0x01, 0, 0}, {0x5816, 0x03, 0, 0},
> +	{0x5817, 0x08, 0, 0}, {0x5818, 0x0d, 0, 0}, {0x5819, 0x08, 0, 0},
> +	{0x581a, 0x05, 0, 0}, {0x581b, 0x06, 0, 0}, {0x581c, 0x08, 0, 0},
> +	{0x581d, 0x0e, 0, 0}, {0x581e, 0x29, 0, 0}, {0x581f, 0x17, 0, 0},
> +	{0x5820, 0x11, 0, 0}, {0x5821, 0x11, 0, 0}, {0x5822, 0x15, 0, 0},
> +	{0x5823, 0x28, 0, 0}, {0x5824, 0x46, 0, 0}, {0x5825, 0x26, 0, 0},
> +	{0x5826, 0x08, 0, 0}, {0x5827, 0x26, 0, 0}, {0x5828, 0x64, 0, 0},
> +	{0x5829, 0x26, 0, 0}, {0x582a, 0x24, 0, 0}, {0x582b, 0x22, 0, 0},
> +	{0x582c, 0x24, 0, 0}, {0x582d, 0x24, 0, 0}, {0x582e, 0x06, 0, 0},
> +	{0x582f, 0x22, 0, 0}, {0x5830, 0x40, 0, 0}, {0x5831, 0x42, 0, 0},
> +	{0x5832, 0x24, 0, 0}, {0x5833, 0x26, 0, 0}, {0x5834, 0x24, 0, 0},
> +	{0x5835, 0x22, 0, 0}, {0x5836, 0x22, 0, 0}, {0x5837, 0x26, 0, 0},
> +	{0x5838, 0x44, 0, 0}, {0x5839, 0x24, 0, 0}, {0x583a, 0x26, 0, 0},
> +	{0x583b, 0x28, 0, 0}, {0x583c, 0x42, 0, 0}, {0x583d, 0xce, 0, 0},
> +	{0x5025, 0x00, 0, 0}, {0x3a0f, 0x30, 0, 0}, {0x3a10, 0x28, 0, 0},
> +	{0x3a1b, 0x30, 0, 0}, {0x3a1e, 0x26, 0, 0}, {0x3a11, 0x60, 0, 0},
> +	{0x3a1f, 0x14, 0, 0}, {0x3008, 0x02, 0, 0}, {0x3c00, 0x04, 0, 300},
> +};
> +
> +static struct reg_value ov5640_setting_30fps_VGA_640_480[] = {
> +
> +	{0x3035, 0x14, 0, 0}, {0x3036, 0x38, 0, 0}, {0x3c07, 0x08, 0, 0},
> +	{0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0}, {0x3c0b, 0x40, 0, 0},
> +	{0x3820, 0x41, 0, 0}, {0x3821, 0x07, 0, 0}, {0x3814, 0x31, 0, 0},
> +	{0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0},
> +	{0x3802, 0x00, 0, 0}, {0x3803, 0x04, 0, 0}, {0x3804, 0x0a, 0, 0},
> +	{0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0}, {0x3807, 0x9b, 0, 0},
> +	{0x3808, 0x02, 0, 0}, {0x3809, 0x80, 0, 0}, {0x380a, 0x01, 0, 0},
> +	{0x380b, 0xe0, 0, 0}, {0x380c, 0x07, 0, 0}, {0x380d, 0x68, 0, 0},
> +	{0x380e, 0x04, 0, 0}, {0x380f, 0x38, 0, 0}, {0x3810, 0x00, 0, 0},
> +	{0x3811, 0x10, 0, 0}, {0x3812, 0x00, 0, 0}, {0x3813, 0x06, 0, 0},
> +	{0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0}, {0x3708, 0x64, 0, 0},
> +	{0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x03, 0, 0},
> +	{0x3a03, 0xd8, 0, 0}, {0x3a08, 0x01, 0, 0}, {0x3a09, 0x0e, 0, 0},
> +	{0x3a0a, 0x00, 0, 0}, {0x3a0b, 0xf6, 0, 0}, {0x3a0e, 0x03, 0, 0},
> +	{0x3a0d, 0x04, 0, 0}, {0x3a14, 0x03, 0, 0}, {0x3a15, 0xd8, 0, 0},
> +	{0x4001, 0x02, 0, 0}, {0x4004, 0x02, 0, 0}, {0x4713, 0x03, 0, 0},
> +	{0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0}, {0x460c, 0x22, 0, 0},
> +	{0x3824, 0x02, 0, 0}, {0x5001, 0xa3, 0, 0}, {0x3503, 0x00, 0, 0},
> +};
> +
> +static struct reg_value ov5640_setting_15fps_VGA_640_480[] = {
> +	{0x3035, 0x22, 0, 0}, {0x3036, 0x38, 0, 0}, {0x3c07, 0x08, 0, 0},
> +	{0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0}, {0x3c0b, 0x40, 0, 0},
> +	{0x3820, 0x41, 0, 0}, {0x3821, 0x07, 0, 0}, {0x3814, 0x31, 0, 0},
> +	{0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0},
> +	{0x3802, 0x00, 0, 0}, {0x3803, 0x04, 0, 0}, {0x3804, 0x0a, 0, 0},
> +	{0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0}, {0x3807, 0x9b, 0, 0},
> +	{0x3808, 0x02, 0, 0}, {0x3809, 0x80, 0, 0}, {0x380a, 0x01, 0, 0},
> +	{0x380b, 0xe0, 0, 0}, {0x380c, 0x07, 0, 0}, {0x380d, 0x68, 0, 0},
> +	{0x380e, 0x03, 0, 0}, {0x380f, 0xd8, 0, 0}, {0x3810, 0x00, 0, 0},
> +	{0x3811, 0x10, 0, 0}, {0x3812, 0x00, 0, 0}, {0x3813, 0x06, 0, 0},
> +	{0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0}, {0x3708, 0x64, 0, 0},
> +	{0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x03, 0, 0},
> +	{0x3a03, 0xd8, 0, 0}, {0x3a08, 0x01, 0, 0}, {0x3a09, 0x27, 0, 0},
> +	{0x3a0a, 0x00, 0, 0}, {0x3a0b, 0xf6, 0, 0}, {0x3a0e, 0x03, 0, 0},
> +	{0x3a0d, 0x04, 0, 0}, {0x3a14, 0x03, 0, 0}, {0x3a15, 0xd8, 0, 0},
> +	{0x4001, 0x02, 0, 0}, {0x4004, 0x02, 0, 0}, {0x4713, 0x03, 0, 0},
> +	{0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0}, {0x460c, 0x22, 0, 0},
> +	{0x3824, 0x02, 0, 0}, {0x5001, 0xa3, 0, 0},
> +};
> +
> +static struct reg_value ov5640_setting_30fps_XGA_1024_768[] = {
> +
> +	{0x3035, 0x14, 0, 0}, {0x3036, 0x38, 0, 0}, {0x3c07, 0x08, 0, 0},
> +	{0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0}, {0x3c0b, 0x40, 0, 0},
> +	{0x3820, 0x41, 0, 0}, {0x3821, 0x07, 0, 0}, {0x3814, 0x31, 0, 0},
> +	{0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0},
> +	{0x3802, 0x00, 0, 0}, {0x3803, 0x04, 0, 0}, {0x3804, 0x0a, 0, 0},
> +	{0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0}, {0x3807, 0x9b, 0, 0},
> +	{0x3808, 0x02, 0, 0}, {0x3809, 0x80, 0, 0}, {0x380a, 0x01, 0, 0},
> +	{0x380b, 0xe0, 0, 0}, {0x380c, 0x07, 0, 0}, {0x380d, 0x68, 0, 0},
> +	{0x380e, 0x04, 0, 0}, {0x380f, 0x38, 0, 0}, {0x3810, 0x00, 0, 0},
> +	{0x3811, 0x10, 0, 0}, {0x3812, 0x00, 0, 0}, {0x3813, 0x06, 0, 0},
> +	{0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0}, {0x3708, 0x64, 0, 0},
> +	{0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x03, 0, 0},
> +	{0x3a03, 0xd8, 0, 0}, {0x3a08, 0x01, 0, 0}, {0x3a09, 0x0e, 0, 0},
> +	{0x3a0a, 0x00, 0, 0}, {0x3a0b, 0xf6, 0, 0}, {0x3a0e, 0x03, 0, 0},
> +	{0x3a0d, 0x04, 0, 0}, {0x3a14, 0x03, 0, 0}, {0x3a15, 0xd8, 0, 0},
> +	{0x4001, 0x02, 0, 0}, {0x4004, 0x02, 0, 0}, {0x4713, 0x03, 0, 0},
> +	{0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0}, {0x460c, 0x22, 0, 0},
> +	{0x3824, 0x02, 0, 0}, {0x5001, 0xa3, 0, 0}, {0x3503, 0x00, 0, 0},
> +	{0x3808, 0x04, 0, 0}, {0x3809, 0x00, 0, 0}, {0x380a, 0x03, 0, 0},
> +	{0x380b, 0x00, 0, 0}, {0x3035, 0x12, 0, 0},
> +};
> +
> +static struct reg_value ov5640_setting_15fps_XGA_1024_768[] = {
> +	{0x3035, 0x22, 0, 0}, {0x3036, 0x38, 0, 0}, {0x3c07, 0x08, 0, 0},
> +	{0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0}, {0x3c0b, 0x40, 0, 0},
> +	{0x3820, 0x41, 0, 0}, {0x3821, 0x07, 0, 0}, {0x3814, 0x31, 0, 0},
> +	{0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0},
> +	{0x3802, 0x00, 0, 0}, {0x3803, 0x04, 0, 0}, {0x3804, 0x0a, 0, 0},
> +	{0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0}, {0x3807, 0x9b, 0, 0},
> +	{0x3808, 0x02, 0, 0}, {0x3809, 0x80, 0, 0}, {0x380a, 0x01, 0, 0},
> +	{0x380b, 0xe0, 0, 0}, {0x380c, 0x07, 0, 0}, {0x380d, 0x68, 0, 0},
> +	{0x380e, 0x03, 0, 0}, {0x380f, 0xd8, 0, 0}, {0x3810, 0x00, 0, 0},
> +	{0x3811, 0x10, 0, 0}, {0x3812, 0x00, 0, 0}, {0x3813, 0x06, 0, 0},
> +	{0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0}, {0x3708, 0x64, 0, 0},
> +	{0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x03, 0, 0},
> +	{0x3a03, 0xd8, 0, 0}, {0x3a08, 0x01, 0, 0}, {0x3a09, 0x27, 0, 0},
> +	{0x3a0a, 0x00, 0, 0}, {0x3a0b, 0xf6, 0, 0}, {0x3a0e, 0x03, 0, 0},
> +	{0x3a0d, 0x04, 0, 0}, {0x3a14, 0x03, 0, 0}, {0x3a15, 0xd8, 0, 0},
> +	{0x4001, 0x02, 0, 0}, {0x4004, 0x02, 0, 0}, {0x4713, 0x03, 0, 0},
> +	{0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0}, {0x460c, 0x22, 0, 0},
> +	{0x3824, 0x02, 0, 0}, {0x5001, 0xa3, 0, 0}, {0x3808, 0x04, 0, 0},
> +	{0x3809, 0x00, 0, 0}, {0x380a, 0x03, 0, 0}, {0x380b, 0x00, 0, 0},
> +};
> +
> +static struct reg_value ov5640_setting_30fps_QVGA_320_240[] = {
> +	{0x3035, 0x14, 0, 0}, {0x3036, 0x38, 0, 0}, {0x3c07, 0x08, 0, 0},
> +	{0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0}, {0x3c0b, 0x40, 0, 0},
> +	{0x3820, 0x41, 0, 0}, {0x3821, 0x07, 0, 0}, {0x3814, 0x31, 0, 0},
> +	{0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0},
> +	{0x3802, 0x00, 0, 0}, {0x3803, 0x04, 0, 0}, {0x3804, 0x0a, 0, 0},
> +	{0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0}, {0x3807, 0x9b, 0, 0},
> +	{0x3808, 0x01, 0, 0}, {0x3809, 0x40, 0, 0}, {0x380a, 0x00, 0, 0},
> +	{0x380b, 0xf0, 0, 0}, {0x380c, 0x07, 0, 0}, {0x380d, 0x68, 0, 0},
> +	{0x380e, 0x03, 0, 0}, {0x380f, 0xd8, 0, 0}, {0x3810, 0x00, 0, 0},
> +	{0x3811, 0x10, 0, 0}, {0x3812, 0x00, 0, 0}, {0x3813, 0x06, 0, 0},
> +	{0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0}, {0x3708, 0x64, 0, 0},
> +	{0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x03, 0, 0},
> +	{0x3a03, 0xd8, 0, 0}, {0x3a08, 0x01, 0, 0}, {0x3a09, 0x27, 0, 0},
> +	{0x3a0a, 0x00, 0, 0}, {0x3a0b, 0xf6, 0, 0}, {0x3a0e, 0x03, 0, 0},
> +	{0x3a0d, 0x04, 0, 0}, {0x3a14, 0x03, 0, 0}, {0x3a15, 0xd8, 0, 0},
> +	{0x4001, 0x02, 0, 0}, {0x4004, 0x02, 0, 0}, {0x4713, 0x03, 0, 0},
> +	{0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0}, {0x460c, 0x22, 0, 0},
> +	{0x3824, 0x02, 0, 0}, {0x5001, 0xa3, 0, 0},
> +};
> +
> +static struct reg_value ov5640_setting_15fps_QVGA_320_240[] = {
> +	{0x3035, 0x22, 0, 0}, {0x3036, 0x38, 0, 0}, {0x3c07, 0x08, 0, 0},
> +	{0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0}, {0x3c0b, 0x40, 0, 0},
> +	{0x3820, 0x41, 0, 0}, {0x3821, 0x07, 0, 0}, {0x3814, 0x31, 0, 0},
> +	{0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0},
> +	{0x3802, 0x00, 0, 0}, {0x3803, 0x04, 0, 0}, {0x3804, 0x0a, 0, 0},
> +	{0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0}, {0x3807, 0x9b, 0, 0},
> +	{0x3808, 0x01, 0, 0}, {0x3809, 0x40, 0, 0}, {0x380a, 0x00, 0, 0},
> +	{0x380b, 0xf0, 0, 0}, {0x380c, 0x07, 0, 0}, {0x380d, 0x68, 0, 0},
> +	{0x380e, 0x03, 0, 0}, {0x380f, 0xd8, 0, 0}, {0x3810, 0x00, 0, 0},
> +	{0x3811, 0x10, 0, 0}, {0x3812, 0x00, 0, 0}, {0x3813, 0x06, 0, 0},
> +	{0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0}, {0x3708, 0x64, 0, 0},
> +	{0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x03, 0, 0},
> +	{0x3a03, 0xd8, 0, 0}, {0x3a08, 0x01, 0, 0}, {0x3a09, 0x27, 0, 0},
> +	{0x3a0a, 0x00, 0, 0}, {0x3a0b, 0xf6, 0, 0}, {0x3a0e, 0x03, 0, 0},
> +	{0x3a0d, 0x04, 0, 0}, {0x3a14, 0x03, 0, 0}, {0x3a15, 0xd8, 0, 0},
> +	{0x4001, 0x02, 0, 0}, {0x4004, 0x02, 0, 0}, {0x4713, 0x03, 0, 0},
> +	{0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0}, {0x460c, 0x22, 0, 0},
> +	{0x3824, 0x02, 0, 0}, {0x5001, 0xa3, 0, 0},
> +};
> +
> +static struct reg_value ov5640_setting_30fps_QCIF_176_144[] = {
> +	{0x3035, 0x14, 0, 0}, {0x3036, 0x38, 0, 0}, {0x3c07, 0x08, 0, 0},
> +	{0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0}, {0x3c0b, 0x40, 0, 0},
> +	{0x3820, 0x41, 0, 0}, {0x3821, 0x07, 0, 0}, {0x3814, 0x31, 0, 0},
> +	{0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0},
> +	{0x3802, 0x00, 0, 0}, {0x3803, 0x04, 0, 0}, {0x3804, 0x0a, 0, 0},
> +	{0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0}, {0x3807, 0x9b, 0, 0},
> +	{0x3808, 0x00, 0, 0}, {0x3809, 0xb0, 0, 0}, {0x380a, 0x00, 0, 0},
> +	{0x380b, 0x90, 0, 0}, {0x380c, 0x07, 0, 0}, {0x380d, 0x68, 0, 0},
> +	{0x380e, 0x03, 0, 0}, {0x380f, 0xd8, 0, 0}, {0x3810, 0x00, 0, 0},
> +	{0x3811, 0x10, 0, 0}, {0x3812, 0x00, 0, 0}, {0x3813, 0x06, 0, 0},
> +	{0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0}, {0x3708, 0x64, 0, 0},
> +	{0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x03, 0, 0},
> +	{0x3a03, 0xd8, 0, 0}, {0x3a08, 0x01, 0, 0}, {0x3a09, 0x27, 0, 0},
> +	{0x3a0a, 0x00, 0, 0}, {0x3a0b, 0xf6, 0, 0}, {0x3a0e, 0x03, 0, 0},
> +	{0x3a0d, 0x04, 0, 0}, {0x3a14, 0x03, 0, 0}, {0x3a15, 0xd8, 0, 0},
> +	{0x4001, 0x02, 0, 0}, {0x4004, 0x02, 0, 0}, {0x4713, 0x03, 0, 0},
> +	{0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0}, {0x460c, 0x22, 0, 0},
> +	{0x3824, 0x02, 0, 0}, {0x5001, 0xa3, 0, 0},
> +};
> +static struct reg_value ov5640_setting_15fps_QCIF_176_144[] = {
> +	{0x3035, 0x22, 0, 0}, {0x3036, 0x38, 0, 0}, {0x3c07, 0x08, 0, 0},
> +	{0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0}, {0x3c0b, 0x40, 0, 0},
> +	{0x3820, 0x41, 0, 0}, {0x3821, 0x07, 0, 0}, {0x3814, 0x31, 0, 0},
> +	{0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0},
> +	{0x3802, 0x00, 0, 0}, {0x3803, 0x04, 0, 0}, {0x3804, 0x0a, 0, 0},
> +	{0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0}, {0x3807, 0x9b, 0, 0},
> +	{0x3808, 0x00, 0, 0}, {0x3809, 0xb0, 0, 0}, {0x380a, 0x00, 0, 0},
> +	{0x380b, 0x90, 0, 0}, {0x380c, 0x07, 0, 0}, {0x380d, 0x68, 0, 0},
> +	{0x380e, 0x03, 0, 0}, {0x380f, 0xd8, 0, 0}, {0x3810, 0x00, 0, 0},
> +	{0x3811, 0x10, 0, 0}, {0x3812, 0x00, 0, 0}, {0x3813, 0x06, 0, 0},
> +	{0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0}, {0x3708, 0x64, 0, 0},
> +	{0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x03, 0, 0},
> +	{0x3a03, 0xd8, 0, 0}, {0x3a08, 0x01, 0, 0}, {0x3a09, 0x27, 0, 0},
> +	{0x3a0a, 0x00, 0, 0}, {0x3a0b, 0xf6, 0, 0}, {0x3a0e, 0x03, 0, 0},
> +	{0x3a0d, 0x04, 0, 0}, {0x3a14, 0x03, 0, 0}, {0x3a15, 0xd8, 0, 0},
> +	{0x4001, 0x02, 0, 0}, {0x4004, 0x02, 0, 0}, {0x4713, 0x03, 0, 0},
> +	{0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0}, {0x460c, 0x22, 0, 0},
> +	{0x3824, 0x02, 0, 0}, {0x5001, 0xa3, 0, 0},
> +};
> +
> +static struct reg_value ov5640_setting_30fps_NTSC_720_480[] = {
> +	{0x3035, 0x12, 0, 0}, {0x3036, 0x38, 0, 0}, {0x3c07, 0x08, 0, 0},
> +	{0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0}, {0x3c0b, 0x40, 0, 0},
> +	{0x3820, 0x41, 0, 0}, {0x3821, 0x07, 0, 0}, {0x3814, 0x31, 0, 0},
> +	{0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0},
> +	{0x3802, 0x00, 0, 0}, {0x3803, 0x04, 0, 0}, {0x3804, 0x0a, 0, 0},
> +	{0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0}, {0x3807, 0x9b, 0, 0},
> +	{0x3808, 0x02, 0, 0}, {0x3809, 0xd0, 0, 0}, {0x380a, 0x01, 0, 0},
> +	{0x380b, 0xe0, 0, 0}, {0x380c, 0x07, 0, 0}, {0x380d, 0x68, 0, 0},
> +	{0x380e, 0x03, 0, 0}, {0x380f, 0xd8, 0, 0}, {0x3810, 0x00, 0, 0},
> +	{0x3811, 0x10, 0, 0}, {0x3812, 0x00, 0, 0}, {0x3813, 0x3c, 0, 0},
> +	{0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0}, {0x3708, 0x64, 0, 0},
> +	{0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x03, 0, 0},
> +	{0x3a03, 0xd8, 0, 0}, {0x3a08, 0x01, 0, 0}, {0x3a09, 0x27, 0, 0},
> +	{0x3a0a, 0x00, 0, 0}, {0x3a0b, 0xf6, 0, 0}, {0x3a0e, 0x03, 0, 0},
> +	{0x3a0d, 0x04, 0, 0}, {0x3a14, 0x03, 0, 0}, {0x3a15, 0xd8, 0, 0},
> +	{0x4001, 0x02, 0, 0}, {0x4004, 0x02, 0, 0}, {0x4713, 0x03, 0, 0},
> +	{0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0}, {0x460c, 0x22, 0, 0},
> +	{0x3824, 0x02, 0, 0}, {0x5001, 0xa3, 0, 0},
> +};
> +
> +static struct reg_value ov5640_setting_15fps_NTSC_720_480[] = {
> +	{0x3035, 0x22, 0, 0}, {0x3036, 0x38, 0, 0}, {0x3c07, 0x08, 0, 0},
> +	{0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0}, {0x3c0b, 0x40, 0, 0},
> +	{0x3820, 0x41, 0, 0}, {0x3821, 0x07, 0, 0}, {0x3814, 0x31, 0, 0},
> +	{0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0},
> +	{0x3802, 0x00, 0, 0}, {0x3803, 0x04, 0, 0}, {0x3804, 0x0a, 0, 0},
> +	{0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0}, {0x3807, 0x9b, 0, 0},
> +	{0x3808, 0x02, 0, 0}, {0x3809, 0xd0, 0, 0}, {0x380a, 0x01, 0, 0},
> +	{0x380b, 0xe0, 0, 0}, {0x380c, 0x07, 0, 0}, {0x380d, 0x68, 0, 0},
> +	{0x380e, 0x03, 0, 0}, {0x380f, 0xd8, 0, 0}, {0x3810, 0x00, 0, 0},
> +	{0x3811, 0x10, 0, 0}, {0x3812, 0x00, 0, 0}, {0x3813, 0x3c, 0, 0},
> +	{0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0}, {0x3708, 0x64, 0, 0},
> +	{0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x03, 0, 0},
> +	{0x3a03, 0xd8, 0, 0}, {0x3a08, 0x01, 0, 0}, {0x3a09, 0x27, 0, 0},
> +	{0x3a0a, 0x00, 0, 0}, {0x3a0b, 0xf6, 0, 0}, {0x3a0e, 0x03, 0, 0},
> +	{0x3a0d, 0x04, 0, 0}, {0x3a14, 0x03, 0, 0}, {0x3a15, 0xd8, 0, 0},
> +	{0x4001, 0x02, 0, 0}, {0x4004, 0x02, 0, 0}, {0x4713, 0x03, 0, 0},
> +	{0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0}, {0x460c, 0x22, 0, 0},
> +	{0x3824, 0x02, 0, 0}, {0x5001, 0xa3, 0, 0},
> +};
> +
> +static struct reg_value ov5640_setting_30fps_PAL_720_576[] = {
> +	{0x3035, 0x12, 0, 0}, {0x3036, 0x38, 0, 0}, {0x3c07, 0x08, 0, 0},
> +	{0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0}, {0x3c0b, 0x40, 0, 0},
> +	{0x3820, 0x41, 0, 0}, {0x3821, 0x07, 0, 0}, {0x3814, 0x31, 0, 0},
> +	{0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0},
> +	{0x3802, 0x00, 0, 0}, {0x3803, 0x04, 0, 0}, {0x3804, 0x0a, 0, 0},
> +	{0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0}, {0x3807, 0x9b, 0, 0},
> +	{0x3808, 0x02, 0, 0}, {0x3809, 0xd0, 0, 0}, {0x380a, 0x02, 0, 0},
> +	{0x380b, 0x40, 0, 0}, {0x380c, 0x07, 0, 0}, {0x380d, 0x68, 0, 0},
> +	{0x380e, 0x03, 0, 0}, {0x380f, 0xd8, 0, 0}, {0x3810, 0x00, 0, 0},
> +	{0x3811, 0x38, 0, 0}, {0x3812, 0x00, 0, 0}, {0x3813, 0x06, 0, 0},
> +	{0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0}, {0x3708, 0x64, 0, 0},
> +	{0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x03, 0, 0},
> +	{0x3a03, 0xd8, 0, 0}, {0x3a08, 0x01, 0, 0}, {0x3a09, 0x27, 0, 0},
> +	{0x3a0a, 0x00, 0, 0}, {0x3a0b, 0xf6, 0, 0}, {0x3a0e, 0x03, 0, 0},
> +	{0x3a0d, 0x04, 0, 0}, {0x3a14, 0x03, 0, 0}, {0x3a15, 0xd8, 0, 0},
> +	{0x4001, 0x02, 0, 0}, {0x4004, 0x02, 0, 0}, {0x4713, 0x03, 0, 0},
> +	{0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0}, {0x460c, 0x22, 0, 0},
> +	{0x3824, 0x02, 0, 0}, {0x5001, 0xa3, 0, 0},
> +};
> +
> +static struct reg_value ov5640_setting_15fps_PAL_720_576[] = {
> +	{0x3035, 0x22, 0, 0}, {0x3036, 0x38, 0, 0}, {0x3c07, 0x08, 0, 0},
> +	{0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0}, {0x3c0b, 0x40, 0, 0},
> +	{0x3820, 0x41, 0, 0}, {0x3821, 0x07, 0, 0}, {0x3814, 0x31, 0, 0},
> +	{0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0},
> +	{0x3802, 0x00, 0, 0}, {0x3803, 0x04, 0, 0}, {0x3804, 0x0a, 0, 0},
> +	{0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0}, {0x3807, 0x9b, 0, 0},
> +	{0x3808, 0x02, 0, 0}, {0x3809, 0xd0, 0, 0}, {0x380a, 0x02, 0, 0},
> +	{0x380b, 0x40, 0, 0}, {0x380c, 0x07, 0, 0}, {0x380d, 0x68, 0, 0},
> +	{0x380e, 0x03, 0, 0}, {0x380f, 0xd8, 0, 0}, {0x3810, 0x00, 0, 0},
> +	{0x3811, 0x38, 0, 0}, {0x3812, 0x00, 0, 0}, {0x3813, 0x06, 0, 0},
> +	{0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0}, {0x3708, 0x64, 0, 0},
> +	{0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x03, 0, 0},
> +	{0x3a03, 0xd8, 0, 0}, {0x3a08, 0x01, 0, 0}, {0x3a09, 0x27, 0, 0},
> +	{0x3a0a, 0x00, 0, 0}, {0x3a0b, 0xf6, 0, 0}, {0x3a0e, 0x03, 0, 0},
> +	{0x3a0d, 0x04, 0, 0}, {0x3a14, 0x03, 0, 0}, {0x3a15, 0xd8, 0, 0},
> +	{0x4001, 0x02, 0, 0}, {0x4004, 0x02, 0, 0}, {0x4713, 0x03, 0, 0},
> +	{0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0}, {0x460c, 0x22, 0, 0},
> +	{0x3824, 0x02, 0, 0}, {0x5001, 0xa3, 0, 0},
> +};
> +
> +static struct reg_value ov5640_setting_30fps_720P_1280_720[] = {
> +	{0x3008, 0x42, 0, 0},
> +	{0x3035, 0x21, 0, 0}, {0x3036, 0x54, 0, 0}, {0x3c07, 0x07, 0, 0},
> +	{0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0}, {0x3c0b, 0x40, 0, 0},
> +	{0x3820, 0x41, 0, 0}, {0x3821, 0x07, 0, 0}, {0x3814, 0x31, 0, 0},
> +	{0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0},
> +	{0x3802, 0x00, 0, 0}, {0x3803, 0xfa, 0, 0}, {0x3804, 0x0a, 0, 0},
> +	{0x3805, 0x3f, 0, 0}, {0x3806, 0x06, 0, 0}, {0x3807, 0xa9, 0, 0},
> +	{0x3808, 0x05, 0, 0}, {0x3809, 0x00, 0, 0}, {0x380a, 0x02, 0, 0},
> +	{0x380b, 0xd0, 0, 0}, {0x380c, 0x07, 0, 0}, {0x380d, 0x64, 0, 0},
> +	{0x380e, 0x02, 0, 0}, {0x380f, 0xe4, 0, 0}, {0x3810, 0x00, 0, 0},
> +	{0x3811, 0x10, 0, 0}, {0x3812, 0x00, 0, 0}, {0x3813, 0x04, 0, 0},
> +	{0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0}, {0x3708, 0x64, 0, 0},
> +	{0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x02, 0, 0},
> +	{0x3a03, 0xe4, 0, 0}, {0x3a08, 0x01, 0, 0}, {0x3a09, 0xbc, 0, 0},
> +	{0x3a0a, 0x01, 0, 0}, {0x3a0b, 0x72, 0, 0}, {0x3a0e, 0x01, 0, 0},
> +	{0x3a0d, 0x02, 0, 0}, {0x3a14, 0x02, 0, 0}, {0x3a15, 0xe4, 0, 0},
> +	{0x4001, 0x02, 0, 0}, {0x4004, 0x02, 0, 0}, {0x4713, 0x02, 0, 0},
> +	{0x4407, 0x04, 0, 0}, {0x460b, 0x37, 0, 0}, {0x460c, 0x20, 0, 0},
> +	{0x3824, 0x04, 0, 0}, {0x5001, 0x83, 0, 0}, {0x4005, 0x1a, 0, 0},
> +	{0x3008, 0x02, 0, 0}, {0x3503, 0,    0, 0},
> +};
> +
> +static struct reg_value ov5640_setting_15fps_720P_1280_720[] = {
> +	{0x3035, 0x41, 0, 0}, {0x3036, 0x54, 0, 0}, {0x3c07, 0x07, 0, 0},
> +	{0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0}, {0x3c0b, 0x40, 0, 0},
> +	{0x3820, 0x41, 0, 0}, {0x3821, 0x07, 0, 0}, {0x3814, 0x31, 0, 0},
> +	{0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0},
> +	{0x3802, 0x00, 0, 0}, {0x3803, 0xfa, 0, 0}, {0x3804, 0x0a, 0, 0},
> +	{0x3805, 0x3f, 0, 0}, {0x3806, 0x06, 0, 0}, {0x3807, 0xa9, 0, 0},
> +	{0x3808, 0x05, 0, 0}, {0x3809, 0x00, 0, 0}, {0x380a, 0x02, 0, 0},
> +	{0x380b, 0xd0, 0, 0}, {0x380c, 0x07, 0, 0}, {0x380d, 0x64, 0, 0},
> +	{0x380e, 0x02, 0, 0}, {0x380f, 0xe4, 0, 0}, {0x3810, 0x00, 0, 0},
> +	{0x3811, 0x10, 0, 0}, {0x3812, 0x00, 0, 0}, {0x3813, 0x04, 0, 0},
> +	{0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0}, {0x3708, 0x64, 0, 0},
> +	{0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x02, 0, 0},
> +	{0x3a03, 0xe4, 0, 0}, {0x3a08, 0x01, 0, 0}, {0x3a09, 0xbc, 0, 0},
> +	{0x3a0a, 0x01, 0, 0}, {0x3a0b, 0x72, 0, 0}, {0x3a0e, 0x01, 0, 0},
> +	{0x3a0d, 0x02, 0, 0}, {0x3a14, 0x02, 0, 0}, {0x3a15, 0xe4, 0, 0},
> +	{0x4001, 0x02, 0, 0}, {0x4004, 0x02, 0, 0}, {0x4713, 0x02, 0, 0},
> +	{0x4407, 0x04, 0, 0}, {0x460b, 0x37, 0, 0}, {0x460c, 0x20, 0, 0},
> +	{0x3824, 0x04, 0, 0}, {0x5001, 0x83, 0, 0},
> +};
> +
> +static struct reg_value ov5640_setting_30fps_1080P_1920_1080[] = {
> +	{0x3008, 0x42, 0, 0},
> +	{0x3035, 0x21, 0, 0}, {0x3036, 0x54, 0, 0}, {0x3c07, 0x08, 0, 0},
> +	{0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0}, {0x3c0b, 0x40, 0, 0},
> +	{0x3820, 0x40, 0, 0}, {0x3821, 0x06, 0, 0}, {0x3814, 0x11, 0, 0},
> +	{0x3815, 0x11, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0},
> +	{0x3802, 0x00, 0, 0}, {0x3803, 0x00, 0, 0}, {0x3804, 0x0a, 0, 0},
> +	{0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0}, {0x3807, 0x9f, 0, 0},
> +	{0x3808, 0x0a, 0, 0}, {0x3809, 0x20, 0, 0}, {0x380a, 0x07, 0, 0},
> +	{0x380b, 0x98, 0, 0}, {0x380c, 0x0b, 0, 0}, {0x380d, 0x1c, 0, 0},
> +	{0x380e, 0x07, 0, 0}, {0x380f, 0xb0, 0, 0}, {0x3810, 0x00, 0, 0},
> +	{0x3811, 0x10, 0, 0}, {0x3812, 0x00, 0, 0}, {0x3813, 0x04, 0, 0},
> +	{0x3618, 0x04, 0, 0}, {0x3612, 0x29, 0, 0}, {0x3708, 0x21, 0, 0},
> +	{0x3709, 0x12, 0, 0}, {0x370c, 0x00, 0, 0}, {0x3a02, 0x03, 0, 0},
> +	{0x3a03, 0xd8, 0, 0}, {0x3a08, 0x01, 0, 0}, {0x3a09, 0x27, 0, 0},
> +	{0x3a0a, 0x00, 0, 0}, {0x3a0b, 0xf6, 0, 0}, {0x3a0e, 0x03, 0, 0},
> +	{0x3a0d, 0x04, 0, 0}, {0x3a14, 0x03, 0, 0}, {0x3a15, 0xd8, 0, 0},
> +	{0x4001, 0x02, 0, 0}, {0x4004, 0x06, 0, 0}, {0x4713, 0x03, 0, 0},
> +	{0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0}, {0x460c, 0x22, 0, 0},
> +	{0x3824, 0x02, 0, 0}, {0x5001, 0x83, 0, 0}, {0x3035, 0x11, 0, 0},
> +	{0x3036, 0x54, 0, 0}, {0x3c07, 0x07, 0, 0}, {0x3c08, 0x00, 0, 0},
> +	{0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0}, {0x3c0b, 0x40, 0, 0},
> +	{0x3800, 0x01, 0, 0}, {0x3801, 0x50, 0, 0}, {0x3802, 0x01, 0, 0},
> +	{0x3803, 0xb2, 0, 0}, {0x3804, 0x08, 0, 0}, {0x3805, 0xef, 0, 0},
> +	{0x3806, 0x05, 0, 0}, {0x3807, 0xf1, 0, 0}, {0x3808, 0x07, 0, 0},
> +	{0x3809, 0x80, 0, 0}, {0x380a, 0x04, 0, 0}, {0x380b, 0x38, 0, 0},
> +	{0x380c, 0x09, 0, 0}, {0x380d, 0xc4, 0, 0}, {0x380e, 0x04, 0, 0},
> +	{0x380f, 0x60, 0, 0}, {0x3612, 0x2b, 0, 0}, {0x3708, 0x64, 0, 0},
> +	{0x3a02, 0x04, 0, 0}, {0x3a03, 0x60, 0, 0}, {0x3a08, 0x01, 0, 0},
> +	{0x3a09, 0x50, 0, 0}, {0x3a0a, 0x01, 0, 0}, {0x3a0b, 0x18, 0, 0},
> +	{0x3a0e, 0x03, 0, 0}, {0x3a0d, 0x04, 0, 0}, {0x3a14, 0x04, 0, 0},
> +	{0x3a15, 0x60, 0, 0}, {0x4713, 0x02, 0, 0}, {0x4407, 0x04, 0, 0},
> +	{0x460b, 0x37, 0, 0}, {0x460c, 0x20, 0, 0}, {0x3824, 0x04, 0, 0},
> +	{0x4005, 0x1a, 0, 0}, {0x3008, 0x02, 0, 0},
> +	{0x3503, 0, 0, 0},
> +};
> +
> +static struct reg_value ov5640_setting_15fps_1080P_1920_1080[] = {
> +	{0x3008, 0x42, 0, 0},
> +	{0x3035, 0x21, 0, 0}, {0x3036, 0x54, 0, 0}, {0x3c07, 0x08, 0, 0},
> +	{0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0}, {0x3c0b, 0x40, 0, 0},
> +	{0x3820, 0x40, 0, 0}, {0x3821, 0x06, 0, 0}, {0x3814, 0x11, 0, 0},
> +	{0x3815, 0x11, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0},
> +	{0x3802, 0x00, 0, 0}, {0x3803, 0x00, 0, 0}, {0x3804, 0x0a, 0, 0},
> +	{0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0}, {0x3807, 0x9f, 0, 0},
> +	{0x3808, 0x0a, 0, 0}, {0x3809, 0x20, 0, 0}, {0x380a, 0x07, 0, 0},
> +	{0x380b, 0x98, 0, 0}, {0x380c, 0x0b, 0, 0}, {0x380d, 0x1c, 0, 0},
> +	{0x380e, 0x07, 0, 0}, {0x380f, 0xb0, 0, 0}, {0x3810, 0x00, 0, 0},
> +	{0x3811, 0x10, 0, 0}, {0x3812, 0x00, 0, 0}, {0x3813, 0x04, 0, 0},
> +	{0x3618, 0x04, 0, 0}, {0x3612, 0x29, 0, 0}, {0x3708, 0x21, 0, 0},
> +	{0x3709, 0x12, 0, 0}, {0x370c, 0x00, 0, 0}, {0x3a02, 0x03, 0, 0},
> +	{0x3a03, 0xd8, 0, 0}, {0x3a08, 0x01, 0, 0}, {0x3a09, 0x27, 0, 0},
> +	{0x3a0a, 0x00, 0, 0}, {0x3a0b, 0xf6, 0, 0}, {0x3a0e, 0x03, 0, 0},
> +	{0x3a0d, 0x04, 0, 0}, {0x3a14, 0x03, 0, 0}, {0x3a15, 0xd8, 0, 0},
> +	{0x4001, 0x02, 0, 0}, {0x4004, 0x06, 0, 0}, {0x4713, 0x03, 0, 0},
> +	{0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0}, {0x460c, 0x22, 0, 0},
> +	{0x3824, 0x02, 0, 0}, {0x5001, 0x83, 0, 0}, {0x3035, 0x21, 0, 0},
> +	{0x3036, 0x54, 0, 1}, {0x3c07, 0x07, 0, 0}, {0x3c08, 0x00, 0, 0},
> +	{0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0}, {0x3c0b, 0x40, 0, 0},
> +	{0x3800, 0x01, 0, 0}, {0x3801, 0x50, 0, 0}, {0x3802, 0x01, 0, 0},
> +	{0x3803, 0xb2, 0, 0}, {0x3804, 0x08, 0, 0}, {0x3805, 0xef, 0, 0},
> +	{0x3806, 0x05, 0, 0}, {0x3807, 0xf1, 0, 0}, {0x3808, 0x07, 0, 0},
> +	{0x3809, 0x80, 0, 0}, {0x380a, 0x04, 0, 0}, {0x380b, 0x38, 0, 0},
> +	{0x380c, 0x09, 0, 0}, {0x380d, 0xc4, 0, 0}, {0x380e, 0x04, 0, 0},
> +	{0x380f, 0x60, 0, 0}, {0x3612, 0x2b, 0, 0}, {0x3708, 0x64, 0, 0},
> +	{0x3a02, 0x04, 0, 0}, {0x3a03, 0x60, 0, 0}, {0x3a08, 0x01, 0, 0},
> +	{0x3a09, 0x50, 0, 0}, {0x3a0a, 0x01, 0, 0}, {0x3a0b, 0x18, 0, 0},
> +	{0x3a0e, 0x03, 0, 0}, {0x3a0d, 0x04, 0, 0}, {0x3a14, 0x04, 0, 0},
> +	{0x3a15, 0x60, 0, 0}, {0x4713, 0x02, 0, 0}, {0x4407, 0x04, 0, 0},
> +	{0x460b, 0x37, 0, 0}, {0x460c, 0x20, 0, 0}, {0x3824, 0x04, 0, 0},
> +	{0x4005, 0x1a, 0, 0}, {0x3008, 0x02, 0, 0}, {0x3503, 0, 0, 0},
> +};
> +
> +static struct reg_value ov5640_setting_15fps_QSXGA_2592_1944[] = {
> +	{0x4202, 0x0f, 0, 0},	/* stream off the sensor */
> +	{0x3820, 0x40, 0, 0}, {0x3821, 0x06, 0, 0}, /*disable flip*/
> +	{0x3035, 0x21, 0, 0}, {0x3036, 0x54, 0, 0}, {0x3c07, 0x08, 0, 0},
> +	{0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0}, {0x3c0b, 0x40, 0, 0},
> +	{0x3820, 0x40, 0, 0}, {0x3821, 0x06, 0, 0}, {0x3814, 0x11, 0, 0},
> +	{0x3815, 0x11, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0},
> +	{0x3802, 0x00, 0, 0}, {0x3803, 0x00, 0, 0}, {0x3804, 0x0a, 0, 0},
> +	{0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0}, {0x3807, 0x9f, 0, 0},
> +	{0x3808, 0x0a, 0, 0}, {0x3809, 0x20, 0, 0}, {0x380a, 0x07, 0, 0},
> +	{0x380b, 0x98, 0, 0}, {0x380c, 0x0b, 0, 0}, {0x380d, 0x1c, 0, 0},
> +	{0x380e, 0x07, 0, 0}, {0x380f, 0xb0, 0, 0}, {0x3810, 0x00, 0, 0},
> +	{0x3811, 0x10, 0, 0}, {0x3812, 0x00, 0, 0}, {0x3813, 0x04, 0, 0},
> +	{0x3618, 0x04, 0, 0}, {0x3612, 0x29, 0, 0}, {0x3708, 0x21, 0, 0},
> +	{0x3709, 0x12, 0, 0}, {0x370c, 0x00, 0, 0}, {0x3a02, 0x03, 0, 0},
> +	{0x3a03, 0xd8, 0, 0}, {0x3a08, 0x01, 0, 0}, {0x3a09, 0x27, 0, 0},
> +	{0x3a0a, 0x00, 0, 0}, {0x3a0b, 0xf6, 0, 0}, {0x3a0e, 0x03, 0, 0},
> +	{0x3a0d, 0x04, 0, 0}, {0x3a14, 0x03, 0, 0}, {0x3a15, 0xd8, 0, 0},
> +	{0x4001, 0x02, 0, 0}, {0x4004, 0x06, 0, 0}, {0x4713, 0x03, 0, 0},
> +	{0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0}, {0x460c, 0x22, 0, 0},
> +	{0x3824, 0x02, 0, 0}, {0x5001, 0x83, 0, 70},
> +	{0x4202, 0x00, 0, 0},	/* stream on the sensor */
> +};
> +
> +static struct ov5640_mode_info
> +ov5640_mode_info_data[ov5640_num_framerates][ov5640_num_modes] = {
> +	{
> +		{ov5640_mode_QCIF_176_144, SUBSAMPLING, 176, 144,
> +		 ov5640_setting_15fps_QCIF_176_144,
> +		 ARRAY_SIZE(ov5640_setting_15fps_QCIF_176_144)},
> +		{ov5640_mode_QVGA_320_240, SUBSAMPLING, 320,  240,
> +		 ov5640_setting_15fps_QVGA_320_240,
> +		 ARRAY_SIZE(ov5640_setting_15fps_QVGA_320_240)},
> +		{ov5640_mode_VGA_640_480, SUBSAMPLING, 640,  480,
> +		 ov5640_setting_15fps_VGA_640_480,
> +		 ARRAY_SIZE(ov5640_setting_15fps_VGA_640_480)},
> +		{ov5640_mode_NTSC_720_480, SUBSAMPLING, 720, 480,
> +		 ov5640_setting_15fps_NTSC_720_480,
> +		 ARRAY_SIZE(ov5640_setting_15fps_NTSC_720_480)},
> +		{ov5640_mode_PAL_720_576, SUBSAMPLING, 720, 576,
> +		 ov5640_setting_15fps_PAL_720_576,
> +		 ARRAY_SIZE(ov5640_setting_15fps_PAL_720_576)},
> +		{ov5640_mode_XGA_1024_768, SUBSAMPLING, 1024, 768,
> +		 ov5640_setting_15fps_XGA_1024_768,
> +		 ARRAY_SIZE(ov5640_setting_15fps_XGA_1024_768)},
> +		{ov5640_mode_720P_1280_720, SUBSAMPLING, 1280, 720,
> +		 ov5640_setting_15fps_720P_1280_720,
> +		 ARRAY_SIZE(ov5640_setting_15fps_720P_1280_720)},
> +		{ov5640_mode_1080P_1920_1080, SCALING, 1920, 1080,
> +		 ov5640_setting_15fps_1080P_1920_1080,
> +		 ARRAY_SIZE(ov5640_setting_15fps_1080P_1920_1080)},
> +		{ov5640_mode_QSXGA_2592_1944, SCALING, 2592, 1944,
> +		 ov5640_setting_15fps_QSXGA_2592_1944,
> +		 ARRAY_SIZE(ov5640_setting_15fps_QSXGA_2592_1944)},
> +	}, {
> +		{ov5640_mode_QCIF_176_144, SUBSAMPLING, 176, 144,
> +		 ov5640_setting_30fps_QCIF_176_144,
> +		 ARRAY_SIZE(ov5640_setting_30fps_QCIF_176_144)},
> +		{ov5640_mode_QVGA_320_240, SUBSAMPLING, 320,  240,
> +		 ov5640_setting_30fps_QVGA_320_240,
> +		 ARRAY_SIZE(ov5640_setting_30fps_QVGA_320_240)},
> +		{ov5640_mode_VGA_640_480, SUBSAMPLING, 640,  480,
> +		 ov5640_setting_30fps_VGA_640_480,
> +		 ARRAY_SIZE(ov5640_setting_30fps_VGA_640_480)},
> +		{ov5640_mode_NTSC_720_480, SUBSAMPLING, 720, 480,
> +		 ov5640_setting_30fps_NTSC_720_480,
> +		 ARRAY_SIZE(ov5640_setting_30fps_NTSC_720_480)},
> +		{ov5640_mode_PAL_720_576, SUBSAMPLING, 720, 576,
> +		 ov5640_setting_30fps_PAL_720_576,
> +		 ARRAY_SIZE(ov5640_setting_30fps_PAL_720_576)},
> +		{ov5640_mode_XGA_1024_768, SUBSAMPLING, 1024, 768,
> +		 ov5640_setting_30fps_XGA_1024_768,
> +		 ARRAY_SIZE(ov5640_setting_30fps_XGA_1024_768)},
> +		{ov5640_mode_720P_1280_720, SUBSAMPLING, 1280, 720,
> +		 ov5640_setting_30fps_720P_1280_720,
> +		 ARRAY_SIZE(ov5640_setting_30fps_720P_1280_720)},
> +		{ov5640_mode_1080P_1920_1080, SCALING, 1920, 1080,
> +		 ov5640_setting_30fps_1080P_1920_1080,
> +		 ARRAY_SIZE(ov5640_setting_30fps_1080P_1920_1080)},
> +		{ov5640_mode_QSXGA_2592_1944, -1, 0, 0, NULL, 0},
> +	},
> +};
> +
> +static int ov5640_probe(struct i2c_client *adapter,
> +			const struct i2c_device_id *device_id);
> +static int ov5640_remove(struct i2c_client *client);
> +
> +static int ov5640_init_slave_id(struct ov5640_dev *sensor)
> +{
> +	struct i2c_msg msg;
> +	u8 buf[4];
> +	int ret;
> +
> +	if (sensor->i2c_client->addr == OV5640_DEFAULT_SLAVE_ID)
> +		return 0;
> +
> +	buf[0] = OV5640_SLAVE_ID >> 8;
> +	buf[1] = OV5640_SLAVE_ID & 0xff;
> +	buf[2] = sensor->i2c_client->addr << 1;
> +	msg.addr = OV5640_DEFAULT_SLAVE_ID;
> +	msg.flags = 0;
> +	msg.len = 3;
> +	msg.buf = buf;
> +
> +	ret = i2c_transfer(sensor->i2c_client->adapter, &msg, 1);
> +	if (ret < 0) {
> +		dev_err(sensor->dev, "%s: failed with %d\n", __func__, ret);
> +		return ret;
> +	}
> +
> +	return 0;
> +}
> +
> +static int ov5640_write_reg(struct ov5640_dev *sensor, u16 reg, u8 val)
> +{
> +	u8 buf[3] = {0};
> +	int ret;
> +
> +	buf[0] = reg >> 8;
> +	buf[1] = reg & 0xff;
> +	buf[2] = val;
> +
> +	ret = i2c_master_send(sensor->i2c_client, buf, 3);
> +	if (ret < 0) {
> +		v4l2_err(&sensor->sd, "%s: error: reg=%x, val=%x\n",
> +			__func__, reg, val);
> +		return ret;
> +	}
> +
> +	return 0;
> +}
> +
> +static int ov5640_read_reg(struct ov5640_dev *sensor, u16 reg, u8 *val)
> +{
> +	u8 reg_buf[2] = {0};
> +	u8 read_val = 0;
> +
> +	reg_buf[0] = reg >> 8;
> +	reg_buf[1] = reg & 0xff;
> +
> +	if (2 != i2c_master_send(sensor->i2c_client, reg_buf, 2)) {
> +		v4l2_err(&sensor->sd, "%s: write reg error: reg=%x\n",
> +			__func__, reg);
> +		return -EIO;
> +	}
> +
> +	if (1 != i2c_master_recv(sensor->i2c_client, &read_val, 1)) {
> +		v4l2_err(&sensor->sd, "%s: read reg error: reg=%x, val=%x\n",
> +			__func__, reg, read_val);
> +		return -EIO;
> +	}
> +
> +	*val = read_val;
> +	return 0;
> +}
> +
> +#define OV5640_READ_REG(s, r, v) {				\
> +		ret = ov5640_read_reg((s), (r), (v));		\
> +		if (ret)					\
> +			return ret;				\
> +	}
> +#define OV5640_WRITE_REG(s, r, v) {				\
> +		ret = ov5640_write_reg((s), (r), (v));		\
> +		if (ret)					\
> +			return ret;				\
> +	}
> +
> +static int ov5640_read_reg16(struct ov5640_dev *sensor, u16 reg, u16 *val)
> +{
> +	u8 hi, lo;
> +	int ret;
> +
> +	OV5640_READ_REG(sensor, reg, &hi);
> +	OV5640_READ_REG(sensor, reg+1, &lo);
> +
> +	*val = ((u16)hi << 8) | (u16)lo;
> +	return 0;
> +}
> +#define OV5640_READ_REG16(s, r, v) {				\
> +		ret = ov5640_read_reg16((s), (r), (v));		\
> +		if (ret)					\
> +			return ret;				\
> +	}
> +
> +static int ov5640_write_reg16(struct ov5640_dev *sensor, u16 reg, u16 val)
> +{
> +	int ret;
> +
> +	OV5640_WRITE_REG(sensor, reg, val >> 8);
> +	OV5640_WRITE_REG(sensor, reg+1, val & 0xff);
> +	return 0;
> +}
> +#define OV5640_WRITE_REG16(s, r, v) {				\
> +		ret = ov5640_write_reg16((s), (r), (v));	\
> +		if (ret)					\
> +			return ret;				\
> +	}
> +
> +static int ov5640_mod_reg(struct ov5640_dev *sensor, u16 reg,
> +			  u8 mask, u8 val)
> +{
> +	u8 readval;
> +	int ret;
> +
> +	OV5640_READ_REG(sensor, reg, &readval);
> +
> +	readval &= ~mask;
> +	val &= mask;
> +	val |= readval;
> +
> +	OV5640_WRITE_REG(sensor, reg, val);
> +	return 0;
> +}
> +#define OV5640_MOD_REG(s, r, m, v) {				\
> +		ret = ov5640_mod_reg((s), (r), (m), (v));	\
> +		if (ret)					\
> +			return ret;				\
> +	}
> +
> +/* download ov5640 settings to sensor through i2c */
> +static int ov5640_load_regs(struct ov5640_dev *sensor,
> +			    struct reg_value *regs,
> +			    int size)
> +{
> +	register u32 delay_ms = 0;
> +	register u16 reg_addr = 0;
> +	register u8 mask = 0;
> +	register u8 val = 0;
> +	int i, ret;
> +
> +	for (i = 0; i < size; ++i, ++regs) {
> +		delay_ms = regs->delay_ms;
> +		reg_addr = regs->reg_addr;
> +		val = regs->val;
> +		mask = regs->mask;
> +
> +		if (mask) {
> +			OV5640_MOD_REG(sensor, reg_addr, mask, val);
> +		} else {
> +			OV5640_WRITE_REG(sensor, reg_addr, val);
> +		}
> +		if (delay_ms)
> +			usleep_range(1000*delay_ms, 1000*delay_ms+100);
> +	}
> +
> +	return 0;
> +}
> +
> +static int ov5640_set_stream(struct ov5640_dev *sensor, bool on)
> +{
> +	int ret;
> +
> +	OV5640_WRITE_REG(sensor, 0x4202, on ? 0x00 : 0x0f);
> +	return 0;
> +}
> +
> +static int ov5640_get_sysclk(struct ov5640_dev *sensor)
> +{
> +	 /* calculate sysclk */
> +	int xvclk = sensor->xclk_freq / 10000;
> +	int multiplier, prediv, VCO, sysdiv, pll_rdiv;
> +	int sclk_rdiv_map[] = {1, 2, 4, 8};
> +	int bit_div2x = 1, sclk_rdiv, sysclk;
> +	u8 temp1, temp2;
> +	int ret;
> +
> +	OV5640_READ_REG(sensor, 0x3034, &temp1);
> +	temp2 = temp1 & 0x0f;
> +	if (temp2 == 8 || temp2 == 10)
> +		bit_div2x = temp2 / 2;
> +
> +	OV5640_READ_REG(sensor, 0x3035, &temp1);
> +	sysdiv = temp1>>4;
> +	if (sysdiv == 0)
> +		sysdiv = 16;
> +
> +	OV5640_READ_REG(sensor, 0x3036, &temp1);
> +	multiplier = temp1;
> +
> +	OV5640_READ_REG(sensor, 0x3037, &temp1);
> +	prediv = temp1 & 0x0f;
> +	pll_rdiv = ((temp1 >> 4) & 0x01) + 1;
> +
> +	OV5640_READ_REG(sensor, 0x3108, &temp1);
> +	temp2 = temp1 & 0x03;
> +	sclk_rdiv = sclk_rdiv_map[temp2];
> +
> +	VCO = xvclk * multiplier / prediv;
> +
> +	sysclk = VCO / sysdiv / pll_rdiv * 2 / bit_div2x / sclk_rdiv;
> +
> +	return sysclk;
> +}
> +
> +static int ov5640_set_night_mode(struct ov5640_dev *sensor)
> +{
> +	 /* read HTS from register settings */
> +	u8 mode;
> +	int ret;
> +
> +	OV5640_READ_REG(sensor, 0x3a00, &mode);
> +	mode &= 0xfb;
> +	OV5640_WRITE_REG(sensor, 0x3a00, mode);
> +	return 0;
> +}
> +
> +static int ov5640_get_HTS(struct ov5640_dev *sensor)
> +{
> +	 /* read HTS from register settings */
> +	u16 HTS;
> +	int ret;
> +
> +	OV5640_READ_REG16(sensor, 0x380c, &HTS);
> +	return HTS;
> +}
> +
> +static int ov5640_get_VTS(struct ov5640_dev *sensor)
> +{
> +	u16 VTS;
> +	int ret;
> +
> +	OV5640_READ_REG16(sensor, 0x380e, &VTS);
> +	return VTS;
> +}
> +
> +static int ov5640_set_VTS(struct ov5640_dev *sensor, int VTS)
> +{
> +	int ret;
> +
> +	OV5640_WRITE_REG16(sensor, 0x380e, VTS);
> +	return 0;
> +}
> +
> +static int ov5640_get_light_freq(struct ov5640_dev *sensor)
> +{
> +	/* get banding filter value */
> +	u8 temp, temp1;
> +	int light_freq = 0;
> +	int ret;
> +
> +	OV5640_READ_REG(sensor, 0x3c01, &temp);
> +
> +	if (temp & 0x80) {
> +		/* manual */
> +		OV5640_READ_REG(sensor, 0x3c00, &temp1);
> +		if (temp1 & 0x04) {
> +			/* 50Hz */
> +			light_freq = 50;
> +		} else {
> +			/* 60Hz */
> +			light_freq = 60;
> +		}
> +	} else {
> +		/* auto */
> +		OV5640_READ_REG(sensor, 0x3c0c, &temp1);
> +		if (temp1 & 0x01) {
> +			/* 50Hz */
> +			light_freq = 50;
> +		} else {
> +			/* 60Hz */
> +		}
> +	}
> +
> +	return light_freq;
> +}
> +
> +static int ov5640_set_bandingfilter(struct ov5640_dev *sensor)
> +{
> +	int prev_vts;
> +	int band_step60, max_band60, band_step50, max_band50;
> +	int ret;
> +
> +	/* read preview PCLK */
> +	ret = ov5640_get_sysclk(sensor);
> +	if (ret < 0)
> +		return ret;
> +	sensor->prev_sysclk = ret;
> +	/* read preview HTS */
> +	ret = ov5640_get_HTS(sensor);
> +	if (ret < 0)
> +		return ret;
> +	sensor->prev_hts = ret;
> +
> +	/* read preview VTS */
> +	ret = ov5640_get_VTS(sensor);
> +	if (ret < 0)
> +		return ret;
> +	prev_vts = ret;
> +
> +	/* calculate banding filter */
> +	/* 60Hz */
> +	band_step60 = sensor->prev_sysclk * 100 / sensor->prev_hts * 100/120;
> +	OV5640_WRITE_REG16(sensor, 0x3a0a, band_step60);
> +
> +	max_band60 = (int)((prev_vts-4)/band_step60);
> +	OV5640_WRITE_REG(sensor, 0x3a0d, max_band60);
> +
> +	/* 50Hz */
> +	band_step50 = sensor->prev_sysclk * 100 / sensor->prev_hts;
> +	OV5640_WRITE_REG16(sensor, 0x3a08, band_step50);
> +
> +	max_band50 = (int)((prev_vts-4)/band_step50);
> +	OV5640_WRITE_REG(sensor, 0x3a0e, max_band50);
> +
> +	return 0;
> +}
> +
> +static int ov5640_set_AE_target(struct ov5640_dev *sensor, int target)
> +{
> +	/* stable in high */
> +	int fast_high, fast_low;
> +	int ret;
> +
> +	sensor->ae_low = target * 23 / 25;	/* 0.92 */
> +	sensor->ae_high = target * 27 / 25;	/* 1.08 */
> +
> +	fast_high = sensor->ae_high<<1;
> +	if (fast_high > 255)
> +		fast_high = 255;
> +
> +	fast_low = sensor->ae_low >> 1;
> +
> +	OV5640_WRITE_REG(sensor, 0x3a0f, sensor->ae_high);
> +	OV5640_WRITE_REG(sensor, 0x3a10, sensor->ae_low);
> +	OV5640_WRITE_REG(sensor, 0x3a1b, sensor->ae_high);
> +	OV5640_WRITE_REG(sensor, 0x3a1e, sensor->ae_low);
> +	OV5640_WRITE_REG(sensor, 0x3a11, fast_high);
> +	OV5640_WRITE_REG(sensor, 0x3a1f, fast_low);
> +
> +	return 0;
> +}
> +
> +static int ov5640_binning_on(struct ov5640_dev *sensor)
> +{
> +	u8 temp;
> +	int ret;
> +
> +	OV5640_READ_REG(sensor, 0x3821, &temp);
> +	temp &= 0xfe;
> +
> +	return temp ? 1 : 0;
> +}
> +
> +static int ov5640_set_virtual_channel(struct ov5640_dev *sensor)
> +{
> +	u8 temp, channel = sensor->ep.base.id;
> +	int ret;
> +
> +	OV5640_READ_REG(sensor, 0x4814, &temp);
> +	temp &= ~(3 << 6);
> +	temp |= (channel << 6);
> +	OV5640_WRITE_REG(sensor, 0x4814, temp);
> +
> +	return 0;
> +}
> +
> +static enum ov5640_mode
> +ov5640_find_nearest_mode(struct ov5640_dev *sensor,
> +			 int width, int height)
> +{
> +	int i;
> +
> +	for (i = ov5640_num_modes - 1; i >= 0; i--) {
> +		if (ov5640_mode_info_data[0][i].width <= width &&
> +		    ov5640_mode_info_data[0][i].height <= height)
> +			break;
> +	}
> +
> +	if (i < 0)
> +		i = 0;
> +
> +	return (enum ov5640_mode)i;
> +}
> +
> +/*
> + * sensor changes between scaling and subsampling, go through
> + * exposure calculation
> + */
> +static int ov5640_change_mode_exposure_calc(struct ov5640_dev *sensor,
> +					    enum ov5640_frame_rate frame_rate,
> +					    enum ov5640_mode mode)
> +{
> +	struct reg_value *mode_data = NULL;
> +	int mode_size = 0;
> +	u8 average;
> +	int prev_shutter, prev_gain16;
> +	int cap_shutter, cap_gain16;
> +	int cap_sysclk, cap_hts, cap_vts;
> +	int light_freq, cap_bandfilt, cap_maxband;
> +	long cap_gain16_shutter;
> +	int ret = 0;
> +
> +	/* check if the input mode and frame rate is valid */
> +	mode_data = ov5640_mode_info_data[frame_rate][mode].init_data_ptr;
> +	mode_size = ov5640_mode_info_data[frame_rate][mode].init_data_size;
> +
> +	sensor->fmt.width = ov5640_mode_info_data[frame_rate][mode].width;
> +	sensor->fmt.height = ov5640_mode_info_data[frame_rate][mode].height;
> +
> +	if (sensor->fmt.width == 0 || sensor->fmt.height == 0 ||
> +	    mode_data == NULL || mode_size == 0)
> +		return -EINVAL;
> +
> +	/* auto focus */
> +	/* ov5640_auto_focus();//if no af function, just skip it */
> +
> +	/* turn off AE/AG */
> +	ret = ov5640_set_agc(sensor, false);
> +	if (ret < 0)
> +		return ret;
> +
> +	/* read preview shutter */
> +	ret = ov5640_get_exposure(sensor);
> +	if (ret < 0)
> +		return ret;
> +	prev_shutter = ret;
> +	ret = ov5640_binning_on(sensor);
> +	if (ret < 0)
> +		return ret;
> +	if (ret && mode != ov5640_mode_720P_1280_720 &&
> +	    mode != ov5640_mode_1080P_1920_1080)
> +		prev_shutter *= 2;
> +
> +	/* read preview gain */
> +	ret = ov5640_get_gain(sensor);
> +	if (ret < 0)
> +		return ret;
> +	prev_gain16 = ret;
> +
> +	/* get average */
> +	OV5640_READ_REG(sensor, 0x56a1, &average);
> +
> +	/* turn off night mode for capture */
> +	ret = ov5640_set_night_mode(sensor);
> +	if (ret < 0)
> +		return ret;
> +
> +	/* turn off overlay */
> +	/* OV5640_WRITE_REG(0x3022, 0x06); //if no af function,
> +	   just skip it */
> +
> +	ret = ov5640_set_stream(sensor, false);
> +	if (ret < 0)
> +		return ret;
> +
> +	/* Write capture setting */
> +	ret = ov5640_load_regs(sensor, mode_data, mode_size);
> +	if (ret < 0)
> +		return ret;
> +
> +	/* read capture VTS */
> +	ret = ov5640_get_VTS(sensor);
> +	if (ret < 0)
> +		return ret;
> +	cap_vts = ret;
> +	ret = ov5640_get_HTS(sensor);
> +	if (ret < 0)
> +		return ret;
> +	cap_hts = ret;
> +	ret = ov5640_get_sysclk(sensor);
> +	if (ret < 0)
> +		return ret;
> +	cap_sysclk = ret;
> +
> +	/* calculate capture banding filter */
> +	ret = ov5640_get_light_freq(sensor);
> +	if (ret < 0)
> +		return ret;
> +	light_freq = ret;
> +
> +	if (light_freq == 60) {
> +		/* 60Hz */
> +		cap_bandfilt = cap_sysclk * 100 / cap_hts * 100 / 120;
> +	} else {
> +		/* 50Hz */
> +		cap_bandfilt = cap_sysclk * 100 / cap_hts;
> +	}
> +	cap_maxband = (int)((cap_vts - 4) / cap_bandfilt);
> +
> +	/* calculate capture shutter/gain16 */
> +	if (average > sensor->ae_low && average < sensor->ae_high) {
> +		/* in stable range */
> +		cap_gain16_shutter =
> +			prev_gain16 * prev_shutter *
> +			cap_sysclk / sensor->prev_sysclk *
> +			sensor->prev_hts / cap_hts *
> +			sensor->ae_target / average;
> +	} else {
> +		cap_gain16_shutter =
> +			prev_gain16 * prev_shutter *
> +			cap_sysclk / sensor->prev_sysclk *
> +			sensor->prev_hts / cap_hts;
> +	}
> +
> +	/* gain to shutter */
> +	if (cap_gain16_shutter < (cap_bandfilt * 16)) {
> +		/* shutter < 1/100 */
> +		cap_shutter = cap_gain16_shutter / 16;
> +		if (cap_shutter < 1)
> +			cap_shutter = 1;
> +
> +		cap_gain16 = cap_gain16_shutter / cap_shutter;
> +		if (cap_gain16 < 16)
> +			cap_gain16 = 16;
> +	} else {
> +		if (cap_gain16_shutter > (cap_bandfilt * cap_maxband * 16)) {
> +			/* exposure reach max */
> +			cap_shutter = cap_bandfilt * cap_maxband;
> +			cap_gain16 = cap_gain16_shutter / cap_shutter;
> +		} else {
> +			/* 1/100 < (cap_shutter = n/100) =< max */
> +			cap_shutter =
> +				((int)(cap_gain16_shutter / 16 / cap_bandfilt))
> +				* cap_bandfilt;
> +			cap_gain16 = cap_gain16_shutter / cap_shutter;
> +		}
> +	}
> +
> +	/* write capture gain */
> +	ret = ov5640_set_gain(sensor, cap_gain16);
> +	if (ret < 0)
> +		return ret;
> +
> +	/* write capture shutter */
> +	if (cap_shutter > (cap_vts - 4)) {
> +		cap_vts = cap_shutter + 4;
> +		ret = ov5640_set_VTS(sensor, cap_vts);
> +		if (ret < 0)
> +			return ret;
> +	}
> +
> +	ret = ov5640_set_exposure(sensor, cap_shutter);
> +	if (ret < 0)
> +		return ret;
> +
> +	return ov5640_set_stream(sensor, true);
> +}
> +
> +/*
> + * if sensor changes inside scaling or subsampling
> + * change mode directly
> + */
> +static int ov5640_change_mode_direct(struct ov5640_dev *sensor,
> +				     enum ov5640_frame_rate frame_rate,
> +				     enum ov5640_mode mode)
> +{
> +	struct reg_value *mode_data = NULL;
> +	int mode_size = 0;
> +	int ret = 0;
> +
> +	/* check if the input mode and frame rate is valid */
> +	mode_data = ov5640_mode_info_data[frame_rate][mode].init_data_ptr;
> +	mode_size = ov5640_mode_info_data[frame_rate][mode].init_data_size;
> +
> +	sensor->fmt.width = ov5640_mode_info_data[frame_rate][mode].width;
> +	sensor->fmt.height = ov5640_mode_info_data[frame_rate][mode].height;
> +
> +	if (sensor->fmt.width == 0 || sensor->fmt.height == 0 ||
> +	    mode_data == NULL || mode_size == 0)
> +		return -EINVAL;
> +
> +	/* turn off AE/AG */
> +	ret = ov5640_set_agc(sensor, false);
> +	if (ret < 0)
> +		return ret;
> +
> +	ret = ov5640_set_stream(sensor, false);
> +	if (ret < 0)
> +		return ret;
> +
> +	/* Write capture setting */
> +	ret = ov5640_load_regs(sensor, mode_data, mode_size);
> +	if (ret < 0)
> +		return ret;
> +
> +	ret = ov5640_set_stream(sensor, true);
> +	if (ret < 0)
> +		return ret;
> +
> +	return ov5640_set_agc(sensor, true);
> +}
> +
> +static int ov5640_change_mode(struct ov5640_dev *sensor,
> +			      enum ov5640_frame_rate frame_rate,
> +			      enum ov5640_mode mode,
> +			      enum ov5640_mode orig_mode)
> +{
> +	enum ov5640_downsize_mode dn_mode, orig_dn_mode;
> +	struct reg_value *mode_data = NULL;
> +	int mode_size = 0;
> +	int ret = 0;
> +
> +	if ((mode >= ov5640_num_modes || mode < ov5640_mode_MIN) &&
> +	    mode != ov5640_mode_INIT) {
> +		v4l2_err(&sensor->sd, "Wrong ov5640 mode detected!\n");
> +		return -EINVAL;
> +	}
> +
> +	dn_mode = ov5640_mode_info_data[frame_rate][mode].dn_mode;
> +	orig_dn_mode = ov5640_mode_info_data[frame_rate][orig_mode].dn_mode;
> +	if (mode == ov5640_mode_INIT) {
> +		mode_data = ov5640_init_setting_30fps_VGA;
> +		mode_size = ARRAY_SIZE(ov5640_init_setting_30fps_VGA);
> +
> +		sensor->fmt.width = 640;
> +		sensor->fmt.height = 480;
> +		ret = ov5640_load_regs(sensor, mode_data, mode_size);
> +		if (ret < 0)
> +			return ret;
> +
> +		mode_data = ov5640_setting_30fps_VGA_640_480;
> +		mode_size = ARRAY_SIZE(ov5640_setting_30fps_VGA_640_480);
> +		ret = ov5640_load_regs(sensor, mode_data, mode_size);
> +	} else if ((dn_mode == SUBSAMPLING && orig_dn_mode == SCALING) ||
> +			(dn_mode == SCALING && orig_dn_mode == SUBSAMPLING)) {
> +		/* change between subsampling and scaling
> +		 * go through exposure calucation */
> +		ret = ov5640_change_mode_exposure_calc(sensor, frame_rate,
> +							  mode);
> +	} else {
> +		/* change inside subsampling or scaling
> +		 * download firmware directly */
> +		ret = ov5640_change_mode_direct(sensor, frame_rate, mode);
> +	}
> +
> +	if (ret < 0)
> +		return ret;
> +
> +	ret = ov5640_set_AE_target(sensor, sensor->ae_target);
> +	if (ret < 0)
> +		return ret;
> +	ret = ov5640_get_light_freq(sensor);
> +	if (ret < 0)
> +		return ret;
> +	ret = ov5640_set_bandingfilter(sensor);
> +	if (ret < 0)
> +		return ret;
> +	ret = ov5640_set_virtual_channel(sensor);
> +	if (ret < 0)
> +		return ret;
> +
> +	/* restore controls */
> +	ov5640_restore_ctrls(sensor);
> +
> +	if (ret >= 0 && mode != ov5640_mode_INIT) {
> +		sensor->current_mode = mode;
> +		sensor->current_fr = frame_rate;
> +	}
> +
> +	return 0;
> +}
> +
> +/* restore the last set video mode after chip power-on */
> +static int ov5640_restore_mode(struct ov5640_dev *sensor)
> +{
> +	int ret = 0;
> +
> +	/* first we need to set some initial register values */
> +	ret = ov5640_change_mode(sensor, sensor->current_fr,
> +				    ov5640_mode_INIT, ov5640_mode_INIT);
> +	if (ret < 0)
> +		return ret;
> +
> +	/* now restore the last capture mode */
> +	return ov5640_change_mode(sensor,
> +				  sensor->current_fr,
> +				  sensor->current_mode,
> +				  ov5640_mode_VGA_640_480);
> +}
> +
> +static int ov5640_regulators_on(struct ov5640_dev *sensor)
> +{
> +	int ret;
> +
> +	if (sensor->io_regulator) {
> +		ret = regulator_enable(sensor->io_regulator);
> +		if (ret) {
> +			v4l2_err(&sensor->sd, "io reg enable failed\n");
> +			return ret;
> +		}
> +	}
> +	if (sensor->core_regulator) {
> +		ret = regulator_enable(sensor->core_regulator);
> +		if (ret) {
> +			v4l2_err(&sensor->sd, "core reg enable failed\n");
> +			return ret;
> +		}
> +	}
> +	if (sensor->gpo_regulator) {
> +		ret = regulator_enable(sensor->gpo_regulator);
> +		if (ret) {
> +			v4l2_err(&sensor->sd, "gpo reg enable failed\n");
> +			return ret;
> +		}
> +	}
> +	if (sensor->analog_regulator) {
> +		ret = regulator_enable(sensor->analog_regulator);
> +		if (ret) {
> +			v4l2_err(&sensor->sd, "analog reg enable failed\n");
> +			return ret;
> +		}
> +	}
> +
> +	return 0;
> +}
> +
> +static void ov5640_regulators_off(struct ov5640_dev *sensor)
> +{
> +	if (sensor->analog_regulator)
> +		regulator_disable(sensor->analog_regulator);
> +	if (sensor->core_regulator)
> +		regulator_disable(sensor->core_regulator);
> +	if (sensor->io_regulator)
> +		regulator_disable(sensor->io_regulator);
> +	if (sensor->gpo_regulator)
> +		regulator_disable(sensor->gpo_regulator);
> +}
> +
> +/* --------------- Subdev Operations --------------- */
> +
> +static int ov5640_s_power(struct v4l2_subdev *sd, int on)
> +{
> +	struct ov5640_dev *sensor = to_ov5640_dev(sd);
> +	int ret;
> +
> +	v4l2_info(sd, "power %s\n", on ? "ON" : "OFF");
> +
> +	if (on && !sensor->on) {
> +		if (sensor->xclk)
> +			clk_prepare_enable(sensor->xclk);
> +
> +		ret = ov5640_regulators_on(sensor);
> +		if (ret)
> +			return ret;
> +
> +		ov5640_reset(sensor);
> +		ov5640_power(sensor, true);
> +
> +		ret = ov5640_init_slave_id(sensor);
> +		if (ret)
> +			return ret;
> +
> +		ret = ov5640_restore_mode(sensor);
> +		if (ret)
> +			return ret;
> +
> +		/*
> +		 * NOTE: Freescale adds a long delay (600 msec) after
> +		 * powering up and programming a mode on the ov5640-mipi
> +		 * camera (search for "msec_wait4stable" in FSL's
> +		 * ov5640_mipi.c), which equivalently would need to go
> +		 * right here. If we run into MIPI CSI-2 receiver dphy
> +		 * ready timeouts, it might be a clue to add that delay
> +		 * here.
> +		 */
> +	} else if (!on && sensor->on) {
> +		ov5640_power(sensor, false);
> +
> +		ov5640_regulators_off(sensor);
> +
> +		if (sensor->xclk)
> +			clk_disable_unprepare(sensor->xclk);
> +	}
> +
> +	sensor->on = on;
> +
> +	return 0;
> +}
> +
> +static int ov5640_g_parm(struct v4l2_subdev *sd, struct v4l2_streamparm *a)
> +{
> +	struct ov5640_dev *sensor = to_ov5640_dev(sd);
> +	struct v4l2_captureparm *cparm = &a->parm.capture;
> +
> +	if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
> +		return -EINVAL;
> +
> +	/* This is the only case currently handled. */
> +	memset(a, 0, sizeof(*a));
> +	a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
> +	cparm->capability = sensor->streamcap.capability;
> +	cparm->timeperframe = sensor->streamcap.timeperframe;
> +	cparm->capturemode = sensor->streamcap.capturemode;
> +
> +	return 0;
> +}
> +
> +static int ov5640_s_parm(struct v4l2_subdev *sd, struct v4l2_streamparm *a)
> +{
> +	struct ov5640_dev *sensor = to_ov5640_dev(sd);
> +	struct v4l2_fract *timeperframe = &a->parm.capture.timeperframe;
> +	enum ov5640_frame_rate frame_rate;
> +	u32 tgt_fps;	/* target frames per secound */
> +	int ret = 0;
> +
> +	if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
> +		return -EINVAL;
> +
> +	/* Check that the new frame rate is allowed. */
> +	if ((timeperframe->numerator == 0) ||
> +	    (timeperframe->denominator == 0)) {
> +		timeperframe->denominator = DEFAULT_FPS;
> +		timeperframe->numerator = 1;
> +	}
> +
> +	tgt_fps = timeperframe->denominator / timeperframe->numerator;
> +
> +	if (tgt_fps > MAX_FPS) {
> +		timeperframe->denominator = MAX_FPS;
> +		timeperframe->numerator = 1;
> +	} else if (tgt_fps < MIN_FPS) {
> +		timeperframe->denominator = MIN_FPS;
> +		timeperframe->numerator = 1;
> +	}
> +
> +	/* Actual frame rate we use */
> +	tgt_fps = timeperframe->denominator / timeperframe->numerator;
> +
> +	if (tgt_fps == 15)
> +		frame_rate = ov5640_15_fps;
> +	else if (tgt_fps == 30)
> +		frame_rate = ov5640_30_fps;
> +	else {
> +		v4l2_err(&sensor->sd, "frame rate %u not supported!\n",
> +			 tgt_fps);
> +		return -EINVAL;
> +	}
> +
> +	ret = ov5640_change_mode(sensor, frame_rate,
> +				 sensor->current_mode,
> +				 sensor->current_mode);
> +	if (ret < 0)
> +		return ret;
> +
> +	sensor->streamcap.timeperframe = *timeperframe;
> +
> +	return 0;
> +}
> +
> +static int ov5640_get_fmt(struct v4l2_subdev *sd,
> +			  struct v4l2_subdev_pad_config *cfg,
> +			  struct v4l2_subdev_format *format)
> +{
> +	struct ov5640_dev *sensor = to_ov5640_dev(sd);
> +
> +	if (format->pad != 0)
> +		return -EINVAL;
> +
> +	format->format = sensor->fmt;
> +
> +	return 0;
> +}
> +
> +static int ov5640_try_fmt_internal(struct v4l2_subdev *sd,
> +				   struct v4l2_mbus_framefmt *fmt,
> +				   enum ov5640_mode *new_mode)
> +{
> +	struct ov5640_dev *sensor = to_ov5640_dev(sd);
> +	enum ov5640_mode mode;
> +
> +	mode = ov5640_find_nearest_mode(sensor, fmt->width, fmt->height);
> +
> +	fmt->width = ov5640_mode_info_data[0][mode].width;
> +	fmt->height = ov5640_mode_info_data[0][mode].height;
> +	fmt->code = sensor->fmt.code;
> +
> +	if (new_mode)
> +		*new_mode = mode;
> +	return 0;
> +}
> +
> +static int ov5640_set_fmt(struct v4l2_subdev *sd,
> +			  struct v4l2_subdev_pad_config *cfg,
> +			  struct v4l2_subdev_format *format)
> +{
> +	struct ov5640_dev *sensor = to_ov5640_dev(sd);
> +	enum ov5640_mode new_mode;
> +	int ret;
> +
> +	if (format->pad != 0)
> +		return -EINVAL;
> +
> +	if (format->which == V4L2_SUBDEV_FORMAT_TRY) {
> +		ret = ov5640_try_fmt_internal(sd, &format->format, NULL);
> +		if (ret)
> +			return ret;
> +		cfg->try_fmt = format->format;
> +		return 0;
> +	}
> +
> +	ret = ov5640_try_fmt_internal(sd, &format->format, &new_mode);
> +	if (ret)
> +		return ret;
> +
> +	ret = ov5640_change_mode(sensor, sensor->current_fr,
> +				 new_mode, sensor->current_mode);
> +	if (ret >= 0)
> +		sensor->fmt = format->format;
> +
> +	return ret;
> +}
> +
> +
> +/*
> + * Sensor Controls.
> + */
> +
> +static int ov5640_set_hue(struct ov5640_dev *sensor, int value)
> +{
> +	int ret;
> +
> +	if (value) {
> +		OV5640_MOD_REG(sensor, 0x5580, 1 << 0, 1 << 0);
> +		OV5640_WRITE_REG16(sensor, 0x5581, value);
> +	} else
> +		OV5640_MOD_REG(sensor, 0x5580, 1 << 0, 0);
> +
> +	return 0;
> +}
> +
> +static int ov5640_set_contrast(struct ov5640_dev *sensor, int value)
> +{
> +	int ret;
> +
> +	if (value) {
> +		OV5640_MOD_REG(sensor, 0x5580, 1 << 2, 1 << 2);
> +		OV5640_WRITE_REG(sensor, 0x5585, value & 0xff);
> +	} else
> +		OV5640_MOD_REG(sensor, 0x5580, 1 << 2, 0);
> +
> +	return 0;
> +}
> +
> +static int ov5640_set_saturation(struct ov5640_dev *sensor, int value)
> +{
> +	int ret;
> +
> +	if (value) {
> +		OV5640_MOD_REG(sensor, 0x5580, 1 << 1, 1 << 1);
> +		OV5640_WRITE_REG(sensor, 0x5583, value & 0xff);
> +		OV5640_WRITE_REG(sensor, 0x5584, value & 0xff);
> +	} else
> +		OV5640_MOD_REG(sensor, 0x5580, 1 << 1, 0);
> +
> +	return 0;
> +}
> +
> +static int ov5640_set_awb(struct ov5640_dev *sensor, int value)
> +{
> +	int ret;
> +
> +	sensor->awb_on = value ? true : false;
> +	OV5640_MOD_REG(sensor, 0x3406, 1 << 0, sensor->awb_on ? 0 : 1);
> +	return 0;
> +}
> +
> +static int ov5640_set_red_balance(struct ov5640_dev *sensor, int value)
> +{
> +	int ret;
> +
> +	if (sensor->awb_on)
> +		return -EINVAL;
> +
> +	OV5640_WRITE_REG(sensor, 0x3401, value & 0xff);
> +	OV5640_WRITE_REG(sensor, 0x3400, (value & 0xf00) >> 8);
> +	return 0;
> +}
> +
> +#if 0
> +static int ov5640_set_green_balance(struct ov5640_dev *sensor, int value)
> +{
> +	int ret;
> +
> +	if (sensor->awb_on)
> +		return -EINVAL;
> +
> +	OV5640_WRITE_REG(sensor, 0x3403, value & 0xff);
> +	OV5640_WRITE_REG(sensor, 0x3402, (value & 0xf00) >> 8);
> +	return 0;
> +}
> +#endif
> +
> +static int ov5640_set_blue_balance(struct ov5640_dev *sensor, int value)
> +{
> +	int ret;
> +
> +	if (sensor->awb_on)
> +		return -EINVAL;
> +
> +	OV5640_WRITE_REG(sensor, 0x3405, value & 0xff);
> +	OV5640_WRITE_REG(sensor, 0x3404, (value & 0xf00) >> 8);
> +	return 0;
> +}
> +
> +static int ov5640_set_exposure(struct ov5640_dev *sensor, int value)
> +{
> +	u16 max_exp = 0;
> +	int ret;
> +
> +	if (sensor->agc_on)
> +		return -EINVAL;
> +
> +	OV5640_READ_REG16(sensor, 0x350c, &max_exp);
> +	if (value < max_exp) {
> +		u32 exp = value << 4;
> +
> +		OV5640_WRITE_REG(sensor, 0x3502, exp & 0xff);
> +		OV5640_WRITE_REG(sensor, 0x3501, (exp >> 8) & 0xff);
> +		OV5640_WRITE_REG(sensor, 0x3500, (exp >> 16) & 0x0f);
> +	}
> +
> +	return 0;
> +}
> +
> +/* read exposure, in number of line periods */
> +static int ov5640_get_exposure(struct ov5640_dev *sensor)
> +{
> +	u8 temp;
> +	int exp, ret;
> +
> +	if (sensor->agc_on)
> +		return -EINVAL;
> +
> +	OV5640_READ_REG(sensor, 0x3500, &temp);
> +	exp = ((int)temp & 0x0f) << 16;
> +	OV5640_READ_REG(sensor, 0x3501, &temp);
> +	exp |= ((int)temp << 8);
> +	OV5640_READ_REG(sensor, 0x3502, &temp);
> +	exp |= (int)temp;
> +
> +	return exp >> 4;
> +}
> +
> +static int ov5640_set_agc(struct ov5640_dev *sensor, int value)
> +{
> +	int ret;
> +
> +	/* this enables/disables both AEC and AGC */
> +	sensor->agc_on = value ? true : false;
> +	OV5640_MOD_REG(sensor, 0x3503, 0x3, sensor->agc_on ? 0 : 0x3);
> +
> +	return 0;
> +}
> +
> +static int ov5640_set_gain(struct ov5640_dev *sensor, int value)
> +{
> +	int ret;
> +
> +	if (sensor->agc_on)
> +		return -EINVAL;
> +
> +	OV5640_WRITE_REG16(sensor, 0x350a, value & 0x3ff);
> +	return 0;
> +}
> +
> +static int ov5640_get_gain(struct ov5640_dev *sensor)
> +{
> +	u16 gain;
> +	int ret;
> +
> +	if (sensor->agc_on)
> +		return -EINVAL;
> +
> +	OV5640_READ_REG16(sensor, 0x350a, &gain);
> +
> +	return gain & 0x3ff;
> +}
> +
> +#if 0
> +static int ov5640_set_test_pattern(struct ov5640_dev *sensor, int value)
> +{
> +	int ret;
> +
> +	OV5640_MOD_REG(sensor, 0x503d, 0xa4, value ? 0xa4 : 0);
> +	return 0;
> +}
> +#endif
> +
> +static struct ov5640_control ov5640_ctrls[] = {
> +	{
> +		.set = ov5640_set_agc,
> +		.ctrl = {
> +			.id = V4L2_CID_AUTOGAIN,
> +			.name = "Auto Gain/Exposure Control",
> +			.minimum = 0,
> +			.maximum = 1,
> +			.step = 1,
> +			.default_value = 1,
> +			.type = V4L2_CTRL_TYPE_BOOLEAN,
> +		},
> +	}, {
> +		.set = ov5640_set_exposure,
> +		.ctrl = {
> +			.id = V4L2_CID_EXPOSURE,
> +			.name = "Exposure",
> +			.minimum = 0,
> +			.maximum = 65535,
> +			.step = 1,
> +			.default_value = 0,
> +			.type = V4L2_CTRL_TYPE_INTEGER,
> +		},
> +	}, {
> +		.set = ov5640_set_gain,
> +		.ctrl = {
> +			.id = V4L2_CID_GAIN,
> +			.name = "Gain",
> +			.minimum = 0,
> +			.maximum = 1023,
> +			.step = 1,
> +			.default_value = 0,
> +			.type = V4L2_CTRL_TYPE_INTEGER,
> +		},
> +	}, {
> +		.set = ov5640_set_hue,
> +		.ctrl = {
> +			.id = V4L2_CID_HUE,
> +			.name = "Hue",
> +			.minimum = 0,
> +			.maximum = 359,
> +			.step = 1,
> +			.default_value = 0,
> +			.type = V4L2_CTRL_TYPE_INTEGER,
> +		},
> +	}, {
> +		.set = ov5640_set_contrast,
> +		.ctrl = {
> +			.id = V4L2_CID_CONTRAST,
> +			.name = "Contrast",
> +			.minimum = 0,
> +			.maximum = 255,
> +			.step = 1,
> +			.default_value = 0,
> +			.type = V4L2_CTRL_TYPE_INTEGER,
> +		},
> +	}, {
> +		.set = ov5640_set_saturation,
> +		.ctrl = {
> +			.id = V4L2_CID_SATURATION,
> +			.name = "Saturation",
> +			.minimum = 0,
> +			.maximum = 255,
> +			.step = 1,
> +			.default_value = 64,
> +			.type = V4L2_CTRL_TYPE_INTEGER,
> +		},
> +	}, {
> +		.set = ov5640_set_awb,
> +		.ctrl = {
> +			.id = V4L2_CID_AUTO_WHITE_BALANCE,
> +			.name = "Auto White Balance",
> +			.minimum = 0,
> +			.maximum = 1,
> +			.step = 1,
> +			.default_value = 1,
> +			.type = V4L2_CTRL_TYPE_BOOLEAN,
> +		},
> +	}, {
> +		.set = ov5640_set_red_balance,
> +		.ctrl = {
> +			.id = V4L2_CID_RED_BALANCE,
> +			.name = "Red Balance",
> +			.minimum = 0,
> +			.maximum = 4095,
> +			.step = 1,
> +			.default_value = 0,
> +			.type = V4L2_CTRL_TYPE_INTEGER,
> +		},
> +	}, {
> +		.set = ov5640_set_blue_balance,
> +		.ctrl = {
> +			.id = V4L2_CID_BLUE_BALANCE,
> +			.name = "Blue Balance",
> +			.minimum = 0,
> +			.maximum = 4095,
> +			.step = 1,
> +			.default_value = 0,
> +			.type = V4L2_CTRL_TYPE_INTEGER,
> +		},
> +	},
> +};
> +#define OV5640_NUM_CONTROLS ARRAY_SIZE(ov5640_ctrls)

This should use v4l2_ctrl_new_std() instead of this array.
Just put a switch on ctrl->id in s_ctrl, and each case calls the corresponding
set function.

> +
> +static struct ov5640_control *ov5640_get_ctrl(int id, int *index)
> +{
> +	struct ov5640_control *ret = NULL;
> +	int i;
> +
> +	for (i = 0; i < OV5640_NUM_CONTROLS; i++) {
> +		if (id == ov5640_ctrls[i].ctrl.id) {
> +			ret = &ov5640_ctrls[i];
> +			break;
> +		}
> +	}
> +
> +	if (ret && index)
> +		*index = i;
> +	return ret;
> +}
> +
> +static int ov5640_restore_ctrls(struct ov5640_dev *sensor)
> +{
> +	struct ov5640_control *c;
> +	int i;
> +
> +	for (i = 0; i < OV5640_NUM_CONTROLS; i++) {
> +		c = &ov5640_ctrls[i];
> +		c->set(sensor, sensor->ctrl_cache[i]);
> +	}
> +
> +	return 0;
> +}

This does the same as v4l2_ctrl_handler_setup() if I understand the code correctly.

> +
> +static int ov5640_s_ctrl(struct v4l2_ctrl *ctrl)
> +{
> +	struct ov5640_dev *sensor = ctrl_to_ov5640_dev(ctrl);
> +	struct ov5640_control *c;
> +	int ret = 0;
> +	int i;
> +
> +	c = ov5640_get_ctrl(ctrl->id, &i);
> +	if (!c)
> +		return -EINVAL;
> +
> +	ret = c->set(sensor, ctrl->val);
> +	/* update cached value if no error */
> +	if (!ret)
> +		sensor->ctrl_cache[i] = ctrl->val;
> +
> +	return ret;
> +}
> +
> +static const struct v4l2_ctrl_ops ov5640_ctrl_ops = {
> +	.s_ctrl = ov5640_s_ctrl,
> +};
> +
> +static int ov5640_init_controls(struct ov5640_dev *sensor)
> +{
> +	struct ov5640_control *c;
> +	int i;
> +
> +	v4l2_ctrl_handler_init(&sensor->ctrl_hdl, OV5640_NUM_CONTROLS);
> +
> +	for (i = 0; i < OV5640_NUM_CONTROLS; i++) {
> +		c = &ov5640_ctrls[i];
> +
> +		v4l2_ctrl_new_std(&sensor->ctrl_hdl, &ov5640_ctrl_ops,
> +				  c->ctrl.id, c->ctrl.minimum, c->ctrl.maximum,
> +				  c->ctrl.step, c->ctrl.default_value);
> +	}

As mentioned, just drop the ov5640_ctrls array and call v4l2_ctr_new_std for each
control you're adding.

> +
> +	sensor->sd.ctrl_handler = &sensor->ctrl_hdl;
> +	if (sensor->ctrl_hdl.error) {
> +		int err = sensor->ctrl_hdl.error;
> +
> +		v4l2_ctrl_handler_free(&sensor->ctrl_hdl);
> +
> +		v4l2_err(&sensor->sd, "%s: error %d\n", __func__, err);
> +		return err;
> +	}
> +	v4l2_ctrl_handler_setup(&sensor->ctrl_hdl);
> +
> +	return 0;
> +}
> +
> +static int ov5640_enum_frame_size(struct v4l2_subdev *sd,
> +				  struct v4l2_subdev_pad_config *cfg,
> +				  struct v4l2_subdev_frame_size_enum *fse)
> +{
> +	if (fse->pad != 0)
> +		return -EINVAL;
> +	if (fse->index >= ov5640_num_modes)
> +		return -EINVAL;
> +
> +	fse->min_width = fse->max_width =
> +		ov5640_mode_info_data[0][fse->index].width;
> +	fse->min_height = fse->max_height =
> +		ov5640_mode_info_data[0][fse->index].height;
> +
> +	return 0;
> +}
> +
> +static int ov5640_enum_frame_interval(
> +	struct v4l2_subdev *sd,
> +	struct v4l2_subdev_pad_config *cfg,
> +	struct v4l2_subdev_frame_interval_enum *fie)
> +{
> +	struct ov5640_dev *sensor = to_ov5640_dev(sd);
> +	enum ov5640_mode mode;
> +
> +	if (fie->pad != 0)
> +		return -EINVAL;
> +	if (fie->index < 0 || fie->index >= ov5640_num_framerates)
> +		return -EINVAL;
> +
> +	if (fie->width == 0 || fie->height == 0)
> +		return -EINVAL;
> +
> +	mode = ov5640_find_nearest_mode(sensor, fie->width, fie->height);
> +
> +	if (ov5640_mode_info_data[fie->index][mode].init_data_ptr == NULL)
> +		return -EINVAL;
> +
> +	fie->interval.numerator = 1;
> +	fie->interval.denominator = ov5640_framerates[fie->index];
> +
> +	dev_dbg(sensor->dev, "%dx%d: [%d] = %d fps\n",
> +		fie->width, fie->height, fie->index, fie->interval.denominator);
> +	return 0;
> +}
> +
> +static int ov5640_g_input_status(struct v4l2_subdev *sd, u32 *status)
> +{
> +	struct ov5640_dev *sensor = to_ov5640_dev(sd);
> +
> +	*status = !sensor->on ? V4L2_IN_ST_NO_POWER : 0;
> +
> +	return 0;
> +}
> +
> +static int ov5640_s_routing(struct v4l2_subdev *sd, u32 input,
> +			    u32 output, u32 config)
> +{
> +	return (input != 0) ? -EINVAL : 0;
> +}
> +
> +static int ov5640_enum_mbus_code(struct v4l2_subdev *sd,
> +				  struct v4l2_subdev_pad_config *cfg,
> +				  struct v4l2_subdev_mbus_code_enum *code)
> +{
> +	struct ov5640_dev *sensor = to_ov5640_dev(sd);
> +
> +	if (code->pad != 0)
> +		return -EINVAL;
> +	if (code->index != 0)
> +		return -EINVAL;
> +
> +	code->code = sensor->fmt.code;
> +
> +	return 0;
> +}
> +
> +static int ov5640_g_mbus_config(struct v4l2_subdev *sd,
> +				struct v4l2_mbus_config *cfg)
> +{
> +	struct ov5640_dev *sensor = to_ov5640_dev(sd);
> +
> +	cfg->type = V4L2_MBUS_CSI2;
> +	cfg->flags = sensor->ep.bus.mipi_csi2.flags;
> +	cfg->flags |= (1 << (sensor->ep.bus.mipi_csi2.num_data_lanes - 1));
> +	cfg->flags |= V4L2_MBUS_CSI2_CHANNEL_0;
> +
> +	return 0;
> +}
> +
> +static int ov5640_s_stream(struct v4l2_subdev *sd, int enable)
> +{
> +	struct ov5640_dev *sensor = to_ov5640_dev(sd);
> +
> +	v4l2_info(sd, "stream %s\n", enable ? "ON" : "OFF");
> +
> +	return ov5640_set_stream(sensor, enable);
> +}
> +
> +static struct v4l2_subdev_core_ops ov5640_core_ops = {
> +	.s_power = ov5640_s_power,
> +};
> +
> +static struct v4l2_subdev_video_ops ov5640_video_ops = {
> +	.s_parm = ov5640_s_parm,
> +	.g_parm = ov5640_g_parm,
> +	.g_input_status = ov5640_g_input_status,
> +	.s_routing = ov5640_s_routing,
> +	.g_mbus_config  = ov5640_g_mbus_config,
> +	.s_stream = ov5640_s_stream,
> +};
> +
> +static struct v4l2_subdev_pad_ops ov5640_pad_ops = {
> +	.enum_mbus_code = ov5640_enum_mbus_code,
> +	.get_fmt = ov5640_get_fmt,
> +	.set_fmt = ov5640_set_fmt,
> +	.enum_frame_size = ov5640_enum_frame_size,
> +	.enum_frame_interval = ov5640_enum_frame_interval,
> +};
> +
> +static struct v4l2_subdev_ops ov5640_subdev_ops = {
> +	.core = &ov5640_core_ops,
> +	.video = &ov5640_video_ops,
> +	.pad = &ov5640_pad_ops,
> +};
> +
> +static void ov5640_power(struct ov5640_dev *sensor, bool enable)
> +{
> +	gpiod_set_value(sensor->pwdn_gpio, enable ? 0 : 1);
> +}
> +
> +static void ov5640_reset(struct ov5640_dev *sensor)
> +{
> +	gpiod_set_value(sensor->reset_gpio, 0);
> +
> +	/* camera power cycle */
> +	ov5640_power(sensor, false);
> +	usleep_range(5000, 10000);
> +	ov5640_power(sensor, true);
> +	usleep_range(5000, 10000);
> +
> +	gpiod_set_value(sensor->reset_gpio, 1);
> +	usleep_range(1000, 2000);
> +
> +	gpiod_set_value(sensor->reset_gpio, 0);
> +	usleep_range(5000, 10000);
> +}
> +
> +static void ov5640_get_regulators(struct ov5640_dev *sensor)
> +{
> +	sensor->io_regulator = devm_regulator_get(sensor->dev, "DOVDD");
> +	if (!IS_ERR(sensor->io_regulator)) {
> +		regulator_set_voltage(sensor->io_regulator,
> +				      OV5640_VOLTAGE_DIGITAL_IO,
> +				      OV5640_VOLTAGE_DIGITAL_IO);
> +	} else {
> +		dev_dbg(sensor->dev, "%s: no io voltage reg found\n",
> +			__func__);
> +		sensor->io_regulator = NULL;
> +	}
> +
> +	sensor->core_regulator = devm_regulator_get(sensor->dev, "DVDD");
> +	if (!IS_ERR(sensor->core_regulator)) {
> +		regulator_set_voltage(sensor->core_regulator,
> +				      OV5640_VOLTAGE_DIGITAL_CORE,
> +				      OV5640_VOLTAGE_DIGITAL_CORE);
> +	} else {
> +		sensor->core_regulator = NULL;
> +		dev_dbg(sensor->dev, "%s: no core voltage reg found\n",
> +			__func__);
> +	}
> +
> +	sensor->analog_regulator = devm_regulator_get(sensor->dev, "AVDD");
> +	if (!IS_ERR(sensor->analog_regulator)) {
> +		regulator_set_voltage(sensor->analog_regulator,
> +				      OV5640_VOLTAGE_ANALOG,
> +				      OV5640_VOLTAGE_ANALOG);
> +	} else {
> +		sensor->analog_regulator = NULL;
> +		dev_dbg(sensor->dev, "%s: no analog voltage reg found\n",
> +			__func__);
> +	}
> +}
> +
> +static int ov5640_probe(struct i2c_client *client,
> +			const struct i2c_device_id *id)
> +{
> +	struct device *dev = &client->dev;
> +	struct device_node *endpoint;
> +	struct ov5640_dev *sensor;
> +	int i, xclk, ret;
> +
> +	sensor = devm_kzalloc(dev, sizeof(struct ov5640_dev), GFP_KERNEL);
> +	if (!sensor)
> +		return -ENOMEM;
> +
> +	sensor->i2c_client = client;
> +	sensor->dev = dev;
> +	sensor->fmt.code = MEDIA_BUS_FMT_UYVY8_2X8;
> +	sensor->fmt.width = 640;
> +	sensor->fmt.height = 480;
> +	sensor->fmt.field = V4L2_FIELD_NONE;
> +	sensor->streamcap.capability = V4L2_MODE_HIGHQUALITY |
> +					   V4L2_CAP_TIMEPERFRAME;
> +	sensor->streamcap.capturemode = 0;
> +	sensor->streamcap.timeperframe.denominator = DEFAULT_FPS;
> +	sensor->streamcap.timeperframe.numerator = 1;
> +
> +	sensor->current_mode = ov5640_mode_VGA_640_480;
> +	sensor->current_fr = ov5640_30_fps;
> +
> +	sensor->ae_target = 52;
> +
> +	endpoint = of_graph_get_next_endpoint(client->dev.of_node, NULL);
> +	if (!endpoint) {
> +		dev_err(dev, "endpoint node not found\n");
> +		return -EINVAL;
> +	}
> +
> +	v4l2_of_parse_endpoint(endpoint, &sensor->ep);
> +	if (sensor->ep.bus_type != V4L2_MBUS_CSI2) {
> +		dev_err(dev, "invalid bus type, must be MIPI CSI2\n");
> +		return -EINVAL;
> +	}
> +	of_node_put(endpoint);
> +
> +	/* get system clock (xclk) frequency */
> +	ret = of_property_read_u32(dev->of_node, "xclk", &xclk);
> +	if (!ret) {
> +		if (xclk < OV5640_XCLK_MIN || xclk > OV5640_XCLK_MAX) {
> +			dev_err(dev, "invalid xclk frequency\n");
> +			return -EINVAL;
> +		}
> +		sensor->xclk_freq = xclk;
> +	}
> +
> +	/* get system clock (xclk) */
> +	sensor->xclk = devm_clk_get(dev, "xclk");
> +	if (!IS_ERR(sensor->xclk)) {
> +		if (!sensor->xclk_freq) {
> +			dev_err(dev, "xclk requires xclk frequency!\n");
> +			return -EINVAL;
> +		}
> +		clk_set_rate(sensor->xclk, sensor->xclk_freq);
> +	} else {
> +		/* assume system clock enabled by default */
> +		sensor->xclk = NULL;
> +	}
> +
> +	/* request power down pin */
> +	sensor->pwdn_gpio = devm_gpiod_get(dev, "pwdn", GPIOD_OUT_HIGH);
> +	if (IS_ERR(sensor->pwdn_gpio)) {
> +		dev_err(dev, "request for power down gpio failed\n");
> +		return PTR_ERR(sensor->pwdn_gpio);
> +	}
> +
> +	/* request reset pin */
> +	sensor->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH);
> +	if (IS_ERR(sensor->reset_gpio)) {
> +		dev_err(dev, "request for reset gpio failed\n");
> +		return PTR_ERR(sensor->reset_gpio);
> +	}
> +
> +	/* initialize the cached controls to their defaults */
> +	for (i = 0; i < OV5640_NUM_CONTROLS; i++) {
> +		struct ov5640_control *c = &ov5640_ctrls[i];
> +
> +		sensor->ctrl_cache[i] = c->ctrl.default_value;
> +	}
> +	sensor->awb_on = sensor->agc_on = true;
> +
> +	v4l2_i2c_subdev_init(&sensor->sd, client, &ov5640_subdev_ops);
> +
> +	sensor->sd.flags = V4L2_SUBDEV_FL_HAS_DEVNODE;
> +	sensor->pad.flags = MEDIA_PAD_FL_SOURCE;
> +	sensor->sd.entity.function = MEDIA_ENT_F_CAM_SENSOR;
> +	ret = media_entity_pads_init(&sensor->sd.entity, 1, &sensor->pad);
> +	if (ret)
> +		return ret;
> +
> +	ov5640_get_regulators(sensor);
> +
> +	ret = ov5640_s_power(&sensor->sd, 1);
> +	if (ret)
> +		goto entity_cleanup;
> +	ret = ov5640_init_controls(sensor);
> +	if (ret)
> +		goto power_off;
> +
> +	ret = ov5640_s_power(&sensor->sd, 0);
> +	if (ret)
> +		goto free_ctrls;
> +
> +	ret = v4l2_async_register_subdev(&sensor->sd);
> +	if (ret)
> +		goto free_ctrls;
> +
> +	return 0;
> +
> +free_ctrls:
> +	v4l2_ctrl_handler_free(&sensor->ctrl_hdl);
> +power_off:
> +	ov5640_s_power(&sensor->sd, 0);
> +entity_cleanup:
> +	media_entity_cleanup(&sensor->sd.entity);
> +	ov5640_regulators_off(sensor);
> +	return ret;
> +}
> +
> +/*!
> + * ov5640 I2C detach function
> + *
> + * @param client            struct i2c_client *
> + * @return  Error code indicating success or failure
> + */
> +static int ov5640_remove(struct i2c_client *client)
> +{
> +	struct v4l2_subdev *sd = i2c_get_clientdata(client);
> +	struct ov5640_dev *sensor = to_ov5640_dev(sd);
> +
> +	ov5640_regulators_off(sensor);
> +
> +	v4l2_async_unregister_subdev(&sensor->sd);
> +	media_entity_cleanup(&sensor->sd.entity);
> +	v4l2_device_unregister_subdev(sd);
> +	v4l2_ctrl_handler_free(&sensor->ctrl_hdl);
> +
> +	return 0;
> +}
> +
> +static const struct i2c_device_id ov5640_id[] = {
> +	{"ov5640", 0},
> +	{},
> +};
> +MODULE_DEVICE_TABLE(i2c, ov5640_id);
> +
> +static const struct of_device_id ov5640_dt_ids[] = {
> +	{ .compatible = "ovti,ov5640" },
> +	{ /* sentinel */ }
> +};
> +MODULE_DEVICE_TABLE(of, ov5640_dt_ids);
> +
> +static struct i2c_driver ov5640_i2c_driver = {
> +	.driver = {
> +		.name  = "ov5640",
> +		.of_match_table	= ov5640_dt_ids,
> +	},
> +	.id_table = ov5640_id,
> +	.probe    = ov5640_probe,
> +	.remove   = ov5640_remove,
> +};
> +
> +module_i2c_driver(ov5640_i2c_driver);
> +
> +MODULE_AUTHOR("Freescale Semiconductor, Inc.");
> +MODULE_AUTHOR("Steve Longerbeam <steve_longerbeam@mentor.com>");
> +MODULE_DESCRIPTION("OV5640 MIPI Camera Subdev Driver");
> +MODULE_LICENSE("GPL");
> +MODULE_VERSION("1.0");
> 

Same comments apply to the next patch, so I won't repeat them.

Regards,

	Hans

^ 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